add signer dialog to communities and public chats

This commit is contained in:
greenart7c3
2023-08-14 16:34:40 -03:00
parent e6f6f64512
commit 66b1e4b15d
3 changed files with 158 additions and 26 deletions

View File

@@ -503,7 +503,7 @@ class Account(
returningContactList = if (keyPair.privKey == null) { returningContactList = if (keyPair.privKey == null) {
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey()) ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey())
} else { } else {
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.privKey) ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey(), keyPair.privKey)
} }
} }
} }
@@ -515,7 +515,7 @@ class Account(
returningContactList = if (keyPair.privKey == null) { returningContactList = if (keyPair.privKey == null) {
ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey()) ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey())
} else { } else {
ContactListEvent.followEvent(returningContactList, it, keyPair.privKey) ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey(), keyPair.privKey)
} }
} }
followingChannels = emptySet() followingChannels = emptySet()
@@ -557,13 +557,13 @@ class Account(
return null return null
} }
fun follow(channel: Channel) { fun follow(channel: Channel, signEvent: Boolean): ContactListEvent? {
if (!isWriteable()) return if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList) val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) { val event = if (contactList != null) {
ContactListEvent.followEvent(contactList, channel.idHex, keyPair.privKey!!) ContactListEvent.followEvent(contactList, channel.idHex, keyPair.pubKey.toHexKey(), keyPair.privKey)
} else { } else {
ContactListEvent.createFromScratch( ContactListEvent.createFromScratch(
followUsers = emptyList(), followUsers = emptyList(),
@@ -572,21 +572,27 @@ class Account(
followCommunities = emptyList(), followCommunities = emptyList(),
followEvents = DefaultChannels.toList().plus(channel.idHex), followEvents = DefaultChannels.toList().plus(channel.idHex),
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) }, relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
privateKey = keyPair.privKey!! publicKey = if (!signEvent) keyPair.pubKey else null,
privateKey = keyPair.privKey
) )
} }
if (!signEvent) {
return event
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
return null
} }
fun follow(community: AddressableNote) { fun follow(community: AddressableNote, signEvent: Boolean): ContactListEvent? {
if (!isWriteable()) return if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList) val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) { val event = if (contactList != null) {
ContactListEvent.followAddressableEvent(contactList, community.address, keyPair.privKey!!) ContactListEvent.followAddressableEvent(contactList, community.address, keyPair.pubKey.toHexKey(), keyPair.privKey)
} else { } else {
val relays = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) } val relays = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) }
ContactListEvent.createFromScratch( ContactListEvent.createFromScratch(
@@ -596,12 +602,18 @@ class Account(
followCommunities = listOf(community.address), followCommunities = listOf(community.address),
followEvents = DefaultChannels.toList(), followEvents = DefaultChannels.toList(),
relayUse = relays, relayUse = relays,
privateKey = keyPair.privKey!! publicKey = if (!signEvent) keyPair.pubKey else null,
privateKey = keyPair.privKey
) )
} }
if (!signEvent) {
return event
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
return null
} }
fun followHashtag(tag: String, signEvent: Boolean = true): ContactListEvent? { fun followHashtag(tag: String, signEvent: Boolean = true): ContactListEvent? {
@@ -745,8 +757,8 @@ class Account(
} }
} }
fun unfollow(channel: Channel) { fun unfollow(channel: Channel, signEvent: Boolean): ContactListEvent? {
if (!isWriteable()) return if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList) val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
@@ -754,16 +766,22 @@ class Account(
val event = ContactListEvent.unfollowEvent( val event = ContactListEvent.unfollowEvent(
contactList, contactList,
channel.idHex, channel.idHex,
keyPair.privKey!! keyPair.pubKey.toHexKey(),
keyPair.privKey
) )
if (!signEvent) {
return event
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
} }
return null
} }
fun unfollow(community: AddressableNote) { fun unfollow(community: AddressableNote, signEvent: Boolean): ContactListEvent? {
if (!isWriteable()) return if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList) val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
@@ -771,12 +789,18 @@ class Account(
val event = ContactListEvent.unfollowAddressableEvent( val event = ContactListEvent.unfollowAddressableEvent(
contactList, contactList,
community.address, community.address,
keyPair.privKey!! keyPair.pubKey.toHexKey(),
keyPair.privKey
) )
if (!signEvent) {
return event
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
} }
return null
} }
fun createNip95(byteArray: ByteArray, headerInfo: FileHeader): Pair<FileStorageEvent, FileStorageHeaderEvent>? { fun createNip95(byteArray: ByteArray, headerInfo: FileHeader): Pair<FileStorageEvent, FileStorageHeaderEvent>? {
@@ -1131,7 +1155,7 @@ class Account(
LocalCache.consume(event) LocalCache.consume(event)
LocalCache.getChannelIfExists(event.id)?.let { LocalCache.getChannelIfExists(event.id)?.let {
follow(it) follow(it, true)
} }
} }
@@ -1597,7 +1621,7 @@ class Account(
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
follow(channel) follow(channel, true)
} }
fun unwrap(event: GiftWrapEvent): Event? { fun unwrap(event: GiftWrapEvent): Event? {

View File

@@ -253,9 +253,18 @@ class ContactListEvent(
) )
} }
fun followEvent(earlierVersion: ContactListEvent, idHex: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent { fun followEvent(earlierVersion: ContactListEvent, idHex: String, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
pubKey = pubKey,
createdAt = createdAt
)
}
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)), tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
@@ -275,9 +284,18 @@ class ContactListEvent(
) )
} }
fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent { fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, publicKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedEvent(idHex)) return earlierVersion if (!earlierVersion.isTaggedEvent(idHex)) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex },
pubKey = publicKey,
createdAt = createdAt
)
}
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex },
@@ -286,9 +304,18 @@ class ContactListEvent(
) )
} }
fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent { fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
pubKey = pubKey,
createdAt = createdAt
)
}
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)), tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
@@ -308,9 +335,18 @@ class ContactListEvent(
) )
} }
fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent { fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() },
pubKey = pubKey,
createdAt = createdAt
)
}
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() },

