mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
fix(ui): restore full-size quiet marks, tighten the dotted timestamp, drop Boosted
Quiet marks go back to the row's regular text size in bold with 16dp icons; the hashtag/community soft links lose their 12sp override too (the smaller tier read as too small). A new TimeAgoStyle.DottedTight renders "• 5m" without the leading space for rows whose spacedBy already provides the gap, removing the double space before the timestamp. The OTS pending pill shrinks to the stamp icon plus an ellipsis (the words move to the content description). The Boosted mark is removed entirely — from the Android header, the commons component, and the desktop feed — since the repost context is already visible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AgEpNtwnetPhETXQSdq4b5
This commit is contained in:
@@ -78,7 +78,6 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeEditDraftTo
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.DisplayZapSplits
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.BoostedMark
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayEditStatus
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayFollowingCommunityInPost
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayFollowingHashtagsInPost
|
||||
@@ -91,6 +90,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.Reward
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.StaleRelayHint
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgoStyle
|
||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayBlockedRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayBroadcastRelayList
|
||||
@@ -1834,10 +1834,6 @@ fun FirstUserInfoRow(
|
||||
NoteUsernameDisplay(baseNote, Modifier.weight(1f), textColor = textColor, accountViewModel = accountViewModel)
|
||||
}
|
||||
|
||||
if (isRepost) {
|
||||
BoostedMark()
|
||||
}
|
||||
|
||||
CheckAndDisplayEditStatus(editState)
|
||||
|
||||
if (isDraft) {
|
||||
@@ -1899,7 +1895,7 @@ fun FirstUserInfoRow(
|
||||
// The dotted TimeAgo carries its own " • " separator and the options
|
||||
// button has slack around its icon, so this pair stays unspaced.
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
TimeAgo(baseNote)
|
||||
TimeAgo(baseNote, style = TimeAgoStyle.DottedTight)
|
||||
|
||||
if (moreOptions == null) {
|
||||
MoreOptionsButton(baseNote, editState, accountViewModel, nav)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.ui.note.elements
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.QuietMark
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
fun BoostedMark() {
|
||||
QuietMark(text = stringRes(id = R.string.boosted))
|
||||
}
|
||||
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.note.elements
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -35,7 +34,6 @@ import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNo
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font12SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||
import com.vitorpamplona.quartz.nip72ModCommunities.communityAddress
|
||||
@@ -66,7 +64,6 @@ private fun DisplayCommunity(
|
||||
|
||||
ClickableTextColor(
|
||||
label,
|
||||
style = LocalTextStyle.current.copy(fontSize = Font12SP),
|
||||
linkColor = MaterialTheme.colorScheme.lessImportantLink,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
|
||||
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.note.elements
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -39,7 +38,6 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font12SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.firstIsTaggedHashes
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
@@ -85,7 +83,6 @@ private fun DisplayTagList(
|
||||
) {
|
||||
ClickableTextColor(
|
||||
"#$firstTag",
|
||||
style = LocalTextStyle.current.copy(fontSize = Font12SP),
|
||||
linkColor = MaterialTheme.colorScheme.lessImportantLink,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
|
||||
@@ -74,10 +74,12 @@ fun DisplayOts(
|
||||
)
|
||||
},
|
||||
whenPending = {
|
||||
// The stamp icon plus an ellipsis: attestation requested, not yet
|
||||
// anchored. The content description carries the words.
|
||||
HeaderPill(
|
||||
symbol = MaterialSymbols.OpenTimestamps,
|
||||
text = stringRes(id = R.string.pending),
|
||||
contentDescription = stringRes(R.string.ots_info_title),
|
||||
text = "…",
|
||||
contentDescription = stringRes(R.string.timestamp_pending_short),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
-8
@@ -29,7 +29,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.commons.model.nip18Reposts.RepostAction.repost
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable
|
||||
import com.vitorpamplona.amethyst.model.FeatureSetType
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
@@ -44,7 +43,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -59,7 +57,6 @@ private val AUTHOR_METADATA_ID = "e1".repeat(32)
|
||||
private val LONG_NAME_METADATA_ID = "e2".repeat(32)
|
||||
|
||||
private val PLAIN_ID = "1".repeat(64)
|
||||
private val REPOST_ID = "2".repeat(64)
|
||||
private val RUMOR_ID = "3".repeat(64)
|
||||
private val EDITED_ID = "4".repeat(64)
|
||||
private val EDIT_VERSION_ID = "5".repeat(64)
|
||||
@@ -108,7 +105,6 @@ fun NoteHeaderFirstRowDensityPreview() {
|
||||
val draftEvent = DraftWrapEvent(DRAFT_ID, AUTHOR, now - 300, arrayOf(arrayOf("d", "preview-draft")), "", "x")
|
||||
|
||||
val plain: Note = LocalCache.getOrCreateNote(PLAIN_ID)
|
||||
val repost: Note = LocalCache.getOrCreateNote(REPOST_ID)
|
||||
val rumorPinned: Note = LocalCache.getOrCreateNote(RUMOR_ID)
|
||||
val edited: Note = LocalCache.getOrCreateNote(EDITED_ID)
|
||||
val editVersion: Note = LocalCache.getOrCreateNote(EDIT_VERSION_ID)
|
||||
@@ -132,7 +128,6 @@ fun NoteHeaderFirstRowDensityPreview() {
|
||||
|
||||
LocalCache.justConsume(plainEvent, null, true)
|
||||
LocalCache.justConsume(TextNoteEvent(EDIT_VERSION_ID, AUTHOR, now - 60, emptyArray(), "GM! (fixed typo)", "x"), null, true)
|
||||
LocalCache.justConsume(RepostEvent(REPOST_ID, AUTHOR, now - 300, arrayOf(arrayOf("e", PLAIN_ID)), plainEvent.toJson(), "x"), null, true)
|
||||
// An empty sig is what marks a note as a private rumor.
|
||||
LocalCache.justConsume(TextNoteEvent(RUMOR_ID, AUTHOR, now - 300, emptyArray(), "just between us", ""), null, true)
|
||||
LocalCache.justConsume(TextNoteEvent(EDITED_ID, AUTHOR, now - 300, emptyArray(), "GM!", "x"), null, true)
|
||||
@@ -197,9 +192,6 @@ fun NoteHeaderFirstRowDensityPreview() {
|
||||
// Bare minimum: username + time + options
|
||||
HeaderRowSample(plain, accountViewModel)
|
||||
|
||||
// One quiet mark: repost
|
||||
HeaderRowSample(repost, accountViewModel)
|
||||
|
||||
// Quiet icon marks: private rumor + pinned
|
||||
HeaderRowSample(rumorPinned, accountViewModel, isPinned = true)
|
||||
|
||||
|
||||
@@ -53,6 +53,12 @@ enum class TimeAgoStyle {
|
||||
/** "• 5m", uses [timeAgo]. Used by note timestamps and chatroom row last-message time. */
|
||||
Dotted,
|
||||
|
||||
/**
|
||||
* "• 5m" without the leading space — for rows whose `Arrangement.spacedBy`
|
||||
* already provides the gap before the timestamp (the note-header first row).
|
||||
*/
|
||||
DottedTight,
|
||||
|
||||
/** "5m" (no dot, no leading space), uses [timeAgoShort]. Used by chat bubbles and channel headers. */
|
||||
Short,
|
||||
}
|
||||
@@ -96,6 +102,7 @@ fun ToggleableTimeAgoText(
|
||||
if (showAbsolute) {
|
||||
when (style) {
|
||||
TimeAgoStyle.Dotted -> timeAbsolute(timestamp, context)
|
||||
TimeAgoStyle.DottedTight -> timeAbsolute(timestamp, context).trimStart()
|
||||
TimeAgoStyle.Short -> timeAbsoluteNoDot(timestamp, context)
|
||||
}
|
||||
} else {
|
||||
@@ -104,6 +111,7 @@ fun ToggleableTimeAgoText(
|
||||
nowState.value
|
||||
when (style) {
|
||||
TimeAgoStyle.Dotted -> timeAgo(timestamp, context)
|
||||
TimeAgoStyle.DottedTight -> timeAgo(timestamp, context).trimStart()
|
||||
TimeAgoStyle.Short -> timeAgoShort(timestamp, nowStr)
|
||||
}
|
||||
}
|
||||
@@ -125,16 +133,22 @@ fun ToggleableTimeAgoText(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimeAgo(note: Note) {
|
||||
fun TimeAgo(
|
||||
note: Note,
|
||||
style: TimeAgoStyle = TimeAgoStyle.Dotted,
|
||||
) {
|
||||
val time = note.createdAt() ?: return
|
||||
TimeAgo(time)
|
||||
TimeAgo(time, style)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimeAgo(time: Long) {
|
||||
fun TimeAgo(
|
||||
time: Long,
|
||||
style: TimeAgoStyle = TimeAgoStyle.Dotted,
|
||||
) {
|
||||
ToggleableTimeAgoText(
|
||||
timestamp = time,
|
||||
style = TimeAgoStyle.Dotted,
|
||||
style = style,
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -127,6 +127,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.Reward
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgoStyle
|
||||
import com.vitorpamplona.amethyst.ui.note.observeEdits
|
||||
import com.vitorpamplona.amethyst.ui.note.showAmount
|
||||
import com.vitorpamplona.amethyst.ui.note.types.AudioHeader
|
||||
@@ -744,7 +745,7 @@ private fun FullBleedNoteCompose(
|
||||
// The dotted TimeAgo carries its own " • " separator and the
|
||||
// options button has slack around its icon: keep the pair unspaced.
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
TimeAgo(note = baseNote)
|
||||
TimeAgo(note = baseNote, style = TimeAgoStyle.DottedTight)
|
||||
|
||||
MoreOptionsButton(baseNote, editState, accountViewModel, nav)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
<string name="timestamp_it">Timestamp it</string>
|
||||
<string name="timestamp_pending">Timestamp: Pending Confirmations</string>
|
||||
<string name="timestamp_pending_short">OTS: Pending</string>
|
||||
<string name="pending">Pending</string>
|
||||
<string name="request_deletion">Request Deletion</string>
|
||||
<string name="block_report">Block / Report</string>
|
||||
<string name="block_hide_user"><![CDATA[Block & Hide User]]></string>
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.commons.ui.elements
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun BoostedMark() {
|
||||
Text(
|
||||
"Boosted",
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
maxLines = 1,
|
||||
modifier = Modifier.padding(start = 5.dp),
|
||||
)
|
||||
}
|
||||
+5
-10
@@ -31,18 +31,15 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
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.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
|
||||
private val QuietMarkFontSize = 12.sp
|
||||
|
||||
/**
|
||||
* Quiet passive-state marker for note headers: Boosted, Draft, Edited, pinned,
|
||||
* Quiet passive-state marker for note headers: Draft, Edited, pinned,
|
||||
* private rumor, ... One spec for all of them so the header reads as a single
|
||||
* system: 12sp medium gray text with an optional 12dp icon. Contrast with
|
||||
* [HeaderPill], which is the loud tier for tappable/verifiable metadata.
|
||||
* system: bold gray text at the row's text size with an optional 16dp icon.
|
||||
* Contrast with [HeaderPill], the chip tier for tappable/verifiable metadata.
|
||||
*
|
||||
* Spacing between markers is owned by the parent row (`Arrangement.spacedBy`),
|
||||
* not baked in here.
|
||||
@@ -65,16 +62,14 @@ fun QuietMark(
|
||||
symbol = symbol,
|
||||
contentDescription = contentDescription,
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
modifier = Modifier.size(12.dp),
|
||||
modifier = Modifier.size(16.dp),
|
||||
)
|
||||
}
|
||||
if (text != null) {
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
fontSize = QuietMarkFontSize,
|
||||
lineHeight = QuietMarkFontSize,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,6 @@ import com.vitorpamplona.amethyst.commons.search.QuerySerializer
|
||||
import com.vitorpamplona.amethyst.commons.search.SearchResultFilter
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.LoadingState
|
||||
import com.vitorpamplona.amethyst.commons.ui.elements.BoostedMark
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedState
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.NewPostsChip
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
@@ -304,7 +303,6 @@ private fun FeedNoteCardBody(
|
||||
)
|
||||
},
|
||||
)
|
||||
BoostedMark()
|
||||
}
|
||||
|
||||
// Original note content with actions inside card
|
||||
|
||||
Reference in New Issue
Block a user