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

View File

@ -117,6 +117,7 @@ class Account(
keyPair.pubKey.toHexKey()
)
blockList?.decryptedContent = AmberUtils.content
live.invalidateData()
AmberUtils.content = ""
}
@ -1684,7 +1685,7 @@ class Account(
return returningList
}
fun hideUser(pubkeyHex: String, encryptedContent: String): PeopleListEvent? {
fun hideUser(pubkeyHex: String, encryptedContent: String): PeopleListEvent {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())
return if (blockList != null) {
@ -1732,6 +1733,20 @@ class Account(
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) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())

View File

@ -1,6 +1,9 @@
package com.vitorpamplona.amethyst.ui.note
import android.app.Activity
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -26,11 +29,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ServiceManager
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.AmberUtils
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
import com.vitorpamplona.amethyst.ui.actions.SignerType
import com.vitorpamplona.amethyst.ui.screen.ZapReqResponse
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.FollowButton
@ -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.Size55dp
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.events.ContactListEvent
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.LnZapEvent
@ -177,10 +184,114 @@ fun UserActionOptions(
baseAuthor: User,
accountViewModel: AccountViewModel
) {
val scope = rememberCoroutineScope()
val context = LocalContext.current
var event by remember { mutableStateOf<Event?>(null) }
if (event != null) {
SignerDialog(
onClose = {
event = null
},
onPost = {
scope.launch(Dispatchers.IO) {
val signedEvent = Event.fromJson(it)
Client.send(signedEvent)
LocalCache.verifyAndConsume(signedEvent, null)
accountViewModel.account.live.invalidateData()
accountViewModel.account.saveable.invalidateData()
event = null
}
},
data = event!!.toJson()
)
}
val encryptResult = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult(),
onResult = {
if (it.resultCode != Activity.RESULT_OK) {
scope.launch {
Toast.makeText(
context,
"Sign request rejected",
Toast.LENGTH_SHORT
).show()
}
return@rememberLauncherForActivityResult
}
val encryptedContent = it.data?.getStringExtra("signature") ?: ""
event = accountViewModel.show(baseAuthor, encryptedContent)
}
)
val decryptResult = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult(),
onResult = {
if (it.resultCode != Activity.RESULT_OK) {
scope.launch {
Toast.makeText(
context,
"Sign request rejected",
Toast.LENGTH_SHORT
).show()
}
return@rememberLauncherForActivityResult
}
val decryptedContent = it.data?.getStringExtra("signature") ?: ""
val blockList = accountViewModel.account.getBlockList()
val privateTags = if (blockList == null) {
listOf(listOf("p", baseAuthor.pubkeyHex))
} else {
if (accountViewModel.account.isHidden(baseAuthor)) {
blockList.privateTagsOrEmpty(decryptedContent).filter { element -> !element.contains(baseAuthor.pubkeyHex) }
} else {
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", baseAuthor.pubkeyHex))
}
}
val msg = Event.mapper.writeValueAsString(privateTags)
ServiceManager.shouldPauseService = true
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
)
WatchIsHiddenUser(baseAuthor, accountViewModel) { isHidden ->
if (isHidden) {
ShowUserButton {
accountViewModel.show(baseAuthor)
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)
}
}
} else {
ShowFollowingOrUnfollowingButton(baseAuthor, accountViewModel)

View File

@ -467,6 +467,10 @@ class AccountViewModel(val account: Account) : ViewModel() {
return account.unseal(event)
}
fun show(user: User, encryptedContent: String): PeopleListEvent? {
return account.showUser(user.pubkeyHex, encryptedContent)
}
fun show(user: User) {
viewModelScope.launch(Dispatchers.IO) {
account.showUser(user.pubkeyHex)

View File

@ -727,10 +727,114 @@ private fun ProfileActions(
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 ->
if (isHidden) {
ShowUserButton {
accountViewModel.showUser(baseUser.pubkeyHex)
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)
}
}
} else {
DisplayFollowUnfollowButton(baseUser, accountViewModel)
@ -1737,9 +1841,9 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
val signedEvent = Event.fromJson(it)
Client.send(signedEvent)
LocalCache.verifyAndConsume(signedEvent, null)
event = null
accountViewModel.account.live.invalidateData()
accountViewModel.account.saveable.invalidateData()
event = null
onDismiss()
}
},
@ -1762,7 +1866,11 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
}
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)
}
}
)
@ -1785,7 +1893,11 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
val privateTags = if (blockList == null) {
listOf(listOf("p", user.pubkeyHex))
} else {
blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("p", user.pubkeyHex))
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)
@ -1806,10 +1918,37 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
if (accountViewModel.userProfile() != user) {
Divider()
if (accountViewModel.account.isHidden(user)) {
DropdownMenuItem(onClick = {
accountViewModel.show(user)
onDismiss()
}) {
DropdownMenuItem(
onClick = {
if (accountViewModel.loggedInWithAmber()) {
scope.launch(Dispatchers.IO) {
val blockList = accountViewModel.account.getBlockList()
val content = blockList?.content ?: ""
if (content.isBlank()) {
val privateTags = listOf(listOf("p", user.pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
AmberUtils.openAmber(
msg,
SignerType.NIP04_ENCRYPT,
encryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
} else {
AmberUtils.openAmber(
content,
SignerType.NIP04_DECRYPT,
decryptResult,
accountViewModel.account.keyPair.pubKey.toHexKey()
)
}
}
} else {
accountViewModel.show(user)
onDismiss()
}
}
) {
Text(stringResource(R.string.unblock_user))
}
} else {

View File

@ -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 {
if (!earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion