mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 11:48:24 +00:00
refactor(commonsUI): move the chat bubble group, and fix the round's audit findings
The chat bubble layout, its group-position shapes, jumbo emoji sizing, the date/subject divisor and the scroll-to-newest effect move to commonsUI commons/chats/ui. Desktop keeps its older ChatBubbleLayout fork for now; the merge is the Desktop phase. Audit follow-ups on the previous commit: - PdfFetcher reads the disk cache from a provider on the IO dispatcher, so a cold-start PDF card no longer builds the app's lazy cache on main. - The Buzz DM lists resolve TimeAgoLabels once per list, not per row. - The iOS DateSkeletonFormatter rebuilds on a locale/time-zone change. - ScreenLayoutTest pins the inclusive 600dp breakpoint. - Stale KDoc links, a same-package import, and the baseline profile's stable-name entries for NowProvider and the moved theme functions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjQQN9CgWHVtNCSWqnKoqY
This commit is contained in:
@@ -24768,17 +24768,17 @@ SPLcom/vitorpamplona/amethyst/ui/components/WindowUtilsKt;->getActivityOrNull(La
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/navigation/topbars/ShorterTopAppBarKt;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/navigation/topbars/ShorterTopAppBarKt;-><clinit>()V
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/navigation/topbars/ShorterTopAppBarKt;->getTopBarSize()F
|
||||
Lcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt;-><clinit>()V
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt;->NowProvider(Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
|
||||
Lcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$$ExternalSyntheticLambda1;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$$ExternalSyntheticLambda1;-><init>()V
|
||||
Lcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;-><init>(Lkotlin/coroutines/Continuation;)V
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invoke(Landroidx/compose/runtime/ProduceStateScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
SPLcom/vitorpamplona/amethyst/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt;-><clinit>()V
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt;->NowProvider(Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$$ExternalSyntheticLambda1;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$$ExternalSyntheticLambda1;-><init>()V
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;-><init>(Lkotlin/coroutines/Continuation;)V
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invoke(Landroidx/compose/runtime/ProduceStateScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/note/elements/NowProviderKt$NowProvider$now$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||
Lcom/vitorpamplona/amethyst/ui/screen/AccountScreenKt;
|
||||
SPLcom/vitorpamplona/amethyst/ui/screen/AccountScreenKt;->AccountScreen$lambda$0(Landroidx/compose/runtime/State;)Lcom/vitorpamplona/amethyst/ui/screen/AccountState;
|
||||
SPLcom/vitorpamplona/amethyst/ui/screen/AccountScreenKt;->AccountScreen$lambda$2(Lcom/vitorpamplona/amethyst/ui/screen/AccountSessionManager;Lcom/vitorpamplona/amethyst/ui/screen/AccountState;Landroidx/compose/runtime/Composer;I)Lkotlin/Unit;
|
||||
@@ -25632,6 +25632,7 @@ SPLcom/vitorpamplona/amethyst/commons/ui/theme/ShapeKt;->getSize40dp()F
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/ShapeKt;->getSize50dp()F
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/ShapeKt;->getSmallBorder()Landroidx/compose/foundation/shape/RoundedCornerShape;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/ShapeKt;->getSmallestBorder()Landroidx/compose/foundation/shape/RoundedCornerShape;
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;
|
||||
Lcom/vitorpamplona/amethyst/ui/theme/ThemeKt;
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/theme/MarkdownStyleKt;
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;
|
||||
@@ -25648,13 +25649,13 @@ SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->AmethystTheme$lambda$9(Landroid
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->AmethystTheme(Lcom/vitorpamplona/amethyst/commons/model/ThemeType;Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;Lcom/vitorpamplona/amethyst/commons/model/FontFamilyType;Lcom/vitorpamplona/amethyst/commons/model/FontSizeType;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->AmethystTheme(Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;I)V
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->accentContainer-DxMtmZc(JZ)J
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->accentPrimary(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;Z)J
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->accentSecondary(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;Z)J
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->darkColors(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;)Landroidx/compose/material3/ColorScheme;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;->accentPrimary(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;Z)J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;->accentSecondary(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;Z)J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;->amethystDarkColors(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;)Landroidx/compose/material3/ColorScheme;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->getPlaceholderText(Landroidx/compose/material3/ColorScheme;)J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->getTransparentBackground(Landroidx/compose/material3/ColorScheme;)J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->isLight(Landroidx/compose/material3/ColorScheme;)Z
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->lightColors(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;)Landroidx/compose/material3/ColorScheme;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;->amethystLightColors(Lcom/vitorpamplona/amethyst/commons/model/AccentColorType;)Landroidx/compose/material3/ColorScheme;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->onAccent-8_81llA(J)J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystColorSchemeKt;->onAccentContainer-DxMtmZc(JZ)J
|
||||
Lcom/vitorpamplona/amethyst/ui/theme/ThemeKt$$ExternalSyntheticLambda0;
|
||||
@@ -25685,7 +25686,7 @@ SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt;->getDefaultParagraphSpaci
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt;->getFont14SP()J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt;->getFont17SP()J
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt;->getTypography()Landroidx/compose/material3/Typography;
|
||||
SPLcom/vitorpamplona/amethyst/ui/theme/ThemeKt;->toFontFamily(Lcom/vitorpamplona/amethyst/commons/model/FontFamilyType;)Landroidx/compose/ui/text/font/FontFamily;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/AmethystThemeKt;->toFontFamily(Lcom/vitorpamplona/amethyst/commons/model/FontFamilyType;)Landroidx/compose/ui/text/font/FontFamily;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt;->withFontFamily(Landroidx/compose/material3/Typography;Landroidx/compose/ui/text/font/FontFamily;)Landroidx/compose/material3/Typography;
|
||||
Lcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt$$ExternalSyntheticLambda0;
|
||||
SPLcom/vitorpamplona/amethyst/commons/ui/theme/TypeKt$$ExternalSyntheticLambda0;-><init>()V
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ private fun LoadedPdfPreviewCard(
|
||||
value =
|
||||
try {
|
||||
PdfFetcher
|
||||
.fetchSnapshot(content.url, Amethyst.instance.diskCache) { url ->
|
||||
.fetchSnapshot(content.url, { Amethyst.instance.diskCache }) { url ->
|
||||
accountViewModel.httpClientBuilder.okHttpClientForPreview(url)
|
||||
}.use { snapshot ->
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
+1
-1
@@ -196,7 +196,7 @@ private fun PdfViewerContent(
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val snapshot =
|
||||
PdfFetcher.fetchSnapshot(content.url, Amethyst.instance.diskCache) { url ->
|
||||
PdfFetcher.fetchSnapshot(content.url, { Amethyst.instance.diskCache }) { url ->
|
||||
accountViewModel.httpClientBuilder.okHttpClientForPreview(url)
|
||||
}
|
||||
try {
|
||||
|
||||
+1
-1
@@ -273,7 +273,7 @@ private fun PermanentDrawerShell(
|
||||
|
||||
/**
|
||||
* Hosts the navigation content. Screen width capping happens per NavHost destination
|
||||
* ([com.vitorpamplona.amethyst.ui.layouts.CappedScreenContent] via the NavigationEffects
|
||||
* ([com.vitorpamplona.amethyst.commons.ui.layouts.CappedScreenContent] via the NavigationEffects
|
||||
* builders), so this pane just claims the leftover row width.
|
||||
*/
|
||||
@Composable
|
||||
|
||||
+7
-3
@@ -85,6 +85,7 @@ import com.vitorpamplona.amethyst.commons.resources.cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.remove_from_messages
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarWithBackButton
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.TimeAgoLabels
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.rememberTimeAgoLabels
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.timeAgoShort
|
||||
import com.vitorpamplona.amethyst.commons.ui.pluralStringRes
|
||||
@@ -127,6 +128,8 @@ fun BuzzDmListScreen(
|
||||
// Hidden conversations stay collapsed behind a header — they are off Messages by the user's own
|
||||
// choice, so they must not compete with the live inbox; they only need to be *reachable* again.
|
||||
var showHidden by remember { mutableStateOf(false) }
|
||||
// Resolved once for the list, not per row.
|
||||
val timeLabels = rememberTimeAgoLabels()
|
||||
|
||||
Scaffold(
|
||||
topBar = { TopBarWithBackButton(stringRes(Res.string.buzz_dm_title), nav) },
|
||||
@@ -149,7 +152,7 @@ fun BuzzDmListScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
) {
|
||||
items(rows, key = { it.channelId }) { row ->
|
||||
DmRowCard(row, isHidden = false, viewModel = viewModel, accountViewModel = accountViewModel, nav = nav)
|
||||
DmRowCard(row, isHidden = false, viewModel = viewModel, timeLabels = timeLabels, accountViewModel = accountViewModel, nav = nav)
|
||||
}
|
||||
if (hiddenRows.isNotEmpty()) {
|
||||
item(key = "hidden-header") {
|
||||
@@ -161,7 +164,7 @@ fun BuzzDmListScreen(
|
||||
}
|
||||
if (showHidden) {
|
||||
items(hiddenRows, key = { "hidden-${it.channelId}" }) { row ->
|
||||
DmRowCard(row, isHidden = true, viewModel = viewModel, accountViewModel = accountViewModel, nav = nav)
|
||||
DmRowCard(row, isHidden = true, viewModel = viewModel, timeLabels = timeLabels, accountViewModel = accountViewModel, nav = nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,6 +214,7 @@ private fun DmRowCard(
|
||||
row: BuzzDmListViewModel.DmRow,
|
||||
isHidden: Boolean,
|
||||
viewModel: BuzzDmListViewModel,
|
||||
timeLabels: TimeAgoLabels,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
@@ -256,7 +260,7 @@ private fun DmRowCard(
|
||||
}
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text(
|
||||
text = timeAgoShort(row.lastActivity, rememberTimeAgoLabels()),
|
||||
text = timeAgoShort(row.lastActivity, timeLabels),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
+1
-1
@@ -69,6 +69,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.AutoScrollToNewest
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnGroupManager
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
@@ -121,7 +122,6 @@ import com.vitorpamplona.amethyst.ui.note.UserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.types.RenderAudioWaveformPlayer
|
||||
import com.vitorpamplona.amethyst.ui.pluralStringRes
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.AutoScrollToNewest
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.types.observeUserNameByHex
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.ChatFileUploadDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.ChatFileUploadState
|
||||
|
||||
+5
-5
@@ -55,8 +55,13 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.CHAT_GROUP_WINDOW_SECONDS
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatBubbleLayout
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatDivisor
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.UserDisplayNameLayout
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.jumboEmojiCount
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.jumboEmojiFontSize
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnMentions
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
@@ -109,11 +114,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.ReactionChipView
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.SectionDivider
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.TileRow
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.authorNameColorFor
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.jumboEmojiCount
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.jumboEmojiFontSize
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.CHAT_GROUP_WINDOW_SECONDS
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.ChatBubbleLayout
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.ChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.types.observeUserNameByHex
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.cordn.coordinatorDisplayName
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
+3
-1
@@ -36,6 +36,9 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.AutoScrollToNewest
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.NewDateOrSubjectDivisor
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.watchChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedState
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
@@ -48,7 +51,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
||||
import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.watchChatGroupPosition
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
+3
-2
@@ -45,6 +45,9 @@ import androidx.compose.ui.Alignment.Companion.CenterStart
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatBubbleLayout
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.jumboEmojiCount
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.model.latestBuzzEdit
|
||||
import com.vitorpamplona.amethyst.commons.model.latestConcordEdit
|
||||
@@ -60,8 +63,6 @@ import com.vitorpamplona.amethyst.ui.note.WatchBlockAndReport
|
||||
import com.vitorpamplona.amethyst.ui.note.WatchNoteEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.DisplayZapSplits
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.ChatBubbleLayout
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.ChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.types.RenderBuzzActivityRow
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.types.RenderBuzzDiff
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.types.RenderBuzzEditedNote
|
||||
|
||||
+2
-2
@@ -26,6 +26,8 @@ import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.jumboEmojiCount
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.jumboEmojiFontSize
|
||||
import com.vitorpamplona.amethyst.commons.model.EmptyTagList
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists
|
||||
@@ -40,8 +42,6 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderAudioFromIMeta
|
||||
import com.vitorpamplona.amethyst.ui.note.types.appendMissingImetaUrls
|
||||
import com.vitorpamplona.amethyst.ui.note.types.getAudioMetaWithWaveform
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.jumboEmojiCount
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.jumboEmojiFontSize
|
||||
|
||||
@Composable
|
||||
fun RenderRegularTextNote(
|
||||
|
||||
+7
-1
@@ -99,6 +99,7 @@ import com.vitorpamplona.amethyst.commons.resources.relay_tor_clearnet_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarExtensibleWithBackButton
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.TimeAgoLabels
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.rememberTimeAgoLabels
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.timeAgoShort
|
||||
import com.vitorpamplona.amethyst.commons.ui.pluralStringRes
|
||||
@@ -263,6 +264,8 @@ fun RelayGroupChannelListScreen(
|
||||
// as the workspace overflow menu (Add people / Invite), whose own doc notes "any member sees them,
|
||||
// the relay only serves the owner/admin ones."
|
||||
val myPubkey = accountViewModel.account.signer.pubKey
|
||||
// Resolved once for the list, not per DM row.
|
||||
val timeLabels = rememberTimeAgoLabels()
|
||||
|
||||
val buzzVm: BuzzRelayImportViewModel = viewModel(key = "BuzzImport-${relay.url}")
|
||||
LaunchedEffect(relay, isBuzz) { if (isBuzz) buzzVm.bind(accountViewModel.account, relay.url) }
|
||||
@@ -644,6 +647,7 @@ fun RelayGroupChannelListScreen(
|
||||
BuzzDmInlineRow(
|
||||
row = row,
|
||||
myPubkey = myPubkey,
|
||||
timeLabels = timeLabels,
|
||||
isHidden = false,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
@@ -675,6 +679,7 @@ fun RelayGroupChannelListScreen(
|
||||
BuzzDmInlineRow(
|
||||
row = row,
|
||||
myPubkey = myPubkey,
|
||||
timeLabels = timeLabels,
|
||||
isHidden = true,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
@@ -828,6 +833,7 @@ private fun SectionAddButton(
|
||||
private fun BuzzDmInlineRow(
|
||||
row: BuzzDmListViewModel.DmRow,
|
||||
myPubkey: HexKey,
|
||||
timeLabels: TimeAgoLabels,
|
||||
isHidden: Boolean,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
@@ -885,7 +891,7 @@ private fun BuzzDmInlineRow(
|
||||
}
|
||||
if (row.lastActivity > 0) {
|
||||
Text(
|
||||
text = timeAgoShort(row.lastActivity, rememberTimeAgoLabels()),
|
||||
text = timeAgoShort(row.lastActivity, timeLabels),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.cordn
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatGroupPosition
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.cordnGroup.cordnGroupPositionFor
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.cordnGroup.sameDayAs
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.layouts.ChatGroupPosition
|
||||
import com.vitorpamplona.quartz.cordn.spec02Envelopes.CordnDeliveredMessage
|
||||
import com.vitorpamplona.quartz.cordn.spec02Envelopes.CordnEnvelope
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
|
||||
@@ -88,6 +88,10 @@ class ScreenLayoutTest {
|
||||
@Test
|
||||
fun compactWidthKeepsTheBottomBar() = assertStyle(NavigationStyle.BOTTOM_BAR, 599, 900)
|
||||
|
||||
// The Medium breakpoint is inclusive: exactly 600dp is no longer Compact.
|
||||
@Test
|
||||
fun exactlyAtTheMediumBreakpointRails() = assertStyle(NavigationStyle.NAV_RAIL, 600, 900)
|
||||
|
||||
// ---- Notification panel ----
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1501,3 +1501,26 @@ A transitive-blocker sweep of the 1,385 files under `amethyst/…/ui/`, after th
|
||||
- **Two corrections to the MOVE-AFTER table above:**
|
||||
- `INav`/`Route` are no longer blockers: every ui file imports the commons ones.
|
||||
- `ui/note/types` is 111 files, not ~89, and "AVM threading" understates it: the hubs matter more than the parameter.
|
||||
|
||||
### Follow-up in the same round: the chat bubble group, and the audit
|
||||
|
||||
- **Moved to `commonsUI/…/commons/chats/ui`**, beside `ChatDivisor` and
|
||||
`UserDisplayNameLayout`: `ChatBubbleLayout`, `ChatGroupPosition`, `JumboEmoji`,
|
||||
`NewDateOrSubjectDivisor` and `AutoScrollToNewest`. `AutoScrollToNewest` and
|
||||
`CHAT_GROUP_WINDOW_SECONDS` went from `internal` to public so the app can reach them.
|
||||
Desktop's `ui/chats/ChatBubbleLayout.kt` is an older fork of this one (no group
|
||||
position, jumbo emoji, swipe-to-reply or reaction row). Replacing it is the Desktop
|
||||
phase.
|
||||
- **Audit follow-ups:**
|
||||
- `PdfFetcher` takes the disk cache as a provider, read on the IO dispatcher, so a PDF
|
||||
card composing on a cold start doesn't build the app's lazy cache on the main thread.
|
||||
- The two DM lists resolve `TimeAgoLabels` once per list instead of once per row.
|
||||
- The iOS `DateSkeletonFormatter` rebuilds on a locale or time-zone change, like the
|
||||
other actuals.
|
||||
- `ScreenLayoutTest` pins the inclusive 600dp boundary.
|
||||
- Two stale KDoc links and a same-package import are fixed.
|
||||
- The generated baseline profile has its stable-name entries repointed:
|
||||
`NowProviderKt`, and the five theme functions now in `AmethystThemeKt`. Its R8
|
||||
lambda entries were already stale before this round (it still lists
|
||||
`MarkDownStyleOnDark` under `ThemeKt`), so **regenerate the profile** after these
|
||||
moves.
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
* 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.ui.screen.loggedIn.chats.feed
|
||||
package com.vitorpamplona.amethyst.commons.chats.ui
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -46,7 +46,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
* message they just wrote somewhere off-screen below.
|
||||
*/
|
||||
@Composable
|
||||
internal fun AutoScrollToNewest(
|
||||
fun AutoScrollToNewest(
|
||||
listState: LazyListState,
|
||||
newest: Any?,
|
||||
mine: Boolean = false,
|
||||
+1
-2
@@ -18,7 +18,7 @@
|
||||
* 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.ui.screen.loggedIn.chats.feed.layouts
|
||||
package com.vitorpamplona.amethyst.commons.chats.ui
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.animate
|
||||
@@ -73,7 +73,6 @@ import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.UserDisplayNameLayout
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.CommentIcon
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
* 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.ui.screen.loggedIn.chats.feed.layouts
|
||||
package com.vitorpamplona.amethyst.commons.chats.ui
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -88,7 +88,7 @@ fun chatBubbleShapeFor(
|
||||
}
|
||||
|
||||
/** Messages more than this far apart never group, even from the same author. */
|
||||
internal const val CHAT_GROUP_WINDOW_SECONDS = 10 * 60L
|
||||
const val CHAT_GROUP_WINDOW_SECONDS = 10 * 60L
|
||||
|
||||
/**
|
||||
* Event kinds that don't render as regular bubbles (zaps, raids, clips) or that
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* 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.ui.screen.loggedIn.chats.feed
|
||||
package com.vitorpamplona.amethyst.commons.chats.ui
|
||||
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.sp
|
||||
+1
-2
@@ -18,11 +18,10 @@
|
||||
* 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.ui.screen.loggedIn.chats.feed
|
||||
package com.vitorpamplona.amethyst.commons.chats.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.ChatDivisor
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.never
|
||||
+1
-1
@@ -91,7 +91,7 @@ fun FileAttachmentCard(
|
||||
/**
|
||||
* The icon + title + subtitle row shared by every card that stands in for a file it can't
|
||||
* render inline: this one and the PDF placeholder/skeleton in
|
||||
* [com.vitorpamplona.amethyst.ui.components.pdf.PdfPreviewCard].
|
||||
* the Android app's `PdfPreviewCard`.
|
||||
*/
|
||||
@Composable
|
||||
fun FileAttachmentRow(
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.elements.LocalNowSeconds
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.rememberTimeAgoLabels
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.rememberTimeOfDayFormatter
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.timeAbsoluteWith
|
||||
|
||||
+27
-8
@@ -30,22 +30,41 @@ import platform.Foundation.NSDateFormatter
|
||||
import platform.Foundation.NSDateFormatterNoStyle
|
||||
import platform.Foundation.NSDateFormatterShortStyle
|
||||
import platform.Foundation.NSLocale
|
||||
import platform.Foundation.NSTimeZone
|
||||
import platform.Foundation.currentLocale
|
||||
import platform.Foundation.dateWithTimeIntervalSince1970
|
||||
import platform.Foundation.defaultTimeZone
|
||||
import platform.Foundation.localeIdentifier
|
||||
import kotlin.concurrent.Volatile
|
||||
|
||||
private fun dateOf(epochMillis: Long) = NSDate.dateWithTimeIntervalSince1970(epochMillis / 1000.0)
|
||||
|
||||
/** NSDateFormatter is thread-safe for formatting on iOS 7+; the template picks the locale's order. */
|
||||
/**
|
||||
* NSDateFormatter is thread-safe for formatting on iOS 7+; the template picks the locale's order.
|
||||
* Rebuilt when the current locale or time zone changes, like the other actuals.
|
||||
*/
|
||||
actual class DateSkeletonFormatter actual constructor(
|
||||
skeleton: String,
|
||||
private val skeleton: String,
|
||||
) {
|
||||
private val formatter =
|
||||
NSDateFormatter().apply {
|
||||
locale = NSLocale.currentLocale
|
||||
setLocalizedDateFormatFromTemplate(skeleton)
|
||||
}
|
||||
private class Cached(
|
||||
val key: String,
|
||||
val formatter: NSDateFormatter,
|
||||
)
|
||||
|
||||
actual fun format(epochMillis: Long): String = formatter.stringFromDate(dateOf(epochMillis))
|
||||
@Volatile private var cached: Cached? = null
|
||||
|
||||
actual fun format(epochMillis: Long): String {
|
||||
val locale = NSLocale.currentLocale
|
||||
val key = locale.localeIdentifier + "|" + NSTimeZone.defaultTimeZone.name
|
||||
val formatter =
|
||||
cached?.takeIf { it.key == key }?.formatter
|
||||
?: NSDateFormatter()
|
||||
.apply {
|
||||
this.locale = locale
|
||||
setLocalizedDateFormatFromTemplate(skeleton)
|
||||
}.also { cached = Cached(key, it) }
|
||||
return formatter.stringFromDate(dateOf(epochMillis))
|
||||
}
|
||||
}
|
||||
|
||||
actual fun calendarYearAndDay(epochMillis: Long): Int {
|
||||
|
||||
+5
-3
@@ -34,15 +34,17 @@ object PdfFetcher {
|
||||
* responsible for closing the returned snapshot; while it's open the cache entry cannot be
|
||||
* evicted, so the underlying file stays valid for `PdfRenderer`.
|
||||
*
|
||||
* Pass the app's Coil [diskCache] so PDFs share the same LRU eviction and disk budget as
|
||||
* images.
|
||||
* Pass the app's Coil disk cache so PDFs share the same LRU eviction and disk budget as
|
||||
* images. It is a provider, read on the IO dispatcher: the app builds its cache lazily
|
||||
* (statvfs, directory setup), and a card composing on a cold start must not do that on main.
|
||||
*/
|
||||
suspend fun fetchSnapshot(
|
||||
url: String,
|
||||
diskCache: DiskCache,
|
||||
diskCache: () -> DiskCache,
|
||||
okHttpClient: (String) -> OkHttpClient,
|
||||
): DiskCache.Snapshot =
|
||||
withContext(Dispatchers.IO) {
|
||||
val diskCache = diskCache()
|
||||
// Covers the cache-hit fast path too, not just the download below it. openSnapshot()
|
||||
// contends on the global DiskLruCache lock, which Coil's cleanup pass holds across a
|
||||
// burst of unlink syscalls (see DeferredDeleteFileSystem) — calling it from a caller
|
||||
|
||||
Reference in New Issue
Block a user