sign event in background
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -35,11 +35,29 @@ object AmberUtils {
|
||||
}
|
||||
|
||||
fun openAmber(event: EventInterface) {
|
||||
checkNotInMainThread()
|
||||
ServiceManager.shouldPauseService = false
|
||||
content = ""
|
||||
isActivityRunning = true
|
||||
openAmber(
|
||||
event.toJson(),
|
||||
SignerType.SIGN_EVENT,
|
||||
IntentUtils.decryptActivityResultLauncher,
|
||||
IntentUtils.activityResultLauncher,
|
||||
""
|
||||
)
|
||||
while (isActivityRunning) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
fun loginWithAmber() {
|
||||
checkNotInMainThread()
|
||||
content = ""
|
||||
isActivityRunning = true
|
||||
openAmber(
|
||||
"",
|
||||
SignerType.GET_PUBLIC_KEY,
|
||||
IntentUtils.activityResultLauncher,
|
||||
""
|
||||
)
|
||||
while (isActivityRunning) {
|
||||
@@ -53,7 +71,7 @@ object AmberUtils {
|
||||
openAmber(
|
||||
encryptedContent,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
IntentUtils.decryptActivityResultLauncher,
|
||||
IntentUtils.activityResultLauncher,
|
||||
pubKey
|
||||
)
|
||||
while (isActivityRunning) {
|
||||
@@ -68,7 +86,7 @@ object AmberUtils {
|
||||
openAmber(
|
||||
decryptedContent,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
IntentUtils.decryptActivityResultLauncher,
|
||||
IntentUtils.activityResultLauncher,
|
||||
pubKey
|
||||
)
|
||||
while (isActivityRunning) {
|
||||
|
||||
@@ -6,14 +6,8 @@ import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.ServiceManager
|
||||
import com.vitorpamplona.amethyst.service.notifications.PushNotificationUtils
|
||||
import com.vitorpamplona.amethyst.service.notifications.RegisterAccounts
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.MainActivity
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.RelayAuthEvent
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
@@ -21,64 +15,11 @@ import kotlinx.coroutines.launch
|
||||
|
||||
object IntentUtils {
|
||||
lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
|
||||
lateinit var authActivityResultLauncher: ActivityResultLauncher<Intent>
|
||||
lateinit var decryptActivityResultLauncher: ActivityResultLauncher<Intent>
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun start(activity: MainActivity) {
|
||||
activityResultLauncher = activity.registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
Toast.makeText(
|
||||
Amethyst.instance,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val event = it.data?.getStringExtra("event") ?: ""
|
||||
|
||||
val signedEvent = Event.fromJson(event)
|
||||
val authEvent = RelayAuthEvent(signedEvent.id, signedEvent.pubKey, signedEvent.createdAt, signedEvent.tags, signedEvent.content, signedEvent.sig)
|
||||
|
||||
RegisterAccounts(LocalPreferences.allSavedAccounts()).postRegistrationEvent(
|
||||
listOf(authEvent)
|
||||
)
|
||||
PushNotificationUtils.hasInit = true
|
||||
ServiceManager.shouldPauseService = true
|
||||
}
|
||||
|
||||
authActivityResultLauncher = activity.registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
Toast.makeText(
|
||||
Amethyst.instance,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val event = it.data?.getStringExtra("event") ?: ""
|
||||
|
||||
val signedEvent = Event.fromJson(event)
|
||||
val authEvent = RelayAuthEvent(signedEvent.id, signedEvent.pubKey, signedEvent.createdAt, signedEvent.tags, signedEvent.content, signedEvent.sig)
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
Client.send(authEvent, authEvent.relay())
|
||||
}
|
||||
ServiceManager.shouldPauseService = true
|
||||
}
|
||||
|
||||
decryptActivityResultLauncher = activity.registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
@@ -95,6 +36,7 @@ object IntentUtils {
|
||||
val event = it.data?.getStringExtra("signature") ?: ""
|
||||
AmberUtils.content = event
|
||||
AmberUtils.isActivityRunning = false
|
||||
ServiceManager.shouldPauseService = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.vitorpamplona.amethyst.service.relays.EOSEAccount
|
||||
import com.vitorpamplona.amethyst.service.relays.JsonFilter
|
||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
||||
import com.vitorpamplona.amethyst.service.relays.TypedFilter
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerType
|
||||
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.events.BadgeAwardEvent
|
||||
import com.vitorpamplona.quartz.events.BadgeProfilesEvent
|
||||
@@ -190,25 +189,13 @@ object NostrAccountDataSource : NostrDataSource("AccountData") {
|
||||
super.auth(relay, challenge)
|
||||
|
||||
if (this::account.isInitialized) {
|
||||
val loggedInWithAmber = account.loginWithAmber
|
||||
val event = account.createAuthEvent(relay, challenge, loggedInWithAmber)
|
||||
val event = account.createAuthEvent(relay, challenge)
|
||||
|
||||
if (loggedInWithAmber && !account.isWriteable()) {
|
||||
if (event != null) {
|
||||
AmberUtils.openAmber(
|
||||
event.toJson(),
|
||||
SignerType.SIGN_EVENT,
|
||||
IntentUtils.authActivityResultLauncher,
|
||||
""
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (event != null) {
|
||||
Client.send(
|
||||
event,
|
||||
relay.url
|
||||
)
|
||||
}
|
||||
if (event != null) {
|
||||
Client.send(
|
||||
event,
|
||||
relay.url
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-27
@@ -4,10 +4,7 @@ import android.util.Log
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.BuildConfig
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.service.AmberUtils
|
||||
import com.vitorpamplona.amethyst.service.HttpClient
|
||||
import com.vitorpamplona.amethyst.service.IntentUtils
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerType
|
||||
import com.vitorpamplona.quartz.events.RelayAuthEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -22,16 +19,14 @@ class RegisterAccounts(
|
||||
// creates proof that it controls all accounts
|
||||
private fun signEventsToProveControlOfAccounts(
|
||||
accounts: List<AccountInfo>,
|
||||
notificationToken: String,
|
||||
loggedInWithAmber: Boolean
|
||||
notificationToken: String
|
||||
): List<RelayAuthEvent> {
|
||||
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, loggedInWithAmber)
|
||||
event
|
||||
acc.createAuthEvent(relayToUse, notificationToken)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -68,25 +63,8 @@ class RegisterAccounts(
|
||||
}
|
||||
|
||||
suspend fun go(notificationToken: String) = withContext(Dispatchers.IO) {
|
||||
val accountsWithoutPrivKey = accounts.filter { !it.hasPrivKey }
|
||||
val accountsWithPrivKey = accounts.filter { it.hasPrivKey }
|
||||
accountsWithoutPrivKey.forEach { account ->
|
||||
Log.d("fcm register", account.npub)
|
||||
val events = signEventsToProveControlOfAccounts(listOf(account), notificationToken, account.loggedInWithAmber)
|
||||
if (events.isNotEmpty()) {
|
||||
AmberUtils.openAmber(
|
||||
events.first().toJson(),
|
||||
SignerType.SIGN_EVENT,
|
||||
IntentUtils.activityResultLauncher,
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (accountsWithPrivKey.isNotEmpty()) {
|
||||
postRegistrationEvent(
|
||||
signEventsToProveControlOfAccounts(accountsWithPrivKey, notificationToken, false)
|
||||
)
|
||||
}
|
||||
postRegistrationEvent(
|
||||
signEventsToProveControlOfAccounts(accounts, notificationToken)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,14 +75,12 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ServersAvailable
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
|
||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||
import com.vitorpamplona.amethyst.service.noProtocolUrlValidator
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.components.*
|
||||
import com.vitorpamplona.amethyst.ui.note.CancelIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.CloseIcon
|
||||
@@ -105,7 +103,6 @@ import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
@@ -162,25 +159,6 @@ fun NewPostView(
|
||||
}
|
||||
}
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent, relayList = relayList)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Dialog(
|
||||
onDismissRequest = { onClose() },
|
||||
properties = DialogProperties(
|
||||
@@ -234,10 +212,8 @@ fun NewPostView(
|
||||
PostButton(
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = postViewModel.sendPost(relayList = relayList, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onClose()
|
||||
}
|
||||
postViewModel.sendPost(relayList = relayList)
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
isActive = postViewModel.canPost()
|
||||
|
||||
@@ -14,7 +14,11 @@ import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.vitorpamplona.amethyst.model.*
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ServersAvailable
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.FileHeader
|
||||
import com.vitorpamplona.amethyst.service.LocationUtil
|
||||
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
|
||||
@@ -27,7 +31,6 @@ import com.vitorpamplona.quartz.events.AddressableEvent
|
||||
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
||||
import com.vitorpamplona.quartz.events.ChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -158,7 +161,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
this.account = account
|
||||
}
|
||||
|
||||
fun sendPost(relayList: List<Relay>? = null, signEvent: Boolean): Event? {
|
||||
fun sendPost(relayList: List<Relay>? = null) {
|
||||
try {
|
||||
val tagger = NewMessageTagger(message.text, mentions, replyTos, originalNote?.channelHex())
|
||||
tagger.run()
|
||||
@@ -188,13 +191,12 @@ open class NewPostViewModel() : ViewModel() {
|
||||
|
||||
if (originalNote?.channelHex() != null) {
|
||||
if (originalNote is AddressableEvent && originalNote?.address() != null) {
|
||||
return account?.sendLiveMessage(tagger.message, originalNote?.address()!!, tagger.replyTos, tagger.mentions, zapReceiver, wantsToMarkAsSensitive, localZapRaiserAmount, geoHash, signEvent)
|
||||
account?.sendLiveMessage(tagger.message, originalNote?.address()!!, tagger.replyTos, tagger.mentions, zapReceiver, wantsToMarkAsSensitive, localZapRaiserAmount, geoHash)
|
||||
} else {
|
||||
return account?.sendChannelMessage(tagger.message, tagger.channelHex!!, tagger.replyTos, tagger.mentions, zapReceiver, wantsToMarkAsSensitive, localZapRaiserAmount, geoHash, signEvent)
|
||||
account?.sendChannelMessage(tagger.message, tagger.channelHex!!, tagger.replyTos, tagger.mentions, zapReceiver, wantsToMarkAsSensitive, localZapRaiserAmount, geoHash)
|
||||
}
|
||||
} else if (originalNote?.event is PrivateDmEvent) {
|
||||
account?.sendPrivateMessage(tagger.message, originalNote!!.author!!, originalNote!!, tagger.mentions, zapReceiver, wantsToMarkAsSensitive, localZapRaiserAmount, geoHash)
|
||||
return null
|
||||
} else if (originalNote?.event is ChatMessageEvent) {
|
||||
val receivers = (originalNote?.event as ChatMessageEvent).recipientsPubKey().plus(originalNote?.author?.pubkeyHex).filterNotNull().toSet().toList()
|
||||
|
||||
@@ -207,10 +209,8 @@ open class NewPostViewModel() : ViewModel() {
|
||||
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
||||
zapReceiver = zapReceiver,
|
||||
zapRaiserAmount = localZapRaiserAmount,
|
||||
geohash = geoHash,
|
||||
signEvent = signEvent
|
||||
geohash = geoHash
|
||||
)
|
||||
return null
|
||||
} else if (!dmUsers.isNullOrEmpty()) {
|
||||
if (nip24 || dmUsers.size > 1) {
|
||||
account?.sendNIP24PrivateMessage(
|
||||
@@ -222,10 +222,8 @@ open class NewPostViewModel() : ViewModel() {
|
||||
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
||||
zapReceiver = zapReceiver,
|
||||
zapRaiserAmount = localZapRaiserAmount,
|
||||
geohash = geoHash,
|
||||
signEvent = signEvent
|
||||
geohash = geoHash
|
||||
)
|
||||
return null
|
||||
} else {
|
||||
account?.sendPrivateMessage(
|
||||
message = tagger.message,
|
||||
@@ -235,14 +233,12 @@ open class NewPostViewModel() : ViewModel() {
|
||||
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
||||
zapReceiver = zapReceiver,
|
||||
zapRaiserAmount = localZapRaiserAmount,
|
||||
geohash = geoHash,
|
||||
signEvent = signEvent
|
||||
geohash = geoHash
|
||||
)
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
if (wantsPoll) {
|
||||
return account?.sendPoll(
|
||||
account?.sendPoll(
|
||||
tagger.message,
|
||||
tagger.replyTos,
|
||||
tagger.mentions,
|
||||
@@ -255,8 +251,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
wantsToMarkAsSensitive,
|
||||
localZapRaiserAmount,
|
||||
relayList,
|
||||
geoHash,
|
||||
signEvent
|
||||
geoHash
|
||||
)
|
||||
} else {
|
||||
// adds markers
|
||||
@@ -266,7 +261,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
?: originalNote?.replyTo?.firstOrNull()?.idHex // old rules, first item is root.
|
||||
val replyId = originalNote?.idHex
|
||||
|
||||
return account?.sendPost(
|
||||
account?.sendPost(
|
||||
message = tagger.message,
|
||||
replyTo = tagger.replyTos,
|
||||
mentions = tagger.mentions,
|
||||
@@ -278,8 +273,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
root = rootId,
|
||||
directMentions = tagger.directMentions,
|
||||
relayList = relayList,
|
||||
geohash = geoHash,
|
||||
signEvent = signEvent
|
||||
geohash = geoHash
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,8 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.RelayInformation
|
||||
import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.service.relays.Constants.defaultRelays
|
||||
import com.vitorpamplona.amethyst.service.relays.FeedType
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -69,9 +67,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.Math.round
|
||||
|
||||
@@ -91,26 +87,6 @@ fun NewRelayListView(onClose: () -> Unit, accountViewModel: AccountViewModel, re
|
||||
}
|
||||
}
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
postViewModel.clear()
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Dialog(
|
||||
onDismissRequest = onClose,
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false)
|
||||
@@ -144,12 +120,8 @@ fun NewRelayListView(onClose: () -> Unit, accountViewModel: AccountViewModel, re
|
||||
|
||||
PostButton(
|
||||
onPost = {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = postViewModel.create(false)
|
||||
} else {
|
||||
postViewModel.create(true)
|
||||
onClose()
|
||||
}
|
||||
postViewModel.create()
|
||||
onClose()
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
@@ -26,20 +26,14 @@ class NewRelayListViewModel : ViewModel() {
|
||||
clear()
|
||||
}
|
||||
|
||||
fun create(signEvent: Boolean): ContactListEvent? {
|
||||
if (!signEvent) {
|
||||
relays.let {
|
||||
return account.saveRelayList(it.value, false)
|
||||
}
|
||||
}
|
||||
fun create() {
|
||||
relays.let {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
account.saveRelayList(it.value, true)
|
||||
account.saveRelayList(it.value)
|
||||
}
|
||||
}
|
||||
|
||||
clear()
|
||||
return null
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
|
||||
@@ -17,11 +17,7 @@ import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -33,10 +29,7 @@ import androidx.compose.ui.window.DialogProperties
|
||||
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.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -70,26 +63,6 @@ fun NewUserMetadataView(onClose: () -> Unit, account: Account) {
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp)
|
||||
) {
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
postViewModel.clear()
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
@@ -103,12 +76,8 @@ fun NewUserMetadataView(onClose: () -> Unit, account: Account) {
|
||||
|
||||
PostButton(
|
||||
onPost = {
|
||||
if (account.loginWithAmber) {
|
||||
event = postViewModel.create(false)
|
||||
} else {
|
||||
postViewModel.create(true)
|
||||
onClose()
|
||||
}
|
||||
postViewModel.create()
|
||||
onClose()
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
+4
-11
@@ -13,7 +13,6 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.ui.components.MediaCompressor
|
||||
import com.vitorpamplona.quartz.events.GitHubIdentity
|
||||
import com.vitorpamplona.quartz.events.MastodonIdentity
|
||||
import com.vitorpamplona.quartz.events.MetadataEvent
|
||||
import com.vitorpamplona.quartz.events.TwitterIdentity
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@@ -73,7 +72,7 @@ class NewUserMetadataViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun create(signEvent: Boolean): MetadataEvent? {
|
||||
fun create() {
|
||||
// Tries to not delete any existing attribute that we do not work with.
|
||||
val latest = account.userProfile().info?.latestMetadata
|
||||
val currentJson = if (latest != null) {
|
||||
@@ -122,16 +121,10 @@ class NewUserMetadataViewModel : ViewModel() {
|
||||
val writer = StringWriter()
|
||||
ObjectMapper().writeValue(writer, currentJson)
|
||||
|
||||
if (signEvent) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
account.sendNewUserMetadata(writer.buffer.toString(), newClaims, true)
|
||||
}
|
||||
clear()
|
||||
} else {
|
||||
return account.sendNewUserMetadata(writer.buffer.toString(), newClaims, false)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
account.sendNewUserMetadata(writer.buffer.toString(), newClaims)
|
||||
}
|
||||
|
||||
return null
|
||||
clear()
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
|
||||
@@ -30,7 +30,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
@@ -41,8 +40,6 @@ import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class SignerType {
|
||||
@@ -189,15 +186,3 @@ fun SignerDialog(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun Test() {
|
||||
SignerDialog(
|
||||
onClose = { },
|
||||
onPost = { },
|
||||
data = TextNoteEvent("", "", TimeUtils.now(), emptyList(), "test", "").toJson(),
|
||||
type = SignerType.SIGN_EVENT,
|
||||
pubKey = ""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -33,16 +32,11 @@ import androidx.lifecycle.ViewModel
|
||||
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.model.Note
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.CloseButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.PostButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -57,11 +51,11 @@ class AddBountyAmountViewModel : ViewModel() {
|
||||
this.bounty = bounty
|
||||
}
|
||||
|
||||
fun sendPost(signEvent: Boolean): TextNoteEvent? {
|
||||
fun sendPost() {
|
||||
val newValue = nextAmount.text.trim().toLongOrNull()
|
||||
|
||||
if (newValue != null) {
|
||||
val event = account?.sendPost(
|
||||
account?.sendPost(
|
||||
message = newValue.toString(),
|
||||
replyTo = listOfNotNull(bounty),
|
||||
mentions = listOfNotNull(bounty?.author),
|
||||
@@ -69,14 +63,11 @@ class AddBountyAmountViewModel : ViewModel() {
|
||||
wantsToMarkAsSensitive = false,
|
||||
replyingTo = null,
|
||||
root = null,
|
||||
directMentions = setOf(),
|
||||
signEvent = signEvent
|
||||
directMentions = setOf()
|
||||
)
|
||||
|
||||
nextAmount = TextFieldValue("")
|
||||
return event
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun cancel() {
|
||||
@@ -94,25 +85,6 @@ fun AddBountyAmountDialog(bounty: Note, accountViewModel: AccountViewModel, onCl
|
||||
postViewModel.load(accountViewModel.account, bounty)
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Dialog(
|
||||
onDismissRequest = { onClose() },
|
||||
properties = DialogProperties(
|
||||
@@ -138,8 +110,8 @@ fun AddBountyAmountDialog(bounty: Note, accountViewModel: AccountViewModel, onCl
|
||||
|
||||
PostButton(
|
||||
onPost = {
|
||||
event = postViewModel.sendPost(!accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
postViewModel.sendPost()
|
||||
onClose()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -37,11 +37,9 @@ import androidx.compose.material.icons.filled.Report
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
@@ -62,17 +60,13 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.components.SelectTextDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ReportNoteDialog
|
||||
import com.vitorpamplona.amethyst.ui.theme.WarningColor
|
||||
import com.vitorpamplona.amethyst.ui.theme.secondaryButtonBackground
|
||||
import com.vitorpamplona.quartz.events.AudioTrackEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -206,25 +200,6 @@ private fun RenderMainPopup(
|
||||
val isOwnNote = accountViewModel.isLoggedUser(note.author)
|
||||
val isFollowingUser = !isOwnNote && accountViewModel.isFollowing(note.author)
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Popup(onDismissRequest = onDismiss, alignment = Alignment.Center) {
|
||||
Card(
|
||||
modifier = Modifier.shadow(elevation = 6.dp, shape = cardShape),
|
||||
@@ -300,10 +275,8 @@ private fun RenderMainPopup(
|
||||
) {
|
||||
if (accountViewModel.hideDeleteRequestDialog) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.delete(note)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
showDeleteAlertDialog.value = true
|
||||
@@ -315,10 +288,8 @@ private fun RenderMainPopup(
|
||||
stringResource(R.string.quick_action_unfollow)
|
||||
) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.unfollow(note.author!!, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.unfollow(note.author!!)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -327,10 +298,8 @@ private fun RenderMainPopup(
|
||||
stringResource(R.string.quick_action_follow)
|
||||
) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.follow(note.author!!, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.follow(note.author!!)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,25 +382,6 @@ fun NoteQuickActionItem(icon: ImageVector, label: String, onClick: () -> Unit) {
|
||||
fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
QuickActionAlertDialog(
|
||||
title = stringResource(R.string.quick_action_request_deletion_alert_title),
|
||||
textContent = stringResource(R.string.quick_action_request_deletion_alert_body),
|
||||
@@ -439,20 +389,16 @@ fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss:
|
||||
buttonText = stringResource(R.string.quick_action_delete_dialog_btn),
|
||||
onClickDoOnce = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
|
||||
}
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
accountViewModel.delete(note)
|
||||
}
|
||||
onDismiss()
|
||||
},
|
||||
onClickDontShowAgain = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
|
||||
accountViewModel.delete(note)
|
||||
accountViewModel.dontShowDeleteRequestDialog()
|
||||
}
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
}
|
||||
onDismiss()
|
||||
},
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
|
||||
@@ -77,11 +77,8 @@ import coil.compose.AsyncImage
|
||||
import coil.request.CachePolicy
|
||||
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.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.components.ImageUrlType
|
||||
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
|
||||
import com.vitorpamplona.amethyst.ui.components.TextType
|
||||
@@ -110,7 +107,6 @@ import com.vitorpamplona.amethyst.ui.theme.TinyBorders
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderTextColorFilter
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -647,26 +643,6 @@ fun BoostReaction(
|
||||
val iconButtonModifier = remember {
|
||||
Modifier.size(iconSize)
|
||||
}
|
||||
var event by remember {
|
||||
mutableStateOf<Event?>(null)
|
||||
}
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(
|
||||
modifier = iconButtonModifier,
|
||||
@@ -674,7 +650,7 @@ fun BoostReaction(
|
||||
if (accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.hasBoosted(baseNote)) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.deleteBoostsTo(baseNote, true)
|
||||
accountViewModel.deleteBoostsTo(baseNote)
|
||||
}
|
||||
} else {
|
||||
wantsToBoost = true
|
||||
@@ -683,7 +659,7 @@ fun BoostReaction(
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
if (accountViewModel.hasBoosted(baseNote)) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.deleteBoostsTo(baseNote, false)
|
||||
accountViewModel.deleteBoostsTo(baseNote)
|
||||
}
|
||||
} else {
|
||||
wantsToBoost = true
|
||||
@@ -716,7 +692,7 @@ fun BoostReaction(
|
||||
},
|
||||
onRepost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.boost(baseNote, false)
|
||||
accountViewModel.boost(baseNote)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -766,24 +742,6 @@ fun LikeReaction(
|
||||
|
||||
var wantsToChangeReactionSymbol by remember { mutableStateOf(false) }
|
||||
var wantsToReact by remember { mutableStateOf(false) }
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
contentAlignment = Center,
|
||||
@@ -804,9 +762,9 @@ fun LikeReaction(
|
||||
if (accountViewModel.account.reactionChoices.size == 1) {
|
||||
val reaction = accountViewModel.account.reactionChoices.first()
|
||||
if (accountViewModel.hasReactedTo(baseNote, reaction)) {
|
||||
event = accountViewModel.deleteReactionTo(baseNote, reaction, false)
|
||||
accountViewModel.deleteReactionTo(baseNote, reaction)
|
||||
} else {
|
||||
event = accountViewModel.reactTo(baseNote, reaction, false)
|
||||
accountViewModel.reactTo(baseNote, reaction)
|
||||
}
|
||||
} else if (accountViewModel.account.reactionChoices.size > 1) {
|
||||
wantsToReact = true
|
||||
@@ -961,9 +919,9 @@ private fun likeClick(
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val reaction = accountViewModel.account.reactionChoices.first()
|
||||
if (accountViewModel.hasReactedTo(baseNote, reaction)) {
|
||||
accountViewModel.deleteReactionTo(baseNote, reaction, true)
|
||||
accountViewModel.deleteReactionTo(baseNote, reaction)
|
||||
} else {
|
||||
accountViewModel.reactTo(baseNote, reaction, true)
|
||||
accountViewModel.reactTo(baseNote, reaction)
|
||||
}
|
||||
}
|
||||
} else if (accountViewModel.account.reactionChoices.size > 1) {
|
||||
@@ -1294,7 +1252,7 @@ private fun BoostTypeChoicePopup(baseNote: Note, iconSize: Dp, accountViewModel:
|
||||
onClick = {
|
||||
if (accountViewModel.isWriteable()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.boost(baseNote, true)
|
||||
accountViewModel.boost(baseNote)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
@@ -1377,40 +1335,16 @@ private fun ActionableReactionButton(
|
||||
toRemove: Set<String>
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
onDismiss()
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = {
|
||||
val loggedInWithAmber = accountViewModel.loggedInWithAmber()
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.reactToOrDelete(
|
||||
accountViewModel.reactToOrDelete(
|
||||
baseNote,
|
||||
reactionType,
|
||||
!loggedInWithAmber
|
||||
reactionType
|
||||
)
|
||||
if (!loggedInWithAmber) {
|
||||
onDismiss()
|
||||
}
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
shape = ButtonBorder,
|
||||
@@ -1422,16 +1356,12 @@ private fun ActionableReactionButton(
|
||||
val thisModifier = remember(reactionType) {
|
||||
Modifier.combinedClickable(
|
||||
onClick = {
|
||||
val loggedInWithAmber = accountViewModel.loggedInWithAmber()
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.reactToOrDelete(
|
||||
accountViewModel.reactToOrDelete(
|
||||
baseNote,
|
||||
reactionType,
|
||||
!loggedInWithAmber
|
||||
reactionType
|
||||
)
|
||||
if (!loggedInWithAmber) {
|
||||
onDismiss()
|
||||
}
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
|
||||
@@ -41,19 +41,15 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.AmberUtils
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ReportNoteDialog
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -388,31 +384,12 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
if (!state.isFollowingAuthor) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
val author = note.author ?: return@DropdownMenuItem
|
||||
event = accountViewModel.follow(author, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.follow(author)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
@@ -479,7 +456,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
)
|
||||
bookmarks?.decryptedContent = AmberUtils.content
|
||||
AmberUtils.content = ""
|
||||
event = accountViewModel.removePrivateBookmark(note, bookmarks?.decryptedContent ?: "")
|
||||
accountViewModel.removePrivateBookmark(note, bookmarks?.decryptedContent ?: "")
|
||||
} else {
|
||||
accountViewModel.removePrivateBookmark(note)
|
||||
onDismiss()
|
||||
@@ -501,7 +478,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
)
|
||||
bookmarks?.decryptedContent = AmberUtils.content
|
||||
AmberUtils.content = ""
|
||||
event = accountViewModel.addPrivateBookmark(note, bookmarks?.decryptedContent ?: "")
|
||||
accountViewModel.addPrivateBookmark(note, bookmarks?.decryptedContent ?: "")
|
||||
} else {
|
||||
accountViewModel.addPrivateBookmark(note)
|
||||
onDismiss()
|
||||
@@ -524,7 +501,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
)
|
||||
bookmarks?.decryptedContent = AmberUtils.content
|
||||
AmberUtils.content = ""
|
||||
event = accountViewModel.removePublicBookmark(
|
||||
accountViewModel.removePublicBookmark(
|
||||
note,
|
||||
bookmarks?.decryptedContent ?: ""
|
||||
)
|
||||
@@ -549,7 +526,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
)
|
||||
bookmarks?.decryptedContent = AmberUtils.content
|
||||
AmberUtils.content = ""
|
||||
event = accountViewModel.addPublicBookmark(
|
||||
accountViewModel.addPublicBookmark(
|
||||
note,
|
||||
bookmarks?.decryptedContent ?: ""
|
||||
)
|
||||
@@ -572,10 +549,8 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
|
||||
if (!accountViewModel.loggedInWithAmber()) {
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.delete(note)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import android.app.Activity
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -29,14 +26,9 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ServiceManager
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.AmberUtils
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerType
|
||||
import com.vitorpamplona.amethyst.ui.screen.ZapReqResponse
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.FollowButton
|
||||
@@ -47,9 +39,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||
import com.vitorpamplona.quartz.events.LnZapRequestEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -185,113 +174,11 @@ fun UserActionOptions(
|
||||
accountViewModel: AccountViewModel
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
accountViewModel.account.live.invalidateData()
|
||||
accountViewModel.account.saveable.invalidateData()
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
val encryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val encryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
event = accountViewModel.show(baseAuthor, encryptedContent)
|
||||
}
|
||||
)
|
||||
|
||||
val decryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val decryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val privateTags = if (blockList == null) {
|
||||
listOf(listOf("p", baseAuthor.pubkeyHex))
|
||||
} else {
|
||||
if (accountViewModel.account.isHidden(baseAuthor)) {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(baseAuthor.pubkeyHex) }
|
||||
} else {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", baseAuthor.pubkeyHex))
|
||||
}
|
||||
}
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
ServiceManager.shouldPauseService = true
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
WatchIsHiddenUser(baseAuthor, accountViewModel) { isHidden ->
|
||||
if (isHidden) {
|
||||
ShowUserButton {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val content = blockList?.content ?: ""
|
||||
if (content.isBlank()) {
|
||||
val privateTags = listOf(listOf("p", baseAuthor.pubkeyHex))
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
} else {
|
||||
AmberUtils.openAmber(
|
||||
content,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
decryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accountViewModel.show(baseAuthor)
|
||||
}
|
||||
accountViewModel.show(baseAuthor)
|
||||
}
|
||||
} else {
|
||||
ShowFollowingOrUnfollowingButton(baseAuthor, accountViewModel)
|
||||
@@ -321,30 +208,13 @@ fun ShowFollowingOrUnfollowingButton(
|
||||
}
|
||||
}
|
||||
|
||||
var event by remember { mutableStateOf<ContactListEvent?>(null) }
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
if (isFollowing) {
|
||||
UnfollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.unfollow(baseAuthor, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.unfollow(baseAuthor)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -358,7 +228,7 @@ fun ShowFollowingOrUnfollowingButton(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.unfollow(baseAuthor, true)
|
||||
accountViewModel.unfollow(baseAuthor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +236,9 @@ fun ShowFollowingOrUnfollowingButton(
|
||||
FollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.follow(baseAuthor, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.follow(baseAuthor)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -380,7 +252,7 @@ fun ShowFollowingOrUnfollowingButton(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.follow(baseAuthor, true)
|
||||
accountViewModel.follow(baseAuthor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-38
@@ -30,16 +30,11 @@ import com.vitorpamplona.amethyst.ui.note.ZapAmountCommentNotification
|
||||
import com.vitorpamplona.amethyst.ui.note.ZapraiserStatus
|
||||
import com.vitorpamplona.amethyst.ui.note.showAmount
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.events.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||
import com.vitorpamplona.quartz.events.DeletionEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||
import com.vitorpamplona.quartz.events.LnZapRequestEvent
|
||||
import com.vitorpamplona.quartz.events.PayInvoiceErrorResponse
|
||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.events.ReactionEvent
|
||||
import com.vitorpamplona.quartz.events.ReportEvent
|
||||
import com.vitorpamplona.quartz.events.SealedGossipEvent
|
||||
import com.vitorpamplona.quartz.events.UserMetadata
|
||||
@@ -112,16 +107,16 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
return account.userProfile()
|
||||
}
|
||||
|
||||
fun reactTo(note: Note, reaction: String, signEvent: Boolean): ReactionEvent? {
|
||||
return account.reactTo(note, reaction, signEvent)
|
||||
fun reactTo(note: Note, reaction: String) {
|
||||
account.reactTo(note, reaction)
|
||||
}
|
||||
|
||||
fun reactToOrDelete(note: Note, reaction: String, signEvent: Boolean): Event? {
|
||||
fun reactToOrDelete(note: Note, reaction: String) {
|
||||
val currentReactions = account.reactionTo(note, reaction)
|
||||
if (currentReactions.isNotEmpty()) {
|
||||
return account.delete(currentReactions, signEvent)
|
||||
account.delete(currentReactions)
|
||||
} else {
|
||||
return account.reactTo(note, reaction, signEvent)
|
||||
account.reactTo(note, reaction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,16 +129,16 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
return account.hasReacted(baseNote, reaction)
|
||||
}
|
||||
|
||||
fun deleteReactionTo(note: Note, reaction: String, signEvent: Boolean): DeletionEvent? {
|
||||
return account.delete(account.reactionTo(note, reaction), signEvent)
|
||||
fun deleteReactionTo(note: Note, reaction: String) {
|
||||
account.delete(account.reactionTo(note, reaction))
|
||||
}
|
||||
|
||||
fun hasBoosted(baseNote: Note): Boolean {
|
||||
return account.hasBoosted(baseNote)
|
||||
}
|
||||
|
||||
fun deleteBoostsTo(note: Note, signEvent: Boolean): DeletionEvent? {
|
||||
return account.delete(account.boostsTo(note), signEvent)
|
||||
fun deleteBoostsTo(note: Note) {
|
||||
account.delete(account.boostsTo(note))
|
||||
}
|
||||
|
||||
fun calculateIfNoteWasZappedByAccount(zappedNote: Note, onWasZapped: (Boolean) -> Unit) {
|
||||
@@ -302,8 +297,8 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun boost(note: Note, signEvent: Boolean): Event? {
|
||||
return account.boost(note, signEvent)
|
||||
fun boost(note: Note) {
|
||||
account.boost(note)
|
||||
}
|
||||
|
||||
fun removeEmojiPack(usersEmojiList: Note, emojiList: Note) {
|
||||
@@ -318,24 +313,24 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
account.addPrivateBookmark(note)
|
||||
}
|
||||
|
||||
fun addPrivateBookmark(note: Note, decryptedContent: String): BookmarkListEvent? {
|
||||
return account.addPrivateBookmark(note, decryptedContent)
|
||||
fun addPrivateBookmark(note: Note, decryptedContent: String) {
|
||||
account.addPrivateBookmark(note, decryptedContent)
|
||||
}
|
||||
|
||||
fun addPublicBookmark(note: Note, decryptedContent: String): BookmarkListEvent? {
|
||||
return account.addPublicBookmark(note, decryptedContent)
|
||||
fun addPublicBookmark(note: Note, decryptedContent: String) {
|
||||
account.addPublicBookmark(note, decryptedContent)
|
||||
}
|
||||
|
||||
fun removePublicBookmark(note: Note, decryptedContent: String): BookmarkListEvent? {
|
||||
return account.removePublicBookmark(note, decryptedContent)
|
||||
fun removePublicBookmark(note: Note, decryptedContent: String) {
|
||||
account.removePublicBookmark(note, decryptedContent)
|
||||
}
|
||||
|
||||
fun addPublicBookmark(note: Note) {
|
||||
account.addPublicBookmark(note)
|
||||
}
|
||||
|
||||
fun removePrivateBookmark(note: Note, decryptedContent: String): BookmarkListEvent? {
|
||||
return account.removePrivateBookmark(note, decryptedContent)
|
||||
fun removePrivateBookmark(note: Note, decryptedContent: String) {
|
||||
account.removePrivateBookmark(note, decryptedContent)
|
||||
}
|
||||
|
||||
fun removePrivateBookmark(note: Note) {
|
||||
@@ -358,8 +353,8 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
account.broadcast(note)
|
||||
}
|
||||
|
||||
fun delete(note: Note, signEvent: Boolean): DeletionEvent? {
|
||||
return account.delete(note, signEvent)
|
||||
fun delete(note: Note) {
|
||||
account.delete(note)
|
||||
}
|
||||
|
||||
fun decrypt(note: Note): String? {
|
||||
@@ -382,12 +377,12 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
account.prefer(source, target, preference)
|
||||
}
|
||||
|
||||
fun follow(user: User, signEvent: Boolean): ContactListEvent? {
|
||||
return account.follow(user, signEvent)
|
||||
fun follow(user: User) {
|
||||
account.follow(user)
|
||||
}
|
||||
|
||||
fun unfollow(user: User, signEvent: Boolean): ContactListEvent? {
|
||||
return account.unfollow(user, signEvent)
|
||||
fun unfollow(user: User) {
|
||||
account.unfollow(user)
|
||||
}
|
||||
|
||||
fun isLoggedUser(user: User?): Boolean {
|
||||
@@ -489,20 +484,12 @@ class AccountViewModel(val account: Account) : ViewModel() {
|
||||
return account.unseal(event)
|
||||
}
|
||||
|
||||
fun show(user: User, encryptedContent: String): PeopleListEvent? {
|
||||
return account.showUser(user.pubkeyHex, encryptedContent)
|
||||
}
|
||||
|
||||
fun show(user: User) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
account.showUser(user.pubkeyHex)
|
||||
}
|
||||
}
|
||||
|
||||
fun hide(user: User, encryptedContent: String): PeopleListEvent? {
|
||||
return account.hideUser(user.pubkeyHex, encryptedContent)
|
||||
}
|
||||
|
||||
fun hide(user: User) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
account.hideUser(user.pubkeyHex)
|
||||
|
||||
@@ -86,12 +86,10 @@ import com.vitorpamplona.amethyst.model.PublicChatChannel
|
||||
import com.vitorpamplona.amethyst.model.ServersAvailable
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewChannelView
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.actions.PostButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
|
||||
@@ -131,7 +129,6 @@ import com.vitorpamplona.amethyst.ui.theme.SmallBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent.Companion.STATUS_LIVE
|
||||
import com.vitorpamplona.quartz.events.Participant
|
||||
@@ -263,24 +260,6 @@ fun ChannelScreen(
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
// LAST ROW
|
||||
EditFieldRow(newPostModel, isPrivate = false, accountViewModel = accountViewModel) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
@@ -292,22 +271,20 @@ fun ChannelScreen(
|
||||
)
|
||||
tagger.run()
|
||||
if (channel is PublicChatChannel) {
|
||||
event = accountViewModel.account.sendChannelMessage(
|
||||
accountViewModel.account.sendChannelMessage(
|
||||
message = tagger.message,
|
||||
toChannel = channel.idHex,
|
||||
replyTo = tagger.replyTos,
|
||||
mentions = tagger.mentions,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = !accountViewModel.loggedInWithAmber()
|
||||
wantsToMarkAsSensitive = false
|
||||
)
|
||||
} else if (channel is LiveActivitiesChannel) {
|
||||
event = accountViewModel.account.sendLiveMessage(
|
||||
accountViewModel.account.sendLiveMessage(
|
||||
message = tagger.message,
|
||||
toChannel = channel.address,
|
||||
replyTo = tagger.replyTos,
|
||||
mentions = tagger.mentions,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = !accountViewModel.loggedInWithAmber()
|
||||
wantsToMarkAsSensitive = false
|
||||
)
|
||||
}
|
||||
newPostModel.message = TextFieldValue("")
|
||||
@@ -1127,30 +1104,12 @@ private fun EditButton(accountViewModel: AccountViewModel, channel: PublicChatCh
|
||||
@Composable
|
||||
fun JoinChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (String) -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.account.follow(channel, !accountViewModel.loggedInWithAmber())
|
||||
accountViewModel.account.follow(channel)
|
||||
}
|
||||
},
|
||||
shape = ButtonBorder,
|
||||
@@ -1167,30 +1126,12 @@ fun JoinChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (S
|
||||
@Composable
|
||||
fun LeaveChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (String) -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.account.unfollow(channel, !accountViewModel.loggedInWithAmber())
|
||||
accountViewModel.account.unfollow(channel)
|
||||
}
|
||||
},
|
||||
shape = ButtonBorder,
|
||||
@@ -1207,30 +1148,12 @@ fun LeaveChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (
|
||||
@Composable
|
||||
fun JoinCommunityButton(accountViewModel: AccountViewModel, note: AddressableNote, nav: (String) -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.account.follow(note, !accountViewModel.loggedInWithAmber())
|
||||
accountViewModel.account.follow(note)
|
||||
}
|
||||
},
|
||||
shape = ButtonBorder,
|
||||
@@ -1247,30 +1170,12 @@ fun JoinCommunityButton(accountViewModel: AccountViewModel, note: AddressableNot
|
||||
@Composable
|
||||
fun LeaveCommunityButton(accountViewModel: AccountViewModel, note: AddressableNote, nav: (String) -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.account.unfollow(note, !accountViewModel.loggedInWithAmber())
|
||||
accountViewModel.account.unfollow(note)
|
||||
}
|
||||
},
|
||||
shape = ButtonBorder,
|
||||
|
||||
@@ -63,17 +63,13 @@ import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
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.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.CloseButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.actions.PostButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerType
|
||||
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||
@@ -96,7 +92,6 @@ import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.ChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.ChatroomKey
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -297,49 +292,6 @@ fun ChatroomScreen(
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
var message by remember { mutableStateOf<String?>(null) }
|
||||
if (message != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
message = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
event = accountViewModel.account.sendPrivateMessage(
|
||||
message = it,
|
||||
toUser = room.users.first(),
|
||||
replyingTo = replyTo.value,
|
||||
mentions = null,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = false
|
||||
)
|
||||
message = null
|
||||
}
|
||||
},
|
||||
data = message!!,
|
||||
pubKey = room.users.first(),
|
||||
type = SignerType.NIP04_ENCRYPT
|
||||
)
|
||||
}
|
||||
|
||||
// LAST ROW
|
||||
PrivateMessageEditFieldRow(newPostModel, isPrivate = true, accountViewModel) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
@@ -350,22 +302,16 @@ fun ChatroomScreen(
|
||||
toUsers = room.users.toList(),
|
||||
replyingTo = replyTo.value,
|
||||
mentions = null,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = true
|
||||
wantsToMarkAsSensitive = false
|
||||
)
|
||||
} else {
|
||||
if (!accountViewModel.isWriteable() && accountViewModel.loggedInWithAmber()) {
|
||||
message = newPostModel.message.text
|
||||
} else {
|
||||
accountViewModel.account.sendPrivateMessage(
|
||||
message = newPostModel.message.text,
|
||||
toUser = room.users.first(),
|
||||
replyingTo = replyTo.value,
|
||||
mentions = null,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = true
|
||||
)
|
||||
}
|
||||
accountViewModel.account.sendPrivateMessage(
|
||||
message = newPostModel.message.text,
|
||||
toUser = room.users.first(),
|
||||
replyingTo = replyTo.value,
|
||||
mentions = null,
|
||||
wantsToMarkAsSensitive = false
|
||||
)
|
||||
}
|
||||
|
||||
newPostModel.message = TextFieldValue("")
|
||||
@@ -700,8 +646,7 @@ fun NewSubjectView(onClose: () -> Unit, accountViewModel: AccountViewModel, room
|
||||
subject = groupName.value.ifBlank { null },
|
||||
replyingTo = null,
|
||||
mentions = null,
|
||||
wantsToMarkAsSensitive = false,
|
||||
signEvent = true
|
||||
wantsToMarkAsSensitive = false
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,15 +31,11 @@ import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.fonfon.kgeohash.toGeoHash
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.service.NostrGeohashDataSource
|
||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.NostrGeoHashFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.RefresheableFeedView
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -171,29 +167,14 @@ fun GeoHashActionOptions(
|
||||
userState?.user?.isFollowingGeohashCached(tag) ?: false
|
||||
}
|
||||
}
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
if (isFollowingTag) {
|
||||
UnfollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.unfollowGeohash(tag, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollowGeohash(tag)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -207,7 +188,7 @@ fun GeoHashActionOptions(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollowGeohash(tag, true)
|
||||
accountViewModel.account.unfollowGeohash(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +196,9 @@ fun GeoHashActionOptions(
|
||||
FollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.followGeohash(tag, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.followGeohash(tag)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -229,7 +212,7 @@ fun GeoHashActionOptions(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.followGeohash(tag, true)
|
||||
accountViewModel.account.followGeohash(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -30,14 +28,10 @@ import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.service.NostrHashtagDataSource
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.NostrHashtagFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.RefresheableFeedView
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -149,30 +143,14 @@ fun HashtagActionOptions(
|
||||
userState?.user?.isFollowingHashtagCached(tag) ?: false
|
||||
}
|
||||
}
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
if (isFollowingTag) {
|
||||
UnfollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.unfollowHashtag(tag, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollowHashtag(tag)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -186,7 +164,7 @@ fun HashtagActionOptions(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollowHashtag(tag, true)
|
||||
accountViewModel.account.unfollowHashtag(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,7 +172,9 @@ fun HashtagActionOptions(
|
||||
FollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.followHashtag(tag, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.followHashtag(tag)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -208,7 +188,7 @@ fun HashtagActionOptions(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.followHashtag(tag, true)
|
||||
accountViewModel.account.followHashtag(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.*
|
||||
@@ -56,17 +53,12 @@ import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ServiceManager
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.AmberUtils
|
||||
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerType
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.DisplayNip05ProfileStatus
|
||||
import com.vitorpamplona.amethyst.ui.components.InvoiceRequestCard
|
||||
@@ -101,13 +93,10 @@ import com.vitorpamplona.amethyst.ui.theme.Size16Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.encoders.ATag
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.events.AppDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.BadgeDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.BadgeProfilesEvent
|
||||
import com.vitorpamplona.quartz.events.ChatroomKey
|
||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.GitHubIdentity
|
||||
import com.vitorpamplona.quartz.events.IdentityClaim
|
||||
import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
||||
@@ -728,113 +717,11 @@ private fun ProfileActions(
|
||||
}
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
accountViewModel.account.live.invalidateData()
|
||||
accountViewModel.account.saveable.invalidateData()
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
val encryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val encryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
event = accountViewModel.show(baseUser, encryptedContent)
|
||||
}
|
||||
)
|
||||
|
||||
val decryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val decryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val privateTags = if (blockList == null) {
|
||||
listOf(listOf("p", baseUser.pubkeyHex))
|
||||
} else {
|
||||
if (accountViewModel.account.isHidden(baseUser)) {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(baseUser.pubkeyHex) }
|
||||
} else {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", baseUser.pubkeyHex))
|
||||
}
|
||||
}
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
ServiceManager.shouldPauseService = true
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
WatchIsHiddenUser(baseUser, accountViewModel) { isHidden ->
|
||||
if (isHidden) {
|
||||
ShowUserButton {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val content = blockList?.content ?: ""
|
||||
if (content.isBlank()) {
|
||||
val privateTags = listOf(listOf("p", baseUser.pubkeyHex))
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
} else {
|
||||
AmberUtils.openAmber(
|
||||
content,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
decryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accountViewModel.showUser(baseUser.pubkeyHex)
|
||||
}
|
||||
accountViewModel.showUser(baseUser.pubkeyHex)
|
||||
}
|
||||
} else {
|
||||
DisplayFollowUnfollowButton(baseUser, accountViewModel)
|
||||
@@ -858,30 +745,13 @@ private fun DisplayFollowUnfollowButton(
|
||||
it.user.isFollowing(accountViewModel.account.userProfile())
|
||||
}.distinctUntilChanged().observeAsState(initial = baseUser.isFollowing(accountViewModel.account.userProfile()))
|
||||
|
||||
var event by remember { mutableStateOf<ContactListEvent?>(null) }
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
if (isLoggedInFollowingUser) {
|
||||
UnfollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.unfollow(baseUser, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollow(baseUser)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -895,7 +765,7 @@ private fun DisplayFollowUnfollowButton(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.unfollow(baseUser, true)
|
||||
accountViewModel.account.unfollow(baseUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -904,7 +774,9 @@ private fun DisplayFollowUnfollowButton(
|
||||
FollowButton(R.string.follow_back) {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.follow(baseUser, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.follow(baseUser)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -918,7 +790,7 @@ private fun DisplayFollowUnfollowButton(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.follow(baseUser, true)
|
||||
accountViewModel.account.follow(baseUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -926,7 +798,9 @@ private fun DisplayFollowUnfollowButton(
|
||||
FollowButton(R.string.follow) {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
event = accountViewModel.account.follow(baseUser, false)
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.follow(baseUser)
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
@@ -940,7 +814,7 @@ private fun DisplayFollowUnfollowButton(
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.follow(baseUser, true)
|
||||
accountViewModel.account.follow(baseUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1828,88 +1702,6 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
|
||||
) {
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
||||
var event by remember { mutableStateOf<Event?>(null) }
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val signedEvent = Event.fromJson(it)
|
||||
Client.send(signedEvent)
|
||||
LocalCache.verifyAndConsume(signedEvent, null)
|
||||
accountViewModel.account.live.invalidateData()
|
||||
accountViewModel.account.saveable.invalidateData()
|
||||
event = null
|
||||
onDismiss()
|
||||
}
|
||||
},
|
||||
data = event!!.toJson()
|
||||
)
|
||||
}
|
||||
|
||||
val encryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val encryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
event = if (accountViewModel.account.isHidden(user)) {
|
||||
accountViewModel.show(user, encryptedContent)
|
||||
} else {
|
||||
accountViewModel.hide(user, encryptedContent)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val decryptResult = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode != Activity.RESULT_OK) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Sign request rejected",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
val decryptedContent = it.data?.getStringExtra("signature") ?: ""
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val privateTags = if (blockList == null) {
|
||||
listOf(listOf("p", user.pubkeyHex))
|
||||
} else {
|
||||
if (accountViewModel.account.isHidden(user)) {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(user.pubkeyHex) }
|
||||
} else {
|
||||
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", user.pubkeyHex))
|
||||
}
|
||||
}
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
ServiceManager.shouldPauseService = true
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(user.pubkeyNpub())); onDismiss() }) {
|
||||
Text(stringResource(R.string.copy_user_id))
|
||||
@@ -1920,33 +1712,8 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
|
||||
if (accountViewModel.account.isHidden(user)) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val content = blockList?.content ?: ""
|
||||
if (content.isBlank()) {
|
||||
val privateTags = listOf(listOf("p", user.pubkeyHex))
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
} else {
|
||||
AmberUtils.openAmber(
|
||||
content,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
decryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accountViewModel.show(user)
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.show(user)
|
||||
onDismiss()
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.unblock_user))
|
||||
@@ -1954,33 +1721,8 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
|
||||
} else {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
if (accountViewModel.loggedInWithAmber()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val blockList = accountViewModel.account.getBlockList()
|
||||
val content = blockList?.content ?: ""
|
||||
if (content.isBlank()) {
|
||||
val privateTags = listOf(listOf("p", user.pubkeyHex))
|
||||
val msg = Event.mapper.writeValueAsString(privateTags)
|
||||
|
||||
AmberUtils.openAmber(
|
||||
msg,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
encryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
} else {
|
||||
AmberUtils.openAmber(
|
||||
content,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
decryptResult,
|
||||
accountViewModel.account.keyPair.pubKey.toHexKey()
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accountViewModel.hide(user)
|
||||
onDismiss()
|
||||
}
|
||||
accountViewModel.hide(user)
|
||||
onDismiss()
|
||||
}
|
||||
) {
|
||||
Text(stringResource(id = R.string.block_hide_user))
|
||||
|
||||
@@ -36,15 +36,16 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.service.AmberUtils
|
||||
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.qrcode.SimpleQrCodeScanner
|
||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ConnectOrbotDialog
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@@ -65,7 +66,7 @@ fun LoginPage(
|
||||
val useProxy = remember { mutableStateOf(false) }
|
||||
val proxyPort = remember { mutableStateOf("9050") }
|
||||
var connectOrbotDialogOpen by remember { mutableStateOf(false) }
|
||||
var loginWithAmber by remember { mutableStateOf(false) }
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -258,37 +259,6 @@ fun LoginPage(
|
||||
}
|
||||
}
|
||||
|
||||
if (loginWithAmber) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
loginWithAmber = false
|
||||
},
|
||||
onPost = {
|
||||
key.value = TextFieldValue(it)
|
||||
if (!acceptedTerms.value) {
|
||||
termsAcceptanceIsRequired =
|
||||
context.getString(R.string.acceptance_of_terms_is_required)
|
||||
}
|
||||
|
||||
if (key.value.text.isBlank()) {
|
||||
errorMessage = context.getString(R.string.key_is_required)
|
||||
}
|
||||
|
||||
if (acceptedTerms.value && key.value.text.isNotBlank()) {
|
||||
try {
|
||||
accountViewModel.startUI(key.value.text, useProxy.value, proxyPort.value.toInt(), true)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Login", "Could not sign in", e)
|
||||
errorMessage = context.getString(R.string.invalid_key)
|
||||
}
|
||||
}
|
||||
loginWithAmber = false
|
||||
},
|
||||
data = "",
|
||||
type = SignerType.GET_PUBLIC_KEY
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
|
||||
Box(modifier = Modifier.padding(40.dp, 0.dp, 40.dp, 0.dp)) {
|
||||
@@ -329,7 +299,27 @@ fun LoginPage(
|
||||
Box(modifier = Modifier.padding(40.dp, 40.dp, 40.dp, 0.dp)) {
|
||||
Button(
|
||||
onClick = {
|
||||
loginWithAmber = true
|
||||
scope.launch(Dispatchers.IO) {
|
||||
AmberUtils.loginWithAmber()
|
||||
key.value = TextFieldValue(AmberUtils.content)
|
||||
if (!acceptedTerms.value) {
|
||||
termsAcceptanceIsRequired =
|
||||
context.getString(R.string.acceptance_of_terms_is_required)
|
||||
}
|
||||
|
||||
if (key.value.text.isBlank()) {
|
||||
errorMessage = context.getString(R.string.key_is_required)
|
||||
}
|
||||
|
||||
if (acceptedTerms.value && key.value.text.isNotBlank()) {
|
||||
try {
|
||||
accountViewModel.startUI(key.value.text, useProxy.value, proxyPort.value.toInt(), true)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Login", "Could not sign in", e)
|
||||
errorMessage = context.getString(R.string.invalid_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = RoundedCornerShape(Size35dp),
|
||||
modifier = Modifier
|
||||
|
||||
Reference in New Issue
Block a user