Skip to content

Commit

Permalink
Fixes for Subscripton Handling and Caching
Browse files Browse the repository at this point in the history
- Add PTagList variant for handling multiple pubkeys
- Rename Relationship to Marker for clarity
- Add pubkey field to ETag for better NIP compliance
- Improve tag parsing with better error handling
- Fix collectEventsUntilEose to wait for all relay EOSE signals
- Remove redundant relay field from follow list comparison
- Optimize profile and event caching with invalidation on updates
- Fix event deletion by properly clearing caches and databases
- Make post and private message views consistent in styling and behavior
- Improve timeline cache handling and event updates
- Remove redundant event caching in publisher
  • Loading branch information
prolic committed Jan 29, 2025
1 parent 51bff23 commit 5f6e0a7
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 324 deletions.
1 change: 0 additions & 1 deletion resources/qml/content/FollowList.ui.qml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ Rectangle {
mode: AutoListModel.ByKey
equalityTest: function (oldItem, newItem) {
return oldItem.pubkey === newItem.pubkey
&& oldItem.relay === newItem.relay
&& oldItem.petname === newItem.petname
&& oldItem.displayName === newItem.displayName
&& oldItem.name === newItem.name
Expand Down
178 changes: 90 additions & 88 deletions resources/qml/content/MainContent.ui.qml
Original file line number Diff line number Diff line change
Expand Up @@ -163,110 +163,101 @@ Rectangle {
Layout.topMargin: Constants.spacing_m
currentIndex: chatTypeSelector.currentIndex

// Public Notes View
Item {
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: Constants.spacing_m

ColumnLayout {
anchors.fill: parent
// Public notes list
ListView {
id: postsView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
leftMargin: Constants.spacing_m
rightMargin: Constants.spacing_m
spacing: Constants.spacing_m
bottomMargin: 0

// Public notes list (now takes all space except input area)
ListView {
id: postsView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
leftMargin: Constants.spacing_m
rightMargin: Constants.spacing_m
spacing: Constants.spacing_m
bottomMargin: Constants.spacing_m

model: AutoListModel {
id: postsModel
source: posts
mode: AutoListModel.ByKey
equalityTest: function (oldItem, newItem) {
return oldItem.content === newItem.content
&& oldItem.timestamp === newItem.timestamp
}
model: AutoListModel {
id: postsModel
source: posts
mode: AutoListModel.ByKey
equalityTest: function (oldItem, newItem) {
return oldItem.id === newItem.id
}
}

delegate: Loader {
active: modelData !== undefined && modelData !== null
width: postsView.width - postsView.leftMargin - postsView.rightMargin
height: active ? item.implicitHeight : 0
delegate: Loader {
active: modelData !== undefined && modelData !== null
width: postsView.width - postsView.leftMargin - postsView.rightMargin
height: active ? item.implicitHeight : 0

sourceComponent: PostContent {
post: modelData
sourceComponent: PostContent {
post: modelData

onCommentClicked: {
if (modelData) {
commentsDialog.targetPost = modelData
commentsDialog.open()
}
onCommentClicked: {
if (modelData) {
commentsDialog.targetPost = modelData
commentsDialog.open()
}
}

onRepostClicked: {
if (modelData) {
repostMenu.targetPost = modelData
repostMenu.popup()
}
onRepostClicked: {
if (modelData) {
repostMenu.targetPost = modelData
repostMenu.popup()
}
}
}
}

onCountChanged: {
if (atYEnd || count === 1) {
onCountChanged: {
if (atYEnd) {
Qt.callLater(() => {
positionViewAtEnd()
}
})
}
}

Component.onCompleted: {
positionViewAtEnd()
}
Component.onCompleted: positionViewAtEnd()

ScrollBar.vertical: ScrollBar {
id: scrollBar
active: true
interactive: true
policy: ScrollBar.AsNeeded

contentItem: Rectangle {
implicitWidth: 6
radius: width / 2
color: scrollBar.pressed ? Material.scrollBarPressedColor :
scrollBar.hovered ? Material.scrollBarHoveredColor :
Material.scrollBarColor
opacity: scrollBar.active ? 1 : 0

Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
}

onContentHeightChanged: {
if (atYEnd) {
positionViewAtEnd()
ScrollBar.vertical: ScrollBar {
id: scrollBar
active: true
interactive: true
policy: ScrollBar.AsNeeded

contentItem: Rectangle {
implicitWidth: 6
radius: width / 2
color: scrollBar.pressed ? Material.scrollBarPressedColor :
scrollBar.hovered ? Material.scrollBarHoveredColor :
Material.scrollBarColor
opacity: scrollBar.active ? 1 : 0

Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
}
}

// Input area for new public notes (at the bottom)
MessageInput {
placeholderText: qsTr("What's on your mind?")
buttonText: qsTr("Post")
onMessageSent: function(text) {
sendShortTextNote(text)
}
// Input area for new public notes (at the bottom)
MessageInput {
placeholderText: qsTr("What's on your mind?")
buttonText: qsTr("Post")
onMessageSent: function(text) {
sendShortTextNote(text)
}
}
}

// Private Chat View
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: Constants.spacing_m

DMRelays {
Expand All @@ -276,30 +267,30 @@ Rectangle {
}

ListView {
id: messageListView
id: privateMessageListView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
verticalLayoutDirection: ListView.TopToBottom
layoutDirection: Qt.LeftToRight
leftMargin: Constants.spacing_m
rightMargin: Constants.spacing_m
spacing: Constants.spacing_m
bottomMargin: 0
visible: ctxRelayMgmt.dmRelays.length > 0

model: AutoListModel {
id: messagesModel
source: privateMessages
mode: AutoListModel.ByKey
equalityTest: function (oldItem, newItem) {
return oldItem.content === newItem.content
&& oldItem.isOwnMessage === newItem.isOwnMessage
&& oldItem.timestamp === newItem.timestamp
return oldItem.id === newItem.id
}
}

delegate: Loader {
active: modelData !== undefined && modelData !== null
width: messageListView.width - messageListView.leftMargin - messageListView.rightMargin - 15
width: privateMessageListView.width - privateMessageListView.leftMargin - privateMessageListView.rightMargin - 15
height: active ? item.height : 0

sourceComponent: Item {
Expand Down Expand Up @@ -355,22 +346,33 @@ Rectangle {
}

onCountChanged: {
if (atYEnd || count === 1) {
positionViewAtEnd()
if (atYEnd) {
Qt.callLater(() => {
positionViewAtEnd()
})
}
}

onContentHeightChanged: {
positionViewAtEnd()
}

Component.onCompleted: {
positionViewAtEnd()
}
Component.onCompleted: positionViewAtEnd()

ScrollBar.vertical: ScrollBar {
id: scrollBarPrivate
active: true
interactive: true
policy: ScrollBar.AsNeeded

contentItem: Rectangle {
implicitWidth: 6
radius: width / 2
color: scrollBarPrivate.pressed ? Material.scrollBarPressedColor :
scrollBarPrivate.hovered ? Material.scrollBarHoveredColor :
Material.scrollBarColor
opacity: scrollBarPrivate.active ? 1 : 0

Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
}
}

Expand Down
12 changes: 4 additions & 8 deletions src/Futr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ runFutr = interpret $ \_ -> \case
Nothing -> logError "Failed to create seal" >> return Nothing

let validGiftWraps = catMaybes giftWraps

forM_ validGiftWraps $ \gw -> do
putEvent $ EventWithRelays gw Set.empty
publishGiftWrap gw senderPubKeyXO
publishGiftWrap gw senderPubKeyXO recipient
notify $ emptyUpdates { privateMessagesChanged = True }

(Nothing, _) -> logError "No key pair found"
Expand All @@ -248,10 +248,11 @@ runFutr = interpret $ \_ -> \case
kp <- getKeyPair
now <- getCurrentTime
let u = createShortTextNote input (keyPairToPubKeyXO kp) now
logDebug $ "Sending short text note: " <> input
logDebug $ "unsigned: " <> pack (show u)
signed <- signEvent u kp
case signed of
Just s -> do
putEvent $ EventWithRelays s Set.empty
publishToOutbox s
notify $ emptyUpdates { postsChanged = True }
Nothing -> logError "Failed to sign short text note"
Expand Down Expand Up @@ -306,7 +307,6 @@ runFutr = interpret $ \_ -> \case

let targetUris = eventRelayUris `Set.union` authorInboxUris `Set.union` relaySet

putEvent $ EventWithRelays s targetUris
forM_ (Set.toList targetUris) $ \relay ->
publishToRelay s relay
notify $ emptyUpdates { postsChanged = True }
Expand All @@ -327,7 +327,6 @@ runFutr = interpret $ \_ -> \case
signed <- signEvent q kp
case signed of
Just s -> do
putEvent $ EventWithRelays s Set.empty
publishToOutbox s
notify $ emptyUpdates { postsChanged = True }
Nothing -> logError "Failed to sign quote repost"
Expand Down Expand Up @@ -359,7 +358,6 @@ runFutr = interpret $ \_ -> \case

let targetUris = eventRelayUris `Set.union` authorInboxUris `Set.union` relaySet

putEvent $ EventWithRelays s targetUris
forM_ (Set.toList targetUris) $ \relay ->
publishToRelay s relay
notify $ emptyUpdates { postsChanged = True }
Expand All @@ -376,7 +374,6 @@ runFutr = interpret $ \_ -> \case
signed <- signEvent deletion kp
case signed of
Just s -> do
putEvent $ EventWithRelays s Set.empty
publishToOutbox s
notify $ emptyUpdates { postsChanged = True, privateMessagesChanged = True }
Nothing -> logError "Failed to sign event deletion"
Expand Down Expand Up @@ -430,7 +427,6 @@ sendFollowListEvent follows = do
signedEvent <- signEvent event kp
case signedEvent of
Just signedEvent' -> do
putEvent $ EventWithRelays signedEvent' Set.empty
publishToOutbox signedEvent'
Nothing -> logError "Failed to sign follow list event"

Expand Down
1 change: 1 addition & 0 deletions src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Store.Lmdb (LmdbState, initialLmdbState, runLmdbStore)
import Types (AppState(..), RelayPool(..))
import Types qualified as Types


-- | Main function for the app.
main :: IO ()
main = do
Expand Down
Loading

0 comments on commit 5f6e0a7

Please sign in to comment.