unblock users

This commit is contained in:
greenart7c3
2023-08-30 14:15:20 -03:00
parent 7a68cf867e
commit 9ee1250f3a
5 changed files with 297 additions and 10 deletions
@@ -117,6 +117,7 @@ class Account(
keyPair.pubKey.toHexKey() keyPair.pubKey.toHexKey()
) )
blockList?.decryptedContent = AmberUtils.content blockList?.decryptedContent = AmberUtils.content
live.invalidateData()
AmberUtils.content = "" AmberUtils.content = ""
} }
@@ -1684,7 +1685,7 @@ class Account(
return returningList return returningList
} }
fun hideUser(pubkeyHex: String, encryptedContent: String): PeopleListEvent? { fun hideUser(pubkeyHex: String, encryptedContent: String): PeopleListEvent {
val blockList = migrateHiddenUsersIfNeeded(getBlockList()) val blockList = migrateHiddenUsersIfNeeded(getBlockList())
return if (blockList != null) { return if (blockList != null) {
@@ -1732,6 +1733,20 @@ class Account(
saveable.invalidateData() saveable.invalidateData()
} }
fun showUser(pubkeyHex: String, encryptedContent: String): PeopleListEvent? {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())
if (blockList != null) {
return PeopleListEvent.removeUser(
earlierVersion = blockList,
pubKeyHex = pubkeyHex,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent = encryptedContent
)
}
return null
}
fun showUser(pubkeyHex: String) { fun showUser(pubkeyHex: String) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList()) val blockList = migrateHiddenUsersIfNeeded(getBlockList())
@@ -1,6 +1,9 @@
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
@@ -26,11 +29,14 @@ 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.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.SignerDialog 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
@@ -41,6 +47,7 @@ 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.ContactListEvent
import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.LnZapEvent import com.vitorpamplona.quartz.events.LnZapEvent
@@ -177,11 +184,115 @@ fun UserActionOptions(
baseAuthor: User, baseAuthor: User,
accountViewModel: AccountViewModel accountViewModel: AccountViewModel
) { ) {
val scope = rememberCoroutineScope()
val context = LocalContext.current
var event by remember { mutableStateOf<Event?>(null) }
if (event != null) {
SignerDialog(
onClose = {
event = null
},
onPost = {
scope.launch(Dispatchers.IO) {
val signedEvent = Event.fromJson(it)
Client.send(signedEvent)
LocalCache.verifyAndConsume(signedEvent, null)
accountViewModel.account.live.invalidateData()
accountViewModel.account.saveable.invalidateData()
event = null
}
},
data = event!!.toJson()
)
}
val encryptResult = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult(),
onResult = {
if (it.resultCode != Activity.RESULT_OK) {
scope.launch {
Toast.makeText(
context,
"Sign request rejected",
Toast.LENGTH_SHORT
).show()
}
return@rememberLauncherForActivityResult
}
val encryptedContent = it.data?.getStringExtra("signature") ?: ""
event = accountViewModel.show(baseAuthor, encryptedContent)
}
)
val decryptResult = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult(),
onResult = {
if (it.resultCode != Activity.RESULT_OK) {
scope.launch {
Toast.makeText(
context,
"Sign request rejected",
Toast.LENGTH_SHORT
).show()
}
return@rememberLauncherForActivityResult
}
val decryptedContent = it.data?.getStringExtra("signature") ?: ""
val blockList = accountViewModel.account.getBlockList()
val privateTags = if (blockList == null) {
listOf(listOf("p", baseAuthor.pubkeyHex))
} else {
if (accountViewModel.account.isHidden(baseAuthor)) {
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(baseAuthor.pubkeyHex) }
} else {
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", baseAuthor.pubkeyHex))
}
}
val msg = Event.mapper.writeValueAsString(privateTags)
ServiceManager.shouldPauseService = true
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
)
WatchIsHiddenUser(baseAuthor, accountViewModel) { isHidden -> WatchIsHiddenUser(baseAuthor, accountViewModel) { isHidden ->
if (isHidden) { if (isHidden) {
ShowUserButton { ShowUserButton {
if (accountViewModel.loggedInWithAmber()) {
scope.launch(Dispatchers.IO) {
val blockList = accountViewModel.account.getBlockList()
val content = blockList?.content ?: ""
if (content.isBlank()) {
val privateTags = listOf(listOf("p", baseAuthor.pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
} else {
AmberUtils.openAmber(
content,
SignerType.NIP04_DECRYPT,
decryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
}
} else {
accountViewModel.show(baseAuthor) accountViewModel.show(baseAuthor)
} }
}
} else { } else {
ShowFollowingOrUnfollowingButton(baseAuthor, accountViewModel) ShowFollowingOrUnfollowingButton(baseAuthor, accountViewModel)
} }
@@ -467,6 +467,10 @@ 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)
@@ -727,11 +727,115 @@ private fun ProfileActions(
EditButton(accountViewModel.account) EditButton(accountViewModel.account)
} }
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()) {
scope.launch(Dispatchers.IO) {
val blockList = accountViewModel.account.getBlockList()
val content = blockList?.content ?: ""
if (content.isBlank()) {
val privateTags = listOf(listOf("p", baseUser.pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
} else {
AmberUtils.openAmber(
content,
SignerType.NIP04_DECRYPT,
decryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
}
} else {
accountViewModel.showUser(baseUser.pubkeyHex) accountViewModel.showUser(baseUser.pubkeyHex)
} }
}
} else { } else {
DisplayFollowUnfollowButton(baseUser, accountViewModel) DisplayFollowUnfollowButton(baseUser, accountViewModel)
} }
@@ -1737,9 +1841,9 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
val signedEvent = Event.fromJson(it) val signedEvent = Event.fromJson(it)
Client.send(signedEvent) Client.send(signedEvent)
LocalCache.verifyAndConsume(signedEvent, null) LocalCache.verifyAndConsume(signedEvent, null)
event = null
accountViewModel.account.live.invalidateData() accountViewModel.account.live.invalidateData()
accountViewModel.account.saveable.invalidateData() accountViewModel.account.saveable.invalidateData()
event = null
onDismiss() onDismiss()
} }
}, },
@@ -1762,7 +1866,11 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
} }
val encryptedContent = it.data?.getStringExtra("signature") ?: "" val encryptedContent = it.data?.getStringExtra("signature") ?: ""
event = accountViewModel.hide(user, encryptedContent) event = if (accountViewModel.account.isHidden(user)) {
accountViewModel.show(user, encryptedContent)
} else {
accountViewModel.hide(user, encryptedContent)
}
} }
) )
@@ -1784,9 +1892,13 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
val blockList = accountViewModel.account.getBlockList() val blockList = accountViewModel.account.getBlockList()
val privateTags = if (blockList == null) { val privateTags = if (blockList == null) {
listOf(listOf("p", user.pubkeyHex)) listOf(listOf("p", user.pubkeyHex))
} else {
if (accountViewModel.account.isHidden(user)) {
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(user.pubkeyHex) }
} else { } else {
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", user.pubkeyHex)) blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", user.pubkeyHex))
} }
}
val msg = Event.mapper.writeValueAsString(privateTags) val msg = Event.mapper.writeValueAsString(privateTags)
ServiceManager.shouldPauseService = true ServiceManager.shouldPauseService = true
@@ -1806,10 +1918,37 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
if (accountViewModel.userProfile() != user) { if (accountViewModel.userProfile() != user) {
Divider() Divider()
if (accountViewModel.account.isHidden(user)) { if (accountViewModel.account.isHidden(user)) {
DropdownMenuItem(onClick = { DropdownMenuItem(
onClick = {
if (accountViewModel.loggedInWithAmber()) {
scope.launch(Dispatchers.IO) {
val blockList = accountViewModel.account.getBlockList()
val content = blockList?.content ?: ""
if (content.isBlank()) {
val privateTags = listOf(listOf("p", user.pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
} else {
AmberUtils.openAmber(
content,
SignerType.NIP04_DECRYPT,
decryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
}
} else {
accountViewModel.show(user) accountViewModel.show(user)
onDismiss() onDismiss()
}) { }
}
) {
Text(stringResource(R.string.unblock_user)) Text(stringResource(R.string.unblock_user))
} }
} else { } else {
@@ -176,6 +176,24 @@ class PeopleListEvent(
} }
} }
fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, encryptedContent: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): PeopleListEvent {
return if (isPrivate) {
create(
content = encryptedContent,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
pubKey = pubKey,
createdAt = createdAt
)
} else {
create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
pubKey = pubKey,
createdAt = createdAt
)
}
}
fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent { fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
if (!earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion if (!earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion