add chat viewmodel
This commit is contained in:
@@ -52,6 +52,10 @@ val LocalNostrViewModel = staticCompositionLocalOf<NostrViewModel> {
|
||||
error("No NostrViewModel provided")
|
||||
}
|
||||
|
||||
val LocalChatViewModel = staticCompositionLocalOf<ChatViewModel> {
|
||||
error("No ChatViewModel provided")
|
||||
}
|
||||
|
||||
val LocalAuthViewModel = staticCompositionLocalOf<AuthViewModel> {
|
||||
error("No AuthViewModel provided")
|
||||
}
|
||||
@@ -72,6 +76,7 @@ val LocalScanResult = staticCompositionLocalOf<QrScanResult> {
|
||||
@Composable
|
||||
fun App(
|
||||
nostrViewModel: NostrViewModel,
|
||||
chatViewModel: ChatViewModel,
|
||||
authViewModel: AuthViewModel,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@@ -153,6 +158,7 @@ fun App(
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalNostrViewModel provides nostrViewModel,
|
||||
LocalChatViewModel provides chatViewModel,
|
||||
LocalAuthViewModel provides authViewModel,
|
||||
LocalSnackbarHostState provides snackbarHostState,
|
||||
LocalNavigator provides navigator,
|
||||
|
||||
@@ -28,12 +28,15 @@ class MainActivity : ComponentActivity() {
|
||||
private val secretStore = SecretStore(this@MainActivity)
|
||||
private val nostrViewModel =
|
||||
NostrViewModel(NostrManager.instance)
|
||||
private val chatViewModel =
|
||||
ChatViewModel(NostrManager.instance)
|
||||
private val authViewModel =
|
||||
AuthViewModel(NostrManager.instance, secretStore, androidSigner)
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return when {
|
||||
modelClass.isAssignableFrom(NostrViewModel::class.java) -> nostrViewModel
|
||||
modelClass.isAssignableFrom(ChatViewModel::class.java) -> chatViewModel
|
||||
modelClass.isAssignableFrom(AuthViewModel::class.java) -> authViewModel
|
||||
else -> throw IllegalArgumentException("Unknown ViewModel class")
|
||||
} as T
|
||||
@@ -42,6 +45,7 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
private val nostrViewModel: NostrViewModel by viewModels { factory }
|
||||
private val chatViewModel: ChatViewModel by viewModels { factory }
|
||||
private val authViewModel: AuthViewModel by viewModels { factory }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -87,6 +91,7 @@ class MainActivity : ComponentActivity() {
|
||||
setContent {
|
||||
App(
|
||||
nostrViewModel = nostrViewModel,
|
||||
chatViewModel = chatViewModel,
|
||||
authViewModel = authViewModel,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ 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.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalSnackbarHostState
|
||||
@@ -96,6 +97,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
val navigator = LocalNavigator.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
@@ -103,7 +105,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
val currentUser by nostrViewModel.currentUserProfile.collectAsStateWithLifecycle()
|
||||
|
||||
// Get chat room by ID
|
||||
val chatRooms by nostrViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val chatRooms by chatViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val room by remember(id) { derivedStateOf { chatRooms.firstOrNull { it.id == id } } }
|
||||
|
||||
// Show empty screen
|
||||
@@ -144,7 +146,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
val type = context.contentResolver.getType(uri)
|
||||
|
||||
// Send message
|
||||
nostrViewModel.sendFileMessage(id, file, type)
|
||||
chatViewModel.sendFileMessage(id, file, type)
|
||||
} catch (e: Exception) {
|
||||
snackbarHostState.showSnackbar("Error: ${e.message}")
|
||||
}
|
||||
@@ -157,7 +159,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
|
||||
LaunchedEffect(id) {
|
||||
// Get messages
|
||||
val initialMessages = nostrViewModel.getChatRoomMessages(id)
|
||||
val initialMessages = chatViewModel.getChatRoomMessages(id)
|
||||
messages.clear()
|
||||
messages.addAll(initialMessages)
|
||||
|
||||
@@ -165,10 +167,10 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
loading = false
|
||||
|
||||
// Get msg relays for each member
|
||||
nostrViewModel.chatRoomConnect(id)
|
||||
chatViewModel.chatRoomConnect(id)
|
||||
|
||||
// Handle new messages
|
||||
nostrViewModel.newEvents.collect { event ->
|
||||
chatViewModel.newEvents.collect { event ->
|
||||
if (event.roomId() == id) {
|
||||
if (event.id() !in messages.map { it.id() }) {
|
||||
messages.add(0, event)
|
||||
@@ -350,7 +352,7 @@ fun ChatScreen(id: Long, screening: Boolean = false) {
|
||||
value = text,
|
||||
onValueChange = { text = it },
|
||||
onSend = {
|
||||
nostrViewModel.sendMessage(id, text)
|
||||
chatViewModel.sendMessage(id, text)
|
||||
text = ""
|
||||
},
|
||||
onUpload = {
|
||||
|
||||
@@ -91,6 +91,7 @@ import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import rust.nostr.sdk.PublicKey
|
||||
import su.reya.coop.LocalAuthViewModel
|
||||
import su.reya.coop.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalScanResult
|
||||
@@ -112,6 +113,7 @@ fun HomeScreen() {
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
val clipboardManager = LocalClipboard.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val authViewModel = LocalAuthViewModel.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
@@ -120,11 +122,11 @@ fun HomeScreen() {
|
||||
val pullToRefreshState = rememberPullToRefreshState()
|
||||
|
||||
val userProfile by nostrViewModel.currentUserProfile.collectAsStateWithLifecycle()
|
||||
val chatRooms by nostrViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val chatRooms by chatViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
|
||||
val isRelayListEmpty by nostrViewModel.isRelayListEmpty.collectAsStateWithLifecycle()
|
||||
val isSyncing by nostrViewModel.isSyncing.collectAsStateWithLifecycle()
|
||||
val isPartialProcessedGiftWrap by nostrViewModel.isPartialProcessedGiftWrap.collectAsStateWithLifecycle()
|
||||
val isSyncing by chatViewModel.isSyncing.collectAsStateWithLifecycle()
|
||||
val isPartialProcessedGiftWrap by chatViewModel.isPartialProcessedGiftWrap.collectAsStateWithLifecycle()
|
||||
|
||||
val authState by authViewModel.state.collectAsStateWithLifecycle()
|
||||
val isBannerDismissed = authState.isNotificationBannerDismissed
|
||||
@@ -155,7 +157,7 @@ fun HomeScreen() {
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
nostrViewModel.getChatRooms()
|
||||
chatViewModel.refreshChatRooms()
|
||||
}
|
||||
|
||||
LaunchedEffect(qrScanResult.content) {
|
||||
@@ -163,7 +165,7 @@ fun HomeScreen() {
|
||||
runCatching { PublicKey.parse(result) }
|
||||
.onSuccess { pubkey ->
|
||||
try {
|
||||
val roomId = nostrViewModel.createChatRoom(listOf(pubkey))
|
||||
val roomId = chatViewModel.createChatRoom(listOf(pubkey))
|
||||
navigator.navigate(Screen.Chat(roomId))
|
||||
} catch (e: Exception) {
|
||||
e.message?.let { snackbarHostState.showSnackbar(it) }
|
||||
@@ -320,7 +322,7 @@ fun HomeScreen() {
|
||||
onRefresh = {
|
||||
scope.launch {
|
||||
isRefreshing = true
|
||||
nostrViewModel.refreshChatRooms()
|
||||
chatViewModel.refreshChatRooms()
|
||||
isRefreshing = false
|
||||
}
|
||||
},
|
||||
@@ -746,6 +748,7 @@ fun BottomMenuList(
|
||||
) {
|
||||
val navigator = LocalNavigator.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val authViewModel = LocalAuthViewModel.current
|
||||
|
||||
val defaultMenuList = listOf(
|
||||
@@ -776,7 +779,14 @@ fun BottomMenuList(
|
||||
}
|
||||
Spacer(modifier = Modifier.size(16.dp))
|
||||
FilledTonalButton(
|
||||
onClick = { onDismiss { authViewModel.logout(onLogout = nostrViewModel::resetInternalState) } },
|
||||
onClick = {
|
||||
onDismiss {
|
||||
authViewModel.logout(onLogout = {
|
||||
nostrViewModel.resetInternalState()
|
||||
chatViewModel.resetInternalState()
|
||||
})
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.filledTonalButtonColors(
|
||||
containerColor = MaterialTheme.colorScheme.error,
|
||||
contentColor = MaterialTheme.colorScheme.onError
|
||||
|
||||
@@ -55,6 +55,7 @@ import coop.composeapp.generated.resources.ic_scanner
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import rust.nostr.sdk.PublicKey
|
||||
import su.reya.coop.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalScanResult
|
||||
@@ -71,6 +72,7 @@ fun NewChatScreen() {
|
||||
val navigator = LocalNavigator.current
|
||||
val qrScanResult = LocalScanResult.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
|
||||
val contactList by nostrViewModel.contactList.collectAsStateWithLifecycle()
|
||||
var query by remember { mutableStateOf("") }
|
||||
@@ -169,7 +171,7 @@ fun NewChatScreen() {
|
||||
) {
|
||||
ExtendedFloatingActionButton(
|
||||
onClick = {
|
||||
val roomId = nostrViewModel.createChatRoom(selectedReceivers.toList())
|
||||
val roomId = chatViewModel.createChatRoom(selectedReceivers.toList())
|
||||
navigator.navigate(Screen.Chat(roomId))
|
||||
},
|
||||
expanded = false,
|
||||
@@ -260,7 +262,7 @@ fun NewChatScreen() {
|
||||
items = searchResults,
|
||||
selectedReceivers = selectedReceivers,
|
||||
onContactClick = { pubkey ->
|
||||
val roomId = nostrViewModel.createChatRoom(listOf(pubkey))
|
||||
val roomId = chatViewModel.createChatRoom(listOf(pubkey))
|
||||
navigator.navigate(Screen.Chat(roomId))
|
||||
},
|
||||
)
|
||||
@@ -271,7 +273,7 @@ fun NewChatScreen() {
|
||||
items = contactList.toList(),
|
||||
selectedReceivers = selectedReceivers,
|
||||
onContactClick = { pubkey ->
|
||||
val roomId = nostrViewModel.createChatRoom(listOf(pubkey))
|
||||
val roomId = chatViewModel.createChatRoom(listOf(pubkey))
|
||||
navigator.navigate(Screen.Chat(roomId))
|
||||
}
|
||||
)
|
||||
|
||||
@@ -44,6 +44,7 @@ import coop.composeapp.generated.resources.ic_share
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import rust.nostr.sdk.PublicKey
|
||||
import su.reya.coop.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalSnackbarHostState
|
||||
@@ -55,19 +56,20 @@ import su.reya.coop.short
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun ProfileScreen(pubkey: String) {
|
||||
val pubkey = runCatching { PublicKey.parse(pubkey) }.getOrNull() ?: return
|
||||
|
||||
val context = LocalContext.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
val navigator = LocalNavigator.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val pubkeyObj = runCatching { PublicKey.parse(pubkey) }.getOrNull() ?: return
|
||||
|
||||
val profileFlow = remember(pubkeyObj) { nostrViewModel.getMetadata(pubkeyObj) }
|
||||
val profileFlow = remember(pubkey) { nostrViewModel.getMetadata(pubkey) }
|
||||
val profile by profileFlow.collectAsStateWithLifecycle()
|
||||
|
||||
val metadata = profile?.metadata?.asRecord()
|
||||
val nip05 = metadata?.nip05 ?: pubkeyObj.short()
|
||||
val nip05 = metadata?.nip05 ?: pubkey.short()
|
||||
val picture = metadata?.picture
|
||||
|
||||
val details = remember(profile) {
|
||||
@@ -159,7 +161,7 @@ fun ProfileScreen(pubkey: String) {
|
||||
scope.launch {
|
||||
try {
|
||||
val roomId =
|
||||
nostrViewModel.createChatRoom(listOf(pubkeyObj))
|
||||
chatViewModel.createChatRoom(listOf(pubkey))
|
||||
navigator.navigate(Screen.Chat(roomId))
|
||||
} catch (e: Exception) {
|
||||
e.message?.let { snackbarHostState.showSnackbar(it) }
|
||||
@@ -189,7 +191,7 @@ fun ProfileScreen(pubkey: String) {
|
||||
onClick = {
|
||||
val sendIntent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_TEXT, pubkeyObj.toBech32())
|
||||
putExtra(Intent.EXTRA_TEXT, pubkey.toBech32())
|
||||
type = "text/plain"
|
||||
}
|
||||
val shareIntent = Intent.createChooser(sendIntent, null)
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coop.composeapp.generated.resources.Res
|
||||
import coop.composeapp.generated.resources.ic_arrow_back
|
||||
import kotlinx.coroutines.launch
|
||||
import su.reya.coop.LocalChatViewModel
|
||||
import su.reya.coop.LocalNavigator
|
||||
import su.reya.coop.LocalNostrViewModel
|
||||
import su.reya.coop.LocalSnackbarHostState
|
||||
@@ -49,13 +50,14 @@ fun RequestListScreen() {
|
||||
val navigator = LocalNavigator.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
val nostrViewModel = LocalNostrViewModel.current
|
||||
val chatViewModel = LocalChatViewModel.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
val pullToRefreshState = rememberPullToRefreshState()
|
||||
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
val chatRooms by nostrViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
val chatRooms by chatViewModel.chatRooms.collectAsStateWithLifecycle()
|
||||
|
||||
// Get all request rooms
|
||||
val requests = remember(chatRooms) {
|
||||
@@ -103,7 +105,7 @@ fun RequestListScreen() {
|
||||
onRefresh = {
|
||||
scope.launch {
|
||||
isRefreshing = true
|
||||
nostrViewModel.refreshChatRooms()
|
||||
chatViewModel.refreshChatRooms()
|
||||
isRefreshing = false
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user