summaryrefslogtreecommitdiff
path: root/eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml
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/eventsview-plugin-mastodon/mastodon-delegate.qml
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/eventsview-plugin-mastodon/mastodon-delegate.qml')
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/mastodon-delegate.qml170
1 files changed, 68 insertions, 102 deletions
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
}
}