Skip to content

Commit

Permalink
Mute keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
vitorpamplona committed Sep 24, 2023
1 parent 57dfe3a commit f4da2ae
Show file tree
Hide file tree
Showing 16 changed files with 838 additions and 69 deletions.
170 changes: 163 additions & 7 deletions app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class Account(
data class LiveHiddenUsers(
val hiddenUsers: ImmutableSet<String>,
val spammers: ImmutableSet<String>,
val hiddenWords: ImmutableSet<String>,
val showSensitiveContent: Boolean?
)

Expand All @@ -129,32 +130,36 @@ class Account(

LiveHiddenUsers(
hiddenUsers = persistentSetOf(),
spammers = localLive?.account?.transientHiddenUsers
?: persistentSetOf(),
hiddenWords = persistentSetOf(),
spammers = localLive?.account?.transientHiddenUsers ?: persistentSetOf(),
showSensitiveContent = showSensitiveContent
)
} else {
blockList.decryptedContent = ExternalSignerUtils.cachedDecryptedContent[blockList.id]
val liveBlockedUsers = blockList.publicAndPrivateUsers(blockList.decryptedContent ?: "")
val liveBlockedWords = blockList.publicAndPrivateWords(blockList.decryptedContent ?: "")
LiveHiddenUsers(
hiddenUsers = liveBlockedUsers,
spammers = localLive?.account?.transientHiddenUsers
?: persistentSetOf(),
hiddenWords = liveBlockedWords,
spammers = localLive?.account?.transientHiddenUsers ?: persistentSetOf(),
showSensitiveContent = showSensitiveContent
)
}
} else {
LiveHiddenUsers(
hiddenUsers = persistentSetOf(),
hiddenWords = persistentSetOf(),
spammers = localLive?.account?.transientHiddenUsers
?: persistentSetOf(),
showSensitiveContent = showSensitiveContent
)
}
} else {
val liveBlockedUsers = blockList?.publicAndPrivateUsers(keyPair.privKey)
val liveBlockedWords = blockList?.publicAndPrivateWords(keyPair.privKey)
LiveHiddenUsers(
hiddenUsers = liveBlockedUsers ?: persistentSetOf(),
hiddenWords = liveBlockedWords ?: persistentSetOf(),
spammers = localLive?.account?.transientHiddenUsers ?: persistentSetOf(),
showSensitiveContent = showSensitiveContent
)
Expand Down Expand Up @@ -2276,6 +2281,157 @@ class Account(
return returningList
}

fun hideWord(word: String) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())
if (loginWithExternalSigner) {
val id = blockList?.id
val encryptedContent = if (id == null) {
val privateTags = listOf(listOf("word", word))
val msg = Event.mapper.writeValueAsString(privateTags)

ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), "encrypted")
val encryptedContent = ExternalSignerUtils.content["encrypted"] ?: ""
ExternalSignerUtils.content.remove("encrypted")
if (encryptedContent.isBlank()) return
encryptedContent
} else {
var decryptedContent = ExternalSignerUtils.cachedDecryptedContent[id]
if (decryptedContent == null) {
ExternalSignerUtils.decrypt(blockList.content, keyPair.pubKey.toHexKey(), id)
val content = ExternalSignerUtils.content[id] ?: ""
if (content.isBlank()) return
decryptedContent = content
}

val privateTags = blockList.privateTagsOrEmpty(decryptedContent).plus(element = listOf("word", word))
val msg = Event.mapper.writeValueAsString(privateTags)
ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), id)
val eventContent = ExternalSignerUtils.content[id] ?: ""
if (eventContent.isBlank()) return
eventContent
}

var event = if (blockList != null) {
PeopleListEvent.addWord(
earlierVersion = blockList,
word = word,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
)
} else {
PeopleListEvent.createListWithWord(
name = PeopleListEvent.blockList,
word = word,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
)
}

ExternalSignerUtils.openSigner(event)

val eventContent = ExternalSignerUtils.content[event.id] ?: ""
if (eventContent.isBlank()) return
event = PeopleListEvent(
event.id,
event.pubKey,
event.createdAt,
event.tags,
event.content,
eventContent
)

Client.send(event)
LocalCache.consume(event)
} else {
val event = if (blockList != null) {
PeopleListEvent.addWord(
earlierVersion = blockList,
word = word,
isPrivate = true,
privateKey = keyPair.privKey!!
)
} else {
PeopleListEvent.createListWithWord(
name = PeopleListEvent.blockList,
word = word,
isPrivate = true,
privateKey = keyPair.privKey!!
)
}

Client.send(event)
LocalCache.consume(event)
}

live.invalidateData()
saveable.invalidateData()
}

fun showWord(word: String) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())

if (blockList != null) {
if (loginWithExternalSigner) {
val content = blockList.content
val encryptedContent = if (content.isBlank()) {
val privateTags = listOf(listOf("word", word))
val msg = Event.mapper.writeValueAsString(privateTags)

ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), blockList.id)
val eventContent = ExternalSignerUtils.content[blockList.id] ?: ""
if (eventContent.isBlank()) return
eventContent
} else {
var decryptedContent = ExternalSignerUtils.cachedDecryptedContent[blockList.id]
if (decryptedContent == null) {
ExternalSignerUtils.decrypt(blockList.content, keyPair.pubKey.toHexKey(), blockList.id)
val eventContent = ExternalSignerUtils.content[blockList.id] ?: ""
if (eventContent.isBlank()) return
decryptedContent = eventContent
}
val privateTags = blockList.privateTagsOrEmpty(decryptedContent).minus(element = listOf("word", word))
val msg = Event.mapper.writeValueAsString(privateTags)
ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), blockList.id)
val eventContent = ExternalSignerUtils.content[blockList.id] ?: ""
if (eventContent.isBlank()) return
eventContent
}

