mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 00:16:59 +00:00
Merge remote-tracking branch 'origin/main' into claude/fix-banner-positioning-susFe
# Conflicts: # amethyst/src/main/java/com/vitorpamplona/amethyst/ui/broadcast/BroadcastBanner.kt
This commit is contained in:
@@ -263,7 +263,6 @@ dependencies {
|
||||
|
||||
// Material 3 Design
|
||||
implementation libs.androidx.material3
|
||||
implementation libs.androidx.material.icons
|
||||
|
||||
// Adaptive Layout / Two Pane
|
||||
implementation libs.androidx.material3.windowSize
|
||||
|
||||
+4
-1
@@ -76,7 +76,10 @@ class PushMessageReceiver : MessagingReceiver() {
|
||||
private suspend fun receiveIfNew(event: GiftWrapEvent) {
|
||||
if (eventCache.get(event.id) == null) {
|
||||
eventCache.put(event.id, event.id)
|
||||
EventNotificationConsumer(appContext).consume(event)
|
||||
// The push server re-wraps the real GiftWrap and strips the p tag;
|
||||
// unwrap the outer layer, feed the inner into LocalCache, and let
|
||||
// the usual Account → EventProcessor chain take over.
|
||||
PushWrapDecryptor.unwrapAndFeed(event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -57,6 +55,8 @@ import com.halilibo.richtext.ui.RichTextStyle
|
||||
import com.halilibo.richtext.ui.material3.RichText
|
||||
import com.halilibo.richtext.ui.resolveDefaults
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.UiSettingsFlow
|
||||
import com.vitorpamplona.amethyst.service.notifications.PushDistributorHandler
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
|
||||
@@ -159,7 +159,7 @@ fun SelectNotificationProvider(sharedPrefs: UiSettingsFlow) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
symbol = MaterialSymbols.Check,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.vitorpamplona.amethyst.service.images.ImageLoaderSetup
|
||||
import com.vitorpamplona.amethyst.service.images.ThumbnailDiskCache
|
||||
import com.vitorpamplona.amethyst.service.location.LocationState
|
||||
import com.vitorpamplona.amethyst.service.notifications.AlwaysOnNotificationServiceManager
|
||||
import com.vitorpamplona.amethyst.service.notifications.NotificationDispatcher
|
||||
import com.vitorpamplona.amethyst.service.notifications.PokeyReceiver
|
||||
import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager
|
||||
import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManagerForRelays
|
||||
@@ -397,6 +398,11 @@ class AppModules(
|
||||
// Manages always-on notification service lifecycle
|
||||
val alwaysOnNotificationServiceManager = AlwaysOnNotificationServiceManager(appContext, applicationIOScope)
|
||||
|
||||
// Observes LocalCache for notification-relevant events and routes them to
|
||||
// EventNotificationConsumer. Sources: FCM, UnifiedPush, Pokey, active relay
|
||||
// subscriptions, and NotificationRelayService.
|
||||
val notificationDispatcher = NotificationDispatcher(appContext, applicationIOScope)
|
||||
|
||||
// Organizes cache clearing
|
||||
val trimmingService by
|
||||
lazy {
|
||||
@@ -494,6 +500,9 @@ class AppModules(
|
||||
// registers to receive events
|
||||
pokeyReceiver.register(appContext)
|
||||
|
||||
// starts observing LocalCache for notification-worthy events
|
||||
notificationDispatcher.start()
|
||||
|
||||
// Watch for account login and start/stop always-on notification service
|
||||
applicationIOScope.launch {
|
||||
sessionManager.accountContent.collectLatest { state ->
|
||||
@@ -515,6 +524,7 @@ class AppModules(
|
||||
|
||||
fun terminate(appContext: Context) {
|
||||
pokeyReceiver.unregister(appContext)
|
||||
notificationDispatcher.stop()
|
||||
BackgroundMedia.removeBackgroundControllerAndReleaseIt()
|
||||
PlaybackServiceClient.shutdown()
|
||||
alwaysOnNotificationServiceManager.stop()
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChann
|
||||
import com.vitorpamplona.amethyst.commons.model.nip53LiveActivities.LiveActivitiesChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.observables.CreatedAtIdHexComparator
|
||||
import com.vitorpamplona.amethyst.commons.model.observables.EventListMatchingFilter
|
||||
import com.vitorpamplona.amethyst.commons.model.observables.NewEventMatchingFilter
|
||||
import com.vitorpamplona.amethyst.commons.model.observables.NoteListMatchingFilter
|
||||
import com.vitorpamplona.amethyst.commons.model.observables.Observable
|
||||
import com.vitorpamplona.amethyst.commons.model.privateChats.ChatroomList
|
||||
@@ -66,6 +67,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryE
|
||||
import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent
|
||||
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageEvent
|
||||
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRelayListEvent
|
||||
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
|
||||
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
@@ -380,6 +382,25 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
}
|
||||
}.buffer(kotlinx.coroutines.channels.Channel.CONFLATED)
|
||||
|
||||
/**
|
||||
* Emits each new event that matches the filter, one at a time, as it is
|
||||
* inserted into the cache. Unlike [observeEvents], this does not accumulate
|
||||
* a list — useful for per-event reactive pipelines like notifications.
|
||||
*/
|
||||
fun <T : Event> observeNewEvents(filter: Filter): Flow<T> =
|
||||
callbackFlow {
|
||||
val newFilter =
|
||||
NewEventMatchingFilter<T>(filter) {
|
||||
trySend(it)
|
||||
}
|
||||
|
||||
observables.put(newFilter, newFilter)
|
||||
|
||||
awaitClose {
|
||||
observables.remove(newFilter)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Event> observeLatestEvent(filter: Filter) = observeEvents<T>(filter).map { it.firstOrNull() }
|
||||
|
||||
@@ -2788,6 +2809,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
is VoiceReplyEvent -> consumeRegularEvent(event, relay, wasVerified)
|
||||
is WakeUpEvent -> consumeRegularEvent(event, relay, wasVerified)
|
||||
is WebBookmarkEvent -> consumeBaseReplaceable(event, relay, wasVerified)
|
||||
is WelcomeEvent -> consumeRegularEvent(event, relay, wasVerified)
|
||||
is WikiNoteEvent -> consume(event, relay, wasVerified)
|
||||
is PaymentTargetsEvent -> consume(event, relay, wasVerified)
|
||||
else -> Log.w("Event Not Supported") { "From ${relay?.url}: ${event.toJson()}" }.let { false }
|
||||
|
||||
+3
-3
@@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -39,6 +37,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeToMessage
|
||||
@@ -95,7 +95,7 @@ fun DisplayCrashMessages(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = stringRes(R.string.crashreport_found_send),
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
|
||||
+74
-182
@@ -45,10 +45,10 @@ import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.sendZa
|
||||
import com.vitorpamplona.amethyst.service.relayClient.authCommand.model.ScreenAuthAccount
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderQueryState
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderQueryState
|
||||
import com.vitorpamplona.amethyst.ui.MainActivity
|
||||
import com.vitorpamplona.amethyst.ui.note.showAmount
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.experimental.notifications.wake.WakeUpEvent
|
||||
import com.vitorpamplona.quartz.marmot.WelcomeResult
|
||||
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
@@ -63,8 +63,6 @@ import com.vitorpamplona.quartz.nip21UriScheme.toNostrUri
|
||||
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip64Chess.baseEvent.BaseChessEvent
|
||||
import com.vitorpamplona.quartz.nip64Chess.challenge.accept.LiveChessGameAcceptEvent
|
||||
import com.vitorpamplona.quartz.nip64Chess.move.LiveChessMoveEvent
|
||||
@@ -115,96 +113,73 @@ class EventNotificationConsumer(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun consume(event: GiftWrapEvent) =
|
||||
/**
|
||||
* Entry point for notification-relevant events arriving into [LocalCache]
|
||||
* from any source (FCM push, UnifiedPush, Pokey, active relay subscriptions,
|
||||
* NotificationRelayService). The [NotificationDispatcher] only invokes this
|
||||
* after [Account.newNotesPreProcessor] has fully unwrapped wraps and seals,
|
||||
* so this method receives the final inner payload directly.
|
||||
*
|
||||
* Matches the event to a logged-in account by its `p` tags and dispatches
|
||||
* to [dispatchForAccount].
|
||||
*/
|
||||
suspend fun consumeFromCache(event: Event) =
|
||||
withWakeLock {
|
||||
Log.d(TAG, "New Notification Arrived")
|
||||
Log.d(TAG) { "New Notification from cache: kind=${event.kind} id=${event.id}" }
|
||||
|
||||
// PushNotification Wraps don't include a receiver.
|
||||
// Test with all logged in accounts
|
||||
var matchAccount = false
|
||||
LocalPreferences.allSavedAccounts().forEach {
|
||||
if (!matchAccount && (it.hasPrivKey || it.loggedInWithExternalSigner)) {
|
||||
LocalPreferences.loadAccountConfigFromEncryptedStorage(it.npub)?.let { acc ->
|
||||
Log.d(TAG) { "New Notification Testing if for ${it.npub}" }
|
||||
try {
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(acc)
|
||||
consumeIfMatchesAccount(event, account)
|
||||
matchAccount = true
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.d(TAG) { "Message was not for user ${it.npub}: ${e.message}" }
|
||||
}
|
||||
}
|
||||
if (!notificationManager().areNotificationsEnabled()) return@withWakeLock
|
||||
|
||||
val taggedNpubs =
|
||||
event
|
||||
.taggedUserIds()
|
||||
.mapTo(mutableSetOf()) { LocalCache.getOrCreateUser(it).pubkeyNpub() }
|
||||
if (taggedNpubs.isEmpty()) return@withWakeLock
|
||||
|
||||
LocalPreferences.allSavedAccounts().forEach { savedAccount ->
|
||||
if (!savedAccount.hasPrivKey && !savedAccount.loggedInWithExternalSigner) return@forEach
|
||||
if (savedAccount.npub !in taggedNpubs) return@forEach
|
||||
|
||||
val accountSettings = LocalPreferences.loadAccountConfigFromEncryptedStorage(savedAccount.npub) ?: return@forEach
|
||||
try {
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(accountSettings)
|
||||
dispatchForAccount(event, account)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.d(TAG) { "Failed to dispatch ${event.kind} ${event.id} for ${savedAccount.npub}: ${e.message}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun consumeIfMatchesAccount(
|
||||
pushWrappedEvent: GiftWrapEvent,
|
||||
private suspend fun dispatchForAccount(
|
||||
event: Event,
|
||||
account: Account,
|
||||
) {
|
||||
val notificationEvent = pushWrappedEvent.unwrapThrowing(account.signer)
|
||||
consumeNotificationEvent(notificationEvent, account)
|
||||
}
|
||||
|
||||
suspend fun consumeNotificationEvent(
|
||||
notificationEvent: Event,
|
||||
account: Account,
|
||||
) {
|
||||
Log.d(TAG) { "New Notification ${notificationEvent.kind} ${notificationEvent.id} Arrived for ${account.signer.pubKey}" }
|
||||
val consumed = LocalCache.hasConsumed(notificationEvent)
|
||||
Log.d(TAG) { "New Notification ${notificationEvent.kind} ${notificationEvent.id} Arrived for ${account.signer.pubKey} consumed= $consumed" }
|
||||
if (!consumed) {
|
||||
Log.d(TAG, "New Notification was verified")
|
||||
if (!notificationManager().areNotificationsEnabled()) return
|
||||
Log.d(TAG, "Notifications are enabled")
|
||||
|
||||
unwrapAndConsume(notificationEvent, account.signer)?.let { innerNote ->
|
||||
val innerEvent = innerNote.event
|
||||
Log.d(TAG) { "Unwrapped consume ${innerEvent?.javaClass?.simpleName}" }
|
||||
|
||||
when (innerEvent) {
|
||||
is PrivateDmEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
|
||||
is LnZapEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
|
||||
is ChatMessageEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
|
||||
is ChatMessageEncryptedFileHeaderEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
|
||||
is ReactionEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
|
||||
is LiveChessGameAcceptEvent -> {
|
||||
notifyChessEvent(innerEvent, account, R.string.app_notification_chess_challenge_accepted)
|
||||
}
|
||||
|
||||
is LiveChessMoveEvent -> {
|
||||
notifyChessEvent(innerEvent, account, R.string.app_notification_chess_your_turn)
|
||||
}
|
||||
|
||||
is CallOfferEvent -> {
|
||||
notifyIncomingCall(innerEvent, account)
|
||||
}
|
||||
|
||||
is WakeUpEvent -> {
|
||||
wakeUpFor(innerEvent, innerNote, account)
|
||||
}
|
||||
|
||||
is WelcomeEvent -> {
|
||||
notify(innerEvent, account)
|
||||
}
|
||||
}
|
||||
// Calls and wake-ups are high-priority and always notify, even when MainActivity is visible.
|
||||
when (event) {
|
||||
is CallOfferEvent -> {
|
||||
notifyIncomingCall(event, account)
|
||||
return
|
||||
}
|
||||
|
||||
is WakeUpEvent -> {
|
||||
wakeUpFor(event, LocalCache.getOrCreateNote(event.id), account)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Everything else is suppressed while the user is actively on the home screen.
|
||||
if (MainActivity.isResumed) return
|
||||
|
||||
when (event) {
|
||||
is PrivateDmEvent -> notify(event, account)
|
||||
is LnZapEvent -> notify(event, account)
|
||||
is ChatMessageEvent -> notify(event, account)
|
||||
is ChatMessageEncryptedFileHeaderEvent -> notify(event, account)
|
||||
is ReactionEvent -> notify(event, account)
|
||||
is LiveChessGameAcceptEvent -> notifyChessEvent(event, account, R.string.app_notification_chess_challenge_accepted)
|
||||
is LiveChessMoveEvent -> notifyChessEvent(event, account, R.string.app_notification_chess_your_turn)
|
||||
// WelcomeEvent is dispatched directly from processMarmotWelcomeFlow
|
||||
// (no `p` tag, so tag-based matching doesn't work).
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,79 +224,6 @@ class EventNotificationConsumer(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun findAccountAndConsume(event: Event) =
|
||||
withWakeLock {
|
||||
Log.d(TAG, "New Notification Arrived")
|
||||
val users = event.taggedUserIds().map { LocalCache.getOrCreateUser(it) }
|
||||
val npubs = users.map { it.pubkeyNpub() }.toSet()
|
||||
|
||||
// PushNotification Wraps don't include a receiver.
|
||||
// Test with all logged in accounts
|
||||
var matchAccount = false
|
||||
LocalPreferences.allSavedAccounts().forEach {
|
||||
if (!matchAccount && (it.hasPrivKey || it.loggedInWithExternalSigner) && it.npub in npubs) {
|
||||
LocalPreferences.loadAccountConfigFromEncryptedStorage(it.npub)?.let { accountSettings ->
|
||||
Log.d(TAG) { "New Notification Testing if for ${it.npub}" }
|
||||
try {
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(accountSettings)
|
||||
consumeNotificationEvent(event, account)
|
||||
matchAccount = true
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.d(TAG) { "Message was not for user ${it.npub}: ${e.message}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun unwrapAndConsume(
|
||||
event: Event,
|
||||
signer: NostrSigner,
|
||||
): Note? {
|
||||
if (LocalCache.hasConsumed(event)) return null
|
||||
|
||||
return when (event) {
|
||||
is GiftWrapEvent -> {
|
||||
if (LocalCache.justConsume(event, null, false)) {
|
||||
// new event
|
||||
val inner = event.unwrapThrowing(signer)
|
||||
// clear the encrypted payload to save memory
|
||||
LocalCache.getOrCreateNote(event.id).event = event.copyNoContent()
|
||||
|
||||
unwrapAndConsume(inner, signer)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
is SealedRumorEvent -> {
|
||||
if (LocalCache.justConsume(event, null, false)) {
|
||||
// new event
|
||||
val inner = event.unsealThrowing(signer)
|
||||
// clear the encrypted payload to save memory
|
||||
LocalCache.getOrCreateNote(event.id).event = event.copyNoContent()
|
||||
|
||||
val note = LocalCache.getOrCreateNote(inner.id)
|
||||
// this is not verifiable
|
||||
if (LocalCache.justConsume(inner, null, true)) {
|
||||
note
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
val note = LocalCache.getOrCreateNote(event.id)
|
||||
LocalCache.justConsume(event, null, false)
|
||||
note
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun notify(
|
||||
event: ChatMessageEncryptedFileHeaderEvent,
|
||||
account: Account,
|
||||
@@ -469,38 +371,28 @@ class EventNotificationConsumer(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun notify(
|
||||
/**
|
||||
* Welcomes have no `p` tag, so [consumeFromCache]'s tag-based account match
|
||||
* can't route them. They are instead dispatched here directly by
|
||||
* [com.vitorpamplona.amethyst.ui.screen.loggedIn.processMarmotWelcomeFlow]
|
||||
* after [MarmotManager.processWelcome] joins the group — which is also the
|
||||
* only place we reliably know which account the invite was for.
|
||||
*/
|
||||
suspend fun notifyWelcome(
|
||||
event: WelcomeEvent,
|
||||
account: Account,
|
||||
) {
|
||||
) = withWakeLock {
|
||||
Log.d(TAG, "New Marmot Welcome to Notify")
|
||||
|
||||
if (!notificationManager().areNotificationsEnabled()) return@withWakeLock
|
||||
if (MainActivity.isResumed) return@withWakeLock
|
||||
|
||||
// old event being re-broadcast
|
||||
if (event.createdAt < TimeUtils.fifteenMinutesAgo()) return
|
||||
if (event.createdAt < TimeUtils.fifteenMinutesAgo()) return@withWakeLock
|
||||
// a welcome we ourselves emitted
|
||||
if (event.pubKey == account.signer.pubKey) return
|
||||
if (event.pubKey == account.signer.pubKey) return@withWakeLock
|
||||
|
||||
val nostrGroupId = event.nostrGroupId() ?: return
|
||||
val manager = account.marmotManager ?: return
|
||||
|
||||
// Best-effort: process the welcome here so the chatroom is hydrated
|
||||
// before composing the notification body. The push-notification
|
||||
// background path does NOT go through Account.eventProcessor, so
|
||||
// without this the invitee would only join the group later, when
|
||||
// they next open the app and the relay subscription redelivers.
|
||||
if (!manager.isMember(nostrGroupId)) {
|
||||
try {
|
||||
val result = manager.processWelcome(event, nostrGroupId)
|
||||
if (result is WelcomeResult.Joined) {
|
||||
val chatroom = account.marmotGroupList.getOrCreateGroup(result.nostrGroupId)
|
||||
manager.syncMetadataTo(result.nostrGroupId, chatroom)
|
||||
account.marmotGroupList.notifyGroupChanged(result.nostrGroupId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.w(TAG) { "Failed to process Marmot Welcome from notification path: ${e.message}" }
|
||||
}
|
||||
}
|
||||
val nostrGroupId = event.nostrGroupId() ?: return@withWakeLock
|
||||
|
||||
val chatroom = account.marmotGroupList.getOrCreateGroup(nostrGroupId)
|
||||
val groupName = chatroom.displayName.value?.takeIf { it.isNotBlank() } ?: "a private group"
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.service.notifications
|
||||
|
||||
import android.content.Context
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.quartz.experimental.notifications.wake.WakeUpEvent
|
||||
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent
|
||||
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import com.vitorpamplona.quartz.nip64Chess.challenge.accept.LiveChessGameAcceptEvent
|
||||
import com.vitorpamplona.quartz.nip64Chess.move.LiveChessMoveEvent
|
||||
import com.vitorpamplona.quartz.nipACWebRtcCalls.events.CallOfferEvent
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Observes [LocalCache] for notification-relevant events and hands them to
|
||||
* [EventNotificationConsumer]. Events can reach [LocalCache] from any source —
|
||||
* FCM push, UnifiedPush, Pokey, active relay subscriptions, or the
|
||||
* [NotificationRelayService] — and the observer fires once per new insertion,
|
||||
* giving us a single dedup'd source of truth for notification triggers.
|
||||
*
|
||||
* The dispatcher itself is always on (any of the delivery paths can fire it).
|
||||
* Foreground suppression and per-event filtering are handled downstream in
|
||||
* [EventNotificationConsumer].
|
||||
*/
|
||||
class NotificationDispatcher(
|
||||
private val context: Context,
|
||||
private val scope: CoroutineScope,
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "NotificationDispatcher"
|
||||
|
||||
// The dispatcher observes the *final* notification payload kinds.
|
||||
// GiftWrap/EphemeralGiftWrap (1059/21059) and SealedRumor (13) are NOT
|
||||
// listed here — by the time we care, Account.newNotesPreProcessor has
|
||||
// already unwrapped them and inserted the inner payload into LocalCache,
|
||||
// which fires the observer a second time on the inner event.
|
||||
//
|
||||
// WelcomeEvent (kind:444) is also excluded: it has no `p` tag, so
|
||||
// consumeFromCache can't route it. It's delivered directly via
|
||||
// [notifyWelcome] from processMarmotWelcomeFlow, which does know the
|
||||
// recipient account.
|
||||
private val NOTIFICATION_KINDS =
|
||||
listOf(
|
||||
// Direct-arrival
|
||||
PrivateDmEvent.KIND,
|
||||
LnZapEvent.KIND,
|
||||
ReactionEvent.KIND,
|
||||
LiveChessGameAcceptEvent.KIND,
|
||||
LiveChessMoveEvent.KIND,
|
||||
WakeUpEvent.KIND,
|
||||
// Unwrapped from GiftWrap → Seal
|
||||
ChatMessageEvent.KIND,
|
||||
ChatMessageEncryptedFileHeaderEvent.KIND,
|
||||
// Unwrapped from EphemeralGiftWrap
|
||||
CallOfferEvent.KIND,
|
||||
)
|
||||
}
|
||||
|
||||
private val consumer = EventNotificationConsumer(context)
|
||||
private var job: Job? = null
|
||||
|
||||
fun start() {
|
||||
if (job?.isActive == true) return
|
||||
Log.d(TAG, "Starting notification dispatcher")
|
||||
job =
|
||||
scope.launch {
|
||||
LocalCache
|
||||
.observeNewEvents<Event>(Filter(kinds = NOTIFICATION_KINDS))
|
||||
.collect { event ->
|
||||
try {
|
||||
consumer.consumeFromCache(event)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.e(TAG, "Failed to dispatch notification for ${event.kind} ${event.id}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
job?.cancel()
|
||||
job = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct-invocation entry point for [WelcomeEvent]. Bypasses the
|
||||
* cache-observer path because Welcomes have no `p` tag for account
|
||||
* routing. Called from processMarmotWelcomeFlow once MLS group join
|
||||
* succeeds — at which point we know which account the invite was for.
|
||||
*/
|
||||
suspend fun notifyWelcome(
|
||||
event: WelcomeEvent,
|
||||
account: Account,
|
||||
) {
|
||||
try {
|
||||
consumer.notifyWelcome(event, account)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.e(TAG, "Failed to dispatch Welcome notification ${event.id}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -26,6 +26,7 @@ import android.content.Context.RECEIVER_EXPORTED
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
@@ -75,7 +76,8 @@ class PokeyReceiver : BroadcastReceiver() {
|
||||
|
||||
scope.launch {
|
||||
try {
|
||||
EventNotificationConsumer(context.applicationContext).findAccountAndConsume(Event.fromJson(eventStr))
|
||||
// Feeds the shared cache; NotificationDispatcher observes and dispatches.
|
||||
LocalCache.justConsume(Event.fromJson(eventStr), null, false)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to parse Pokey Event", e)
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.service.notifications
|
||||
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
||||
/**
|
||||
* Handles GiftWraps that arrive via FCM / UnifiedPush. The push server
|
||||
* re-wraps the real NIP-59 GiftWrap inside its own outer GiftWrap and strips
|
||||
* the recipient `p` tag, so neither the relay's [CacheClientConnector] nor
|
||||
* the account's [GiftWrapEventHandler] can identify which account owns it.
|
||||
* We have to probe every saved account's signer until one decrypts.
|
||||
*
|
||||
* Once decrypted, the inner event is fed into [LocalCache]. From there the
|
||||
* normal `Account.newNotesPreProcessor` → `GiftWrapEventHandler` →
|
||||
* `SealedRumorEventHandler` chain unwraps any remaining layers, and
|
||||
* [NotificationDispatcher] picks up the final payload and notifies.
|
||||
*/
|
||||
object PushWrapDecryptor {
|
||||
private const val TAG = "PushWrapDecryptor"
|
||||
|
||||
suspend fun unwrapAndFeed(outerWrap: GiftWrapEvent) {
|
||||
LocalPreferences.allSavedAccounts().forEach { savedAccount ->
|
||||
if (!savedAccount.hasPrivKey && !savedAccount.loggedInWithExternalSigner) return@forEach
|
||||
|
||||
val accountSettings = LocalPreferences.loadAccountConfigFromEncryptedStorage(savedAccount.npub) ?: return@forEach
|
||||
try {
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(accountSettings)
|
||||
val inner = outerWrap.unwrapThrowing(account.signer)
|
||||
LocalCache.justConsume(inner, null, false)
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.d(TAG) { "Push wrap not for ${savedAccount.npub}: ${e.message}" }
|
||||
}
|
||||
}
|
||||
Log.w(TAG) { "Push wrap ${outerWrap.id} did not decrypt for any saved account" }
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -27,8 +27,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ZoomOutMap
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -41,6 +39,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
||||
@@ -86,7 +86,7 @@ fun FullScreenButton(
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ZoomOutMap,
|
||||
symbol = MaterialSymbols.ZoomOutMap,
|
||||
contentDescription = stringRes(id = R.string.enter_picture_in_picture),
|
||||
modifier = modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
|
||||
+4
-5
@@ -27,9 +27,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeOff
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -43,6 +40,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size30Modifier
|
||||
@@ -125,7 +124,7 @@ fun MuteButton(
|
||||
@Composable
|
||||
fun MutedIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.VolumeOff,
|
||||
symbol = MaterialSymbols.AutoMirrored.VolumeOff,
|
||||
contentDescription = stringRes(id = R.string.muted_button),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Size30Modifier,
|
||||
@@ -135,7 +134,7 @@ fun MutedIcon() {
|
||||
@Composable
|
||||
fun MuteIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.VolumeUp,
|
||||
symbol = MaterialSymbols.AutoMirrored.VolumeUp,
|
||||
contentDescription = stringRes(id = R.string.mute_button),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Size30Modifier,
|
||||
|
||||
+9
-16
@@ -27,15 +27,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeOff
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.filled.PictureInPicture
|
||||
import androidx.compose.material.icons.filled.SaveAlt
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material.icons.filled.ZoomOutMap
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -48,6 +39,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.VideoPlayerAction
|
||||
import com.vitorpamplona.amethyst.ui.components.M3ActionDialog
|
||||
import com.vitorpamplona.amethyst.ui.components.M3ActionRow
|
||||
@@ -140,7 +133,7 @@ fun OverflowMenuButton(
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
symbol = MaterialSymbols.MoreVert,
|
||||
contentDescription = stringRes(R.string.more_options),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Size20Modifier,
|
||||
@@ -159,7 +152,7 @@ fun OverflowMenuButton(
|
||||
VideoPlayerAction.Fullscreen -> {
|
||||
onFullscreenClick?.let { zoom ->
|
||||
M3ActionRow(
|
||||
icon = Icons.Default.ZoomOutMap,
|
||||
icon = MaterialSymbols.ZoomOutMap,
|
||||
text = stringRes(R.string.video_player_settings_action_fullscreen),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
@@ -170,7 +163,7 @@ fun OverflowMenuButton(
|
||||
|
||||
VideoPlayerAction.Mute -> {
|
||||
M3ActionRow(
|
||||
icon = if (startingMuteState) Icons.AutoMirrored.Filled.VolumeOff else Icons.AutoMirrored.Filled.VolumeUp,
|
||||
icon = if (startingMuteState) MaterialSymbols.AutoMirrored.VolumeOff else MaterialSymbols.AutoMirrored.VolumeUp,
|
||||
text = if (startingMuteState) stringRes(R.string.muted_button) else stringRes(R.string.mute_button),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
@@ -180,7 +173,7 @@ fun OverflowMenuButton(
|
||||
|
||||
VideoPlayerAction.Quality -> {
|
||||
M3ActionRow(
|
||||
icon = Icons.Default.Settings,
|
||||
icon = MaterialSymbols.Settings,
|
||||
text = stringRes(R.string.call_settings_video_quality),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
@@ -190,7 +183,7 @@ fun OverflowMenuButton(
|
||||
|
||||
VideoPlayerAction.Share -> {
|
||||
M3ActionRow(
|
||||
icon = Icons.Default.Share,
|
||||
icon = MaterialSymbols.Share,
|
||||
text = stringRes(R.string.share_or_save),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
@@ -200,7 +193,7 @@ fun OverflowMenuButton(
|
||||
|
||||
VideoPlayerAction.Download -> {
|
||||
M3ActionRow(
|
||||
icon = Icons.Default.SaveAlt,
|
||||
icon = MaterialSymbols.SaveAlt,
|
||||
text = stringRes(R.string.download_to_phone),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
@@ -210,7 +203,7 @@ fun OverflowMenuButton(
|
||||
|
||||
VideoPlayerAction.PictureInPicture -> {
|
||||
M3ActionRow(
|
||||
icon = Icons.Default.PictureInPicture,
|
||||
icon = MaterialSymbols.PictureInPicture,
|
||||
text = stringRes(R.string.picture_in_picture),
|
||||
) {
|
||||
menuExpanded.value = false
|
||||
|
||||
+4
-5
@@ -28,9 +28,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Pause
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -44,6 +41,8 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.PlayIconSize
|
||||
@@ -114,13 +113,13 @@ fun PlayPauseButton(
|
||||
) {
|
||||
if (!isPlaying) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlayArrow,
|
||||
symbol = MaterialSymbols.PlayArrow,
|
||||
modifier = Size50Modifier,
|
||||
contentDescription = stringRes(R.string.play),
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Pause,
|
||||
symbol = MaterialSymbols.Pause,
|
||||
modifier = Size50Modifier,
|
||||
contentDescription = stringRes(R.string.pause),
|
||||
)
|
||||
|
||||
+8
-10
@@ -29,10 +29,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PictureInPicture
|
||||
import androidx.compose.material.icons.filled.SaveAlt
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -47,7 +43,6 @@ 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.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
@@ -55,6 +50,9 @@ import androidx.media3.common.Player
|
||||
import androidx.media3.common.Tracks
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
|
||||
import com.vitorpamplona.amethyst.model.VideoButtonLocation
|
||||
import com.vitorpamplona.amethyst.model.VideoPlayerAction
|
||||
@@ -255,7 +253,7 @@ fun RenderTopButtons(
|
||||
VideoPlayerAction.Share -> {
|
||||
AnimatedTopBarIconButton(
|
||||
controllerVisible = controllerVisible,
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
contentDescription = stringRes(R.string.share_or_save),
|
||||
onClick = { shareDialogVisible.value = true },
|
||||
)
|
||||
@@ -264,7 +262,7 @@ fun RenderTopButtons(
|
||||
VideoPlayerAction.Download -> {
|
||||
AnimatedTopBarIconButton(
|
||||
controllerVisible = controllerVisible,
|
||||
imageVector = Icons.Default.SaveAlt,
|
||||
symbol = MaterialSymbols.SaveAlt,
|
||||
contentDescription = stringRes(R.string.download_to_phone),
|
||||
onClick = saveAction,
|
||||
)
|
||||
@@ -273,7 +271,7 @@ fun RenderTopButtons(
|
||||
VideoPlayerAction.PictureInPicture -> {
|
||||
AnimatedTopBarIconButton(
|
||||
controllerVisible = controllerVisible,
|
||||
imageVector = Icons.Default.PictureInPicture,
|
||||
symbol = MaterialSymbols.PictureInPicture,
|
||||
contentDescription = stringRes(R.string.picture_in_picture),
|
||||
onClick = onPictureInPictureClick,
|
||||
)
|
||||
@@ -323,7 +321,7 @@ fun RenderTopButtons(
|
||||
@Composable
|
||||
internal fun AnimatedTopBarIconButton(
|
||||
controllerVisible: State<Boolean>,
|
||||
imageVector: ImageVector,
|
||||
symbol: MaterialSymbol,
|
||||
contentDescription: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -348,7 +346,7 @@ internal fun AnimatedTopBarIconButton(
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = imageVector,
|
||||
symbol = symbol,
|
||||
contentDescription = contentDescription,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Size20Modifier,
|
||||
|
||||
+3
-3
@@ -31,8 +31,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -50,6 +48,8 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
||||
@@ -130,7 +130,7 @@ fun SaveMediaButton(onSaveClick: (localContext: Context) -> Unit) {
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Download,
|
||||
symbol = MaterialSymbols.Download,
|
||||
modifier = Size20Modifier,
|
||||
contentDescription = stringRes(R.string.download_to_phone),
|
||||
)
|
||||
|
||||
+3
-3
@@ -27,8 +27,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -42,6 +40,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
||||
@@ -98,7 +98,7 @@ fun ShareButton(innerAction: @Composable (MutableState<Boolean>, () -> Unit) ->
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
modifier = Size20Modifier,
|
||||
contentDescription = stringRes(R.string.share_or_save),
|
||||
)
|
||||
|
||||
+4
-5
@@ -26,9 +26,6 @@ import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Forward10
|
||||
import androidx.compose.material.icons.filled.Replay10
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -38,6 +35,8 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.playback.composable.SKIP_SECONDS
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
@@ -88,9 +87,9 @@ fun SkipButton(
|
||||
isForward: Boolean,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
val icon = if (isForward) Icons.Default.Forward10 else Icons.Default.Replay10
|
||||
val icon = if (isForward) MaterialSymbols.Forward10 else MaterialSymbols.Replay10
|
||||
val label = if (isForward) stringRes(R.string.skip_forward, SKIP_SECONDS) else stringRes(R.string.skip_back, SKIP_SECONDS)
|
||||
IconButton(onClick = onClick, modifier = Modifier.size(48.dp)) {
|
||||
Icon(imageVector = icon, contentDescription = label, tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(symbol = icon, contentDescription = label, tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -30,8 +30,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -56,6 +54,8 @@ import androidx.media3.common.Tracks
|
||||
import androidx.media3.common.VideoSize
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
@@ -108,7 +108,7 @@ fun VideoQualityButton(
|
||||
modifier = Size50Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Settings,
|
||||
symbol = MaterialSymbols.Settings,
|
||||
contentDescription = stringRes(id = R.string.call_settings_video_quality),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Size20Modifier,
|
||||
|
||||
+3
-3
@@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
@@ -39,6 +37,8 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.EmptyTagList
|
||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -87,7 +87,7 @@ fun NotifyRequestDialog(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
|
||||
@@ -56,6 +56,15 @@ import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
// True only while MainActivity is resumed. Used by the notification
|
||||
// pipeline to suppress in-app notifications — PiP/Call activities
|
||||
// have their own lifecycle, so MainActivity is paused while they're up.
|
||||
@Volatile
|
||||
var isResumed: Boolean = false
|
||||
private set
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
@@ -74,6 +83,7 @@ class MainActivity : AppCompatActivity() {
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
isResumed = true
|
||||
|
||||
Log.d("ActivityLifecycle") { "MainActivity.onResume $this" }
|
||||
|
||||
@@ -82,6 +92,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
isResumed = false
|
||||
Log.d("ActivityLifecycle") { "MainActivity.onPause $this" }
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
|
||||
@@ -37,8 +37,6 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -74,6 +72,8 @@ import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.playback.composable.VideoView
|
||||
@@ -457,14 +457,14 @@ private fun AddLnInvoiceButton(
|
||||
) {
|
||||
if (!isLnInvoiceActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CurrencyBitcoin,
|
||||
symbol = MaterialSymbols.CurrencyBitcoin,
|
||||
contentDescription = stringRes(id = R.string.add_bitcoin_invoice),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CurrencyBitcoin,
|
||||
symbol = MaterialSymbols.CurrencyBitcoin,
|
||||
contentDescription = stringRes(id = R.string.cancel_bitcoin_invoice),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = BitcoinOrange,
|
||||
|
||||
@@ -27,8 +27,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
@@ -44,6 +42,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg
|
||||
import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg2
|
||||
import com.vitorpamplona.amethyst.ui.components.util.setText
|
||||
@@ -141,7 +141,7 @@ fun InformationDialog(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
|
||||
+3
-4
@@ -35,9 +35,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -57,6 +54,8 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectSingleFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
|
||||
@@ -347,7 +346,7 @@ private fun ExpandableSection(
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Icon(
|
||||
imageVector = if (expanded.value) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
|
||||
symbol = if (expanded.value) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore,
|
||||
contentDescription = if (expanded.value) "Collapse" else "Expand",
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
|
||||
+3
-4
@@ -29,9 +29,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Add
|
||||
import androidx.compose.material.icons.rounded.Delete
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -44,6 +41,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.SettingsCategory
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.SettingsCategoryWithButton
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -209,7 +208,7 @@ fun MediaServerEntry(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isAmethystDefault) Icons.Rounded.Add else Icons.Rounded.Delete,
|
||||
symbol = if (isAmethystDefault) MaterialSymbols.Add else MaterialSymbols.Delete,
|
||||
contentDescription =
|
||||
if (isAmethystDefault) {
|
||||
stringRes(id = R.string.add_media_server)
|
||||
|
||||
+3
-3
@@ -31,8 +31,6 @@ import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Delete
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -55,6 +53,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -203,7 +203,7 @@ fun PaymentTargetEntry(
|
||||
}
|
||||
IconButton(onClick = onDelete) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Delete,
|
||||
symbol = MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(id = R.string.delete_payment_target),
|
||||
)
|
||||
}
|
||||
|
||||
+3
-3
@@ -26,8 +26,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -41,6 +39,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
@@ -91,7 +91,7 @@ fun RecordVoiceButton(
|
||||
|
||||
// Microphone icon
|
||||
Icon(
|
||||
imageVector = Icons.Default.Mic,
|
||||
symbol = MaterialSymbols.Mic,
|
||||
contentDescription = stringRes(id = R.string.record_a_message),
|
||||
modifier = Modifier.height(22.dp),
|
||||
tint =
|
||||
|
||||
+3
-3
@@ -35,8 +35,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Stop
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -51,6 +49,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
/**
|
||||
@@ -228,7 +228,7 @@ fun FloatingRecordingIndicator(
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Default.Stop,
|
||||
symbol = MaterialSymbols.Stop,
|
||||
contentDescription = recordingLabel,
|
||||
tint = Color.White,
|
||||
modifier =
|
||||
|
||||
+3
-3
@@ -24,8 +24,6 @@ import android.net.Uri
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AttachFile
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -39,6 +37,8 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadingAnimation
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -83,7 +83,7 @@ private fun FileSelectButton(
|
||||
) {
|
||||
if (!isUploading) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AttachFile,
|
||||
symbol = MaterialSymbols.AttachFile,
|
||||
contentDescription = stringRes(id = R.string.upload_file),
|
||||
modifier = Modifier.height(20.dp),
|
||||
tint = tint,
|
||||
|
||||
+3
-3
@@ -25,8 +25,6 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.PickVisualMediaRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddPhotoAlternate
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -41,6 +39,8 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadingAnimation
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -128,7 +128,7 @@ private fun GallerySelectButton(
|
||||
) {
|
||||
if (!isUploading) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AddPhotoAlternate,
|
||||
symbol = MaterialSymbols.AddPhotoAlternate,
|
||||
contentDescription = stringRes(id = R.string.upload_image),
|
||||
modifier = Modifier.height(25.dp),
|
||||
tint = tint,
|
||||
|
||||
+7
-7
@@ -38,9 +38,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AudioFile
|
||||
import androidx.compose.material.icons.filled.PictureAsPdf
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -65,6 +62,9 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.playback.composable.VideoView
|
||||
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||
@@ -126,12 +126,12 @@ fun ShowImageGallery(
|
||||
)
|
||||
} else if (media.isAudio() == true) {
|
||||
FilePreviewPlaceholder(
|
||||
icon = Icons.Default.AudioFile,
|
||||
icon = MaterialSymbols.AudioFile,
|
||||
label = media.mimeType ?: "audio/*",
|
||||
)
|
||||
} else if (media.isDocument()) {
|
||||
FilePreviewPlaceholder(
|
||||
icon = Icons.Default.PictureAsPdf,
|
||||
icon = MaterialSymbols.PictureAsPdf,
|
||||
label = media.mimeType ?: "application/pdf",
|
||||
)
|
||||
} else if (media.isVideo() == true && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
@@ -279,7 +279,7 @@ fun UploadingState(
|
||||
|
||||
@Composable
|
||||
fun FilePreviewPlaceholder(
|
||||
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
label: String,
|
||||
) {
|
||||
Box(
|
||||
@@ -295,7 +295,7 @@ fun FilePreviewPlaceholder(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = label,
|
||||
modifier = Modifier.size(40.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
|
||||
@@ -27,9 +27,6 @@ import android.os.Environment
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CameraAlt
|
||||
import androidx.compose.material.icons.filled.Videocam
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -48,6 +45,8 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -129,7 +128,7 @@ fun PictureButton(onClick: () -> Unit) {
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CameraAlt,
|
||||
symbol = MaterialSymbols.CameraAlt,
|
||||
contentDescription = stringRes(id = R.string.take_a_picture),
|
||||
modifier = Modifier.height(22.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
@@ -216,7 +215,7 @@ fun VideoButton(onClick: () -> Unit) {
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Videocam,
|
||||
symbol = MaterialSymbols.Videocam,
|
||||
contentDescription = stringRes(id = R.string.record_a_video),
|
||||
modifier = Modifier.height(22.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
|
||||
+8
-12
@@ -32,12 +32,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material.icons.filled.Pause
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Stop
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -56,6 +50,8 @@ import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.components.AudioWaveformReadOnly
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.AudioMeta
|
||||
@@ -125,7 +121,7 @@ fun VoiceMessagePreview(
|
||||
modifier = Modifier.size(48.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isPlaying) Icons.Default.Pause else Icons.Default.PlayArrow,
|
||||
symbol = if (isPlaying) MaterialSymbols.Pause else MaterialSymbols.PlayArrow,
|
||||
contentDescription = if (isPlaying) stringRes(context, R.string.pause) else stringRes(context, R.string.play),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -168,7 +164,7 @@ fun VoiceMessagePreview(
|
||||
modifier = Modifier.size(48.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
symbol = MaterialSymbols.Close,
|
||||
contentDescription = stringRes(context, R.string.remove),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -199,7 +195,7 @@ private fun ReRecordButton(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Mic,
|
||||
symbol = MaterialSymbols.Mic,
|
||||
contentDescription = stringRes(id = R.string.record_a_message),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -224,9 +220,9 @@ private fun ReRecordButton(
|
||||
}
|
||||
val icon =
|
||||
if (isRecording) {
|
||||
Icons.Default.Stop
|
||||
MaterialSymbols.Stop
|
||||
} else {
|
||||
Icons.Default.Mic
|
||||
MaterialSymbols.Mic
|
||||
}
|
||||
val label =
|
||||
if (isRecording) {
|
||||
@@ -246,7 +242,7 @@ private fun ReRecordButton(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = iconDescription,
|
||||
tint = contentColor,
|
||||
)
|
||||
|
||||
@@ -39,11 +39,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Error
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.filled.Sync
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
@@ -60,6 +55,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.defaults.Constants
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.broadcast.BroadcastEvent
|
||||
import com.vitorpamplona.amethyst.service.broadcast.BroadcastStatus
|
||||
import com.vitorpamplona.amethyst.service.broadcast.RelayResult
|
||||
@@ -140,7 +137,7 @@ private fun SingleBroadcastContent(broadcast: BroadcastEvent) {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Sync,
|
||||
symbol = MaterialSymbols.Sync,
|
||||
contentDescription = stringRes(R.string.broadcasting),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
@@ -198,7 +195,7 @@ private fun MultipleBroadcastsContent(broadcasts: ImmutableList<BroadcastEvent>)
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Sync,
|
||||
symbol = MaterialSymbols.Sync,
|
||||
contentDescription = stringRes(R.string.broadcasting),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
@@ -258,15 +255,15 @@ fun CompletedBroadcastContent(
|
||||
|
||||
val (statusIcon, iconTint) =
|
||||
when (broadcast.status) {
|
||||
BroadcastStatus.SUCCESS -> Icons.Default.CheckCircle to successColor
|
||||
BroadcastStatus.PARTIAL -> Icons.Default.Error to warningColor
|
||||
BroadcastStatus.FAILED -> Icons.Default.Error to MaterialTheme.colorScheme.error
|
||||
BroadcastStatus.IN_PROGRESS -> Icons.Default.CheckCircle to MaterialTheme.colorScheme.primary
|
||||
BroadcastStatus.SUCCESS -> MaterialSymbols.CheckCircle to successColor
|
||||
BroadcastStatus.PARTIAL -> MaterialSymbols.Error to warningColor
|
||||
BroadcastStatus.FAILED -> MaterialSymbols.Error to MaterialTheme.colorScheme.error
|
||||
BroadcastStatus.IN_PROGRESS -> MaterialSymbols.CheckCircle to MaterialTheme.colorScheme.primary
|
||||
}
|
||||
|
||||
// Small status icon (like BroadcastBanner)
|
||||
Icon(
|
||||
imageVector = statusIcon,
|
||||
symbol = statusIcon,
|
||||
contentDescription = broadcast.status.name,
|
||||
tint = iconTint,
|
||||
modifier = Modifier.size(18.dp),
|
||||
@@ -310,7 +307,7 @@ fun CompletedBroadcastContent(
|
||||
modifier = Modifier.size(22.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Refresh,
|
||||
symbol = MaterialSymbols.Refresh,
|
||||
contentDescription = stringRes(R.string.retry_failed),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
@@ -353,16 +350,16 @@ fun MultipleCompletedBroadcastContent(
|
||||
|
||||
val (statusIcon, iconTint) =
|
||||
if (allSuccess) {
|
||||
Icons.Default.CheckCircle to successColor
|
||||
MaterialSymbols.CheckCircle to successColor
|
||||
} else if (allFailed) {
|
||||
Icons.Default.Error to MaterialTheme.colorScheme.error
|
||||
MaterialSymbols.Error to MaterialTheme.colorScheme.error
|
||||
} else {
|
||||
Icons.Default.Error to warningColor
|
||||
MaterialSymbols.Error to warningColor
|
||||
}
|
||||
|
||||
// Small status icon (like BroadcastBanner)
|
||||
Icon(
|
||||
imageVector = statusIcon,
|
||||
symbol = statusIcon,
|
||||
contentDescription =
|
||||
if (allSuccess) {
|
||||
stringRes(R.string.bradcasting_result_success)
|
||||
@@ -413,7 +410,7 @@ fun MultipleCompletedBroadcastContent(
|
||||
modifier = Modifier.size(22.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Refresh,
|
||||
symbol = MaterialSymbols.Refresh,
|
||||
contentDescription = stringRes(R.string.retry_failed),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
|
||||
+16
-21
@@ -42,13 +42,6 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Error
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material.icons.filled.HourglassEmpty
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -78,6 +71,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.defaults.Constants
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.broadcast.BroadcastEvent
|
||||
import com.vitorpamplona.amethyst.service.broadcast.BroadcastStatus
|
||||
import com.vitorpamplona.amethyst.service.broadcast.RelayResult
|
||||
@@ -252,7 +247,7 @@ private fun BroadcastSection(
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = if (isExpanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
|
||||
symbol = if (isExpanded) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore,
|
||||
contentDescription = if (isExpanded) stringRes(R.string.collapse) else stringRes(R.string.expand),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(24.dp),
|
||||
@@ -289,7 +284,7 @@ private fun BroadcastSection(
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Refresh,
|
||||
symbol = MaterialSymbols.Refresh,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
@@ -318,14 +313,14 @@ private fun StatusIcon(
|
||||
) {
|
||||
val (icon, tint, shouldRotate) =
|
||||
when (status) {
|
||||
BroadcastStatus.SUCCESS -> Triple(Icons.Default.CheckCircle, Color(0xFF22C55E), false)
|
||||
BroadcastStatus.PARTIAL -> Triple(Icons.Default.Error, Color(0xFFF59E0B), false)
|
||||
BroadcastStatus.FAILED -> Triple(Icons.Default.Error, MaterialTheme.colorScheme.error, false)
|
||||
BroadcastStatus.IN_PROGRESS -> Triple(Icons.Default.HourglassEmpty, MaterialTheme.colorScheme.primary, true)
|
||||
BroadcastStatus.SUCCESS -> Triple(MaterialSymbols.CheckCircle, Color(0xFF22C55E), false)
|
||||
BroadcastStatus.PARTIAL -> Triple(MaterialSymbols.Error, Color(0xFFF59E0B), false)
|
||||
BroadcastStatus.FAILED -> Triple(MaterialSymbols.Error, MaterialTheme.colorScheme.error, false)
|
||||
BroadcastStatus.IN_PROGRESS -> Triple(MaterialSymbols.HourglassEmpty, MaterialTheme.colorScheme.primary, true)
|
||||
}
|
||||
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = status.name,
|
||||
tint = tint,
|
||||
modifier =
|
||||
@@ -362,15 +357,15 @@ private fun RelayResultRow(
|
||||
// Status icon
|
||||
val (icon, tint, shouldRotate) =
|
||||
when (result) {
|
||||
is RelayResult.Success -> Triple(Icons.Default.CheckCircle, successColor, false)
|
||||
is RelayResult.Error -> Triple(Icons.Default.Error, errorColor, false)
|
||||
is RelayResult.Timeout -> Triple(Icons.Default.Error, warningColor, false)
|
||||
is RelayResult.Pending -> Triple(Icons.Default.HourglassEmpty, MaterialTheme.colorScheme.onSurfaceVariant, true)
|
||||
is RelayResult.Retrying -> Triple(Icons.Default.HourglassEmpty, MaterialTheme.colorScheme.primary, true)
|
||||
is RelayResult.Success -> Triple(MaterialSymbols.CheckCircle, successColor, false)
|
||||
is RelayResult.Error -> Triple(MaterialSymbols.Error, errorColor, false)
|
||||
is RelayResult.Timeout -> Triple(MaterialSymbols.Error, warningColor, false)
|
||||
is RelayResult.Pending -> Triple(MaterialSymbols.HourglassEmpty, MaterialTheme.colorScheme.onSurfaceVariant, true)
|
||||
is RelayResult.Retrying -> Triple(MaterialSymbols.HourglassEmpty, MaterialTheme.colorScheme.primary, true)
|
||||
}
|
||||
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier =
|
||||
@@ -437,7 +432,7 @@ private fun RelayResultRow(
|
||||
modifier = Modifier.size(32.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Refresh,
|
||||
symbol = MaterialSymbols.Refresh,
|
||||
contentDescription = stringResource(R.string.retry),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
|
||||
@@ -36,9 +36,6 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Call
|
||||
import androidx.compose.material.icons.filled.CallEnd
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -59,6 +56,8 @@ import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.call.CallManager
|
||||
import com.vitorpamplona.amethyst.commons.call.CallState
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.call.session.CallSession
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -256,7 +255,7 @@ private fun CallInProgressUI(
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.CallEnd,
|
||||
MaterialSymbols.CallEnd,
|
||||
contentDescription = stringRes(R.string.call_hangup),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(32.dp),
|
||||
@@ -321,7 +320,7 @@ private fun IncomingCallUI(
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.CallEnd,
|
||||
MaterialSymbols.CallEnd,
|
||||
contentDescription = stringRes(R.string.call_reject),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(32.dp),
|
||||
@@ -334,7 +333,7 @@ private fun IncomingCallUI(
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Call,
|
||||
MaterialSymbols.Call,
|
||||
contentDescription = stringRes(R.string.call_accept),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(32.dp),
|
||||
|
||||
@@ -32,18 +32,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeOff
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.BluetoothAudio
|
||||
import androidx.compose.material.icons.filled.Call
|
||||
import androidx.compose.material.icons.filled.CallEnd
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material.icons.filled.MicOff
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.PersonAdd
|
||||
import androidx.compose.material.icons.filled.Videocam
|
||||
import androidx.compose.material.icons.filled.VideocamOff
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -57,6 +45,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||
|
||||
// ---- Shared building blocks for previews ----
|
||||
@@ -67,7 +57,7 @@ private fun PreviewAvatar(
|
||||
tint: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Person,
|
||||
MaterialSymbols.Person,
|
||||
contentDescription = null,
|
||||
modifier = modifier.size(120.dp),
|
||||
tint = tint,
|
||||
@@ -91,7 +81,7 @@ private fun PreviewGroupAvatars(
|
||||
}
|
||||
if (i < 3 || count <= 4) {
|
||||
Icon(
|
||||
Icons.Default.Person,
|
||||
MaterialSymbols.Person,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(halfSize).align(alignment),
|
||||
tint = tint,
|
||||
@@ -133,7 +123,7 @@ private fun PreviewCallControls(
|
||||
) {
|
||||
IconButton(onClick = {}, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector = if (isMuted) Icons.Default.MicOff else Icons.Default.Mic,
|
||||
symbol = if (isMuted) MaterialSymbols.MicOff else MaterialSymbols.Mic,
|
||||
contentDescription = "Mute",
|
||||
tint = if (isMuted) Color.Red else Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -141,7 +131,7 @@ private fun PreviewCallControls(
|
||||
}
|
||||
IconButton(onClick = {}, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector = if (isVideoEnabled) Icons.Default.Videocam else Icons.Default.VideocamOff,
|
||||
symbol = if (isVideoEnabled) MaterialSymbols.Videocam else MaterialSymbols.VideocamOff,
|
||||
contentDescription = "Camera",
|
||||
tint = if (!isVideoEnabled) Color.Red else Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -149,11 +139,11 @@ private fun PreviewCallControls(
|
||||
}
|
||||
IconButton(onClick = {}, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector =
|
||||
symbol =
|
||||
when (audioRoute) {
|
||||
"speaker" -> Icons.AutoMirrored.Filled.VolumeUp
|
||||
"bluetooth" -> Icons.Default.BluetoothAudio
|
||||
else -> Icons.AutoMirrored.Filled.VolumeOff
|
||||
"speaker" -> MaterialSymbols.AutoMirrored.VolumeUp
|
||||
"bluetooth" -> MaterialSymbols.BluetoothAudio
|
||||
else -> MaterialSymbols.AutoMirrored.VolumeOff
|
||||
},
|
||||
contentDescription = "Audio route",
|
||||
tint =
|
||||
@@ -168,7 +158,7 @@ private fun PreviewCallControls(
|
||||
if (showAddParticipant) {
|
||||
IconButton(onClick = {}, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
Icons.Default.PersonAdd,
|
||||
MaterialSymbols.PersonAdd,
|
||||
contentDescription = "Add participant",
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -183,7 +173,7 @@ private fun PreviewCallControls(
|
||||
shape = CircleShape,
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(Icons.Default.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,7 +208,7 @@ private fun PreviewCallInProgress(
|
||||
shape = CircleShape,
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(Icons.Default.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,7 +251,7 @@ fun PreviewCallingGroupScreen() {
|
||||
shape = CircleShape,
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(Icons.Default.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Hang up", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,10 +293,10 @@ fun PreviewIncomingVoiceCallScreen() {
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(48.dp)) {
|
||||
FloatingActionButton(onClick = {}, containerColor = Color.Red, shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
FloatingActionButton(onClick = {}, containerColor = Color(0xFF4CAF50), shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,10 +329,10 @@ fun PreviewIncomingVideoCallScreen() {
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(48.dp)) {
|
||||
FloatingActionButton(onClick = {}, containerColor = Color.Red, shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
FloatingActionButton(onClick = {}, containerColor = Color(0xFF4CAF50), shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,10 +365,10 @@ fun PreviewIncomingGroupCallScreen() {
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(48.dp)) {
|
||||
FloatingActionButton(onClick = {}, containerColor = Color.Red, shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.CallEnd, "Reject", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
FloatingActionButton(onClick = {}, containerColor = Color(0xFF4CAF50), shape = CircleShape, modifier = Modifier.size(64.dp)) {
|
||||
Icon(Icons.Default.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
Icon(MaterialSymbols.Call, "Accept", tint = Color.White, modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -589,7 +579,7 @@ fun PreviewPipCallUI() {
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(Icons.Default.Person, contentDescription = null, modifier = Modifier.size(48.dp))
|
||||
Icon(MaterialSymbols.Person, contentDescription = null, modifier = Modifier.size(48.dp))
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text("Calling\u2026", fontSize = 10.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
}
|
||||
@@ -612,7 +602,7 @@ fun PreviewPipConnectedCallUI() {
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(Icons.Default.Person, contentDescription = null, modifier = Modifier.size(48.dp), tint = Color.White.copy(alpha = 0.5f))
|
||||
Icon(MaterialSymbols.Person, contentDescription = null, modifier = Modifier.size(48.dp), tint = Color.White.copy(alpha = 0.5f))
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text("02:45", fontSize = 10.sp, color = Color.White.copy(alpha = 0.7f))
|
||||
}
|
||||
|
||||
@@ -36,18 +36,6 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||
import androidx.compose.material.icons.filled.BluetoothAudio
|
||||
import androidx.compose.material.icons.filled.CallEnd
|
||||
import androidx.compose.material.icons.filled.CameraFront
|
||||
import androidx.compose.material.icons.filled.CameraRear
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material.icons.filled.MicOff
|
||||
import androidx.compose.material.icons.filled.PersonAdd
|
||||
import androidx.compose.material.icons.filled.Videocam
|
||||
import androidx.compose.material.icons.filled.VideocamOff
|
||||
import androidx.compose.material.icons.outlined.Hearing
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -70,6 +58,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.call.CallState
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.call.AudioRoute
|
||||
import com.vitorpamplona.amethyst.ui.call.session.CallSession
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
||||
@@ -257,7 +247,7 @@ private fun CallControls(
|
||||
) {
|
||||
IconButton(onClick = onToggleMute, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector = if (isAudioMuted) Icons.Default.MicOff else Icons.Default.Mic,
|
||||
symbol = if (isAudioMuted) MaterialSymbols.MicOff else MaterialSymbols.Mic,
|
||||
contentDescription = stringRes(if (isAudioMuted) R.string.call_unmute else R.string.call_mute),
|
||||
tint = if (isAudioMuted) Color.Red else Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -265,7 +255,7 @@ private fun CallControls(
|
||||
}
|
||||
IconButton(onClick = onToggleVideo, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector = if (isVideoEnabled) Icons.Default.Videocam else Icons.Default.VideocamOff,
|
||||
symbol = if (isVideoEnabled) MaterialSymbols.Videocam else MaterialSymbols.VideocamOff,
|
||||
contentDescription = stringRes(if (isVideoEnabled) R.string.call_camera_off else R.string.call_camera_on),
|
||||
tint = if (!isVideoEnabled) Color.Red else Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -274,11 +264,11 @@ private fun CallControls(
|
||||
if (isVideoEnabled) {
|
||||
IconButton(onClick = onSwitchCamera, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector =
|
||||
symbol =
|
||||
if (isFrontCamera) {
|
||||
Icons.Default.CameraRear
|
||||
MaterialSymbols.CameraRear
|
||||
} else {
|
||||
Icons.Default.CameraFront
|
||||
MaterialSymbols.CameraFront
|
||||
},
|
||||
contentDescription = stringRes(R.string.call_switch_camera),
|
||||
tint = Color.White,
|
||||
@@ -288,11 +278,11 @@ private fun CallControls(
|
||||
}
|
||||
IconButton(onClick = onCycleAudioRoute, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector =
|
||||
symbol =
|
||||
when (currentAudioRoute) {
|
||||
AudioRoute.EARPIECE -> Icons.Outlined.Hearing
|
||||
AudioRoute.SPEAKER -> Icons.AutoMirrored.Filled.VolumeUp
|
||||
AudioRoute.BLUETOOTH -> Icons.Default.BluetoothAudio
|
||||
AudioRoute.EARPIECE -> MaterialSymbols.Hearing
|
||||
AudioRoute.SPEAKER -> MaterialSymbols.AutoMirrored.VolumeUp
|
||||
AudioRoute.BLUETOOTH -> MaterialSymbols.BluetoothAudio
|
||||
},
|
||||
contentDescription =
|
||||
stringRes(
|
||||
@@ -313,7 +303,7 @@ private fun CallControls(
|
||||
}
|
||||
IconButton(onClick = onAddParticipant, modifier = Modifier.size(56.dp)) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PersonAdd,
|
||||
symbol = MaterialSymbols.PersonAdd,
|
||||
contentDescription = stringRes(R.string.call_add_participant),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(28.dp),
|
||||
@@ -328,7 +318,7 @@ private fun CallControls(
|
||||
modifier = Modifier.size(64.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.CallEnd,
|
||||
MaterialSymbols.CallEnd,
|
||||
contentDescription = stringRes(R.string.call_hangup),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(32.dp),
|
||||
|
||||
@@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
@@ -39,11 +38,12 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
|
||||
@@ -95,7 +95,7 @@ fun M3ActionSection(content: @Composable ColumnScope.() -> Unit) {
|
||||
|
||||
@Composable
|
||||
fun M3ActionRow(
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
text: String,
|
||||
isDestructive: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
@@ -125,7 +125,7 @@ fun M3ActionRow(
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = null,
|
||||
modifier = Size20Modifier,
|
||||
tint = tint,
|
||||
|
||||
+5
-8
@@ -21,8 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Face
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -34,6 +32,8 @@ import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.rememberMaterialSymbolPainter
|
||||
import com.vitorpamplona.amethyst.commons.robohash.CachedRobohash
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ProfilePictureUrl
|
||||
import com.vitorpamplona.amethyst.ui.theme.isLight
|
||||
@@ -54,7 +54,7 @@ fun RobohashAsyncImage(
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
imageVector = Icons.Default.Face,
|
||||
painter = rememberMaterialSymbolPainter(MaterialSymbols.Face),
|
||||
contentDescription = contentDescription,
|
||||
colorFilter = MaterialTheme.colorScheme.onBackgroundColorFilter,
|
||||
modifier = modifier,
|
||||
@@ -84,10 +84,7 @@ fun RobohashFallbackAsyncImage(
|
||||
)
|
||||
} else {
|
||||
forwardingPainter(
|
||||
painter =
|
||||
rememberVectorPainter(
|
||||
image = Icons.Default.Face,
|
||||
),
|
||||
painter = rememberMaterialSymbolPainter(MaterialSymbols.Face),
|
||||
colorFilter = MaterialTheme.colorScheme.onBackgroundColorFilter,
|
||||
)
|
||||
}
|
||||
@@ -117,7 +114,7 @@ fun RobohashFallbackAsyncImage(
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
imageVector = Icons.Default.Face,
|
||||
painter = rememberMaterialSymbolPainter(MaterialSymbols.Face),
|
||||
contentDescription = contentDescription,
|
||||
colorFilter = MaterialTheme.colorScheme.onBackgroundColorFilter,
|
||||
modifier = modifier,
|
||||
|
||||
+6
-7
@@ -33,9 +33,6 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.rounded.Warning
|
||||
import androidx.compose.material3.AssistChip
|
||||
import androidx.compose.material3.AssistChipDefaults
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
@@ -63,6 +60,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.imageLoader
|
||||
import coil3.request.ImageRequest
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||
@@ -268,7 +267,7 @@ private fun ContentWarningOverlayBody(
|
||||
.width(90.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Visibility,
|
||||
symbol = MaterialSymbols.Visibility,
|
||||
contentDescription = stringRes(R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -277,7 +276,7 @@ private fun ContentWarningOverlayBody(
|
||||
tint = Color.White,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Warning,
|
||||
symbol = MaterialSymbols.Warning,
|
||||
contentDescription = stringRes(R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -352,7 +351,7 @@ fun ContentWarningNote(
|
||||
.width(90.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Visibility,
|
||||
symbol = MaterialSymbols.Visibility,
|
||||
contentDescription = stringRes(R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -361,7 +360,7 @@ fun ContentWarningNote(
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Warning,
|
||||
symbol = MaterialSymbols.Warning,
|
||||
contentDescription = stringRes(R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
|
||||
@@ -30,9 +30,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -54,6 +51,8 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -157,12 +156,12 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState) {
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(id = R.string.request_deletion),
|
||||
)
|
||||
Spacer(modifier = Modifier)
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(id = R.string.request_deletion),
|
||||
)
|
||||
}
|
||||
@@ -212,7 +211,7 @@ fun ConfirmDeleteBackground(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(id = R.string.request_deletion),
|
||||
tint = Color.White,
|
||||
)
|
||||
@@ -233,7 +232,7 @@ fun ConfirmDeleteBackground(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Close,
|
||||
MaterialSymbols.Close,
|
||||
contentDescription = stringRes(id = R.string.cancel),
|
||||
tint = Color.White,
|
||||
)
|
||||
|
||||
@@ -24,8 +24,6 @@ import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.ContentCopy
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -39,6 +37,7 @@ import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.preview.UrlInfoItem
|
||||
import com.vitorpamplona.amethyst.ui.components.util.setText
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -69,7 +68,7 @@ fun UrlPreviewCard(
|
||||
) {
|
||||
M3ActionSection {
|
||||
M3ActionRow(
|
||||
icon = Icons.Outlined.ContentCopy,
|
||||
icon = MaterialSymbols.ContentCopy,
|
||||
text = stringRes(R.string.copy_url_to_clipboard),
|
||||
) {
|
||||
scope.launch {
|
||||
|
||||
+5
-7
@@ -48,10 +48,6 @@ import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -84,6 +80,8 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalImage
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalVideo
|
||||
@@ -351,7 +349,7 @@ private fun DialogContent(
|
||||
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
symbol = MaterialSymbols.AutoMirrored.ArrowBack,
|
||||
contentDescription = stringRes(R.string.back),
|
||||
)
|
||||
}
|
||||
@@ -366,7 +364,7 @@ private fun DialogContent(
|
||||
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
modifier = Size20Modifier,
|
||||
contentDescription = stringRes(R.string.quick_action_share),
|
||||
)
|
||||
@@ -421,7 +419,7 @@ private fun DialogContent(
|
||||
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Download,
|
||||
symbol = MaterialSymbols.Download,
|
||||
modifier = Size20Modifier,
|
||||
contentDescription = stringRes(R.string.download_to_phone),
|
||||
)
|
||||
|
||||
+9
-13
@@ -36,12 +36,6 @@ import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Report
|
||||
import androidx.compose.material.icons.outlined.Collections
|
||||
import androidx.compose.material.icons.outlined.ContentCopy
|
||||
import androidx.compose.material.icons.outlined.Link
|
||||
import androidx.compose.material.icons.outlined.Share
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -82,6 +76,8 @@ import coil3.size.Size
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalImage
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalVideo
|
||||
@@ -872,7 +868,7 @@ fun ShareMediaAction(
|
||||
if ((videoUri != null && !videoUri.startsWith("file")) || postNostrUri != null) {
|
||||
M3ActionSection {
|
||||
if (videoUri != null && !videoUri.startsWith("file")) {
|
||||
M3ActionRow(icon = Icons.Outlined.Link, text = stringRes(R.string.copy_url_to_clipboard)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Link, text = stringRes(R.string.copy_url_to_clipboard)) {
|
||||
scope.launch {
|
||||
clipboardManager.setText(videoUri)
|
||||
}
|
||||
@@ -880,13 +876,13 @@ fun ShareMediaAction(
|
||||
}
|
||||
}
|
||||
postNostrUri?.let {
|
||||
M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_the_note_id_to_the_clipboard)) {
|
||||
M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(R.string.copy_the_note_id_to_the_clipboard)) {
|
||||
scope.launch {
|
||||
clipboardManager.setText(it)
|
||||
}
|
||||
onDismiss()
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.Collections, text = stringRes(R.string.add_media_to_gallery)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Collections, text = stringRes(R.string.add_media_to_gallery)) {
|
||||
if (videoUri != null) {
|
||||
val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent
|
||||
if (n19 != null) {
|
||||
@@ -909,7 +905,7 @@ fun ShareMediaAction(
|
||||
is MediaUrlImage -> {
|
||||
videoUri?.let {
|
||||
if (videoUri.isNotEmpty()) {
|
||||
M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_image)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(R.string.share_image)) {
|
||||
accountViewModel.viewModelScope.launch { shareImageFile(context, videoUri, mimeType) }
|
||||
onDismiss()
|
||||
}
|
||||
@@ -921,7 +917,7 @@ fun ShareMediaAction(
|
||||
videoUri?.let {
|
||||
if (videoUri.isNotEmpty()) {
|
||||
M3ActionRow(
|
||||
icon = Icons.Outlined.Share,
|
||||
icon = MaterialSymbols.Share,
|
||||
text = stringRes(R.string.share_video),
|
||||
enabled = !isDownloadingVideo.value,
|
||||
) {
|
||||
@@ -951,7 +947,7 @@ fun ShareMediaAction(
|
||||
|
||||
is MediaLocalVideo -> {
|
||||
content.localFile?.let { localFile ->
|
||||
M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_video)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(R.string.share_video)) {
|
||||
accountViewModel.viewModelScope.launch { shareLocalVideoFile(context, localFile, mimeType) }
|
||||
onDismiss()
|
||||
}
|
||||
@@ -1173,7 +1169,7 @@ private fun HashVerificationSymbol(verifiedHash: Boolean) {
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Report,
|
||||
symbol = MaterialSymbols.Report,
|
||||
contentDescription = stringRes(id = R.string.hash_verification_failed),
|
||||
modifier = Size30Modifier,
|
||||
tint = Color.Red,
|
||||
|
||||
+3
-3
@@ -33,8 +33,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.PictureAsPdf
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -52,6 +50,8 @@ import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlPdf
|
||||
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||
import com.vitorpamplona.amethyst.ui.components.ShareMediaAction
|
||||
@@ -222,7 +222,7 @@ private fun FilenameRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.PictureAsPdf,
|
||||
symbol = MaterialSymbols.PictureAsPdf,
|
||||
contentDescription = null,
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
|
||||
+4
-5
@@ -37,9 +37,6 @@ import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -66,6 +63,8 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import coil3.disk.DiskCache
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlPdf
|
||||
import com.vitorpamplona.amethyst.ui.components.ShareMediaAction
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -273,7 +272,7 @@ private fun PdfViewerContent(
|
||||
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
symbol = MaterialSymbols.AutoMirrored.ArrowBack,
|
||||
contentDescription = stringRes(R.string.back),
|
||||
)
|
||||
}
|
||||
@@ -297,7 +296,7 @@ private fun PdfViewerContent(
|
||||
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
modifier = Size20Modifier,
|
||||
contentDescription = stringRes(R.string.quick_action_share),
|
||||
)
|
||||
|
||||
+3
-3
@@ -22,8 +22,6 @@ package com.vitorpamplona.amethyst.ui.components.toasts.multiline
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -31,6 +29,8 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
||||
@@ -95,7 +95,7 @@ fun MultiUserErrorMessageDialog(
|
||||
contentPadding = PaddingValues(horizontal = Size16dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
|
||||
+2
-1
@@ -44,6 +44,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -144,7 +145,7 @@ private fun NotifiableIcon(
|
||||
val iconSizeModifier = Modifier.size(Size20dp)
|
||||
val description = stringRes(def.labelRes)
|
||||
Icon(
|
||||
imageVector = def.icon,
|
||||
symbol = def.icon,
|
||||
contentDescription = description,
|
||||
modifier = iconSizeModifier,
|
||||
)
|
||||
|
||||
+30
-54
@@ -20,33 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.navigation.bottombars
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.FormatListBulleted
|
||||
import androidx.compose.material.icons.automirrored.outlined.Article
|
||||
import androidx.compose.material.icons.automirrored.outlined.Chat
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.outlined.AccountBalanceWallet
|
||||
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
||||
import androidx.compose.material.icons.outlined.Drafts
|
||||
import androidx.compose.material.icons.outlined.EmojiEmotions
|
||||
import androidx.compose.material.icons.outlined.Groups
|
||||
import androidx.compose.material.icons.outlined.Home
|
||||
import androidx.compose.material.icons.outlined.Language
|
||||
import androidx.compose.material.icons.outlined.Mail
|
||||
import androidx.compose.material.icons.outlined.Mic
|
||||
import androidx.compose.material.icons.outlined.MilitaryTech
|
||||
import androidx.compose.material.icons.outlined.Notifications
|
||||
import androidx.compose.material.icons.outlined.Photo
|
||||
import androidx.compose.material.icons.outlined.PlayCircle
|
||||
import androidx.compose.material.icons.outlined.Poll
|
||||
import androidx.compose.material.icons.outlined.Sensors
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.SmartDisplay
|
||||
import androidx.compose.material.icons.outlined.Storefront
|
||||
import androidx.compose.material.icons.outlined.Subscriptions
|
||||
import androidx.compose.material.icons.outlined.Tag
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.isDebug
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -90,7 +66,7 @@ enum class NavBarItem {
|
||||
data class NavBarItemDef(
|
||||
val id: NavBarItem,
|
||||
val labelRes: Int,
|
||||
val icon: ImageVector,
|
||||
val icon: MaterialSymbol,
|
||||
val resolveRoute: (AccountViewModel) -> Route,
|
||||
)
|
||||
|
||||
@@ -100,189 +76,189 @@ val NavBarCatalog: Map<NavBarItem, NavBarItemDef> =
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.HOME,
|
||||
labelRes = R.string.route_home,
|
||||
icon = Icons.Outlined.Home,
|
||||
icon = MaterialSymbols.Home,
|
||||
resolveRoute = { Route.Home },
|
||||
),
|
||||
NavBarItem.MESSAGES to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.MESSAGES,
|
||||
labelRes = R.string.route_messages,
|
||||
icon = Icons.Outlined.Mail,
|
||||
icon = MaterialSymbols.Mail,
|
||||
resolveRoute = { Route.Message },
|
||||
),
|
||||
NavBarItem.VIDEO to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.VIDEO,
|
||||
labelRes = R.string.route_video,
|
||||
icon = Icons.Outlined.Subscriptions,
|
||||
icon = MaterialSymbols.Subscriptions,
|
||||
resolveRoute = { Route.Video },
|
||||
),
|
||||
NavBarItem.DISCOVER to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.DISCOVER,
|
||||
labelRes = R.string.route_discover,
|
||||
icon = Icons.Outlined.Sensors,
|
||||
icon = MaterialSymbols.Sensors,
|
||||
resolveRoute = { Route.Discover },
|
||||
),
|
||||
NavBarItem.NOTIFICATIONS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.NOTIFICATIONS,
|
||||
labelRes = R.string.route_notifications,
|
||||
icon = Icons.Outlined.Notifications,
|
||||
icon = MaterialSymbols.Notifications,
|
||||
resolveRoute = { Route.Notification() },
|
||||
),
|
||||
NavBarItem.PROFILE to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.PROFILE,
|
||||
labelRes = R.string.profile,
|
||||
icon = Icons.Default.AccountCircle,
|
||||
icon = MaterialSymbols.AccountCircle,
|
||||
resolveRoute = { Route.Profile(it.userProfile().pubkeyHex) },
|
||||
),
|
||||
NavBarItem.MY_LISTS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.MY_LISTS,
|
||||
labelRes = R.string.my_lists,
|
||||
icon = Icons.AutoMirrored.Filled.FormatListBulleted,
|
||||
icon = MaterialSymbols.AutoMirrored.FormatListBulleted,
|
||||
resolveRoute = { Route.Lists },
|
||||
),
|
||||
NavBarItem.BOOKMARKS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.BOOKMARKS,
|
||||
labelRes = R.string.bookmarks,
|
||||
icon = Icons.Outlined.CollectionsBookmark,
|
||||
icon = MaterialSymbols.CollectionsBookmark,
|
||||
resolveRoute = { Route.BookmarkGroups },
|
||||
),
|
||||
NavBarItem.WEB_BOOKMARKS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.WEB_BOOKMARKS,
|
||||
labelRes = R.string.web_bookmarks,
|
||||
icon = Icons.Outlined.Language,
|
||||
icon = MaterialSymbols.Language,
|
||||
resolveRoute = { Route.WebBookmarks },
|
||||
),
|
||||
NavBarItem.DRAFTS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.DRAFTS,
|
||||
labelRes = R.string.drafts,
|
||||
icon = Icons.Outlined.Drafts,
|
||||
icon = MaterialSymbols.Drafts,
|
||||
resolveRoute = { Route.Drafts },
|
||||
),
|
||||
NavBarItem.INTEREST_SETS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.INTEREST_SETS,
|
||||
labelRes = R.string.interest_sets_title,
|
||||
icon = Icons.Outlined.Tag,
|
||||
icon = MaterialSymbols.Tag,
|
||||
resolveRoute = { Route.InterestSets },
|
||||
),
|
||||
NavBarItem.EMOJI_PACKS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.EMOJI_PACKS,
|
||||
labelRes = R.string.manage_emoji_packs,
|
||||
icon = Icons.Outlined.EmojiEmotions,
|
||||
icon = MaterialSymbols.EmojiEmotions,
|
||||
resolveRoute = { Route.EmojiPacks },
|
||||
),
|
||||
NavBarItem.WALLET to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.WALLET,
|
||||
labelRes = R.string.wallet,
|
||||
icon = Icons.Outlined.AccountBalanceWallet,
|
||||
icon = MaterialSymbols.AccountBalanceWallet,
|
||||
resolveRoute = { Route.Wallet },
|
||||
),
|
||||
NavBarItem.COMMUNITIES to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.COMMUNITIES,
|
||||
labelRes = R.string.communities,
|
||||
icon = Icons.Outlined.Groups,
|
||||
icon = MaterialSymbols.Groups,
|
||||
resolveRoute = { Route.Communities },
|
||||
),
|
||||
NavBarItem.ARTICLES to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.ARTICLES,
|
||||
labelRes = R.string.discover_reads,
|
||||
icon = Icons.AutoMirrored.Outlined.Article,
|
||||
icon = MaterialSymbols.AutoMirrored.Article,
|
||||
resolveRoute = { Route.Articles },
|
||||
),
|
||||
NavBarItem.PICTURES to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.PICTURES,
|
||||
labelRes = R.string.pictures,
|
||||
icon = Icons.Outlined.Photo,
|
||||
icon = MaterialSymbols.Photo,
|
||||
resolveRoute = { Route.Pictures },
|
||||
),
|
||||
NavBarItem.SHORTS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.SHORTS,
|
||||
labelRes = R.string.shorts,
|
||||
icon = Icons.Outlined.PlayCircle,
|
||||
icon = MaterialSymbols.PlayCircle,
|
||||
resolveRoute = { Route.Shorts },
|
||||
),
|
||||
NavBarItem.PUBLIC_CHATS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.PUBLIC_CHATS,
|
||||
labelRes = R.string.public_chats,
|
||||
icon = Icons.AutoMirrored.Outlined.Chat,
|
||||
icon = MaterialSymbols.AutoMirrored.Chat,
|
||||
resolveRoute = { Route.PublicChats },
|
||||
),
|
||||
NavBarItem.FOLLOW_PACKS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.FOLLOW_PACKS,
|
||||
labelRes = R.string.follow_packs,
|
||||
icon = Icons.Outlined.CollectionsBookmark,
|
||||
icon = MaterialSymbols.CollectionsBookmark,
|
||||
resolveRoute = { Route.FollowPacks },
|
||||
),
|
||||
NavBarItem.LIVE_STREAMS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.LIVE_STREAMS,
|
||||
labelRes = R.string.live_streams,
|
||||
icon = Icons.Outlined.Sensors,
|
||||
icon = MaterialSymbols.Sensors,
|
||||
resolveRoute = { Route.LiveStreams },
|
||||
),
|
||||
NavBarItem.AUDIO_ROOMS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.AUDIO_ROOMS,
|
||||
labelRes = R.string.audio_rooms,
|
||||
icon = Icons.Outlined.Mic,
|
||||
icon = MaterialSymbols.Mic,
|
||||
resolveRoute = { Route.AudioRooms },
|
||||
),
|
||||
NavBarItem.LONGS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.LONGS,
|
||||
labelRes = R.string.longs,
|
||||
icon = Icons.Outlined.SmartDisplay,
|
||||
icon = MaterialSymbols.SmartDisplay,
|
||||
resolveRoute = { Route.Longs },
|
||||
),
|
||||
NavBarItem.POLLS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.POLLS,
|
||||
labelRes = R.string.polls,
|
||||
icon = Icons.Outlined.Poll,
|
||||
icon = MaterialSymbols.Poll,
|
||||
resolveRoute = { Route.Polls },
|
||||
),
|
||||
NavBarItem.BADGES to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.BADGES,
|
||||
labelRes = R.string.badges,
|
||||
icon = Icons.Outlined.MilitaryTech,
|
||||
icon = MaterialSymbols.MilitaryTech,
|
||||
resolveRoute = { Route.Badges },
|
||||
),
|
||||
NavBarItem.PRODUCTS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.PRODUCTS,
|
||||
labelRes = R.string.discover_marketplace,
|
||||
icon = Icons.Outlined.Storefront,
|
||||
icon = MaterialSymbols.Storefront,
|
||||
resolveRoute = { Route.Products },
|
||||
),
|
||||
NavBarItem.EMOJI_SETS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.EMOJI_SETS,
|
||||
labelRes = R.string.emoji_sets,
|
||||
icon = Icons.Outlined.EmojiEmotions,
|
||||
icon = MaterialSymbols.EmojiEmotions,
|
||||
resolveRoute = { Route.BrowseEmojiSets },
|
||||
),
|
||||
NavBarItem.SETTINGS to
|
||||
NavBarItemDef(
|
||||
id = NavBarItem.SETTINGS,
|
||||
labelRes = R.string.settings,
|
||||
icon = Icons.Outlined.Settings,
|
||||
icon = MaterialSymbols.Settings,
|
||||
resolveRoute = { Route.AllSettings },
|
||||
),
|
||||
)
|
||||
|
||||
+4
-5
@@ -31,9 +31,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Logout
|
||||
import androidx.compose.material.icons.filled.RadioButtonChecked
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -57,6 +54,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
|
||||
@@ -205,7 +204,7 @@ private fun ActiveMarker(
|
||||
|
||||
if (isCurrentUser) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.RadioButtonChecked,
|
||||
symbol = MaterialSymbols.RadioButtonChecked,
|
||||
contentDescription = stringRes(R.string.account_switch_active_account),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
@@ -288,7 +287,7 @@ private fun LogoutButton(
|
||||
onClick = { logoutDialog = true },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.Logout,
|
||||
symbol = MaterialSymbols.AutoMirrored.Logout,
|
||||
contentDescription = stringRes(R.string.log_out),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
|
||||
+18
-29
@@ -49,18 +49,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.outlined.CollectionsBookmark
|
||||
import androidx.compose.material.icons.outlined.Drafts
|
||||
import androidx.compose.material.icons.outlined.ExpandLess
|
||||
import androidx.compose.material.icons.outlined.ExpandMore
|
||||
import androidx.compose.material.icons.outlined.GroupAdd
|
||||
import androidx.compose.material.icons.outlined.Photo
|
||||
import androidx.compose.material.icons.outlined.SettingsInputAntenna
|
||||
import androidx.compose.material.icons.outlined.SmartDisplay
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -81,7 +69,6 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -99,6 +86,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.BuildConfig
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.isDebug
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
@@ -467,7 +457,7 @@ fun SendButton(
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.Send,
|
||||
symbol = MaterialSymbols.AutoMirrored.Send,
|
||||
null,
|
||||
modifier = Size20Modifier,
|
||||
tint = tint,
|
||||
@@ -482,7 +472,7 @@ fun UserStatusDeleteButton(onClick: () -> Unit) {
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
symbol = MaterialSymbols.Delete,
|
||||
null,
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -549,7 +539,7 @@ fun ListContent(
|
||||
CollapsibleSection(title = R.string.drawer_section_create) {
|
||||
NavigationRow(
|
||||
title = R.string.share_hls_video,
|
||||
icon = Icons.Outlined.SettingsInputAntenna,
|
||||
icon = MaterialSymbols.SettingsInputAntenna,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
nav = nav,
|
||||
route = Route.NewHlsVideo,
|
||||
@@ -558,8 +548,7 @@ fun ListContent(
|
||||
if (isDebug) {
|
||||
NavigationRow(
|
||||
title = R.string.route_chess,
|
||||
icon = R.drawable.ic_chess,
|
||||
iconReference = 1,
|
||||
icon = MaterialSymbols.ChessKnight,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
nav = nav,
|
||||
route = Route.Chess,
|
||||
@@ -585,7 +574,7 @@ fun ListContent(
|
||||
|
||||
IconRow(
|
||||
title = R.string.drawer_accounts,
|
||||
icon = Icons.Outlined.GroupAdd,
|
||||
icon = MaterialSymbols.GroupAdd,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
onClick = openSheet,
|
||||
)
|
||||
@@ -653,7 +642,7 @@ fun CollapsibleSection(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
Icon(
|
||||
imageVector = if (expanded) Icons.Outlined.ExpandLess else Icons.Outlined.ExpandMore,
|
||||
symbol = if (expanded) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore,
|
||||
contentDescription = sectionTitle,
|
||||
modifier = Size22Modifier,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -711,7 +700,7 @@ fun NavigationRow(
|
||||
@Composable
|
||||
fun NavigationRow(
|
||||
title: Int,
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
tint: Color,
|
||||
nav: INav,
|
||||
route: Route,
|
||||
@@ -730,7 +719,7 @@ fun NavigationRow(
|
||||
@Composable
|
||||
fun NavigationRow(
|
||||
title: Int,
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
tint: Color,
|
||||
nav: INav,
|
||||
computeRoute: () -> Route,
|
||||
@@ -783,7 +772,7 @@ fun IconRow(
|
||||
@Composable
|
||||
fun IconRow(
|
||||
title: Int,
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
tint: Color,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
@@ -800,7 +789,7 @@ fun IconRow(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = title,
|
||||
modifier = Size22ModifierWith4Padding,
|
||||
tint = tint,
|
||||
@@ -943,19 +932,19 @@ private fun CollapsibleSectionPreview() {
|
||||
CollapsibleSection(title = R.string.drawer_section_you) {
|
||||
IconRow(
|
||||
title = R.string.profile,
|
||||
icon = Icons.Default.AccountCircle,
|
||||
icon = MaterialSymbols.AccountCircle,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
onClick = {},
|
||||
)
|
||||
IconRow(
|
||||
title = R.string.bookmarks,
|
||||
icon = Icons.Outlined.CollectionsBookmark,
|
||||
icon = MaterialSymbols.CollectionsBookmark,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
onClick = {},
|
||||
)
|
||||
IconRow(
|
||||
title = R.string.drafts,
|
||||
icon = Icons.Outlined.Drafts,
|
||||
icon = MaterialSymbols.Drafts,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
onClick = {},
|
||||
)
|
||||
@@ -963,13 +952,13 @@ private fun CollapsibleSectionPreview() {
|
||||
CollapsibleSection(title = R.string.drawer_section_feeds) {
|
||||
IconRow(
|
||||
title = R.string.pictures,
|
||||
icon = Icons.Outlined.Photo,
|
||||
icon = MaterialSymbols.Photo,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
onClick = {},
|
||||
)
|
||||
IconRow(
|
||||
title = R.string.longs,
|
||||
icon = Icons.Outlined.SmartDisplay,
|
||||
icon = MaterialSymbols.SmartDisplay,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
+19
-27
@@ -36,16 +36,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ViewList
|
||||
import androidx.compose.material.icons.automirrored.outlined.VolumeOff
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material.icons.outlined.AutoAwesome
|
||||
import androidx.compose.material.icons.outlined.Groups
|
||||
import androidx.compose.material.icons.outlined.LocationOn
|
||||
import androidx.compose.material.icons.outlined.Person
|
||||
import androidx.compose.material.icons.outlined.Public
|
||||
import androidx.compose.material.icons.outlined.Storage
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
@@ -78,6 +68,8 @@ import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.TopFilter
|
||||
import com.vitorpamplona.amethyst.service.call.CallSessionBridge.accountViewModel
|
||||
@@ -261,7 +253,7 @@ fun FeedFilterSpinner(
|
||||
}
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
symbol = MaterialSymbols.ExpandMore,
|
||||
contentDescription = explainer,
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -579,54 +571,54 @@ private fun FeedIcon(
|
||||
val icon =
|
||||
when (item.code) {
|
||||
is TopFilter.Global -> {
|
||||
Icons.Outlined.Public
|
||||
MaterialSymbols.Public
|
||||
}
|
||||
|
||||
is TopFilter.AroundMe -> {
|
||||
Icons.Outlined.LocationOn
|
||||
MaterialSymbols.LocationOn
|
||||
}
|
||||
|
||||
is TopFilter.AllFollows -> {
|
||||
Icons.Outlined.Groups
|
||||
MaterialSymbols.Groups
|
||||
}
|
||||
|
||||
is TopFilter.AllUserFollows -> {
|
||||
Icons.Outlined.Person
|
||||
MaterialSymbols.Person
|
||||
}
|
||||
|
||||
is TopFilter.DefaultFollows -> {
|
||||
Icons.Outlined.Groups
|
||||
MaterialSymbols.Groups
|
||||
}
|
||||
|
||||
is TopFilter.MuteList -> {
|
||||
Icons.AutoMirrored.Outlined.VolumeOff
|
||||
MaterialSymbols.AutoMirrored.VolumeOff
|
||||
}
|
||||
|
||||
is TopFilter.PeopleList -> {
|
||||
Icons.AutoMirrored.Outlined.ViewList
|
||||
MaterialSymbols.AutoMirrored.ViewList
|
||||
}
|
||||
|
||||
is TopFilter.FavoriteAlgoFeed -> {
|
||||
Icons.Outlined.AutoAwesome
|
||||
MaterialSymbols.AutoAwesome
|
||||
}
|
||||
|
||||
is TopFilter.AllFavoriteAlgoFeeds -> {
|
||||
Icons.Outlined.AutoAwesome
|
||||
MaterialSymbols.AutoAwesome
|
||||
}
|
||||
|
||||
else -> {
|
||||
when (item.name) {
|
||||
is GeoHashName -> Icons.Outlined.LocationOn
|
||||
is RelayName -> Icons.Outlined.Storage
|
||||
is CommunityName -> Icons.Outlined.Groups
|
||||
is PeopleListName -> Icons.AutoMirrored.Outlined.ViewList
|
||||
is FavoriteAlgoFeedName -> Icons.Outlined.AutoAwesome
|
||||
else -> Icons.Outlined.Person
|
||||
is GeoHashName -> MaterialSymbols.LocationOn
|
||||
is RelayName -> MaterialSymbols.Storage
|
||||
is CommunityName -> MaterialSymbols.Groups
|
||||
is PeopleListName -> MaterialSymbols.AutoMirrored.ViewList
|
||||
is FavoriteAlgoFeedName -> MaterialSymbols.AutoAwesome
|
||||
else -> MaterialSymbols.Person
|
||||
}
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
|
||||
@@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MilitaryTech
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -42,6 +40,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
|
||||
@@ -102,7 +102,7 @@ fun BadgeCompose(
|
||||
modifier = Modifier.width(55.dp).padding(0.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MilitaryTech,
|
||||
symbol = MaterialSymbols.MilitaryTech,
|
||||
null,
|
||||
modifier = Modifier.size(25.dp).align(Alignment.TopEnd),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
||||
@@ -27,8 +27,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
@@ -42,6 +40,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.painterRes
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size16dp
|
||||
@@ -97,7 +97,7 @@ fun ErrorMessageDialog(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Done,
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(StdHorzSpacer)
|
||||
|
||||
@@ -22,25 +22,6 @@ package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.OpenInNew
|
||||
import androidx.compose.material.icons.automirrored.outlined.OpenInNew
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material.icons.filled.Cancel
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.ContentCopy
|
||||
import androidx.compose.material.icons.filled.DownloadForOffline
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material.icons.filled.Link
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.filled.PushPin
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material.icons.outlined.AddReaction
|
||||
import androidx.compose.material.icons.outlined.Close
|
||||
import androidx.compose.material.icons.outlined.Mic
|
||||
import androidx.compose.material.icons.outlined.PlayCircle
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -62,6 +43,8 @@ import com.vitorpamplona.amethyst.commons.icons.Repost
|
||||
import com.vitorpamplona.amethyst.commons.icons.Reposted
|
||||
import com.vitorpamplona.amethyst.commons.icons.Search
|
||||
import com.vitorpamplona.amethyst.commons.icons.Zap
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size19Modifier
|
||||
@@ -94,7 +77,7 @@ fun FollowingIcon(modifier: Modifier) {
|
||||
@Composable
|
||||
fun ArrowBackIcon(tint: Color = MaterialTheme.colorScheme.grayText) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
symbol = MaterialSymbols.AutoMirrored.ArrowBack,
|
||||
contentDescription = stringRes(R.string.back),
|
||||
tint = tint,
|
||||
)
|
||||
@@ -106,7 +89,7 @@ fun DownloadForOfflineIcon(
|
||||
tint: Color = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.DownloadForOffline,
|
||||
symbol = MaterialSymbols.DownloadForOffline,
|
||||
contentDescription = stringRes(id = R.string.accessibility_download_for_offline),
|
||||
modifier = remember(iconSize) { Modifier.size(iconSize) },
|
||||
tint = tint,
|
||||
@@ -132,7 +115,7 @@ fun ChangeReactionIcon(
|
||||
tint: Color = Color.Unspecified,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AddReaction,
|
||||
symbol = MaterialSymbols.AddReaction,
|
||||
contentDescription = stringRes(id = R.string.change_reaction),
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
@@ -184,7 +167,7 @@ fun LightningAddressIcon(
|
||||
tint: Color = Color.Unspecified,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(R.string.lightning_address),
|
||||
tint = tint,
|
||||
modifier = modifier,
|
||||
@@ -222,7 +205,7 @@ fun ZapIcon(
|
||||
contentDescriptor: Int = R.string.zap_description,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(contentDescriptor),
|
||||
tint = tint,
|
||||
modifier = modifier,
|
||||
@@ -249,7 +232,7 @@ fun ShareIcon(
|
||||
tint: Color = Color.Unspecified,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
modifier = modifier,
|
||||
contentDescription = stringRes(R.string.share_or_save),
|
||||
tint = tint,
|
||||
@@ -269,7 +252,7 @@ fun CashuIcon(modifier: Modifier) {
|
||||
@Composable
|
||||
fun CopyIcon(modifier: Modifier) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ContentCopy,
|
||||
symbol = MaterialSymbols.ContentCopy,
|
||||
stringRes(id = R.string.copy_to_clipboard),
|
||||
modifier = modifier,
|
||||
)
|
||||
@@ -278,7 +261,7 @@ fun CopyIcon(modifier: Modifier) {
|
||||
@Composable
|
||||
fun OpenInNewIcon(modifier: Modifier) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
stringRes(id = R.string.copy_to_clipboard),
|
||||
modifier = modifier,
|
||||
)
|
||||
@@ -290,7 +273,7 @@ fun ExpandLessIcon(
|
||||
contentDescriptor: Int,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandLess,
|
||||
symbol = MaterialSymbols.ExpandLess,
|
||||
contentDescription = stringRes(id = contentDescriptor),
|
||||
modifier = modifier,
|
||||
tint = MaterialTheme.colorScheme.subtleButton,
|
||||
@@ -303,7 +286,7 @@ fun ExpandMoreIcon(
|
||||
contentDescriptor: Int,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
symbol = MaterialSymbols.ExpandMore,
|
||||
contentDescription = stringRes(id = contentDescriptor),
|
||||
modifier = modifier,
|
||||
tint = MaterialTheme.colorScheme.subtleButton,
|
||||
@@ -316,7 +299,7 @@ fun VoiceReplyIcon(
|
||||
tint: Color,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Mic,
|
||||
symbol = MaterialSymbols.Mic,
|
||||
contentDescription = stringRes(id = R.string.record_a_message),
|
||||
tint = tint,
|
||||
modifier = iconSizeModifier,
|
||||
@@ -339,7 +322,7 @@ fun CommentIcon(
|
||||
@Composable
|
||||
fun CancelIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Cancel,
|
||||
symbol = MaterialSymbols.Cancel,
|
||||
contentDescription = stringRes(id = R.string.cancel),
|
||||
modifier = Size30Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -349,7 +332,7 @@ fun CancelIcon() {
|
||||
@Composable
|
||||
fun CloseIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Close,
|
||||
symbol = MaterialSymbols.Close,
|
||||
contentDescription = stringRes(id = R.string.cancel),
|
||||
modifier = Size20Modifier,
|
||||
)
|
||||
@@ -374,7 +357,7 @@ fun PlayIcon(
|
||||
tint: Color,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.PlayCircle,
|
||||
symbol = MaterialSymbols.PlayCircle,
|
||||
contentDescription = stringRes(id = R.string.accessibility_play_username),
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
@@ -387,7 +370,7 @@ fun PinIcon(
|
||||
tint: Color,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PushPin,
|
||||
symbol = MaterialSymbols.PushPin,
|
||||
contentDescription = stringRes(id = R.string.accessibility_pushpin),
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
@@ -400,7 +383,7 @@ fun EnablePiP(
|
||||
tint: Color,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
contentDescription = stringRes(id = R.string.enter_picture_in_picture),
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
@@ -410,7 +393,7 @@ fun EnablePiP(
|
||||
@Composable
|
||||
fun ClearTextIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Clear,
|
||||
symbol = MaterialSymbols.Clear,
|
||||
contentDescription = stringRes(R.string.clear),
|
||||
)
|
||||
}
|
||||
@@ -421,7 +404,7 @@ fun LinkIcon(
|
||||
tint: Color,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Link,
|
||||
symbol = MaterialSymbols.Link,
|
||||
contentDescription = stringRes(R.string.website),
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
@@ -431,7 +414,7 @@ fun LinkIcon(
|
||||
@Composable
|
||||
fun VerticalDotsIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
symbol = MaterialSymbols.MoreVert,
|
||||
contentDescription = stringRes(id = R.string.note_options),
|
||||
modifier = Size19Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
|
||||
+10
-12
@@ -23,10 +23,6 @@ package com.vitorpamplona.amethyst.ui.note
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.OpenInNew
|
||||
import androidx.compose.material.icons.filled.Downloading
|
||||
import androidx.compose.material.icons.filled.Report
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
@@ -49,6 +45,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
|
||||
import com.vitorpamplona.amethyst.commons.hashtags.Tunestr
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05State
|
||||
import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05VerifState
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
@@ -303,7 +301,7 @@ fun DisplayStatusInner(
|
||||
onClick = { runCatching { uri.openUri(url.trim()) } },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
null,
|
||||
modifier = Size15Modifier,
|
||||
tint = MaterialTheme.colorScheme.lessImportantLink,
|
||||
@@ -323,7 +321,7 @@ fun DisplayStatusInner(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
null,
|
||||
modifier = Size15Modifier,
|
||||
tint = MaterialTheme.colorScheme.lessImportantLink,
|
||||
@@ -345,7 +343,7 @@ fun DisplayStatusInner(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
null,
|
||||
modifier = Size15Modifier,
|
||||
tint = MaterialTheme.colorScheme.lessImportantLink,
|
||||
@@ -362,7 +360,7 @@ fun DisplayStatusInner(
|
||||
onClick = { nav.nav(routeForUser(nostrPTag)) },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
symbol = MaterialSymbols.AutoMirrored.OpenInNew,
|
||||
null,
|
||||
modifier = Size15Modifier,
|
||||
tint = MaterialTheme.colorScheme.lessImportantLink,
|
||||
@@ -461,7 +459,7 @@ fun RenderNIP05VerifiedSymbol(
|
||||
when (it) {
|
||||
is Nip05VerifState.Verifying -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Downloading,
|
||||
symbol = MaterialSymbols.Downloading,
|
||||
contentDescription = stringRes(id = R.string.nip05_checking),
|
||||
modifier = modifier,
|
||||
tint = Color.Yellow,
|
||||
@@ -470,7 +468,7 @@ fun RenderNIP05VerifiedSymbol(
|
||||
|
||||
is Nip05VerifState.NotStarted -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Downloading,
|
||||
symbol = MaterialSymbols.Downloading,
|
||||
contentDescription = stringRes(id = R.string.nip05_checking),
|
||||
modifier = modifier,
|
||||
tint = Color.Yellow,
|
||||
@@ -488,7 +486,7 @@ fun RenderNIP05VerifiedSymbol(
|
||||
|
||||
is Nip05VerifState.Failed -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Report,
|
||||
symbol = MaterialSymbols.Report,
|
||||
contentDescription = stringRes(id = R.string.nip05_failed),
|
||||
modifier = modifier,
|
||||
tint = Color.Red,
|
||||
@@ -497,7 +495,7 @@ fun RenderNIP05VerifiedSymbol(
|
||||
|
||||
is Nip05VerifState.Error -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Report,
|
||||
symbol = MaterialSymbols.Report,
|
||||
contentDescription = stringRes(id = R.string.nip05_failed),
|
||||
modifier = modifier,
|
||||
tint = Color.Red,
|
||||
|
||||
@@ -34,9 +34,6 @@ import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PushPin
|
||||
import androidx.compose.material.icons.outlined.Timer
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
@@ -61,6 +58,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.compose.produceCachedStateAsync
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
@@ -1550,7 +1549,7 @@ fun DisplayExpiration(expirationDate: Long) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Timer,
|
||||
symbol = MaterialSymbols.Timer,
|
||||
contentDescription = stringRes(R.string.expiration_date_label),
|
||||
modifier = Modifier.padding(start = 5.dp).size(15.dp),
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -1681,7 +1680,7 @@ fun FirstUserInfoRow(
|
||||
@Composable
|
||||
fun PinnedMark() {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PushPin,
|
||||
symbol = MaterialSymbols.PushPin,
|
||||
contentDescription = stringRes(R.string.pinned_notes),
|
||||
modifier = Modifier.padding(start = 5.dp).size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
|
||||
@@ -34,17 +34,6 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AlternateEmail
|
||||
import androidx.compose.material.icons.filled.Block
|
||||
import androidx.compose.material.icons.filled.ContentCopy
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.FormatQuote
|
||||
import androidx.compose.material.icons.filled.PersonAdd
|
||||
import androidx.compose.material.icons.filled.PersonRemove
|
||||
import androidx.compose.material.icons.filled.Report
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
@@ -66,16 +55,17 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Popup
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -285,7 +275,7 @@ fun CardBody(
|
||||
Column(modifier = Modifier.width(IntrinsicSize.Min)) {
|
||||
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
|
||||
NoteQuickActionItem(
|
||||
icon = Icons.Default.ContentCopy,
|
||||
icon = MaterialSymbols.ContentCopy,
|
||||
label = stringRes(R.string.quick_action_copy_text),
|
||||
) {
|
||||
accountViewModel.decrypt(note) {
|
||||
@@ -299,7 +289,7 @@ fun CardBody(
|
||||
}
|
||||
VerticalDivider(color = primaryLight)
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.AlternateEmail,
|
||||
MaterialSymbols.AlternateEmail,
|
||||
stringRes(R.string.quick_action_copy_user_id),
|
||||
) {
|
||||
note.author?.let {
|
||||
@@ -312,7 +302,7 @@ fun CardBody(
|
||||
}
|
||||
VerticalDivider(color = primaryLight)
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.FormatQuote,
|
||||
MaterialSymbols.FormatQuote,
|
||||
stringRes(R.string.quick_action_copy_note_id),
|
||||
) {
|
||||
scope.launch {
|
||||
@@ -326,7 +316,7 @@ fun CardBody(
|
||||
VerticalDivider(color = primaryLight)
|
||||
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.Block,
|
||||
MaterialSymbols.Block,
|
||||
stringRes(R.string.quick_action_block),
|
||||
) {
|
||||
if (accountViewModel.account.settings.hideBlockAlertDialog) {
|
||||
@@ -344,7 +334,7 @@ fun CardBody(
|
||||
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
|
||||
if (isOwnNote) {
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.Delete,
|
||||
MaterialSymbols.Delete,
|
||||
stringRes(R.string.quick_action_delete),
|
||||
) {
|
||||
if (accountViewModel.account.settings.hideDeleteRequestDialog) {
|
||||
@@ -356,7 +346,7 @@ fun CardBody(
|
||||
}
|
||||
} else if (isFollowingUser) {
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.PersonRemove,
|
||||
MaterialSymbols.PersonRemove,
|
||||
stringRes(R.string.quick_action_unfollow),
|
||||
) {
|
||||
accountViewModel.unfollow(note.author!!)
|
||||
@@ -364,7 +354,7 @@ fun CardBody(
|
||||
}
|
||||
} else {
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.PersonAdd,
|
||||
MaterialSymbols.PersonAdd,
|
||||
stringRes(R.string.quick_action_follow),
|
||||
) {
|
||||
accountViewModel.follow(note.author!!)
|
||||
@@ -374,7 +364,7 @@ fun CardBody(
|
||||
|
||||
VerticalDivider(color = primaryLight)
|
||||
NoteQuickActionItem(
|
||||
icon = ImageVector.vectorResource(id = R.drawable.relays),
|
||||
icon = MaterialSymbols.Dns,
|
||||
label = stringRes(R.string.broadcast),
|
||||
) {
|
||||
accountViewModel.broadcast(note)
|
||||
@@ -384,14 +374,14 @@ fun CardBody(
|
||||
VerticalDivider(color = primaryLight)
|
||||
if (isOwnNote && note.isDraft()) {
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.Edit,
|
||||
MaterialSymbols.Edit,
|
||||
stringRes(R.string.edit_draft),
|
||||
) {
|
||||
onWantsToEditDraft()
|
||||
}
|
||||
} else {
|
||||
NoteQuickActionItem(
|
||||
icon = Icons.Default.Share,
|
||||
icon = MaterialSymbols.Share,
|
||||
label = stringRes(R.string.quick_action_share),
|
||||
) {
|
||||
val sendIntent =
|
||||
@@ -422,7 +412,7 @@ fun CardBody(
|
||||
VerticalDivider(color = primaryLight)
|
||||
|
||||
NoteQuickActionItem(
|
||||
Icons.Default.Report,
|
||||
MaterialSymbols.Report,
|
||||
stringRes(R.string.quick_action_report),
|
||||
) {
|
||||
showReportDialog.value = true
|
||||
@@ -434,7 +424,7 @@ fun CardBody(
|
||||
|
||||
@Composable
|
||||
fun NoteQuickActionItem(
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
label: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
@@ -447,7 +437,7 @@ fun NoteQuickActionItem(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = null,
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -468,7 +458,7 @@ fun DeleteAlertDialog(
|
||||
QuickActionAlertDialog(
|
||||
title = stringRes(R.string.quick_action_request_deletion_alert_title),
|
||||
textContent = stringRes(R.string.quick_action_request_deletion_alert_body),
|
||||
buttonIcon = Icons.Default.Delete,
|
||||
buttonIcon = MaterialSymbols.Delete,
|
||||
buttonText = stringRes(R.string.quick_action_delete_dialog_btn),
|
||||
onClickDoOnce = {
|
||||
accountViewModel.delete(note)
|
||||
@@ -491,7 +481,7 @@ private fun BlockAlertDialog(
|
||||
) = QuickActionAlertDialog(
|
||||
title = stringRes(R.string.report_dialog_block_hide_user_btn),
|
||||
textContent = stringRes(R.string.report_dialog_blocking_a_user),
|
||||
buttonIcon = Icons.Default.Block,
|
||||
buttonIcon = MaterialSymbols.Block,
|
||||
buttonText = stringRes(R.string.quick_action_block_dialog_btn),
|
||||
buttonColors =
|
||||
ButtonDefaults.buttonColors(
|
||||
@@ -514,7 +504,7 @@ private fun BlockAlertDialog(
|
||||
fun QuickActionAlertDialog(
|
||||
title: String,
|
||||
textContent: String,
|
||||
buttonIcon: ImageVector,
|
||||
buttonIcon: MaterialSymbol,
|
||||
buttonText: String,
|
||||
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
onClickDoOnce: () -> Unit,
|
||||
@@ -526,7 +516,7 @@ fun QuickActionAlertDialog(
|
||||
textContent = textContent,
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = buttonIcon,
|
||||
symbol = buttonIcon,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
@@ -615,7 +605,7 @@ fun QuickActionAlertDialog(
|
||||
fun QuickActionAlertDialogOneButton(
|
||||
title: String,
|
||||
textContent: String,
|
||||
buttonIcon: ImageVector,
|
||||
buttonIcon: MaterialSymbol,
|
||||
buttonText: String,
|
||||
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
onClickDoOnce: () -> Unit,
|
||||
@@ -626,7 +616,7 @@ fun QuickActionAlertDialogOneButton(
|
||||
textContent = textContent,
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = buttonIcon,
|
||||
symbol = buttonIcon,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -50,8 +50,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AccountBalanceWallet
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CardDefaults
|
||||
@@ -103,6 +101,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ReactionRowAction
|
||||
import com.vitorpamplona.amethyst.model.ReactionRowItem
|
||||
@@ -361,7 +361,7 @@ fun PayReaction(
|
||||
onClick = { expanded = true },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AccountBalanceWallet,
|
||||
symbol = MaterialSymbols.AccountBalanceWallet,
|
||||
contentDescription = stringRes(R.string.payment_targets),
|
||||
tint = grayTint,
|
||||
modifier = iconSizeModifier,
|
||||
@@ -376,7 +376,7 @@ fun PayReaction(
|
||||
M3ActionSection {
|
||||
if (targets.isEmpty()) {
|
||||
M3ActionRow(
|
||||
icon = Icons.Outlined.AccountBalanceWallet,
|
||||
icon = MaterialSymbols.AccountBalanceWallet,
|
||||
text = stringRes(R.string.no_payment_targets_message),
|
||||
enabled = false,
|
||||
onClick = {},
|
||||
@@ -384,7 +384,7 @@ fun PayReaction(
|
||||
} else {
|
||||
targets.forEach { target ->
|
||||
M3ActionRow(
|
||||
icon = Icons.Outlined.AccountBalanceWallet,
|
||||
icon = MaterialSymbols.AccountBalanceWallet,
|
||||
text = "${target.type.replaceFirstChar(Char::titlecase)}: ${target.authority}",
|
||||
onClick = {
|
||||
expanded = false
|
||||
|
||||
@@ -33,8 +33,6 @@ 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.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -50,6 +48,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -242,7 +242,7 @@ private fun ShowMoreRelaysButton(onClick: () -> Unit) {
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
symbol = MaterialSymbols.ExpandMore,
|
||||
contentDescription = stringRes(id = R.string.expand_relay_list),
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
|
||||
@@ -30,8 +30,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ChevronRight
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -50,6 +48,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
|
||||
import com.vitorpamplona.amethyst.ui.components.ClickableBox
|
||||
@@ -114,7 +114,7 @@ fun ChatRelayExpandButton(onClick: () -> Unit) {
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
symbol = MaterialSymbols.ChevronRight,
|
||||
contentDescription = stringRes(id = R.string.expand_relay_list),
|
||||
modifier = Size15Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
|
||||
+11
-20
@@ -60,17 +60,6 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
import androidx.compose.material.icons.outlined.AddCircle
|
||||
import androidx.compose.material.icons.outlined.ContentPaste
|
||||
import androidx.compose.material.icons.outlined.RadioButtonUnchecked
|
||||
import androidx.compose.material.icons.outlined.Visibility
|
||||
import androidx.compose.material.icons.outlined.VisibilityOff
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -102,6 +91,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.components.TextSpinner
|
||||
import com.vitorpamplona.amethyst.ui.components.TitleExplainer
|
||||
import com.vitorpamplona.amethyst.ui.components.util.getText
|
||||
@@ -259,7 +250,7 @@ fun UpdateZapAmountContent(
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Close,
|
||||
symbol = MaterialSymbols.Close,
|
||||
contentDescription = stringRes(R.string.remove),
|
||||
modifier = Modifier.size(InputChipDefaults.AvatarSize),
|
||||
)
|
||||
@@ -304,7 +295,7 @@ fun UpdateZapAmountContent(
|
||||
enabled = postViewModel.nextAmount.text.isNotBlank(),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AddCircle,
|
||||
symbol = MaterialSymbols.AddCircle,
|
||||
contentDescription = stringRes(R.string.add),
|
||||
modifier = Size20Modifier,
|
||||
)
|
||||
@@ -394,7 +385,7 @@ fun UpdateZapAmountContent(
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (connected) Icons.Filled.CheckCircle else Icons.Outlined.RadioButtonUnchecked,
|
||||
symbol = if (connected) MaterialSymbols.CheckCircle else MaterialSymbols.RadioButtonUnchecked,
|
||||
contentDescription = null,
|
||||
tint = statusColor,
|
||||
modifier = Modifier.size(18.dp),
|
||||
@@ -436,7 +427,7 @@ fun UpdateZapAmountContent(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Add,
|
||||
symbol = MaterialSymbols.Add,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
@@ -464,7 +455,7 @@ fun UpdateZapAmountContent(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.ContentPaste,
|
||||
symbol = MaterialSymbols.ContentPaste,
|
||||
contentDescription = stringRes(id = R.string.paste_from_clipboard),
|
||||
modifier = Size24Modifier,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
@@ -522,7 +513,7 @@ fun UpdateZapAmountContent(
|
||||
fontSize = Font14SP,
|
||||
)
|
||||
Icon(
|
||||
imageVector = if (showManualConfig) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore,
|
||||
symbol = if (showManualConfig) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
modifier = Modifier.size(20.dp),
|
||||
@@ -629,11 +620,11 @@ fun UpdateZapAmountContent(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector =
|
||||
symbol =
|
||||
if (showPassword) {
|
||||
Icons.Outlined.VisibilityOff
|
||||
MaterialSymbols.VisibilityOff
|
||||
} else {
|
||||
Icons.Outlined.Visibility
|
||||
MaterialSymbols.Visibility
|
||||
},
|
||||
contentDescription =
|
||||
if (showPassword) {
|
||||
|
||||
@@ -25,9 +25,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -42,6 +39,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationSummaryState
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
@@ -70,7 +69,7 @@ fun UserReactionsRow(
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
symbol = MaterialSymbols.ExpandMore,
|
||||
null,
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -98,7 +97,7 @@ fun UserReactionsRow(
|
||||
@Composable
|
||||
private fun UserZapModel(model: NotificationSummaryState) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(R.string.zaps),
|
||||
modifier = Size24Modifier,
|
||||
tint = BitcoinOrange,
|
||||
|
||||
@@ -38,9 +38,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
@@ -75,6 +72,8 @@ import androidx.compose.ui.window.Popup
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.EmptyTagList
|
||||
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists
|
||||
@@ -659,7 +658,7 @@ fun ZapVote(
|
||||
if (poolOption.zappedByLoggedIn.value) {
|
||||
zappingProgress = 1f
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(R.string.zaps),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = BitcoinOrange,
|
||||
@@ -667,7 +666,7 @@ fun ZapVote(
|
||||
} else {
|
||||
if (zappingProgress < 0.1 || zappingProgress > 0.99) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(id = R.string.zaps),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
|
||||
+3
-3
@@ -21,8 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.aihelp
|
||||
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AutoAwesome
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -30,6 +28,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
@@ -41,7 +41,7 @@ fun AiWritingHelpButton(
|
||||
onClick = { onClick() },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AutoAwesome,
|
||||
symbol = MaterialSymbols.AutoAwesome,
|
||||
contentDescription = stringRes(R.string.ai_writing_help),
|
||||
modifier = Modifier.height(22.dp),
|
||||
tint =
|
||||
|
||||
+4
-4
@@ -20,14 +20,14 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.anonymous
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PersonOff
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size19Modifier
|
||||
|
||||
@@ -41,14 +41,14 @@ fun AnonymousPostButton(
|
||||
) {
|
||||
if (!isActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PersonOff,
|
||||
symbol = MaterialSymbols.PersonOff,
|
||||
contentDescription = stringRes(R.string.post_anonymously),
|
||||
modifier = Size19Modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PersonOff,
|
||||
symbol = MaterialSymbols.PersonOff,
|
||||
contentDescription = stringRes(R.string.post_anonymously),
|
||||
modifier = Size19Modifier,
|
||||
tint = Color.Red,
|
||||
|
||||
+4
-5
@@ -28,9 +28,6 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.material.icons.rounded.Warning
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -44,6 +41,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -67,7 +66,7 @@ fun ContentSensitivityExplainer(
|
||||
.width(25.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.VisibilityOff,
|
||||
symbol = MaterialSymbols.VisibilityOff,
|
||||
contentDescription = stringRes(id = R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -76,7 +75,7 @@ fun ContentSensitivityExplainer(
|
||||
tint = Color.Red,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Warning,
|
||||
symbol = MaterialSymbols.Warning,
|
||||
contentDescription = stringRes(id = R.string.content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
|
||||
+6
-8
@@ -24,10 +24,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.material.icons.rounded.Warning
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -37,6 +33,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
@@ -54,7 +52,7 @@ fun MarkAsSensitiveButton(
|
||||
) {
|
||||
if (!isActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Visibility,
|
||||
symbol = MaterialSymbols.Visibility,
|
||||
contentDescription = stringRes(R.string.add_content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -63,7 +61,7 @@ fun MarkAsSensitiveButton(
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Warning,
|
||||
symbol = MaterialSymbols.Warning,
|
||||
contentDescription = stringRes(R.string.add_content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -73,7 +71,7 @@ fun MarkAsSensitiveButton(
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.VisibilityOff,
|
||||
symbol = MaterialSymbols.VisibilityOff,
|
||||
contentDescription = stringRes(id = R.string.remove_content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -82,7 +80,7 @@ fun MarkAsSensitiveButton(
|
||||
tint = Color.Red,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Warning,
|
||||
symbol = MaterialSymbols.Warning,
|
||||
contentDescription = stringRes(id = R.string.remove_content_warning),
|
||||
modifier =
|
||||
Modifier
|
||||
|
||||
+3
-3
@@ -28,8 +28,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.OpenInFull
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -43,6 +41,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.nip30CustomEmojis.EmojiPackState
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
@@ -88,7 +88,7 @@ fun ShowEmojiSuggestionList(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.OpenInFull,
|
||||
symbol = MaterialSymbols.OpenInFull,
|
||||
contentDescription = stringRes(R.string.use_direct_url),
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
|
||||
+4
-5
@@ -21,9 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.expiration
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Timer
|
||||
import androidx.compose.material.icons.outlined.TimerOff
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -32,6 +29,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
@@ -44,14 +43,14 @@ fun ExpirationDateButton(
|
||||
) {
|
||||
if (!isActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Timer,
|
||||
symbol = MaterialSymbols.Timer,
|
||||
contentDescription = stringRes(R.string.add_expiration_date),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.TimerOff,
|
||||
symbol = MaterialSymbols.TimerOff,
|
||||
contentDescription = stringRes(R.string.remove_expiration_date),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = Color(0xFFFF6600),
|
||||
|
||||
+4
-4
@@ -27,8 +27,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Timer
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.DatePickerDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -57,6 +55,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
@@ -102,7 +102,7 @@ fun ExpirationDatePicker(model: IExpiration) {
|
||||
.padding(bottom = 5.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Timer,
|
||||
symbol = MaterialSymbols.Timer,
|
||||
contentDescription = stringRes(R.string.expiration_date_label),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = Color(0xFFFF6600),
|
||||
@@ -132,7 +132,7 @@ fun ExpirationDatePicker(model: IExpiration) {
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(Icons.Outlined.Timer, contentDescription = stringResource(R.string.expiration_date_select))
|
||||
Icon(MaterialSymbols.Timer, contentDescription = stringResource(R.string.expiration_date_select))
|
||||
Spacer(Modifier.width(12.dp))
|
||||
|
||||
if (model.expirationDate < TimeUtils.oneMinuteFromNow()) {
|
||||
|
||||
+4
-4
@@ -20,13 +20,13 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.invoice
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
@@ -41,14 +41,14 @@ fun AddLnInvoiceButton(
|
||||
) {
|
||||
if (!isLnInvoiceActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CurrencyBitcoin,
|
||||
symbol = MaterialSymbols.CurrencyBitcoin,
|
||||
contentDescription = stringRes(id = R.string.add_bitcoin_invoice),
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CurrencyBitcoin,
|
||||
symbol = MaterialSymbols.CurrencyBitcoin,
|
||||
contentDescription = stringRes(id = R.string.cancel_bitcoin_invoice),
|
||||
modifier = Size20Modifier,
|
||||
tint = BitcoinOrange,
|
||||
|
||||
+4
-5
@@ -21,9 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.location
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationOff
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -31,6 +28,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
@@ -43,14 +42,14 @@ fun AddGeoHashButton(
|
||||
) {
|
||||
if (!isActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.LocationOff,
|
||||
symbol = MaterialSymbols.LocationOff,
|
||||
contentDescription = stringRes(id = R.string.add_location),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.LocationOn,
|
||||
symbol = MaterialSymbols.LocationOn,
|
||||
contentDescription = stringRes(id = R.string.remove_location),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
||||
+3
-3
@@ -29,8 +29,6 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -46,6 +44,8 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -93,7 +93,7 @@ fun DisplayLocationBox(
|
||||
.width(20.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.LocationOn,
|
||||
symbol = MaterialSymbols.LocationOn,
|
||||
null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
||||
+3
-3
@@ -26,8 +26,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.DatePickerDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -53,6 +51,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -99,7 +99,7 @@ fun PollDeadlinePicker(model: ShortNotePostViewModel) {
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(Icons.Default.DateRange, contentDescription = stringResource(R.string.accessibility_select_date))
|
||||
Icon(MaterialSymbols.DateRange, contentDescription = stringResource(R.string.accessibility_select_date))
|
||||
Spacer(Modifier.width(12.dp))
|
||||
|
||||
if (model.closedAt < TimeUtils.oneMinuteFromNow()) {
|
||||
|
||||
+4
-5
@@ -29,9 +29,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.FilterChip
|
||||
@@ -46,6 +43,8 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -96,7 +95,7 @@ fun PollOptionsField(postViewModel: ShortNotePostViewModel) {
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
symbol = MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(R.string.clear),
|
||||
)
|
||||
}
|
||||
@@ -124,7 +123,7 @@ fun PollOptionsField(postViewModel: ShortNotePostViewModel) {
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
),
|
||||
) {
|
||||
Icon(Icons.Default.Add, contentDescription = stringRes(R.string.add_poll_option_button))
|
||||
Icon(MaterialSymbols.Add, contentDescription = stringRes(R.string.add_poll_option_button))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,13 +20,13 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note.creators.secretEmoji
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Assistant
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
@@ -41,14 +41,14 @@ fun AddSecretEmojiButton(
|
||||
) {
|
||||
if (!isSecretEmojiActive) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Assistant,
|
||||
symbol = MaterialSymbols.Assistant,
|
||||
contentDescription = stringRes(id = R.string.secret_emoji_maker_explainer),
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Assistant,
|
||||
symbol = MaterialSymbols.Assistant,
|
||||
contentDescription = stringRes(id = R.string.secret_emoji_maker_explainer),
|
||||
modifier = Size20Modifier,
|
||||
tint = BitcoinOrange,
|
||||
|
||||
+3
-3
@@ -25,8 +25,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Assistant
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
@@ -48,6 +46,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
@@ -62,7 +62,7 @@ fun SecretEmojiRequest(onSuccess: (String) -> Unit) {
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 5.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Assistant,
|
||||
symbol = MaterialSymbols.Assistant,
|
||||
null,
|
||||
modifier = Size20Modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
|
||||
+3
-3
@@ -26,8 +26,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.DatePickerDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -53,6 +51,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -99,7 +99,7 @@ fun ZapPollDeadlinePicker(model: ShortNotePostViewModel) {
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(Icons.Default.DateRange, contentDescription = stringResource(R.string.accessibility_select_date))
|
||||
Icon(MaterialSymbols.DateRange, contentDescription = stringResource(R.string.accessibility_select_date))
|
||||
Spacer(Modifier.width(12.dp))
|
||||
|
||||
if (model.zapPollClosedAt < TimeUtils.oneMinuteFromNow()) {
|
||||
|
||||
+3
-3
@@ -25,8 +25,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -35,6 +33,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@@ -69,7 +69,7 @@ fun ZapPollField(postViewModel: ShortNotePostViewModel) {
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
),
|
||||
) {
|
||||
Icon(Icons.Default.Add, contentDescription = stringRes(R.string.add_poll_option_button))
|
||||
Icon(MaterialSymbols.Add, contentDescription = stringRes(R.string.add_poll_option_button))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -23,8 +23,6 @@ package com.vitorpamplona.amethyst.ui.note.creators.zappolls
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -35,6 +33,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -52,7 +52,7 @@ fun ZapPollOption(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
symbol = MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(R.string.clear),
|
||||
)
|
||||
}
|
||||
|
||||
+6
-7
@@ -24,9 +24,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ShowChart
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -35,6 +32,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
|
||||
@@ -53,7 +52,7 @@ fun AddZapraiserButton(
|
||||
) {
|
||||
if (!isLnInvoiceActive) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.ShowChart,
|
||||
symbol = MaterialSymbols.AutoMirrored.ShowChart,
|
||||
null,
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -62,7 +61,7 @@ fun AddZapraiserButton(
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(R.string.add_zapraiser),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -72,7 +71,7 @@ fun AddZapraiserButton(
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.ShowChart,
|
||||
symbol = MaterialSymbols.AutoMirrored.ShowChart,
|
||||
null,
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -81,7 +80,7 @@ fun AddZapraiserButton(
|
||||
tint = BitcoinOrange,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(R.string.cancel_zapraiser),
|
||||
modifier =
|
||||
Modifier
|
||||
|
||||
+4
-5
@@ -25,9 +25,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowForwardIos
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -39,6 +36,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.ZapSplit
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
@@ -82,7 +81,7 @@ fun ZapSplitPreview() {
|
||||
.width(25.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Bolt,
|
||||
symbol = MaterialSymbols.Bolt,
|
||||
contentDescription = stringRes(id = R.string.zaps),
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -91,7 +90,7 @@ fun ZapSplitPreview() {
|
||||
tint = BitcoinOrange,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.ArrowForwardIos,
|
||||
symbol = MaterialSymbols.AutoMirrored.ArrowForwardIos,
|
||||
contentDescription = stringRes(id = R.string.zaps),
|
||||
modifier =
|
||||
Modifier
|
||||
|
||||
+25
-42
@@ -21,24 +21,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.note.elements
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.PlaylistAdd
|
||||
import androidx.compose.material.icons.outlined.Bookmark
|
||||
import androidx.compose.material.icons.outlined.BookmarkAdd
|
||||
import androidx.compose.material.icons.outlined.BookmarkRemove
|
||||
import androidx.compose.material.icons.outlined.CellTower
|
||||
import androidx.compose.material.icons.outlined.ContentCopy
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.Edit
|
||||
import androidx.compose.material.icons.outlined.EmojiEmotions
|
||||
import androidx.compose.material.icons.outlined.Lock
|
||||
import androidx.compose.material.icons.outlined.LockOpen
|
||||
import androidx.compose.material.icons.outlined.PersonAdd
|
||||
import androidx.compose.material.icons.outlined.PersonRemove
|
||||
import androidx.compose.material.icons.outlined.PushPin
|
||||
import androidx.compose.material.icons.outlined.Report
|
||||
import androidx.compose.material.icons.outlined.Schedule
|
||||
import androidx.compose.material.icons.outlined.Share
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.State
|
||||
@@ -51,6 +33,7 @@ import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.actions.EditPostView
|
||||
@@ -177,19 +160,19 @@ fun NoteDropDownMenu(
|
||||
// Follow section
|
||||
M3ActionSection {
|
||||
if (!state.isFollowingAuthor) {
|
||||
M3ActionRow(icon = Icons.Outlined.PersonAdd, text = stringRes(R.string.follow)) {
|
||||
M3ActionRow(icon = MaterialSymbols.PersonAdd, text = stringRes(R.string.follow)) {
|
||||
val author = note.author ?: return@M3ActionRow
|
||||
accountViewModel.follow(author)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.PersonRemove, text = stringRes(R.string.unfollow)) {
|
||||
M3ActionRow(icon = MaterialSymbols.PersonRemove, text = stringRes(R.string.unfollow)) {
|
||||
val author = note.author ?: return@M3ActionRow
|
||||
accountViewModel.unfollow(author)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
M3ActionRow(icon = Icons.AutoMirrored.Outlined.PlaylistAdd, text = stringRes(R.string.follow_set_add_author_from_note_action)) {
|
||||
M3ActionRow(icon = MaterialSymbols.AutoMirrored.PlaylistAdd, text = stringRes(R.string.follow_set_add_author_from_note_action)) {
|
||||
val authorHexKey = note.author?.pubkeyHex ?: return@M3ActionRow
|
||||
nav.nav(Route.PeopleListManagement(authorHexKey))
|
||||
onDismiss()
|
||||
@@ -198,7 +181,7 @@ fun NoteDropDownMenu(
|
||||
|
||||
// Copy & Share section
|
||||
M3ActionSection {
|
||||
M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_text)) {
|
||||
M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(R.string.copy_text)) {
|
||||
val lastNoteVersion = (editState?.value as? GenericLoadable.Loaded)?.loaded?.modificationToShow?.value ?: note
|
||||
accountViewModel.decrypt(lastNoteVersion) {
|
||||
scope.launch {
|
||||
@@ -207,7 +190,7 @@ fun NoteDropDownMenu(
|
||||
}
|
||||
onDismiss()
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_user_pubkey)) {
|
||||
M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(R.string.copy_user_pubkey)) {
|
||||
note.author?.let {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
clipboardManager.setText("nostr:${it.pubkeyNpub()}")
|
||||
@@ -215,13 +198,13 @@ fun NoteDropDownMenu(
|
||||
}
|
||||
}
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_note_id)) {
|
||||
M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(R.string.copy_note_id)) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
clipboardManager.setText(note.toNostrUri())
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.quick_action_share)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(R.string.quick_action_share)) {
|
||||
val sendIntent =
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
@@ -238,28 +221,28 @@ fun NoteDropDownMenu(
|
||||
// Edit & Broadcast section
|
||||
M3ActionSection {
|
||||
if (state.isLoggedUser && note.isDraft()) {
|
||||
M3ActionRow(icon = Icons.Outlined.Edit, text = stringRes(R.string.edit_draft)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Edit, text = stringRes(R.string.edit_draft)) {
|
||||
nav.nav { routeEditDraftTo(note, accountViewModel.account) }
|
||||
}
|
||||
}
|
||||
if (!note.isDraft()) {
|
||||
if (note.event is TextNoteEvent) {
|
||||
if (state.isLoggedUser) {
|
||||
M3ActionRow(icon = Icons.Outlined.Edit, text = stringRes(R.string.edit_post)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Edit, text = stringRes(R.string.edit_post)) {
|
||||
wantsToEditPost.value = true
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.Edit, text = stringRes(R.string.propose_an_edit)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Edit, text = stringRes(R.string.propose_an_edit)) {
|
||||
wantsToEditPost.value = true
|
||||
}
|
||||
}
|
||||
} else if (note.event is LongTextNoteEvent && state.isLoggedUser) {
|
||||
M3ActionRow(icon = Icons.Outlined.Edit, text = stringRes(R.string.edit_article)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Edit, text = stringRes(R.string.edit_article)) {
|
||||
nav.nav { Route.NewLongFormPost(version = note.idHex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.CellTower, text = stringRes(R.string.broadcast)) {
|
||||
M3ActionRow(icon = MaterialSymbols.CellTower, text = stringRes(R.string.broadcast)) {
|
||||
accountViewModel.broadcast(note)
|
||||
onDismiss()
|
||||
}
|
||||
@@ -268,21 +251,21 @@ fun NoteDropDownMenu(
|
||||
// Timestamp & Bookmarks section
|
||||
M3ActionSection {
|
||||
if (accountViewModel.account.otsState.hasPendingAttestations(note)) {
|
||||
M3ActionRow(icon = Icons.Outlined.Schedule, text = stringRes(R.string.timestamp_pending)) { onDismiss() }
|
||||
M3ActionRow(icon = MaterialSymbols.Schedule, text = stringRes(R.string.timestamp_pending)) { onDismiss() }
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.Schedule, text = stringRes(R.string.timestamp_it)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Schedule, text = stringRes(R.string.timestamp_it)) {
|
||||
accountViewModel.timestamp(note)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
if (state.isLoggedUser) {
|
||||
if (state.isPinnedNote) {
|
||||
M3ActionRow(icon = Icons.Outlined.PushPin, text = stringRes(R.string.unpin_from_profile)) {
|
||||
M3ActionRow(icon = MaterialSymbols.PushPin, text = stringRes(R.string.unpin_from_profile)) {
|
||||
accountViewModel.removePin(note)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.PushPin, text = stringRes(R.string.pin_to_profile)) {
|
||||
M3ActionRow(icon = MaterialSymbols.PushPin, text = stringRes(R.string.pin_to_profile)) {
|
||||
accountViewModel.addPin(note)
|
||||
onDismiss()
|
||||
}
|
||||
@@ -296,14 +279,14 @@ fun NoteDropDownMenu(
|
||||
} else {
|
||||
stringRes(R.string.add_to_emoji_list)
|
||||
}
|
||||
M3ActionRow(icon = Icons.Outlined.EmojiEmotions, text = emojiText) {
|
||||
M3ActionRow(icon = MaterialSymbols.EmojiEmotions, text = emojiText) {
|
||||
val address = (note as AddressableNote).address
|
||||
nav.nav(Route.EmojiPackSelection(kind = EmojiPackEvent.KIND, pubKeyHex = address.pubKeyHex, dTag = address.dTag))
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
val noteBookmarkType = if (note.event is LongTextNoteEvent) stringRes(R.string.article) else stringRes(R.string.post)
|
||||
M3ActionRow(icon = Icons.Outlined.BookmarkAdd, text = stringRes(R.string.manage_bookmark_label, noteBookmarkType)) {
|
||||
M3ActionRow(icon = MaterialSymbols.BookmarkAdd, text = stringRes(R.string.manage_bookmark_label, noteBookmarkType)) {
|
||||
if (note.event is LongTextNoteEvent) {
|
||||
nav.nav(Route.ArticleBookmarkManagement((note as AddressableNote).address))
|
||||
} else {
|
||||
@@ -313,23 +296,23 @@ fun NoteDropDownMenu(
|
||||
}
|
||||
}
|
||||
if (state.isPrivateBookmarkNote) {
|
||||
M3ActionRow(icon = Icons.Outlined.LockOpen, text = stringRes(R.string.remove_from_private_bookmarks)) {
|
||||
M3ActionRow(icon = MaterialSymbols.LockOpen, text = stringRes(R.string.remove_from_private_bookmarks)) {
|
||||
accountViewModel.removePrivateBookmark(note)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.Lock, text = stringRes(R.string.add_to_private_bookmarks)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Lock, text = stringRes(R.string.add_to_private_bookmarks)) {
|
||||
accountViewModel.addPrivateBookmark(note)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
if (state.isPublicBookmarkNote) {
|
||||
M3ActionRow(icon = Icons.Outlined.BookmarkRemove, text = stringRes(R.string.remove_from_public_bookmarks)) {
|
||||
M3ActionRow(icon = MaterialSymbols.BookmarkRemove, text = stringRes(R.string.remove_from_public_bookmarks)) {
|
||||
accountViewModel.removePublicBookmark(note)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.Bookmark, text = stringRes(R.string.add_to_public_bookmarks)) {
|
||||
M3ActionRow(icon = MaterialSymbols.Bookmark, text = stringRes(R.string.add_to_public_bookmarks)) {
|
||||
accountViewModel.addPublicBookmark(note)
|
||||
onDismiss()
|
||||
}
|
||||
@@ -339,12 +322,12 @@ fun NoteDropDownMenu(
|
||||
// Moderation section
|
||||
M3ActionSection {
|
||||
if (state.isLoggedUser) {
|
||||
M3ActionRow(icon = Icons.Outlined.Delete, text = stringRes(R.string.request_deletion), isDestructive = true) {
|
||||
M3ActionRow(icon = MaterialSymbols.Delete, text = stringRes(R.string.request_deletion), isDestructive = true) {
|
||||
accountViewModel.delete(note)
|
||||
onDismiss()
|
||||
}
|
||||
} else {
|
||||
M3ActionRow(icon = Icons.Outlined.Report, text = stringRes(R.string.block_report), isDestructive = true) {
|
||||
M3ActionRow(icon = MaterialSymbols.Report, text = stringRes(R.string.block_report), isDestructive = true) {
|
||||
reportDialogShowing = true
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -40,6 +38,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.location.LoadCityName
|
||||
@@ -68,7 +68,7 @@ fun DisplayGeohashExternalId(
|
||||
Row(modifier = MaterialTheme.colorScheme.replyModifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
LoadCityName(geohash) { cityName ->
|
||||
Icon(
|
||||
imageVector = Icons.Default.LocationOn,
|
||||
symbol = MaterialSymbols.LocationOn,
|
||||
contentDescription = stringRes(id = R.string.geohash_exclusive),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
||||
+3
-3
@@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Tag
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -40,6 +38,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -66,7 +66,7 @@ fun DisplayHashtagExternalId(
|
||||
) {
|
||||
Row(modifier = MaterialTheme.colorScheme.replyModifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Tag,
|
||||
symbol = MaterialSymbols.Tag,
|
||||
contentDescription = stringRes(id = R.string.hashtag_exclusive),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
||||
+3
-2
@@ -51,6 +51,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.actions.StrippingFailureDialog
|
||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromFiles
|
||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||
@@ -83,7 +85,6 @@ import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
||||
import com.vitorpamplona.amethyst.ui.note.types.ReplyRenderType
|
||||
import com.vitorpamplona.amethyst.ui.painterRes
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||
@@ -255,7 +256,7 @@ private fun GenericCommentPostBody(
|
||||
onClick = { postViewModel.wantsAnonymousPost = false },
|
||||
) {
|
||||
Icon(
|
||||
painter = painterRes(resourceId = R.drawable.incognito, 1),
|
||||
symbol = MaterialSymbols.NoAccounts,
|
||||
contentDescription = stringRes(R.string.post_anonymously),
|
||||
modifier = Size30Modifier,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
|
||||
@@ -33,15 +33,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.ErrorOutline
|
||||
import androidx.compose.material.icons.filled.HourglassTop
|
||||
import androidx.compose.material.icons.filled.Recommend
|
||||
import androidx.compose.material.icons.filled.RemoveDone
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -54,12 +45,14 @@ 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.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.EmptyTagList
|
||||
import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
@@ -182,7 +175,7 @@ fun RenderAttestation(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = statusIcon,
|
||||
symbol = statusIcon,
|
||||
contentDescription = stringRes(R.string.attestation),
|
||||
tint = statusColor,
|
||||
modifier = Modifier.size(24.dp),
|
||||
@@ -308,7 +301,7 @@ fun RenderAttestationRequest(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.Send,
|
||||
symbol = MaterialSymbols.AutoMirrored.Send,
|
||||
contentDescription = stringRes(R.string.attestation_request),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(24.dp),
|
||||
@@ -435,7 +428,7 @@ fun RenderAttestorRecommendation(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Recommend,
|
||||
symbol = MaterialSymbols.Recommend,
|
||||
contentDescription = stringRes(R.string.attestor_recommendation),
|
||||
tint = MaterialTheme.colorScheme.tertiary,
|
||||
modifier = Modifier.size(24.dp),
|
||||
@@ -527,7 +520,7 @@ fun RenderAttestorProficiency(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Star,
|
||||
symbol = MaterialSymbols.Star,
|
||||
contentDescription = stringRes(R.string.attestor_proficiency),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier.size(24.dp),
|
||||
@@ -585,13 +578,13 @@ private fun attestationColor(status: AttestationStatus?): Color =
|
||||
else -> Color(0xFF757575)
|
||||
}
|
||||
|
||||
private fun attestationIcon(status: AttestationStatus?): ImageVector =
|
||||
private fun attestationIcon(status: AttestationStatus?): MaterialSymbol =
|
||||
when {
|
||||
status == AttestationStatus.INVALID -> Icons.Default.Close
|
||||
status == AttestationStatus.VALID -> Icons.Default.CheckCircle
|
||||
status == AttestationStatus.REVOKED -> Icons.Default.RemoveDone
|
||||
status == AttestationStatus.VERIFYING -> Icons.Default.HourglassTop
|
||||
else -> Icons.Default.ErrorOutline
|
||||
status == AttestationStatus.INVALID -> MaterialSymbols.Close
|
||||
status == AttestationStatus.VALID -> MaterialSymbols.CheckCircle
|
||||
status == AttestationStatus.REVOKED -> MaterialSymbols.RemoveDone
|
||||
status == AttestationStatus.VERIFYING -> MaterialSymbols.HourglassTop
|
||||
else -> MaterialSymbols.ErrorOutline
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -33,8 +33,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.MilitaryTech
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -61,6 +59,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -118,7 +118,7 @@ fun BadgeDisplay(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.MilitaryTech,
|
||||
symbol = MaterialSymbols.MilitaryTech,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
|
||||
@@ -32,9 +32,6 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material.icons.outlined.Edit
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
@@ -60,6 +57,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.EmptyTagList
|
||||
import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
@@ -462,7 +461,7 @@ fun EditCommunityButton(
|
||||
onClick = { nav.nav(Route.EditCommunity(note.address)) },
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Edit,
|
||||
symbol = MaterialSymbols.Edit,
|
||||
modifier = Size18Modifier,
|
||||
contentDescription = stringRes(R.string.edit_community),
|
||||
)
|
||||
@@ -543,7 +542,7 @@ fun ShareCommunityButton(
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Share,
|
||||
symbol = MaterialSymbols.Share,
|
||||
modifier = Size18Modifier,
|
||||
contentDescription = stringRes(R.string.quick_action_share),
|
||||
)
|
||||
|
||||
@@ -34,8 +34,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Schedule
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -49,6 +47,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -237,7 +237,7 @@ private fun MetaSeparator() {
|
||||
private fun ReadingTimeBadge(minutes: Int) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Schedule,
|
||||
symbol = MaterialSymbols.Schedule,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.grayText,
|
||||
modifier = Modifier.size(14.dp),
|
||||
|
||||
@@ -31,14 +31,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Dns
|
||||
import androidx.compose.material.icons.filled.Language
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.LockOpen
|
||||
import androidx.compose.material.icons.filled.Numbers
|
||||
import androidx.compose.material.icons.filled.Tag
|
||||
import androidx.compose.material.icons.filled.TravelExplore
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
@@ -48,13 +40,15 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -121,7 +115,7 @@ fun RenderRelayDiscovery(
|
||||
// Network type
|
||||
if (networkTypes.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = Icons.Default.Language,
|
||||
icon = MaterialSymbols.Language,
|
||||
label = stringRes(R.string.relay_monitor_network),
|
||||
value = networkTypes.joinToString { it.code },
|
||||
)
|
||||
@@ -130,7 +124,7 @@ fun RenderRelayDiscovery(
|
||||
// Relay type
|
||||
if (relayTypes.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = Icons.Default.Dns,
|
||||
icon = MaterialSymbols.Dns,
|
||||
label = stringRes(R.string.relay_monitor_relay_type),
|
||||
value = relayTypes.joinToString(),
|
||||
)
|
||||
@@ -139,7 +133,7 @@ fun RenderRelayDiscovery(
|
||||
// Requirements
|
||||
if (requirements.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = if (requirements.any { !it.negated }) Icons.Default.Lock else Icons.Default.LockOpen,
|
||||
icon = if (requirements.any { !it.negated }) MaterialSymbols.Lock else MaterialSymbols.LockOpen,
|
||||
label = stringRes(R.string.relay_monitor_requirements),
|
||||
value =
|
||||
requirements.joinToString { req ->
|
||||
@@ -151,7 +145,7 @@ fun RenderRelayDiscovery(
|
||||
// Supported NIPs
|
||||
if (supportedNips.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = Icons.Default.Numbers,
|
||||
icon = MaterialSymbols.Numbers,
|
||||
label = stringRes(R.string.relay_monitor_supported_nips),
|
||||
value = supportedNips.sorted().joinToString(),
|
||||
)
|
||||
@@ -160,7 +154,7 @@ fun RenderRelayDiscovery(
|
||||
// Accepted kinds
|
||||
if (acceptedKinds.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = Icons.Default.Dns,
|
||||
icon = MaterialSymbols.Dns,
|
||||
label = stringRes(R.string.relay_discovery_accepted_kinds),
|
||||
value =
|
||||
acceptedKinds.joinToString { kind ->
|
||||
@@ -176,7 +170,7 @@ fun RenderRelayDiscovery(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Tag,
|
||||
MaterialSymbols.Tag,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
@@ -196,7 +190,7 @@ fun RenderRelayDiscovery(
|
||||
// Geohashes
|
||||
if (geohashes.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = Icons.Default.TravelExplore,
|
||||
icon = MaterialSymbols.TravelExplore,
|
||||
label = stringRes(R.string.relay_discovery_geohash),
|
||||
value = geohashes.joinToString(),
|
||||
)
|
||||
@@ -264,7 +258,7 @@ private fun TopicChip(topic: String) {
|
||||
|
||||
@Composable
|
||||
private fun DiscoveryInfoRow(
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
label: String,
|
||||
value: String,
|
||||
) {
|
||||
|
||||
@@ -26,11 +26,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ExitToApp
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.PersonAdd
|
||||
import androidx.compose.material.icons.filled.PersonRemove
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -38,11 +33,13 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
@@ -62,7 +59,7 @@ fun RenderRelayMembershipList(
|
||||
val memberCount = remember(noteEvent) { noteEvent.members().size }
|
||||
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.People,
|
||||
icon = MaterialSymbols.People,
|
||||
title = stringRes(R.string.relay_membership_list),
|
||||
subtitle = stringRes(R.string.relay_members_count, memberCount),
|
||||
nav = nav,
|
||||
@@ -87,7 +84,7 @@ fun RenderRelayAddMember(
|
||||
val subtitle = remember(memberKeys) { memberKeys.joinToString(", ") { it.take(16) + "..." } }
|
||||
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonAdd,
|
||||
icon = MaterialSymbols.PersonAdd,
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
relayPubKey = noteEvent.pubKey,
|
||||
@@ -111,7 +108,7 @@ fun RenderRelayRemoveMember(
|
||||
val subtitle = remember(memberKeys) { memberKeys.joinToString(", ") { it.take(16) + "..." } }
|
||||
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonRemove,
|
||||
icon = MaterialSymbols.PersonRemove,
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
relayPubKey = noteEvent.pubKey,
|
||||
@@ -125,7 +122,7 @@ fun RenderRelayJoinRequest(
|
||||
nav: INav,
|
||||
) {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonAdd,
|
||||
icon = MaterialSymbols.PersonAdd,
|
||||
title = stringRes(R.string.relay_join_request),
|
||||
subtitle = null,
|
||||
nav = nav,
|
||||
@@ -140,7 +137,7 @@ fun RenderRelayLeaveRequest(
|
||||
nav: INav,
|
||||
) {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.AutoMirrored.Filled.ExitToApp,
|
||||
icon = MaterialSymbols.AutoMirrored.ExitToApp,
|
||||
title = stringRes(R.string.relay_leave_request),
|
||||
subtitle = null,
|
||||
nav = nav,
|
||||
@@ -150,7 +147,7 @@ fun RenderRelayLeaveRequest(
|
||||
|
||||
@Composable
|
||||
private fun RelayMemberEventCard(
|
||||
icon: ImageVector,
|
||||
icon: MaterialSymbol,
|
||||
title: String,
|
||||
subtitle: String?,
|
||||
nav: INav? = null,
|
||||
@@ -167,7 +164,7 @@ private fun RelayMemberEventCard(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
symbol = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
@@ -195,7 +192,7 @@ private fun RelayMemberEventCard(
|
||||
private fun RelayMembershipListCardPreview() {
|
||||
ThemeComparisonColumn {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.People,
|
||||
icon = MaterialSymbols.People,
|
||||
title = "Relay membership list",
|
||||
subtitle = "42 members",
|
||||
)
|
||||
@@ -207,7 +204,7 @@ private fun RelayMembershipListCardPreview() {
|
||||
private fun RelayAddMemberCardPreview() {
|
||||
ThemeComparisonColumn {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonAdd,
|
||||
icon = MaterialSymbols.PersonAdd,
|
||||
title = "Member added to relay",
|
||||
subtitle = "a1b2c3d4e5f6a7b8...",
|
||||
)
|
||||
@@ -219,7 +216,7 @@ private fun RelayAddMemberCardPreview() {
|
||||
private fun RelayRemoveMemberCardPreview() {
|
||||
ThemeComparisonColumn {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonRemove,
|
||||
icon = MaterialSymbols.PersonRemove,
|
||||
title = "Member removed from relay",
|
||||
subtitle = "a1b2c3d4e5f6a7b8...",
|
||||
)
|
||||
@@ -231,7 +228,7 @@ private fun RelayRemoveMemberCardPreview() {
|
||||
private fun RelayJoinRequestCardPreview() {
|
||||
ThemeComparisonColumn {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.Default.PersonAdd,
|
||||
icon = MaterialSymbols.PersonAdd,
|
||||
title = "Relay join request",
|
||||
subtitle = null,
|
||||
)
|
||||
@@ -243,7 +240,7 @@ private fun RelayJoinRequestCardPreview() {
|
||||
private fun RelayLeaveRequestCardPreview() {
|
||||
ThemeComparisonColumn {
|
||||
RelayMemberEventCard(
|
||||
icon = Icons.AutoMirrored.Filled.ExitToApp,
|
||||
icon = MaterialSymbols.AutoMirrored.ExitToApp,
|
||||
title = "Relay leave request",
|
||||
subtitle = null,
|
||||
)
|
||||
|
||||
@@ -28,8 +28,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.FileOpen
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -46,6 +44,8 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.countToHumanReadableBytes
|
||||
@@ -249,7 +249,7 @@ fun ShortTorrentHeader(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.FileOpen,
|
||||
symbol = MaterialSymbols.FileOpen,
|
||||
contentDescription = stringRes(id = R.string.torrent_file),
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
|
||||
@@ -28,9 +28,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PauseCircleOutline
|
||||
import androidx.compose.material.icons.filled.PlayCircleOutline
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -51,6 +48,8 @@ import androidx.media3.ui.compose.ContentFrame
|
||||
import androidx.media3.ui.compose.SURFACE_TYPE_TEXTURE_VIEW
|
||||
import androidx.media3.ui.compose.state.rememberPlayPauseButtonState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.playback.composable.DEFAULT_MUTED_SETTING
|
||||
@@ -252,7 +251,7 @@ fun PlayPauseButton(controllerState: MediaControllerState) {
|
||||
modifier = Size75Modifier,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (state.showPlay) Icons.Default.PlayCircleOutline else Icons.Default.PauseCircleOutline,
|
||||
symbol = if (state.showPlay) MaterialSymbols.PlayCircleOutline else MaterialSymbols.PauseCircleOutline,
|
||||
contentDescription = if (state.showPlay) stringResource(R.string.play) else stringResource(R.string.pause),
|
||||
modifier = Size50Modifier,
|
||||
tint = Color.White,
|
||||
|
||||
@@ -23,8 +23,6 @@ package com.vitorpamplona.amethyst.ui.note.types
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowForwardIos
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
@@ -38,6 +36,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -167,7 +167,7 @@ fun TransferCard(
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.ArrowForwardIos,
|
||||
symbol = MaterialSymbols.AutoMirrored.ArrowForwardIos,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.bitcoinColor,
|
||||
modifier = Size20Modifier,
|
||||
|
||||
+26
-27
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.commons.call.CallManager
|
||||
import com.vitorpamplona.amethyst.commons.model.privateChats.ChatroomList
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
@@ -311,28 +312,21 @@ class GiftWrapEventHandler(
|
||||
|
||||
eventNote.event = event.copyNoContent()
|
||||
|
||||
// Check if the unwrapped event is a Marmot WelcomeEvent (kind:444)
|
||||
if (MarmotInboundProcessor.isWelcomeEvent(innerGift)) {
|
||||
Log.d("MarmotDbg") {
|
||||
"GiftWrapEventHandler: detected Marmot WelcomeEvent — routing to processMarmotWelcome"
|
||||
}
|
||||
processMarmotWelcome(innerGift, eventNote, publicNote)
|
||||
return
|
||||
}
|
||||
|
||||
if (cache.justConsume(innerGift, null, false)) {
|
||||
cache.copyRelaysFromTo(publicNote, innerGift)
|
||||
val innerGiftNote = cache.getOrCreateNote(innerGift.id)
|
||||
eventProcessor.consumeEvent(innerGift, innerGiftNote, publicNote)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processMarmotWelcome(
|
||||
innerEvent: Event,
|
||||
eventNote: Note,
|
||||
publicNote: Note,
|
||||
) {
|
||||
processMarmotWelcomeFlow(innerEvent, account)
|
||||
// Marmot Welcomes need MLS processing in addition to being cached,
|
||||
// but they do not route through the normal eventProcessor consumer.
|
||||
if (MarmotInboundProcessor.isWelcomeEvent(innerGift)) {
|
||||
Log.d("MarmotDbg") {
|
||||
"GiftWrapEventHandler: detected Marmot WelcomeEvent — routing to processMarmotWelcomeFlow"
|
||||
}
|
||||
processMarmotWelcomeFlow(innerGift, account)
|
||||
} else {
|
||||
eventProcessor.consumeEvent(innerGift, innerGiftNote, publicNote)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processExistingGiftWrap(
|
||||
@@ -404,6 +398,11 @@ private suspend fun processMarmotWelcomeFlow(
|
||||
if (result.needsKeyPackageRotation) {
|
||||
account.publishMarmotKeyPackages()
|
||||
}
|
||||
|
||||
// Fire the "You've been added to <group>" notification. Welcomes
|
||||
// have no `p` tag, so the cache-observer path can't route them;
|
||||
// this is the single point where we know the recipient account.
|
||||
Amethyst.instance.notificationDispatcher.notifyWelcome(innerEvent, account)
|
||||
}
|
||||
|
||||
is WelcomeResult.AlreadyJoined -> {
|
||||
@@ -472,23 +471,23 @@ class SealedRumorEventHandler(
|
||||
|
||||
eventNote.event = event.copyNoContent()
|
||||
|
||||
cache.justConsume(innerRumor, null, true)
|
||||
cache.copyRelaysFromTo(publicNote, innerRumor)
|
||||
|
||||
val innerRumorNote = cache.getOrCreateNote(innerRumor.id)
|
||||
|
||||
// Marmot Welcome: GiftWrap → Seal → WelcomeEvent. The Seal handler
|
||||
// is the actual point at which we see the kind:444 inner. Route it
|
||||
// straight to the shared flow — there's no normal LocalCache event
|
||||
// handler for kind:444, so otherwise it would be silently dropped.
|
||||
// to the MLS flow for group joining in addition to caching — there's
|
||||
// no normal eventProcessor consumer for kind:444.
|
||||
if (MarmotInboundProcessor.isWelcomeEvent(innerRumor)) {
|
||||
Log.d("MarmotDbg") {
|
||||
"SealedRumorEventHandler: detected Marmot WelcomeEvent inside seal — routing to processMarmotWelcomeFlow"
|
||||
}
|
||||
processMarmotWelcomeFlow(innerRumor, account)
|
||||
return
|
||||
} else {
|
||||
eventProcessor.consumeEvent(innerRumor, innerRumorNote, publicNote)
|
||||
}
|
||||
|
||||
cache.justConsume(innerRumor, null, true)
|
||||
cache.copyRelaysFromTo(publicNote, innerRumor)
|
||||
|
||||
val innerRumorNote = cache.getOrCreateNote(innerRumor.id)
|
||||
eventProcessor.consumeEvent(innerRumor, innerRumorNote, publicNote)
|
||||
}
|
||||
|
||||
private suspend fun processExistingSealedRumor(
|
||||
|
||||
+3
-3
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.articles
|
||||
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@@ -44,7 +44,7 @@ fun NewArticleButton(nav: INav) {
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Add,
|
||||
symbol = MaterialSymbols.Add,
|
||||
contentDescription = stringRes(id = R.string.new_long_form_post),
|
||||
modifier = Size26Modifier,
|
||||
tint = Color.White,
|
||||
|
||||
+3
-4
@@ -28,9 +28,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PanTool
|
||||
import androidx.compose.material.icons.outlined.PanTool
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
@@ -50,6 +47,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.nip53LiveActivities.LiveActivitiesChannel
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote
|
||||
@@ -181,7 +180,7 @@ private fun AudioRoomStageContent(
|
||||
) {
|
||||
FilledTonalIconButton(onClick = { handRaised = !handRaised }) {
|
||||
Icon(
|
||||
imageVector = if (handRaised) Icons.Filled.PanTool else Icons.Outlined.PanTool,
|
||||
symbol = if (handRaised) MaterialSymbols.PanTool else MaterialSymbols.PanTool,
|
||||
contentDescription =
|
||||
stringRes(
|
||||
if (handRaised) R.string.audio_room_lower_hand else R.string.audio_room_raise_hand,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user