mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-09 04:18:11 +02:00
Migrates DVM route from pubkey to AppDefinition eventId and makes sure NFC reading will load the AppDefinition itself before rendering the rest of the screen.
This commit is contained in:
parent
d6988ad4e1
commit
72c6e93524
@ -229,7 +229,7 @@ fun AppNavigation(
|
||||
content = {
|
||||
it.arguments?.getString("id")?.let { id ->
|
||||
NIP90ContentDiscoveryScreen(
|
||||
dvmPublicKey = id,
|
||||
appDefinitionEventId = id,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
|
@ -34,8 +34,10 @@ import androidx.compose.foundation.layout.Spacer
|
||||
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.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
@ -60,11 +62,13 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
@ -73,6 +77,7 @@ import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import coil.Coil
|
||||
import coil.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
@ -97,6 +102,7 @@ import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
||||
import com.vitorpamplona.amethyst.service.NostrVideoDataSource
|
||||
import com.vitorpamplona.amethyst.service.relays.Client
|
||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.note.AmethystIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
|
||||
@ -106,6 +112,7 @@ import com.vitorpamplona.amethyst.ui.note.LoadChannel
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadCityName
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadUser
|
||||
import com.vitorpamplona.amethyst.ui.note.NonClickableUserPictures
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.SearchIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
@ -122,6 +129,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.LongRoomHeader
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.RoomNameOnlyDisplay
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ShortChannelHeader
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SpinnerSelectionDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.observeAppDefinition
|
||||
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||
@ -297,26 +305,34 @@ private fun RoomTopBar(
|
||||
|
||||
@Composable
|
||||
private fun DvmTopBar(
|
||||
id: String,
|
||||
appDefinitionId: String,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
navPopBack: () -> Unit,
|
||||
) {
|
||||
FlexibleTopBarWithBackButton(
|
||||
title = {
|
||||
LoadUser(baseUserHex = id, accountViewModel) { baseUser ->
|
||||
if (baseUser != null) {
|
||||
ClickableUserPicture(
|
||||
baseUser = baseUser,
|
||||
accountViewModel = accountViewModel,
|
||||
size = Size34dp,
|
||||
)
|
||||
LoadNote(baseNoteHex = appDefinitionId, accountViewModel = accountViewModel) { appDefinitionNote ->
|
||||
if (appDefinitionNote != null) {
|
||||
val card = observeAppDefinition(appDefinitionNote)
|
||||
|
||||
card.cover?.let {
|
||||
AsyncImage(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.size(Size34dp).clip(shape = CircleShape),
|
||||
)
|
||||
} ?: run { NoteAuthorPicture(baseNote = appDefinitionNote, size = Size34dp, accountViewModel = accountViewModel) }
|
||||
|
||||
Spacer(modifier = DoubleHorzSpacer)
|
||||
|
||||
UsernameDisplay(baseUser, Modifier.weight(1f), fontWeight = FontWeight.Normal)
|
||||
} else {
|
||||
Spacer(BottomTopHeight)
|
||||
Text(
|
||||
text = card.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -80,6 +80,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.EndedFlag
|
||||
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.observeAppDefinition
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||
@ -342,7 +343,9 @@ fun InnerRenderClassifiedsThumb(
|
||||
note: Note,
|
||||
) {
|
||||
Box(
|
||||
Modifier.fillMaxWidth().aspectRatio(1f),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1f),
|
||||
contentAlignment = BottomStart,
|
||||
) {
|
||||
card.image?.let {
|
||||
@ -355,7 +358,10 @@ fun InnerRenderClassifiedsThumb(
|
||||
} ?: run { DisplayAuthorBanner(note) }
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxWidth().background(Color.Black.copy(0.6f)).padding(Size5dp),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.background(Color.Black.copy(0.6f))
|
||||
.padding(Size5dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
card.title?.let {
|
||||
@ -451,14 +457,20 @@ fun RenderLiveActivityThumb(
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = TopEnd,
|
||||
modifier = Modifier.aspectRatio(ratio = 16f / 9f).fillMaxWidth(),
|
||||
modifier =
|
||||
Modifier
|
||||
.aspectRatio(ratio = 16f / 9f)
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
card.cover?.let {
|
||||
AsyncImage(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.fillMaxSize().clip(QuoteBorder),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.clip(QuoteBorder),
|
||||
)
|
||||
} ?: run { DisplayAuthorBanner(baseNote) }
|
||||
|
||||
@ -494,7 +506,9 @@ fun RenderLiveActivityThumb(
|
||||
|
||||
LoadParticipants(card.participants, baseNote, accountViewModel) { participantUsers ->
|
||||
Box(
|
||||
Modifier.padding(10.dp).align(BottomStart),
|
||||
Modifier
|
||||
.padding(10.dp)
|
||||
.align(BottomStart),
|
||||
) {
|
||||
if (participantUsers.isNotEmpty()) {
|
||||
Gallery(participantUsers, accountViewModel)
|
||||
@ -572,7 +586,10 @@ fun RenderCommunitiesThumb(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.fillMaxSize().clip(QuoteBorder),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.clip(QuoteBorder),
|
||||
)
|
||||
}
|
||||
} ?: run { DisplayAuthorBanner(baseNote) }
|
||||
@ -742,29 +759,7 @@ fun RenderContentDVMThumb(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteEvent = baseNote.event as? AppDefinitionEvent ?: return
|
||||
|
||||
val card by
|
||||
baseNote
|
||||
.live()
|
||||
.metadata
|
||||
.map {
|
||||
val noteEvent = it.note.event as? AppDefinitionEvent
|
||||
|
||||
DVMCard(
|
||||
name = noteEvent?.appMetaData()?.name ?: "",
|
||||
description = noteEvent?.appMetaData()?.about ?: "",
|
||||
cover = noteEvent?.appMetaData()?.image?.ifBlank { null },
|
||||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.observeAsState(
|
||||
DVMCard(
|
||||
name = noteEvent.appMetaData()?.name ?: "",
|
||||
description = noteEvent.appMetaData()?.about ?: "",
|
||||
cover = noteEvent.appMetaData()?.image?.ifBlank { null },
|
||||
),
|
||||
)
|
||||
val card = observeAppDefinition(appDefinitionNote = baseNote)
|
||||
|
||||
LeftPictureLayout(
|
||||
onImage = {
|
||||
@ -774,7 +769,10 @@ fun RenderContentDVMThumb(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.fillMaxSize().clip(QuoteBorder),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.clip(QuoteBorder),
|
||||
)
|
||||
}
|
||||
} ?: run { DisplayAuthorBanner(baseNote) }
|
||||
@ -788,7 +786,7 @@ fun RenderContentDVMThumb(
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = RowColSpacing,
|
||||
@ -895,7 +893,10 @@ fun RenderChannelThumb(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.fillMaxSize().clip(QuoteBorder),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.clip(QuoteBorder),
|
||||
)
|
||||
} ?: run { DisplayAuthorBanner(baseNote) }
|
||||
},
|
||||
@ -970,6 +971,11 @@ fun Gallery(
|
||||
@Composable
|
||||
fun DisplayAuthorBanner(note: Note) {
|
||||
WatchAuthor(note) {
|
||||
BannerImage(it, Modifier.fillMaxSize().clip(QuoteBorder))
|
||||
BannerImage(
|
||||
it,
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.clip(QuoteBorder),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,33 @@ fun WatchNoteEvent(
|
||||
accountViewModel: AccountViewModel,
|
||||
modifier: Modifier = Modifier,
|
||||
onNoteEventFound: @Composable () -> Unit,
|
||||
) {
|
||||
WatchNoteEvent(
|
||||
baseNote,
|
||||
onNoteEventFound,
|
||||
onBlank = {
|
||||
LongPressToQuickAction(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
) { showPopup ->
|
||||
BlankNote(
|
||||
remember {
|
||||
modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchNoteEvent(
|
||||
baseNote: Note,
|
||||
onNoteEventFound: @Composable () -> Unit,
|
||||
onBlank: @Composable () -> Unit,
|
||||
) {
|
||||
if (baseNote.event != null) {
|
||||
onNoteEventFound()
|
||||
@ -49,19 +76,7 @@ fun WatchNoteEvent(
|
||||
if (it) {
|
||||
onNoteEventFound()
|
||||
} else {
|
||||
LongPressToQuickAction(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
) { showPopup ->
|
||||
BlankNote(
|
||||
remember {
|
||||
modifier.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = showPopup,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
onBlank()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@ -36,45 +37,77 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadUser
|
||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||
import com.vitorpamplona.amethyst.ui.note.DVMCard
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.WatchNoteEvent
|
||||
import com.vitorpamplona.amethyst.ui.screen.FeedEmpty
|
||||
import com.vitorpamplona.amethyst.ui.screen.NostrNIP90ContentDiscoveryFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.ui.screen.RenderFeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size75dp
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.events.AppDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.NIP90ContentDiscoveryResponseEvent
|
||||
import com.vitorpamplona.quartz.events.NIP90StatusEvent
|
||||
|
||||
@Composable
|
||||
fun NIP90ContentDiscoveryScreen(
|
||||
dvmPublicKey: String,
|
||||
appDefinitionEventId: String,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
LoadNote(baseNoteHex = appDefinitionEventId, accountViewModel = accountViewModel) {
|
||||
it?.let { baseNote ->
|
||||
WatchNoteEvent(
|
||||
baseNote,
|
||||
onNoteEventFound = {
|
||||
NIP90ContentDiscoveryScreen(baseNote, accountViewModel, nav)
|
||||
},
|
||||
onBlank = {
|
||||
FeedEmptywithStatus(baseNote, stringResource(R.string.dvm_looking_for_app), accountViewModel, nav)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NIP90ContentDiscoveryScreen(
|
||||
appDefinition: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteAuthor = appDefinition.author ?: return
|
||||
|
||||
var requestEventID by
|
||||
remember(dvmPublicKey) {
|
||||
remember(appDefinition) {
|
||||
mutableStateOf<Note?>(null)
|
||||
}
|
||||
|
||||
val onRefresh = {
|
||||
accountViewModel.requestDVMContentDiscovery(dvmPublicKey) {
|
||||
accountViewModel.requestDVMContentDiscovery(noteAuthor.pubkeyHex) {
|
||||
requestEventID = it
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = dvmPublicKey) {
|
||||
LaunchedEffect(key1 = appDefinition) {
|
||||
onRefresh()
|
||||
}
|
||||
|
||||
@ -84,7 +117,7 @@ fun NIP90ContentDiscoveryScreen(
|
||||
val myRequestEventID = requestEventID
|
||||
if (myRequestEventID != null) {
|
||||
ObserverContentDiscoveryResponse(
|
||||
dvmPublicKey,
|
||||
appDefinition,
|
||||
myRequestEventID,
|
||||
onRefresh,
|
||||
accountViewModel,
|
||||
@ -92,19 +125,20 @@ fun NIP90ContentDiscoveryScreen(
|
||||
)
|
||||
} else {
|
||||
// TODO: Make a good splash screen with loading animation for this DVM.
|
||||
FeedEmptywithStatus(dvmPublicKey, stringResource(R.string.dvm_requesting_job), accountViewModel, nav)
|
||||
FeedEmptywithStatus(appDefinition, stringResource(R.string.dvm_requesting_job), accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ObserverContentDiscoveryResponse(
|
||||
dvmPublicKey: String,
|
||||
appDefinition: Note,
|
||||
dvmRequestId: Note,
|
||||
onRefresh: () -> Unit,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteAuthor = appDefinition.author ?: return
|
||||
val updateFiltersFromRelays = dvmRequestId.live().metadata.observeAsState()
|
||||
|
||||
val resultFlow =
|
||||
@ -116,7 +150,7 @@ fun ObserverContentDiscoveryResponse(
|
||||
|
||||
if (latestResponse != null) {
|
||||
PrepareViewContentDiscoveryModels(
|
||||
dvmPublicKey,
|
||||
noteAuthor,
|
||||
dvmRequestId.idHex,
|
||||
onRefresh,
|
||||
accountViewModel,
|
||||
@ -124,7 +158,7 @@ fun ObserverContentDiscoveryResponse(
|
||||
)
|
||||
} else {
|
||||
ObserverDvmStatusResponse(
|
||||
dvmPublicKey,
|
||||
appDefinition,
|
||||
dvmRequestId.idHex,
|
||||
accountViewModel,
|
||||
nav,
|
||||
@ -134,7 +168,7 @@ fun ObserverContentDiscoveryResponse(
|
||||
|
||||
@Composable
|
||||
fun ObserverDvmStatusResponse(
|
||||
dvmPublicKey: String,
|
||||
appDefinition: Note,
|
||||
dvmRequestId: String,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
@ -149,17 +183,17 @@ fun ObserverDvmStatusResponse(
|
||||
if (latestStatus != null) {
|
||||
// TODO: Make a good splash screen with loading animation for this DVM.
|
||||
latestStatus?.let {
|
||||
FeedEmptywithStatus(dvmPublicKey, it.content(), accountViewModel, nav)
|
||||
FeedEmptywithStatus(appDefinition, it.content(), accountViewModel, nav)
|
||||
}
|
||||
} else {
|
||||
// TODO: Make a good splash screen with loading animation for this DVM.
|
||||
FeedEmptywithStatus(dvmPublicKey, stringResource(R.string.dvm_waiting_status), accountViewModel, nav)
|
||||
FeedEmptywithStatus(appDefinition, stringResource(R.string.dvm_waiting_status), accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PrepareViewContentDiscoveryModels(
|
||||
dvmPublicKey: String,
|
||||
dvm: User,
|
||||
dvmRequestId: String,
|
||||
onRefresh: () -> Unit,
|
||||
accountViewModel: AccountViewModel,
|
||||
@ -167,8 +201,8 @@ fun PrepareViewContentDiscoveryModels(
|
||||
) {
|
||||
val resultFeedViewModel: NostrNIP90ContentDiscoveryFeedViewModel =
|
||||
viewModel(
|
||||
key = "NostrNIP90ContentDiscoveryFeedViewModel$dvmPublicKey$dvmRequestId",
|
||||
factory = NostrNIP90ContentDiscoveryFeedViewModel.Factory(accountViewModel.account, dvmkey = dvmPublicKey, requestid = dvmRequestId),
|
||||
key = "NostrNIP90ContentDiscoveryFeedViewModel${dvm.pubkeyHex}$dvmRequestId",
|
||||
factory = NostrNIP90ContentDiscoveryFeedViewModel.Factory(accountViewModel.account, dvmkey = dvm.pubkeyHex, requestid = dvmRequestId),
|
||||
)
|
||||
|
||||
LaunchedEffect(key1 = dvmRequestId) {
|
||||
@ -210,7 +244,7 @@ fun RenderNostrNIP90ContentDiscoveryScreen(
|
||||
|
||||
@Composable
|
||||
fun FeedEmptywithStatus(
|
||||
pubkey: HexKey,
|
||||
appDefinitionNote: Note,
|
||||
status: String,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
@ -222,22 +256,62 @@ fun FeedEmptywithStatus(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
LoadUser(baseUserHex = pubkey, accountViewModel = accountViewModel) { baseUser ->
|
||||
if (baseUser != null) {
|
||||
ClickableUserPicture(
|
||||
baseUser = baseUser,
|
||||
accountViewModel = accountViewModel,
|
||||
size = Size75dp,
|
||||
)
|
||||
val card = observeAppDefinition(appDefinitionNote)
|
||||
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
card.cover?.let {
|
||||
AsyncImage(
|
||||
model = it,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.size(Size75dp).clip(QuoteBorder),
|
||||
)
|
||||
} ?: run { NoteAuthorPicture(appDefinitionNote, nav, accountViewModel, Size75dp) }
|
||||
|
||||
UsernameDisplay(baseUser, Modifier, fontWeight = FontWeight.Normal)
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = card.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
|
||||
Text(status)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun observeAppDefinition(appDefinitionNote: Note): DVMCard {
|
||||
val noteEvent =
|
||||
appDefinitionNote.event as? AppDefinitionEvent ?: return DVMCard(
|
||||
name = "",
|
||||
description = "",
|
||||
cover = null,
|
||||
)
|
||||
|
||||
val card by
|
||||
appDefinitionNote
|
||||
.live()
|
||||
.metadata
|
||||
.map {
|
||||
val noteEvent = it.note.event as? AppDefinitionEvent
|
||||
|
||||
DVMCard(
|
||||
name = noteEvent?.appMetaData()?.name ?: "",
|
||||
description = noteEvent?.appMetaData()?.about ?: "",
|
||||
cover = noteEvent?.appMetaData()?.image?.ifBlank { null },
|
||||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.observeAsState(
|
||||
DVMCard(
|
||||
name = noteEvent.appMetaData()?.name ?: "",
|
||||
description = noteEvent.appMetaData()?.about ?: "",
|
||||
cover = noteEvent.appMetaData()?.image?.ifBlank { null },
|
||||
),
|
||||
)
|
||||
|
||||
return card
|
||||
}
|
||||
|
@ -847,6 +847,7 @@
|
||||
|
||||
<string name="load_from_text">From Msg</string>
|
||||
|
||||
<string name="dvm_looking_for_app">Looking for Application</string>
|
||||
<string name="dvm_waiting_status">Job Requested, waiting for a reply</string>
|
||||
<string name="dvm_requesting_job">Requesting Job from DVM</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user