Skip to content

Commit

Permalink
add draft in the home feed
Browse files Browse the repository at this point in the history
  • Loading branch information
greenart7c3 committed Mar 15, 2024
1 parent fa5d992 commit e292aff
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 107 deletions.
33 changes: 22 additions & 11 deletions app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import com.vitorpamplona.quartz.events.ClassifiedsEvent
import com.vitorpamplona.quartz.events.Contact
import com.vitorpamplona.quartz.events.ContactListEvent
import com.vitorpamplona.quartz.events.DeletionEvent
import com.vitorpamplona.quartz.events.DraftEvent
import com.vitorpamplona.quartz.events.EmojiPackEvent
import com.vitorpamplona.quartz.events.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.events.EmojiUrl
Expand Down Expand Up @@ -1422,6 +1423,7 @@ class Account(
relayList: List<Relay>? = null,
geohash: String? = null,
nip94attachments: List<FileHeaderEvent>? = null,
draftTag: String?,
) {
if (!isWriteable()) return

Expand All @@ -1445,20 +1447,28 @@ class Account(
nip94attachments = nip94attachments,
forkedFrom = forkedFrom,
signer = signer,
isDraft = draftTag != null,
) {
Client.send(it, relayList = relayList)
LocalCache.justConsume(it, null)
if (draftTag != null) {
DraftEvent.create(draftTag, it, signer) { draftEvent ->
Client.send(draftEvent, relayList = relayList)
LocalCache.justConsume(draftEvent, null)
}
} else {
Client.send(it, relayList = relayList)
LocalCache.justConsume(it, null)

// broadcast replied notes
replyingTo?.let {
LocalCache.getNoteIfExists(replyingTo)?.event?.let {
Client.send(it, relayList = relayList)
// broadcast replied notes
replyingTo?.let {
LocalCache.getNoteIfExists(replyingTo)?.event?.let {
Client.send(it, relayList = relayList)
}
}
}
replyTo?.forEach { it.event?.let { Client.send(it, relayList = relayList) } }
addresses?.forEach {
LocalCache.getAddressableNoteIfExists(it.toTag())?.event?.let {
Client.send(it, relayList = relayList)
replyTo?.forEach { it.event?.let { Client.send(it, relayList = relayList) } }
addresses?.forEach {
LocalCache.getAddressableNoteIfExists(it.toTag())?.event?.let {
Client.send(it, relayList = relayList)
}
}
}
}
Expand Down Expand Up @@ -2210,6 +2220,7 @@ class Account(

fun cachedDecryptContent(note: Note): String? {
val event = note.event

return if (event is PrivateDmEvent && isWriteable()) {
event.cachedContentFor(signer)
} else if (event is LnZapRequestEvent && event.isPrivateZap() && isWriteable()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import com.vitorpamplona.quartz.events.CommunityListEvent
import com.vitorpamplona.quartz.events.CommunityPostApprovalEvent
import com.vitorpamplona.quartz.events.ContactListEvent
import com.vitorpamplona.quartz.events.DeletionEvent
import com.vitorpamplona.quartz.events.DraftEvent
import com.vitorpamplona.quartz.events.EmojiPackEvent
import com.vitorpamplona.quartz.events.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.events.Event
Expand Down Expand Up @@ -2042,6 +2043,13 @@ object LocalCache {
}
}

private fun consume(
event: DraftEvent,
relay: Relay?,
) {
consumeBaseReplaceable(event, relay)
}

fun justConsume(
event: Event,
relay: Relay?,
Expand Down Expand Up @@ -2079,6 +2087,7 @@ object LocalCache {
}
is ContactListEvent -> consume(event)
is DeletionEvent -> consume(event)
is DraftEvent -> consume(event, relay)
is EmojiPackEvent -> consume(event, relay)
is EmojiPackSelectionEvent -> consume(event, relay)
is SealedGossipEvent -> consume(event, relay)
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ open class Note(val idHex: String) {
var event: EventInterface? = null
var author: User? = null
var replyTo: List<Note>? = null
var draft: String? = null

// These fields are updated every time an event related to this note is received.
var replies = listOf<Note>()
Expand Down Expand Up @@ -183,6 +184,17 @@ open class Note(val idHex: String) {

open fun createdAt() = event?.createdAt()

fun updateDraft(id: String) {
draft = id
}

fun isDraft(): Boolean {
draft?.let {
return it.isNotBlank()
}
return false
}

fun loadEvent(
event: Event,
author: User,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import com.vitorpamplona.quartz.events.CalendarRSVPEvent
import com.vitorpamplona.quartz.events.CalendarTimeSlotEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
import com.vitorpamplona.quartz.events.ContactListEvent
import com.vitorpamplona.quartz.events.DraftEvent
import com.vitorpamplona.quartz.events.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
Expand Down Expand Up @@ -229,6 +230,16 @@ object NostrAccountDataSource : NostrDataSource("AccountData") {
)
}

fun createDraftsFilter() =
TypedFilter(
types = COMMON_FEED_TYPES,
filter =
JsonFilter(
kinds = listOf(DraftEvent.KIND),
authors = listOf(account.userProfile().pubkeyHex),
),
)

fun createGiftWrapsToMeFilter() =
TypedFilter(
types = COMMON_FEED_TYPES,
Expand Down Expand Up @@ -262,22 +273,38 @@ object NostrAccountDataSource : NostrDataSource("AccountData") {
checkNotInMainThread()

if (LocalCache.justVerify(event)) {
if (event is GiftWrapEvent) {
// Avoid decrypting over and over again if the event already exist.
val note = LocalCache.getNoteIfExists(event.id)
if (note != null && relay.brief in note.relays) return

event.cachedGift(account.signer) { this.consume(it, relay) }
}

if (event is SealedGossipEvent) {
// Avoid decrypting over and over again if the event already exist.
val note = LocalCache.getNoteIfExists(event.id)
if (note != null && relay.brief in note.relays) return

event.cachedGossip(account.signer) { LocalCache.justConsume(it, relay) }
} else {
LocalCache.justConsume(event, relay)
when (event) {
is DraftEvent -> {
// Avoid decrypting over and over again if the event already exist.
val note = LocalCache.getNoteIfExists(event.id)
if (note != null && relay.brief in note.relays) return

event.plainContent(account.signer) {
LocalCache.justConsume(it, relay)
val draftNote = LocalCache.getNoteIfExists(it.id)
draftNote?.updateDraft(event.id)
}
}

is GiftWrapEvent -> {
// Avoid decrypting over and over again if the event already exist.
val note = LocalCache.getNoteIfExists(event.id)
if (note != null && relay.brief in note.relays) return

event.cachedGift(account.signer) { this.consume(it, relay) }
}

is SealedGossipEvent -> {
// Avoid decrypting over and over again if the event already exist.
val note = LocalCache.getNoteIfExists(event.id)
if (note != null && relay.brief in note.relays) return

event.cachedGossip(account.signer) { LocalCache.justConsume(it, relay) }
}

else -> {
LocalCache.justConsume(event, relay)
}
}
}
}
Expand Down Expand Up @@ -328,6 +355,7 @@ object NostrAccountDataSource : NostrDataSource("AccountData") {
createAccountSettingsFilter(),
createAccountLastPostsListFilter(),
createOtherAccountsBaseFilter(),
createDraftsFilter(),
)
.ifEmpty { null }
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class Relay(
val subscriptionId = msgArray.get(1).asText()
val event = Event.fromJson(msgArray.get(2))

// Log.w("Relay", "Relay onEVENT ${event.kind} $url, $subscriptionId ${msgArray.get(2)}")
Log.w("Relay", "Relay onEVENT ${event.kind} $url, $subscriptionId ${msgArray.get(2)}")
listeners.forEach {
it.onEvent(
this@Relay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.launch
import java.util.UUID

enum class UserSuggestionAnchor {
MAIN_MESSAGE,
Expand All @@ -83,6 +84,7 @@ enum class UserSuggestionAnchor {

@Stable
open class NewPostViewModel() : ViewModel() {
var draftTag: String = UUID.randomUUID().toString()
var accountViewModel: AccountViewModel? = null
var account: Account? = null
var requiresNIP24: Boolean = false
Expand Down Expand Up @@ -306,11 +308,17 @@ open class NewPostViewModel() : ViewModel() {
}
}

fun sendPost(relayList: List<Relay>? = null) {
viewModelScope.launch(Dispatchers.IO) { innerSendPost(relayList) }
fun sendPost(
relayList: List<Relay>? = null,
localDraft: String? = null,
) {
viewModelScope.launch(Dispatchers.IO) { innerSendPost(relayList, localDraft) }
}

suspend fun innerSendPost(relayList: List<Relay>? = null) {
private suspend fun innerSendPost(
relayList: List<Relay>? = null,
localDraft: String?,
) {
if (accountViewModel == null) {
cancel()
return
Expand Down Expand Up @@ -555,11 +563,13 @@ open class NewPostViewModel() : ViewModel() {
relayList = relayList,
geohash = geoHash,
nip94attachments = usedAttachments,
draftTag = draftTag,
)
}
}

cancel()
if (localDraft == null) {
cancel()
}
}

fun upload(
Expand Down Expand Up @@ -693,8 +703,8 @@ open class NewPostViewModel() : ViewModel() {
pTags = pTags?.filter { it != userToRemove }
}

open fun saveDraft(message: String) {
account?.let { LocalPreferences.saveDraft(message, originalNote?.idHex, it) }
open fun saveDraft() {
sendPost(localDraft = draftTag)
}

open fun loadDraft(): String? {
Expand All @@ -708,9 +718,6 @@ open class NewPostViewModel() : ViewModel() {
}

open fun updateMessage(it: TextFieldValue) {
viewModelScope.launch(Dispatchers.IO) {
saveDraft(it.text)
}
message = it
urlPreview = findUrlInMessage()

Expand All @@ -732,6 +739,10 @@ open class NewPostViewModel() : ViewModel() {
userSuggestions = emptyList()
}
}

viewModelScope.launch(Dispatchers.IO) {
saveDraft()
}
}

open fun updateToUsers(it: TextFieldValue) {
Expand All @@ -755,10 +766,16 @@ open class NewPostViewModel() : ViewModel() {
userSuggestions = emptyList()
}
}
viewModelScope.launch(Dispatchers.IO) {
saveDraft()
}
}

open fun updateSubject(it: TextFieldValue) {
subject = it
viewModelScope.launch(Dispatchers.IO) {
saveDraft()
}
}

open fun updateZapForwardTo(it: TextFieldValue) {
Expand All @@ -785,6 +802,9 @@ open class NewPostViewModel() : ViewModel() {
userSuggestions = emptyList()
}
}
viewModelScope.launch(Dispatchers.IO) {
saveDraft()
}
}

open fun autocompleteWithUser(item: User) {
Expand All @@ -800,9 +820,6 @@ open class NewPostViewModel() : ViewModel() {
message.text.replaceRange(lastWordStart, it.end, wordToInsert),
TextRange(lastWordStart + wordToInsert.length, lastWordStart + wordToInsert.length),
)
viewModelScope.launch(Dispatchers.IO) {
saveDraft(message.text)
}
} else if (userSuggestionsMainMessage == UserSuggestionAnchor.FORWARD_ZAPS) {
forwardZapTo.addItem(item)
forwardZapToEditting = TextFieldValue("")
Expand Down Expand Up @@ -833,6 +850,10 @@ open class NewPostViewModel() : ViewModel() {
userSuggestionsMainMessage = null
userSuggestions = emptyList()
}

viewModelScope.launch(Dispatchers.IO) {
saveDraft()
}
}

private fun newStateMapPollOptions(): SnapshotStateMap<Int, String> {
Expand Down Expand Up @@ -902,8 +923,8 @@ open class NewPostViewModel() : ViewModel() {
nip94attachments = nip94attachments + event

message = message.insertUrlAtCursor(imageUrl)
saveDraft(message.text)
urlPreview = findUrlInMessage()
saveDraft()
}
},
onError = {
Expand Down Expand Up @@ -945,10 +966,10 @@ open class NewPostViewModel() : ViewModel() {

note?.let {
message = message.insertUrlAtCursor("nostr:" + it.toNEvent())
saveDraft(message.text)
}

urlPreview = findUrlInMessage()
saveDraft()
}
},
onError = {
Expand All @@ -969,6 +990,7 @@ open class NewPostViewModel() : ViewModel() {
locUtil?.let {
location =
it.locationStateFlow.mapLatest { it.toGeoHash(GeohashPrecision.KM_5_X_5.digits).toString() }
saveDraft()
}
viewModelScope.launch(Dispatchers.IO) { locUtil?.start() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.events.ChannelMessageEvent
import com.vitorpamplona.quartz.events.DraftEvent
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
import com.vitorpamplona.quartz.events.MuteListEvent
import com.vitorpamplona.quartz.events.PeopleListEvent
Expand Down Expand Up @@ -69,7 +70,8 @@ class HomeConversationsFeedFilter(val account: Account) : AdditiveFeedFilter<Not
it.event is TextNoteEvent ||
it.event is PollNoteEvent ||
it.event is ChannelMessageEvent ||
it.event is LiveActivitiesChatMessageEvent
it.event is LiveActivitiesChatMessageEvent ||
it.event is DraftEvent
) &&
(
isGlobal ||
Expand Down
Loading

0 comments on commit e292aff

Please sign in to comment.