.
This commit is contained in:
@@ -39,14 +39,12 @@ import androidx.compose.ui.text.font.FontStyle
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import androidx.navigation.toRoute
|
import androidx.navigation.toRoute
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import su.reya.coop.coop.storage.SecretStore
|
|
||||||
import su.reya.coop.screens.ChatScreen
|
import su.reya.coop.screens.ChatScreen
|
||||||
import su.reya.coop.screens.HomeScreen
|
import su.reya.coop.screens.HomeScreen
|
||||||
import su.reya.coop.screens.ImportScreen
|
import su.reya.coop.screens.ImportScreen
|
||||||
@@ -72,7 +70,10 @@ val LocalNavController = staticCompositionLocalOf<NavController> {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun App(openRoomId: Long? = null) {
|
fun App(
|
||||||
|
viewModel: NostrViewModel,
|
||||||
|
openRoomId: Long? = null
|
||||||
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -81,10 +82,6 @@ fun App(openRoomId: Long? = null) {
|
|||||||
// Snackbar
|
// Snackbar
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
// Initialize Nostr View Model and Secret Store
|
|
||||||
val secretStore = remember { SecretStore(context) }
|
|
||||||
val viewModel: NostrViewModel = viewModel { NostrViewModel(NostrManager.instance, secretStore) }
|
|
||||||
|
|
||||||
// Enabled the dynamic color scheme
|
// Enabled the dynamic color scheme
|
||||||
val colorScheme = when {
|
val colorScheme = when {
|
||||||
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S -> {
|
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S -> {
|
||||||
@@ -101,12 +98,6 @@ fun App(openRoomId: Long? = null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(openRoomId) {
|
|
||||||
if (openRoomId != null) {
|
|
||||||
navController.navigate(Screen.Chat(openRoomId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialExpressiveTheme(
|
MaterialExpressiveTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
typography = Typography(),
|
typography = Typography(),
|
||||||
@@ -123,15 +114,20 @@ fun App(openRoomId: Long? = null) {
|
|||||||
|
|
||||||
LaunchedEffect(emptySecret) {
|
LaunchedEffect(emptySecret) {
|
||||||
// Navigate to the home screen if the secret is already set
|
// Navigate to the home screen if the secret is already set
|
||||||
if (emptySecret == false) {
|
if (emptySecret == false && openRoomId == null) {
|
||||||
navController.navigate(Screen.Home) {
|
navController.navigate(Screen.Home) {
|
||||||
popUpTo(Screen.Onboarding) { inclusive = true }
|
popUpTo(Screen.Onboarding) { inclusive = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show loading screen while initializing
|
LaunchedEffect(openRoomId) {
|
||||||
if (emptySecret == null) return@CompositionLocalProvider
|
if (openRoomId != null) {
|
||||||
|
navController.navigate(Screen.Chat(openRoomId)) {
|
||||||
|
popUpTo(Screen.Home) { saveState = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Show the relay setup dialog if the msg relay list is empty
|
// Show the relay setup dialog if the msg relay list is empty
|
||||||
if (isRelayListEmpty) {
|
if (isRelayListEmpty) {
|
||||||
|
|||||||
@@ -7,26 +7,40 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
|
import su.reya.coop.coop.storage.SecretStore
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
installSplashScreen()
|
val splashScreen = installSplashScreen()
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
val intent = Intent(this, NostrForegroundService::class.java)
|
val serviceIntent = Intent(this, NostrForegroundService::class.java)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
startForegroundService(intent)
|
startForegroundService(serviceIntent)
|
||||||
} else {
|
} else {
|
||||||
startService(intent)
|
startService(serviceIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
val roomId = intent.getLongExtra("room_id", -1L)
|
val roomId = intent.getLongExtra("room_id", -1L)
|
||||||
|
val secretStore = SecretStore(this)
|
||||||
|
val viewModel = NostrViewModel(NostrManager.instance, secretStore)
|
||||||
|
|
||||||
|
splashScreen.setKeepOnScreenCondition {
|
||||||
|
viewModel.emptySecret.value == null
|
||||||
|
}
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
App(openRoomId = if (roomId != -1L) roomId else null)
|
App(
|
||||||
|
viewModel = viewModel,
|
||||||
|
openRoomId = if (roomId != -1L) roomId else null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
setIntent(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import io.ktor.client.plugins.websocket.WebSockets
|
|||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.HttpResponse
|
import io.ktor.client.statement.HttpResponse
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.coroutineScope
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.supervisorScope
|
||||||
import rust.nostr.sdk.AckPolicy
|
import rust.nostr.sdk.AckPolicy
|
||||||
import rust.nostr.sdk.Alphabet
|
import rust.nostr.sdk.Alphabet
|
||||||
import rust.nostr.sdk.AsyncNostrSigner
|
import rust.nostr.sdk.AsyncNostrSigner
|
||||||
@@ -170,8 +170,6 @@ class Nostr {
|
|||||||
suspend fun setSigner(new: AsyncNostrSigner) {
|
suspend fun setSigner(new: AsyncNostrSigner) {
|
||||||
try {
|
try {
|
||||||
signer.switch(new)
|
signer.switch(new)
|
||||||
// Fetch metadata for current user
|
|
||||||
getUserMetadata()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw IllegalStateException("Failed to set signer: ${e.message}", e)
|
throw IllegalStateException("Failed to set signer: ${e.message}", e)
|
||||||
}
|
}
|
||||||
@@ -244,10 +242,10 @@ class Nostr {
|
|||||||
onContactListUpdate: (List<PublicKey>) -> Unit,
|
onContactListUpdate: (List<PublicKey>) -> Unit,
|
||||||
onNewMessage: (UnsignedEvent) -> Unit,
|
onNewMessage: (UnsignedEvent) -> Unit,
|
||||||
onSubscriptionClose: () -> Unit,
|
onSubscriptionClose: () -> Unit,
|
||||||
) = coroutineScope {
|
) = supervisorScope {
|
||||||
val now = Timestamp.now()
|
val now = Timestamp.now()
|
||||||
val processedEvent = mutableSetOf<EventId>()
|
val processedEvent = mutableSetOf<EventId>()
|
||||||
val notifications = client?.notifications() ?: return@coroutineScope
|
val notifications = client?.notifications() ?: return@supervisorScope
|
||||||
|
|
||||||
var eoseTrackerJob: Job? = null
|
var eoseTrackerJob: Job? = null
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class NostrViewModel(
|
|||||||
|
|
||||||
// Observe new events from the Nostr client
|
// Observe new events from the Nostr client
|
||||||
runObserver()
|
runObserver()
|
||||||
|
|
||||||
// Wait and merge metadata requests into a single batch
|
// Wait and merge metadata requests into a single batch
|
||||||
runMetadataBatching()
|
runMetadataBatching()
|
||||||
}
|
}
|
||||||
@@ -201,9 +201,6 @@ class NostrViewModel(
|
|||||||
|
|
||||||
private fun login() {
|
private fun login() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
// Wait until the client is ready
|
|
||||||
nostr.waitUntilInitialized()
|
|
||||||
|
|
||||||
// Get user's signer secret
|
// Get user's signer secret
|
||||||
val secret = secretStore.get("user_signer")
|
val secret = secretStore.get("user_signer")
|
||||||
|
|
||||||
@@ -249,6 +246,9 @@ class NostrViewModel(
|
|||||||
_isPartialProcessedGiftWrap.value = true
|
_isPartialProcessedGiftWrap.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all metadata for the current user
|
||||||
|
nostr.getUserMetadata()
|
||||||
|
|
||||||
// Small delay to ensure all relays are connected
|
// Small delay to ensure all relays are connected
|
||||||
delay(3000)
|
delay(3000)
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ class NostrViewModel(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1000)
|
delay(500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user