forked from reya/coop-mobile
chore: refactor the internal structure (#33)
Reviewed-on: https://git.reya.su/reya/coop-mobile/pulls/33
This commit is contained in:
@@ -70,27 +70,24 @@ import coop.composeapp.generated.resources.ic_cancel
|
||||
import coop.composeapp.generated.resources.ic_check_circle
|
||||
import coop.composeapp.generated.resources.ic_send
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import rust.nostr.sdk.PublicKey
|
||||
import rust.nostr.sdk.Timestamp
|
||||
import rust.nostr.sdk.UnsignedEvent
|
||||
import su.reya.coop.LocalAccountViewModel
|
||||
import su.reya.coop.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalProfileViewModel
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalSnackbarHostState
|
||||
import su.reya.coop.Room
|
||||
import su.reya.coop.Screen
|
||||
import su.reya.coop.nostr.Room
|
||||
import su.reya.coop.nostr.formatAsGroupHeader
|
||||
import su.reya.coop.nostr.humanReadable
|
||||
import su.reya.coop.nostr.roomId
|
||||
import su.reya.coop.formatAsGroupHeader
|
||||
import su.reya.coop.humanReadable
|
||||
import su.reya.coop.rememberUiState
|
||||
import su.reya.coop.roomId
|
||||
import su.reya.coop.shared.Avatar
|
||||
import su.reya.coop.shared.getExpressiveFontFamily
|
||||
import su.reya.coop.shared.nameFlow
|
||||
import su.reya.coop.shared.pictureFlow
|
||||
import su.reya.coop.short
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@@ -99,11 +96,14 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
val context = LocalContext.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
val navigator = LocalNavigator.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val profileViewModel = LocalProfileViewModel.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
// Get current user
|
||||
val currentUser by nostrViewModel.currentUserProfile.collectAsStateWithLifecycle()
|
||||
|
||||
// Get chat room by ID
|
||||
val chatRooms by chatViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val room by remember(id) { derivedStateOf { chatRooms.firstOrNull { it.id == id } } }
|
||||
@@ -123,15 +123,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
val displayName by remember(room) {
|
||||
room?.nameFlow(profileViewModel) ?: flowOf("Loading...")
|
||||
}.collectAsStateWithLifecycle("Loading...")
|
||||
|
||||
val picture by remember(room) {
|
||||
room?.pictureFlow(profileViewModel) ?: flowOf(null)
|
||||
}.collectAsStateWithLifecycle(null)
|
||||
|
||||
val roomState by (room as Room).rememberUiState(nostrViewModel, currentUser?.publicKey)
|
||||
var text by remember { mutableStateOf("") }
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
var newOtherMessages by remember { mutableIntStateOf(0) }
|
||||
@@ -215,14 +207,14 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
LoadingIndicator(modifier = Modifier.size(32.dp))
|
||||
} else {
|
||||
Avatar(
|
||||
picture = picture,
|
||||
description = displayName,
|
||||
picture = roomState.picture,
|
||||
description = roomState.name,
|
||||
size = 32.dp,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = displayName,
|
||||
text = roomState.name,
|
||||
style = MaterialTheme.typography.titleMediumEmphasized,
|
||||
)
|
||||
}
|
||||
@@ -282,7 +274,10 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
items = messagesInGroup,
|
||||
key = { it.id()?.toBech32() ?: it.hashCode() }
|
||||
) {
|
||||
ChatMessage(it)
|
||||
ChatMessage(
|
||||
rumor = it,
|
||||
isMine = currentUser?.publicKey == it.author()
|
||||
)
|
||||
}
|
||||
item {
|
||||
DateSeparator(dateHeader)
|
||||
@@ -377,28 +372,24 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
fun ScreenerCard(room: Room) {
|
||||
val pubkey = room.members.firstOrNull() ?: return
|
||||
|
||||
val profileViewModel = LocalProfileViewModel.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var isContact by remember { mutableStateOf(false) }
|
||||
var mutualContacts by remember { mutableStateOf<Set<PublicKey>>(emptySet()) }
|
||||
var lastActivity by remember { mutableStateOf<Timestamp?>(null) }
|
||||
|
||||
val metadataFlow = remember(pubkey) { profileViewModel.getMetadata(pubkey) }
|
||||
val metadata by metadataFlow.collectAsStateWithLifecycle()
|
||||
|
||||
val profile = metadata?.asRecord()
|
||||
val displayName = profile?.displayName ?: profile?.name ?: "No name"
|
||||
val picture = profile?.picture
|
||||
val profileFlow = remember(pubkey) { nostrViewModel.getMetadata(pubkey) }
|
||||
val profile by profileFlow.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(pubkey) {
|
||||
scope.launch {
|
||||
// Check contact
|
||||
profileViewModel.verifyContact(pubkey).let { isContact = it }
|
||||
nostrViewModel.verifyContact(pubkey).let { isContact = it }
|
||||
// Get mutual contacts
|
||||
profileViewModel.mutualContacts(pubkey).let { mutualContacts = it }
|
||||
nostrViewModel.mutualContacts(pubkey).let { mutualContacts = it }
|
||||
// Get the last activity
|
||||
profileViewModel.verifyActivity(pubkey)?.let { lastActivity = it }
|
||||
nostrViewModel.verifyActivity(pubkey)?.let { lastActivity = it }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +406,7 @@ fun ScreenerCard(room: Room) {
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Avatar(
|
||||
picture = picture,
|
||||
picture = profile?.picture,
|
||||
description = "Profile picture",
|
||||
modifier = Modifier.size(120.dp),
|
||||
shape = MaterialShapes.Cookie12Sided.toShape(),
|
||||
@@ -425,7 +416,7 @@ fun ScreenerCard(room: Room) {
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = displayName,
|
||||
text = profile?.name ?: "No name",
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.titleLargeEmphasized.copy(
|
||||
fontFamily = getExpressiveFontFamily()
|
||||
@@ -514,13 +505,9 @@ fun DateSeparator(date: String) {
|
||||
|
||||
@Composable
|
||||
fun ChatMessage(
|
||||
rumor: UnsignedEvent
|
||||
rumor: UnsignedEvent,
|
||||
isMine: Boolean = false,
|
||||
) {
|
||||
val accountViewModel = LocalAccountViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val currentUser = accountViewModel.nostr.signer.currentUser
|
||||
val isMine = rumor.author() == currentUser
|
||||
|
||||
val bubbleShape = if (isMine) {
|
||||
RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp, bottomStart = 20.dp, bottomEnd = 4.dp)
|
||||
} else {
|
||||
@@ -546,17 +533,7 @@ fun ChatMessage(
|
||||
color = containerColor,
|
||||
contentColor = contentColor,
|
||||
shape = bubbleShape,
|
||||
modifier = Modifier
|
||||
.widthIn(max = 280.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
val id = rumor.id()
|
||||
if (id != null) {
|
||||
val sent = chatViewModel.isMessageSent(id)
|
||||
println("Sent: $sent")
|
||||
}
|
||||
}
|
||||
)
|
||||
modifier = Modifier.widthIn(max = 280.dp)
|
||||
) {
|
||||
Text(
|
||||
text = rumor.content(),
|
||||
|
||||
Reference in New Issue
Block a user