diff options
| author | Andrew Branson <andrew.branson@jolla.com> | 2026-02-18 21:37:05 +0100 |
|---|---|---|
| committer | Andrew Branson <andrew.branson@jolla.com> | 2026-02-18 21:37:05 +0100 |
| commit | 60d8504a8b5b0d5e5fa40c4ab7df8e5f98c88e32 (patch) | |
| tree | 79529799246d3affe713775abdf5577e1f08d907 /eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml | |
| parent | 1ce97352a0aa2cea0be39fb7eb3a8333aadd2487 (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.qml | 281 |
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) } } } |
