diff --git a/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt index 891303243..47d5aad06 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt @@ -1,6 +1,5 @@ package com.vitorpamplona.amethyst -import android.content.Context import androidx.lifecycle.LiveData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -14,7 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean object NotificationCache { val lastReadByRoute = mutableMapOf() - fun markAsRead(route: String, timestampInSecs: Long, context: Context) { + fun markAsRead(route: String, timestampInSecs: Long) { val lastTime = lastReadByRoute[route] if (lastTime == null || timestampInSecs > lastTime) { lastReadByRoute.put(route, timestampInSecs) @@ -27,7 +26,7 @@ object NotificationCache { } } - fun load(route: String, context: Context): Long { + fun load(route: String): Long { var lastTime = lastReadByRoute[route] if (lastTime == null) { lastTime = LocalPreferences.loadLastRead(route) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 42d631421..268366c8d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -23,6 +23,7 @@ import com.vitorpamplona.amethyst.service.relays.FeedType import com.vitorpamplona.amethyst.service.relays.Relay import com.vitorpamplona.amethyst.service.relays.RelayPool import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job @@ -48,6 +49,7 @@ fun getLanguagesSpokenByUser(): Set { return codedList } +@OptIn(DelicateCoroutinesApi::class) class Account( val loggedIn: Persona, var followingChannels: Set = DefaultChannels, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 034d5fb7d..91e8f9ffd 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -283,8 +283,9 @@ object LocalCache { refreshObservers() } + @Suppress("UNUSED_PARAMETER") fun consume(event: RecommendRelayEvent) { - // Log.d("RR", event.toJson()) +// // Log.d("RR", event.toJson()) } fun consume(event: ContactListEvent) { @@ -542,9 +543,11 @@ object LocalCache { refreshObservers() } + @Suppress("UNUSED_PARAMETER") fun consume(event: ChannelHideMessageEvent) { } + @Suppress("UNUSED_PARAMETER") fun consume(event: ChannelMuteUserEvent) { } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt index d8b01a019..00b84d565 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt @@ -7,6 +7,7 @@ import com.vitorpamplona.amethyst.service.model.TextNoteEvent import com.vitorpamplona.amethyst.service.relays.FeedType import com.vitorpamplona.amethyst.service.relays.JsonFilter import com.vitorpamplona.amethyst.service.relays.TypedFilter +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -18,6 +19,7 @@ object NostrHomeDataSource : NostrDataSource("HomeFeed") { invalidateFilters() } + @OptIn(DelicateCoroutinesApi::class) override fun start() { if (this::account.isInitialized) { GlobalScope.launch(Dispatchers.Main) { @@ -27,6 +29,7 @@ object NostrHomeDataSource : NostrDataSource("HomeFeed") { super.start() } + @OptIn(DelicateCoroutinesApi::class) override fun stop() { super.stop() if (this::account.isInitialized) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt index 7beaf1777..801f9e30c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt @@ -133,9 +133,9 @@ class LightningAddressResolver { fetchLightningAddressJson( lnaddress, - onSuccess = { + onSuccess = { lnAddressJson -> val lnurlp = try { - mapper.readTree(it) + mapper.readTree(lnAddressJson) } catch (t: Throwable) { onError("Error Parsing JSON from Lightning Address. Check the user's lightning setup") null @@ -149,9 +149,9 @@ class LightningAddressResolver { val allowsNostr = lnurlp?.get("allowsNostr")?.asBoolean() ?: false - callback?.let { callback -> + callback?.let { cb -> fetchLightningInvoice( - callback, + cb, milliSats, message, if (allowsNostr) nostrRequest else null, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelHideMessageEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelHideMessageEvent.kt index 1a8481854..5de80f0b6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelHideMessageEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelHideMessageEvent.kt @@ -18,17 +18,16 @@ class ChannelHideMessageEvent( companion object { const val kind = 43 - fun create(reason: String, messagesToHide: List?, mentions: List?, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ChannelHideMessageEvent { - val content = reason + fun create(reason: String, messagesToHide: List?, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ChannelHideMessageEvent { val pubKey = Utils.pubkeyCreate(privateKey).toHexKey() val tags = messagesToHide?.map { listOf("e", it) } ?: emptyList() - val id = generateId(pubKey, createdAt, kind, tags, content) + val id = generateId(pubKey, createdAt, kind, tags, reason) val sig = Utils.sign(id, privateKey) - return ChannelHideMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) + return ChannelHideMessageEvent(id.toHexKey(), pubKey, createdAt, tags, reason, sig.toHexKey()) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/MetadataEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/MetadataEvent.kt index 1b57e095e..7cec19bca 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/MetadataEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/MetadataEvent.kt @@ -28,9 +28,7 @@ abstract class IdentityClaim( companion object { fun create(platformIdentity: String, proof: String): IdentityClaim? { - val platformIdentity = platformIdentity.split(':') - val platform = platformIdentity[0] - val identity = platformIdentity[1] + val (platform, identity) = platformIdentity.split(':') return when (platform.lowercase()) { GitHubIdentity.platform -> GitHubIdentity(identity, proof) @@ -169,16 +167,16 @@ class MetadataEvent( } fun create(contactMetaData: String, identities: List, privateKey: ByteArray, createdAt: Long = Date().time / 1000): MetadataEvent { - val content = contactMetaData val pubKey = Utils.pubkeyCreate(privateKey).toHexKey() val tags = mutableListOf>() - identities?.forEach { + + identities.forEach { tags.add(listOf("i", it.platformIdentity(), it.proof)) } - val id = generateId(pubKey, createdAt, kind, tags, content) + val id = generateId(pubKey, createdAt, kind, tags, contactMetaData) val sig = Utils.sign(id, privateKey) - return MetadataEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) + return MetadataEvent(id.toHexKey(), pubKey, createdAt, tags, contactMetaData, sig.toHexKey()) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt index 4b2021c26..1920085e0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt @@ -19,9 +19,9 @@ class ReportEvent( private fun defaultReportType(): ReportType { // Works with old and new structures for report. - var reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.toUpperCase()) }.firstOrNull() + var reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.uppercase()) }.firstOrNull() if (reportType == null) { - reportType = tags.mapNotNull { it.getOrNull(2) }.map { ReportType.valueOf(it.toUpperCase()) }.firstOrNull() + reportType = tags.mapNotNull { it.getOrNull(2) }.map { ReportType.valueOf(it.uppercase()) }.firstOrNull() } if (reportType == null) { reportType = ReportType.SPAM @@ -34,7 +34,7 @@ class ReportEvent( .map { ReportedKey( it[1], - it.getOrNull(2)?.toUpperCase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() + it.getOrNull(2)?.uppercase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() ) } @@ -43,7 +43,7 @@ class ReportEvent( .map { ReportedKey( it[1], - it.getOrNull(2)?.toUpperCase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() + it.getOrNull(2)?.uppercase()?.let { it1 -> ReportType.valueOf(it1) } ?: defaultReportType() ) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt index 76d098c74..6ea8815e7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt @@ -2,6 +2,7 @@ package com.vitorpamplona.amethyst.service.relays import com.vitorpamplona.amethyst.service.model.Event import com.vitorpamplona.amethyst.service.model.EventInterface +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -78,6 +79,7 @@ object Client : RelayPool.Listener { RelayPool.unloadRelays() } + @OptIn(DelicateCoroutinesApi::class) override fun onEvent(event: Event, subscriptionId: String, relay: Relay) { // Releases the Web thread for the new payload. // May need to add a processing queue if processing new events become too costly. @@ -86,6 +88,7 @@ object Client : RelayPool.Listener { } } + @OptIn(DelicateCoroutinesApi::class) override fun onError(error: Error, subscriptionId: String, relay: Relay) { // Releases the Web thread for the new payload. // May need to add a processing queue if processing new events become too costly. @@ -94,6 +97,7 @@ object Client : RelayPool.Listener { } } + @OptIn(DelicateCoroutinesApi::class) override fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) { // Releases the Web thread for the new payload. // May need to add a processing queue if processing new events become too costly. @@ -102,6 +106,7 @@ object Client : RelayPool.Listener { } } + @OptIn(DelicateCoroutinesApi::class) override fun onSendResponse(eventId: String, success: Boolean, message: String, relay: Relay) { // Releases the Web thread for the new payload. // May need to add a processing queue if processing new events become too costly. diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt index d52a1d11c..eb6f08154 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt @@ -27,13 +27,13 @@ class TypedFilter( fun filterToJson(filter: JsonFilter): JsonObject { val jsonObject = JsonObject() filter.ids?.run { - jsonObject.add("ids", JsonArray().apply { filter.ids?.forEach { add(it) } }) + jsonObject.add("ids", JsonArray().apply { filter.ids.forEach { add(it) } }) } filter.authors?.run { - jsonObject.add("authors", JsonArray().apply { filter.authors?.forEach { add(it) } }) + jsonObject.add("authors", JsonArray().apply { filter.authors.forEach { add(it) } }) } filter.kinds?.run { - jsonObject.add("kinds", JsonArray().apply { filter.kinds?.forEach { add(it) } }) + jsonObject.add("kinds", JsonArray().apply { filter.kinds.forEach { add(it) } }) } filter.tags?.run { entries.forEach { kv -> diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 0cd9b18dd..0b8a19a57 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -21,6 +21,7 @@ import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.screen.AccountScreen import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel import com.vitorpamplona.amethyst.ui.theme.AmethystTheme +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -67,6 +68,7 @@ class MainActivity : FragmentActivity() { Client.lenient = true } + @OptIn(DelicateCoroutinesApi::class) override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt index 7f3666703..ef763f8e6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt @@ -3,12 +3,11 @@ package com.vitorpamplona.amethyst.ui.actions import android.content.ContentResolver import android.content.ContentValues import android.content.Context -import android.content.Intent +import android.media.MediaScannerConnection import android.os.Build import android.os.Environment import android.provider.MediaStore import androidx.annotation.RequiresApi -import androidx.core.net.toUri import okhttp3.* import okio.BufferedSource import okio.IOException @@ -135,12 +134,7 @@ object ImageSaver { // Call the media scanner manually, so the image // appears in the gallery faster. - context.sendBroadcast( - Intent( - Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, - outputFile.toUri() - ) - ) + MediaScannerConnection.scanFile(context, arrayOf(outputFile.toString()), null, null) } private const val PICTURES_SUBDIRECTORY = "Amethyst" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelView.kt index bc8bb5a0f..55ec22a7c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelView.kt @@ -16,7 +16,6 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.style.TextDirection @@ -31,8 +30,6 @@ import com.vitorpamplona.amethyst.model.Channel @Composable fun NewChannelView(onClose: () -> Unit, account: Account, channel: Channel? = null) { val postViewModel: NewChannelViewModel = viewModel() - val context = LocalContext.current.applicationContext - postViewModel.load(account, channel) Dialog( @@ -58,7 +55,7 @@ fun NewChannelView(onClose: () -> Unit, account: Account, channel: Channel? = nu PostButton( onPost = { - postViewModel.create(context) + postViewModel.create() onClose() }, postViewModel.channelName.value.text.isNotBlank() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelViewModel.kt index bd68bc7cb..96ba1afe3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewChannelViewModel.kt @@ -1,6 +1,5 @@ package com.vitorpamplona.amethyst.ui.actions -import android.content.Context import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel @@ -25,7 +24,7 @@ class NewChannelViewModel : ViewModel() { } } - fun create(context: Context) { + fun create() { this.account?.let { account -> if (originalChannel == null) { account.sendCreateNewChannel( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index 40d517fd1..805362dd7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -208,7 +208,7 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n itemsIndexed( userSuggestions, key = { _, item -> item.pubkeyHex } - ) { index, item -> + ) { _, item -> UserLine(item, account) { postViewModel.autocompleteWithUser(item) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt index c96ba3b56..ba64aa835 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt @@ -40,7 +40,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow @@ -58,12 +57,10 @@ import java.lang.Math.round @Composable fun NewRelayListView(onClose: () -> Unit, account: Account, relayToAdd: String = "") { val postViewModel: NewRelayListViewModel = viewModel() - val ctx = LocalContext.current.applicationContext - val feedState by postViewModel.relays.collectAsState() LaunchedEffect(Unit) { - postViewModel.load(account, ctx) + postViewModel.load(account) } Dialog( @@ -83,13 +80,13 @@ fun NewRelayListView(onClose: () -> Unit, account: Account, relayToAdd: String = verticalAlignment = Alignment.CenterVertically ) { CloseButton(onCancel = { - postViewModel.clear(ctx) + postViewModel.clear() onClose() }) PostButton( onPost = { - postViewModel.create(ctx) + postViewModel.create() onClose() }, true diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListViewModel.kt index d4422143a..cafe4d200 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListViewModel.kt @@ -1,6 +1,5 @@ package com.vitorpamplona.amethyst.ui.actions -import android.content.Context import androidx.lifecycle.ViewModel import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.RelaySetupInfo @@ -18,20 +17,20 @@ class NewRelayListViewModel : ViewModel() { private val _relays = MutableStateFlow>(emptyList()) val relays = _relays.asStateFlow() - fun load(account: Account, ctx: Context) { + fun load(account: Account) { this.account = account - clear(ctx) + clear() } - fun create(ctx: Context) { + fun create() { relays.let { account.saveRelayList(it.value) } - clear(ctx) + clear() } - fun clear(ctx: Context) { + fun clear() { _relays.update { var relayFile = account.userProfile().latestContactList?.relays() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt index ed19bcc92..a1fc45052 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt @@ -218,7 +218,7 @@ fun TagLink(word: String, tags: List>, canPreview: Boolean, backgro val index = try { matcher.find() - matcher.group(1).toInt() + matcher.group(1)?.toInt() } catch (e: Exception) { println("Couldn't link tag $word") null diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslateableRichTextViewer.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslateableRichTextViewer.kt index 2c11013ca..ef96b08a4 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslateableRichTextViewer.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/TranslateableRichTextViewer.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString @@ -60,8 +59,6 @@ fun TranslateableRichTextViewer( var showOriginal by remember { mutableStateOf(false) } var langSettingsPopupExpanded by remember { mutableStateOf(false) } - val context = LocalContext.current - val accountState by accountViewModel.accountLanguagesLiveData.observeAsState() val account = accountState?.account ?: return @@ -154,7 +151,7 @@ fun TranslateableRichTextViewer( onDismissRequest = { langSettingsPopupExpanded = false } ) { DropdownMenuItem(onClick = { - accountViewModel.dontTranslateFrom(source, context) + accountViewModel.dontTranslateFrom(source) langSettingsPopupExpanded = false }) { if (source in account.dontTranslateFrom) { @@ -169,7 +166,7 @@ fun TranslateableRichTextViewer( Spacer(modifier = Modifier.size(10.dp)) - Text(stringResource(R.string.never_translate_from) + "${Locale(source).displayName}") + Text(stringResource(R.string.never_translate_from) + Locale(source).displayName) } Divider() DropdownMenuItem(onClick = { @@ -223,11 +220,11 @@ fun TranslateableRichTextViewer( Divider() val languageList = - ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration()) + ConfigurationCompat.getLocales(Resources.getSystem().configuration) for (i in 0 until languageList.size()) { languageList.get(i)?.let { lang -> DropdownMenuItem(onClick = { - accountViewModel.translateTo(lang, context) + accountViewModel.translateTo(lang) langSettingsPopupExpanded = false }) { if (lang.language in account.translateTo) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/UrlPreview.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/UrlPreview.kt index 2693f4a6f..9405c5362 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/UrlPreview.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/UrlPreview.kt @@ -18,14 +18,14 @@ import kotlinx.coroutines.withContext @Composable fun UrlPreview(url: String, urlText: String) { - val default = UrlCachedPreviewer.cache[url]?.let { - if (it.url == url) { - UrlPreviewState.Loaded(it) - } else { - UrlPreviewState.Empty - } - } ?: UrlPreviewState.Loading - var context = LocalContext.current +// val default = UrlCachedPreviewer.cache[url]?.let { +// if (it.url == url) { +// UrlPreviewState.Loaded(it) +// } else { +// UrlPreviewState.Empty +// } +// } ?: UrlPreviewState.Loading + val context = LocalContext.current var urlPreviewState by remember { mutableStateOf(UrlPreviewState.Loading) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableAsyncImage.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableAsyncImage.kt index b213c6399..a55282ce0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableAsyncImage.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableAsyncImage.kt @@ -1,9 +1,9 @@ package com.vitorpamplona.amethyst.ui.components +import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.gestures.calculatePan import androidx.compose.foundation.gestures.calculateZoom -import androidx.compose.foundation.gestures.forEachGesture import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -32,17 +32,15 @@ fun ZoomableAsyncImage(imageUrl: String) { horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .pointerInput(Unit) { - forEachGesture { - awaitPointerEventScope { - awaitFirstDown() - do { - val event = awaitPointerEvent() - scale *= event.calculateZoom() - val offset = event.calculatePan() - offsetX += offset.x - offsetY += offset.y - } while (event.changes.any { it.pressed }) - } + awaitEachGesture { + awaitFirstDown() + do { + val event = awaitPointerEvent() + scale *= event.calculateZoom() + val offset = event.calculatePan() + offsetX += offset.x + offsetY += offset.y + } while (event.changes.any { it.pressed }) } } ) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt index eeb90bdcc..ceb663192 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AccountSwitchBottomSheet.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -60,9 +59,7 @@ fun AccountSwitchBottomSheet( accountViewModel: AccountViewModel, accountStateViewModel: AccountStateViewModel ) { - val context = LocalContext.current val accounts = LocalPreferences.allSavedAccounts() - val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppBottomBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppBottomBar.kt index 5d68ddba0..e275cf4f6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppBottomBar.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppBottomBar.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign @@ -141,7 +140,7 @@ private fun NotifiableIcon(route: Route, selected: Boolean, accountViewModel: Ac Box(Modifier.size(if ("Home" == route.base) 25.dp else 23.dp)) { Icon( painter = painterResource(id = route.icon), - null, + contentDescription = null, modifier = Modifier.size(if ("Home" == route.base) 24.dp else 20.dp), tint = if (selected) MaterialTheme.colors.primary else Color.Unspecified ) @@ -158,17 +157,15 @@ private fun NotifiableIcon(route: Route, selected: Boolean, accountViewModel: Ac var hasNewItems by remember { mutableStateOf(false) } - val context = LocalContext.current.applicationContext - LaunchedEffect(key1 = notif) { withContext(Dispatchers.IO) { - hasNewItems = route.hasNewItems(account, notif.cache, context) + hasNewItems = route.hasNewItems(account, notif.cache) } } LaunchedEffect(key1 = db) { withContext(Dispatchers.IO) { - hasNewItems = route.hasNewItems(account, notif.cache, context) + hasNewItems = route.hasNewItems(account, notif.cache) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index 95f475004..48dca0bc6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -12,7 +12,6 @@ import com.google.accompanist.pager.rememberPagerState import com.vitorpamplona.amethyst.ui.dal.GlobalFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter -import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel import com.vitorpamplona.amethyst.ui.screen.NostrGlobalFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel @@ -32,7 +31,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.ThreadScreen fun AppNavigation( navController: NavHostController, accountViewModel: AccountViewModel, - accountStateViewModel: AccountStateViewModel, nextPage: String? = null ) { val accountState by accountViewModel.accountLiveData.observeAsState() @@ -111,7 +109,6 @@ fun AppNavigation( ChannelScreen( channelId = it.arguments?.getString("id"), accountViewModel = accountViewModel, - accountStateViewModel = accountStateViewModel, navController = navController ) }) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt index eed7bfd60..299ea57ed 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt @@ -1,253 +1,252 @@ -package com.vitorpamplona.amethyst.ui.navigation - -import android.util.Log -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Divider -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme -import androidx.compose.material.ScaffoldState -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -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.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavHostController -import coil.Coil -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.service.NostrAccountDataSource -import com.vitorpamplona.amethyst.service.NostrChannelDataSource -import com.vitorpamplona.amethyst.service.NostrChatroomDataSource -import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource -import com.vitorpamplona.amethyst.service.NostrGlobalDataSource -import com.vitorpamplona.amethyst.service.NostrHomeDataSource -import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource -import com.vitorpamplona.amethyst.service.NostrSingleChannelDataSource -import com.vitorpamplona.amethyst.service.NostrSingleEventDataSource -import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource -import com.vitorpamplona.amethyst.service.NostrThreadDataSource -import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource -import com.vitorpamplona.amethyst.service.relays.Client -import com.vitorpamplona.amethyst.service.relays.RelayPool -import com.vitorpamplona.amethyst.ui.actions.NewRelayListView -import com.vitorpamplona.amethyst.ui.components.ResizeImage -import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy -import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import kotlinx.coroutines.launch - -@Composable -fun AppTopBar(navController: NavHostController, scaffoldState: ScaffoldState, accountViewModel: AccountViewModel) { - when (currentRoute(navController)) { - // Route.Profile.route -> TopBarWithBackButton(navController) - else -> MainTopBar(scaffoldState, accountViewModel) - } -} - -@Composable -fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel) { - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account ?: return - - val accountUserState by account.userProfile().live().metadata.observeAsState() - val accountUser = accountUserState?.user ?: return - - val relayViewModel: RelayPoolViewModel = viewModel { RelayPoolViewModel() } - val connectedRelaysLiveData by relayViewModel.connectedRelaysLiveData.observeAsState() - val availableRelaysLiveData by relayViewModel.availableRelaysLiveData.observeAsState() - - val coroutineScope = rememberCoroutineScope() - - val context = LocalContext.current - val ctx = LocalContext.current.applicationContext - - var wantsToEditRelays by remember { - mutableStateOf(false) - } - - if (wantsToEditRelays) { - NewRelayListView({ wantsToEditRelays = false }, account) - } - - Column() { - TopAppBar( - elevation = 0.dp, - backgroundColor = Color(0xFFFFFF), - title = { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Box(Modifier) { - Column( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .padding(start = 0.dp, end = 20.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - IconButton( - onClick = { - Client.allSubscriptions().map { - "$it ${ - Client.getSubscriptionFilters(it) - .joinToString { it.filter.toJson() } - }" - }.forEach { - Log.d("STATE DUMP", it) - } - - NostrAccountDataSource.printCounter() - NostrChannelDataSource.printCounter() - NostrChatroomDataSource.printCounter() - NostrChatroomListDataSource.printCounter() - - NostrGlobalDataSource.printCounter() - NostrHomeDataSource.printCounter() - - NostrSingleEventDataSource.printCounter() - NostrSearchEventOrUserDataSource.printCounter() - NostrSingleChannelDataSource.printCounter() - NostrSingleUserDataSource.printCounter() - NostrThreadDataSource.printCounter() - - NostrUserProfileDataSource.printCounter() - - Log.d("STATE DUMP", "Connected Relays: " + RelayPool.connectedRelays()) - - val imageLoader = Coil.imageLoader(context) - Log.d("STATE DUMP", "Image Disk Cache ${(imageLoader.diskCache?.size ?: 0) / (1024 * 1024)}/${(imageLoader.diskCache?.maxSize ?: 0) / (1024 * 1024)} MB") - Log.d("STATE DUMP", "Image Memory Cache ${(imageLoader.memoryCache?.size ?: 0) / (1024 * 1024)}/${(imageLoader.memoryCache?.maxSize ?: 0) / (1024 * 1024)} MB") - - Log.d("STATE DUMP", "Notes: " + LocalCache.notes.filter { it.value.event != null }.size + "/" + LocalCache.notes.size) - Log.d("STATE DUMP", "Users: " + LocalCache.users.filter { it.value.info?.latestMetadata != null }.size + "/" + LocalCache.users.size) - } - ) { - Icon( - painter = painterResource(R.drawable.amethyst), - null, - modifier = Modifier.size(40.dp), - tint = Color.Unspecified - ) - } - } - - Column( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight(), - horizontalAlignment = Alignment.End - - ) { - Row( - modifier = Modifier.fillMaxHeight(), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - "${connectedRelaysLiveData ?: "--"}/${availableRelaysLiveData ?: "--"}", - color = if (connectedRelaysLiveData == 0) Color.Red else MaterialTheme.colors.onSurface.copy(alpha = 0.32f), - style = MaterialTheme.typography.subtitle1, - modifier = Modifier.clickable( - onClick = { - wantsToEditRelays = true - } - ) - ) - } - } - } - } - }, - navigationIcon = { - IconButton( - onClick = { - coroutineScope.launch { - scaffoldState.drawerState.open() - } - }, - modifier = Modifier - ) { - RobohashAsyncImageProxy( - robot = accountUser.pubkeyHex, - model = ResizeImage(accountUser.profilePicture(), 34.dp), - contentDescription = stringResource(id = R.string.profile_image), - modifier = Modifier - .width(34.dp) - .height(34.dp) - .clip(shape = CircleShape) - ) - } - }, - actions = { - IconButton( - onClick = { wantsToEditRelays = true }, - modifier = Modifier - ) { - Icon( - painter = painterResource(R.drawable.ic_trends), - null, - modifier = Modifier.size(24.dp), - tint = Color.Unspecified - ) - } - } - ) - Divider(thickness = 0.25.dp) - } -} - -@Composable -fun TopBarWithBackButton(navController: NavHostController) { - Column() { - TopAppBar( - elevation = 0.dp, - backgroundColor = Color(0xFFFFFF), - title = {}, - navigationIcon = { - IconButton( - onClick = { - navController.popBackStack() - }, - modifier = Modifier - ) { - Icon( - imageVector = Icons.Filled.ArrowBack, - null, - modifier = Modifier.size(28.dp), - tint = MaterialTheme.colors.primary - ) - } - }, - actions = {} - ) - Divider(thickness = 0.25.dp) - } -} +package com.vitorpamplona.amethyst.ui.navigation + +import android.util.Log +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Divider +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.ScaffoldState +import androidx.compose.material.Text +import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +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.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavHostController +import coil.Coil +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.service.NostrAccountDataSource +import com.vitorpamplona.amethyst.service.NostrChannelDataSource +import com.vitorpamplona.amethyst.service.NostrChatroomDataSource +import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource +import com.vitorpamplona.amethyst.service.NostrGlobalDataSource +import com.vitorpamplona.amethyst.service.NostrHomeDataSource +import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource +import com.vitorpamplona.amethyst.service.NostrSingleChannelDataSource +import com.vitorpamplona.amethyst.service.NostrSingleEventDataSource +import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource +import com.vitorpamplona.amethyst.service.NostrThreadDataSource +import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource +import com.vitorpamplona.amethyst.service.relays.Client +import com.vitorpamplona.amethyst.service.relays.RelayPool +import com.vitorpamplona.amethyst.ui.actions.NewRelayListView +import com.vitorpamplona.amethyst.ui.components.ResizeImage +import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy +import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import kotlinx.coroutines.launch + +@Composable +fun AppTopBar(navController: NavHostController, scaffoldState: ScaffoldState, accountViewModel: AccountViewModel) { + when (currentRoute(navController)) { + // Route.Profile.route -> TopBarWithBackButton(navController) + else -> MainTopBar(scaffoldState, accountViewModel) + } +} + +@OptIn(coil.annotation.ExperimentalCoilApi::class) +@Composable +fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel) { + val accountState by accountViewModel.accountLiveData.observeAsState() + val account = accountState?.account ?: return + + val accountUserState by account.userProfile().live().metadata.observeAsState() + val accountUser = accountUserState?.user ?: return + + val relayViewModel: RelayPoolViewModel = viewModel { RelayPoolViewModel() } + val connectedRelaysLiveData by relayViewModel.connectedRelaysLiveData.observeAsState() + val availableRelaysLiveData by relayViewModel.availableRelaysLiveData.observeAsState() + + val coroutineScope = rememberCoroutineScope() + + val context = LocalContext.current + + var wantsToEditRelays by remember { + mutableStateOf(false) + } + + if (wantsToEditRelays) { + NewRelayListView({ wantsToEditRelays = false }, account) + } + + Column() { + TopAppBar( + elevation = 0.dp, + title = { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box(Modifier) { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(start = 0.dp, end = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + IconButton( + onClick = { + Client.allSubscriptions().map { + "$it ${ + Client.getSubscriptionFilters(it) + .joinToString { it.filter.toJson() } + }" + }.forEach { + Log.d("STATE DUMP", it) + } + + NostrAccountDataSource.printCounter() + NostrChannelDataSource.printCounter() + NostrChatroomDataSource.printCounter() + NostrChatroomListDataSource.printCounter() + + NostrGlobalDataSource.printCounter() + NostrHomeDataSource.printCounter() + + NostrSingleEventDataSource.printCounter() + NostrSearchEventOrUserDataSource.printCounter() + NostrSingleChannelDataSource.printCounter() + NostrSingleUserDataSource.printCounter() + NostrThreadDataSource.printCounter() + + NostrUserProfileDataSource.printCounter() + + Log.d("STATE DUMP", "Connected Relays: " + RelayPool.connectedRelays()) + + val imageLoader = Coil.imageLoader(context) + Log.d("STATE DUMP", "Image Disk Cache ${(imageLoader.diskCache?.size ?: 0) / (1024 * 1024)}/${(imageLoader.diskCache?.maxSize ?: 0) / (1024 * 1024)} MB") + Log.d("STATE DUMP", "Image Memory Cache ${(imageLoader.memoryCache?.size ?: 0) / (1024 * 1024)}/${(imageLoader.memoryCache?.maxSize ?: 0) / (1024 * 1024)} MB") + + Log.d("STATE DUMP", "Notes: " + LocalCache.notes.filter { it.value.event != null }.size + "/" + LocalCache.notes.size) + Log.d("STATE DUMP", "Users: " + LocalCache.users.filter { it.value.info?.latestMetadata != null }.size + "/" + LocalCache.users.size) + } + ) { + Icon( + painter = painterResource(R.drawable.amethyst), + null, + modifier = Modifier.size(40.dp), + tint = Color.Unspecified + ) + } + } + + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + horizontalAlignment = Alignment.End + + ) { + Row( + modifier = Modifier.fillMaxHeight(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + "${connectedRelaysLiveData ?: "--"}/${availableRelaysLiveData ?: "--"}", + color = if (connectedRelaysLiveData == 0) Color.Red else MaterialTheme.colors.onSurface.copy(alpha = 0.32f), + style = MaterialTheme.typography.subtitle1, + modifier = Modifier.clickable( + onClick = { + wantsToEditRelays = true + } + ) + ) + } + } + } + } + }, + navigationIcon = { + IconButton( + onClick = { + coroutineScope.launch { + scaffoldState.drawerState.open() + } + }, + modifier = Modifier + ) { + RobohashAsyncImageProxy( + robot = accountUser.pubkeyHex, + model = ResizeImage(accountUser.profilePicture(), 34.dp), + contentDescription = stringResource(id = R.string.profile_image), + modifier = Modifier + .width(34.dp) + .height(34.dp) + .clip(shape = CircleShape) + ) + } + }, + actions = { + IconButton( + onClick = { wantsToEditRelays = true }, + modifier = Modifier + ) { + Icon( + painter = painterResource(R.drawable.ic_trends), + null, + modifier = Modifier.size(24.dp), + tint = Color.Unspecified + ) + } + } + ) + Divider(thickness = 0.25.dp) + } +} + +@Composable +fun TopBarWithBackButton(navController: NavHostController) { + Column() { + TopAppBar( + elevation = 0.dp, + backgroundColor = Color(0xFFFFFF), + title = {}, + navigationIcon = { + IconButton( + onClick = { + navController.popBackStack() + }, + modifier = Modifier + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + null, + modifier = Modifier.size(28.dp), + tint = MaterialTheme.colors.primary + ) + } + }, + actions = {} + ) + Divider(thickness = 0.25.dp) + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt index 2c6146e9e..97a2d883d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -110,11 +109,9 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol val accountUserFollowsState by baseAccountUser.live().follows.observeAsState() val accountUserFollows = accountUserFollowsState?.user ?: return - val ctx = LocalContext.current.applicationContext - Box { val banner = accountUser.info?.banner - if (banner != null && banner.isNotBlank()) { + if (!banner.isNullOrBlank()) { AsyncImage( model = banner, contentDescription = stringResource(id = R.string.profile_image), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt index 3ee743e87..2d9b45224 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt @@ -1,6 +1,5 @@ package com.vitorpamplona.amethyst.ui.navigation -import android.content.Context import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.navigation.NamedNavArgument @@ -18,7 +17,7 @@ import com.vitorpamplona.amethyst.ui.dal.NotificationFeedFilter sealed class Route( val route: String, val icon: Int, - val hasNewItems: (Account, NotificationCache, Context) -> Boolean = { _, _, _ -> false }, + val hasNewItems: (Account, NotificationCache) -> Boolean = { _, _ -> false }, val arguments: List = emptyList() ) { val base: String @@ -28,7 +27,7 @@ sealed class Route( route = "Home?scrollToTop={scrollToTop}", icon = R.drawable.ic_home, arguments = listOf(navArgument("scrollToTop") { type = NavType.BoolType; defaultValue = false }), - hasNewItems = { accountViewModel, cache, context -> homeHasNewItems(accountViewModel, cache, context) } + hasNewItems = { accountViewModel, cache -> homeHasNewItems(accountViewModel, cache) } ) object Search : Route( @@ -40,17 +39,13 @@ sealed class Route( object Notification : Route( route = "Notification", icon = R.drawable.ic_notifications, - hasNewItems = { accountViewModel, cache, context -> - notificationHasNewItems(accountViewModel, cache, context) - } + hasNewItems = { accountViewModel, cache -> notificationHasNewItems(accountViewModel, cache) } ) object Message : Route( route = "Message", icon = R.drawable.ic_dm, - hasNewItems = { accountViewModel, cache, context -> - messagesHasNewItems(accountViewModel, cache, context) - } + hasNewItems = { accountViewModel, cache -> messagesHasNewItems(accountViewModel, cache) } ) object Filters : Route( @@ -92,8 +87,8 @@ fun currentRoute(navController: NavHostController): String? { return navBackStackEntry?.destination?.route } -private fun homeHasNewItems(account: Account, cache: NotificationCache, context: Context): Boolean { - val lastTime = cache.load("HomeFollows", context) +private fun homeHasNewItems(account: Account, cache: NotificationCache): Boolean { + val lastTime = cache.load("HomeFollows") HomeNewThreadFeedFilter.account = account @@ -103,12 +98,8 @@ private fun homeHasNewItems(account: Account, cache: NotificationCache, context: ) > lastTime } -private fun notificationHasNewItems( - account: Account, - cache: NotificationCache, - context: Context -): Boolean { - val lastTime = cache.load("Notification", context) +private fun notificationHasNewItems(account: Account, cache: NotificationCache): Boolean { + val lastTime = cache.load("Notification") NotificationFeedFilter.account = account @@ -118,18 +109,14 @@ private fun notificationHasNewItems( ) > lastTime } -private fun messagesHasNewItems( - account: Account, - cache: NotificationCache, - context: Context -): Boolean { +private fun messagesHasNewItems(account: Account, cache: NotificationCache): Boolean { ChatroomListKnownFeedFilter.account = account val note = ChatroomListKnownFeedFilter.feed().firstOrNull { it.createdAt() != null && it.channel() == null && it.author != account.userProfile() } ?: return false - val lastTime = cache.load("Room/${note.author?.pubkeyHex}", context) + val lastTime = cache.load("Room/${note.author?.pubkeyHex}") return (note.createdAt() ?: 0) > lastTime } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BadgeCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BadgeCompose.kt index 9901856a7..5e4fef8b2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BadgeCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BadgeCompose.kt @@ -42,13 +42,10 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalFoundationApi::class) @Composable -fun BadgeCompose(likeSetCard: BadgeCard, modifier: Modifier = Modifier, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { +fun BadgeCompose(likeSetCard: BadgeCard, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { val noteState by likeSetCard.note.live().metadata.observeAsState() val note = noteState?.note - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account ?: return - val context = LocalContext.current.applicationContext val noteEvent = note?.event @@ -61,13 +58,13 @@ fun BadgeCompose(likeSetCard: BadgeCard, modifier: Modifier = Modifier, isInnerN LaunchedEffect(key1 = likeSetCard) { withContext(Dispatchers.IO) { - isNew = likeSetCard.createdAt() > NotificationCache.load(routeForLastRead, context) + isNew = likeSetCard.createdAt() > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, likeSetCard.createdAt(), context) + NotificationCache.markAsRead(routeForLastRead, likeSetCard.createdAt()) } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { MaterialTheme.colors.primary.copy(0.12f).compositeOver(MaterialTheme.colors.background) } else { MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt index 053a2e253..da4d768e0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -44,8 +43,6 @@ fun BoostSetCompose(boostSetCard: BoostSetCard, isInnerNote: Boolean = false, ro val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return - val context = LocalContext.current.applicationContext - val noteEvent = note?.event var popupExpanded by remember { mutableStateOf(false) } @@ -56,13 +53,13 @@ fun BoostSetCompose(boostSetCard: BoostSetCard, isInnerNote: Boolean = false, ro LaunchedEffect(key1 = boostSetCard) { withContext(Dispatchers.IO) { - isNew = boostSetCard.createdAt > NotificationCache.load(routeForLastRead, context) + isNew = boostSetCard.createdAt > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, boostSetCard.createdAt, context) + NotificationCache.markAsRead(routeForLastRead, boostSetCard.createdAt) } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { MaterialTheme.colors.primary.copy(0.12f).compositeOver(MaterialTheme.colors.background) } else { MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt index 9be25b43f..246b1fef2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt @@ -64,8 +64,6 @@ fun ChatroomCompose( val notificationCacheState = NotificationCache.live.observeAsState() val notificationCache = notificationCacheState.value ?: return - val context = LocalContext.current.applicationContext - if (note?.event == null) { BlankNote(Modifier) } else if (note.channel() != null) { @@ -84,22 +82,22 @@ fun ChatroomCompose( } else { noteEvent?.content() } - channel?.let { channel -> + channel?.let { chan -> var hasNewMessages by remember { mutableStateOf(false) } LaunchedEffect(key1 = notificationCache, key2 = note) { withContext(Dispatchers.IO) { - note.createdAt()?.let { + note.createdAt()?.let { timestamp -> hasNewMessages = - it > notificationCache.cache.load("Channel/${channel.idHex}", context) + timestamp > notificationCache.cache.load("Channel/${chan.idHex}") } } } ChannelName( - channelIdHex = channel.idHex, - channelPicture = channel.profilePicture(), - channelTitle = { + channelIdHex = chan.idHex, + channelPicture = chan.profilePicture(), + channelTitle = { modifier -> Text( text = buildAnnotatedString { withStyle( @@ -107,7 +105,7 @@ fun ChatroomCompose( fontWeight = FontWeight.Bold ) ) { - append(channel.info.name) + append(chan.info.name) } withStyle( @@ -120,14 +118,14 @@ fun ChatroomCompose( } }, fontWeight = FontWeight.Bold, - modifier = it, + modifier = modifier, style = LocalTextStyle.current.copy(textDirection = TextDirection.Content) ) }, channelLastTime = note.createdAt(), channelLastContent = "${author?.toBestDisplayName()}: " + description, hasNewMessages = hasNewMessages, - onClick = { navController.navigate("Channel/${channel.idHex}") } + onClick = { navController.navigate("Channel/${chan.idHex}") } ) } } else { @@ -153,8 +151,7 @@ fun ChatroomCompose( withContext(Dispatchers.IO) { noteEvent?.let { hasNewMessages = it.createdAt() > notificationCache.cache.load( - "Room/${userToComposeOn.pubkeyHex}", - context + "Room/${userToComposeOn.pubkeyHex}" ) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index 0c7a730bb..ee19c865a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -132,11 +132,11 @@ fun ChatroomMessageCompose( LaunchedEffect(key1 = routeForLastRead) { routeForLastRead?.let { withContext(Dispatchers.IO) { - val lastTime = NotificationCache.load(it, context) + val lastTime = NotificationCache.load(it) val createdAt = note.createdAt() if (createdAt != null) { - NotificationCache.markAsRead(it, createdAt, context) + NotificationCache.markAsRead(it, createdAt) isNew = createdAt > lastTime } } @@ -206,17 +206,17 @@ fun ChatroomMessageCompose( .height(25.dp) .clip(shape = CircleShape) .clickable(onClick = { - author?.let { + author.let { navController.navigate("User/${it.pubkeyHex}") } }) ) Text( - " ${author?.toBestDisplayName()}", + " ${author.toBestDisplayName()}", fontWeight = FontWeight.Bold, modifier = Modifier.clickable(onClick = { - author?.let { + author.let { navController.navigate("User/${it.pubkeyHex}") } }) @@ -225,9 +225,9 @@ fun ChatroomMessageCompose( } val replyTo = note.replyTo - if (!innerQuote && replyTo != null && replyTo.isNotEmpty()) { + if (!innerQuote && !replyTo.isNullOrEmpty()) { Row(verticalAlignment = Alignment.CenterVertically) { - replyTo.toSet().mapIndexed { index, note -> + replyTo.toSet().mapIndexed { _, note -> if (note.event != null) { ChatroomMessageCompose( note, @@ -360,7 +360,6 @@ private fun RelayBadges(baseNote: Note) { val relaysToDisplay = if (expanded) noteRelays else noteRelays.take(3) val uri = LocalUriHandler.current - val ctx = LocalContext.current.applicationContext FlowRow(Modifier.padding(start = 10.dp)) { relaysToDisplay.forEach { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt index 722a74220..2d347b9f7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -37,15 +36,13 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalFoundationApi::class) @Composable -fun LikeSetCompose(likeSetCard: LikeSetCard, modifier: Modifier = Modifier, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { +fun LikeSetCompose(likeSetCard: LikeSetCard, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { val noteState by likeSetCard.note.live().metadata.observeAsState() val note = noteState?.note val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return - val context = LocalContext.current.applicationContext - val noteEvent = note?.event var popupExpanded by remember { mutableStateOf(false) } @@ -56,13 +53,13 @@ fun LikeSetCompose(likeSetCard: LikeSetCard, modifier: Modifier = Modifier, isIn LaunchedEffect(key1 = likeSetCard) { withContext(Dispatchers.IO) { - isNew = likeSetCard.createdAt > NotificationCache.load(routeForLastRead, context) + isNew = likeSetCard.createdAt > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, likeSetCard.createdAt, context) + NotificationCache.markAsRead(routeForLastRead, likeSetCard.createdAt) } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { MaterialTheme.colors.primary.copy(0.12f).compositeOver(MaterialTheme.colors.background) } else { MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MessageSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MessageSetCompose.kt index 743b06e73..bf0fa2cdb 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MessageSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MessageSetCompose.kt @@ -21,7 +21,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -39,11 +38,6 @@ fun MessageSetCompose(messageSetCard: MessageSetCard, isInnerNote: Boolean = fal val noteState by messageSetCard.note.live().metadata.observeAsState() val note = noteState?.note - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account ?: return - - val context = LocalContext.current.applicationContext - val noteEvent = note?.event var popupExpanded by remember { mutableStateOf(false) } @@ -55,13 +49,13 @@ fun MessageSetCompose(messageSetCard: MessageSetCard, isInnerNote: Boolean = fal LaunchedEffect(key1 = messageSetCard) { withContext(Dispatchers.IO) { isNew = - messageSetCard.createdAt() > NotificationCache.load(routeForLastRead, context) + messageSetCard.createdAt() > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, messageSetCard.createdAt(), context) + NotificationCache.markAsRead(routeForLastRead, messageSetCard.createdAt()) } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { MaterialTheme.colors.primary.copy(0.12f).compositeOver(MaterialTheme.colors.background) } else { MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index f1fd8e8fa..4264a12e1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -41,15 +40,13 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalFoundationApi::class) @Composable -fun MultiSetCompose(multiSetCard: MultiSetCard, modifier: Modifier = Modifier, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { +fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { val noteState by multiSetCard.note.live().metadata.observeAsState() val note = noteState?.note val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return - val context = LocalContext.current.applicationContext - val noteEvent = note?.event var popupExpanded by remember { mutableStateOf(false) } @@ -60,13 +57,13 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, modifier: Modifier = Modifier, r LaunchedEffect(key1 = multiSetCard) { withContext(Dispatchers.IO) { - isNew = multiSetCard.createdAt > NotificationCache.load(routeForLastRead, context) + isNew = multiSetCard.createdAt > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, multiSetCard.createdAt, context) + NotificationCache.markAsRead(routeForLastRead, multiSetCard.createdAt) } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { MaterialTheme.colors.primary.copy(0.12f).compositeOver(MaterialTheme.colors.background) } else { MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 8c61fb254..ac10c138e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -124,18 +124,18 @@ fun NoteCompose( LaunchedEffect(key1 = routeForLastRead) { withContext(Dispatchers.IO) { routeForLastRead?.let { - val lastTime = NotificationCache.load(it, context) + val lastTime = NotificationCache.load(it) val createdAt = note.createdAt() if (createdAt != null) { - NotificationCache.markAsRead(it, createdAt, context) + NotificationCache.markAsRead(it, createdAt) isNew = createdAt > lastTime } } } } - var backgroundColor = if (isNew) { + val backgroundColor = if (isNew) { val newColor = MaterialTheme.colors.primary.copy(0.12f) if (parentBackgroundColor != null) { newColor.compositeOver(parentBackgroundColor) @@ -350,7 +350,7 @@ fun NoteCompose( // Reposts have trash in their contents. if (noteEvent is ReactionEvent) { val refactorReactionText = - if (noteEvent.content == "+") "❤" else noteEvent.content ?: " " + if (noteEvent.content == "+") "❤" else noteEvent.content Text( text = refactorReactionText @@ -365,7 +365,6 @@ fun NoteCompose( ReportEvent.ReportType.SPAM -> stringResource(R.string.spam) ReportEvent.ReportType.IMPERSONATION -> stringResource(R.string.impersonation) ReportEvent.ReportType.ILLEGAL -> stringResource(R.string.illegal_behavior) - else -> stringResource(R.string.unknown) } }.toSet().joinToString(", ") @@ -600,7 +599,6 @@ private fun RelayBadges(baseNote: Note) { val relaysToDisplay = if (expanded) noteRelays else noteRelays.take(3) val uri = LocalUriHandler.current - val ctx = LocalContext.current.applicationContext FlowRow(Modifier.padding(top = 10.dp, start = 5.dp, end = 4.dp)) { relaysToDisplay.forEach { @@ -666,7 +664,7 @@ fun NoteAuthorPicture( baseNote: Note, baseUserAccount: User, size: Dp, - pictureModifier: Modifier = Modifier, + modifier: Modifier = Modifier, onClick: ((User) -> Unit)? = null ) { val noteState by baseNote.live().metadata.observeAsState() @@ -674,8 +672,6 @@ fun NoteAuthorPicture( val author = note.author - val ctx = LocalContext.current.applicationContext - Box( Modifier .width(size) @@ -685,13 +681,13 @@ fun NoteAuthorPicture( RobohashAsyncImage( robot = "authornotfound", contentDescription = stringResource(R.string.unknown_author), - modifier = pictureModifier + modifier = modifier .fillMaxSize(1f) .clip(shape = CircleShape) .background(MaterialTheme.colors.background) ) } else { - UserPicture(author, baseUserAccount, size, pictureModifier, onClick) + UserPicture(author, baseUserAccount, size, modifier, onClick) } } } @@ -715,15 +711,13 @@ fun UserPicture( baseUser: User, baseUserAccount: User, size: Dp, - pictureModifier: Modifier = Modifier, + modifier: Modifier = Modifier, onClick: ((User) -> Unit)? = null, onLongClick: ((User) -> Unit)? = null ) { val userState by baseUser.live().metadata.observeAsState() val user = userState?.user ?: return - val ctx = LocalContext.current.applicationContext - Box( Modifier .width(size) @@ -733,7 +727,7 @@ fun UserPicture( robot = user.pubkeyHex, model = ResizeImage(user.profilePicture(), size), contentDescription = stringResource(id = R.string.profile_image), - modifier = pictureModifier + modifier = modifier .fillMaxSize(1f) .clip(shape = CircleShape) .background(MaterialTheme.colors.background) @@ -803,7 +797,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(accountViewModel.decrypt(note) ?: "")); onDismiss() }) { Text(stringResource(R.string.copy_text)) } - DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString("@${note.author?.pubkeyNpub()}" ?: "")); onDismiss() }) { + DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString("@${note.author?.pubkeyNpub()}")); onDismiss() }) { Text(stringResource(R.string.copy_user_pubkey)) } DropdownMenuItem(onClick = { clipboardManager.setText(AnnotatedString(note.idNote())); onDismiss() }) { @@ -840,10 +834,7 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, Divider() DropdownMenuItem(onClick = { note.author?.let { - accountViewModel.hide( - it, - appContext - ) + accountViewModel.hide(it) }; onDismiss() }) { Text(stringResource(R.string.block_hide_user)) @@ -851,35 +842,35 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, Divider() DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.SPAM) - note.author?.let { accountViewModel.hide(it, appContext) } + note.author?.let { accountViewModel.hide(it) } onDismiss() }) { Text(stringResource(R.string.report_spam_scam)) } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.PROFANITY) - note.author?.let { accountViewModel.hide(it, appContext) } + note.author?.let { accountViewModel.hide(it) } onDismiss() }) { Text(stringResource(R.string.report_hateful_speech)) } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.IMPERSONATION) - note.author?.let { accountViewModel.hide(it, appContext) } + note.author?.let { accountViewModel.hide(it) } onDismiss() }) { Text(stringResource(R.string.report_impersonation)) } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.NUDITY) - note.author?.let { accountViewModel.hide(it, appContext) } + note.author?.let { accountViewModel.hide(it) } onDismiss() }) { Text(stringResource(R.string.report_nudity_porn)) } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.ILLEGAL) - note.author?.let { accountViewModel.hide(it, appContext) } + note.author?.let { accountViewModel.hide(it) } onDismiss() }) { Text(stringResource(R.string.report_illegal_behaviour)) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt index 1b0aaf245..4f70ca414 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt @@ -124,7 +124,7 @@ fun NoteQuickActionMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Uni } VerticalDivider(primaryLight) NoteQuickActionItem(Icons.Default.AlternateEmail, stringResource(R.string.quick_action_copy_user_id)) { - clipboardManager.setText(AnnotatedString("@${note.author?.pubkeyNpub()}" ?: "")) + clipboardManager.setText(AnnotatedString("@${note.author?.pubkeyNpub()}")) showToast(R.string.copied_user_id_to_clipboard) onDismiss() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index a302ba1c6..2647167dc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -39,12 +39,10 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -280,7 +278,7 @@ fun LikeReaction( } } ) { - if (reactedNote?.isReactedBy(accountViewModel.userProfile()) == true) { + if (reactedNote.isReactedBy(accountViewModel.userProfile())) { Icon( painter = painterResource(R.drawable.ic_liked), null, @@ -298,7 +296,7 @@ fun LikeReaction( } Text( - " ${showCount(reactedNote?.reactions?.size)}", + " ${showCount(reactedNote.reactions.size)}", fontSize = 14.sp, color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f), modifier = textModifier @@ -590,15 +588,13 @@ class UpdateZapAmountViewModel : ViewModel() { } } -@OptIn(ExperimentalComposeUiApi::class, ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class) @Composable fun UpdateZapAmountDialog(onClose: () -> Unit, account: Account) { val postViewModel: UpdateZapAmountViewModel = viewModel() - val ctx = LocalContext.current.applicationContext - // initialize focus reference to be able to request focus programmatically - val keyboardController = LocalSoftwareKeyboardController.current +// val keyboardController = LocalSoftwareKeyboardController.current LaunchedEffect(account) { postViewModel.load(account) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt index 9625a2c49..f110d6369 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.navigation.NavController import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.RelayInfo import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -34,7 +33,6 @@ import java.time.format.DateTimeFormatter fun RelayCompose( relay: RelayInfo, accountViewModel: AccountViewModel, - navController: NavController, onAddRelay: () -> Unit, onRemoveRelay: () -> Unit ) { @@ -48,8 +46,6 @@ fun RelayCompose( modifier = Modifier .padding(start = 12.dp, end = 12.dp, top = 10.dp) ) { - // UserPicture(user, navController, account.userProfile(), 55.dp) - Column( modifier = Modifier .padding(start = 10.dp) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt index 24bb69ee1..46f154fe1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -33,7 +32,6 @@ fun UserCompose(baseUser: User, accountViewModel: AccountViewModel, navControlle val userState by account.userProfile().live().follows.observeAsState() val userFollows = userState?.user ?: return - val ctx = LocalContext.current.applicationContext val coroutineScope = rememberCoroutineScope() Column( @@ -58,8 +56,8 @@ fun UserCompose(baseUser: User, accountViewModel: AccountViewModel, navControlle UsernameDisplay(baseUser) } - val userState by baseUser.live().metadata.observeAsState() - val user = userState?.user ?: return + val baseUserState by baseUser.live().metadata.observeAsState() + val user = baseUserState?.user ?: return Text( user.info?.about ?: "", diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapNoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapNoteCompose.kt index e26caff52..e8e2ccf61 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapNoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapNoteCompose.kt @@ -18,7 +18,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -54,7 +53,6 @@ fun ZapNoteCompose(baseNote: Pair, accountViewModel: AccountViewMode val baseAuthor = noteZapRequest.author - val ctx = LocalContext.current.applicationContext val coroutineScope = rememberCoroutineScope() if (baseAuthor == null) { @@ -83,8 +81,8 @@ fun ZapNoteCompose(baseNote: Pair, accountViewModel: AccountViewMode UsernameDisplay(baseAuthor) } - val userState by baseAuthor.live().metadata.observeAsState() - val user = userState?.user ?: return + val baseAuthorState by baseAuthor.live().metadata.observeAsState() + val user = baseAuthorState?.user ?: return Text( user.info?.about ?: "", diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapSetCompose.kt index 98b0c1e09..8e9c2ed0d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapSetCompose.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -39,15 +38,13 @@ import kotlinx.coroutines.withContext @OptIn(ExperimentalFoundationApi::class) @Composable -fun ZapSetCompose(zapSetCard: ZapSetCard, modifier: Modifier = Modifier, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { +fun ZapSetCompose(zapSetCard: ZapSetCard, isInnerNote: Boolean = false, routeForLastRead: String, accountViewModel: AccountViewModel, navController: NavController) { val noteState by zapSetCard.note.live().metadata.observeAsState() val note = noteState?.note val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return - val context = LocalContext.current.applicationContext - val noteEvent = note?.event var popupExpanded by remember { mutableStateOf(false) } @@ -58,9 +55,9 @@ fun ZapSetCompose(zapSetCard: ZapSetCard, modifier: Modifier = Modifier, isInner LaunchedEffect(key1 = zapSetCard) { withContext(Dispatchers.IO) { - isNew = zapSetCard.createdAt > NotificationCache.load(routeForLastRead, context) + isNew = zapSetCard.createdAt > NotificationCache.load(routeForLastRead) - NotificationCache.markAsRead(routeForLastRead, zapSetCard.createdAt, context) + NotificationCache.markAsRead(routeForLastRead, zapSetCard.createdAt) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt index 2884b931d..bb95308a4 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -44,8 +43,6 @@ import com.vitorpamplona.amethyst.ui.qrcode.QrCodeScanner fun ShowQRDialog(user: User, onScan: (String) -> Unit, onClose: () -> Unit) { var presenting by remember { mutableStateOf(true) } - val ctx = LocalContext.current.applicationContext - Dialog( onDismissRequest = onClose, properties = DialogProperties(usePlatformDefaultWidth = false) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index 10cc60808..79b3158f5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -6,6 +6,7 @@ import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.Account import fr.acinq.secp256k1.Hex import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job @@ -67,6 +68,7 @@ class AccountStateViewModel() : ViewModel() { login(account) } + @OptIn(DelicateCoroutinesApi::class) fun login(account: Account) { LocalPreferences.updatePrefsForLogin(account) @@ -86,16 +88,16 @@ class AccountStateViewModel() : ViewModel() { } } + @OptIn(DelicateCoroutinesApi::class) private val saveListener: (com.vitorpamplona.amethyst.model.AccountState) -> Unit = { GlobalScope.launch(Dispatchers.IO) { LocalPreferences.saveToEncryptedStorage(it.account) } } + @OptIn(DelicateCoroutinesApi::class) private fun prepareLogoutOrSwitch() { - val state = accountContent.value - - when (state) { + when (val state = accountContent.value) { is AccountState.LoggedIn -> { GlobalScope.launch(Dispatchers.Main) { state.account.saveable.removeObserver(saveListener) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedView.kt index 9b77d4156..7adedfd84 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedView.kt @@ -90,7 +90,7 @@ private fun FeedLoaded( ), state = listState ) { - itemsIndexed(state.feed.value, key = { _, item -> item.id() }) { index, item -> + itemsIndexed(state.feed.value, key = { _, item -> item.id() }) { _, item -> when (item) { is NoteCard -> NoteCompose( item.note, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ChatroomListFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ChatroomListFeedView.kt index 72a3223f5..6d4b94e82 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ChatroomListFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ChatroomListFeedView.kt @@ -22,7 +22,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController @@ -94,7 +93,6 @@ private fun FeedLoaded( val account = accountState?.account ?: return val notificationCacheState = NotificationCache.live.observeAsState() val notificationCache = notificationCacheState.value ?: return - val context = LocalContext.current.applicationContext LaunchedEffect(key1 = markAsRead.value) { if (markAsRead.value) { @@ -118,7 +116,7 @@ private fun FeedLoaded( "Room/${userToComposeOn.pubkeyHex}" } - notificationCache.cache.markAsRead(route, it.createdAt(), context) + notificationCache.cache.markAsRead(route, it.createdAt()) } } markAsRead.value = false diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedView.kt index d4d8767bd..6981b5631 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedView.kt @@ -78,7 +78,7 @@ private fun LnZapFeedLoaded( ), state = listState ) { - itemsIndexed(state.feed.value, key = { _, item -> item.second.idHex }) { index, item -> + itemsIndexed(state.feed.value, key = { _, item -> item.second.idHex }) { _, item -> ZapNoteCompose(item, accountViewModel = accountViewModel, navController = navController) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt index 6b1833a65..8dd8df5f6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.navigation.NavController import com.vitorpamplona.amethyst.model.RelayInfo import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.UserState @@ -107,7 +106,7 @@ class RelayFeedViewModel : ViewModel() { @OptIn(ExperimentalMaterialApi::class) @Composable -fun RelayFeedView(viewModel: RelayFeedViewModel, accountViewModel: AccountViewModel, navController: NavController) { +fun RelayFeedView(viewModel: RelayFeedViewModel, accountViewModel: AccountViewModel) { val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return @@ -136,11 +135,10 @@ fun RelayFeedView(viewModel: RelayFeedViewModel, accountViewModel: AccountViewMo ), state = listState ) { - itemsIndexed(feedState, key = { _, item -> item.url }) { index, item -> + itemsIndexed(feedState, key = { _, item -> item.url }) { _, item -> RelayCompose( item, accountViewModel = accountViewModel, - navController = navController, onAddRelay = { wantsToAddRelay = item.url }, onRemoveRelay = { wantsToAddRelay = item.url } ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedView.kt index 3452677c8..916a863da 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedView.kt @@ -78,7 +78,7 @@ private fun FeedLoaded( ), state = listState ) { - itemsIndexed(state.feed.value, key = { _, item -> item.pubkeyHex }) { index, item -> + itemsIndexed(state.feed.value, key = { _, item -> item.pubkeyHex }) { _, item -> UserCompose(item, accountViewModel = accountViewModel, navController = navController) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountBackupDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountBackupDialog.kt index 773f216df..1ae127357 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountBackupDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountBackupDialog.kt @@ -167,6 +167,7 @@ private fun authenticatedCopyNSec( return } + @Suppress("DEPRECATION") fun keyguardPrompt() { val intent = keyguardManager.createConfirmDeviceCredentialIntent( context.getString(R.string.app_name_release), 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 2734c6ee1..bd84aa779 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 @@ -97,19 +97,19 @@ class AccountViewModel(private val account: Account) : ViewModel() { return account.decryptContent(note) } - fun hide(user: User, ctx: Context) { + fun hide(user: User) { account.hideUser(user.pubkeyHex) } - fun show(user: User, ctx: Context) { + fun show(user: User) { account.showUser(user.pubkeyHex) } - fun translateTo(lang: Locale, ctx: Context) { + fun translateTo(lang: Locale) { account.updateTranslateTo(lang.language) } - fun dontTranslateFrom(lang: String, ctx: Context) { + fun dontTranslateFrom(lang: String) { account.addDontTranslateFrom(lang) } 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 5d54cbdc5..43d5a88d9 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 @@ -71,7 +71,6 @@ import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.dal.ChannelFeedFilter import com.vitorpamplona.amethyst.ui.navigation.Route import com.vitorpamplona.amethyst.ui.note.ChatroomMessageCompose -import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel import com.vitorpamplona.amethyst.ui.screen.ChatroomFeedView import com.vitorpamplona.amethyst.ui.screen.NostrChannelFeedViewModel @@ -79,7 +78,6 @@ import com.vitorpamplona.amethyst.ui.screen.NostrChannelFeedViewModel fun ChannelScreen( channelId: String?, accountViewModel: AccountViewModel, - accountStateViewModel: AccountStateViewModel, navController: NavController ) { val accountState by accountViewModel.accountLiveData.observeAsState() @@ -103,7 +101,7 @@ fun ChannelScreen( } DisposableEffect(channelId) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { println("Channel Start") NostrChannelDataSource.start() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt index b416c2f2f..8b3cefa8d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt @@ -145,7 +145,7 @@ fun TabKnown( val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { NostrChatroomListDataSource.resetFilters() feedViewModel.refresh() @@ -186,7 +186,7 @@ fun TabNew( val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { NostrChatroomListDataSource.resetFilters() feedViewModel.refresh() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index e566bb055..0465c0124 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -1,241 +1,234 @@ -package com.vitorpamplona.amethyst.ui.screen.loggedIn - -import androidx.compose.animation.animateContentSize -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.Divider -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.LocalTextStyle -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Cancel -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardCapitalization -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.text.style.TextDirection -import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleEventObserver -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavController -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.model.User -import com.vitorpamplona.amethyst.service.NostrChatroomDataSource -import com.vitorpamplona.amethyst.ui.actions.PostButton -import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status -import com.vitorpamplona.amethyst.ui.components.ResizeImage -import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy -import com.vitorpamplona.amethyst.ui.dal.ChatroomFeedFilter -import com.vitorpamplona.amethyst.ui.note.ChatroomMessageCompose -import com.vitorpamplona.amethyst.ui.note.UsernameDisplay -import com.vitorpamplona.amethyst.ui.screen.ChatroomFeedView -import com.vitorpamplona.amethyst.ui.screen.NostrChatRoomFeedViewModel - -@Composable -fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navController: NavController) { - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account - - if (account != null && userId != null) { - val newPost = remember { mutableStateOf(TextFieldValue("")) } - val replyTo = remember { mutableStateOf(null) } - - ChatroomFeedFilter.loadMessagesBetween(account, userId) - NostrChatroomDataSource.loadMessagesBetween(account, userId) - - val feedViewModel: NostrChatRoomFeedViewModel = viewModel() - val lifeCycleOwner = LocalLifecycleOwner.current - - LaunchedEffect(userId) { - feedViewModel.refresh() - } - - DisposableEffect(userId) { - val observer = LifecycleEventObserver { source, event -> - if (event == Lifecycle.Event.ON_RESUME) { - println("Private Message Start") - NostrChatroomDataSource.start() - feedViewModel.refresh() - } - if (event == Lifecycle.Event.ON_PAUSE) { - println("Private Message Stop") - NostrChatroomDataSource.stop() - } - } - - lifeCycleOwner.lifecycle.addObserver(observer) - onDispose { - lifeCycleOwner.lifecycle.removeObserver(observer) - } - } - - Column(Modifier.fillMaxHeight()) { - NostrChatroomDataSource.withUser?.let { - ChatroomHeader( - it, - accountViewModel = accountViewModel, - navController = navController - ) - } - - Column( - modifier = Modifier - .fillMaxHeight() - .padding(vertical = 0.dp) - .weight(1f, true) - ) { - ChatroomFeedView(feedViewModel, accountViewModel, navController, "Room/$userId") { - replyTo.value = it - } - } - - Spacer(modifier = Modifier.height(10.dp)) - - Row(Modifier.padding(horizontal = 10.dp).animateContentSize(), verticalAlignment = Alignment.CenterVertically) { - val replyingNote = replyTo.value - if (replyingNote != null) { - Column(Modifier.weight(1f)) { - ChatroomMessageCompose( - baseNote = replyingNote, - null, - innerQuote = true, - accountViewModel = accountViewModel, - navController = navController, - onWantsToReply = { - replyTo.value = it - } - ) - } - - Column(Modifier.padding(end = 10.dp)) { - IconButton( - modifier = Modifier.size(30.dp), - onClick = { replyTo.value = null } - ) { - Icon( - imageVector = Icons.Default.Cancel, - null, - modifier = Modifier.padding(end = 5.dp).size(30.dp), - tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) - ) - } - } - } - } - - // LAST ROW - Row( - modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - TextField( - value = newPost.value, - onValueChange = { newPost.value = it }, - keyboardOptions = KeyboardOptions.Default.copy( - capitalization = KeyboardCapitalization.Sentences - ), - modifier = Modifier.weight(1f, true), - shape = RoundedCornerShape(25.dp), - placeholder = { - Text( - text = stringResource(id = R.string.reply_here), - color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) - ) - }, - textStyle = LocalTextStyle.current.copy(textDirection = TextDirection.Content), - trailingIcon = { - PostButton( - onPost = { - account.sendPrivateMeesage(newPost.value.text, userId, replyTo.value) - newPost.value = TextFieldValue("") - replyTo.value = null - feedViewModel.refresh() // Don't wait a full second before updating - }, - newPost.value.text.isNotBlank(), - modifier = Modifier.padding(end = 10.dp) - ) - }, - colors = TextFieldDefaults.textFieldColors( - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent - ) - ) - } - } - } -} - -@Composable -fun ChatroomHeader(baseUser: User, accountViewModel: AccountViewModel, navController: NavController) { - val ctx = LocalContext.current.applicationContext - - Column( - modifier = Modifier.clickable( - onClick = { navController.navigate("User/${baseUser.pubkeyHex}") } - ) - ) { - Column(modifier = Modifier.padding(12.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - val authorState by baseUser.live().metadata.observeAsState() - val author = authorState?.user!! - - RobohashAsyncImageProxy( - robot = author.pubkeyHex, - model = ResizeImage(author.profilePicture(), 35.dp), - contentDescription = stringResource(id = R.string.profile_image), - modifier = Modifier - .width(35.dp) - .height(35.dp) - .clip(shape = CircleShape) - ) - - Column(modifier = Modifier.padding(start = 10.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - UsernameDisplay(baseUser) - } - - Row(verticalAlignment = Alignment.CenterVertically) { - ObserveDisplayNip05Status(baseUser) - } - } - } - } - - Divider( - modifier = Modifier.padding(start = 12.dp, end = 12.dp), - thickness = 0.25.dp - ) - } -} +package com.vitorpamplona.amethyst.ui.screen.loggedIn + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Divider +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.LocalTextStyle +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Cancel +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextDirection +import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.service.NostrChatroomDataSource +import com.vitorpamplona.amethyst.ui.actions.PostButton +import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status +import com.vitorpamplona.amethyst.ui.components.ResizeImage +import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy +import com.vitorpamplona.amethyst.ui.dal.ChatroomFeedFilter +import com.vitorpamplona.amethyst.ui.note.ChatroomMessageCompose +import com.vitorpamplona.amethyst.ui.note.UsernameDisplay +import com.vitorpamplona.amethyst.ui.screen.ChatroomFeedView +import com.vitorpamplona.amethyst.ui.screen.NostrChatRoomFeedViewModel + +@Composable +fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navController: NavController) { + val accountState by accountViewModel.accountLiveData.observeAsState() + val account = accountState?.account + + if (account != null && userId != null) { + val newPost = remember { mutableStateOf(TextFieldValue("")) } + val replyTo = remember { mutableStateOf(null) } + + ChatroomFeedFilter.loadMessagesBetween(account, userId) + NostrChatroomDataSource.loadMessagesBetween(account, userId) + + val feedViewModel: NostrChatRoomFeedViewModel = viewModel() + val lifeCycleOwner = LocalLifecycleOwner.current + + LaunchedEffect(userId) { + feedViewModel.refresh() + } + + DisposableEffect(userId) { + val observer = LifecycleEventObserver { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + println("Private Message Start") + NostrChatroomDataSource.start() + feedViewModel.refresh() + } + if (event == Lifecycle.Event.ON_PAUSE) { + println("Private Message Stop") + NostrChatroomDataSource.stop() + } + } + + lifeCycleOwner.lifecycle.addObserver(observer) + onDispose { + lifeCycleOwner.lifecycle.removeObserver(observer) + } + } + + Column(Modifier.fillMaxHeight()) { + NostrChatroomDataSource.withUser?.let { + ChatroomHeader(it, navController = navController) + } + + Column( + modifier = Modifier + .fillMaxHeight() + .padding(vertical = 0.dp) + .weight(1f, true) + ) { + ChatroomFeedView(feedViewModel, accountViewModel, navController, "Room/$userId") { + replyTo.value = it + } + } + + Spacer(modifier = Modifier.height(10.dp)) + + Row(Modifier.padding(horizontal = 10.dp).animateContentSize(), verticalAlignment = Alignment.CenterVertically) { + val replyingNote = replyTo.value + if (replyingNote != null) { + Column(Modifier.weight(1f)) { + ChatroomMessageCompose( + baseNote = replyingNote, + null, + innerQuote = true, + accountViewModel = accountViewModel, + navController = navController, + onWantsToReply = { + replyTo.value = it + } + ) + } + + Column(Modifier.padding(end = 10.dp)) { + IconButton( + modifier = Modifier.size(30.dp), + onClick = { replyTo.value = null } + ) { + Icon( + imageVector = Icons.Default.Cancel, + null, + modifier = Modifier.padding(end = 5.dp).size(30.dp), + tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) + ) + } + } + } + } + + // LAST ROW + Row( + modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + TextField( + value = newPost.value, + onValueChange = { newPost.value = it }, + keyboardOptions = KeyboardOptions.Default.copy( + capitalization = KeyboardCapitalization.Sentences + ), + modifier = Modifier.weight(1f, true), + shape = RoundedCornerShape(25.dp), + placeholder = { + Text( + text = stringResource(id = R.string.reply_here), + color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) + ) + }, + textStyle = LocalTextStyle.current.copy(textDirection = TextDirection.Content), + trailingIcon = { + PostButton( + onPost = { + account.sendPrivateMeesage(newPost.value.text, userId, replyTo.value) + newPost.value = TextFieldValue("") + replyTo.value = null + feedViewModel.refresh() // Don't wait a full second before updating + }, + newPost.value.text.isNotBlank(), + modifier = Modifier.padding(end = 10.dp) + ) + }, + colors = TextFieldDefaults.textFieldColors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ) + ) + } + } + } +} + +@Composable +fun ChatroomHeader(baseUser: User, navController: NavController) { + Column( + modifier = Modifier.clickable( + onClick = { navController.navigate("User/${baseUser.pubkeyHex}") } + ) + ) { + Column(modifier = Modifier.padding(12.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + val authorState by baseUser.live().metadata.observeAsState() + val author = authorState?.user!! + + RobohashAsyncImageProxy( + robot = author.pubkeyHex, + model = ResizeImage(author.profilePicture(), 35.dp), + contentDescription = stringResource(id = R.string.profile_image), + modifier = Modifier + .width(35.dp) + .height(35.dp) + .clip(shape = CircleShape) + ) + + Column(modifier = Modifier.padding(start = 10.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + UsernameDisplay(baseUser) + } + + Row(verticalAlignment = Alignment.CenterVertically) { + ObserveDisplayNip05Status(baseUser) + } + } + } + } + + Divider( + modifier = Modifier.padding(start = 12.dp, end = 12.dp), + thickness = 0.25.dp + ) + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt index a7f82a63f..e2e22b469 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt @@ -69,7 +69,7 @@ fun MainScreen(accountViewModel: AccountViewModel, accountStateViewModel: Accoun scaffoldState = scaffoldState ) { Column(modifier = Modifier.padding(bottom = it.calculateBottomPadding())) { - AppNavigation(navController, accountViewModel, accountStateViewModel, startingPage) + AppNavigation(navController, accountViewModel, startingPage) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NotificationScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NotificationScreen.kt index 3f438c05d..55bb17eba 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NotificationScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NotificationScreen.kt @@ -34,7 +34,7 @@ fun NotificationScreen(accountViewModel: AccountViewModel, navController: NavCon val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { feedViewModel.refresh() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index 71c3c08ad..041780219 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -27,7 +27,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalUriHandler @@ -111,7 +110,7 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { println("Profile Start") NostrUserProfileDataSource.loadUserProfile(userId) @@ -259,13 +258,13 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro } ) { when (pagerState.currentPage) { - 0 -> TabNotesNewThreads(baseUser, accountViewModel, navController) - 1 -> TabNotesConversations(baseUser, accountViewModel, navController) + 0 -> TabNotesNewThreads(accountViewModel, navController) + 1 -> TabNotesConversations(accountViewModel, navController) 2 -> TabFollows(baseUser, accountViewModel, navController) 3 -> TabFollowers(baseUser, accountViewModel, navController) 4 -> TabReceivedZaps(baseUser, accountViewModel, navController) 5 -> TabReports(baseUser, accountViewModel, navController) - 6 -> TabRelays(baseUser, accountViewModel, navController) + 6 -> TabRelays(baseUser, accountViewModel) } } } @@ -335,7 +334,7 @@ private fun ProfileHeader( baseUser = baseUser, baseUserAccount = account.userProfile(), size = 100.dp, - pictureModifier = Modifier.border( + modifier = Modifier.border( 3.dp, MaterialTheme.colors.background, CircleShape @@ -576,8 +575,6 @@ fun BadgeThumb( val event = (note.event as? BadgeDefinitionEvent) val image = event?.thumb() ?: event?.image() - val ctx = LocalContext.current.applicationContext - Box( Modifier .width(size) @@ -656,7 +653,7 @@ private fun DrawBanner(baseUser: User) { } @Composable -fun TabNotesNewThreads(user: User, accountViewModel: AccountViewModel, navController: NavController) { +fun TabNotesNewThreads(accountViewModel: AccountViewModel, navController: NavController) { val accountState by accountViewModel.accountLiveData.observeAsState() if (accountState != null) { val feedViewModel: NostrUserProfileNewThreadsFeedViewModel = viewModel() @@ -676,7 +673,7 @@ fun TabNotesNewThreads(user: User, accountViewModel: AccountViewModel, navContro } @Composable -fun TabNotesConversations(user: User, accountViewModel: AccountViewModel, navController: NavController) { +fun TabNotesConversations(accountViewModel: AccountViewModel, navController: NavController) { val accountState by accountViewModel.accountLiveData.observeAsState() if (accountState != null) { val feedViewModel: NostrUserProfileConversationsFeedViewModel = viewModel() @@ -772,13 +769,13 @@ fun TabReports(baseUser: User, accountViewModel: AccountViewModel, navController } @Composable -fun TabRelays(user: User, accountViewModel: AccountViewModel, navController: NavController) { +fun TabRelays(user: User, accountViewModel: AccountViewModel) { val feedViewModel: RelayFeedViewModel = viewModel() val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(user) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { println("Profile Relay Start") feedViewModel.subscribeTo(user) @@ -801,7 +798,7 @@ fun TabRelays(user: User, accountViewModel: AccountViewModel, navController: Nav Column( modifier = Modifier.padding(vertical = 0.dp) ) { - RelayFeedView(feedViewModel, accountViewModel, navController) + RelayFeedView(feedViewModel, accountViewModel) } } } @@ -943,8 +940,6 @@ fun ShowUserButton(onClick: () -> Unit) { @Composable fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () -> Unit, accountViewModel: AccountViewModel) { val clipboardManager = LocalClipboardManager.current - val context = LocalContext.current.applicationContext - val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return @@ -960,52 +955,51 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () -> Divider() if (account.isHidden(user)) { DropdownMenuItem(onClick = { - user.let { - accountViewModel.show( - it, - context - ) - }; onDismiss() + accountViewModel.show(user) + onDismiss() }) { Text(stringResource(R.string.unblock_user)) } } else { - DropdownMenuItem(onClick = { user.let { accountViewModel.hide(it, context) }; onDismiss() }) { + DropdownMenuItem(onClick = { + accountViewModel.hide(user) + onDismiss() + }) { Text(stringResource(id = R.string.block_hide_user)) } } Divider() DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.SPAM) - user.let { accountViewModel.hide(it, context) } + accountViewModel.hide(user) onDismiss() }) { Text(stringResource(id = R.string.report_spam_scam)) } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.PROFANITY) - user.let { accountViewModel.hide(it, context) } + accountViewModel.hide(user) onDismiss() }) { Text(stringResource(R.string.report_hateful_speech)) } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.IMPERSONATION) - user.let { accountViewModel.hide(it, context) } + accountViewModel.hide(user) onDismiss() }) { Text(stringResource(id = R.string.report_impersonation)) } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.NUDITY) - user.let { accountViewModel.hide(it, context) } + accountViewModel.hide(user) onDismiss() }) { Text(stringResource(R.string.report_nudity_porn)) } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.ILLEGAL) - user.let { accountViewModel.hide(it, context) } + accountViewModel.hide(user) onDismiss() }) { Text(stringResource(id = R.string.report_illegal_behaviour)) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt index 1707582bc..74746d4af 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -88,7 +87,7 @@ fun SearchScreen( } DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { println("Global Start") NostrGlobalDataSource.start() @@ -127,8 +126,6 @@ private fun SearchBar(accountViewModel: AccountViewModel, navController: NavCont val onlineSearch = NostrSearchEventOrUserDataSource - val ctx = LocalContext.current.applicationContext - val isTrailingIconVisible by remember { derivedStateOf { searchValue.isNotBlank() @@ -237,11 +234,11 @@ private fun SearchBar(accountViewModel: AccountViewModel, navController: NavCont bottom = 10.dp ) ) { - itemsIndexed(searchResults.value, key = { _, item -> "u" + item.pubkeyHex }) { index, item -> + itemsIndexed(searchResults.value, key = { _, item -> "u" + item.pubkeyHex }) { _, item -> UserCompose(item, accountViewModel = accountViewModel, navController = navController) } - itemsIndexed(searchResultsChannels.value, key = { _, item -> "c" + item.idHex }) { index, item -> + itemsIndexed(searchResultsChannels.value, key = { _, item -> "c" + item.idHex }) { _, item -> ChannelName( channelIdHex = item.idHex, channelPicture = item.profilePicture(), @@ -258,7 +255,7 @@ private fun SearchBar(accountViewModel: AccountViewModel, navController: NavCont ) } - itemsIndexed(searchResultsNotes.value, key = { _, item -> "n" + item.idHex }) { index, item -> + itemsIndexed(searchResultsNotes.value, key = { _, item -> "n" + item.idHex }) { _, item -> NoteCompose(item, accountViewModel = accountViewModel, navController = navController) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ThreadScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ThreadScreen.kt index 184ac9c7c..c984de4be 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ThreadScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ThreadScreen.kt @@ -36,7 +36,7 @@ fun ThreadScreen(noteId: String?, accountViewModel: AccountViewModel, navControl } DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { source, event -> + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { println("Thread Start") ThreadFeedFilter.loadThread(noteId)