Merge remote-tracking branch 'upstream/main' into NIP90-ContentDiscovery

This commit is contained in:
Believethehype
2024-05-14 23:16:49 +02:00
41 changed files with 202 additions and 200 deletions
@@ -91,7 +91,7 @@ private object PrefKeys {
const val LATEST_CONTACT_LIST = "latestContactList"
const val HIDE_DELETE_REQUEST_DIALOG = "hide_delete_request_dialog"
const val HIDE_BLOCK_ALERT_DIALOG = "hide_block_alert_dialog"
const val HIDE_NIP_24_WARNING_DIALOG = "hide_nip24_warning_dialog"
const val HIDE_NIP_17_WARNING_DIALOG = "hide_nip24_warning_dialog" // delete later
const val USE_PROXY = "use_proxy"
const val PROXY_PORT = "proxy_port"
const val SHOW_SENSITIVE_CONTENT = "show_sensitive_content"
@@ -318,7 +318,7 @@ object LocalPreferences {
Event.mapper.writeValueAsString(account.backupContactList),
)
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, account.hideDeleteRequestDialog)
putBoolean(PrefKeys.HIDE_NIP_24_WARNING_DIALOG, account.hideNIP24WarningDialog)
putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, account.hideNIP17WarningDialog)
putBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, account.hideBlockAlertDialog)
putBoolean(PrefKeys.USE_PROXY, account.proxy != null)
putInt(PrefKeys.PROXY_PORT, account.proxyPort)
@@ -526,7 +526,7 @@ object LocalPreferences {
val hideDeleteRequestDialog = getBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, false)
val hideBlockAlertDialog = getBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, false)
val hideNIP24WarningDialog = getBoolean(PrefKeys.HIDE_NIP_24_WARNING_DIALOG, false)
val hideNIP17WarningDialog = getBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, false)
val useProxy = getBoolean(PrefKeys.USE_PROXY, false)
val proxyPort = getInt(PrefKeys.PROXY_PORT, 9050)
val proxy = HttpClientManager.initProxy(useProxy, "127.0.0.1", proxyPort)
@@ -591,7 +591,7 @@ object LocalPreferences {
zapPaymentRequest = zapPaymentRequestServer,
hideDeleteRequestDialog = hideDeleteRequestDialog,
hideBlockAlertDialog = hideBlockAlertDialog,
hideNIP24WarningDialog = hideNIP24WarningDialog,
hideNIP17WarningDialog = hideNIP17WarningDialog,
backupContactList = latestContactList,
proxy = proxy,
proxyPort = proxyPort,
@@ -78,7 +78,7 @@ import com.vitorpamplona.quartz.events.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.events.LnZapRequestEvent
import com.vitorpamplona.quartz.events.MetadataEvent
import com.vitorpamplona.quartz.events.MuteListEvent
import com.vitorpamplona.quartz.events.NIP24Factory
import com.vitorpamplona.quartz.events.NIP17Factory
import com.vitorpamplona.quartz.events.OtsEvent
import com.vitorpamplona.quartz.events.PeopleListEvent
import com.vitorpamplona.quartz.events.PollNoteEvent
@@ -185,7 +185,7 @@ class Account(
var zapPaymentRequest: Nip47WalletConnect.Nip47URI? = null,
var hideDeleteRequestDialog: Boolean = false,
var hideBlockAlertDialog: Boolean = false,
var hideNIP24WarningDialog: Boolean = false,
var hideNIP17WarningDialog: Boolean = false,
var backupContactList: ContactListEvent? = null,
var proxy: Proxy? = null,
var proxyPort: Int = 9050,
@@ -593,7 +593,7 @@ class Account(
val emojiUrl = EmojiUrl.decode(reaction)
if (emojiUrl != null) {
note.event?.let {
NIP24Factory().createReactionWithinGroup(
NIP17Factory().createReactionWithinGroup(
emojiUrl = emojiUrl,
originalNote = it,
to = users,
@@ -608,7 +608,7 @@ class Account(
}
note.event?.let {
NIP24Factory().createReactionWithinGroup(
NIP17Factory().createReactionWithinGroup(
content = reaction,
originalNote = it,
to = users,
@@ -1736,7 +1736,7 @@ class Account(
}
}
fun sendNIP24PrivateMessage(
fun sendNIP17PrivateMessage(
message: String,
toUsers: List<HexKey>,
subject: String? = null,
@@ -1754,7 +1754,7 @@ class Account(
val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null }
val mentionsHex = mentions?.map { it.pubkeyHex }
NIP24Factory().createMsgNIP24(
NIP17Factory().createMsgNIP17(
msg = message,
to = toUsers,
subject = subject,
@@ -1783,7 +1783,7 @@ class Account(
}
}
fun broadcastPrivately(signedEvents: NIP24Factory.Result) {
fun broadcastPrivately(signedEvents: NIP17Factory.Result) {
val mine = signedEvents.wraps.filter { (it.recipientPubKey() == signer.pubKey) }
mine.forEach { giftWrap ->
@@ -2538,8 +2538,8 @@ class Account(
saveable.invalidateData()
}
fun setHideNIP24WarningDialog() {
hideNIP24WarningDialog = true
fun setHideNIP17WarningDialog() {
hideNIP17WarningDialog = true
saveable.invalidateData()
}
@@ -92,10 +92,10 @@ open class NewPostViewModel() : ViewModel() {
var accountViewModel: AccountViewModel? = null
var account: Account? = null
var requiresNIP24: Boolean = false
var requiresNIP17: Boolean = false
var originalNote: Note? = null
var forkedFromNote: Note? = null
var originalNote: Note? by mutableStateOf<Note?>(null)
var forkedFromNote: Note? by mutableStateOf<Note?>(null)
var pTags by mutableStateOf<List<User>?>(null)
var eTags by mutableStateOf<List<Note>?>(null)
@@ -169,8 +169,8 @@ open class NewPostViewModel() : ViewModel() {
var wantsZapraiser by mutableStateOf(false)
var zapRaiserAmount by mutableStateOf<Long?>(null)
// NIP24 Wrapped DMs / Group messages
var nip24 by mutableStateOf(false)
// NIP17 Wrapped DMs / Group messages
var nip17 by mutableStateOf(false)
val draftTextChanges = Channel<String>(Channel.CONFLATED)
@@ -425,8 +425,8 @@ open class NewPostViewModel() : ViewModel() {
TextFieldValue(draftEvent.content())
}
requiresNIP24 = draftEvent is ChatMessageEvent
nip24 = draftEvent is ChatMessageEvent
requiresNIP17 = draftEvent is ChatMessageEvent
nip17 = draftEvent is ChatMessageEvent
if (draftEvent is ChatMessageEvent) {
toUsers =
@@ -557,7 +557,7 @@ open class NewPostViewModel() : ViewModel() {
.toSet()
.toList()
account?.sendNIP24PrivateMessage(
account?.sendNIP17PrivateMessage(
message = tagger.message,
toUsers = receivers,
subject = subject.text.ifBlank { null },
@@ -571,8 +571,8 @@ open class NewPostViewModel() : ViewModel() {
draftTag = localDraft,
)
} else if (!dmUsers.isNullOrEmpty()) {
if (nip24 || dmUsers.size > 1) {
account?.sendNIP24PrivateMessage(
if (nip17 || dmUsers.size > 1) {
account?.sendNIP17PrivateMessage(
message = tagger.message,
toUsers = dmUsers.map { it.pubkeyHex },
subject = subject.text.ifBlank { null },
@@ -1131,10 +1131,10 @@ open class NewPostViewModel() : ViewModel() {
}
fun toggleNIP04And24() {
if (requiresNIP24) {
nip24 = true
if (requiresNIP17) {
nip17 = true
} else {
nip24 = !nip24
nip17 = !nip17
}
if (message.text.isNotBlank()) {
saveDraft()
@@ -64,7 +64,7 @@ class MediaCompressor {
appSpecificStorageConfiguration = AppSpecificStorageConfiguration(),
configureWith =
Configuration(
quality = VideoQuality.LOW,
quality = VideoQuality.MEDIUM,
// => required name
videoNames = listOf(UUID.randomUUID().toString()),
),
@@ -54,6 +54,7 @@ import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.compose.produceCachedStateAsync
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.FeatureSetType
import com.vitorpamplona.amethyst.model.Note
@@ -75,6 +76,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
import com.vitorpamplona.amethyst.ui.note.elements.Reward
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
import com.vitorpamplona.amethyst.ui.note.types.EditState
@@ -87,6 +89,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderBadgeAward
import com.vitorpamplona.amethyst.ui.note.types.RenderChannelMessage
import com.vitorpamplona.amethyst.ui.note.types.RenderChatMessage
import com.vitorpamplona.amethyst.ui.note.types.RenderClassifieds
import com.vitorpamplona.amethyst.ui.note.types.RenderCommunity
import com.vitorpamplona.amethyst.ui.note.types.RenderEmojiPack
import com.vitorpamplona.amethyst.ui.note.types.RenderFhirResource
import com.vitorpamplona.amethyst.ui.note.types.RenderGitIssueEvent
@@ -108,7 +111,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderTextModificationEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderWikiContent
import com.vitorpamplona.amethyst.ui.note.types.VideoDisplay
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChannelHeader
import com.vitorpamplona.amethyst.ui.screen.loggedIn.RenderChannelHeader
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.Font12SP
@@ -137,6 +140,7 @@ import com.vitorpamplona.quartz.events.AppDefinitionEvent
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.BadgeAwardEvent
import com.vitorpamplona.quartz.events.BadgeDefinitionEvent
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
@@ -240,13 +244,22 @@ fun AcceptableNote(
is ChannelCreateEvent,
is ChannelMetadataEvent,
->
ChannelHeader(
RenderChannelHeader(
channelNote = baseNote,
showVideo = !makeItShort,
sendToChannel = true,
accountViewModel = accountViewModel,
nav = nav,
)
is CommunityDefinitionEvent ->
(baseNote as? AddressableNote)?.let {
RenderCommunity(
baseNote = it,
accountViewModel = accountViewModel,
nav = nav,
)
}
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote)
else ->
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) {
showPopup,
@@ -273,13 +286,22 @@ fun AcceptableNote(
is ChannelCreateEvent,
is ChannelMetadataEvent,
->
ChannelHeader(
RenderChannelHeader(
channelNote = baseNote,
showVideo = !makeItShort,
sendToChannel = true,
accountViewModel = accountViewModel,
nav = nav,
)
is CommunityDefinitionEvent ->
(baseNote as? AddressableNote)?.let {
RenderCommunity(
baseNote = it,
accountViewModel = accountViewModel,
nav = nav,
)
}
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote)
is FileHeaderEvent -> FileHeaderDisplay(baseNote, false, accountViewModel)
is FileStorageHeaderEvent -> FileStorageHeaderDisplay(baseNote, false, accountViewModel)
else ->
@@ -25,12 +25,9 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -50,6 +47,7 @@ import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
@@ -74,7 +72,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size25dp
import com.vitorpamplona.amethyst.ui.theme.Size35dp
import com.vitorpamplona.amethyst.ui.theme.Size5dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.innerPostModifier
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
import com.vitorpamplona.quartz.events.EmptyTagList
import com.vitorpamplona.quartz.events.Participant
@@ -84,43 +82,22 @@ import kotlinx.collections.immutable.toImmutableList
import java.util.Locale
@Composable
fun CommunityHeader(
baseNote: AddressableNote,
sendToCommunity: Boolean,
modifier: Modifier = StdPadding,
fun RenderCommunity(
baseNote: Note,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val expanded = remember { mutableStateOf(false) }
Column(Modifier.fillMaxWidth()) {
Column(
verticalArrangement = Arrangement.Center,
modifier =
Modifier.clickable {
if (sendToCommunity) {
routeFor(baseNote, accountViewModel.userProfile())?.let { nav(it) }
} else {
expanded.value = !expanded.value
}
},
if (baseNote is AddressableNote) {
Row(
MaterialTheme.colorScheme.innerPostModifier.clickable {
routeFor(baseNote, accountViewModel.userProfile())?.let { nav(it) }
}.padding(Size10dp),
) {
ShortCommunityHeader(
baseNote = baseNote,
accountViewModel = accountViewModel,
nav = nav,
)
if (expanded.value) {
Column(Modifier.verticalScroll(rememberScrollState())) {
LongCommunityHeader(
baseNote = baseNote,
lineModifier = modifier,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
}
}
}
@@ -58,9 +58,8 @@ fun RenderPostApproval(
noteEvent.communities().forEach { tag ->
LoadAddressableNote(tag, accountViewModel) { baseNote ->
baseNote?.let {
CommunityHeader(
RenderCommunity(
baseNote = it,
sendToCommunity = true,
accountViewModel = accountViewModel,
nav = nav,
)
@@ -666,11 +666,11 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View
viewModelScope.launch(Dispatchers.IO) { account.setHideDeleteRequestDialog() }
}
val hideNIP24WarningDialog: Boolean
get() = account.hideNIP24WarningDialog
val hideNIP17WarningDialog: Boolean
get() = account.hideNIP17WarningDialog
fun dontShowNIP24WarningDialog() {
account.setHideNIP24WarningDialog()
fun dontShowNIP17WarningDialog() {
account.setHideNIP17WarningDialog()
}
val hideBlockAlertDialog: Boolean
@@ -147,6 +147,7 @@ import com.vitorpamplona.amethyst.ui.theme.EditFieldModifier
import com.vitorpamplona.amethyst.ui.theme.EditFieldTrailingIconModifier
import com.vitorpamplona.amethyst.ui.theme.HeaderPictureModifier
import com.vitorpamplona.amethyst.ui.theme.RowColSpacing
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.Size25dp
import com.vitorpamplona.amethyst.ui.theme.Size34dp
import com.vitorpamplona.amethyst.ui.theme.Size35dp
@@ -154,6 +155,7 @@ import com.vitorpamplona.amethyst.ui.theme.SmallBorder
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.ZeroPadding
import com.vitorpamplona.amethyst.ui.theme.innerPostModifier
import com.vitorpamplona.amethyst.ui.theme.liveStreamTag
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.events.EmptyTagList
@@ -587,6 +589,25 @@ fun MyTextField(
}
}
@Composable
fun RenderChannelHeader(
channelNote: Note,
showVideo: Boolean,
sendToChannel: Boolean,
modifier: Modifier = StdPadding,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
ChannelHeader(
channelNote = channelNote,
showVideo = showVideo,
sendToChannel = sendToChannel,
modifier = MaterialTheme.colorScheme.innerPostModifier.padding(Size10dp),
accountViewModel = accountViewModel,
nav = nav,
)
}
@Composable
fun ChannelHeader(
channelNote: Note,
@@ -122,7 +122,6 @@ import com.vitorpamplona.quartz.events.findURLs
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.receiveAsFlow
@@ -210,7 +209,6 @@ fun LoadRoomByAuthor(
content(room)
}
@OptIn(FlowPreview::class)
@Composable
fun PrepareChatroomViewModels(
room: ChatroomKey,
@@ -231,23 +229,8 @@ fun PrepareChatroomViewModels(
val newPostModel: NewPostViewModel = viewModel()
newPostModel.accountViewModel = accountViewModel
newPostModel.account = accountViewModel.account
newPostModel.requiresNIP24 = room.users.size > 1
if (newPostModel.requiresNIP24) {
newPostModel.nip24 = true
}
LaunchedEffect(key1 = newPostModel) {
launch(Dispatchers.IO) {
val hasNIP24 =
accountViewModel.userProfile().privateChatrooms[room]?.roomMessages?.any {
it.event is ChatMessageEvent &&
(it.event as ChatMessageEvent).pubKey != accountViewModel.userProfile().pubkeyHex
}
if (hasNIP24 == true && newPostModel.nip24 == false) {
newPostModel.nip24 = true
}
}
}
newPostModel.requiresNIP17 = room.users.size > 1
newPostModel.nip17 = true // defaults to the new GiftWrap
if (draftMessage != null) {
LaunchedEffect(key1 = draftMessage) { newPostModel.message = TextFieldValue(draftMessage) }
@@ -373,8 +356,8 @@ private fun innerSendPost(
val urls = findURLs(newPostModel.message.text)
val usedAttachments = newPostModel.nip94attachments.filter { it.urls().intersect(urls.toSet()).isNotEmpty() }
if (newPostModel.nip24 || room.users.size > 1 || replyTo.value?.event is ChatMessageEvent) {
accountViewModel.account.sendNIP24PrivateMessage(
if (newPostModel.nip17 || room.users.size > 1 || replyTo.value?.event is ChatMessageEvent) {
accountViewModel.account.sendNIP17PrivateMessage(
message = newPostModel.message.text,
toUsers = room.users.toList(),
replyingTo = replyTo.value,
@@ -454,13 +437,13 @@ fun PrivateMessageEditFieldRow(
)
}
var wantsToActivateNIP24 by remember { mutableStateOf(false) }
var wantsToActivateNIP17 by remember { mutableStateOf(false) }
if (wantsToActivateNIP24) {
NewFeatureNIP24AlertDialog(
if (wantsToActivateNIP17) {
NewFeatureNIP17AlertDialog(
accountViewModel = accountViewModel,
onConfirm = { channelScreenModel.toggleNIP04And24() },
onDismiss = { wantsToActivateNIP24 = false },
onDismiss = { wantsToActivateNIP17 = false },
)
}
@@ -468,17 +451,17 @@ fun PrivateMessageEditFieldRow(
modifier = Size30Modifier,
onClick = {
if (
!accountViewModel.hideNIP24WarningDialog &&
!channelScreenModel.nip24 &&
!channelScreenModel.requiresNIP24
!accountViewModel.hideNIP17WarningDialog &&
!channelScreenModel.nip17 &&
!channelScreenModel.requiresNIP17
) {
wantsToActivateNIP24 = true
wantsToActivateNIP17 = true
} else {
channelScreenModel.toggleNIP04And24()
}
},
) {
if (channelScreenModel.nip24) {
if (channelScreenModel.nip17) {
IncognitoIconOn(
modifier =
Modifier
@@ -537,7 +520,7 @@ fun ShowUserSuggestionList(
}
@Composable
fun NewFeatureNIP24AlertDialog(
fun NewFeatureNIP17AlertDialog(
accountViewModel: AccountViewModel,
onConfirm: () -> Unit,
onDismiss: () -> Unit,
@@ -545,10 +528,10 @@ fun NewFeatureNIP24AlertDialog(
val scope = rememberCoroutineScope()
QuickActionAlertDialog(
title = stringResource(R.string.new_feature_nip24_might_not_be_available_title),
textContent = stringResource(R.string.new_feature_nip24_might_not_be_available_description),
title = stringResource(R.string.new_feature_nip17_might_not_be_available_title),
textContent = stringResource(R.string.new_feature_nip17_might_not_be_available_description),
buttonIconResource = R.drawable.incognito,
buttonText = stringResource(R.string.new_feature_nip24_activate),
buttonText = stringResource(R.string.new_feature_nip17_activate),
onClickDoOnce = {
scope.launch(Dispatchers.IO) { onConfirm() }
onDismiss()
@@ -556,7 +539,7 @@ fun NewFeatureNIP24AlertDialog(
onClickDontShowAgain = {
scope.launch(Dispatchers.IO) {
onConfirm()
accountViewModel.dontShowNIP24WarningDialog()
accountViewModel.dontShowNIP17WarningDialog()
}
onDismiss()
},
@@ -732,7 +715,7 @@ fun NewSubjectView(
PostButton(
onPost = {
scope.launch(Dispatchers.IO) {
accountViewModel.account.sendNIP24PrivateMessage(
accountViewModel.account.sendNIP17PrivateMessage(
message = message.value,
toUsers = room.users.toList(),
subject = groupName.value.ifBlank { null },