add signerDialog in the profile screen follow button
This commit is contained in:
@@ -460,7 +460,11 @@ class Account(
|
||||
if (followingCommunities.isNotEmpty()) {
|
||||
followingCommunities.forEach {
|
||||
ATag.parse(it, null)?.let {
|
||||
returningContactList = ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.privKey!!)
|
||||
returningContactList = if (keyPair.privKey == null) {
|
||||
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey())
|
||||
} else {
|
||||
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.privKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
followingCommunities = emptySet()
|
||||
@@ -468,7 +472,11 @@ class Account(
|
||||
|
||||
if (followingChannels.isNotEmpty()) {
|
||||
followingChannels.forEach {
|
||||
returningContactList = ContactListEvent.followEvent(returningContactList, it, keyPair.privKey!!)
|
||||
returningContactList = if (keyPair.privKey == null) {
|
||||
ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey())
|
||||
} else {
|
||||
ContactListEvent.followEvent(returningContactList, it, keyPair.privKey)
|
||||
}
|
||||
}
|
||||
followingChannels = emptySet()
|
||||
}
|
||||
@@ -476,13 +484,17 @@ class Account(
|
||||
return returningContactList
|
||||
}
|
||||
|
||||
fun follow(user: User) {
|
||||
if (!isWriteable()) return
|
||||
fun follow(user: User, signEvent: Boolean = true): ContactListEvent? {
|
||||
if (!isWriteable() && signEvent) return null
|
||||
|
||||
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
|
||||
|
||||
val event = if (contactList != null) {
|
||||
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair.privKey!!)
|
||||
if (signEvent) {
|
||||
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair.privKey!!)
|
||||
} else {
|
||||
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair.pubKey.toHexKey())
|
||||
}
|
||||
} else {
|
||||
ContactListEvent.createFromScratch(
|
||||
followUsers = listOf(Contact(user.pubkeyHex, null)),
|
||||
@@ -491,12 +503,18 @@ class Account(
|
||||
followCommunities = emptyList(),
|
||||
followEvents = DefaultChannels.toList(),
|
||||
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
|
||||
privateKey = keyPair.privKey!!
|
||||
privateKey = keyPair.privKey!!,
|
||||
publicKey = keyPair.pubKey
|
||||
)
|
||||
}
|
||||
|
||||
if (!signEvent) {
|
||||
return event
|
||||
}
|
||||
|
||||
Client.send(event)
|
||||
LocalCache.consume(event)
|
||||
return null
|
||||
}
|
||||
|
||||
fun follow(channel: Channel) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.vitorpamplona.amethyst.service
|
||||
|
||||
import android.content.Context
|
||||
|
||||
object PackageUtils {
|
||||
fun isPackageInstalled(context: Context, target: String): Boolean {
|
||||
return context.packageManager.getInstalledApplications(0).find { info -> info.packageName == target } != null
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,8 @@ class ContactListEvent(
|
||||
followEvents: List<String>,
|
||||
relayUse: Map<String, ReadWrite>?,
|
||||
privateKey: ByteArray,
|
||||
createdAt: Long = TimeUtils.now()
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
publicKey: ByteArray? = null
|
||||
): ContactListEvent {
|
||||
val content = if (relayUse != null) {
|
||||
gson.toJson(relayUse)
|
||||
@@ -126,10 +127,29 @@ class ContactListEvent(
|
||||
listOf("g", it)
|
||||
}
|
||||
|
||||
if (publicKey == null) {
|
||||
return create(
|
||||
content = content,
|
||||
tags = tags,
|
||||
privateKey = privateKey,
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
return create(
|
||||
content = content,
|
||||
tags = tags,
|
||||
privateKey = privateKey,
|
||||
pubKey = publicKey.toHexKey(),
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
|
||||
fun followUser(earlierVersion: ContactListEvent, pubKeyHex: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
if (earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion
|
||||
|
||||
return create(
|
||||
content = earlierVersion.content,
|
||||
tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)),
|
||||
pubKey = pubKey,
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
@@ -211,6 +231,17 @@ class ContactListEvent(
|
||||
)
|
||||
}
|
||||
|
||||
fun followEvent(earlierVersion: ContactListEvent, idHex: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion
|
||||
|
||||
return create(
|
||||
content = earlierVersion.content,
|
||||
tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
|
||||
pubKey = pubKey,
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
|
||||
fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
if (!earlierVersion.isTaggedEvent(idHex)) return earlierVersion
|
||||
|
||||
@@ -233,6 +264,17 @@ class ContactListEvent(
|
||||
)
|
||||
}
|
||||
|
||||
fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
|
||||
|
||||
return create(
|
||||
content = earlierVersion.content,
|
||||
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
|
||||
pubKey = pubKey,
|
||||
createdAt = createdAt
|
||||
)
|
||||
}
|
||||
|
||||
fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
|
||||
|
||||
@@ -259,6 +301,11 @@ class ContactListEvent(
|
||||
)
|
||||
}
|
||||
|
||||
fun create(content: String, tags: List<List<String>>, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
val id = generateId(pubKey, createdAt, kind, tags, content)
|
||||
return ContactListEvent(id.toHexKey(), pubKey, createdAt, tags, content, "")
|
||||
}
|
||||
|
||||
fun create(content: String, tags: List<List<String>>, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
|
||||
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
|
||||
val id = generateId(pubKey, createdAt, kind, tags, content)
|
||||
|
||||
@@ -59,7 +59,7 @@ fun openAmber(
|
||||
@Composable
|
||||
fun SignerDialog(
|
||||
onClose: () -> Unit,
|
||||
onPost: () -> Unit,
|
||||
onPost: (signedEvent: Event) -> Unit,
|
||||
event: Event
|
||||
) {
|
||||
var signature by remember { mutableStateOf("") }
|
||||
@@ -120,7 +120,26 @@ fun SignerDialog(
|
||||
|
||||
PostButton(
|
||||
onPost = {
|
||||
onPost()
|
||||
val signedEvent = Event(
|
||||
event.id,
|
||||
event.pubKey,
|
||||
event.createdAt,
|
||||
event.kind,
|
||||
event.tags,
|
||||
event.content,
|
||||
signature
|
||||
)
|
||||
if (!signedEvent.hasValidSignature()) {
|
||||
scope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Invalid signature",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
return@PostButton
|
||||
}
|
||||
onPost(signedEvent)
|
||||
},
|
||||
isActive = true
|
||||
)
|
||||
|
||||
@@ -59,16 +59,21 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
||||
import com.vitorpamplona.amethyst.service.PackageUtils
|
||||
import com.vitorpamplona.amethyst.service.model.ATag
|
||||
import com.vitorpamplona.amethyst.service.model.AppDefinitionEvent
|
||||
import com.vitorpamplona.amethyst.service.model.BadgeDefinitionEvent
|
||||
import com.vitorpamplona.amethyst.service.model.BadgeProfilesEvent
|
||||
import com.vitorpamplona.amethyst.service.model.ContactListEvent
|
||||
import com.vitorpamplona.amethyst.service.model.Event
|
||||
import com.vitorpamplona.amethyst.service.model.IdentityClaim
|
||||
import com.vitorpamplona.amethyst.service.model.PayInvoiceErrorResponse
|
||||
import com.vitorpamplona.amethyst.service.model.PayInvoiceSuccessResponse
|
||||
import com.vitorpamplona.amethyst.service.model.ReportEvent
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
|
||||
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.toImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.DisplayNip05ProfileStatus
|
||||
@@ -742,6 +747,24 @@ private fun DisplayFollowUnfollowButton(
|
||||
it.user.isFollowing(accountViewModel.account.userProfile())
|
||||
}.distinctUntilChanged().observeAsState(initial = baseUser.isFollowing(accountViewModel.account.userProfile()))
|
||||
|
||||
var event by remember { mutableStateOf<ContactListEvent?>(null) }
|
||||
|
||||
if (event != null) {
|
||||
SignerDialog(
|
||||
onClose = {
|
||||
event = null
|
||||
},
|
||||
onPost = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Client.send(it)
|
||||
LocalCache.verifyAndConsume(it, null)
|
||||
event = null
|
||||
}
|
||||
},
|
||||
event = event!!
|
||||
)
|
||||
}
|
||||
|
||||
if (isLoggedInFollowingUser) {
|
||||
UnfollowButton {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
@@ -782,14 +805,18 @@ private fun DisplayFollowUnfollowButton(
|
||||
} else {
|
||||
FollowButton(R.string.follow) {
|
||||
if (!accountViewModel.isWriteable()) {
|
||||
scope.launch {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
context.getString(R.string.login_with_a_private_key_to_be_able_to_follow),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
if (PackageUtils.isPackageInstalled(context, "com.greenart7c3.nostrsigner")) {
|
||||
event = accountViewModel.account.follow(baseUser, false)
|
||||
} else {
|
||||
scope.launch {
|
||||
Toast
|
||||
.makeText(
|
||||
context,
|
||||
context.getString(R.string.login_with_a_private_key_to_be_able_to_follow),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedOff
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -37,6 +36,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.service.PackageUtils
|
||||
import com.vitorpamplona.amethyst.ui.qrcode.SimpleQrCodeScanner
|
||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ConnectOrbotDialog
|
||||
@@ -229,7 +229,7 @@ fun LoginPage(
|
||||
}
|
||||
}
|
||||
|
||||
if (isPackageInstalled(context, "org.torproject.android")) {
|
||||
if (PackageUtils.isPackageInstalled(context, "org.torproject.android")) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Checkbox(
|
||||
checked = useProxy.value,
|
||||
@@ -315,7 +315,3 @@ fun LoginPage(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun isPackageInstalled(context: Context, target: String): Boolean {
|
||||
return context.packageManager.getInstalledApplications(0).find { info -> info.packageName == target } != null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user