diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt index a7cd5ab0b..1176b793a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt @@ -1,8 +1,8 @@ package com.vitorpamplona.amethyst.ui.actions +import androidx.compose.runtime.Immutable import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.quartz.crypto.KeyPair import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.Nip19 @@ -14,7 +14,7 @@ class NewMessageTagger( var mentions: List? = null, var replyTos: List? = null, var channelHex: String? = null, - var accountViewModel: AccountViewModel + var dao: Dao ) { val directMentions = mutableSetOf() @@ -48,13 +48,13 @@ class NewMessageTagger( val results = parseDirtyWordForKey(word) if (results?.key?.type == Nip19.Type.USER) { - addUserToMentions(accountViewModel.getOrCreateUser(results.key.hex)) + addUserToMentions(dao.getOrCreateUser(results.key.hex)) } else if (results?.key?.type == Nip19.Type.NOTE) { - addNoteToReplyTos(accountViewModel.getOrCreateNote(results.key.hex)) + addNoteToReplyTos(dao.getOrCreateNote(results.key.hex)) } else if (results?.key?.type == Nip19.Type.EVENT) { - addNoteToReplyTos(accountViewModel.getOrCreateNote(results.key.hex)) + addNoteToReplyTos(dao.getOrCreateNote(results.key.hex)) } else if (results?.key?.type == Nip19.Type.ADDRESS) { - val note = accountViewModel.checkGetOrCreateAddressableNote(results.key.hex) + val note = dao.checkGetOrCreateAddressableNote(results.key.hex) if (note != null) { addNoteToReplyTos(note) } @@ -67,19 +67,19 @@ class NewMessageTagger( paragraph.split(' ').map { word: String -> val results = parseDirtyWordForKey(word) if (results?.key?.type == Nip19.Type.USER) { - val user = accountViewModel.getOrCreateUser(results.key.hex) + val user = dao.getOrCreateUser(results.key.hex) "nostr:${user.pubkeyNpub()}${results.restOfWord}" } else if (results?.key?.type == Nip19.Type.NOTE) { - val note = accountViewModel.getOrCreateNote(results.key.hex) + val note = dao.getOrCreateNote(results.key.hex) "nostr:${note.toNEvent()}${results.restOfWord}" } else if (results?.key?.type == Nip19.Type.EVENT) { - val note = accountViewModel.getOrCreateNote(results.key.hex) + val note = dao.getOrCreateNote(results.key.hex) "nostr:${note.toNEvent()}${results.restOfWord}" } else if (results?.key?.type == Nip19.Type.ADDRESS) { - val note = accountViewModel.checkGetOrCreateAddressableNote(results.key.hex) + val note = dao.checkGetOrCreateAddressableNote(results.key.hex) if (note != null) { "nostr:${note.idNote()}${results.restOfWord}" } else { @@ -92,6 +92,7 @@ class NewMessageTagger( }.joinToString("\n") } + @Immutable data class DirtyKeyInfo(val key: Nip19.Return, val restOfWord: String) fun parseDirtyWordForKey(mightBeAKey: String): DirtyKeyInfo? { @@ -156,3 +157,9 @@ class NewMessageTagger( return null } } + +interface Dao { + suspend fun getOrCreateUser(hex: String): User + suspend fun getOrCreateNote(hex: String): Note + suspend fun checkGetOrCreateAddressableNote(hex: String): Note? +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslationConfig.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslationConfig.kt new file mode 100644 index 000000000..c7c2b6501 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslationConfig.kt @@ -0,0 +1,11 @@ +package com.vitorpamplona.amethyst.ui.components + +import androidx.compose.runtime.Immutable + +@Immutable +data class TranslationConfig( + val result: String?, + val sourceLang: String?, + val targetLang: String?, + val showOriginal: Boolean +) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 2759aae2c..8d1bfd41f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.service.OnlineChecker import com.vitorpamplona.amethyst.service.ZapPaymentHandler import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.lang.LanguageTranslatorService +import com.vitorpamplona.amethyst.ui.actions.Dao import com.vitorpamplona.amethyst.ui.components.TranslationConfig import com.vitorpamplona.amethyst.ui.components.UrlPreviewState import com.vitorpamplona.amethyst.ui.note.ZapAmountCommentNotification @@ -55,7 +56,7 @@ import java.math.BigDecimal import java.util.Locale @Stable -class AccountViewModel(val account: Account) : ViewModel() { +class AccountViewModel(val account: Account) : ViewModel(), Dao { val accountLiveData: LiveData = account.live.map { it } val accountLanguagesLiveData: LiveData = account.liveLanguages.map { it } val accountLastReadLiveData: LiveData = account.liveLastRead.map { it } @@ -593,7 +594,7 @@ class AccountViewModel(val account: Account) : ViewModel() { return LocalCache.checkGetOrCreateUser(key) } - suspend fun getOrCreateUser(key: HexKey): User { + override suspend fun getOrCreateUser(key: HexKey): User { return LocalCache.getOrCreateUser(key) } @@ -611,7 +612,7 @@ class AccountViewModel(val account: Account) : ViewModel() { return LocalCache.checkGetOrCreateNote(key) } - suspend fun getOrCreateNote(key: HexKey): Note { + override suspend fun getOrCreateNote(key: HexKey): Note { return LocalCache.getOrCreateNote(key) } @@ -625,7 +626,7 @@ class AccountViewModel(val account: Account) : ViewModel() { return LocalCache.getNoteIfExists(hex) } - suspend fun checkGetOrCreateAddressableNote(key: HexKey): AddressableNote? { + override suspend fun checkGetOrCreateAddressableNote(key: HexKey): AddressableNote? { return LocalCache.checkGetOrCreateAddressableNote(key) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt index 56de8f45f..84d875069 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt @@ -269,7 +269,7 @@ fun ChannelScreen( mentions = listOfNotNull(replyTo.value?.author), replyTos = listOfNotNull(replyTo.value), channelHex = channel.idHex, - accountViewModel = accountViewModel + dao = accountViewModel ) tagger.run() if (channel is PublicChatChannel) { diff --git a/app/src/play/java/com/vitorpamplona/amethyst/ui/components/TranslatableRichTextViewer.kt b/app/src/play/java/com/vitorpamplona/amethyst/ui/components/TranslatableRichTextViewer.kt index f0d4c2da9..0e88a00a2 100644 --- a/app/src/play/java/com/vitorpamplona/amethyst/ui/components/TranslatableRichTextViewer.kt +++ b/app/src/play/java/com/vitorpamplona/amethyst/ui/components/TranslatableRichTextViewer.kt @@ -14,7 +14,6 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.derivedStateOf @@ -41,14 +40,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.Locale -@Immutable -data class TranslationConfig( - val result: String?, - val sourceLang: String?, - val targetLang: String?, - val showOriginal: Boolean -) - @Composable fun TranslatableRichTextViewer( content: String, diff --git a/app/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt b/app/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt index f555f8684..68c28a198 100644 --- a/app/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt +++ b/app/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt @@ -1,5 +1,8 @@ package com.vitorpamplona.amethyst +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.ui.actions.Dao import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger import com.vitorpamplona.quartz.encoders.Nip19 import org.junit.Assert.assertEquals @@ -11,9 +14,23 @@ import org.junit.Test * See [testing documentation](http://d.android.com/tools/testing). */ class NewMessageTaggerKeyParseTest { + val dao: Dao = object : Dao { + override suspend fun getOrCreateUser(hex: String): User { + return User(hex) + } + + override suspend fun getOrCreateNote(hex: String): Note { + return Note(hex) + } + + override suspend fun checkGetOrCreateAddressableNote(hex: String): Note? { + return Note(hex) + } + } + @Test fun keyParseTestNote() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn") assertEquals(Nip19.Type.NOTE, result?.key?.type) assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.key?.hex) assertEquals("", result?.restOfWord) @@ -21,7 +38,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestPub() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z") assertEquals(Nip19.Type.USER, result?.key?.type) assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.key?.hex) assertEquals("", result?.restOfWord) @@ -29,7 +46,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestNoteWithExtraChars() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") assertEquals(Nip19.Type.NOTE, result?.key?.type) assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -37,7 +54,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestPubWithExtraChars() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") assertEquals(Nip19.Type.USER, result?.key?.type) assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -45,7 +62,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestNoteWithExtraCharsAndAt() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("@note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("@note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") assertEquals(Nip19.Type.NOTE, result?.key?.type) assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -53,7 +70,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestPubWithExtraCharsAndAt() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") assertEquals(Nip19.Type.USER, result?.key?.type) assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -61,7 +78,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestNoteWithExtraCharsAndNostrPrefix() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") assertEquals(Nip19.Type.NOTE, result?.key?.type) assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -69,7 +86,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestPubWithExtraCharsAndNostrPrefix() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("nostr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("nostr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") assertEquals(Nip19.Type.USER, result?.key?.type) assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -77,7 +94,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestUppercaseNoteWithExtraCharsAndNostrPrefix() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("Nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("Nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") assertEquals(Nip19.Type.NOTE, result?.key?.type) assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.key?.hex) assertEquals(",", result?.restOfWord) @@ -85,7 +102,7 @@ class NewMessageTaggerKeyParseTest { @Test fun keyParseTestUppercasePubWithExtraCharsAndNostrPrefix() { - val result = NewMessageTagger(message = "").parseDirtyWordForKey("nOstr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") + val result = NewMessageTagger(message = "", dao = dao).parseDirtyWordForKey("nOstr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,") assertEquals(Nip19.Type.USER, result?.key?.type) assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.key?.hex) assertEquals(",", result?.restOfWord)