var event = PeopleListEvent.removeTag(
earlierVersion = blockList,
tag = word,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
)

ExternalSignerUtils.openSigner(event)
val eventContent = ExternalSignerUtils.content[event.id] ?: ""
if (eventContent.isBlank()) return
event = PeopleListEvent.create(event, eventContent)

Client.send(event)
LocalCache.consume(event)
} else {
val event = PeopleListEvent.removeWord(
earlierVersion = blockList,
word = word,
isPrivate = true,
privateKey = keyPair.privKey!!
)

Client.send(event)
LocalCache.consume(event)
}
}

transientHiddenUsers = (transientHiddenUsers - word).toImmutableSet()
live.invalidateData()
saveable.invalidateData()
}

fun hideUser(pubkeyHex: String) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList())
if (loginWithExternalSigner) {
Expand All @@ -2284,7 +2440,7 @@ class Account(
val privateTags = listOf(listOf("p", pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)

ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), "encrypt")
ExternalSignerUtils.encrypt(msg, keyPair.pubKey.toHexKey(), "encrypted")
val encryptedContent = ExternalSignerUtils.content["encrypted"] ?: ""
ExternalSignerUtils.content.remove("encrypted")
if (encryptedContent.isBlank()) return
Expand Down Expand Up @@ -2393,9 +2549,9 @@ class Account(
eventContent
}

var event = PeopleListEvent.addUser(
var event = PeopleListEvent.removeTag(
earlierVersion = blockList,
pubKeyHex = pubkeyHex,
tag = pubkeyHex,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
Expand Down
16 changes: 12 additions & 4 deletions app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt
Original file line number Diff line number Diff line change
Expand Up @@ -673,16 +673,24 @@ open class Note(val idHex: String) {
}

fun isHiddenFor(accountChoices: Account.LiveHiddenUsers): Boolean {
if (event == null) return false
val thisEvent = event ?: return false

val isBoostedNoteHidden = if (event is GenericRepostEvent || event is RepostEvent || event is CommunityPostApprovalEvent) {
val isBoostedNoteHidden = if (thisEvent is GenericRepostEvent || thisEvent is RepostEvent || thisEvent is CommunityPostApprovalEvent) {
replyTo?.lastOrNull()?.isHiddenFor(accountChoices) ?: false
} else {
false
}

val isSensitive = event?.isSensitive() ?: false
return isBoostedNoteHidden ||
val isHiddenByWord = if (thisEvent is BaseTextNoteEvent) {
accountChoices.hiddenWords.any {
thisEvent.content.contains(it, true)
}
} else {
false
}

val isSensitive = thisEvent.isSensitive()
return isBoostedNoteHidden || isHiddenByWord ||
accountChoices.hiddenUsers.contains(author?.pubkeyHex) ||
accountChoices.spammers.contains(author?.pubkeyHex) ||
(isSensitive && accountChoices.showSensitiveContent == false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ class HiddenAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
}
}

class HiddenWordsFeedFilter(val account: Account) : FeedFilter<String>() {
override fun feedKey(): String {
return account.userProfile().pubkeyHex
}

override fun showHiddenKey(): Boolean {
return true
}

override fun feed(): List<String> {
val blockList = account.getBlockList()
val decryptedContent = blockList?.decryptedContent ?: ""
if (account.loginWithExternalSigner) {
if (decryptedContent.isEmpty()) return emptyList()

return blockList
?.publicAndPrivateWords(decryptedContent)?.toList()
?: emptyList()
}

return blockList
?.publicAndPrivateWords(account.keyPair.privKey)?.toList()
?: emptyList()
}
}

class SpammerAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
override fun feedKey(): String {
return account.userProfile().pubkeyHex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ private fun EditStatusBox(baseAccountUser: User, accountViewModel: AccountViewMo
singleLine = true,
trailingIcon = {
if (hasChanged) {
UserStatusSendButton() {
SendButton() {
accountViewModel.createStatus(currentStatus.value)
focusManager.clearFocus(true)
}
Expand Down Expand Up @@ -338,7 +338,7 @@ private fun EditStatusBox(baseAccountUser: User, accountViewModel: AccountViewMo
singleLine = true,
trailingIcon = {
if (hasChanged) {
UserStatusSendButton() {
SendButton() {
accountViewModel.updateStatus(it, thisStatus.value)
focusManager.clearFocus(true)
}
Expand All @@ -356,7 +356,7 @@ private fun EditStatusBox(baseAccountUser: User, accountViewModel: AccountViewMo
}

@Composable
fun UserStatusSendButton(onClick: () -> Unit) {
fun SendButton(onClick: () -> Unit) {
IconButton(
modifier = Size26Modifier,
onClick = onClick
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,7 @@ fun FeedError(errorMessage: String, onRefresh: () -> Unit) {
@Composable
fun FeedEmpty(onRefresh: () -> Unit) {
Column(
Modifier
.fillMaxHeight()
.fillMaxWidth(),
Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.vitorpamplona.amethyst.ui.screen

import androidx.compose.runtime.MutableState
import kotlinx.collections.immutable.ImmutableList

sealed class StringFeedState {
object Loading : StringFeedState()
class Loaded(val feed: MutableState<ImmutableList<String>>) : StringFeedState()
object Empty : StringFeedState()
class FeedError(val errorMessage: String) : StringFeedState()
}

0 comments on commit f4da2ae

Please sign in to comment.