chore: clean up codebase #42
@@ -8,17 +8,12 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import su.reya.coop.nostr.NostrManager
|
import su.reya.coop.nostr.NostrManager
|
||||||
import su.reya.coop.repository.AccountRepository
|
import su.reya.coop.repository.AccountRepository
|
||||||
import su.reya.coop.repository.ChatRepository
|
import su.reya.coop.repository.ChatRepository
|
||||||
import su.reya.coop.repository.MediaRepository
|
import su.reya.coop.repository.MediaRepository
|
||||||
import su.reya.coop.viewmodel.AccountViewModel
|
|
||||||
import su.reya.coop.viewmodel.ChatViewModel
|
|
||||||
import su.reya.coop.viewmodel.ProfileCache
|
import su.reya.coop.viewmodel.ProfileCache
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
@@ -42,28 +37,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
ChatRepository(NostrManager.instance, mediaRepository, scope)
|
ChatRepository(NostrManager.instance, mediaRepository, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val factory by lazy {
|
|
||||||
object : ViewModelProvider.Factory {
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
val result = when {
|
|
||||||
modelClass.isAssignableFrom(ChatViewModel::class.java) -> ChatViewModel(
|
|
||||||
chatRepository
|
|
||||||
)
|
|
||||||
|
|
||||||
modelClass.isAssignableFrom(AccountViewModel::class.java) -> AccountViewModel(
|
|
||||||
accountRepository
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw IllegalArgumentException("Unknown ViewModel class")
|
|
||||||
}
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return result as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val accountViewModel: AccountViewModel by viewModels { factory }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
|
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
|
||||||
throwable.printStackTrace()
|
throwable.printStackTrace()
|
||||||
@@ -101,7 +74,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
// Keep the splash screen visible until the signer check is complete
|
// Keep the splash screen visible until the signer check is complete
|
||||||
splashScreen.setKeepOnScreenCondition {
|
splashScreen.setKeepOnScreenCondition {
|
||||||
accountViewModel.state.value.signerRequired == null
|
accountRepository.state.value.signerRequired == null
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@@ -92,9 +94,22 @@ class AccountRepository(
|
|||||||
init {
|
init {
|
||||||
checkNotificationBannerDismissedStatus()
|
checkNotificationBannerDismissedStatus()
|
||||||
login()
|
login()
|
||||||
|
observeSignerState()
|
||||||
observeContactList()
|
observeContactList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun observeSignerState() {
|
||||||
|
scope.launch {
|
||||||
|
nostr.signer.publicKeyFlow
|
||||||
|
.filterNotNull()
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.collectLatest {
|
||||||
|
getUserMetadata()
|
||||||
|
checkRelayList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkNotificationBannerDismissedStatus() {
|
private fun checkNotificationBannerDismissedStatus() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val dismissed = storage.get(KEY_BANNER_DISMISSED) == "true"
|
val dismissed = storage.get(KEY_BANNER_DISMISSED) == "true"
|
||||||
@@ -119,7 +134,6 @@ class AccountRepository(
|
|||||||
nostr.setSigner(signer)
|
nostr.setSigner(signer)
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
_state.update { it.copy(signerRequired = false) }
|
_state.update { it.copy(signerRequired = false) }
|
||||||
onSignerReady()
|
|
||||||
}.onFailure { e ->
|
}.onFailure { e ->
|
||||||
showError("Login failed: ${e.message}")
|
showError("Login failed: ${e.message}")
|
||||||
_state.update { it.copy(signerRequired = true) }
|
_state.update { it.copy(signerRequired = true) }
|
||||||
@@ -209,7 +223,6 @@ class AccountRepository(
|
|||||||
val (signer, decryptedSecret) = createSigner(secret, password)
|
val (signer, decryptedSecret) = createSigner(secret, password)
|
||||||
|
|
||||||
nostr.setSigner(signer)
|
nostr.setSigner(signer)
|
||||||
onSignerReady()
|
|
||||||
|
|
||||||
storage.setSecret(KEY_USER_SIGNER, decryptedSecret ?: secret)
|
storage.setSecret(KEY_USER_SIGNER, decryptedSecret ?: secret)
|
||||||
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
||||||
@@ -247,7 +260,6 @@ class AccountRepository(
|
|||||||
val uri = "nip55://${result.packageName}/${result.pubkey.toHex()}"
|
val uri = "nip55://${result.packageName}/${result.pubkey.toHex()}"
|
||||||
|
|
||||||
nostr.setSigner(signer)
|
nostr.setSigner(signer)
|
||||||
onSignerReady()
|
|
||||||
|
|
||||||
storage.setSecret(KEY_USER_SIGNER, uri)
|
storage.setSecret(KEY_USER_SIGNER, uri)
|
||||||
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
||||||
@@ -279,7 +291,6 @@ class AccountRepository(
|
|||||||
bio = bio,
|
bio = bio,
|
||||||
picture = avatarUrl
|
picture = avatarUrl
|
||||||
)
|
)
|
||||||
onSignerReady()
|
|
||||||
|
|
||||||
storage.setSecret(KEY_USER_SIGNER, secret)
|
storage.setSecret(KEY_USER_SIGNER, secret)
|
||||||
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
_state.update { it.copy(signerRequired = false, isImporting = false) }
|
||||||
@@ -290,10 +301,6 @@ class AccountRepository(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSignerReady() {
|
|
||||||
getUserMetadata()
|
|
||||||
checkRelayList()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private fun currentUserProfileFlow(pubkey: PublicKey) = merge(
|
private fun currentUserProfileFlow(pubkey: PublicKey) = merge(
|
||||||
@@ -308,7 +315,7 @@ class AccountRepository(
|
|||||||
.map { (p, m) -> Profile(p, m) }
|
.map { (p, m) -> Profile(p, m) }
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getUserMetadata() {
|
private fun getUserMetadata() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
nostr.profiles.getUserMetadata()
|
nostr.profiles.getUserMetadata()
|
||||||
}
|
}
|
||||||
@@ -448,7 +455,7 @@ class AccountRepository(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
fun checkRelayList() {
|
private fun checkRelayList() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val currentUser = nostr.signer.publicKeyFlow.filterNotNull().first()
|
val currentUser = nostr.signer.publicKeyFlow.filterNotNull().first()
|
||||||
|
|
||||||
|
|||||||
@@ -19,37 +19,57 @@ class AccountViewModel(
|
|||||||
val currentUserProfile: StateFlow<Profile?> = repository.currentUserProfile
|
val currentUserProfile: StateFlow<Profile?> = repository.currentUserProfile
|
||||||
val contactList: StateFlow<Set<PublicKey>> = repository.contactList
|
val contactList: StateFlow<Set<PublicKey>> = repository.contactList
|
||||||
val isRelayListEmpty: StateFlow<Boolean> = repository.isRelayListEmpty
|
val isRelayListEmpty: StateFlow<Boolean> = repository.isRelayListEmpty
|
||||||
val currentUserRelayList: StateFlow<Map<RelayUrl, RelayMetadata?>> = repository.currentUserRelayList
|
val currentUserRelayList: StateFlow<Map<RelayUrl, RelayMetadata?>> =
|
||||||
|
repository.currentUserRelayList
|
||||||
val currentUserMsgRelayList: StateFlow<List<RelayUrl>> = repository.currentUserMsgRelayList
|
val currentUserMsgRelayList: StateFlow<List<RelayUrl>> = repository.currentUserMsgRelayList
|
||||||
|
|
||||||
fun logout(onLogout: () -> Unit = {}) = repository.logout(onLogout)
|
fun logout(onLogout: () -> Unit = {}) = repository.logout(onLogout)
|
||||||
fun dismissNotificationBanner() = repository.dismissNotificationBanner()
|
fun dismissNotificationBanner() = repository.dismissNotificationBanner()
|
||||||
fun isExternalSignerAvailable() = repository.isExternalSignerAvailable()
|
fun isExternalSignerAvailable() = repository.isExternalSignerAvailable()
|
||||||
fun importIdentity(secret: String, password: String? = null) = repository.importIdentity(secret, password)
|
fun importIdentity(secret: String, password: String? = null) =
|
||||||
|
repository.importIdentity(secret, password)
|
||||||
|
|
||||||
fun connectExternalSigner() = repository.connectExternalSigner()
|
fun connectExternalSigner() = repository.connectExternalSigner()
|
||||||
fun createIdentity(name: String, bio: String?, picture: ByteArray?, contentType: String? = null) =
|
fun createIdentity(
|
||||||
|
name: String,
|
||||||
|
bio: String?,
|
||||||
|
picture: ByteArray?,
|
||||||
|
contentType: String? = null
|
||||||
|
) =
|
||||||
repository.createIdentity(name, bio, picture, contentType)
|
repository.createIdentity(name, bio, picture, contentType)
|
||||||
|
|
||||||
fun getUserMetadata() = repository.getUserMetadata()
|
fun updateProfile(
|
||||||
fun updateProfile(name: String? = null, bio: String? = null, picture: ByteArray? = null, contentType: String? = null) =
|
name: String? = null,
|
||||||
|
bio: String? = null,
|
||||||
|
picture: ByteArray? = null,
|
||||||
|
contentType: String? = null
|
||||||
|
) =
|
||||||
repository.updateProfile(name, bio, picture, contentType)
|
repository.updateProfile(name, bio, picture, contentType)
|
||||||
|
|
||||||
fun resetInternalState() = repository.resetInternalState()
|
fun resetInternalState() = repository.resetInternalState()
|
||||||
fun addContact(address: String) = repository.addContact(address)
|
fun addContact(address: String) = repository.addContact(address)
|
||||||
fun removeContact(publicKey: PublicKey) = repository.removeContact(publicKey)
|
fun removeContact(publicKey: PublicKey) = repository.removeContact(publicKey)
|
||||||
fun searchByAddress(query: String, onResult: (PublicKey?) -> Unit) = repository.searchByAddress(query, onResult)
|
fun searchByAddress(query: String, onResult: (PublicKey?) -> Unit) =
|
||||||
fun searchByNostr(query: String, onResult: (List<PublicKey>) -> Unit) = repository.searchByNostr(query, onResult)
|
repository.searchByAddress(query, onResult)
|
||||||
fun verifyActivity(pubkey: PublicKey, onResult: (Timestamp?) -> Unit) = repository.verifyActivity(pubkey, onResult)
|
|
||||||
fun verifyContact(pubkey: PublicKey, onResult: (Boolean) -> Unit) = repository.verifyContact(pubkey, onResult)
|
fun searchByNostr(query: String, onResult: (List<PublicKey>) -> Unit) =
|
||||||
fun mutualContacts(pubkey: PublicKey, onResult: (Set<PublicKey>) -> Unit) = repository.mutualContacts(pubkey, onResult)
|
repository.searchByNostr(query, onResult)
|
||||||
fun checkRelayList() = repository.checkRelayList()
|
|
||||||
|
fun verifyActivity(pubkey: PublicKey, onResult: (Timestamp?) -> Unit) =
|
||||||
|
repository.verifyActivity(pubkey, onResult)
|
||||||
|
|
||||||
|
fun verifyContact(pubkey: PublicKey, onResult: (Boolean) -> Unit) =
|
||||||
|
repository.verifyContact(pubkey, onResult)
|
||||||
|
|
||||||
|
fun mutualContacts(pubkey: PublicKey, onResult: (Set<PublicKey>) -> Unit) =
|
||||||
|
repository.mutualContacts(pubkey, onResult)
|
||||||
|
|
||||||
fun dismissRelayWarning() = repository.dismissRelayWarning()
|
fun dismissRelayWarning() = repository.dismissRelayWarning()
|
||||||
fun refetchMsgRelays() = repository.refetchMsgRelays()
|
fun refetchMsgRelays() = repository.refetchMsgRelays()
|
||||||
fun useDefaultMsgRelayList() = repository.useDefaultMsgRelayList()
|
fun useDefaultMsgRelayList() = repository.useDefaultMsgRelayList()
|
||||||
fun loadCurrentUserRelayList() = repository.loadCurrentUserRelayList()
|
fun loadCurrentUserRelayList() = repository.loadCurrentUserRelayList()
|
||||||
fun addInboxRelay(relay: String) = repository.addInboxRelay(relay)
|
fun addInboxRelay(relay: String) = repository.addInboxRelay(relay)
|
||||||
fun addOutboxRelay(relay: String) = repository.addOutboxRelay(relay)
|
fun addOutboxRelay(relay: String) = repository.addOutboxRelay(relay)
|
||||||
fun removeRelay(relay: String) = repository.removeRelay(relay)
|
|
||||||
fun loadCurrentUserMsgRelayList() = repository.loadCurrentUserMsgRelayList()
|
fun loadCurrentUserMsgRelayList() = repository.loadCurrentUserMsgRelayList()
|
||||||
fun addMsgRelay(relay: String) = repository.addMsgRelay(relay)
|
fun addMsgRelay(relay: String) = repository.addMsgRelay(relay)
|
||||||
fun removeMsgRelay(relay: String) = repository.removeMsgRelay(relay)
|
fun removeMsgRelay(relay: String) = repository.removeMsgRelay(relay)
|
||||||
|
|||||||
Reference in New Issue
Block a user