diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index 11f4e730c..ae385c310 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -35,7 +35,8 @@ private const val DEBUG_PREFERENCES_NAME = "debug_prefs" @Immutable data class AccountInfo( val npub: String, - val hasPrivKey: Boolean = false + val hasPrivKey: Boolean, + val loggedInWithAmber: Boolean ) private object PrefKeys { @@ -202,7 +203,11 @@ object LocalPreferences { fun allSavedAccounts(): List { return savedAccounts().map { npub -> - AccountInfo(npub = npub) + AccountInfo( + npub, + hasPrivKey(npub), + getLoggedInWithAmber(npub) + ) } } @@ -291,6 +296,22 @@ object LocalPreferences { return language } + private fun getLoggedInWithAmber(npub: String): Boolean { + var loggedInWithAmber: Boolean + encryptedPreferences(npub).apply { + loggedInWithAmber = getBoolean(PrefKeys.LOGIN_WITH_AMBER, false) + } + return loggedInWithAmber + } + + private fun hasPrivKey(npub: String): Boolean { + var hasPrivKey: Boolean + encryptedPreferences(npub).apply { + hasPrivKey = (getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "").isNotBlank() + } + return hasPrivKey + } + fun loadFromEncryptedStorage(): Account? { val acc = loadFromEncryptedStorage(currentAccount()) acc?.registerObservers() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index acef3735d..d85e58f73 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -202,7 +202,7 @@ class Account( return null } - fun sendNewUserMetadata(toString: String, identities: List, signEvent: Boolean = true): MetadataEvent? { + fun sendNewUserMetadata(toString: String, identities: List, signEvent: Boolean): MetadataEvent? { if (!isWriteable() && signEvent) return null val event = MetadataEvent.create(toString, identities, keyPair.pubKey.toHexKey(), keyPair.privKey) @@ -1438,8 +1438,8 @@ class Account( LocalCache.consume(event) } - fun createAuthEvent(relay: Relay, challenge: String, isAmberInstalled: Boolean): RelayAuthEvent? { - if (!isWriteable() && !isAmberInstalled) return null + fun createAuthEvent(relay: Relay, challenge: String, loggedInWithAmber: Boolean): RelayAuthEvent? { + if (!isWriteable() && !loggedInWithAmber) return null return RelayAuthEvent.create(relay.url, challenge, keyPair.pubKey.toHexKey(), keyPair.privKey) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt index aa56888f4..7a92d4ffc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt @@ -193,10 +193,10 @@ object NostrAccountDataSource : NostrDataSource("AccountData") { if (this::account.isInitialized) { val context = Amethyst.instance - val isAmberInstalled = PackageUtils.isAmberInstalled(context) - val event = account.createAuthEvent(relay, challenge, isAmberInstalled) + val loggedInWithAmber = account.loginWithAmber + val event = account.createAuthEvent(relay, challenge, loggedInWithAmber) - if (isAmberInstalled && !account.isWriteable()) { + if (loggedInWithAmber && !account.isWriteable()) { if (event != null) { openAmber( event.toJson(), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt index 7c04dd131..2e0c9ae8e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt @@ -2,12 +2,10 @@ package com.vitorpamplona.amethyst.service.notifications import android.util.Log import com.vitorpamplona.amethyst.AccountInfo -import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.BuildConfig import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.service.HttpClient import com.vitorpamplona.amethyst.service.IntentUtils -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.amethyst.ui.actions.openAmber import com.vitorpamplona.quartz.events.RelayAuthEvent @@ -25,14 +23,14 @@ class RegisterAccounts( private fun signEventsToProveControlOfAccounts( accounts: List, notificationToken: String, - isAmberInstalled: Boolean + loggedInWithAmber: Boolean ): List { return accounts.mapNotNull { val acc = LocalPreferences.loadFromEncryptedStorage(it.npub) if (acc != null) { val relayToUse = acc.activeRelays()?.firstOrNull { it.read } if (relayToUse != null) { - val event = acc.createAuthEvent(relayToUse, notificationToken, isAmberInstalled) + val event = acc.createAuthEvent(relayToUse, notificationToken, loggedInWithAmber) event } else { null @@ -70,11 +68,11 @@ class RegisterAccounts( } suspend fun go(notificationToken: String) = withContext(Dispatchers.IO) { - val isAmberInstalled = PackageUtils.isAmberInstalled(Amethyst.instance) val accountsWithoutPrivKey = accounts.filter { !it.hasPrivKey } val accountsWithPrivKey = accounts.filter { it.hasPrivKey } accountsWithoutPrivKey.forEach { account -> - val events = signEventsToProveControlOfAccounts(listOf(account), notificationToken, isAmberInstalled) + Log.d("fcm register", account.npub) + val events = signEventsToProveControlOfAccounts(listOf(account), notificationToken, account.loggedInWithAmber) if (events.isNotEmpty()) { openAmber( events.first().toJson(), @@ -87,7 +85,7 @@ class RegisterAccounts( if (accountsWithPrivKey.isNotEmpty()) { postRegistrationEvent( - signEventsToProveControlOfAccounts(accountsWithPrivKey, notificationToken, isAmberInstalled) + signEventsToProveControlOfAccounts(accountsWithPrivKey, notificationToken, false) ) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt index 212747f18..e0c238873 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt @@ -34,7 +34,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.quartz.events.Event @@ -104,9 +103,8 @@ fun NewUserMetadataView(onClose: () -> Unit, account: Account) { PostButton( onPost = { - if (PackageUtils.isAmberInstalled(context)) { + if (account.loginWithAmber) { event = postViewModel.create(false) - println(event) } else { postViewModel.create(true) onClose() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt index 47363e008..da28bb30e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt @@ -124,11 +124,11 @@ class NewUserMetadataViewModel : ViewModel() { if (signEvent) { viewModelScope.launch(Dispatchers.IO) { - account.sendNewUserMetadata(writer.buffer.toString(), newClaims, signEvent) + account.sendNewUserMetadata(writer.buffer.toString(), newClaims, true) } clear() } else { - return account.sendNewUserMetadata(writer.buffer.toString(), newClaims, signEvent) + return account.sendNewUserMetadata(writer.buffer.toString(), newClaims, false) } return null diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index b9bdeb5a9..4eee90c49 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -35,7 +35,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.layout.onSizeChanged -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -45,7 +44,6 @@ import androidx.lifecycle.map import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.ui.actions.SignerDialog import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji @@ -639,10 +637,9 @@ private fun RenderRegularTextNote( val tags = remember(note.event) { note.event?.tags()?.toImmutableListOfLists() ?: ImmutableListOfLists() } var eventContent by remember { mutableStateOf(accountViewModel.decrypt(note)) } val modifier = remember { Modifier.padding(top = 5.dp) } - val context = LocalContext.current - val isAmberInstalled = PackageUtils.isAmberInstalled(context) + val loggedInWithAmber = accountViewModel.loggedInWithAmber() var triedToDecrypt by remember { mutableStateOf(false) } - if (isAmberInstalled && !triedToDecrypt && note.event is PrivateDmEvent) { + if (loggedInWithAmber && !triedToDecrypt && note.event is PrivateDmEvent) { SignerDialog( onClose = { triedToDecrypt = true diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index c62083b6d..43a5a4fea 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -78,7 +78,6 @@ import coil.request.ImageRequest import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.actions.NewPostView import com.vitorpamplona.amethyst.ui.actions.SignerDialog @@ -572,7 +571,7 @@ fun ReplyReaction( if (accountViewModel.isWriteable()) { onPress() } else { - if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.loggedInWithAmber()) { onPress() } else { scope.launch { @@ -705,7 +704,7 @@ fun BoostReaction( wantsToBoost = true } } else { - if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.loggedInWithAmber()) { if (accountViewModel.hasBoosted(baseNote)) { scope.launch(Dispatchers.IO) { event = accountViewModel.deleteBoostsTo(baseNote, false) @@ -995,7 +994,7 @@ private fun likeClick( .show() } } else if (!accountViewModel.isWriteable()) { - if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.loggedInWithAmber()) { onWantsToSignReaction() } else { scope.launch { @@ -1420,14 +1419,14 @@ private fun ActionableReactionButton( Button( modifier = Modifier.padding(horizontal = 3.dp), onClick = { - val isAmberInstalled = PackageUtils.isAmberInstalled(context) + val loggedInWithAmber = accountViewModel.loggedInWithAmber() scope.launch(Dispatchers.IO) { event = accountViewModel.reactToOrDelete( baseNote, reactionType, - !isAmberInstalled + !loggedInWithAmber ) - if (!isAmberInstalled) { + if (!loggedInWithAmber) { onDismiss() } } @@ -1441,14 +1440,14 @@ private fun ActionableReactionButton( val thisModifier = remember(reactionType) { Modifier.combinedClickable( onClick = { - val isAmberInstalled = PackageUtils.isAmberInstalled(context) + val loggedInWithAmber = accountViewModel.loggedInWithAmber() scope.launch(Dispatchers.IO) { event = accountViewModel.reactToOrDelete( baseNote, reactionType, - !isAmberInstalled + !loggedInWithAmber ) - if (!isAmberInstalled) { + if (!loggedInWithAmber) { onDismiss() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index 36f662f29..f57985aa5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -68,7 +68,6 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.ServersAvailable import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.service.NostrChatroomDataSource -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel @@ -338,7 +337,7 @@ fun ChatroomScreen( wantsToMarkAsSensitive = false ) } else { - if (!accountViewModel.isWriteable() && PackageUtils.isAmberInstalled(context)) { + if (!accountViewModel.isWriteable() && accountViewModel.loggedInWithAmber()) { message = newPostModel.message.text } else { accountViewModel.account.sendPrivateMessage( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt index 9d1dd7b3d..15d5b6267 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt @@ -9,15 +9,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material.* -import androidx.compose.material.DrawerValue -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.MaterialTheme -import androidx.compose.material.ModalBottomSheetLayout -import androidx.compose.material.ModalBottomSheetValue -import androidx.compose.material.Scaffold -import androidx.compose.material.rememberDrawerState -import androidx.compose.material.rememberModalBottomSheetState -import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -33,18 +24,11 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavBackStackEntry import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.ui.buttons.ChannelFabColumn import com.vitorpamplona.amethyst.ui.buttons.NewCommunityNoteButton import com.vitorpamplona.amethyst.ui.buttons.NewImageButton import com.vitorpamplona.amethyst.ui.buttons.NewNoteButton import com.vitorpamplona.amethyst.ui.navigation.* -import com.vitorpamplona.amethyst.ui.navigation.AccountSwitchBottomSheet -import com.vitorpamplona.amethyst.ui.navigation.AppBottomBar -import com.vitorpamplona.amethyst.ui.navigation.AppNavigation -import com.vitorpamplona.amethyst.ui.navigation.AppTopBar -import com.vitorpamplona.amethyst.ui.navigation.DrawerContent -import com.vitorpamplona.amethyst.ui.navigation.Route import com.vitorpamplona.amethyst.ui.note.UserReactionsViewModel import com.vitorpamplona.amethyst.ui.screen.AccountState import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel @@ -258,7 +242,7 @@ fun FloatingButtons( Crossfade(targetState = accountState, animationSpec = tween(durationMillis = 100)) { state -> when (state) { is AccountState.LoggedInViewOnly -> { - if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.loggedInWithAmber()) { WritePermissionButtons(navEntryState, accountViewModel, nav, navScrollToTop) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index 604d4c1b7..46837fe79 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -58,7 +58,6 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource -import com.vitorpamplona.amethyst.service.PackageUtils import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView import com.vitorpamplona.amethyst.ui.actions.SignerDialog @@ -768,7 +767,7 @@ private fun DisplayFollowUnfollowButton( if (isLoggedInFollowingUser) { UnfollowButton { if (!accountViewModel.isWriteable()) { - if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.loggedInWithAmber()) { event = accountViewModel.account.unfollow(baseUser, false) } else { scope.launch { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt index d0a3c5bee..ba8cd6835 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/RelayAuthEvent.kt @@ -27,9 +27,10 @@ class RelayAuthEvent( listOf("relay", relay), listOf("challenge", challenge) ) - val id = generateId(pubKey, createdAt, kind, tags, content) + val localPubKey = if (pubKey.isBlank() && privateKey != null) CryptoUtils.pubkeyCreate(privateKey).toHexKey() else pubKey + val id = generateId(localPubKey, createdAt, kind, tags, content) val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) - return RelayAuthEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") + return RelayAuthEvent(id.toHexKey(), localPubKey, createdAt, tags, content, sig?.toHexKey() ?: "") } } }