summaryrefslogtreecommitdiff
path: root/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@jolla.com>2026-02-18 21:37:05 +0100
committerAndrew Branson <andrew.branson@jolla.com>2026-02-18 21:37:05 +0100
commit60d8504a8b5b0d5e5fa40c4ab7df8e5f98c88e32 (patch)
tree79529799246d3affe713775abdf5577e1f08d907 /eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
parent1ce97352a0aa2cea0be39fb7eb3a8333aadd2487 (diff)
Refactor
- Move common pieces to eventsview-extensions e.g. interaction menu - Expose and add useful API to libsocialcache
Diffstat (limited to 'eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml')
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml281
1 files changed, 80 insertions, 201 deletions
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
index c003950..9d04dfe 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
+++ b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
@@ -9,19 +9,20 @@ import Sailfish.Silica 1.0
import Sailfish.TextLinking 1.0
import org.nemomobile.lipstick 0.1
import "shared"
+import "shared/SocialFeedUtils.js" as FeedUtils
SocialMediaFeedItem {
id: item
property variant imageList
- property string resolvedStatusUrl: item.stringValue("url", "link", "uri")
+ property string resolvedStatusUrl: FeedUtils.stringRole(model, ["url", "link", "uri"], "")
property string postId
property QtObject postActions
- property int likeCount: item.intValue("favouritesCount", "likeCount", "favoriteCount")
- property int commentCount: item.intValue("repliesCount", "commentCount")
- property int boostCount: item.intValue("reblogsCount", "boostCount", "repostsCount")
- property bool favourited: !!model.favourited
- property bool reblogged: !!model.reblogged
+ property int likeCount: FeedUtils.intRole(model, ["favouritesCount", "likeCount", "favoriteCount"], 0)
+ property int commentCount: FeedUtils.intRole(model, ["repliesCount", "commentCount"], 0)
+ property int boostCount: FeedUtils.intRole(model, ["reblogsCount", "boostCount", "repostsCount"], 0)
+ property bool favourited: FeedUtils.boolRole(model, ["favourited"], false)
+ property bool reblogged: FeedUtils.boolRole(model, ["reblogged"], false)
property int _likeCountOverride: -1
property int _boostCountOverride: -1
property int _favouritedOverride: -1
@@ -35,10 +36,22 @@ SocialMediaFeedItem {
property var _actionMenu
property real _contextMenuHeight: (_contextMenuOpen && _actionMenu) ? _actionMenu.height : 0
- property string _booster: item.stringValue("boostedBy", "rebloggedBy", "retweeter")
- property string _displayName: item.stringValue("name", "displayName", "display_name")
- property string _accountName: item.stringValue("accountName", "acct", "screenName", "username")
- property string _bodyText: item.stringValue("body", "content", "text")
+ property string _booster: FeedUtils.stringRole(model, ["boostedBy", "rebloggedBy", "retweeter"], "")
+ property string _displayName: FeedUtils.stringRole(model, ["name", "displayName", "display_name"], "")
+ property string _accountName: FeedUtils.stringRole(model, ["accountName", "acct", "screenName", "username"], "")
+ property string _bodyText: FeedUtils.stringRole(model, ["body", "content", "text"], "")
+ //: Action label shown in Mastodon interaction menu.
+ //% "Favourite"
+ readonly property string _favouriteActionText: qsTrId("lipstick-jolla-home-la-mastodon_favourite")
+ //: Action label shown in Mastodon interaction menu when the post is already favourited.
+ //% "Unfavourite"
+ readonly property string _unfavouriteActionText: qsTrId("lipstick-jolla-home-la-mastodon_unfavourite")
+ //: Action label shown in Mastodon interaction menu.
+ //% "Boost"
+ readonly property string _boostActionText: qsTrId("lipstick-jolla-home-la-mastodon_boost")
+ //: Action label shown in Mastodon interaction menu when the post is already boosted.
+ //% "Undo boost"
+ readonly property string _unboostActionText: qsTrId("lipstick-jolla-home-la-mastodon_unboost")
timestamp: model.timestamp
onRefreshTimeCountChanged: formattedTime = Format.formatDate(model.timestamp, Format.TimeElapsed)
@@ -76,7 +89,7 @@ SocialMediaFeedItem {
topMargin: item._booster.length > 0 ? Theme.paddingMedium : Theme.paddingLarge
userRemovable: false
- Image {
+ SocialReshareIcon {
id: boosterIcon
anchors {
@@ -85,21 +98,17 @@ SocialMediaFeedItem {
topMargin: item.topMargin
}
visible: item._booster.length > 0
- source: "image://theme/icon-s-repost" + (item.highlighted ? "?" + Theme.highlightColor : "")
+ highlighted: item.highlighted
+ iconSource: "image://theme/icon-s-repost"
}
- Text {
+ SocialReshareText {
anchors {
left: content.left
right: content.right
verticalCenter: boosterIcon.verticalCenter
}
- elide: Text.ElideRight
- font.pixelSize: Theme.fontSizeExtraSmall
- color: item.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
- textFormat: Text.PlainText
- visible: text.length > 0
-
+ highlighted: item.highlighted
text: item._booster.length > 0
? //: Shown above a post that is boosted by another user. %1 = name of user who boosted
//% "%1 boosted"
@@ -147,61 +156,18 @@ SocialMediaFeedItem {
plainText: item._bodyText
}
- Row {
+ SocialPostMetadataRow {
id: metadataRow
width: parent.width
- height: previewRow.visible ? implicitHeight + Theme.paddingMedium : implicitHeight // add padding below
- spacing: Theme.paddingSmall
-
- readonly property color passiveColor: item.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
- readonly property color activeColor: Theme.highlightColor
-
- Label {
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "↩ " + item.commentCount
- color: metadataRow.passiveColor
- }
-
- Label {
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "|"
- color: metadataRow.passiveColor
- }
-
- Label {
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "★ " + (item._likeCountOverride >= 0 ? item._likeCountOverride : item.likeCount)
- color: item.isFavourited ? metadataRow.activeColor : metadataRow.passiveColor
- }
-
- Label {
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "|"
- color: metadataRow.passiveColor
- }
-
- Label {
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "↻ " + (item._boostCountOverride >= 0 ? item._boostCountOverride : item.boostCount)
- color: item.isReblogged ? metadataRow.activeColor : metadataRow.passiveColor
- }
-
- Label {
- visible: item.formattedTime.length > 0
- font.pixelSize: Theme.fontSizeExtraSmall
- text: "|"
- color: metadataRow.passiveColor
- }
-
- Label {
- visible: item.formattedTime.length > 0
- width: Math.max(0, metadataRow.width - x)
- truncationMode: TruncationMode.Fade
- font.pixelSize: Theme.fontSizeExtraSmall
- text: item.formattedTime
- color: metadataRow.passiveColor
- }
+ highlighted: item.highlighted
+ commentCount: item.commentCount
+ likeCount: item._likeCountOverride >= 0 ? item._likeCountOverride : item.likeCount
+ repostCount: item._boostCountOverride >= 0 ? item._boostCountOverride : item.boostCount
+ liked: item.isFavourited
+ reposted: item.isReblogged
+ timeText: item.formattedTime
+ addBottomPadding: previewRow.visible
}
SocialMediaPreviewRow {
@@ -217,39 +183,11 @@ SocialMediaFeedItem {
}
}
- function stringValue() {
- for (var i = 0; i < arguments.length; ++i) {
- var value = model[arguments[i]]
- if (typeof value === "undefined" || value === null) {
- continue
- }
- value = String(value)
- if (value.length > 0) {
- return value
- }
- }
- return ""
- }
-
- function intValue() {
- for (var i = 0; i < arguments.length; ++i) {
- var value = model[arguments[i]]
- if (typeof value === "undefined" || value === null) {
- continue
- }
- var number = Number(value)
- if (!isNaN(number)) {
- return Math.max(0, Math.floor(number))
- }
- }
- return 0
- }
-
function actionPostId() {
if (item.postId.length > 0) {
return item.postId
}
- return item.stringValue("mastodonId", "statusId", "id", "twitterId")
+ return FeedUtils.stringRole(model, ["mastodonId", "statusId", "id", "twitterId"], "")
}
function actionAccountId() {
@@ -313,115 +251,56 @@ SocialMediaFeedItem {
Component {
id: actionMenuComponent
- ContextMenu {
+ SocialInteractionContextMenu {
id: actionMenu
- property bool menuOpen: height > 0
- property bool wasOpened: false
z: 10000
+ mapSourceItem: _contentColumn
+ actionEnabled: item.postActions
+ && item.actionPostId().length > 0
+ && item.actionAccountId() >= 0
+ && !item.lockScreenActive
+ && !item.housekeeping
+ interactionItems: [
+ {
+ name: "like",
+ symbol: "\u2605",
+ active: item.isFavourited,
+ inactiveText: item._favouriteActionText,
+ activeText: item._unfavouriteActionText
+ },
+ {
+ name: "reblog",
+ symbol: "\u21BB",
+ active: item.isReblogged,
+ inactiveText: item._boostActionText,
+ activeText: item._unboostActionText
+ }
+ ]
- onPositionChanged: {
- horizontalActions.xPos = _contentColumn.mapFromItem(actionMenu, mouse.x, mouse.y).x
+ onInteractionMenuOpened: item._contextMenuOpen = true
+ onInteractionMenuClosed: {
+ item._contextMenuOpen = false
+ destroy()
+ item._actionMenu = null
}
- onMenuOpenChanged: {
- if (menuOpen) {
- wasOpened = true
- item._contextMenuOpen = true
- } else if (wasOpened) {
- item._contextMenuOpen = false
- destroy()
- item._actionMenu = null
+ onInteractionTriggered: function(actionName) {
+ if (!actionEnabled) {
+ return
}
- }
-
- Item {
- id: horizontalActions
-
- // Makes Silica treat this custom row as a context-menu item.
- property int __silica_menuitem
- property bool down
- property bool highlighted
- signal clicked
-
- property real xPos: 0
- property int hoveredIndex: -1
- readonly property bool actionEnabled: item.postActions
- && item.actionPostId().length > 0
- && item.actionAccountId() >= 0
- && !item.lockScreenActive
- && !item.housekeeping
-
- width: parent.width
- height: Theme.itemSizeMedium
-
- onXPosChanged: hoveredIndex = xPos < width / 2 ? 0 : 1
- onDownChanged: if (!down) hoveredIndex = -1
-
- onClicked: {
- xPos = _contentColumn.mapFromItem(actionMenu, actionMenu.mouseX, actionMenu.mouseY).x
- var index = hoveredIndex >= 0 ? hoveredIndex : (xPos < width / 2 ? 0 : 1)
- if (!actionEnabled) {
- return
- }
- var postId = item.actionPostId()
- var accountId = item.actionAccountId()
- if (index === 0) {
- if (item.isFavourited) {
- item.postActions.unfavourite(accountId, postId)
- } else {
- item.postActions.favourite(accountId, postId)
- }
+ var postId = item.actionPostId()
+ var accountId = item.actionAccountId()
+ if (actionName === "like") {
+ if (item.isFavourited) {
+ item.postActions.unfavourite(accountId, postId)
} else {
- if (item.isReblogged) {
- item.postActions.unboost(accountId, postId)
- } else {
- item.postActions.boost(accountId, postId)
- }
+ item.postActions.favourite(accountId, postId)
}
- }
-
- Rectangle {
- anchors.verticalCenter: parent.verticalCenter
- x: horizontalActions.hoveredIndex === 1 ? parent.width / 2 : 0
- width: parent.width / 2
- height: parent.height
- visible: horizontalActions.down && horizontalActions.hoveredIndex >= 0
- color: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
- }
-
- Row {
- anchors.fill: parent
-
- Label {
- width: parent.width / 2
- height: parent.height
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: Theme.fontSizeExtraLarge
- text: "★"
- color: horizontalActions.actionEnabled
- ? (item.isFavourited
- ? Theme.highlightColor
- : ((horizontalActions.down && horizontalActions.hoveredIndex === 0)
- || (horizontalActions.highlighted && horizontalActions.hoveredIndex === 0)
- ? Theme.secondaryHighlightColor : Theme.primaryColor))
- : Theme.rgba(Theme.secondaryColor, 0.4)
- }
-
- Label {
- width: parent.width / 2
- height: parent.height
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: Theme.fontSizeExtraLarge
- text: "↻"
- color: horizontalActions.actionEnabled
- ? (item.isReblogged
- ? Theme.highlightColor
- : ((horizontalActions.down && horizontalActions.hoveredIndex === 1)
- || (horizontalActions.highlighted && horizontalActions.hoveredIndex === 1)
- ? Theme.secondaryHighlightColor : Theme.primaryColor))
- : Theme.rgba(Theme.secondaryColor, 0.4)
+ } else if (actionName === "reblog") {
+ if (item.isReblogged) {
+ item.postActions.unboost(accountId, postId)
+ } else {
+ item.postActions.boost(accountId, postId)
}
}
}