summaryrefslogtreecommitdiff
path: root/eventsview-plugins
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@jolla.com>2026-03-22 20:18:39 +0100
committerAndrew Branson <andrew.branson@jolla.com>2026-03-22 20:25:03 +0100
commit218a05f6ac67f260288ff70344f0f004c7b48c7b (patch)
treed213c375b94b467aa439aabf9810554087b29ec0 /eventsview-plugins
parent2b1a3046832074e47ad2ad703cd518526b9fb459 (diff)
Use shared buteo-common and split notifications service on mainmain
Keep main as the branch that builds against the newer shared social sync modules, while master stays self-contained. - drop the bundled buteo-common sources and stop building or packaging libmastodonbuteocommon - link the Mastodon sync plugins against buteosocialcommon and add the matching build/runtime package requirements - install a dedicated mastodon-notifications account service and wire account creation/packaging around the separate notifications profile - move the posts/events-view side over to the newer shared-helper style used with the updated socialcache stack - clean up qmake project wiring for the shared-module layout and refresh the branch README to describe the split service model - keep the notification schedule at the master value instead of carrying the temporary timing tweak
Diffstat (limited to 'eventsview-plugins')
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml318
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/eventsview-plugin-mastodon.pro1
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml170
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp51
4 files changed, 174 insertions, 366 deletions
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
index 63b9556..e9c76da 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
+++ b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
@@ -15,14 +15,14 @@ SocialMediaFeedItem {
id: item
property variant imageList
- property string resolvedStatusUrl: item.stringValue("url", "link", "uri")
+ property string resolvedStatusUrl: model && model.url ? model.url.toString() : ""
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: model && model.favouritesCount ? model.favouritesCount : 0
+ property int commentCount: model && model.repliesCount ? model.repliesCount : 0
+ property int boostCount: model && model.reblogsCount ? model.reblogsCount : 0
+ property bool favourited: model ? !!model.favourited : false
+ property bool reblogged: model ? !!model.reblogged : false
property int _likeCountOverride: -1
property int _boostCountOverride: -1
property int _favouritedOverride: -1
@@ -41,6 +41,18 @@ SocialMediaFeedItem {
property string _accountName: model && model.accountName ? model.accountName.toString() : ""
property string _bodyText: model && model.body ? model.body.toString() : ""
//: 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")
+ //: Action label shown in Mastodon interaction menu.
//% "Share"
readonly property string _shareActionText: qsTrId("lipstick-jolla-home-la-mastodon_share")
//: Link title used when sharing a Mastodon post.
@@ -86,7 +98,7 @@ SocialMediaFeedItem {
topMargin: item._booster.length > 0 ? Theme.paddingMedium : Theme.paddingLarge
userRemovable: false
- Image {
+ SocialReshareIcon {
id: boosterIcon
anchors {
@@ -95,21 +107,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"
@@ -157,61 +165,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 {
@@ -227,39 +192,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 model && model.mastodonId ? model.mastodonId.toString() : ""
}
function actionAccountId() {
@@ -268,7 +205,7 @@ SocialMediaFeedItem {
}
function shareStatusUrl() {
- return item.stringValue("url", "link", "uri")
+ return model && model.url ? model.url.toString() : ""
}
function topLevelParent() {
@@ -327,141 +264,78 @@ 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",
+ // U+2605 BLACK STAR
+ symbol: "\u2605",
+ active: item.isFavourited,
+ inactiveText: item._favouriteActionText,
+ activeText: item._unfavouriteActionText
+ },
+ {
+ name: "reblog",
+ // U+21BB CLOCKWISE OPEN CIRCLE ARROW
+ symbol: "\u21BB",
+ active: item.isReblogged,
+ inactiveText: item._boostActionText,
+ activeText: item._unboostActionText
+ },
+ {
+ name: "share",
+ // U+260D OPPOSITION (ironic doncha think)
+ symbol: "\u260D",
+ active: false,
+ inactiveText: item._shareActionText,
+ activeText: item._shareActionText
+ }
+ ]
- 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 = Math.max(0, Math.min(2, Math.floor((xPos * 3) / Math.max(1, width))))
- onDownChanged: if (!down) hoveredIndex = -1
-
- onClicked: {
- xPos = _contentColumn.mapFromItem(actionMenu, actionMenu.mouseX, actionMenu.mouseY).x
- var index = hoveredIndex >= 0 ? hoveredIndex : Math.max(0, Math.min(2, Math.floor((xPos * 3) / Math.max(1, width))))
- 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)
- }
- } else if (index === 1) {
- if (item.isReblogged) {
- item.postActions.unboost(accountId, postId)
- } else {
- item.postActions.boost(accountId, postId)
- }
+ var postId = item.actionPostId()
+ var accountId = item.actionAccountId()
+ if (actionName === "like") {
+ if (item.isFavourited) {
+ item.postActions.unfavourite(accountId, postId)
} else {
- var shareUrl = item.shareStatusUrl()
- if (shareUrl.length === 0) {
- return
- }
- item._shareAction.resources = [{
- "data": shareUrl,
- "linkTitle": item._shareLinkTitle,
- "type": "text/x-url"
- }]
- item._shareAction.trigger()
+ item.postActions.favourite(accountId, postId)
}
- }
-
- Rectangle {
- anchors.verticalCenter: parent.verticalCenter
- x: (horizontalActions.hoveredIndex >= 0 ? horizontalActions.hoveredIndex : 0) * (parent.width / 3)
- width: parent.width / 3
- height: parent.height
- visible: horizontalActions.down && horizontalActions.hoveredIndex >= 0
- color: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
- }
-
- Row {
- anchors.fill: parent
-
- Label {
- width: parent.width / 3
- 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 / 3
- 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)
}
-
- Label {
- width: parent.width / 3
- height: parent.height
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: Theme.fontSizeExtraLarge
- text: "\u260D"
- color: horizontalActions.actionEnabled
- ? (((horizontalActions.down && horizontalActions.hoveredIndex === 2)
- || (horizontalActions.highlighted && horizontalActions.hoveredIndex === 2))
- ? Theme.secondaryHighlightColor : Theme.primaryColor)
- : Theme.rgba(Theme.secondaryColor, 0.4)
+ } else if (actionName === "share") {
+ var shareUrl = item.shareStatusUrl()
+ if (shareUrl.length === 0) {
+ return
}
+ item._shareAction.resources = [{
+ "data": shareUrl,
+ "linkTitle": item._shareLinkTitle,
+ "type": "text/x-url"
+ }]
+ item._shareAction.trigger()
}
}
}
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/eventsview-plugin-mastodon.pro b/eventsview-plugins/eventsview-plugin-mastodon/eventsview-plugin-mastodon.pro
index 04be215..8c9663e 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/eventsview-plugin-mastodon.pro
+++ b/eventsview-plugins/eventsview-plugin-mastodon/eventsview-plugin-mastodon.pro
@@ -9,6 +9,7 @@ TARGET = $$qtLibraryTarget($$TARGET)
MODULENAME = com/jolla/eventsview/mastodon
TARGETPATH = $$[QT_INSTALL_QML]/$$MODULENAME
+QT -= gui
QT += qml network
CONFIG += plugin link_pkgconfig
PKGCONFIG += socialcache accounts-qt5 libsignon-qt5 sailfishaccounts
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml b/eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml
index fac0b89..2a5d9c1 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml
+++ b/eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml
@@ -13,6 +13,7 @@ import "shared"
SocialMediaAccountDelegate {
id: delegateItem
+ property string instanceHomeUrl: ""
//: Mastodon posts
//% "Posts"
@@ -21,39 +22,35 @@ SocialMediaAccountDelegate {
showRemainingCount: false
services: ["Posts"]
- socialNetwork: 9
+ socialNetwork: SocialSync.Mastodon
dataType: SocialSync.Posts
providerName: "mastodon"
+ periodicSyncLoopEnabled: true
MastodonPostActions {
id: mastodonPostActions
}
- model: MastodonPostsModel {
- onCountChanged: {
- if (count > 0) {
- if (!updateTimer.running) {
- shortUpdateTimer.start()
- }
- } else {
- shortUpdateTimer.stop()
- }
- }
- }
+ model: MastodonPostsModel {}
delegate: MastodonFeedItem {
downloader: delegateItem.downloader
- imageList: delegateItem.variantRole(model, ["images", "mediaAttachments", "media"])
- avatarSource: delegateItem.convertUrl(delegateItem.stringRole(model, ["icon", "avatar", "avatarUrl"]))
- fallbackAvatarSource: delegateItem.stringRole(model, ["icon", "avatar", "avatarUrl"])
+ imageList: model.images
+ avatarSource: model.icon
+ fallbackAvatarSource: model.icon
resolvedStatusUrl: delegateItem.authorizeInteractionUrl(model)
- postId: delegateItem.stringRole(model, ["mastodonId", "statusId", "id", "twitterId"])
+ postId: model.mastodonId
postActions: mastodonPostActions
- accountId: delegateItem.firstAccountId(model)
+ accountId: delegateItem.firstAccountId(model, -1)
- onTriggered: Qt.openUrlExternally(resolvedStatusUrl)
+ onTriggered: {
+ if (resolvedStatusUrl.length > 0) {
+ Qt.openUrlExternally(resolvedStatusUrl)
+ }
+ }
Component.onCompleted: {
+ delegateItem.instanceHomeUrl = statusUrl({instanceUrl: model.instanceUrl})
refreshTimeCount = Qt.binding(function() { return delegateItem.refreshTimeCount })
connectedToNetwork = Qt.binding(function() { return delegateItem.connectedToNetwork })
eventsColumnMaxWidth = Qt.binding(function() { return delegateItem.eventsColumnMaxWidth })
@@ -62,101 +59,61 @@ SocialMediaAccountDelegate {
//% "Show more in Mastodon"
expandedLabel: qsTrId("lipstick-jolla-home-la-show-more-in-mastodon")
- onHeaderClicked: Qt.openUrlExternally("https://mastodon.social/explore")
- onExpandedClicked: Qt.openUrlExternally("https://mastodon.social/explore")
+ onHeaderClicked: {
+ if (delegateItem.instanceHomeUrl.length > 0) {
+ Qt.openUrlExternally(delegateItem.instanceHomeUrl)
+ }
+ }
+ onExpandedClicked: {
+ if (delegateItem.instanceHomeUrl.length > 0) {
+ Qt.openUrlExternally(delegateItem.instanceHomeUrl)
+ }
+ }
onViewVisibleChanged: {
if (viewVisible) {
delegateItem.resetHasSyncableAccounts()
delegateItem.model.refresh()
- if (delegateItem.hasSyncableAccounts && !updateTimer.running) {
- shortUpdateTimer.start()
+ if (delegateItem.hasSyncableAccounts) {
+ delegateItem.startPeriodicSyncLoop()
}
} else {
- shortUpdateTimer.stop()
+ delegateItem.stopPeriodicSyncLoop()
}
}
onConnectedToNetworkChanged: {
if (viewVisible) {
- if (!updateTimer.running) {
- shortUpdateTimer.start()
- }
- }
- }
-
- // The Mastodon feed is updated 3 seconds after the feed view becomes visible,
- // unless it has been updated during last 60 seconds. After that it will be updated
- // periodically in every 60 seconds as long as the feed view is visible.
-
- Timer {
- id: shortUpdateTimer
-
- interval: 3000
- onTriggered: {
- delegateItem.sync()
- updateTimer.start()
+ delegateItem.startPeriodicSyncLoop()
}
}
- Timer {
- id: updateTimer
+ Connections {
+ target: delegateItem.model
- interval: 60000
- repeat: true
- onTriggered: {
- if (delegateItem.viewVisible) {
- delegateItem.sync()
- } else {
- stop()
- }
- }
- }
-
- function variantRole(modelData, roleNames) {
- for (var i = 0; i < roleNames.length; ++i) {
- var value = modelData[roleNames[i]]
- if (typeof value !== "undefined" && value !== null) {
- return value
- }
- }
- return undefined
- }
-
- function stringRole(modelData, roleNames) {
- for (var i = 0; i < roleNames.length; ++i) {
- var value = modelData[roleNames[i]]
- if (typeof value === "undefined" || value === null) {
- continue
- }
- value = String(value)
- if (value.length > 0) {
- return value
+ onCountChanged: {
+ if (target.count === 0) {
+ delegateItem.instanceHomeUrl = ""
}
}
- return ""
}
function statusUrl(modelData) {
- var directUrl = stringRole(modelData, ["url", "link", "uri"])
+ var directUrl = modelData && modelData.url ? modelData.url.toString() : ""
if (directUrl.length > 0) {
return directUrl
}
- var instanceUrl = stringRole(modelData, ["instanceUrl", "serverUrl", "baseUrl"])
+ var instanceUrl = modelData && modelData.instanceUrl ? modelData.instanceUrl.toString() : ""
+ instanceUrl = stripTrailingSlashes(instanceUrl)
if (instanceUrl.length === 0) {
- instanceUrl = "https://mastodon.social"
- }
- while (instanceUrl.length > 0 && instanceUrl.charAt(instanceUrl.length - 1) === "/") {
- instanceUrl = instanceUrl.slice(0, instanceUrl.length - 1)
+ return ""
}
- var accountName = stringRole(modelData, ["accountName", "acct", "screenName", "username"])
- var statusId = stringRole(modelData, ["mastodonId", "statusId", "id", "twitterId"])
+ var accountName = modelData && modelData.accountName ? modelData.accountName.toString() : ""
+ var statusId = modelData && modelData.mastodonId ? modelData.mastodonId.toString() : ""
if (accountName.length > 0 && statusId.length > 0) {
- while (accountName.length > 0 && accountName.charAt(0) === "@") {
- accountName = accountName.substring(1)
- }
+ accountName = trimLeadingCharacter(accountName, "@")
return instanceUrl + "/@" + accountName + "/" + statusId
}
@@ -169,13 +126,11 @@ SocialMediaAccountDelegate {
return targetUrl
}
- var instanceUrl = stringRole(modelData, ["instanceUrl", "serverUrl", "baseUrl"])
+ var instanceUrl = modelData && modelData.instanceUrl ? modelData.instanceUrl.toString() : ""
if (instanceUrl.length === 0) {
return targetUrl
}
- while (instanceUrl.length > 0 && instanceUrl.charAt(instanceUrl.length - 1) === "/") {
- instanceUrl = instanceUrl.slice(0, instanceUrl.length - 1)
- }
+ instanceUrl = stripTrailingSlashes(instanceUrl)
// Links on the user's own instance should open directly.
var sameServer = /^([a-z][a-z0-9+.-]*):\/\/([^\/?#]+)/i
@@ -192,23 +147,34 @@ SocialMediaAccountDelegate {
return instanceUrl + "/authorize_interaction?uri=" + encodeURIComponent(targetUrl)
}
- function convertUrl(source) {
- if (source.indexOf("_normal.") !== -1) {
- return source.replace("_normal.", "_bigger.")
- } else if (source.indexOf("_mini.") !== -1) {
- return source.replace("_mini.", "_bigger.")
+ function firstAccountId(modelData, defaultValue) {
+ var fallback = typeof defaultValue === "undefined" ? -1 : Number(defaultValue)
+ var accounts = modelData ? modelData.accounts : undefined
+ if (!accounts || accounts.length <= 0) {
+ return fallback
}
- return source
+
+ var accountId = Number(accounts[0])
+ return isNaN(accountId) ? fallback : accountId
}
- function firstAccountId(modelData) {
- var accounts = modelData.accounts
- if (accounts && accounts.length > 0) {
- var accountId = Number(accounts[0])
- if (!isNaN(accountId)) {
- return accountId
- }
+ function stripTrailingSlashes(value) {
+ value = String(value || "")
+ while (value.length > 0 && value.charAt(value.length - 1) === "/") {
+ value = value.slice(0, value.length - 1)
+ }
+ return value
+ }
+
+ function trimLeadingCharacter(value, character) {
+ value = String(value || "")
+ if (!character || character.length === 0) {
+ return value
+ }
+
+ while (value.length > 0 && value.charAt(0) === character) {
+ value = value.substring(1)
}
- return -1
+ return value
}
}
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
index aa98a95..fe61320 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
+++ b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
@@ -17,31 +17,7 @@
*/
#include "mastodonpostsmodel.h"
-#include <QtCore/QVariantMap>
-
-namespace {
-
-static const char *URL_KEY = "url";
-static const char *TYPE_KEY = "type";
-static const char *TYPE_PHOTO = "photo";
-static const char *TYPE_VIDEO = "video";
-
-QVariantMap createImageData(const SocialPostImage::ConstPtr &image)
-{
- QVariantMap imageData;
- imageData.insert(QLatin1String(URL_KEY), image->url());
- switch (image->type()) {
- case SocialPostImage::Video:
- imageData.insert(QLatin1String(TYPE_KEY), QLatin1String(TYPE_VIDEO));
- break;
- default:
- imageData.insert(QLatin1String(TYPE_KEY), QLatin1String(TYPE_PHOTO));
- break;
- }
- return imageData;
-}
-
-}
+#include <socialcache/socialposthelpers.h>
MastodonPostsModel::MastodonPostsModel(QObject *parent)
: QAbstractListModel(parent)
@@ -123,13 +99,16 @@ void MastodonPostsModel::postsChanged()
const bool favourited = m_database.favourited(post);
const bool reblogged = m_database.reblogged(post);
- eventMap.insert(MastodonPostsModel::MastodonId, post->identifier());
- eventMap.insert(MastodonPostsModel::Name, post->name());
+ SocialPostHelpers::appendCommonPostFields(&eventMap, post,
+ MastodonPostsModel::MastodonId,
+ MastodonPostsModel::Name,
+ MastodonPostsModel::Body,
+ MastodonPostsModel::Timestamp,
+ MastodonPostsModel::Icon,
+ MastodonPostsModel::Images,
+ MastodonPostsModel::Accounts);
eventMap.insert(MastodonPostsModel::AccountName, accountName);
eventMap.insert(MastodonPostsModel::Acct, accountName);
- eventMap.insert(MastodonPostsModel::Body, post->body());
- eventMap.insert(MastodonPostsModel::Timestamp, post->timestamp());
- eventMap.insert(MastodonPostsModel::Icon, post->icon());
eventMap.insert(MastodonPostsModel::Url, postUrl);
eventMap.insert(MastodonPostsModel::Link, postUrl);
eventMap.insert(MastodonPostsModel::BoostedBy, boostedBy);
@@ -140,18 +119,6 @@ void MastodonPostsModel::postsChanged()
eventMap.insert(MastodonPostsModel::Favourited, favourited);
eventMap.insert(MastodonPostsModel::Reblogged, reblogged);
eventMap.insert(MastodonPostsModel::InstanceUrl, m_database.instanceUrl(post));
-
- QVariantList images;
- Q_FOREACH (const SocialPostImage::ConstPtr &image, post->images()) {
- images.append(createImageData(image));
- }
- eventMap.insert(MastodonPostsModel::Images, images);
-
- QVariantList accountsVariant;
- Q_FOREACH (int account, post->accounts()) {
- accountsVariant.append(account);
- }
- eventMap.insert(MastodonPostsModel::Accounts, accountsVariant);
data.append(eventMap);
}