1. Refactors the use of dividers out of components
2. Refactors composables to load events, check hidden and check report
This commit is contained in:
@@ -47,7 +47,6 @@ import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.Height4dpModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Composable
|
||||
@@ -134,10 +133,5 @@ fun ChatHeaderLayout(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = StdTopPadding,
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ fun BadgeCompose(
|
||||
likeSetCard: BadgeCard,
|
||||
isInnerNote: Boolean = false,
|
||||
routeForLastRead: String,
|
||||
showHidden: Boolean = false,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
@@ -79,7 +78,7 @@ fun BadgeCompose(
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
if (note == null) {
|
||||
BlankNote(Modifier, !isInnerNote)
|
||||
BlankNote(Modifier)
|
||||
} else {
|
||||
val backgroundColor =
|
||||
calculateBackgroundColor(
|
||||
|
||||
@@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -45,7 +44,6 @@ import com.vitorpamplona.amethyst.ui.components.mockAccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
@@ -60,7 +58,6 @@ fun BlankNotePreview() {
|
||||
@Composable
|
||||
fun BlankNote(
|
||||
modifier: Modifier = Modifier,
|
||||
showDivider: Boolean = true,
|
||||
idHex: String? = null,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
@@ -84,13 +81,6 @@ fun BlankNote(
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
if (showDivider) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 10.dp),
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,10 +161,6 @@ fun HiddenNote(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +175,6 @@ fun HiddenNoteByMePreview() {
|
||||
@Composable
|
||||
fun HiddenNoteByMe(
|
||||
modifier: Modifier = Modifier,
|
||||
isQuote: Boolean = false,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
@@ -222,11 +207,5 @@ fun HiddenNoteByMe(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isQuote) {
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Copyright (c) 2024 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
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
@Composable
|
||||
fun CheckHiddenFeedWatchBlockAndReport(
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
showHiddenWarning: Boolean,
|
||||
showHidden: Boolean = false,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
if (showHidden) {
|
||||
// Ignores reports as well
|
||||
normalNote(true)
|
||||
} else {
|
||||
WatchBlockAndReport(note, showHiddenWarning, modifier, accountViewModel, nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchBlockAndReport(
|
||||
note: Note,
|
||||
showHiddenWarning: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
val isHiddenState by remember(note) {
|
||||
accountViewModel.account.liveHiddenUsers
|
||||
.map { note.isHiddenFor(it) }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
.observeAsState(accountViewModel.isNoteHidden(note))
|
||||
|
||||
val showAnyway =
|
||||
remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
Crossfade(targetState = isHiddenState, label = "CheckHiddenNoteCompose") { isHidden ->
|
||||
if (showAnyway.value) {
|
||||
normalNote(true)
|
||||
} else if (!isHidden) {
|
||||
LoadReportsNoteCompose(note, modifier, accountViewModel, nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
} else if (showHiddenWarning) {
|
||||
// if it is a quoted or boosted note, how the hidden warning.
|
||||
HiddenNoteByMe {
|
||||
showAnyway.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadReportsNoteCompose(
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
var state by
|
||||
remember(note) {
|
||||
mutableStateOf(
|
||||
AccountViewModel.NoteComposeReportState(),
|
||||
)
|
||||
}
|
||||
|
||||
WatchForReports(note, accountViewModel) { newState ->
|
||||
if (state != newState) {
|
||||
state = newState
|
||||
}
|
||||
}
|
||||
|
||||
Crossfade(targetState = state, label = "LoadedNoteCompose") {
|
||||
RenderReportState(state = it, note = note, modifier = modifier, accountViewModel = accountViewModel, nav = nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderReportState(
|
||||
state: AccountViewModel.NoteComposeReportState,
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
var showReportedNote by remember(note) { mutableStateOf(false) }
|
||||
|
||||
Crossfade(targetState = !state.isAcceptable && !showReportedNote, label = "RenderReportState") { showHiddenNote ->
|
||||
if (showHiddenNote) {
|
||||
HiddenNote(
|
||||
state.relevantReports,
|
||||
state.isHiddenAuthor,
|
||||
accountViewModel,
|
||||
modifier,
|
||||
nav,
|
||||
onClick = { showReportedNote = true },
|
||||
)
|
||||
} else {
|
||||
val canPreview = (!state.isAcceptable && showReportedNote) || state.canPreview
|
||||
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchForReports(
|
||||
note: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
onChange: (AccountViewModel.NoteComposeReportState) -> Unit,
|
||||
) {
|
||||
val userFollowsState by accountViewModel.userFollows.observeAsState()
|
||||
val noteReportsState by note.live().reports.observeAsState()
|
||||
val userBlocks by accountViewModel.account.flowHiddenUsers.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(key1 = noteReportsState, key2 = userFollowsState, userBlocks) {
|
||||
accountViewModel.isNoteAcceptable(note, onChange)
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,7 @@
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -36,7 +34,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
@@ -49,7 +46,6 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment.Companion.BottomStart
|
||||
import androidx.compose.ui.Alignment.Companion.TopEnd
|
||||
@@ -81,7 +77,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.LiveFlag
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.OfflineFlag
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ScheduledFlag
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
@@ -106,7 +101,6 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun ChannelCardCompose(
|
||||
baseNote: Note,
|
||||
@@ -114,160 +108,29 @@ fun ChannelCardCompose(
|
||||
modifier: Modifier = Modifier,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
forceEventKind: Int?,
|
||||
showHidden: Boolean = false,
|
||||
isHiddenFeed: Boolean = false,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||
|
||||
Crossfade(targetState = hasEvent, label = "ChannelCardCompose") {
|
||||
if (it) {
|
||||
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
||||
CheckHiddenChannelCardCompose(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
parentBackgroundColor,
|
||||
showHidden,
|
||||
accountViewModel,
|
||||
nav,
|
||||
WatchNoteEvent(baseNote = baseNote, accountViewModel = accountViewModel) {
|
||||
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
||||
CheckHiddenFeedWatchBlockAndReport(
|
||||
note = baseNote,
|
||||
modifier = modifier,
|
||||
showHidden = isHiddenFeed,
|
||||
showHiddenWarning = false,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
) { canPreview ->
|
||||
NormalChannelCard(
|
||||
baseNote = baseNote,
|
||||
routeForLastRead = routeForLastRead,
|
||||
modifier = modifier,
|
||||
parentBackgroundColor = parentBackgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup,
|
||||
->
|
||||
BlankNote(
|
||||
remember {
|
||||
modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CheckHiddenChannelCardCompose(
|
||||
note: Note,
|
||||
routeForLastRead: String? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
showHidden: Boolean,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
if (showHidden) {
|
||||
val state by remember {
|
||||
mutableStateOf(
|
||||
AccountViewModel.NoteComposeReportState(),
|
||||
)
|
||||
}
|
||||
|
||||
RenderChannelCardReportState(
|
||||
state = state,
|
||||
note = note,
|
||||
routeForLastRead = routeForLastRead,
|
||||
modifier = modifier,
|
||||
parentBackgroundColor = parentBackgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
} else {
|
||||
val isHidden by
|
||||
accountViewModel.account.liveHiddenUsers
|
||||
.map { note.isHiddenFor(it) }
|
||||
.distinctUntilChanged()
|
||||
.observeAsState(accountViewModel.isNoteHidden(note))
|
||||
|
||||
Crossfade(targetState = isHidden, label = "CheckHiddenChannelCardCompose") {
|
||||
if (!it) {
|
||||
LoadedChannelCardCompose(
|
||||
note,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoadedChannelCardCompose(
|
||||
note: Note,
|
||||
routeForLastRead: String? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
var state by remember {
|
||||
mutableStateOf(
|
||||
AccountViewModel.NoteComposeReportState(),
|
||||
)
|
||||
}
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
WatchForReports(note, accountViewModel) { newState ->
|
||||
if (state != newState) {
|
||||
scope.launch(Dispatchers.Main) { state = newState }
|
||||
}
|
||||
}
|
||||
|
||||
Crossfade(targetState = state, label = "CheckHiddenChannelCardCompose") {
|
||||
RenderChannelCardReportState(
|
||||
it,
|
||||
note,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RenderChannelCardReportState(
|
||||
state: AccountViewModel.NoteComposeReportState,
|
||||
note: Note,
|
||||
routeForLastRead: String? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
var showReportedNote by remember { mutableStateOf(false) }
|
||||
|
||||
Crossfade(
|
||||
targetState = !state.isAcceptable && !showReportedNote,
|
||||
label = "CheckHiddenChannelCardCompose",
|
||||
) { showHiddenNote ->
|
||||
if (showHiddenNote) {
|
||||
HiddenNote(
|
||||
state.relevantReports,
|
||||
state.isHiddenAuthor,
|
||||
accountViewModel,
|
||||
modifier,
|
||||
nav,
|
||||
onClick = { showReportedNote = true },
|
||||
)
|
||||
} else {
|
||||
NormalChannelCard(
|
||||
note,
|
||||
routeForLastRead,
|
||||
modifier,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,10 +231,6 @@ fun InnerCardRow(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -32,7 +31,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -61,9 +59,8 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.FeatureSetType
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
@@ -97,7 +94,6 @@ import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun ChatroomMessageCompose(
|
||||
baseNote: Note,
|
||||
@@ -108,111 +104,13 @@ fun ChatroomMessageCompose(
|
||||
nav: (String) -> Unit,
|
||||
onWantsToReply: (Note) -> Unit,
|
||||
) {
|
||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||
|
||||
Crossfade(targetState = hasEvent) {
|
||||
if (it) {
|
||||
CheckHiddenChatMessage(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
innerQuote,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
onWantsToReply,
|
||||
)
|
||||
} else {
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup,
|
||||
->
|
||||
BlankNote(
|
||||
remember {
|
||||
Modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CheckHiddenChatMessage(
|
||||
baseNote: Note,
|
||||
routeForLastRead: String?,
|
||||
innerQuote: Boolean = false,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
onWantsToReply: (Note) -> Unit,
|
||||
) {
|
||||
val isHidden by
|
||||
remember {
|
||||
accountViewModel.account.liveHiddenUsers
|
||||
.map { baseNote.isHiddenFor(it) }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
.observeAsState(accountViewModel.isNoteHidden(baseNote))
|
||||
|
||||
if (!isHidden) {
|
||||
LoadedChatMessageCompose(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
innerQuote,
|
||||
parentBackgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
onWantsToReply,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoadedChatMessageCompose(
|
||||
baseNote: Note,
|
||||
routeForLastRead: String?,
|
||||
innerQuote: Boolean = false,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
onWantsToReply: (Note) -> Unit,
|
||||
) {
|
||||
var state by remember {
|
||||
mutableStateOf(
|
||||
AccountViewModel.NoteComposeReportState(),
|
||||
)
|
||||
}
|
||||
|
||||
WatchForReports(baseNote, accountViewModel) { newState ->
|
||||
if (state != newState) {
|
||||
state = newState
|
||||
}
|
||||
}
|
||||
|
||||
var showReportedNote by remember { mutableStateOf(false) }
|
||||
|
||||
val showHiddenNote by
|
||||
remember(state, showReportedNote) {
|
||||
derivedStateOf { !state.isAcceptable && !showReportedNote }
|
||||
}
|
||||
|
||||
Crossfade(targetState = showHiddenNote) {
|
||||
if (it) {
|
||||
HiddenNote(
|
||||
state.relevantReports,
|
||||
state.isHiddenAuthor,
|
||||
accountViewModel,
|
||||
Modifier,
|
||||
nav,
|
||||
onClick = { showReportedNote = true },
|
||||
)
|
||||
} else {
|
||||
val canPreview by
|
||||
remember(state, showReportedNote) {
|
||||
derivedStateOf { (!state.isAcceptable && showReportedNote) || state.canPreview }
|
||||
}
|
||||
|
||||
WatchNoteEvent(baseNote = baseNote, accountViewModel = accountViewModel) {
|
||||
WatchBlockAndReport(
|
||||
note = baseNote,
|
||||
showHiddenWarning = innerQuote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
) { canPreview ->
|
||||
NormalChatNote(
|
||||
baseNote,
|
||||
routeForLastRead,
|
||||
|
||||
@@ -104,7 +104,7 @@ fun MessageSetCompose(
|
||||
baseNote = baseNote,
|
||||
routeForLastRead = null,
|
||||
isBoostedNote = true,
|
||||
showHidden = showHidden,
|
||||
isHiddenFeed = showHidden,
|
||||
quotesLeft = 1,
|
||||
parentBackgroundColor = backgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
|
||||
@@ -145,7 +145,7 @@ fun MultiSetCompose(
|
||||
routeForLastRead = null,
|
||||
modifier = HalfTopPadding,
|
||||
isBoostedNote = true,
|
||||
showHidden = showHidden,
|
||||
isHiddenFeed = showHidden,
|
||||
quotesLeft = 1,
|
||||
parentBackgroundColor = backgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
@@ -42,7 +41,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
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.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -51,7 +49,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@@ -176,7 +173,7 @@ fun NoteCompose(
|
||||
isQuotedNote: Boolean = false,
|
||||
unPackReply: Boolean = true,
|
||||
makeItShort: Boolean = false,
|
||||
showHidden: Boolean = false,
|
||||
isHiddenFeed: Boolean = false,
|
||||
quotesLeft: Int,
|
||||
parentBackgroundColor: MutableState<Color>? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
@@ -185,13 +182,12 @@ fun NoteCompose(
|
||||
WatchNoteEvent(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
showDivider = !isBoostedNote && !isQuotedNote,
|
||||
modifier,
|
||||
) {
|
||||
CheckHiddenNoteCompose(
|
||||
CheckHiddenFeedWatchBlockAndReport(
|
||||
note = baseNote,
|
||||
modifier = modifier,
|
||||
showHidden = showHidden,
|
||||
showHidden = isHiddenFeed,
|
||||
showHiddenWarning = isQuotedNote || isBoostedNote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
@@ -214,171 +210,6 @@ fun NoteCompose(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun WatchNoteEvent(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
showDivider: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onNoteEventFound: @Composable () -> Unit,
|
||||
) {
|
||||
if (baseNote.event != null) {
|
||||
onNoteEventFound()
|
||||
} else {
|
||||
// avoid observing costs if already has an event.
|
||||
|
||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||
Crossfade(targetState = hasEvent, label = "Event presence") {
|
||||
if (it) {
|
||||
onNoteEventFound()
|
||||
} else {
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||
BlankNote(
|
||||
remember {
|
||||
modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
showDivider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CheckHiddenNoteCompose(
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
showHiddenWarning: Boolean,
|
||||
showHidden: Boolean = false,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
if (showHidden) {
|
||||
// Ignores reports as well
|
||||
normalNote(true)
|
||||
} else {
|
||||
WatchIsHidden(note, showHiddenWarning, modifier, accountViewModel, nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchIsHidden(
|
||||
note: Note,
|
||||
showHiddenWarning: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
val isHiddenState by remember(note) {
|
||||
accountViewModel.account.liveHiddenUsers
|
||||
.map { note.isHiddenFor(it) }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
.observeAsState(accountViewModel.isNoteHidden(note))
|
||||
|
||||
val showAnyway =
|
||||
remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
Crossfade(targetState = isHiddenState, label = "CheckHiddenNoteCompose") { isHidden ->
|
||||
if (showAnyway.value) {
|
||||
normalNote(true)
|
||||
} else if (!isHidden) {
|
||||
LoadReportsNoteCompose(note, modifier, accountViewModel, nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
} else if (showHiddenWarning) {
|
||||
// if it is a quoted or boosted note, how the hidden warning.
|
||||
HiddenNoteByMe(
|
||||
isQuote = true,
|
||||
onClick = { showAnyway.value = true },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoadReportsNoteCompose(
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
var state by
|
||||
remember(note) {
|
||||
mutableStateOf(
|
||||
AccountViewModel.NoteComposeReportState(),
|
||||
)
|
||||
}
|
||||
|
||||
WatchForReports(note, accountViewModel) { newState ->
|
||||
if (state != newState) {
|
||||
state = newState
|
||||
}
|
||||
}
|
||||
|
||||
Crossfade(targetState = state, label = "LoadedNoteCompose") {
|
||||
RenderReportState(state = it, note = note, modifier = modifier, accountViewModel = accountViewModel, nav = nav) { canPreview ->
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RenderReportState(
|
||||
state: AccountViewModel.NoteComposeReportState,
|
||||
note: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
normalNote: @Composable (canPreview: Boolean) -> Unit,
|
||||
) {
|
||||
var showReportedNote by remember(note) { mutableStateOf(false) }
|
||||
|
||||
Crossfade(targetState = !state.isAcceptable && !showReportedNote, label = "RenderReportState") { showHiddenNote ->
|
||||
if (showHiddenNote) {
|
||||
HiddenNote(
|
||||
state.relevantReports,
|
||||
state.isHiddenAuthor,
|
||||
accountViewModel,
|
||||
modifier,
|
||||
nav,
|
||||
onClick = { showReportedNote = true },
|
||||
)
|
||||
} else {
|
||||
val canPreview = (!state.isAcceptable && showReportedNote) || state.canPreview
|
||||
|
||||
normalNote(canPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchForReports(
|
||||
note: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
onChange: (AccountViewModel.NoteComposeReportState) -> Unit,
|
||||
) {
|
||||
val userFollowsState by accountViewModel.userFollows.observeAsState()
|
||||
val noteReportsState by note.live().reports.observeAsState()
|
||||
val userBlocks by accountViewModel.account.flowHiddenUsers.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(key1 = noteReportsState, key2 = userFollowsState, userBlocks) {
|
||||
accountViewModel.isNoteAcceptable(note, onChange)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AcceptableNote(
|
||||
baseNote: Note,
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2024 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
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun WatchNoteEvent(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
modifier: Modifier = Modifier,
|
||||
onNoteEventFound: @Composable () -> Unit,
|
||||
) {
|
||||
if (baseNote.event != null) {
|
||||
onNoteEventFound()
|
||||
} else {
|
||||
// avoid observing costs if already has an event.
|
||||
|
||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||
Crossfade(targetState = hasEvent, label = "Event presence") {
|
||||
if (it) {
|
||||
onNoteEventFound()
|
||||
} else {
|
||||
LongPressToQuickAction(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
) { showPopup ->
|
||||
BlankNote(
|
||||
remember {
|
||||
modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -54,7 +53,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.UnfollowButton
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.WatchIsHiddenUser
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||
@@ -77,11 +75,11 @@ fun ZapNoteCompose(
|
||||
}
|
||||
}
|
||||
|
||||
val route = remember(baseAuthor) { "User/${baseAuthor?.pubkeyHex}" }
|
||||
|
||||
if (baseAuthor == null) {
|
||||
BlankNote()
|
||||
} else {
|
||||
val route = remember(baseAuthor) { "User/${baseAuthor?.pubkeyHex}" }
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.clickable(
|
||||
@@ -90,11 +88,6 @@ fun ZapNoteCompose(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
baseAuthor?.let { RenderZapNote(it, baseReqResponse.zapEvent, nav, accountViewModel) }
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 10.dp),
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,6 @@ private fun RenderCardItem(
|
||||
BadgeCompose(
|
||||
item,
|
||||
accountViewModel = accountViewModel,
|
||||
showHidden = showHidden,
|
||||
nav = nav,
|
||||
routeForLastRead = routeForLastRead,
|
||||
)
|
||||
@@ -304,7 +303,7 @@ fun NoteCardCompose(
|
||||
isQuotedNote = isQuotedNote,
|
||||
unPackReply = unPackReply,
|
||||
makeItShort = makeItShort,
|
||||
showHidden = showHidden,
|
||||
isHiddenFeed = showHidden,
|
||||
quotesLeft = 3,
|
||||
parentBackgroundColor = parentBackgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
@@ -35,7 +36,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.ui.note.ChatroomHeaderCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
@Composable
|
||||
@@ -109,6 +112,11 @@ private fun FeedLoaded(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = StdTopPadding,
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ private fun FeedLoaded(
|
||||
routeForLastRead = routeForLastRead,
|
||||
modifier = Modifier,
|
||||
isBoostedNote = false,
|
||||
showHidden = state.showHidden.value,
|
||||
isHiddenFeed = state.showHidden.value,
|
||||
quotesLeft = 3,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
|
||||
@@ -22,14 +22,19 @@ package com.vitorpamplona.amethyst.ui.screen
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.ui.note.ZapNoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
|
||||
@Composable
|
||||
@@ -72,6 +77,11 @@ private fun LnZapFeedLoaded(
|
||||
) {
|
||||
itemsIndexed(state.feed.value, key = { _, item -> item.zapEvent.idHex }) { _, item ->
|
||||
ZapNoteCompose(item, accountViewModel = accountViewModel, nav = nav)
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 10.dp),
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size15Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size24Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@@ -288,11 +289,12 @@ fun ThreadFeedView(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = StdTopPadding,
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,10 +628,6 @@ fun NoteMaster(
|
||||
}
|
||||
|
||||
ReactionsRow(note, true, editState, accountViewModel, nav)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
|
||||
NoteQuickActionMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ScrollableTabRow
|
||||
import androidx.compose.material3.Tab
|
||||
@@ -74,6 +75,7 @@ import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.SaveableGridFeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys
|
||||
import com.vitorpamplona.amethyst.ui.screen.rememberForeverPagerState
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
||||
import com.vitorpamplona.quartz.events.ChannelCreateEvent
|
||||
@@ -352,6 +354,10 @@ private fun DiscoverFeedLoaded(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,6 +390,10 @@ private fun DiscoverFeedColumnsLoaded(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.events.findHashtags
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -401,6 +402,11 @@ private fun DisplaySearchResults(
|
||||
loadProfilePicture = automaticallyShowProfilePicture,
|
||||
onClick = { nav("Channel/${item.idHex}") },
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = StdTopPadding,
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
|
||||
itemsIndexed(
|
||||
|
||||
Reference in New Issue
Block a user