View File

@@ -87,13 +87,17 @@ 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.PackageUtils
import com.vitorpamplona.amethyst.service.model.Event
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE
import com.vitorpamplona.amethyst.service.model.Participant import com.vitorpamplona.amethyst.service.model.Participant
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists
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.actions.toImmutableListOfLists import com.vitorpamplona.amethyst.ui.actions.toImmutableListOfLists
import com.vitorpamplona.amethyst.ui.components.LoadNote import com.vitorpamplona.amethyst.ui.components.LoadNote
@@ -1090,12 +1094,29 @@ 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) {
Client.send(it)
LocalCache.verifyAndConsume(it, null)
event = null
}
},
event = event!!
)
}
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp), modifier = Modifier.padding(horizontal = 3.dp),
onClick = { onClick = {
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
accountViewModel.account.follow(channel) event = accountViewModel.account.follow(channel, !PackageUtils.isAmberInstalled(context))
} }
}, },
shape = ButtonBorder, shape = ButtonBorder,
@@ -1112,12 +1133,29 @@ 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) {
Client.send(it)
LocalCache.verifyAndConsume(it, null)
event = null
}
},
event = event!!
)
}
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp), modifier = Modifier.padding(horizontal = 3.dp),
onClick = { onClick = {
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
accountViewModel.account.unfollow(channel) event = accountViewModel.account.unfollow(channel, !PackageUtils.isAmberInstalled(context))
} }
}, },
shape = ButtonBorder, shape = ButtonBorder,
@@ -1134,12 +1172,29 @@ 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) {
Client.send(it)
LocalCache.verifyAndConsume(it, null)
event = null
}
},
event = event!!
)
}
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp), modifier = Modifier.padding(horizontal = 3.dp),
onClick = { onClick = {
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
accountViewModel.account.follow(note) event = accountViewModel.account.follow(note, !PackageUtils.isAmberInstalled(context))
} }
}, },
shape = ButtonBorder, shape = ButtonBorder,
@@ -1156,12 +1211,29 @@ 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) {
Client.send(it)
LocalCache.verifyAndConsume(it, null)
event = null
}
},
event = event!!
)
}
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp), modifier = Modifier.padding(horizontal = 3.dp),
onClick = { onClick = {
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
accountViewModel.account.unfollow(note) event = accountViewModel.account.unfollow(note, !PackageUtils.isAmberInstalled(context))
} }
}, },
shape = ButtonBorder, shape = ButtonBorder,