chat: локальное удаление канала (Android) + db_sync инстансы в куче
This commit is contained in:
1 parent
ddfffad1ed
commit
7c8d65db78
30 files changed
+466
-42
No files matched your search
@@ -67,7 +67,7 @@ class MainActivity : ComponentActivity() {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val showInvite: (Channel) -> Unit = { ch ->
|
||||
if (ch.id.toLongOrNull() == null) {
|
||||
if (ch.id.toULongOrNull() == null) {
|
||||
LogManager.addLog("ERROR", "INVITE", "channel id is not numeric: ${ch.id}")
|
||||
scope.launch { snackbarHostState.showSnackbar("Invalid channel id") }
|
||||
} else {
|
||||
@@ -111,9 +111,10 @@ class MainActivity : ComponentActivity() {
|
||||
connected = connected,
|
||||
isStuck = stuck,
|
||||
onSelectChannel = { ch -> vm.selectChannel(ch); screen = Screen.Chat },
|
||||
onCreateChannel = { vm.createChannel("general", "channel_1") },
|
||||
onCreateChannel = { name -> vm.createChannel(name, "channel_1") },
|
||||
onJoinChannel = { showJoinDialog = true; joinAutoLink = null },
|
||||
onInviteClick = showInvite,
|
||||
onDeleteChannel = { vm.deleteChannel(it.id) },
|
||||
onSettings = { screen = Screen.Settings },
|
||||
onLogs = { screen = Screen.Logs },
|
||||
onRefresh = { vm.requestRefresh() }
|
||||
|
||||
@@ -460,6 +460,8 @@ class ChatRepository {
|
||||
|
||||
fun transferAdmin(channelId: String, nodeId: Long) = NativeLib.transferAdmin(channelId, nodeId)
|
||||
|
||||
fun deleteChannel(channelId: String) = NativeLib.deleteChannel(channelId)
|
||||
|
||||
fun getMemberLinks(nodeId: Long): MemberLinks {
|
||||
try {
|
||||
val obj = JSONObject(NativeLib.getMemberLinks(nodeId))
|
||||
|
||||
@@ -100,6 +100,7 @@ object NativeLib {
|
||||
nativeSetMemberFlags(channelId, nodeId, admin, supernode, moder, storage, verified, deleted)
|
||||
}
|
||||
fun transferAdmin(channelId: String, nodeId: Long) { nativeTransferAdmin(channelId, nodeId) }
|
||||
fun deleteChannel(channelId: String) { nativeDeleteChannel(channelId) }
|
||||
fun getMemberLinks(nodeId: Long): String = nativeGetMemberLinks(nodeId) ?: "{}"
|
||||
|
||||
/* ── Local sockets (for auto-mode display) ── */
|
||||
@@ -178,6 +179,7 @@ object NativeLib {
|
||||
private external fun nativeSetMemberFlags(channelId: String, nodeId: Long, admin: Boolean, supernode: Boolean, moder: Boolean, storage: Boolean,
|
||||
verified: Boolean, deleted: Boolean)
|
||||
private external fun nativeTransferAdmin(channelId: String, nodeId: Long)
|
||||
private external fun nativeDeleteChannel(channelId: String)
|
||||
private external fun nativeGetMemberLinks(nodeId: Long): String?
|
||||
|
||||
/* ── Local sockets JNI ── */
|
||||
|
||||
+25
-2
@@ -34,9 +34,10 @@ fun ChannelListScreen(
|
||||
connected: Boolean,
|
||||
isStuck: Boolean = false,
|
||||
onSelectChannel: (Channel) -> Unit,
|
||||
onCreateChannel: () -> Unit,
|
||||
onCreateChannel: (String) -> Unit,
|
||||
onJoinChannel: () -> Unit,
|
||||
onInviteClick: (Channel) -> Unit,
|
||||
onDeleteChannel: (Channel) -> Unit,
|
||||
onSettings: () -> Unit,
|
||||
onLogs: () -> Unit,
|
||||
onRefresh: () -> Unit = {}
|
||||
@@ -44,6 +45,7 @@ fun ChannelListScreen(
|
||||
var showCreateDialog by remember { mutableStateOf(false) }
|
||||
var menuChannelId by remember { mutableStateOf<String?>(null) }
|
||||
var optionsChannel by remember { mutableStateOf<Channel?>(null) }
|
||||
var deleteConfirmChannel by remember { mutableStateOf<Channel?>(null) }
|
||||
|
||||
LaunchedEffect(Unit) { onRefresh() }
|
||||
|
||||
@@ -108,6 +110,10 @@ fun ChannelListScreen(
|
||||
text = { Text("Options") },
|
||||
onClick = { menuChannelId = null; optionsChannel = ch }
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Delete channel", color = MaterialTheme.colorScheme.error) },
|
||||
onClick = { menuChannelId = null; deleteConfirmChannel = ch }
|
||||
)
|
||||
}
|
||||
if (badgeText.isNotEmpty()) {
|
||||
val badgeSize = 18.dp
|
||||
@@ -151,7 +157,7 @@ fun ChannelListScreen(
|
||||
onDismiss = { showCreateDialog = false },
|
||||
onCreate = { name ->
|
||||
showCreateDialog = false
|
||||
onCreateChannel()
|
||||
onCreateChannel(name)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -162,6 +168,23 @@ fun ChannelListScreen(
|
||||
onDismiss = { optionsChannel = null }
|
||||
)
|
||||
}
|
||||
|
||||
deleteConfirmChannel?.let { ch ->
|
||||
AlertDialog(
|
||||
onDismissRequest = { deleteConfirmChannel = null },
|
||||
title = { Text("Delete channel") },
|
||||
text = { Text("Delete \"${ch.name}\" and all its local messages and files? Other members keep the channel.") },
|
||||
confirmButton = {
|
||||
TextButton(onClick = { deleteConfirmChannel = null; onDeleteChannel(ch) },
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error)) {
|
||||
Text("Delete")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { deleteConfirmChannel = null }) { Text("Cancel") }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -403,6 +403,20 @@ class ChatViewModel : ViewModel() {
|
||||
_inviteLink.value = link
|
||||
_inviteLinkPending.value = false
|
||||
}
|
||||
31 -> { /* CHANNEL_DELETED: [ch_id_len:1][ch_id:var] */
|
||||
if (repo == null || data == null || data.size < 2) return
|
||||
val cl = data[0].toInt() and 0xFF
|
||||
if (data.size < 1 + cl) return
|
||||
val chId = String(data, 1, cl)
|
||||
LogManager.addLog("INFO", "VM", "CHANNEL_DELETED ch=$chId")
|
||||
if (_currentChannel.value?.id == chId) {
|
||||
_currentChannel.value = null
|
||||
_messages.value = emptyList()
|
||||
_members.value = emptyList()
|
||||
_channelOwner.value = false
|
||||
}
|
||||
refreshChannels()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,6 +570,20 @@ class ChatViewModel : ViewModel() {
|
||||
refreshChannels()
|
||||
}
|
||||
|
||||
fun deleteChannel(channelId: String) {
|
||||
val r = repo ?: return
|
||||
LogManager.addLog("INFO", "VM", "deleteChannel ch=$channelId")
|
||||
r.deleteChannel(channelId)
|
||||
if (_currentChannel.value?.id == channelId) {
|
||||
_currentChannel.value = null
|
||||
_messages.value = emptyList()
|
||||
_members.value = emptyList()
|
||||
_channelOwner.value = false
|
||||
}
|
||||
NotificationSound.setMuted(channelId, false)
|
||||
refreshChannels()
|
||||
}
|
||||
|
||||
fun connectNode(address: String, port: Int, pubkeyHex: String) {
|
||||
val r = repo ?: return
|
||||
r.connectNode(address, port, pubkeyHex)
|
||||
|
||||
Reference in new issue
Block a user