chore: refactor the internal structure #33
@@ -47,6 +47,9 @@ import su.reya.coop.screens.RelayScreen
|
|||||||
import su.reya.coop.screens.RequestListScreen
|
import su.reya.coop.screens.RequestListScreen
|
||||||
import su.reya.coop.screens.ScanScreen
|
import su.reya.coop.screens.ScanScreen
|
||||||
import su.reya.coop.screens.UpdateProfileScreen
|
import su.reya.coop.screens.UpdateProfileScreen
|
||||||
|
import su.reya.coop.viewmodel.AuthViewModel
|
||||||
|
import su.reya.coop.viewmodel.ChatViewModel
|
||||||
|
import su.reya.coop.viewmodel.NostrViewModel
|
||||||
|
|
||||||
val LocalNostrViewModel = staticCompositionLocalOf<NostrViewModel> {
|
val LocalNostrViewModel = staticCompositionLocalOf<NostrViewModel> {
|
||||||
error("No NostrViewModel provided")
|
error("No NostrViewModel provided")
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import su.reya.coop.coop.storage.SecretStore
|
import su.reya.coop.coop.storage.SecretStore
|
||||||
import su.reya.coop.nostr.NostrManager
|
import su.reya.coop.nostr.NostrManager
|
||||||
|
import su.reya.coop.viewmodel.AuthViewModel
|
||||||
|
import su.reya.coop.viewmodel.ChatViewModel
|
||||||
|
import su.reya.coop.viewmodel.NostrViewModel
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ import androidx.compose.material3.rememberTooltipState
|
|||||||
import androidx.compose.material3.toShape
|
import androidx.compose.material3.toShape
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -621,7 +620,6 @@ fun HomeScreen() {
|
|||||||
fun NewRequests(requests: List<Room>) {
|
fun NewRequests(requests: List<Room>) {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val nostrViewModel = LocalNostrViewModel.current
|
val nostrViewModel = LocalNostrViewModel.current
|
||||||
val authViewModel = LocalAuthViewModel.current
|
|
||||||
|
|
||||||
val total = requests.size
|
val total = requests.size
|
||||||
val firstRoom = requests.getOrNull(0)
|
val firstRoom = requests.getOrNull(0)
|
||||||
@@ -700,7 +698,6 @@ fun NewRequests(requests: List<Room>) {
|
|||||||
@Composable
|
@Composable
|
||||||
fun ChatRoom(room: Room, onClick: () -> Unit) {
|
fun ChatRoom(room: Room, onClick: () -> Unit) {
|
||||||
val nostrViewModel = LocalNostrViewModel.current
|
val nostrViewModel = LocalNostrViewModel.current
|
||||||
val authViewModel = LocalAuthViewModel.current
|
|
||||||
val roomState by room.rememberUiState(nostrViewModel)
|
val roomState by room.rememberUiState(nostrViewModel)
|
||||||
|
|
||||||
ListItem(
|
ListItem(
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import su.reya.coop.LocalAuthViewModel
|
import su.reya.coop.LocalAuthViewModel
|
||||||
import su.reya.coop.LocalNavigator
|
import su.reya.coop.LocalNavigator
|
||||||
import su.reya.coop.LocalNostrViewModel
|
|
||||||
import su.reya.coop.Screen
|
import su.reya.coop.Screen
|
||||||
import su.reya.coop.shared.ProfileEditor
|
import su.reya.coop.shared.ProfileEditor
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NewIdentityScreen() {
|
fun NewIdentityScreen() {
|
||||||
val nostrViewModel = LocalNostrViewModel.current
|
|
||||||
val authViewModel = LocalAuthViewModel.current
|
val authViewModel = LocalAuthViewModel.current
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ import kotlinx.coroutines.launch
|
|||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
import su.reya.coop.LocalAuthViewModel
|
import su.reya.coop.LocalAuthViewModel
|
||||||
import su.reya.coop.LocalNavigator
|
import su.reya.coop.LocalNavigator
|
||||||
import su.reya.coop.LocalNostrViewModel
|
|
||||||
import su.reya.coop.LocalSnackbarHostState
|
import su.reya.coop.LocalSnackbarHostState
|
||||||
import su.reya.coop.Screen
|
import su.reya.coop.Screen
|
||||||
import su.reya.coop.shared.getExpressiveFontFamily
|
import su.reya.coop.shared.getExpressiveFontFamily
|
||||||
@@ -58,7 +57,6 @@ fun OnboardingScreen() {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val snackbarHostState = LocalSnackbarHostState.current
|
val snackbarHostState = LocalSnackbarHostState.current
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val nostrViewModel = LocalNostrViewModel.current
|
|
||||||
val authViewModel = LocalAuthViewModel.current
|
val authViewModel = LocalAuthViewModel.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import coop.composeapp.generated.resources.ic_arrow_back
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import su.reya.coop.LocalChatViewModel
|
import su.reya.coop.LocalChatViewModel
|
||||||
import su.reya.coop.LocalNavigator
|
import su.reya.coop.LocalNavigator
|
||||||
import su.reya.coop.LocalNostrViewModel
|
|
||||||
import su.reya.coop.LocalSnackbarHostState
|
import su.reya.coop.LocalSnackbarHostState
|
||||||
import su.reya.coop.RoomKind
|
import su.reya.coop.RoomKind
|
||||||
import su.reya.coop.Screen
|
import su.reya.coop.Screen
|
||||||
@@ -49,7 +48,6 @@ import su.reya.coop.Screen
|
|||||||
fun RequestListScreen() {
|
fun RequestListScreen() {
|
||||||
val navigator = LocalNavigator.current
|
val navigator = LocalNavigator.current
|
||||||
val snackbarHostState = LocalSnackbarHostState.current
|
val snackbarHostState = LocalSnackbarHostState.current
|
||||||
val nostrViewModel = LocalNostrViewModel.current
|
|
||||||
val chatViewModel = LocalChatViewModel.current
|
val chatViewModel = LocalChatViewModel.current
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import kotlinx.datetime.toLocalDateTime
|
|||||||
import rust.nostr.sdk.PublicKey
|
import rust.nostr.sdk.PublicKey
|
||||||
import rust.nostr.sdk.Timestamp
|
import rust.nostr.sdk.Timestamp
|
||||||
import rust.nostr.sdk.UnsignedEvent
|
import rust.nostr.sdk.UnsignedEvent
|
||||||
|
import su.reya.coop.viewmodel.NostrViewModel
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
import kotlin.time.Instant
|
import kotlin.time.Instant
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
package su.reya.coop
|
package su.reya.coop.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import rust.nostr.sdk.AsyncNostrSigner
|
import rust.nostr.sdk.AsyncNostrSigner
|
||||||
import rust.nostr.sdk.Keys
|
import rust.nostr.sdk.Keys
|
||||||
import rust.nostr.sdk.NostrConnect
|
import rust.nostr.sdk.NostrConnect
|
||||||
import rust.nostr.sdk.NostrConnectUri
|
import rust.nostr.sdk.NostrConnectUri
|
||||||
import rust.nostr.sdk.PublicKey
|
import rust.nostr.sdk.PublicKey
|
||||||
import su.reya.coop.blossom.BlossomClient
|
|
||||||
import su.reya.coop.nostr.ExternalSignerHandler
|
import su.reya.coop.nostr.ExternalSignerHandler
|
||||||
import su.reya.coop.nostr.ExternalSignerProxy
|
import su.reya.coop.nostr.ExternalSignerProxy
|
||||||
import su.reya.coop.nostr.Nostr
|
import su.reya.coop.nostr.Nostr
|
||||||
@@ -241,11 +236,15 @@ class AuthViewModel(
|
|||||||
val secret = keys.secretKey().toBech32()
|
val secret = keys.secretKey().toBech32()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val avatarUrl = picture?.let { blossomUpload(it, contentType ?: "image/jpeg") }
|
val avatarUrl =
|
||||||
|
picture?.let { blossomUpload(nostr.signer.get(), it, contentType ?: "image/jpeg") }
|
||||||
|
|
||||||
// Create identity
|
// Create identity
|
||||||
nostr.profiles.createIdentity(keys = keys, name = name, bio = bio, picture = avatarUrl)
|
nostr.profiles.createIdentity(keys = keys, name = name, bio = bio, picture = avatarUrl)
|
||||||
|
|
||||||
// Persist the secret in the secret storage
|
// Persist the secret in the secret storage
|
||||||
secretStore.set(KEY_USER_SIGNER, secret)
|
secretStore.set(KEY_USER_SIGNER, secret)
|
||||||
|
|
||||||
// Update local states
|
// Update local states
|
||||||
_state.update { it.copy(isBusy = false, signerRequired = false) }
|
_state.update { it.copy(isBusy = false, signerRequired = false) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -253,35 +252,4 @@ class AuthViewModel(
|
|||||||
_state.update { it.copy(isBusy = false) }
|
_state.update { it.copy(isBusy = false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun blossomUpload(
|
|
||||||
file: ByteArray,
|
|
||||||
contentType: String? = "image/jpeg"
|
|
||||||
): String? {
|
|
||||||
try {
|
|
||||||
val blossom = BlossomClient(
|
|
||||||
url = "https://blossom.band",
|
|
||||||
client = HttpClient {
|
|
||||||
install(ContentNegotiation) {
|
|
||||||
json(Json {
|
|
||||||
ignoreUnknownKeys = true
|
|
||||||
prettyPrint = true
|
|
||||||
isLenient = true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val descriptor = blossom.upload(
|
|
||||||
file = file,
|
|
||||||
contentType = contentType,
|
|
||||||
signer = nostr.signer.get()
|
|
||||||
)
|
|
||||||
|
|
||||||
return descriptor?.url
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showError("Error: ${e.message}")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package su.reya.coop
|
package su.reya.coop.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
@@ -6,6 +6,7 @@ import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
|||||||
import io.ktor.serialization.kotlinx.json.json
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import rust.nostr.sdk.AsyncNostrSigner
|
import rust.nostr.sdk.AsyncNostrSigner
|
||||||
|
import su.reya.coop.ErrorManager
|
||||||
import su.reya.coop.blossom.BlossomClient
|
import su.reya.coop.blossom.BlossomClient
|
||||||
|
|
||||||
abstract class BaseViewModel : ViewModel() {
|
abstract class BaseViewModel : ViewModel() {
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
package su.reya.coop
|
package su.reya.coop.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -19,7 +18,9 @@ import rust.nostr.sdk.PublicKey
|
|||||||
import rust.nostr.sdk.RelayUrl
|
import rust.nostr.sdk.RelayUrl
|
||||||
import rust.nostr.sdk.Tag
|
import rust.nostr.sdk.Tag
|
||||||
import rust.nostr.sdk.UnsignedEvent
|
import rust.nostr.sdk.UnsignedEvent
|
||||||
|
import su.reya.coop.Room
|
||||||
import su.reya.coop.nostr.Nostr
|
import su.reya.coop.nostr.Nostr
|
||||||
|
import su.reya.coop.roomId
|
||||||
|
|
||||||
data class ChatState(
|
data class ChatState(
|
||||||
val isSyncing: Boolean = false,
|
val isSyncing: Boolean = false,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package su.reya.coop
|
package su.reya.coop.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -27,6 +27,7 @@ import rust.nostr.sdk.PublicKey
|
|||||||
import rust.nostr.sdk.RelayMetadata
|
import rust.nostr.sdk.RelayMetadata
|
||||||
import rust.nostr.sdk.RelayUrl
|
import rust.nostr.sdk.RelayUrl
|
||||||
import rust.nostr.sdk.Timestamp
|
import rust.nostr.sdk.Timestamp
|
||||||
|
import su.reya.coop.Profile
|
||||||
import su.reya.coop.nostr.Nostr
|
import su.reya.coop.nostr.Nostr
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
Reference in New Issue
Block a user