add support for deletion events

This commit is contained in:
greenart7c3 2023-08-25 09:29:13 -03:00
parent e817f94045
commit b2b7799a0f
6 changed files with 78 additions and 26 deletions

View File

@ -432,8 +432,8 @@ class Account(
LocalCache.consume(event, null)
}
fun delete(note: Note) {
delete(listOf(note))
fun delete(note: Note, signEvent: Boolean = true): DeletionEvent? {
return delete(listOf(note), signEvent)
}
fun delete(notes: List<Note>, signEvent: Boolean = true): DeletionEvent? {
@ -442,11 +442,10 @@ class Account(
val myNotes = notes.filter { it.author == userProfile() }.map { it.idHex }
if (myNotes.isNotEmpty()) {
val event = DeletionEvent.create(myNotes, keyPair)
if (!signEvent) {
return DeletionEvent.create(myNotes, keyPair.pubKey.toHexKey())
return event
}
val event = DeletionEvent.create(myNotes, keyPair.privKey!!)
Client.send(event)
LocalCache.consume(event)
}

View File

@ -334,7 +334,7 @@ private fun EditStatusBox(baseAccountUser: User, accountViewModel: AccountViewMo
UserStatusDeleteButton() {
scope.launch(Dispatchers.IO) {
accountViewModel.updateStatus(it, "")
accountViewModel.delete(it)
accountViewModel.delete(it, true)
focusManager.clearFocus(true)
}
}

View File

@ -37,9 +37,11 @@ import androidx.compose.material.icons.filled.Report
import androidx.compose.material.icons.filled.Share
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
@ -60,13 +62,17 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
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.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ReportNoteDialog
import com.vitorpamplona.amethyst.ui.theme.WarningColor
import com.vitorpamplona.amethyst.ui.theme.secondaryButtonBackground
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.FileHeaderEvent
import com.vitorpamplona.quartz.events.PeopleListEvent
import kotlinx.coroutines.Dispatchers
@ -200,6 +206,25 @@ private fun RenderMainPopup(
val isOwnNote = accountViewModel.isLoggedUser(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) {
Card(
modifier = Modifier.shadow(elevation = 6.dp, shape = cardShape),
@ -275,8 +300,10 @@ private fun RenderMainPopup(
) {
if (accountViewModel.hideDeleteRequestDialog) {
scope.launch(Dispatchers.IO) {
accountViewModel.delete(note)
onDismiss()
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
if (!accountViewModel.loggedInWithAmber()) {
onDismiss()
}
}
} else {
showDeleteAlertDialog.value = true
@ -382,6 +409,25 @@ fun NoteQuickActionItem(icon: ImageVector, label: String, onClick: () -> Unit) {
fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit) {
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(
title = stringResource(R.string.quick_action_request_deletion_alert_title),
textContent = stringResource(R.string.quick_action_request_deletion_alert_body),
@ -389,16 +435,20 @@ fun DeleteAlertDialog(note: Note, accountViewModel: AccountViewModel, onDismiss:
buttonText = stringResource(R.string.quick_action_delete_dialog_btn),
onClickDoOnce = {
scope.launch(Dispatchers.IO) {
accountViewModel.delete(note)
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
}
if (!accountViewModel.loggedInWithAmber()) {
onDismiss()
}
onDismiss()
},
onClickDontShowAgain = {
scope.launch(Dispatchers.IO) {
accountViewModel.delete(note)
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
accountViewModel.dontShowDeleteRequestDialog()
}
onDismiss()
if (!accountViewModel.loggedInWithAmber()) {
onDismiss()
}
},
onDismiss = onDismiss
)

View File

@ -531,7 +531,16 @@ fun NoteDropDownMenu(note: Note, popupExpanded: MutableState<Boolean>, accountVi
}
Divider()
if (state.isLoggedUser) {
DropdownMenuItem(onClick = { scope.launch(Dispatchers.IO) { accountViewModel.delete(note); onDismiss() } }) {
DropdownMenuItem(
onClick = {
scope.launch(Dispatchers.IO) {
event = accountViewModel.delete(note, !accountViewModel.loggedInWithAmber())
if (!accountViewModel.loggedInWithAmber()) {
onDismiss()
}
}
}
) {
Text(stringResource(R.string.request_deletion))
}
} else {

View File

@ -264,8 +264,8 @@ class AccountViewModel(val account: Account) : ViewModel() {
account.broadcast(note)
}
fun delete(note: Note) {
account.delete(note)
fun delete(note: Note, signEvent: Boolean): DeletionEvent? {
return account.delete(note, signEvent)
}
fun decrypt(note: Note): String? {

View File

@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey
@Immutable
@ -20,20 +21,13 @@ class DeletionEvent(
companion object {
const val kind = 5
fun create(deleteEvents: List<String>, pubKey: HexKey, createdAt: Long = TimeUtils.now()): DeletionEvent {
fun create(deleteEvents: List<String>, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): DeletionEvent {
val content = ""
val pubKey = keyPair.pubKey.toHexKey()
val tags = deleteEvents.map { listOf("e", it) }
val id = generateId(pubKey, createdAt, kind, tags, content)
return DeletionEvent(id.toHexKey(), pubKey, createdAt, tags, content, "")
}
fun create(deleteEvents: List<String>, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): DeletionEvent {
val content = ""
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
val tags = deleteEvents.map { listOf("e", it) }
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey)
return DeletionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return DeletionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
}
}
}