mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 11:07:24 +01:00
Merge branch 'vitorpamplona:main' into add-feed-indicator-to-live-bubbles
This commit is contained in:
@@ -33,34 +33,32 @@ import kotlin.time.measureTimedValue
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
val isDebug = BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "benchmark"
|
||||
|
||||
fun debugState(context: Context) {
|
||||
// Amethyst.instance.client
|
||||
// .allSubscriptions()
|
||||
// .forEach { Log.d("STATE DUMP", "${it.key} ${it.value.filters.joinToString { it.filter.toJson() }}") }
|
||||
private const val STATE_DUMP_TAG = "STATE DUMP"
|
||||
|
||||
fun debugState(context: Context) {
|
||||
val totalMemoryMb = Runtime.getRuntime().totalMemory() / (1024 * 1024)
|
||||
val freeMemoryMb = Runtime.getRuntime().freeMemory() / (1024 * 1024)
|
||||
val maxMemoryMb = Runtime.getRuntime().maxMemory() / (1024 * 1024)
|
||||
|
||||
val jvmHeapAllocatedMb = totalMemoryMb - freeMemoryMb
|
||||
|
||||
Log.d("STATE DUMP", "Total Heap Allocated: $jvmHeapAllocatedMb/$maxMemoryMb MB")
|
||||
Log.d(STATE_DUMP_TAG, "Total Heap Allocated: $jvmHeapAllocatedMb/$maxMemoryMb MB")
|
||||
|
||||
val nativeHeap = Debug.getNativeHeapAllocatedSize() / (1024 * 1024)
|
||||
val maxNative = Debug.getNativeHeapSize() / (1024 * 1024)
|
||||
|
||||
Log.d("STATE DUMP", "Total Native Heap Allocated: $nativeHeap/$maxNative MB")
|
||||
Log.d(STATE_DUMP_TAG, "Total Native Heap Allocated: $nativeHeap/$maxNative MB")
|
||||
|
||||
val activityManager: ActivityManager? = context.getSystemService()
|
||||
if (activityManager != null) {
|
||||
val isLargeHeap = (context.applicationInfo.flags and ApplicationInfo.FLAG_LARGE_HEAP) != 0
|
||||
val memClass = if (isLargeHeap) activityManager.largeMemoryClass else activityManager.memoryClass
|
||||
|
||||
Log.d("STATE DUMP", "Memory Class $memClass MB (largeHeap $isLargeHeap)")
|
||||
Log.d(STATE_DUMP_TAG, "Memory Class $memClass MB (largeHeap $isLargeHeap)")
|
||||
}
|
||||
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Connected Relays: " +
|
||||
Amethyst.instance.client
|
||||
.relayStatusFlow()
|
||||
@@ -71,16 +69,16 @@ fun debugState(context: Context) {
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Image Disk Cache ${(Amethyst.instance.diskCache.size) / (1024 * 1024)}/${(Amethyst.instance.diskCache.maxSize) / (1024 * 1024)} MB",
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Image Memory Cache ${(Amethyst.instance.memoryCache.size) / (1024 * 1024)}/${(Amethyst.instance.memoryCache.maxSize) / (1024 * 1024)} MB",
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Notes: " +
|
||||
LocalCache.notes.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -89,7 +87,7 @@ fun debugState(context: Context) {
|
||||
LocalCache.notes.size(),
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Addressables: " +
|
||||
LocalCache.addressables.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -98,7 +96,7 @@ fun debugState(context: Context) {
|
||||
LocalCache.addressables.size(),
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Users: " +
|
||||
LocalCache.users.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -107,7 +105,7 @@ fun debugState(context: Context) {
|
||||
LocalCache.users.size(),
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Public Chat Channels: " +
|
||||
LocalCache.publicChatChannels.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -116,7 +114,7 @@ fun debugState(context: Context) {
|
||||
LocalCache.publicChatChannels.values().sumOf { it.notes.size() },
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Live Chat Channels: " +
|
||||
LocalCache.liveChatChannels.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -125,7 +123,7 @@ fun debugState(context: Context) {
|
||||
LocalCache.liveChatChannels.values().sumOf { it.notes.size() },
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Ephemeral Chat Channels: " +
|
||||
LocalCache.ephemeralChannels.filter { _, it -> it.flowSet != null }.size +
|
||||
" / " +
|
||||
@@ -135,7 +133,7 @@ fun debugState(context: Context) {
|
||||
)
|
||||
LocalCache.chatroomList.forEach { key, room ->
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Private Chats $key: " +
|
||||
room.rooms.size() +
|
||||
" / " +
|
||||
@@ -143,12 +141,12 @@ fun debugState(context: Context) {
|
||||
)
|
||||
}
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Deletion Events: " +
|
||||
LocalCache.deletionIndex.size(),
|
||||
)
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Observable Events: " +
|
||||
LocalCache.observablesByKindAndETag.size +
|
||||
" / " +
|
||||
@@ -156,13 +154,13 @@ fun debugState(context: Context) {
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Spam: " +
|
||||
LocalCache.antiSpam.spamMessages.size() + " / " + LocalCache.antiSpam.recentEventIds.size() + " / " + LocalCache.antiSpam.recentAddressables.size(),
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"STATE DUMP",
|
||||
STATE_DUMP_TAG,
|
||||
"Memory used by Events: " +
|
||||
LocalCache.notes.sumOf { _, note -> note.event?.countMemory() ?: 0 } / (1024 * 1024) +
|
||||
" MB",
|
||||
@@ -179,10 +177,10 @@ fun debugState(context: Context) {
|
||||
.sumByGroup(groupMap = { _, it -> it.event?.kind }, sumOf = { _, it -> it.event?.countMemory()?.toLong() ?: 0L })
|
||||
|
||||
qttNotes.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
|
||||
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesNotes[kind]?.div((1024 * 1024))}MB ")
|
||||
Log.d(STATE_DUMP_TAG, "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesNotes[kind]?.div((1024 * 1024))}MB ")
|
||||
}
|
||||
qttAddressables.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
|
||||
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesAddressables[kind]?.div((1024 * 1024))}MB ")
|
||||
Log.d(STATE_DUMP_TAG, "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesAddressables[kind]?.div((1024 * 1024))}MB ")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,8 +75,9 @@ class AccountPreferenceStores(
|
||||
)
|
||||
}
|
||||
|
||||
fun removeAccount(npub: String) {
|
||||
file(npub).delete()
|
||||
fun removeAccount(npub: String): Boolean {
|
||||
val deleted = file(npub).delete()
|
||||
storeCache.remove(npub)
|
||||
return deleted
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,9 @@ class AccountSecretsEncryptedStores(
|
||||
serializer = Nip47WalletConnect.Nip47URI::serializer,
|
||||
)
|
||||
|
||||
fun removeAccount(npub: String) {
|
||||
file(npub).delete()
|
||||
fun removeAccount(npub: String): Boolean {
|
||||
val deleted = file(npub).delete()
|
||||
storeCache.remove(npub)
|
||||
return deleted
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,16 +27,18 @@ import okio.FileNotFoundException
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStreamReader
|
||||
|
||||
private const val STACK_TRACE_FILENAME = "stack.trace"
|
||||
|
||||
class CrashReportCache(
|
||||
val appContext: Context,
|
||||
) {
|
||||
private fun outputStream() = appContext.openFileOutput("stack.trace", Context.MODE_PRIVATE)
|
||||
private fun outputStream() = appContext.openFileOutput(STACK_TRACE_FILENAME, Context.MODE_PRIVATE)
|
||||
|
||||
private fun deleteReport() = appContext.deleteFile("stack.trace")
|
||||
private fun deleteReport() = appContext.deleteFile(STACK_TRACE_FILENAME)
|
||||
|
||||
private fun inputStreamOrNull(): FileInputStream? =
|
||||
try {
|
||||
appContext.openFileInput("stack.trace")
|
||||
appContext.openFileInput(STACK_TRACE_FILENAME)
|
||||
} catch (_: FileNotFoundException) {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -52,13 +52,12 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
private const val TAG = "EventNotificationConsumer"
|
||||
private const val ACCOUNT_QUERY_PARAM = "?account="
|
||||
|
||||
class EventNotificationConsumer(
|
||||
private val applicationContext: Context,
|
||||
) {
|
||||
companion object {
|
||||
const val TAG = "EventNotificationConsumer"
|
||||
}
|
||||
|
||||
suspend fun consume(event: GiftWrapEvent) {
|
||||
Log.d(TAG, "New Notification Arrived")
|
||||
|
||||
@@ -210,7 +209,7 @@ class EventNotificationConsumer(
|
||||
val user = chatNote.author?.toBestDisplayName() ?: ""
|
||||
val userPicture = chatNote.author?.profilePicture()
|
||||
val noteUri =
|
||||
chatNote.toNEvent() + "?account=" +
|
||||
chatNote.toNEvent() + ACCOUNT_QUERY_PARAM +
|
||||
account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
@@ -255,7 +254,7 @@ class EventNotificationConsumer(
|
||||
val user = chatNote.author?.toBestDisplayName() ?: ""
|
||||
val userPicture = chatNote.author?.profilePicture()
|
||||
val noteUri =
|
||||
chatNote.toNEvent() + "?account=" +
|
||||
chatNote.toNEvent() + ACCOUNT_QUERY_PARAM +
|
||||
account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
@@ -297,7 +296,7 @@ class EventNotificationConsumer(
|
||||
val user = note.author?.toBestDisplayName() ?: ""
|
||||
val userPicture = note.author?.profilePicture()
|
||||
val noteUri =
|
||||
note.toNEvent() + "?account=" +
|
||||
note.toNEvent() + ACCOUNT_QUERY_PARAM +
|
||||
account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
@@ -324,17 +323,17 @@ class EventNotificationConsumer(
|
||||
signer: NostrSigner,
|
||||
): String? {
|
||||
val event = note.event
|
||||
when (event) {
|
||||
return when (event) {
|
||||
is PrivateDmEvent -> {
|
||||
return event.decryptContent(signer)
|
||||
event.decryptContent(signer)
|
||||
}
|
||||
|
||||
is LnZapRequestEvent -> {
|
||||
return decryptZapContentAuthor(event, signer)?.content
|
||||
decryptZapContentAuthor(event, signer)?.content
|
||||
}
|
||||
|
||||
else -> {
|
||||
return event?.content
|
||||
event?.content
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,7 +401,7 @@ class EventNotificationConsumer(
|
||||
}
|
||||
val userPicture = senderInfo.first.profilePicture()
|
||||
val noteUri =
|
||||
"notifications?account=" +
|
||||
"notifications$ACCOUNT_QUERY_PARAM" +
|
||||
account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
@@ -437,7 +436,7 @@ class EventNotificationConsumer(
|
||||
|
||||
val userPicture = senderInfo.first.profilePicture()
|
||||
val noteUri =
|
||||
"notifications?account=" +
|
||||
"notifications$ACCOUNT_QUERY_PARAM" +
|
||||
account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
|
||||
@@ -37,7 +37,6 @@ val DEFAULT_MEDIA_SERVERS: List<ServerName> =
|
||||
ServerName("Nostr.Build", "https://nostr.build", ServerType.NIP96),
|
||||
ServerName("NostrCheck.me (NIP-96)", "https://nostrcheck.me", ServerType.NIP96),
|
||||
ServerName("Sovbit", "https://files.sovbit.host", ServerType.NIP96),
|
||||
ServerName("Void.cat", "https://void.cat", ServerType.NIP96),
|
||||
ServerName("Satellite (Paid)", "https://cdn.satellite.earth", ServerType.Blossom),
|
||||
ServerName("NostrCheck.me (Blossom)", "https://cdn.nostrcheck.me", ServerType.Blossom),
|
||||
ServerName("Nostr.Download", "https://nostr.download", ServerType.Blossom),
|
||||
|
||||
@@ -20,27 +20,16 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.navigation.navs
|
||||
|
||||
import androidx.compose.material3.DrawerState
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class ObservableNav(
|
||||
val sourceNav: INav,
|
||||
private val sourceNav: INav,
|
||||
override val navigationScope: CoroutineScope,
|
||||
val onBeforeNavigate: () -> Unit,
|
||||
) : INav {
|
||||
override val drawerState: DrawerState = sourceNav.drawerState
|
||||
|
||||
override fun closeDrawer() {
|
||||
sourceNav.closeDrawer()
|
||||
}
|
||||
|
||||
override fun openDrawer() {
|
||||
sourceNav.openDrawer()
|
||||
}
|
||||
|
||||
) : INav by sourceNav {
|
||||
override fun nav(route: Route) {
|
||||
navigationScope.launch {
|
||||
onBeforeNavigate()
|
||||
@@ -71,11 +60,11 @@ class ObservableNav(
|
||||
|
||||
override fun <T : Route> popUpTo(
|
||||
route: Route,
|
||||
upToClass: KClass<T>,
|
||||
klass: KClass<T>,
|
||||
) {
|
||||
navigationScope.launch {
|
||||
onBeforeNavigate()
|
||||
}
|
||||
sourceNav.popUpTo(route, upToClass)
|
||||
sourceNav.popUpTo(route, klass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,10 @@ import com.vitorpamplona.amethyst.ui.theme.ripple24dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.warningColorOnSecondSurface
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
private const val DAMUS_RELAY_URL = "wss://relay.damus.io"
|
||||
|
||||
@Composable
|
||||
public fun RelayBadgesHorizontal(
|
||||
fun RelayBadgesHorizontal(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
@@ -162,24 +164,24 @@ fun RenderRelayIconPreview() {
|
||||
ThemeComparisonColumn {
|
||||
Row {
|
||||
RenderRelayIcon(
|
||||
displayUrl = "wss://relay.damus.io",
|
||||
iconUrl = "wss://relay.damus.io",
|
||||
displayUrl = DAMUS_RELAY_URL,
|
||||
iconUrl = DAMUS_RELAY_URL,
|
||||
loadProfilePicture = true,
|
||||
pingInMs = 100,
|
||||
loadRobohash = true,
|
||||
iconModifier = LargeRelayIconModifier,
|
||||
)
|
||||
RenderRelayIcon(
|
||||
displayUrl = "wss://relay.damus.io",
|
||||
iconUrl = "wss://relay.damus.io",
|
||||
displayUrl = DAMUS_RELAY_URL,
|
||||
iconUrl = DAMUS_RELAY_URL,
|
||||
loadProfilePicture = true,
|
||||
pingInMs = 300,
|
||||
loadRobohash = true,
|
||||
iconModifier = LargeRelayIconModifier,
|
||||
)
|
||||
RenderRelayIcon(
|
||||
displayUrl = "wss://relay.damus.io",
|
||||
iconUrl = "wss://relay.damus.io",
|
||||
displayUrl = DAMUS_RELAY_URL,
|
||||
iconUrl = DAMUS_RELAY_URL,
|
||||
loadProfilePicture = true,
|
||||
pingInMs = 500,
|
||||
loadRobohash = true,
|
||||
|
||||
@@ -28,9 +28,12 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
private const val YEAR_DATE_FORMAT = "MMM dd, yyyy"
|
||||
private const val MONTH_DATE_FORMAT = "MMM dd"
|
||||
|
||||
var locale = Locale.getDefault()
|
||||
var yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
var monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
var yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
var monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
|
||||
fun timeAgo(
|
||||
time: Long?,
|
||||
@@ -46,8 +49,8 @@ fun timeAgo(
|
||||
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
" • " + yearFormatter.format(time * 1000)
|
||||
@@ -55,8 +58,8 @@ fun timeAgo(
|
||||
// Dec 12
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
" • " + monthFormatter.format(time * 1000)
|
||||
@@ -86,8 +89,8 @@ fun timeAgoNoDot(
|
||||
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
yearFormatter.format(time * 1000)
|
||||
@@ -95,8 +98,8 @@ fun timeAgoNoDot(
|
||||
// Dec 12
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
monthFormatter.format(time * 1000)
|
||||
@@ -127,8 +130,8 @@ fun dateFormatter(
|
||||
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
yearFormatter.format(time * 1000)
|
||||
@@ -136,8 +139,8 @@ fun dateFormatter(
|
||||
// Dec 12
|
||||
if (locale != Locale.getDefault()) {
|
||||
locale = Locale.getDefault()
|
||||
yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale)
|
||||
monthFormatter = SimpleDateFormat("MMM dd", locale)
|
||||
yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale)
|
||||
monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale)
|
||||
}
|
||||
|
||||
monthFormatter.format(time * 1000)
|
||||
|
||||
@@ -59,6 +59,8 @@ import com.vitorpamplona.amethyst.ui.theme.chatDraftBackground
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.messageBubbleLimits
|
||||
|
||||
private const val RELAYS_AND_ACTIONS_TEXT = "Relays and Actions"
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun ChatBubbleLayout(
|
||||
@@ -205,7 +207,7 @@ private fun BubblePreview() {
|
||||
},
|
||||
)
|
||||
},
|
||||
detailRow = { Text("Relays and Actions") },
|
||||
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
|
||||
) { bgColor ->
|
||||
Text("This is my note")
|
||||
}
|
||||
@@ -239,7 +241,7 @@ private fun BubblePreview() {
|
||||
},
|
||||
)
|
||||
},
|
||||
detailRow = { Text("Relays and Actions") },
|
||||
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
|
||||
) { bgColor ->
|
||||
Text("This is a very long long loong note")
|
||||
}
|
||||
@@ -273,7 +275,7 @@ private fun BubblePreview() {
|
||||
},
|
||||
)
|
||||
},
|
||||
detailRow = { Text("Relays and Actions") },
|
||||
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
|
||||
) { bgColor ->
|
||||
Text("This is a draft note")
|
||||
}
|
||||
@@ -307,7 +309,7 @@ private fun BubblePreview() {
|
||||
},
|
||||
)
|
||||
},
|
||||
detailRow = { Text("Relays and Actions") },
|
||||
detailRow = { Text(RELAYS_AND_ACTIONS_TEXT) },
|
||||
) { bgColor ->
|
||||
Text("Short note")
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ fun MessagesScreen(
|
||||
val act = LocalContext.current.getActivity()
|
||||
val windowSizeClass = calculateWindowSizeClass(act)
|
||||
|
||||
val twoPane by remember {
|
||||
val twoPane by remember(windowSizeClass.widthSizeClass) {
|
||||
derivedStateOf {
|
||||
when (windowSizeClass.widthSizeClass) {
|
||||
WindowWidthSizeClass.Compact -> false
|
||||
|
||||
@@ -20,20 +20,16 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.twopane
|
||||
|
||||
import androidx.compose.material3.DrawerState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class TwoPaneNav(
|
||||
val nav: INav,
|
||||
private val nav: INav,
|
||||
override val navigationScope: CoroutineScope,
|
||||
) : INav {
|
||||
override val drawerState: DrawerState = nav.drawerState
|
||||
|
||||
) : INav by nav {
|
||||
val innerNav = mutableStateOf<Route?>(null)
|
||||
|
||||
override fun nav(route: Route) {
|
||||
@@ -56,27 +52,4 @@ class TwoPaneNav(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newStack(route: Route) {
|
||||
nav.newStack(route)
|
||||
}
|
||||
|
||||
override fun popBack() {
|
||||
nav.popBack()
|
||||
}
|
||||
|
||||
override fun <T : Route> popUpTo(
|
||||
route: Route,
|
||||
klass: KClass<T>,
|
||||
) {
|
||||
nav.popUpTo<T>(route, klass)
|
||||
}
|
||||
|
||||
override fun closeDrawer() {
|
||||
nav.closeDrawer()
|
||||
}
|
||||
|
||||
override fun openDrawer() {
|
||||
nav.openDrawer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,16 +33,16 @@ import kotlinx.collections.immutable.toImmutableMap
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@Immutable
|
||||
abstract class Card {
|
||||
abstract fun createdAt(): Long
|
||||
interface Card {
|
||||
fun createdAt(): Long
|
||||
|
||||
abstract fun id(): String
|
||||
fun id(): String
|
||||
}
|
||||
|
||||
@Immutable
|
||||
class BadgeCard(
|
||||
val note: Note,
|
||||
) : Card() {
|
||||
) : Card {
|
||||
override fun createdAt(): Long = note.createdAt() ?: 0L
|
||||
|
||||
override fun id() = note.idHex
|
||||
@@ -51,7 +51,7 @@ class BadgeCard(
|
||||
@Immutable
|
||||
class NoteCard(
|
||||
val note: Note,
|
||||
) : Card() {
|
||||
) : Card {
|
||||
override fun createdAt(): Long = note.createdAt() ?: 0L
|
||||
|
||||
override fun id() = note.idHex
|
||||
@@ -61,7 +61,7 @@ class NoteCard(
|
||||
class ZapUserSetCard(
|
||||
val user: User,
|
||||
val zapEvents: ImmutableList<CombinedZap>,
|
||||
) : Card() {
|
||||
) : Card {
|
||||
val createdAt = zapEvents.maxOfOrNull { it.createdAt() ?: 0L } ?: 0L
|
||||
|
||||
override fun createdAt(): Long = createdAt
|
||||
@@ -75,7 +75,7 @@ class MultiSetCard(
|
||||
val boostEvents: ImmutableList<Note>,
|
||||
val likeEvents: ImmutableList<Note>,
|
||||
val zapEvents: ImmutableList<CombinedZap>,
|
||||
) : Card() {
|
||||
) : Card {
|
||||
val maxCreatedAt =
|
||||
maxOf(
|
||||
zapEvents.maxOfOrNull { it.createdAt() ?: 0L } ?: 0L,
|
||||
@@ -108,7 +108,7 @@ class MultiSetCard(
|
||||
@Immutable
|
||||
class MessageSetCard(
|
||||
val note: Note,
|
||||
) : Card() {
|
||||
) : Card {
|
||||
override fun createdAt(): Long = note.createdAt() ?: 0L
|
||||
|
||||
override fun id() = note.idHex
|
||||
|
||||
Reference in New Issue
Block a user