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