Minor performance improvements throughout the code
This commit is contained in:
@@ -490,9 +490,9 @@ class NoteLiveData(val note: Note) : LiveData<NoteState>(NoteState(note)) {
|
||||
|
||||
fun invalidateData() {
|
||||
bundler.invalidate() {
|
||||
// if (hasObservers()) {
|
||||
postValue(NoteState(note))
|
||||
// }
|
||||
if (hasActiveObservers()) {
|
||||
postValue(NoteState(note))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,8 +144,10 @@ class User(val pubkeyHex: String) {
|
||||
}
|
||||
|
||||
fun updateAcceptedBadges(note: AddressableNote) {
|
||||
acceptedBadges = note
|
||||
liveSet?.badges?.invalidateData()
|
||||
if (acceptedBadges?.idHex != note.idHex) {
|
||||
acceptedBadges = note
|
||||
liveSet?.badges?.invalidateData()
|
||||
}
|
||||
}
|
||||
|
||||
fun addZap(zapRequest: Note, zap: Note?) {
|
||||
|
||||
@@ -17,8 +17,8 @@ class RepostEvent(
|
||||
sig: HexKey
|
||||
) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
|
||||
|
||||
fun boostedPost() = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) }
|
||||
fun originalAuthor() = tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) }
|
||||
fun boostedPost() = taggedEvents()
|
||||
fun originalAuthor() = taggedUsers()
|
||||
|
||||
fun containedPost() = try {
|
||||
fromJson(content, Client.lenient)
|
||||
|
||||
@@ -73,6 +73,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.UserLine
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -621,7 +622,7 @@ private fun ForwardZapTo(
|
||||
Text(
|
||||
text = stringResource(R.string.zap_forward_lnAddress),
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
fontSize = 14.sp
|
||||
fontSize = Font14SP
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
||||
import com.vitorpamplona.amethyst.service.relays.FeedType
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -167,7 +168,7 @@ fun ServerConfigHeader() {
|
||||
Text(
|
||||
text = stringResource(R.string.bytes),
|
||||
maxLines = 1,
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
modifier = Modifier.weight(1.2f),
|
||||
color = MaterialTheme.colors.placeholderText
|
||||
)
|
||||
@@ -177,7 +178,7 @@ fun ServerConfigHeader() {
|
||||
Text(
|
||||
text = stringResource(id = R.string.bytes),
|
||||
maxLines = 1,
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
modifier = Modifier.weight(1.2f),
|
||||
color = MaterialTheme.colors.placeholderText
|
||||
)
|
||||
@@ -187,7 +188,7 @@ fun ServerConfigHeader() {
|
||||
Text(
|
||||
text = stringResource(R.string.errors),
|
||||
maxLines = 1,
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
modifier = Modifier.weight(1f),
|
||||
color = MaterialTheme.colors.placeholderText
|
||||
)
|
||||
@@ -197,7 +198,7 @@ fun ServerConfigHeader() {
|
||||
Text(
|
||||
text = stringResource(R.string.spam),
|
||||
maxLines = 1,
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
modifier = Modifier.weight(1f),
|
||||
color = MaterialTheme.colors.placeholderText
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.vitorpamplona.amethyst.ui.components
|
||||
import android.util.Log
|
||||
import android.util.LruCache
|
||||
import android.util.Patterns
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
@@ -19,16 +18,13 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.halilibo.richtext.markdown.Markdown
|
||||
import com.halilibo.richtext.markdown.MarkdownParseOptions
|
||||
@@ -47,7 +43,9 @@ import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.ui.actions.toImmutableListOfLists
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.MarkdownTextStyle
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.markdownStyle
|
||||
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||
import com.vitorpamplona.amethyst.ui.uriToRoute
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -439,42 +437,6 @@ fun RenderCustomEmoji(word: String, state: RichTextViewerState) {
|
||||
|
||||
@Composable
|
||||
private fun RenderContentAsMarkdown(content: String, backgroundColor: MutableState<Color>, tags: ImmutableListOfLists<String>?, nav: (String) -> Unit) {
|
||||
val myMarkDownStyle = richTextDefaults.copy(
|
||||
paragraphSpacing = DefaultParagraphSpacing,
|
||||
headingStyle = DefaultHeadingStyle,
|
||||
codeBlockStyle = richTextDefaults.codeBlockStyle?.copy(
|
||||
textStyle = TextStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = 14.sp
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(0.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
1.dp,
|
||||
MaterialTheme.colors.subtleBorder,
|
||||
QuoteBorder
|
||||
)
|
||||
.background(
|
||||
MaterialTheme.colors.onSurface
|
||||
.copy(alpha = 0.05f)
|
||||
.compositeOver(backgroundColor.value)
|
||||
)
|
||||
),
|
||||
stringStyle = richTextDefaults.stringStyle?.copy(
|
||||
linkStyle = SpanStyle(
|
||||
color = MaterialTheme.colors.primary
|
||||
),
|
||||
codeStyle = SpanStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = 14.sp,
|
||||
background = MaterialTheme.colors.onSurface.copy(alpha = 0.22f)
|
||||
.compositeOver(backgroundColor.value)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val uri = LocalUriHandler.current
|
||||
val onClick = { link: String ->
|
||||
val route = uriToRoute(link)
|
||||
@@ -486,9 +448,9 @@ private fun RenderContentAsMarkdown(content: String, backgroundColor: MutableSta
|
||||
Unit
|
||||
}
|
||||
|
||||
ProvideTextStyle(TextStyle(lineHeight = 1.30.em)) {
|
||||
ProvideTextStyle(MarkdownTextStyle) {
|
||||
MaterialRichText(
|
||||
style = myMarkDownStyle
|
||||
style = MaterialTheme.colors.markdownStyle
|
||||
) {
|
||||
RefreshableContent(content, tags) {
|
||||
Markdown(
|
||||
|
||||
@@ -29,8 +29,8 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
@@ -120,7 +120,7 @@ fun SpinnerSelectionDialog(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Text(text = it, color = Color.Gray, fontSize = 14.sp)
|
||||
Text(text = it, color = Color.Gray, fontSize = Font14SP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ import com.vitorpamplona.amethyst.service.model.BaseTextNoteEvent
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
||||
import com.vitorpamplona.amethyst.service.model.EventInterface
|
||||
import com.vitorpamplona.amethyst.service.model.FileHeaderEvent
|
||||
import com.vitorpamplona.amethyst.service.model.FileStorageHeaderEvent
|
||||
import com.vitorpamplona.amethyst.service.model.GenericRepostEvent
|
||||
@@ -142,14 +141,28 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChannelHeader
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ReportNoteDialog
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.DiviserThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.Following
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.HalfVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size25dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size30Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size30dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdStartPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.WidthAuthorPictureModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.theme.replyBackground
|
||||
import com.vitorpamplona.amethyst.ui.theme.repostProfileBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
@@ -181,9 +194,13 @@ fun NoteCompose(
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val noteState by baseNote.live().metadata.observeAsState()
|
||||
val noteEvent = remember(noteState) { noteState?.note?.event }
|
||||
val missingEvent by remember(noteState) {
|
||||
derivedStateOf {
|
||||
noteState?.note?.event == null
|
||||
}
|
||||
}
|
||||
|
||||
if (noteEvent == null) {
|
||||
if (missingEvent) {
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||
BlankNote(
|
||||
remember {
|
||||
@@ -337,12 +354,12 @@ fun WatchForReports(
|
||||
accountViewModel: AccountViewModel,
|
||||
onChange: (Boolean, Boolean, Set<Note>) -> Unit
|
||||
) {
|
||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||
val userFollowsState by accountViewModel.userFollows.observeAsState()
|
||||
val noteReportsState by note.live().reports.observeAsState()
|
||||
|
||||
LaunchedEffect(key1 = noteReportsState, key2 = accountState) {
|
||||
LaunchedEffect(key1 = noteReportsState, key2 = userFollowsState) {
|
||||
launch(Dispatchers.Default) {
|
||||
accountState?.account?.let { loggedIn ->
|
||||
accountViewModel.account.let { loggedIn ->
|
||||
val newCanPreview = note.author?.pubkeyHex == loggedIn.userProfile().pubkeyHex ||
|
||||
(note.author?.let { loggedIn.userProfile().isFollowingCached(it) } ?: true) ||
|
||||
noteReportsState?.note?.hasAnyReports() != true
|
||||
@@ -376,10 +393,22 @@ fun NormalNote(
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val noteEvent = remember { baseNote.event }
|
||||
val channelHex = remember { baseNote.channelHex() }
|
||||
|
||||
if ((noteEvent is ChannelCreateEvent || noteEvent is ChannelMetadataEvent) && channelHex != null) {
|
||||
ChannelHeader(channelHex = channelHex, showVideo = !makeItShort, showBottomDiviser = true, accountViewModel = accountViewModel, nav = nav)
|
||||
val isChannelHeader by remember {
|
||||
derivedStateOf {
|
||||
(baseNote.event is ChannelCreateEvent || baseNote.event is ChannelMetadataEvent) && baseNote.channelHex() != null
|
||||
}
|
||||
}
|
||||
|
||||
if (isChannelHeader) {
|
||||
ChannelHeader(
|
||||
channelNote = baseNote,
|
||||
showVideo = !makeItShort,
|
||||
showBottomDiviser = true,
|
||||
accountViewModel =
|
||||
accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
} else if (noteEvent is BadgeDefinitionEvent) {
|
||||
BadgeDisplay(baseNote = baseNote)
|
||||
} else if (noteEvent is FileHeaderEvent) {
|
||||
@@ -387,20 +416,23 @@ fun NormalNote(
|
||||
} else if (noteEvent is FileStorageHeaderEvent) {
|
||||
FileStorageHeaderDisplay(baseNote)
|
||||
} else {
|
||||
CheckNewAndRenderNote(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
isBoostedNote,
|
||||
isQuotedNote,
|
||||
unPackReply,
|
||||
makeItShort,
|
||||
addMarginTop,
|
||||
canPreview,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav
|
||||
)
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||
CheckNewAndRenderNote(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
isBoostedNote,
|
||||
isQuotedNote,
|
||||
unPackReply,
|
||||
makeItShort,
|
||||
addMarginTop,
|
||||
canPreview,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
showPopup,
|
||||
nav
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,6 +449,7 @@ private fun CheckNewAndRenderNote(
|
||||
canPreview: Boolean = true,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
showPopup: () -> Unit,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val newItemColor = MaterialTheme.colors.newItemBackgroundColor
|
||||
@@ -464,22 +497,20 @@ private fun CheckNewAndRenderNote(
|
||||
}
|
||||
}
|
||||
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||
RenderNoteWithReactions(
|
||||
modifier = updatedModifier,
|
||||
backgroundColor = backgroundColor,
|
||||
baseNote = baseNote,
|
||||
isBoostedNote = isBoostedNote,
|
||||
isQuotedNote = isQuotedNote,
|
||||
addMarginTop = addMarginTop,
|
||||
unPackReply = unPackReply,
|
||||
makeItShort = makeItShort,
|
||||
canPreview = canPreview,
|
||||
accountViewModel = accountViewModel,
|
||||
showPopup = showPopup,
|
||||
nav = nav
|
||||
)
|
||||
}
|
||||
RenderNoteWithReactions(
|
||||
modifier = updatedModifier,
|
||||
backgroundColor = backgroundColor,
|
||||
baseNote = baseNote,
|
||||
isBoostedNote = isBoostedNote,
|
||||
isQuotedNote = isQuotedNote,
|
||||
addMarginTop = addMarginTop,
|
||||
unPackReply = unPackReply,
|
||||
makeItShort = makeItShort,
|
||||
canPreview = canPreview,
|
||||
accountViewModel = accountViewModel,
|
||||
showPopup = showPopup,
|
||||
nav = nav
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -539,8 +570,8 @@ private fun RenderNoteWithReactions(
|
||||
}
|
||||
) {
|
||||
if (notBoostedNorQuote) {
|
||||
DrawAuthorImages(baseNote, accountViewModel, nav)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
AuthorAndRelayInformation(baseNote, accountViewModel, nav)
|
||||
Spacer(modifier = DoubleHorzSpacer)
|
||||
}
|
||||
|
||||
NoteBody(
|
||||
@@ -556,22 +587,25 @@ private fun RenderNoteWithReactions(
|
||||
)
|
||||
}
|
||||
|
||||
if (!makeItShort && baseNote.event !is RepostEvent && baseNote.event !is GenericRepostEvent) {
|
||||
ReactionsRow(
|
||||
baseNote = baseNote,
|
||||
showReactionDetail = notBoostedNorQuote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
} else {
|
||||
if (!isBoostedNote && baseNote.event !is RepostEvent && baseNote.event !is GenericRepostEvent) {
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
val isRepost = remember { baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent }
|
||||
if (!isRepost) {
|
||||
if (!makeItShort) {
|
||||
ReactionsRow(
|
||||
baseNote = baseNote,
|
||||
showReactionDetail = notBoostedNorQuote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
} else {
|
||||
if (!isBoostedNote) {
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isQuotedNote && !isBoostedNote) {
|
||||
Divider(
|
||||
thickness = 0.25.dp
|
||||
thickness = DiviserThickness
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -605,7 +639,7 @@ private fun NoteBody(
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Spacer(modifier = HalfVertSpacer)
|
||||
|
||||
if (!makeItShort) {
|
||||
ReplyRow(
|
||||
@@ -1766,38 +1800,40 @@ private fun FirstUserInfoRow(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val eventNote = remember { baseNote.event } ?: return
|
||||
val time = remember { baseNote.createdAt() } ?: return
|
||||
val padding = remember {
|
||||
Modifier.padding(horizontal = 5.dp)
|
||||
}
|
||||
val isRepost = remember { baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent }
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
if (showAuthorPicture) {
|
||||
NoteAuthorPicture(baseNote, nav, accountViewModel, remember { 25.dp })
|
||||
Spacer(padding)
|
||||
NoteAuthorPicture(baseNote, nav, accountViewModel, Size25dp)
|
||||
Spacer(HalfPadding)
|
||||
NoteUsernameDisplay(baseNote, remember { Modifier.weight(1f) })
|
||||
} else {
|
||||
NoteUsernameDisplay(baseNote, remember { Modifier.weight(1f) })
|
||||
}
|
||||
|
||||
if (eventNote is RepostEvent || eventNote is GenericRepostEvent) {
|
||||
Text(
|
||||
" ${stringResource(id = R.string.boosted)}",
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
maxLines = 1
|
||||
)
|
||||
if (isRepost) {
|
||||
BoostedMark()
|
||||
} else {
|
||||
DisplayFollowingHashtagsInPost(eventNote, accountViewModel, nav)
|
||||
DisplayFollowingHashtagsInPost(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
TimeAgo(time)
|
||||
TimeAgo(baseNote)
|
||||
|
||||
MoreOptionsButton(baseNote, accountViewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoostedMark() {
|
||||
Text(
|
||||
stringResource(id = R.string.boosted),
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
maxLines = 1,
|
||||
modifier = StdStartPadding
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MoreOptionsButton(
|
||||
baseNote: Note,
|
||||
@@ -1825,19 +1861,16 @@ private fun MoreOptionsButton(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimeAgo(note: Note) {
|
||||
val time = remember { note.createdAt() } ?: return
|
||||
TimeAgo(time)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimeAgo(time: Long) {
|
||||
val context = LocalContext.current
|
||||
var timeStr by remember { mutableStateOf("") }
|
||||
|
||||
LaunchedEffect(key1 = time) {
|
||||
launch(Dispatchers.IO) {
|
||||
val newTimeStr = timeAgo(time, context = context)
|
||||
if (newTimeStr != timeStr) {
|
||||
timeStr = newTimeStr
|
||||
}
|
||||
}
|
||||
}
|
||||
val timeStr by remember { mutableStateOf(timeAgo(time, context = context)) }
|
||||
|
||||
Text(
|
||||
text = timeStr,
|
||||
@@ -1847,35 +1880,60 @@ fun TimeAgo(time: Long) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DrawAuthorImages(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||
val baseChannelHex = remember { baseNote.channelHex() }
|
||||
val modifier = remember { Modifier.width(55.dp) }
|
||||
|
||||
Column(modifier) {
|
||||
private fun AuthorAndRelayInformation(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||
Column(WidthAuthorPictureModifier) {
|
||||
// Draws the boosted picture outside the boosted card.
|
||||
Box(modifier = modifier, contentAlignment = Alignment.BottomEnd) {
|
||||
NoteAuthorPicture(baseNote, nav, accountViewModel, 55.dp)
|
||||
|
||||
if (baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent) {
|
||||
RepostNoteAuthorPicture(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
if (baseNote.event is ChannelMessageEvent && baseChannelHex != null) {
|
||||
LoadChannel(baseChannelHex) { channel ->
|
||||
ChannelNotePicture(channel)
|
||||
}
|
||||
}
|
||||
Box(modifier = Size55Modifier, contentAlignment = Alignment.BottomEnd) {
|
||||
RenderAuthorImages(baseNote, nav, accountViewModel)
|
||||
}
|
||||
|
||||
if (baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent) {
|
||||
val baseReply = remember {
|
||||
BadgeBox(baseNote, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BadgeBox(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val isRepost = remember { baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent }
|
||||
|
||||
if (isRepost) {
|
||||
val baseReply by remember {
|
||||
derivedStateOf {
|
||||
baseNote.replyTo?.lastOrNull()
|
||||
}
|
||||
baseReply?.let {
|
||||
RelayBadges(it, accountViewModel, nav)
|
||||
}
|
||||
baseReply?.let {
|
||||
RelayBadges(it, accountViewModel, nav)
|
||||
}
|
||||
} else {
|
||||
RelayBadges(baseNote, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderAuthorImages(
|
||||
baseNote: Note,
|
||||
nav: (String) -> Unit,
|
||||
accountViewModel: AccountViewModel
|
||||
) {
|
||||
val isRepost = remember { baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent }
|
||||
val isChannel = remember { baseNote.event is ChannelMessageEvent && baseNote.channelHex() != null }
|
||||
|
||||
NoteAuthorPicture(baseNote, nav, accountViewModel, Size55dp)
|
||||
|
||||
if (isRepost) {
|
||||
RepostNoteAuthorPicture(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
if (isChannel) {
|
||||
val baseChannelHex = remember { baseNote.channelHex() }
|
||||
if (baseChannelHex != null) {
|
||||
LoadChannel(baseChannelHex) { channel ->
|
||||
ChannelNotePicture(channel)
|
||||
}
|
||||
} else {
|
||||
RelayBadges(baseNote, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1945,24 +2003,20 @@ private fun RepostNoteAuthorPicture(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val baseRepost = remember { baseNote.replyTo?.lastOrNull() }
|
||||
|
||||
val modifier = remember {
|
||||
Modifier.size(30.dp)
|
||||
val baseRepost by remember {
|
||||
derivedStateOf {
|
||||
baseNote.replyTo?.lastOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
baseRepost?.let {
|
||||
Box(modifier) {
|
||||
Box(Size30Modifier) {
|
||||
NoteAuthorPicture(
|
||||
baseNote = it,
|
||||
nav = nav,
|
||||
accountViewModel = accountViewModel,
|
||||
size = remember { 30.dp },
|
||||
pictureModifier = Modifier.border(
|
||||
2.dp,
|
||||
MaterialTheme.colors.background,
|
||||
CircleShape
|
||||
)
|
||||
size = Size30dp,
|
||||
pictureModifier = MaterialTheme.colors.repostProfileBorder
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2073,10 +2127,12 @@ private fun LoadAndDisplayUser(
|
||||
|
||||
@Composable
|
||||
fun DisplayFollowingHashtagsInPost(
|
||||
noteEvent: EventInterface,
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val noteEvent = remember { baseNote.event } ?: return
|
||||
|
||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||
var firstTag by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
@@ -2148,12 +2204,14 @@ fun DisplayUncitedHashtags(
|
||||
fun DisplayPoW(
|
||||
pow: Int
|
||||
) {
|
||||
val powStr = remember(pow) {
|
||||
"PoW-$pow"
|
||||
}
|
||||
|
||||
Text(
|
||||
"PoW-$pow",
|
||||
color = MaterialTheme.colors.primary.copy(
|
||||
alpha = 0.52f
|
||||
),
|
||||
fontSize = 14.sp,
|
||||
powStr,
|
||||
color = MaterialTheme.colors.lessImportantLink,
|
||||
fontSize = Font14SP,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1
|
||||
)
|
||||
@@ -2673,19 +2731,23 @@ private fun CreateImageHeader(
|
||||
painter = painterResource(R.drawable.profile_banner),
|
||||
contentDescription = stringResource(R.string.profile_banner),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(150.dp)
|
||||
modifier = remember {
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(150.dp)
|
||||
}
|
||||
)
|
||||
|
||||
Box(
|
||||
Modifier
|
||||
.width(75.dp)
|
||||
.height(75.dp)
|
||||
.padding(10.dp)
|
||||
.align(Alignment.BottomStart)
|
||||
remember {
|
||||
Modifier
|
||||
.width(75.dp)
|
||||
.height(75.dp)
|
||||
.padding(10.dp)
|
||||
.align(Alignment.BottomStart)
|
||||
}
|
||||
) {
|
||||
NoteAuthorPicture(baseNote = note, accountViewModel = accountViewModel, size = 55.dp)
|
||||
NoteAuthorPicture(baseNote = note, accountViewModel = accountViewModel, size = Size55dp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Popup
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@@ -32,6 +31,7 @@ import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -428,9 +428,12 @@ fun ZapVote(
|
||||
|
||||
// only show tallies after a user has zapped note
|
||||
if (!pollViewModel.canZap()) {
|
||||
val amountStr = remember(poolOption.zappedValue) {
|
||||
showAmount(poolOption.zappedValue)
|
||||
}
|
||||
Text(
|
||||
showAmount(poolOption.zappedValue),
|
||||
fontSize = 14.sp,
|
||||
text = amountStr,
|
||||
fontSize = Font14SP,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
@@ -45,12 +45,12 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.Center
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
@@ -59,21 +59,34 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Popup
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.CachePolicy
|
||||
import coil.request.ImageRequest
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
||||
import com.vitorpamplona.amethyst.ui.screen.CombinedZap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.DarkerGreen
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.HalfDoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.NoSoTinyBorders
|
||||
import com.vitorpamplona.amethyst.ui.theme.ReactionRowExpandButton
|
||||
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeight
|
||||
import com.vitorpamplona.amethyst.ui.theme.ReactionRowZapraiserSize
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size18dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size19dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size24dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.TinyBorders
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.theme.subtleButton
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -84,67 +97,118 @@ import java.math.RoundingMode
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Composable
|
||||
fun ReactionsRow(baseNote: Note, showReactionDetail: Boolean, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||
val grayTint = MaterialTheme.colors.placeholderText
|
||||
|
||||
fun ReactionsRow(
|
||||
baseNote: Note,
|
||||
showReactionDetail: Boolean,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val wantsToSeeReactions = remember {
|
||||
mutableStateOf<Boolean>(false)
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
val zapraiserAmount = remember {
|
||||
baseNote.event?.zapraiserAmount()
|
||||
}
|
||||
Spacer(modifier = HalfDoubleVertSpacer)
|
||||
|
||||
Spacer(modifier = Modifier.height(7.dp))
|
||||
InnerReactionRow(baseNote, showReactionDetail, wantsToSeeReactions, accountViewModel, nav)
|
||||
|
||||
Row(verticalAlignment = CenterVertically, modifier = Modifier.padding(start = 10.dp)) {
|
||||
if (showReactionDetail) {
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = Modifier
|
||||
.width(65.dp)
|
||||
.padding(start = 31.dp),
|
||||
horizontalArrangement = Arrangement.Start
|
||||
) {
|
||||
ExpandButton(baseNote, wantsToSeeReactions)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
||||
ReplyReactionWithDialog(accountViewModel, nav, baseNote, grayTint)
|
||||
}
|
||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
||||
BoostWithDialog(accountViewModel, nav, baseNote, grayTint)
|
||||
}
|
||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
||||
LikeReaction(baseNote, grayTint, accountViewModel)
|
||||
}
|
||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
||||
ZapReaction(baseNote, grayTint, accountViewModel)
|
||||
}
|
||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
||||
ViewCountReaction(baseNote.idHex, grayTint)
|
||||
}
|
||||
}
|
||||
|
||||
if (zapraiserAmount != null && zapraiserAmount > 0) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = if (showReactionDetail) 75.dp else 0.dp),
|
||||
horizontalArrangement = Arrangement.Start
|
||||
) {
|
||||
RenderZapRaiser(baseNote, zapraiserAmount, wantsToSeeReactions.value, accountViewModel)
|
||||
}
|
||||
}
|
||||
LoadAndDisplayZapraiser(baseNote, showReactionDetail, wantsToSeeReactions, accountViewModel)
|
||||
|
||||
if (showReactionDetail && wantsToSeeReactions.value) {
|
||||
ReactionDetailGallery(baseNote, nav, accountViewModel)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(7.dp))
|
||||
Spacer(modifier = HalfDoubleVertSpacer)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InnerReactionRow(
|
||||
baseNote: Note,
|
||||
showReactionDetail: Boolean,
|
||||
wantsToSeeReactions: MutableState<Boolean>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically, modifier = ReactionRowHeight) {
|
||||
if (showReactionDetail) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = ReactionRowExpandButton
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
ExpandButton(baseNote, wantsToSeeReactions)
|
||||
}
|
||||
}
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = remember { Modifier.weight(1f) }
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
ReplyReactionWithDialog(baseNote, MaterialTheme.colors.placeholderText, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = remember { Modifier.weight(1f) }
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
BoostWithDialog(baseNote, MaterialTheme.colors.placeholderText, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = remember { Modifier.weight(1f) }
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
LikeReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = remember { Modifier.weight(1f) }
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = remember { Modifier.weight(1f) }
|
||||
) {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
ViewCountReaction(baseNote.idHex, MaterialTheme.colors.placeholderText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadAndDisplayZapraiser(
|
||||
baseNote: Note,
|
||||
showReactionDetail: Boolean,
|
||||
wantsToSeeReactions: MutableState<Boolean>,
|
||||
accountViewModel: AccountViewModel
|
||||
) {
|
||||
val zapraiserAmount by remember {
|
||||
derivedStateOf {
|
||||
baseNote.event?.zapraiserAmount() ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
if (zapraiserAmount > 0) {
|
||||
Spacer(modifier = remember { Modifier.height(4.dp) })
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = remember {
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = if (showReactionDetail) 75.dp else 0.dp)
|
||||
},
|
||||
horizontalArrangement = Arrangement.Start
|
||||
) {
|
||||
RenderZapRaiser(baseNote, zapraiserAmount, wantsToSeeReactions.value, accountViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -165,11 +229,17 @@ fun RenderZapRaiser(baseNote: Note, zapraiserAmount: Long, details: Boolean, acc
|
||||
}
|
||||
|
||||
if (Math.abs(zapraiserProgress - percentage) > 0.001) {
|
||||
zapraiserProgress = percentage
|
||||
if (percentage > 0.99) {
|
||||
zapraiserLeft = "0"
|
||||
val newZapraiserProgress = percentage
|
||||
val newZapraiserLeft = if (percentage > 0.99) {
|
||||
"0"
|
||||
} else {
|
||||
zapraiserLeft = showAmount((zapraiserAmount * (1 - percentage)).toBigDecimal())
|
||||
showAmount((zapraiserAmount * (1 - percentage)).toBigDecimal())
|
||||
}
|
||||
if (zapraiserLeft != newZapraiserLeft) {
|
||||
zapraiserLeft = newZapraiserLeft
|
||||
}
|
||||
if (zapraiserProgress != newZapraiserProgress) {
|
||||
zapraiserProgress = newZapraiserProgress
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,34 +247,34 @@ fun RenderZapRaiser(baseNote: Note, zapraiserAmount: Long, details: Boolean, acc
|
||||
}
|
||||
|
||||
val color = if (zapraiserProgress > 0.99) {
|
||||
Color.Green.copy(alpha = 0.32f)
|
||||
DarkerGreen
|
||||
} else {
|
||||
MaterialTheme.colors.mediumImportanceLink
|
||||
}
|
||||
|
||||
Box(
|
||||
Modifier.padding(end = 10.dp).fillMaxWidth()
|
||||
) {
|
||||
Box(ReactionRowZapraiserSize) {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
modifier = ReactionRowZapraiserSize,
|
||||
color = color,
|
||||
progress = zapraiserProgress
|
||||
)
|
||||
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = Modifier.padding(2.dp)
|
||||
) {
|
||||
if (details) {
|
||||
val totalPercentage = remember(zapraiserProgress) {
|
||||
"${(zapraiserProgress * 100).roundToInt()}%"
|
||||
if (details) {
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = TinyBorders
|
||||
) {
|
||||
val totalPercentage by remember(zapraiserProgress) {
|
||||
derivedStateOf {
|
||||
"${(zapraiserProgress * 100).roundToInt()}%"
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(id = R.string.sats_to_complete, totalPercentage, zapraiserLeft),
|
||||
modifier = Modifier.padding(start = 5.dp, end = 5.dp, top = 2.dp, bottom = 2.dp),
|
||||
modifier = NoSoTinyBorders,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
fontSize = 14.sp
|
||||
fontSize = Font14SP
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -226,27 +296,32 @@ private fun ExpandButton(baseNote: Note, wantsToSeeReactions: MutableState<Boole
|
||||
}
|
||||
|
||||
if (hasReactions) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
wantsToSeeReactions.value = !wantsToSeeReactions.value
|
||||
},
|
||||
modifier = Modifier.size(20.dp)
|
||||
) {
|
||||
if (wantsToSeeReactions.value) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandLess,
|
||||
null,
|
||||
modifier = Modifier.size(22.dp),
|
||||
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.22f)
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
null,
|
||||
modifier = Modifier.size(22.dp),
|
||||
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.22f)
|
||||
)
|
||||
}
|
||||
RenderShowIndividualReactionsButton(wantsToSeeReactions)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderShowIndividualReactionsButton(wantsToSeeReactions: MutableState<Boolean>) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
wantsToSeeReactions.value = !wantsToSeeReactions.value
|
||||
},
|
||||
modifier = Size20Modifier
|
||||
) {
|
||||
if (wantsToSeeReactions.value) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandLess,
|
||||
null,
|
||||
modifier = Size22Modifier,
|
||||
tint = MaterialTheme.colors.subtleButton
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
null,
|
||||
modifier = Size22Modifier,
|
||||
tint = MaterialTheme.colors.subtleButton
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,10 +395,10 @@ private fun ReactionDetailGallery(
|
||||
|
||||
@Composable
|
||||
private fun BoostWithDialog(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
baseNote: Note,
|
||||
grayTint: Color
|
||||
grayTint: Color,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
var wantsToQuote by remember {
|
||||
mutableStateOf<Note?>(null)
|
||||
@@ -340,10 +415,10 @@ private fun BoostWithDialog(
|
||||
|
||||
@Composable
|
||||
private fun ReplyReactionWithDialog(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
baseNote: Note,
|
||||
grayTint: Color
|
||||
grayTint: Color,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
var wantsToReplyTo by remember {
|
||||
mutableStateOf<Note?>(null)
|
||||
@@ -364,7 +439,7 @@ fun ReplyReaction(
|
||||
grayTint: Color,
|
||||
accountViewModel: AccountViewModel,
|
||||
showCounter: Boolean = true,
|
||||
iconSize: Dp = 18.dp,
|
||||
iconSize: Dp = Size18dp,
|
||||
onPress: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@@ -418,7 +493,7 @@ fun ReplyCounter(baseNote: Note, textColor: Color) {
|
||||
|
||||
Text(
|
||||
text = replyCount,
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
color = textColor
|
||||
)
|
||||
}
|
||||
@@ -462,33 +537,33 @@ fun BoostReaction(
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (wantsToBoost) {
|
||||
BoostTypeChoicePopup(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
onDismiss = {
|
||||
wantsToBoost = false
|
||||
},
|
||||
onQuote = {
|
||||
wantsToBoost = false
|
||||
onQuotePress()
|
||||
}
|
||||
)
|
||||
}
|
||||
BoostIcon(baseNote, iconSize, grayTint, accountViewModel)
|
||||
}
|
||||
|
||||
BoostIcon(baseNote, iconSize, grayTint, accountViewModel.userProfile())
|
||||
if (wantsToBoost) {
|
||||
BoostTypeChoicePopup(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
onDismiss = {
|
||||
wantsToBoost = false
|
||||
},
|
||||
onQuote = {
|
||||
wantsToBoost = false
|
||||
onQuotePress()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
BoostText(baseNote, grayTint)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BoostIcon(baseNote: Note, iconSize: Dp = 20.dp, grayTint: Color, loggedIn: User) {
|
||||
fun BoostIcon(baseNote: Note, iconSize: Dp = Size20dp, grayTint: Color, accountViewModel: AccountViewModel) {
|
||||
val boostsState by baseNote.live().boosts.observeAsState()
|
||||
|
||||
val iconTint by remember(boostsState) {
|
||||
derivedStateOf {
|
||||
if (boostsState?.note?.isBoostedBy(loggedIn) == true) Color.Unspecified else grayTint
|
||||
if (boostsState?.note?.isBoostedBy(accountViewModel.userProfile()) == true) Color.Unspecified else grayTint
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,8 +589,8 @@ fun BoostText(baseNote: Note, grayTint: Color) {
|
||||
}
|
||||
|
||||
Text(
|
||||
boostCount,
|
||||
fontSize = 14.sp,
|
||||
text = boostCount,
|
||||
fontSize = Font14SP,
|
||||
color = grayTint
|
||||
)
|
||||
}
|
||||
@@ -528,7 +603,7 @@ fun LikeReaction(
|
||||
accountViewModel: AccountViewModel,
|
||||
iconSize: Dp = 20.dp,
|
||||
heartSize: Dp = 16.dp,
|
||||
iconFontSize: TextUnit = 14.sp
|
||||
iconFontSize: TextUnit = Font14SP
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
@@ -540,13 +615,12 @@ fun LikeReaction(
|
||||
var wantsToChangeReactionSymbol by remember { mutableStateOf(false) }
|
||||
var wantsToReact by remember { mutableStateOf(false) }
|
||||
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
Box(
|
||||
contentAlignment = Center,
|
||||
modifier = iconButtonModifier.combinedClickable(
|
||||
role = Role.Button,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false, radius = 24.dp),
|
||||
indication = rememberRipple(bounded = false, radius = Size24dp),
|
||||
onClick = {
|
||||
likeClick(
|
||||
baseNote,
|
||||
@@ -563,37 +637,37 @@ fun LikeReaction(
|
||||
}
|
||||
)
|
||||
) {
|
||||
LikeIcon(baseNote, iconFontSize, heartSize, grayTint, accountViewModel.userProfile())
|
||||
|
||||
if (wantsToChangeReactionSymbol) {
|
||||
UpdateReactionTypeDialog({ wantsToChangeReactionSymbol = false }, accountViewModel = accountViewModel)
|
||||
}
|
||||
|
||||
if (wantsToReact) {
|
||||
ReactionChoicePopup(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
onDismiss = {
|
||||
wantsToReact = false
|
||||
},
|
||||
onChangeAmount = {
|
||||
wantsToReact = false
|
||||
wantsToChangeReactionSymbol = true
|
||||
}
|
||||
)
|
||||
}
|
||||
LikeIcon(baseNote, iconFontSize, heartSize, grayTint, accountViewModel)
|
||||
}
|
||||
|
||||
LikeText(baseNote, grayTint)
|
||||
|
||||
if (wantsToChangeReactionSymbol) {
|
||||
UpdateReactionTypeDialog({ wantsToChangeReactionSymbol = false }, accountViewModel = accountViewModel)
|
||||
}
|
||||
|
||||
if (wantsToReact) {
|
||||
ReactionChoicePopup(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
onDismiss = {
|
||||
wantsToReact = false
|
||||
},
|
||||
onChangeAmount = {
|
||||
wantsToReact = false
|
||||
wantsToChangeReactionSymbol = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LikeIcon(
|
||||
baseNote: Note,
|
||||
iconFontSize: TextUnit = 14.sp,
|
||||
iconSize: Dp = 20.dp,
|
||||
iconFontSize: TextUnit = Font14SP,
|
||||
iconSize: Dp = Size20dp,
|
||||
grayTint: Color,
|
||||
loggedIn: User
|
||||
accountViewModel: AccountViewModel
|
||||
) {
|
||||
val reactionsState by baseNote.live().reactions.observeAsState()
|
||||
|
||||
@@ -603,37 +677,59 @@ fun LikeIcon(
|
||||
|
||||
LaunchedEffect(key1 = reactionsState) {
|
||||
launch(Dispatchers.Default) {
|
||||
val newReactionType = reactionsState?.note?.isReactedBy(loggedIn)
|
||||
val newReactionType = reactionsState?.note?.isReactedBy(accountViewModel.userProfile())?.take(2)
|
||||
if (reactionType != newReactionType) {
|
||||
reactionType = newReactionType?.take(2)
|
||||
reactionType = newReactionType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reactionType != null) {
|
||||
RenderReactionType(reactionType!!, iconSize, iconFontSize)
|
||||
} else {
|
||||
RenderLikeIcon(iconSize, grayTint)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderLikeIcon(
|
||||
iconSize: Dp = Size20dp,
|
||||
grayTint: Color
|
||||
) {
|
||||
val iconModifier = remember {
|
||||
Modifier.size(iconSize)
|
||||
}
|
||||
|
||||
if (reactionType != null) {
|
||||
when (reactionType) {
|
||||
"+" -> {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_liked),
|
||||
null,
|
||||
modifier = iconModifier,
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
}
|
||||
"-" -> Text(text = "\uD83D\uDC4E", fontSize = iconFontSize)
|
||||
else -> Text(text = reactionType!!, fontSize = iconFontSize)
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_like),
|
||||
null,
|
||||
modifier = iconModifier,
|
||||
tint = grayTint
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderReactionType(
|
||||
reactionType: String,
|
||||
iconSize: Dp = Size20dp,
|
||||
iconFontSize: TextUnit
|
||||
) {
|
||||
val iconModifier = remember {
|
||||
Modifier.size(iconSize)
|
||||
}
|
||||
|
||||
when (reactionType) {
|
||||
"+" -> {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_liked),
|
||||
null,
|
||||
modifier = iconModifier,
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_like),
|
||||
null,
|
||||
modifier = iconModifier,
|
||||
tint = grayTint
|
||||
)
|
||||
|
||||
"-" -> Text(text = "\uD83D\uDC4E", fontSize = iconFontSize)
|
||||
else -> Text(text = reactionType, fontSize = iconFontSize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,8 +751,8 @@ fun LikeText(baseNote: Note, grayTint: Color) {
|
||||
}
|
||||
|
||||
Text(
|
||||
reactionsCount,
|
||||
fontSize = 14.sp,
|
||||
text = reactionsCount,
|
||||
fontSize = Font14SP,
|
||||
color = grayTint
|
||||
)
|
||||
}
|
||||
@@ -727,7 +823,7 @@ fun ZapReaction(
|
||||
.combinedClickable(
|
||||
role = Role.Button,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false, radius = 24.dp),
|
||||
indication = rememberRipple(bounded = false, radius = Size24dp),
|
||||
onClick = {
|
||||
zapClick(
|
||||
baseNote,
|
||||
@@ -930,8 +1026,8 @@ private fun ZapAmountText(
|
||||
}
|
||||
|
||||
Text(
|
||||
zapAmountTxt,
|
||||
fontSize = 14.sp,
|
||||
text = zapAmountTxt,
|
||||
fontSize = Font14SP,
|
||||
color = grayTint
|
||||
)
|
||||
}
|
||||
@@ -940,17 +1036,38 @@ private fun ZapAmountText(
|
||||
fun ViewCountReaction(
|
||||
idHex: String,
|
||||
grayTint: Color,
|
||||
iconSize: Dp = 20.dp,
|
||||
barChartSize: Dp = 19.dp,
|
||||
numberSize: Dp = 24.dp
|
||||
barChartSize: Dp = Size19dp,
|
||||
numberSize: Dp = Size24dp
|
||||
) {
|
||||
val uri = LocalUriHandler.current
|
||||
val context = LocalContext.current
|
||||
DrawViewCountIcon(barChartSize, grayTint)
|
||||
DrawViewCount(idHex, numberSize, grayTint)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DrawViewCountIcon(
|
||||
barChartSize: Dp = Size19dp,
|
||||
grayTint: Color
|
||||
) {
|
||||
val iconButtonModifier = remember {
|
||||
Modifier.size(barChartSize)
|
||||
}
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.BarChart,
|
||||
null,
|
||||
modifier = iconButtonModifier,
|
||||
tint = grayTint
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DrawViewCount(
|
||||
idHex: String,
|
||||
numberSize: Dp = Size24dp,
|
||||
grayTint: Color
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val iconModifier = remember {
|
||||
Modifier.height(numberSize)
|
||||
}
|
||||
@@ -959,34 +1076,18 @@ fun ViewCountReaction(
|
||||
ColorFilter.tint(grayTint)
|
||||
}
|
||||
|
||||
IconButton(
|
||||
modifier = Modifier.size(iconSize),
|
||||
onClick = { uri.openUri("https://counter.amethyst.social/$idHex/") }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.BarChart,
|
||||
null,
|
||||
modifier = iconButtonModifier,
|
||||
tint = grayTint
|
||||
)
|
||||
}
|
||||
|
||||
val request = remember {
|
||||
ImageRequest.Builder(context)
|
||||
.data("https://counter.amethyst.social/$idHex.svg?label=+&color=00000000")
|
||||
.diskCachePolicy(CachePolicy.DISABLED)
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.build()
|
||||
}
|
||||
|
||||
Row {
|
||||
AsyncImage(
|
||||
model = request,
|
||||
contentDescription = stringResource(R.string.view_count),
|
||||
modifier = iconModifier,
|
||||
colorFilter = colorFilter
|
||||
)
|
||||
}
|
||||
AsyncImage(
|
||||
model = remember(idHex) {
|
||||
ImageRequest.Builder(context)
|
||||
.data("https://counter.amethyst.social/$idHex.svg?label=+&color=00000000")
|
||||
.diskCachePolicy(CachePolicy.DISABLED)
|
||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.build()
|
||||
},
|
||||
contentDescription = stringResource(R.string.view_count),
|
||||
modifier = iconModifier,
|
||||
colorFilter = colorFilter
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
|
||||
@@ -60,7 +60,6 @@ import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -78,6 +77,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.getFragmentActivity
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -415,7 +415,7 @@ fun UpdateZapAmountDialog(onClose: () -> Unit, nip47uri: String? = null, account
|
||||
stringResource(id = R.string.wallet_connect_service_explainer),
|
||||
Modifier.weight(1f),
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
fontSize = 14.sp
|
||||
fontSize = Font14SP
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
||||
val updatedCards = (oldNotesState.feed.value + newCards)
|
||||
.sortedWith(compareBy({ it.createdAt() }, { it.id() }))
|
||||
.reversed()
|
||||
.take(1000)
|
||||
.take(localFilter.limit())
|
||||
.toImmutableList()
|
||||
|
||||
if (!equalImmutableLists(oldNotesState.feed.value, updatedCards)) {
|
||||
@@ -115,7 +115,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
||||
val cards = convertToCard(notes)
|
||||
.sortedWith(compareBy({ it.createdAt() }, { it.id() }))
|
||||
.reversed()
|
||||
.take(1000)
|
||||
.take(localFilter.limit())
|
||||
.toImmutableList()
|
||||
|
||||
updateFeed(cards)
|
||||
@@ -255,7 +255,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
||||
val updatedCards = (oldNotesState.feed.value + newCards)
|
||||
.sortedWith(compareBy({ it.createdAt() }, { it.id() }))
|
||||
.reversed()
|
||||
.take(1000)
|
||||
.take(localFilter.limit())
|
||||
.toImmutableList()
|
||||
|
||||
if (!equalImmutableLists(oldNotesState.feed.value, updatedCards)) {
|
||||
|
||||
@@ -288,7 +288,7 @@ fun NoteMaster(
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
NoteUsernameDisplay(baseNote, Modifier.weight(1f))
|
||||
|
||||
DisplayFollowingHashtagsInPost(noteEvent, accountViewModel, nav)
|
||||
DisplayFollowingHashtagsInPost(baseNote, accountViewModel, nav)
|
||||
|
||||
Text(
|
||||
timeAgo(note.createdAt(), context = context),
|
||||
|
||||
@@ -364,14 +364,18 @@ fun EditFieldRow(
|
||||
onSendNewMessage()
|
||||
},
|
||||
isActive = channelScreenModel.message.text.isNotBlank() && !channelScreenModel.isUploadingImage,
|
||||
modifier = Modifier.height(32.dp).padding(end = 10.dp)
|
||||
modifier = Modifier
|
||||
.height(32.dp)
|
||||
.padding(end = 10.dp)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
UploadFromGallery(
|
||||
isUploading = channelScreenModel.isUploadingImage,
|
||||
tint = MaterialTheme.colors.placeholderText,
|
||||
modifier = Modifier.height(32.dp).padding(start = 2.dp)
|
||||
modifier = Modifier
|
||||
.height(32.dp)
|
||||
.padding(start = 2.dp)
|
||||
) {
|
||||
val fileServer = if (isPrivate) {
|
||||
// TODO: Make private servers
|
||||
@@ -478,6 +482,31 @@ fun MyTextField(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelHeader(
|
||||
channelNote: Note,
|
||||
showVideo: Boolean,
|
||||
showBottomDiviser: Boolean,
|
||||
modifier: Modifier = StdPadding,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val channelHex by remember {
|
||||
derivedStateOf {
|
||||
channelNote.channelHex()
|
||||
}
|
||||
}
|
||||
channelHex?.let {
|
||||
ChannelHeader(
|
||||
channelHex = it,
|
||||
showVideo = showVideo,
|
||||
showBottomDiviser = showBottomDiviser,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelHeader(
|
||||
channelHex: String,
|
||||
|
||||
@@ -397,7 +397,7 @@ fun ReactionsColumn(baseNote: Note, accountViewModel: AccountViewModel, nav: (St
|
||||
}*/
|
||||
LikeReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, accountViewModel, iconSize = 40.dp, heartSize = Size35dp, 28.sp)
|
||||
ZapReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, accountViewModel, iconSize = 40.dp, animationSize = Size35dp)
|
||||
ViewCountReaction(baseNote.idHex, grayTint = MaterialTheme.colors.onBackground, iconSize = 40.dp, barChartSize = 39.dp)
|
||||
ViewCountReaction(baseNote.idHex, grayTint = MaterialTheme.colors.onBackground, barChartSize = 39.dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ import androidx.compose.ui.text.input.*
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.qrcode.SimpleQrCodeScanner
|
||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ConnectOrbotDialog
|
||||
import com.vitorpamplona.amethyst.ui.theme.Font14SP
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import java.util.*
|
||||
@@ -305,7 +305,7 @@ fun LoginPage(
|
||||
}
|
||||
},
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontSize = Font14SP,
|
||||
textDecoration = TextDecoration.Underline,
|
||||
color = MaterialTheme.colors.primary,
|
||||
textAlign = TextAlign.Center
|
||||
|
||||
@@ -16,6 +16,8 @@ val Nip05 = Color(0xFF01BAFF)
|
||||
val FollowsFollow = Color.Yellow
|
||||
val NIP05Verified = Color.Blue
|
||||
|
||||
val DarkerGreen = Color.Green.copy(alpha = 0.32f)
|
||||
|
||||
val WarningColor = Color(0xFFC62828)
|
||||
|
||||
val RelayIconFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0.5f) })
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.vitorpamplona.amethyst.ui.theme
|
||||
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -23,17 +25,46 @@ val ChatBubbleShapeMe = RoundedCornerShape(15.dp, 15.dp, 3.dp, 15.dp)
|
||||
val ChatBubbleShapeThem = RoundedCornerShape(3.dp, 15.dp, 15.dp, 15.dp)
|
||||
|
||||
val StdButtonSizeModifier = Modifier.size(20.dp)
|
||||
|
||||
val HalfVertSpacer = Modifier.height(2.dp)
|
||||
|
||||
val StdHorzSpacer = Modifier.width(5.dp)
|
||||
val StdVertSpacer = Modifier.height(5.dp)
|
||||
|
||||
val DoubleHorzSpacer = Modifier.width(10.dp)
|
||||
val DoubleVertSpacer = Modifier.height(10.dp)
|
||||
|
||||
val HalfDoubleVertSpacer = Modifier.height(7.dp)
|
||||
|
||||
val Size13dp = 13.dp
|
||||
val Size16dp = 16.dp
|
||||
val Size18dp = 18.dp
|
||||
val Size19dp = 19.dp
|
||||
val Size20dp = 20.dp
|
||||
val Size24dp = 24.dp
|
||||
val Size25dp = 25.dp
|
||||
val Size30dp = 30.dp
|
||||
val Size35dp = 35.dp
|
||||
val Size55dp = 55.dp
|
||||
|
||||
val StdStartPadding = Modifier.padding(start = 10.dp)
|
||||
|
||||
val HalfPadding = Modifier.padding(5.dp)
|
||||
val StdPadding = Modifier.padding(10.dp)
|
||||
|
||||
val Size15Modifier = Modifier.size(15.dp)
|
||||
val Size20Modifier = Modifier.size(20.dp)
|
||||
val Size22Modifier = Modifier.size(22.dp)
|
||||
val Size30Modifier = Modifier.size(30.dp)
|
||||
val Size55Modifier = Modifier.size(55.dp)
|
||||
|
||||
val TinyBorders = Modifier.padding(2.dp)
|
||||
val NoSoTinyBorders = Modifier.padding(start = 5.dp, end = 5.dp, top = 2.dp, bottom = 2.dp)
|
||||
val ReactionRowZapraiserSize = Modifier.defaultMinSize(minHeight = 4.dp).fillMaxWidth()
|
||||
val ReactionRowExpandButton = Modifier.width(65.dp).padding(start = 31.dp)
|
||||
|
||||
val WidthAuthorPictureModifier = Modifier.width(55.dp)
|
||||
|
||||
val DiviserThickness = 0.25.dp
|
||||
|
||||
val ReactionRowHeight = Modifier.padding(start = 22.dp).padding(start = 10.dp)
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
package com.vitorpamplona.amethyst.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Colors
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.halilibo.richtext.ui.RichTextStyle
|
||||
import com.vitorpamplona.amethyst.ui.components.DefaultHeadingStyle
|
||||
import com.vitorpamplona.amethyst.ui.components.DefaultParagraphSpacing
|
||||
import com.vitorpamplona.amethyst.ui.components.richTextDefaults
|
||||
|
||||
private val DarkColorPalette = darkColors(
|
||||
primary = Purple200,
|
||||
@@ -30,9 +45,6 @@ private val LightColorPalette = lightColors(
|
||||
private val DarkNewItemBackground = DarkColorPalette.primary.copy(0.12f)
|
||||
private val LightNewItemBackground = LightColorPalette.primary.copy(0.12f)
|
||||
|
||||
private val DarkReplyItemBackground = DarkColorPalette.onSurface.copy(alpha = 0.05f)
|
||||
private val LightReplyItemBackground = LightColorPalette.onSurface.copy(alpha = 0.05f)
|
||||
|
||||
private val DarkSelectedNote = DarkNewItemBackground.compositeOver(DarkColorPalette.background)
|
||||
private val LightSelectedNote = LightNewItemBackground.compositeOver(LightColorPalette.background)
|
||||
|
||||
@@ -54,9 +66,15 @@ private val LightGrayText = LightColorPalette.onSurface.copy(alpha = 0.52f)
|
||||
private val DarkPlaceholderText = DarkColorPalette.onSurface.copy(alpha = 0.32f)
|
||||
private val LightPlaceholderText = LightColorPalette.onSurface.copy(alpha = 0.32f)
|
||||
|
||||
private val DarkSubtleButton = DarkColorPalette.onSurface.copy(alpha = 0.22f)
|
||||
private val LightSubtleButton = LightColorPalette.onSurface.copy(alpha = 0.22f)
|
||||
|
||||
private val DarkSubtleBorder = DarkColorPalette.onSurface.copy(alpha = 0.12f)
|
||||
private val LightSubtleBorder = LightColorPalette.onSurface.copy(alpha = 0.12f)
|
||||
|
||||
private val DarkReplyItemBackground = DarkColorPalette.onSurface.copy(alpha = 0.05f)
|
||||
private val LightReplyItemBackground = LightColorPalette.onSurface.copy(alpha = 0.05f)
|
||||
|
||||
private val DarkZapraiserBackground = BitcoinOrange.copy(0.52f).compositeOver(DarkColorPalette.background)
|
||||
private val LightZapraiserBackground = BitcoinOrange.copy(0.52f).compositeOver(LightColorPalette.background)
|
||||
|
||||
@@ -66,6 +84,84 @@ private val LightImageVerifier = Nip05.copy(0.52f).compositeOver(LightColorPalet
|
||||
private val DarkOverPictureBackground = DarkColorPalette.background.copy(0.62f)
|
||||
private val LightOverPictureBackground = LightColorPalette.background.copy(0.62f)
|
||||
|
||||
val RepostPictureBorderDark = Modifier.border(
|
||||
2.dp,
|
||||
DarkColorPalette.background,
|
||||
CircleShape
|
||||
)
|
||||
|
||||
val RepostPictureBorderLight = Modifier.border(
|
||||
2.dp,
|
||||
LightColorPalette.background,
|
||||
CircleShape
|
||||
)
|
||||
|
||||
val MarkDownStyleOnDark = richTextDefaults.copy(
|
||||
paragraphSpacing = DefaultParagraphSpacing,
|
||||
headingStyle = DefaultHeadingStyle,
|
||||
codeBlockStyle = richTextDefaults.codeBlockStyle?.copy(
|
||||
textStyle = TextStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = Font14SP
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(0.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
1.dp,
|
||||
DarkSubtleBorder,
|
||||
QuoteBorder
|
||||
)
|
||||
.drawBehind {
|
||||
drawRect(DarkColorPalette.onSurface.copy(alpha = 0.05f))
|
||||
}
|
||||
),
|
||||
stringStyle = richTextDefaults.stringStyle?.copy(
|
||||
linkStyle = SpanStyle(
|
||||
color = DarkColorPalette.primary
|
||||
),
|
||||
codeStyle = SpanStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = Font14SP,
|
||||
background = DarkColorPalette.onSurface.copy(alpha = 0.22f)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val MarkDownStyleOnLight = richTextDefaults.copy(
|
||||
paragraphSpacing = DefaultParagraphSpacing,
|
||||
headingStyle = DefaultHeadingStyle,
|
||||
codeBlockStyle = richTextDefaults.codeBlockStyle?.copy(
|
||||
textStyle = TextStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = Font14SP
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(0.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
1.dp,
|
||||
LightSubtleBorder,
|
||||
QuoteBorder
|
||||
)
|
||||
.drawBehind {
|
||||
drawRect(LightColorPalette.onSurface.copy(alpha = 0.05f))
|
||||
}
|
||||
),
|
||||
stringStyle = richTextDefaults.stringStyle?.copy(
|
||||
linkStyle = SpanStyle(
|
||||
color = LightColorPalette.primary
|
||||
),
|
||||
codeStyle = SpanStyle(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = Font14SP,
|
||||
background = LightColorPalette.onSurface.copy(alpha = 0.22f)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val Colors.newItemBackgroundColor: Color
|
||||
get() = if (isLight) LightNewItemBackground else DarkNewItemBackground
|
||||
|
||||
@@ -98,12 +194,21 @@ val Colors.grayText: Color
|
||||
val Colors.subtleBorder: Color
|
||||
get() = if (isLight) LightSubtleBorder else DarkSubtleBorder
|
||||
|
||||
val Colors.subtleButton: Color
|
||||
get() = if (isLight) LightSubtleButton else DarkSubtleButton
|
||||
|
||||
val Colors.hashVerified: Color
|
||||
get() = if (isLight) LightImageVerifier else DarkImageVerifier
|
||||
|
||||
val Colors.overPictureBackground: Color
|
||||
get() = if (isLight) LightOverPictureBackground else DarkOverPictureBackground
|
||||
|
||||
val Colors.markdownStyle: RichTextStyle
|
||||
get() = if (isLight) MarkDownStyleOnLight else MarkDownStyleOnDark
|
||||
|
||||
val Colors.repostProfileBorder: Modifier
|
||||
get() = if (isLight) RepostPictureBorderLight else RepostPictureBorderDark
|
||||
|
||||
@Composable
|
||||
fun AmethystTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
|
||||
val colors = if (darkTheme) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
@@ -17,7 +18,7 @@ val Typography = Typography(
|
||||
button = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.W500,
|
||||
fontSize = 14.sp
|
||||
fontSize = Font14SP
|
||||
),
|
||||
caption = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
@@ -26,3 +27,7 @@ val Typography = Typography(
|
||||
)
|
||||
*/
|
||||
)
|
||||
|
||||
val Font14SP = 14.sp
|
||||
|
||||
val MarkdownTextStyle = TextStyle(lineHeight = 1.30.em)
|
||||
|
||||
Reference in New Issue
Block a user