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.DoubleHorzSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Height4dpModifier
|
import com.vitorpamplona.amethyst.ui.theme.Height4dpModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -134,10 +133,5 @@ fun ChatHeaderLayout(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalDivider(
|
|
||||||
modifier = StdTopPadding,
|
|
||||||
thickness = DividerThickness,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ fun BadgeCompose(
|
|||||||
likeSetCard: BadgeCard,
|
likeSetCard: BadgeCard,
|
||||||
isInnerNote: Boolean = false,
|
isInnerNote: Boolean = false,
|
||||||
routeForLastRead: String,
|
routeForLastRead: String,
|
||||||
showHidden: Boolean = false,
|
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -79,7 +78,7 @@ fun BadgeCompose(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
if (note == null) {
|
if (note == null) {
|
||||||
BlankNote(Modifier, !isInnerNote)
|
BlankNote(Modifier)
|
||||||
} else {
|
} else {
|
||||||
val backgroundColor =
|
val backgroundColor =
|
||||||
calculateBackgroundColor(
|
calculateBackgroundColor(
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ButtonPadding
|
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.Size35dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
@@ -60,7 +58,6 @@ fun BlankNotePreview() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun BlankNote(
|
fun BlankNote(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
showDivider: Boolean = true,
|
|
||||||
idHex: String? = null,
|
idHex: String? = null,
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
@@ -84,13 +81,6 @@ fun BlankNote(
|
|||||||
textAlign = TextAlign.Center,
|
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
|
@Composable
|
||||||
fun HiddenNoteByMe(
|
fun HiddenNoteByMe(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isQuote: Boolean = false,
|
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
|
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
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.combinedClickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -49,7 +46,6 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment.Companion.BottomStart
|
import androidx.compose.ui.Alignment.Companion.BottomStart
|
||||||
import androidx.compose.ui.Alignment.Companion.TopEnd
|
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.OfflineFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ScheduledFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ScheduledFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
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.DoubleVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||||
@@ -106,7 +101,6 @@ import kotlinx.collections.immutable.toImmutableList
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChannelCardCompose(
|
fun ChannelCardCompose(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
@@ -114,160 +108,29 @@ fun ChannelCardCompose(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
parentBackgroundColor: MutableState<Color>? = null,
|
parentBackgroundColor: MutableState<Color>? = null,
|
||||||
forceEventKind: Int?,
|
forceEventKind: Int?,
|
||||||
showHidden: Boolean = false,
|
isHiddenFeed: Boolean = false,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
WatchNoteEvent(baseNote = baseNote, accountViewModel = accountViewModel) {
|
||||||
|
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
||||||
Crossfade(targetState = hasEvent, label = "ChannelCardCompose") {
|
CheckHiddenFeedWatchBlockAndReport(
|
||||||
if (it) {
|
note = baseNote,
|
||||||
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
modifier = modifier,
|
||||||
CheckHiddenChannelCardCompose(
|
showHidden = isHiddenFeed,
|
||||||
baseNote,
|
showHiddenWarning = false,
|
||||||
routeForLastRead,
|
accountViewModel = accountViewModel,
|
||||||
modifier,
|
nav = nav,
|
||||||
parentBackgroundColor,
|
) { canPreview ->
|
||||||
showHidden,
|
NormalChannelCard(
|
||||||
accountViewModel,
|
baseNote = baseNote,
|
||||||
nav,
|
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
|
@Composable
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.note
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.clickable
|
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.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.layout.widthIn
|
import androidx.compose.foundation.layout.widthIn
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.distinctUntilChanged
|
|
||||||
import androidx.lifecycle.map
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.FeatureSetType
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
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.PrivateDmEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatroomMessageCompose(
|
fun ChatroomMessageCompose(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
@@ -108,111 +104,13 @@ fun ChatroomMessageCompose(
|
|||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
onWantsToReply: (Note) -> Unit,
|
onWantsToReply: (Note) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
WatchNoteEvent(baseNote = baseNote, accountViewModel = accountViewModel) {
|
||||||
|
WatchBlockAndReport(
|
||||||
Crossfade(targetState = hasEvent) {
|
note = baseNote,
|
||||||
if (it) {
|
showHiddenWarning = innerQuote,
|
||||||
CheckHiddenChatMessage(
|
accountViewModel = accountViewModel,
|
||||||
baseNote,
|
nav = nav,
|
||||||
routeForLastRead,
|
) { canPreview ->
|
||||||
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 }
|
|
||||||
}
|
|
||||||
|
|
||||||
NormalChatNote(
|
NormalChatNote(
|
||||||
baseNote,
|
baseNote,
|
||||||
routeForLastRead,
|
routeForLastRead,
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ fun MessageSetCompose(
|
|||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
routeForLastRead = null,
|
routeForLastRead = null,
|
||||||
isBoostedNote = true,
|
isBoostedNote = true,
|
||||||
showHidden = showHidden,
|
isHiddenFeed = showHidden,
|
||||||
quotesLeft = 1,
|
quotesLeft = 1,
|
||||||
parentBackgroundColor = backgroundColor,
|
parentBackgroundColor = backgroundColor,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ fun MultiSetCompose(
|
|||||||
routeForLastRead = null,
|
routeForLastRead = null,
|
||||||
modifier = HalfTopPadding,
|
modifier = HalfTopPadding,
|
||||||
isBoostedNote = true,
|
isBoostedNote = true,
|
||||||
showHidden = showHidden,
|
isHiddenFeed = showHidden,
|
||||||
quotesLeft = 1,
|
quotesLeft = 1,
|
||||||
parentBackgroundColor = backgroundColor,
|
parentBackgroundColor = backgroundColor,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.note
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
@@ -42,7 +41,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
import androidx.compose.ui.Modifier
|
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.graphics.compositeOver
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
||||||
import androidx.lifecycle.distinctUntilChanged
|
import androidx.lifecycle.distinctUntilChanged
|
||||||
import androidx.lifecycle.map
|
import androidx.lifecycle.map
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
@@ -176,7 +173,7 @@ fun NoteCompose(
|
|||||||
isQuotedNote: Boolean = false,
|
isQuotedNote: Boolean = false,
|
||||||
unPackReply: Boolean = true,
|
unPackReply: Boolean = true,
|
||||||
makeItShort: Boolean = false,
|
makeItShort: Boolean = false,
|
||||||
showHidden: Boolean = false,
|
isHiddenFeed: Boolean = false,
|
||||||
quotesLeft: Int,
|
quotesLeft: Int,
|
||||||
parentBackgroundColor: MutableState<Color>? = null,
|
parentBackgroundColor: MutableState<Color>? = null,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
@@ -185,13 +182,12 @@ fun NoteCompose(
|
|||||||
WatchNoteEvent(
|
WatchNoteEvent(
|
||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
showDivider = !isBoostedNote && !isQuotedNote,
|
|
||||||
modifier,
|
modifier,
|
||||||
) {
|
) {
|
||||||
CheckHiddenNoteCompose(
|
CheckHiddenFeedWatchBlockAndReport(
|
||||||
note = baseNote,
|
note = baseNote,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
showHidden = showHidden,
|
showHidden = isHiddenFeed,
|
||||||
showHiddenWarning = isQuotedNote || isBoostedNote,
|
showHiddenWarning = isQuotedNote || isBoostedNote,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav,
|
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
|
@Composable
|
||||||
fun AcceptableNote(
|
fun AcceptableNote(
|
||||||
baseNote: Note,
|
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.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.WatchIsHiddenUser
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
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.Size55dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||||
@@ -77,11 +75,11 @@ fun ZapNoteCompose(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val route = remember(baseAuthor) { "User/${baseAuthor?.pubkeyHex}" }
|
||||||
|
|
||||||
if (baseAuthor == null) {
|
if (baseAuthor == null) {
|
||||||
BlankNote()
|
BlankNote()
|
||||||
} else {
|
} else {
|
||||||
val route = remember(baseAuthor) { "User/${baseAuthor?.pubkeyHex}" }
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.clickable(
|
Modifier.clickable(
|
||||||
@@ -90,11 +88,6 @@ fun ZapNoteCompose(
|
|||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
) {
|
||||||
baseAuthor?.let { RenderZapNote(it, baseReqResponse.zapEvent, nav, accountViewModel) }
|
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(
|
BadgeCompose(
|
||||||
item,
|
item,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
showHidden = showHidden,
|
|
||||||
nav = nav,
|
nav = nav,
|
||||||
routeForLastRead = routeForLastRead,
|
routeForLastRead = routeForLastRead,
|
||||||
)
|
)
|
||||||
@@ -304,7 +303,7 @@ fun NoteCardCompose(
|
|||||||
isQuotedNote = isQuotedNote,
|
isQuotedNote = isQuotedNote,
|
||||||
unPackReply = unPackReply,
|
unPackReply = unPackReply,
|
||||||
makeItShort = makeItShort,
|
makeItShort = makeItShort,
|
||||||
showHidden = showHidden,
|
isHiddenFeed = showHidden,
|
||||||
quotesLeft = 3,
|
quotesLeft = 3,
|
||||||
parentBackgroundColor = parentBackgroundColor,
|
parentBackgroundColor = parentBackgroundColor,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
@@ -35,7 +36,9 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.vitorpamplona.amethyst.ui.note.ChatroomHeaderCompose
|
import com.vitorpamplona.amethyst.ui.note.ChatroomHeaderCompose
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
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.FeedPadding
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -109,6 +112,11 @@ private fun FeedLoaded(
|
|||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
modifier = StdTopPadding,
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ private fun FeedLoaded(
|
|||||||
routeForLastRead = routeForLastRead,
|
routeForLastRead = routeForLastRead,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
isBoostedNote = false,
|
isBoostedNote = false,
|
||||||
showHidden = state.showHidden.value,
|
isHiddenFeed = state.showHidden.value,
|
||||||
quotesLeft = 3,
|
quotesLeft = 3,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
|
|||||||
@@ -22,14 +22,19 @@ package com.vitorpamplona.amethyst.ui.screen
|
|||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapNoteCompose
|
import com.vitorpamplona.amethyst.ui.note.ZapNoteCompose
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
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.FeedPadding
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -72,6 +77,11 @@ private fun LnZapFeedLoaded(
|
|||||||
) {
|
) {
|
||||||
itemsIndexed(state.feed.value, key = { _, item -> item.zapEvent.idHex }) { _, item ->
|
itemsIndexed(state.feed.value, key = { _, item -> item.zapEvent.idHex }) { _, item ->
|
||||||
ZapNoteCompose(item, accountViewModel = accountViewModel, nav = nav)
|
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.Size15Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size24Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size24Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
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.ThemeComparisonColumn
|
||||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
@@ -288,11 +289,12 @@ fun ThreadFeedView(
|
|||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = DividerThickness,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
modifier = StdTopPadding,
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,10 +628,6 @@ fun NoteMaster(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactionsRow(note, true, editState, accountViewModel, nav)
|
ReactionsRow(note, true, editState, accountViewModel, nav)
|
||||||
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = DividerThickness,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteQuickActionMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
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.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.PagerState
|
import androidx.compose.foundation.pager.PagerState
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ScrollableTabRow
|
import androidx.compose.material3.ScrollableTabRow
|
||||||
import androidx.compose.material3.Tab
|
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.SaveableGridFeedState
|
||||||
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys
|
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys
|
||||||
import com.vitorpamplona.amethyst.ui.screen.rememberForeverPagerState
|
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.FeedPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
||||||
import com.vitorpamplona.quartz.events.ChannelCreateEvent
|
import com.vitorpamplona.quartz.events.ChannelCreateEvent
|
||||||
@@ -352,6 +354,10 @@ private fun DiscoverFeedLoaded(
|
|||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,6 +390,10 @@ private fun DiscoverFeedColumnsLoaded(
|
|||||||
nav = nav,
|
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.DividerThickness
|
||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import com.vitorpamplona.quartz.events.findHashtags
|
import com.vitorpamplona.quartz.events.findHashtags
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -401,6 +402,11 @@ private fun DisplaySearchResults(
|
|||||||
loadProfilePicture = automaticallyShowProfilePicture,
|
loadProfilePicture = automaticallyShowProfilePicture,
|
||||||
onClick = { nav("Channel/${item.idHex}") },
|
onClick = { nav("Channel/${item.idHex}") },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
modifier = StdTopPadding,
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsIndexed(
|
itemsIndexed(
|
||||||
|
|||||||
Reference in New Issue
Block a user