Loading Users and Notes in Launched Effects only because of @Synchronized in the getOrCreate methods in LocalCache
This commit is contained in:
@@ -820,7 +820,7 @@ class Account(
|
|||||||
return if (event is PrivateDmEvent && loggedIn.privKey != null) {
|
return if (event is PrivateDmEvent && loggedIn.privKey != null) {
|
||||||
var pubkeyToUse = event.pubKey
|
var pubkeyToUse = event.pubKey
|
||||||
|
|
||||||
val recepientPK = event.recipientPubKey()
|
val recepientPK = event.verifiedRecipientPubKey()
|
||||||
|
|
||||||
if (note.author == userProfile() && recepientPK != null) {
|
if (note.author == userProfile() && recepientPK != null) {
|
||||||
pubkeyToUse = recepientPK
|
pubkeyToUse = recepientPK
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ object LocalCache {
|
|||||||
// Already processed this event.
|
// Already processed this event.
|
||||||
if (note.event != null) return
|
if (note.event != null) return
|
||||||
|
|
||||||
val recipient = event.recipientPubKey()?.let { getOrCreateUser(it) }
|
val recipient = event.verifiedRecipientPubKey()?.let { getOrCreateUser(it) }
|
||||||
|
|
||||||
// Log.d("PM", "${author.toBestDisplayName()} to ${recipient?.toBestDisplayName()}")
|
// Log.d("PM", "${author.toBestDisplayName()} to ${recipient?.toBestDisplayName()}")
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ object LocalCache {
|
|||||||
|
|
||||||
if (deleteNote.event is PrivateDmEvent) {
|
if (deleteNote.event is PrivateDmEvent) {
|
||||||
val author = deleteNote.author
|
val author = deleteNote.author
|
||||||
val recipient = (deleteNote.event as? PrivateDmEvent)?.recipientPubKey()?.let { checkGetOrCreateUser(it) }
|
val recipient = (deleteNote.event as? PrivateDmEvent)?.verifiedRecipientPubKey()?.let { checkGetOrCreateUser(it) }
|
||||||
|
|
||||||
if (recipient != null && author != null) {
|
if (recipient != null && author != null) {
|
||||||
author.removeMessage(recipient, deleteNote)
|
author.removeMessage(recipient, deleteNote)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import kotlin.time.measureTimedValue
|
|||||||
|
|
||||||
class ThreadAssembler {
|
class ThreadAssembler {
|
||||||
|
|
||||||
fun searchRoot(note: Note, testedNotes: MutableSet<Note> = mutableSetOf()): Note? {
|
private fun searchRoot(note: Note, testedNotes: MutableSet<Note> = mutableSetOf()): Note? {
|
||||||
if (note.replyTo == null || note.replyTo?.isEmpty() == true) return note
|
if (note.replyTo == null || note.replyTo?.isEmpty() == true) return note
|
||||||
|
|
||||||
testedNotes.add(note)
|
testedNotes.add(note)
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun getOrCreatePrivateChatroom(user: User): Chatroom {
|
private fun getOrCreatePrivateChatroom(user: User): Chatroom {
|
||||||
return privateChatrooms[user] ?: run {
|
return privateChatrooms[user] ?: run {
|
||||||
val privateChatroom = Chatroom(setOf<Note>())
|
val privateChatroom = Chatroom(setOf<Note>())
|
||||||
privateChatrooms = privateChatrooms + Pair(user, privateChatroom)
|
privateChatrooms = privateChatrooms + Pair(user, privateChatroom)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.vitorpamplona.amethyst.service
|
package com.vitorpamplona.amethyst.service
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.model.*
|
import com.vitorpamplona.amethyst.service.model.*
|
||||||
import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
|
import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
|
||||||
@@ -10,13 +9,8 @@ import com.vitorpamplona.amethyst.service.relays.TypedFilter
|
|||||||
object NostrUserProfileDataSource : NostrDataSource("UserProfileFeed") {
|
object NostrUserProfileDataSource : NostrDataSource("UserProfileFeed") {
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(userId: String?) {
|
fun loadUserProfile(user: User?) {
|
||||||
if (userId != null) {
|
this.user = user
|
||||||
user = LocalCache.getOrCreateUser(userId)
|
|
||||||
} else {
|
|
||||||
user = null
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFilters()
|
resetFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ class PrivateDmEvent(
|
|||||||
* nip-04 EncryptedDmEvent but may omit the recipient, too. This value can be queried and used
|
* nip-04 EncryptedDmEvent but may omit the recipient, too. This value can be queried and used
|
||||||
* for initial messages.
|
* for initial messages.
|
||||||
*/
|
*/
|
||||||
fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.run { Hex.decode(this[1]).toHexKey() } // makes sure its a valid one
|
fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }
|
||||||
|
|
||||||
|
fun recipientPubKeyBytes() = recipientPubKey()?.runCatching { Hex.decode(this[1]) }?.getOrNull()
|
||||||
|
|
||||||
|
fun verifiedRecipientPubKey() = recipientPubKey()?.runCatching { Hex.decode(this[1]).toHexKey() }?.getOrNull() // makes sure its a valid one
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be fully compatible with nip-04, we read e-tags that are in violation to nip-18.
|
* To be fully compatible with nip-04, we read e-tags that are in violation to nip-18.
|
||||||
|
|||||||
@@ -5,15 +5,23 @@ import androidx.compose.material.LocalTextStyle
|
|||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
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.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
||||||
import com.vitorpamplona.amethyst.service.nip19.Nip19
|
import com.vitorpamplona.amethyst.service.nip19.Nip19
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ClickableRoute(
|
fun ClickableRoute(
|
||||||
@@ -21,56 +29,190 @@ fun ClickableRoute(
|
|||||||
navController: NavController
|
navController: NavController
|
||||||
) {
|
) {
|
||||||
if (nip19.type == Nip19.Type.USER) {
|
if (nip19.type == Nip19.Type.USER) {
|
||||||
val userBase = LocalCache.getOrCreateUser(nip19.hex)
|
DisplayUser(nip19, navController)
|
||||||
|
|
||||||
val userState by userBase.live().metadata.observeAsState()
|
|
||||||
val user = userState?.user ?: return
|
|
||||||
|
|
||||||
CreateClickableText(user.toBestDisplayName(), nip19.additionalChars, "User/${nip19.hex}", navController)
|
|
||||||
} else if (nip19.type == Nip19.Type.ADDRESS) {
|
} else if (nip19.type == Nip19.Type.ADDRESS) {
|
||||||
val noteBase = LocalCache.checkGetOrCreateAddressableNote(nip19.hex)
|
DisplayAddress(nip19, navController)
|
||||||
|
} else if (nip19.type == Nip19.Type.NOTE) {
|
||||||
|
DisplayNote(nip19, navController)
|
||||||
|
} else if (nip19.type == Nip19.Type.EVENT) {
|
||||||
|
DisplayEvent(nip19, navController)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
"@${nip19.hex}${nip19.additionalChars} "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (noteBase == null) {
|
@Composable
|
||||||
Text(
|
private fun DisplayEvent(
|
||||||
"@${nip19.hex}${nip19.additionalChars} "
|
nip19: Nip19.Return,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
var noteBase by remember { mutableStateOf<Note?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = nip19.hex) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
noteBase = LocalCache.checkGetOrCreateNote(nip19.hex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
noteBase?.let {
|
||||||
|
val noteState by it.live().metadata.observeAsState()
|
||||||
|
val note = noteState?.note ?: return
|
||||||
|
val channel = note.channel()
|
||||||
|
|
||||||
|
if (note.event is ChannelCreateEvent) {
|
||||||
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Channel/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
} else if (note.event is PrivateDmEvent) {
|
||||||
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Room/${note.author?.pubkeyHex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
} else if (channel != null) {
|
||||||
|
CreateClickableText(
|
||||||
|
channel.toBestDisplayName(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Channel/${note.channel()?.idHex}",
|
||||||
|
navController
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val noteState by noteBase.live().metadata.observeAsState()
|
CreateClickableText(
|
||||||
val note = noteState?.note ?: return
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Note/${nip19.hex}", navController)
|
"Event/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if (nip19.type == Nip19.Type.NOTE) {
|
}
|
||||||
val noteBase = LocalCache.getOrCreateNote(nip19.hex)
|
|
||||||
val noteState by noteBase.live().metadata.observeAsState()
|
if (noteBase == null) {
|
||||||
|
Text(
|
||||||
|
"@${nip19.hex}${nip19.additionalChars} "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DisplayNote(
|
||||||
|
nip19: Nip19.Return,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
var noteBase by remember { mutableStateOf<Note?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = nip19.hex) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
noteBase = LocalCache.checkGetOrCreateNote(nip19.hex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
noteBase?.let {
|
||||||
|
val noteState by it.live().metadata.observeAsState()
|
||||||
val note = noteState?.note ?: return
|
val note = noteState?.note ?: return
|
||||||
val channel = note.channel()
|
val channel = note.channel()
|
||||||
|
|
||||||
if (note.event is ChannelCreateEvent) {
|
if (note.event is ChannelCreateEvent) {
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Channel/${nip19.hex}", navController)
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Channel/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
} else if (note.event is PrivateDmEvent) {
|
} else if (note.event is PrivateDmEvent) {
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Room/${note.author?.pubkeyHex}", navController)
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Room/${note.author?.pubkeyHex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
} else if (channel != null) {
|
} else if (channel != null) {
|
||||||
CreateClickableText(channel.toBestDisplayName(), nip19.additionalChars, "Channel/${note.channel()?.idHex}", navController)
|
CreateClickableText(
|
||||||
|
channel.toBestDisplayName(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Channel/${note.channel()?.idHex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Note/${nip19.hex}", navController)
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Note/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if (nip19.type == Nip19.Type.EVENT) {
|
}
|
||||||
val noteBase = LocalCache.getOrCreateNote(nip19.hex)
|
|
||||||
val noteState by noteBase.live().metadata.observeAsState()
|
|
||||||
val note = noteState?.note ?: return
|
|
||||||
val channel = note.channel()
|
|
||||||
|
|
||||||
if (note.event is ChannelCreateEvent) {
|
if (noteBase == null) {
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Channel/${nip19.hex}", navController)
|
Text(
|
||||||
} else if (note.event is PrivateDmEvent) {
|
"@${nip19.hex}${nip19.additionalChars} "
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Room/${note.author?.pubkeyHex}", navController)
|
)
|
||||||
} else if (channel != null) {
|
}
|
||||||
CreateClickableText(channel.toBestDisplayName(), nip19.additionalChars, "Channel/${note.channel()?.idHex}", navController)
|
}
|
||||||
} else {
|
|
||||||
CreateClickableText(note.idDisplayNote(), nip19.additionalChars, "Event/${nip19.hex}", navController)
|
@Composable
|
||||||
|
private fun DisplayAddress(
|
||||||
|
nip19: Nip19.Return,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
var noteBase by remember { mutableStateOf<Note?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = nip19.hex) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
noteBase = LocalCache.checkGetOrCreateAddressableNote(nip19.hex)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
noteBase?.let {
|
||||||
|
val noteState by it.live().metadata.observeAsState()
|
||||||
|
val note = noteState?.note ?: return
|
||||||
|
|
||||||
|
CreateClickableText(
|
||||||
|
note.idDisplayNote(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"Note/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noteBase == null) {
|
||||||
|
Text(
|
||||||
|
"@${nip19.hex}${nip19.additionalChars} "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DisplayUser(
|
||||||
|
nip19: Nip19.Return,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
var userBase by remember { mutableStateOf<User?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = nip19.hex) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
userBase = LocalCache.checkGetOrCreateUser(nip19.hex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userBase?.let {
|
||||||
|
val userState by it.live().metadata.observeAsState()
|
||||||
|
val user = userState?.user ?: return
|
||||||
|
|
||||||
|
CreateClickableText(
|
||||||
|
user.toBestDisplayName(),
|
||||||
|
nip19.additionalChars,
|
||||||
|
"User/${nip19.hex}",
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userBase == null) {
|
||||||
Text(
|
Text(
|
||||||
"@${nip19.hex}${nip19.additionalChars} "
|
"@${nip19.hex}${nip19.additionalChars} "
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ import java.io.File
|
|||||||
public var muted = mutableStateOf(true)
|
public var muted = mutableStateOf(true)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoView(localFile: File, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) {
|
fun VideoView(localFile: File?, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) {
|
||||||
VideoView(localFile.toUri(), description, onDialog)
|
if (localFile != null) {
|
||||||
|
VideoView(localFile.toUri(), description, onDialog)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class ZoomableUrlVideo(
|
|||||||
) : ZoomableUrlContent(url, description, hash, dim, uri)
|
) : ZoomableUrlContent(url, description, hash, dim, uri)
|
||||||
|
|
||||||
abstract class ZoomablePreloadedContent(
|
abstract class ZoomablePreloadedContent(
|
||||||
val localFile: File,
|
val localFile: File?,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
val mimeType: String? = null,
|
val mimeType: String? = null,
|
||||||
val isVerified: Boolean? = null,
|
val isVerified: Boolean? = null,
|
||||||
@@ -120,7 +120,7 @@ abstract class ZoomablePreloadedContent(
|
|||||||
) : ZoomableContent(description, dim)
|
) : ZoomableContent(description, dim)
|
||||||
|
|
||||||
class ZoomableLocalImage(
|
class ZoomableLocalImage(
|
||||||
localFile: File,
|
localFile: File?,
|
||||||
mimeType: String? = null,
|
mimeType: String? = null,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
val blurhash: String? = null,
|
val blurhash: String? = null,
|
||||||
@@ -130,7 +130,7 @@ class ZoomableLocalImage(
|
|||||||
) : ZoomablePreloadedContent(localFile, description, mimeType, isVerified, dim, uri)
|
) : ZoomablePreloadedContent(localFile, description, mimeType, isVerified, dim, uri)
|
||||||
|
|
||||||
class ZoomableLocalVideo(
|
class ZoomableLocalVideo(
|
||||||
localFile: File,
|
localFile: File?,
|
||||||
mimeType: String? = null,
|
mimeType: String? = null,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
dim: String? = null,
|
dim: String? = null,
|
||||||
@@ -219,7 +219,7 @@ private fun LocalImageView(
|
|||||||
}
|
}
|
||||||
val contentScale = if (maxHeight.isFinite) ContentScale.Fit else ContentScale.FillWidth
|
val contentScale = if (maxHeight.isFinite) ContentScale.Fit else ContentScale.FillWidth
|
||||||
|
|
||||||
if (content.localFile.exists()) {
|
if (content.localFile != null && content.localFile.exists()) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = content.localFile,
|
model = content.localFile,
|
||||||
contentDescription = content.description,
|
contentDescription = content.description,
|
||||||
@@ -246,7 +246,7 @@ private fun LocalImageView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageState is AsyncImagePainter.State.Error || !content.localFile.exists()) {
|
if (imageState is AsyncImagePainter.State.Error || content.localFile == null || !content.localFile.exists()) {
|
||||||
BlankNote()
|
BlankNote()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -9,9 +9,9 @@ object UserProfileBookmarksFeedFilter : FeedFilter<Note>() {
|
|||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, userId: String) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
user = LocalCache.users[userId]
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
|
|||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.dal
|
package com.vitorpamplona.amethyst.ui.dal
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
|
|
||||||
@@ -9,9 +8,9 @@ object UserProfileConversationsFeedFilter : FeedFilter<Note>() {
|
|||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, userId: String) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
user = LocalCache.checkGetOrCreateUser(userId)
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
|
|||||||
+2
-2
@@ -8,9 +8,9 @@ object UserProfileFollowersFeedFilter : FeedFilter<User>() {
|
|||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, userId: String) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
user = LocalCache.users[userId]
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ object UserProfileFollowsFeedFilter : FeedFilter<User>() {
|
|||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, userId: String) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
user = LocalCache.users[userId]
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
|
|||||||
+2
-2
@@ -9,9 +9,9 @@ object UserProfileNewThreadFeedFilter : FeedFilter<Note>() {
|
|||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, userId: String) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
user = LocalCache.checkGetOrCreateUser(userId)
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.dal
|
package com.vitorpamplona.amethyst.ui.dal
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
|
|
||||||
object UserProfileReportsFeedFilter : FeedFilter<Note>() {
|
object UserProfileReportsFeedFilter : FeedFilter<Note>() {
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(userId: String) {
|
fun loadUserProfile(user: User?) {
|
||||||
user = LocalCache.checkGetOrCreateUser(userId)
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.dal
|
package com.vitorpamplona.amethyst.ui.dal
|
||||||
|
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
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.service.model.zaps.UserZaps
|
import com.vitorpamplona.amethyst.service.model.zaps.UserZaps
|
||||||
@@ -8,8 +7,8 @@ import com.vitorpamplona.amethyst.service.model.zaps.UserZaps
|
|||||||
object UserProfileZapsFeedFilter : FeedFilter<Pair<Note, Note>>() {
|
object UserProfileZapsFeedFilter : FeedFilter<Pair<Note, Note>>() {
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
fun loadUserProfile(userId: String) {
|
fun loadUserProfile(user: User?) {
|
||||||
user = LocalCache.checkGetOrCreateUser(userId)
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feed(): List<Pair<Note, Note>> {
|
override fun feed(): List<Pair<Note, Note>> {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ fun ChatroomCompose(
|
|||||||
} else {
|
} else {
|
||||||
val replyAuthorBase =
|
val replyAuthorBase =
|
||||||
(note.event as? PrivateDmEvent)
|
(note.event as? PrivateDmEvent)
|
||||||
?.recipientPubKey()
|
?.verifiedRecipientPubKey()
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
?.let { LocalCache.getOrCreateUser(it) }
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
var userToComposeOn = note.author!!
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|||||||
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.EventInterface
|
import com.vitorpamplona.amethyst.service.model.EventInterface
|
||||||
import com.vitorpamplona.amethyst.service.model.FileHeaderEvent
|
import com.vitorpamplona.amethyst.service.model.FileHeaderEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.FileStorageEvent
|
|
||||||
import com.vitorpamplona.amethyst.service.model.FileStorageHeaderEvent
|
import com.vitorpamplona.amethyst.service.model.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.HighlightEvent
|
import com.vitorpamplona.amethyst.service.model.HighlightEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.LongTextNoteEvent
|
import com.vitorpamplona.amethyst.service.model.LongTextNoteEvent
|
||||||
@@ -122,6 +121,7 @@ import com.vitorpamplona.amethyst.ui.theme.Following
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import nostr.postr.toNpub
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@@ -387,7 +387,7 @@ fun routeFor(note: Note, loggedIn: User): String? {
|
|||||||
} else if (noteEvent is PrivateDmEvent) {
|
} else if (noteEvent is PrivateDmEvent) {
|
||||||
val replyAuthorBase =
|
val replyAuthorBase =
|
||||||
(note.event as? PrivateDmEvent)
|
(note.event as? PrivateDmEvent)
|
||||||
?.recipientPubKey()
|
?.verifiedRecipientPubKey()
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
?.let { LocalCache.getOrCreateUser(it) }
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
var userToComposeOn = note.author!!
|
||||||
@@ -573,13 +573,13 @@ private fun RenderPrivateMessage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val recipient = noteEvent.recipientPubKey()?.let { LocalCache.checkGetOrCreateUser(it) }
|
val recipient = noteEvent.recipientPubKeyBytes()?.toNpub() ?: "Someone"
|
||||||
|
|
||||||
TranslatableRichTextViewer(
|
TranslatableRichTextViewer(
|
||||||
stringResource(
|
stringResource(
|
||||||
id = R.string.private_conversation_notification,
|
id = R.string.private_conversation_notification,
|
||||||
"@${note.author?.pubkeyNpub()}",
|
"@${note.author?.pubkeyNpub()}",
|
||||||
"@${recipient?.pubkeyNpub()}"
|
"@$recipient"
|
||||||
),
|
),
|
||||||
canPreview = !makeItShort,
|
canPreview = !makeItShort,
|
||||||
Modifier.fillMaxWidth(),
|
Modifier.fillMaxWidth(),
|
||||||
@@ -797,13 +797,8 @@ private fun ReplyRow(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
} else if (noteEvent is ChannelMessageEvent && (note.replyTo != null || noteEvent.hasAnyTaggedUser())) {
|
} else if (noteEvent is ChannelMessageEvent && (note.replyTo != null || noteEvent.hasAnyTaggedUser())) {
|
||||||
val sortedMentions = noteEvent.mentions()
|
|
||||||
.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
|
||||||
.toSet()
|
|
||||||
.sortedBy { account.isFollowing(it) }
|
|
||||||
|
|
||||||
note.channel()?.let {
|
note.channel()?.let {
|
||||||
ReplyInformationChannel(note.replyTo, sortedMentions, it, navController)
|
ReplyInformationChannel(note.replyTo, noteEvent.mentions(), it, account, navController)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
@@ -1016,11 +1011,19 @@ fun DisplayHighlight(
|
|||||||
navController
|
navController
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var userBase by remember { mutableStateOf<User?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
if (authorHex != null) {
|
||||||
|
userBase = LocalCache.checkGetOrCreateUser(authorHex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlowRow() {
|
FlowRow() {
|
||||||
authorHex?.let { authorHex ->
|
authorHex?.let { authorHex ->
|
||||||
val userBase = LocalCache.checkGetOrCreateUser(authorHex)
|
userBase?.let { userBase ->
|
||||||
|
|
||||||
if (userBase != null) {
|
|
||||||
val userState by userBase.live().metadata.observeAsState()
|
val userState by userBase.live().metadata.observeAsState()
|
||||||
val user = userState?.user
|
val user = userState?.user
|
||||||
|
|
||||||
@@ -1307,20 +1310,23 @@ fun FileStorageHeaderDisplay(baseNote: Note) {
|
|||||||
val appContext = LocalContext.current.applicationContext
|
val appContext = LocalContext.current.applicationContext
|
||||||
val eventHeader = (baseNote.event as? FileStorageHeaderEvent) ?: return
|
val eventHeader = (baseNote.event as? FileStorageHeaderEvent) ?: return
|
||||||
|
|
||||||
val fileNote = eventHeader.dataEventId()?.let { LocalCache.checkGetOrCreateNote(it) } ?: return
|
var fileNote by remember { mutableStateOf<Note?>(null) }
|
||||||
|
|
||||||
val noteState by fileNote.live().metadata.observeAsState()
|
LaunchedEffect(key1 = eventHeader.id) {
|
||||||
val note = noteState?.note
|
withContext(Dispatchers.IO) {
|
||||||
|
fileNote = eventHeader.dataEventId()?.let { LocalCache.checkGetOrCreateNote(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val eventBytes = (note?.event as? FileStorageEvent)
|
val noteState = fileNote?.live()?.metadata?.observeAsState()
|
||||||
|
val note = noteState?.value?.note
|
||||||
|
|
||||||
var content by remember { mutableStateOf<ZoomableContent?>(null) }
|
var content by remember { mutableStateOf<ZoomableContent?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(key1 = eventHeader.id, key2 = noteState) {
|
LaunchedEffect(key1 = eventHeader.id, key2 = noteState, key3 = note?.event) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val uri = "nostr:" + baseNote.toNEvent()
|
val uri = "nostr:" + baseNote.toNEvent()
|
||||||
val localDir = File(File(appContext.externalCacheDir, "NIP95"), fileNote.idHex)
|
val localDir = note?.idHex?.let { File(File(appContext.externalCacheDir, "NIP95"), it) }
|
||||||
val bytes = eventBytes?.decode()
|
|
||||||
val blurHash = eventHeader.blurhash()
|
val blurHash = eventHeader.blurhash()
|
||||||
val dimensions = eventHeader.dimensions()
|
val dimensions = eventHeader.dimensions()
|
||||||
val description = eventHeader.content
|
val description = eventHeader.content
|
||||||
@@ -1337,18 +1343,14 @@ fun FileStorageHeaderDisplay(baseNote: Note) {
|
|||||||
uri = uri
|
uri = uri
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (bytes != null) {
|
ZoomableLocalVideo(
|
||||||
ZoomableLocalVideo(
|
localFile = localDir,
|
||||||
localFile = localDir,
|
mimeType = mimeType,
|
||||||
mimeType = mimeType,
|
description = description,
|
||||||
description = description,
|
dim = dimensions,
|
||||||
dim = dimensions,
|
isVerified = true,
|
||||||
isVerified = true,
|
uri = uri
|
||||||
uri = uri
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.compose.material.LocalTextStyle
|
|||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
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
|
||||||
@@ -17,13 +18,23 @@ import androidx.navigation.NavController
|
|||||||
import com.google.accompanist.flowlayout.FlowRow
|
import com.google.accompanist.flowlayout.FlowRow
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.*
|
import com.vitorpamplona.amethyst.model.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReplyInformation(replyTo: List<Note>?, mentions: List<String>, account: Account, navController: NavController) {
|
fun ReplyInformation(replyTo: List<Note>?, mentions: List<String>, account: Account, navController: NavController) {
|
||||||
val dupMentions = mentions.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
var dupMentions by remember { mutableStateOf<List<User>?>(null) }
|
||||||
|
|
||||||
ReplyInformation(replyTo, dupMentions, account) {
|
LaunchedEffect(Unit) {
|
||||||
navController.navigate("User/${it.pubkeyHex}")
|
withContext(Dispatchers.IO) {
|
||||||
|
dupMentions = mentions.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dupMentions != null) {
|
||||||
|
ReplyInformation(replyTo, dupMentions, account) {
|
||||||
|
navController.navigate("User/${it.pubkeyHex}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +113,34 @@ fun ReplyInformation(replyTo: List<Note>?, dupMentions: List<User>?, account: Ac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReplyInformationChannel(replyTo: List<Note>?, mentions: List<String>, channel: Channel, account: Account, navController: NavController) {
|
||||||
|
var sortedMentions by remember { mutableStateOf<List<User>?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
sortedMentions = mentions
|
||||||
|
.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
||||||
|
.toSet()
|
||||||
|
.sortedBy { account.isFollowing(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sortedMentions != null) {
|
||||||
|
ReplyInformationChannel(
|
||||||
|
replyTo,
|
||||||
|
sortedMentions,
|
||||||
|
channel,
|
||||||
|
onUserTagClick = {
|
||||||
|
navController.navigate("User/${it.pubkeyHex}")
|
||||||
|
},
|
||||||
|
onChannelTagClick = {
|
||||||
|
navController.navigate("Channel/${it.idHex}")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReplyInformationChannel(replyTo: List<Note>?, mentions: List<User>?, channel: Channel, navController: NavController) {
|
fun ReplyInformationChannel(replyTo: List<Note>?, mentions: List<User>?, channel: Channel, navController: NavController) {
|
||||||
ReplyInformationChannel(
|
ReplyInformationChannel(
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshFromOldState(newItems: Set<Note>) {
|
private fun refreshFromOldState(newItems: Set<Note>) {
|
||||||
val oldNotesState = _feedContent.value
|
val oldNotesState = _feedContent.value
|
||||||
|
|
||||||
val thisAccount = (localFilter as? NotificationFeedFilter)?.account
|
val thisAccount = (localFilter as? NotificationFeedFilter)?.account
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ private fun FeedLoaded(
|
|||||||
} else {
|
} else {
|
||||||
val replyAuthorBase =
|
val replyAuthorBase =
|
||||||
(note.event as? PrivateDmEvent)
|
(note.event as? PrivateDmEvent)
|
||||||
?.recipientPubKey()
|
?.verifiedRecipientPubKey()
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
?.let { LocalCache.getOrCreateUser(it) }
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
var userToComposeOn = note.author!!
|
||||||
|
|||||||
@@ -100,23 +100,42 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navController: NavController) {
|
fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navController: NavController) {
|
||||||
|
if (userId == null) return
|
||||||
|
|
||||||
|
var userBase by remember { mutableStateOf<User?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
userBase = LocalCache.checkGetOrCreateUser(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userBase?.let {
|
||||||
|
ProfileScreen(
|
||||||
|
user = it,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun ProfileScreen(user: User, accountViewModel: AccountViewModel, navController: NavController) {
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||||
val account = accountState?.account ?: return
|
val account = accountState?.account ?: return
|
||||||
|
|
||||||
if (userId == null) return
|
UserProfileNewThreadFeedFilter.loadUserProfile(account, user)
|
||||||
|
UserProfileConversationsFeedFilter.loadUserProfile(account, user)
|
||||||
|
UserProfileFollowersFeedFilter.loadUserProfile(account, user)
|
||||||
|
UserProfileFollowsFeedFilter.loadUserProfile(account, user)
|
||||||
|
UserProfileZapsFeedFilter.loadUserProfile(user)
|
||||||
|
UserProfileReportsFeedFilter.loadUserProfile(user)
|
||||||
|
UserProfileBookmarksFeedFilter.loadUserProfile(account, user)
|
||||||
|
|
||||||
UserProfileNewThreadFeedFilter.loadUserProfile(account, userId)
|
NostrUserProfileDataSource.loadUserProfile(user)
|
||||||
UserProfileConversationsFeedFilter.loadUserProfile(account, userId)
|
|
||||||
UserProfileFollowersFeedFilter.loadUserProfile(account, userId)
|
|
||||||
UserProfileFollowsFeedFilter.loadUserProfile(account, userId)
|
|
||||||
UserProfileZapsFeedFilter.loadUserProfile(userId)
|
|
||||||
UserProfileReportsFeedFilter.loadUserProfile(userId)
|
|
||||||
UserProfileBookmarksFeedFilter.loadUserProfile(account, userId)
|
|
||||||
|
|
||||||
NostrUserProfileDataSource.loadUserProfile(userId)
|
|
||||||
|
|
||||||
val lifeCycleOwner = LocalLifecycleOwner.current
|
val lifeCycleOwner = LocalLifecycleOwner.current
|
||||||
|
|
||||||
@@ -124,7 +143,7 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro
|
|||||||
val observer = LifecycleEventObserver { _, event ->
|
val observer = LifecycleEventObserver { _, event ->
|
||||||
if (event == Lifecycle.Event.ON_RESUME) {
|
if (event == Lifecycle.Event.ON_RESUME) {
|
||||||
println("Profidle Start")
|
println("Profidle Start")
|
||||||
NostrUserProfileDataSource.loadUserProfile(userId)
|
NostrUserProfileDataSource.loadUserProfile(user)
|
||||||
NostrUserProfileDataSource.start()
|
NostrUserProfileDataSource.start()
|
||||||
}
|
}
|
||||||
if (event == Lifecycle.Event.ON_PAUSE) {
|
if (event == Lifecycle.Event.ON_PAUSE) {
|
||||||
|
|||||||
Reference in New Issue
Block a user