chat: UI настройки звука канала (Android toggle + JNI, desktop через C API) + trampoline
This commit is contained in:
1 parent
3d9c79e752
commit
cc0dcb071e
8 files changed
+116
-10
No files matched your search
@@ -85,6 +85,10 @@ object NativeLib {
|
||||
fun setChatSetting(name: String, value: String) { nativeSetChatSetting(name, value) }
|
||||
fun getChatSettingInt(name: String, def: Int = 0): Int = nativeGetChatSettingInt(name, def)
|
||||
|
||||
/* ── Per-channel «play sound on message» ── */
|
||||
fun getSoundOnMessage(chId: String): Boolean = nativeGetSoundOnMessage(chId) != 0
|
||||
fun setSoundOnMessage(chId: String, on: Boolean) { nativeSetSoundOnMessage(chId, on) }
|
||||
|
||||
/** Enable/disable forwarding native C logs to LogManager (expensive, off by default) */
|
||||
fun subscribeNativeLogs(enabled: Boolean) { nativeSubscribeLogs(enabled) }
|
||||
fun setUdpLogTarget(ip: String, port: Int) { nativeSetUdpLogTarget(ip, port) }
|
||||
@@ -186,6 +190,8 @@ object NativeLib {
|
||||
private external fun nativeSetDebugLevel(category: String, level: String)
|
||||
private external fun nativeSetChatSetting(name: String, value: String)
|
||||
private external fun nativeGetChatSettingInt(name: String, def: Int): Int
|
||||
private external fun nativeGetSoundOnMessage(chId: String): Int
|
||||
private external fun nativeSetSoundOnMessage(chId: String, on: Boolean)
|
||||
private external fun nativeSubscribeLogs(enabled: Boolean)
|
||||
private external fun nativeSetUdpLogTarget(ip: String, port: Int)
|
||||
private external fun nativeRegenerateKeys()
|
||||
|
||||
@@ -70,6 +70,9 @@ fun ChatScreen(
|
||||
val overlayShown by RadioOverlayService.isShown.collectAsState()
|
||||
val localTalking by RadioAudioEngine.instance().talkingFlow.collectAsState()
|
||||
|
||||
/* звук сообщений канала */
|
||||
val soundOn by viewModel.soundOn.collectAsState()
|
||||
|
||||
/* attach menu */
|
||||
var showAttachMenu by remember { mutableStateOf(false) }
|
||||
|
||||
@@ -140,6 +143,9 @@ fun ChatScreen(
|
||||
IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back") }
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = { viewModel.toggleSound() }) {
|
||||
Text(if (soundOn) "\uD83D\uDD14" else "\uD83D\uDD15", fontSize = 18.sp)
|
||||
}
|
||||
IconButton(onClick = { viewModel.toggleRadio() }) {
|
||||
Text(if (radioActive) "\uD83D\uDCFB" else "\uD83D\uDD07", fontSize = 18.sp)
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ class ChatViewModel : ViewModel() {
|
||||
private val _currentChannel = MutableStateFlow<Channel?>(null)
|
||||
val currentChannel: StateFlow<Channel?> = _currentChannel
|
||||
|
||||
private val _soundOn = MutableStateFlow(true)
|
||||
val soundOn: StateFlow<Boolean> = _soundOn
|
||||
|
||||
private val _pubKey = MutableStateFlow("")
|
||||
val pubKey: StateFlow<String> = _pubKey
|
||||
|
||||
@@ -857,10 +860,21 @@ class ChatViewModel : ViewModel() {
|
||||
val r = repo ?: return
|
||||
radioOff() /* рацию выключаем при переключении канала */
|
||||
_currentChannel.value = channel
|
||||
_soundOn.value = NativeLib.getSoundOnMessage(channel.id)
|
||||
NotificationSound.setMuted(channel.id, !_soundOn.value)
|
||||
r.connectChannel(channel.id)
|
||||
refreshMessages(channel.id)
|
||||
}
|
||||
|
||||
/* ── per-channel «play sound on message» ── */
|
||||
fun toggleSound() {
|
||||
val ch = _currentChannel.value ?: return
|
||||
val on = !_soundOn.value
|
||||
_soundOn.value = on
|
||||
NotificationSound.setMuted(ch.id, !on)
|
||||
NativeLib.setSoundOnMessage(ch.id, on)
|
||||
}
|
||||
|
||||
/* ── DM (личные сообщения) ── */
|
||||
|
||||
fun refreshDmConversations() {
|
||||
|
||||
@@ -1027,6 +1027,40 @@ void utun_bridge_delete_channel(const char* channel_id) {
|
||||
bridge_log(BLEV_INFO, "delete_channel queued ch=%s", channel_id);
|
||||
}
|
||||
|
||||
/* ── Per-channel «play sound on message» ── */
|
||||
|
||||
struct sound_setting_req {
|
||||
struct UTUN_INSTANCE* inst;
|
||||
char ch_id[64];
|
||||
int on;
|
||||
};
|
||||
|
||||
static void sound_setting_trampoline(void* arg) {
|
||||
struct sound_setting_req* req = (struct sound_setting_req*)arg;
|
||||
if (!req || !req->inst) { u_free(arg); return; }
|
||||
chat_core_set_sound_on_message(req->inst, req->ch_id, req->on);
|
||||
u_free(arg);
|
||||
}
|
||||
|
||||
int utun_bridge_get_sound_on_message(const char* channel_id) {
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst || !chat_core_is_initialized(inst) || !channel_id || !channel_id[0]) return 1;
|
||||
return chat_core_get_sound_on_message(inst, channel_id);
|
||||
}
|
||||
|
||||
void utun_bridge_set_sound_on_message(const char* channel_id, int on) {
|
||||
if (!channel_id || !channel_id[0]) { bridge_log(BLEV_ERROR, "set_sound: empty ch_id"); return; }
|
||||
struct UASYNC* ua = instance_lite_get_uasync();
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "set_sound: uasync not running"); return; }
|
||||
struct sound_setting_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "set_sound: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
req->on = on ? 1 : 0;
|
||||
uasync_post(ua, sound_setting_trampoline, req);
|
||||
bridge_log(BLEV_INFO, "set_sound queued ch=%s on=%d", channel_id, on ? 1 : 0);
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────
|
||||
* Local sockets state (for auto-mode UI display)
|
||||
* ────────────────────────────────────────────────────────────────── */
|
||||
@@ -1943,15 +1977,32 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSetChatSetting(
|
||||
if (n) (*env)->ReleaseStringUTFChars(env, name, n);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeGetChatSettingInt(
|
||||
JNIEnv* env, jobject thiz, jstring name, jint def) {
|
||||
(void)thiz;
|
||||
const char* n = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
int val = chat_setting_get_int(inst, n, (int)def);
|
||||
if (n) (*env)->ReleaseStringUTFChars(env, name, n);
|
||||
return (jint)val;
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeGetChatSettingInt(
|
||||
JNIEnv* env, jobject thiz, jstring name, jint def) {
|
||||
(void)thiz;
|
||||
const char* n = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
int val = chat_setting_get_int(inst, n, (int)def);
|
||||
if (n) (*env)->ReleaseStringUTFChars(env, name, n);
|
||||
return (jint)val;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeGetSoundOnMessage(
|
||||
JNIEnv* env, jobject thiz, jstring chId) {
|
||||
(void)thiz;
|
||||
const char* c = (*env)->GetStringUTFChars(env, chId, NULL);
|
||||
int on = utun_bridge_get_sound_on_message(c);
|
||||
if (c) (*env)->ReleaseStringUTFChars(env, chId, c);
|
||||
return (jint)on;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSetSoundOnMessage(
|
||||
JNIEnv* env, jobject thiz, jstring chId, jboolean on) {
|
||||
(void)thiz;
|
||||
const char* c = (*env)->GetStringUTFChars(env, chId, NULL);
|
||||
utun_bridge_set_sound_on_message(c, on ? 1 : 0);
|
||||
if (c) (*env)->ReleaseStringUTFChars(env, chId, c);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSubscribeLogs(
|
||||
JNIEnv* env, jobject thiz, jboolean enabled) {
|
||||
|
||||
@@ -176,6 +176,11 @@ void utun_bridge_transfer_admin(const char* channel_id, uint64_t node_id);
|
||||
/* Локально удалить канал (drop таблиц, соединений, медиа, db_sync). */
|
||||
void utun_bridge_delete_channel(const char* channel_id);
|
||||
|
||||
/* ── Per-channel «play sound on message» (троттлинг db_sync на сервере) ── */
|
||||
|
||||
int utun_bridge_get_sound_on_message(const char* channel_id);
|
||||
void utun_bridge_set_sound_on_message(const char* channel_id, int on);
|
||||
|
||||
/* ── Local sockets state (for auto-mode display) ── */
|
||||
|
||||
char* utun_bridge_get_local_sockets_json(void);
|
||||
|
||||
Reference in new issue
Block a user