From 5fb6483eb3674ff42ba7022127425ef7e7a9432f Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Mon, 6 Apr 2026 13:20:06 +0200 Subject: Fediverse --- .../fediverse-delegate.qml | 49 ++++++++++-- .../fediversepostsmodel.cpp | 2 +- settings/accounts/ui/fediverse.qml | 92 +++++++++++++++++----- .../fediverseshareplugin/fediverseplugininfo.cpp | 2 +- .../fediverseshareplugin/fediverseshareplugin.cpp | 2 +- .../fediverseshareplugin/fediverseshareplugin.h | 2 +- .../fediversetransferplugin.cpp | 2 +- .../fediversetransferplugin.h | 2 +- 8 files changed, 120 insertions(+), 33 deletions(-) diff --git a/eventsview-plugins/eventsview-plugin-fediverse/fediverse-delegate.qml b/eventsview-plugins/eventsview-plugin-fediverse/fediverse-delegate.qml index f954db4..334be86 100644 --- a/eventsview-plugins/eventsview-plugin-fediverse/fediverse-delegate.qml +++ b/eventsview-plugins/eventsview-plugin-fediverse/fediverse-delegate.qml @@ -23,16 +23,25 @@ SocialMediaAccountDelegate { showRemainingCount: false services: ["Posts"] - socialNetwork: SocialSync.Fediverse + socialNetwork: 9 dataType: SocialSync.Posts providerName: "fediverse" - periodicSyncLoopEnabled: true FediversePostActions { id: fediversePostActions } - model: FediversePostsModel {} + model: FediversePostsModel { + onCountChanged: { + if (count > 0) { + if (!updateTimer.running) { + shortUpdateTimer.start() + } + } else { + shortUpdateTimer.stop() + } + } + } delegate: FediverseFeedItem { downloader: delegateItem.downloader @@ -78,17 +87,19 @@ SocialMediaAccountDelegate { if (viewVisible) { delegateItem.resetHasSyncableAccounts() delegateItem.model.refresh() - if (delegateItem.hasSyncableAccounts) { - delegateItem.startPeriodicSyncLoop() + if (delegateItem.hasSyncableAccounts && !updateTimer.running) { + shortUpdateTimer.start() } } else { - delegateItem.stopPeriodicSyncLoop() + shortUpdateTimer.stop() } } onConnectedToNetworkChanged: { if (viewVisible) { - delegateItem.startPeriodicSyncLoop() + if (!updateTimer.running) { + shortUpdateTimer.start() + } } } @@ -103,6 +114,30 @@ SocialMediaAccountDelegate { } } + Timer { + id: shortUpdateTimer + + interval: 3000 + onTriggered: { + delegateItem.sync() + updateTimer.start() + } + } + + Timer { + id: updateTimer + + interval: 60000 + repeat: true + onTriggered: { + if (delegateItem.viewVisible) { + delegateItem.sync() + } else { + stop() + } + } + } + function statusUrl(modelData) { var directUrl = modelData && modelData.url ? modelData.url.toString() : "" if (directUrl.length > 0) { diff --git a/eventsview-plugins/eventsview-plugin-fediverse/fediversepostsmodel.cpp b/eventsview-plugins/eventsview-plugin-fediverse/fediversepostsmodel.cpp index 48b3446..b6d0aa3 100644 --- a/eventsview-plugins/eventsview-plugin-fediverse/fediversepostsmodel.cpp +++ b/eventsview-plugins/eventsview-plugin-fediverse/fediversepostsmodel.cpp @@ -39,7 +39,7 @@ QVariantList imageListForPost(const SocialPost::ConstPtr &post) imageMap.insert(QStringLiteral("url"), image->url()); imageMap.insert(QStringLiteral("type"), image->type() == SocialPostImage::Video ? QStringLiteral("video") - : QStringLiteral("image")); + : QStringLiteral("photo")); images.append(imageMap); } diff --git a/settings/accounts/ui/fediverse.qml b/settings/accounts/ui/fediverse.qml index 3f5968a..b29e68e 100644 --- a/settings/accounts/ui/fediverse.qml +++ b/settings/accounts/ui/fediverse.qml @@ -88,6 +88,7 @@ AccountCreationAgent { return { "apiHost": normalizedApiHost, "oauthHost": oauthHost(normalizedApiHost), + //% "Fediverse" "instanceTitle": title.length > 0 ? title : qsTrId("settings-accounts-fediverse-la-provider_name"), "instanceDescription": "", "instanceIconUrl": "", @@ -130,24 +131,70 @@ AccountCreationAgent { return "" } - if (responseData.thumbnail) { - if (typeof responseData.thumbnail === "string") { - return _normalizeResourceUrl(responseData.thumbnail, apiHost) - } - if (responseData.thumbnail.url) { - return _normalizeResourceUrl(responseData.thumbnail.url, apiHost) + function normalizedIconUrl(candidate) { + return _normalizeResourceUrl(_trimmedString(candidate), apiHost) + } + + function iconScore(iconObject) { + var size = _trimmedString(iconObject && iconObject.size) + var match = size.match(/^(\d+)x(\d+)$/) + if (!match) { + return 1000000 } - if (responseData.thumbnail.static_url) { - return _normalizeResourceUrl(responseData.thumbnail.static_url, apiHost) + + var width = parseInt(match[1], 10) + var height = parseInt(match[2], 10) + if (!(width > 0) || !(height > 0)) { + return 1000000 } + + var area = width * height + var squarenessPenalty = Math.abs(width - height) * 1000 + var sizePenalty = Math.abs(Math.max(width, height) - 64) + return squarenessPenalty + sizePenalty + area } if (responseData.icon) { if (typeof responseData.icon === "string") { - return _normalizeResourceUrl(responseData.icon, apiHost) + return normalizedIconUrl(responseData.icon) + } + + if (responseData.icon.src) { + return normalizedIconUrl(responseData.icon.src) + } + + if (responseData.icon.length > 0) { + var bestIndex = -1 + var bestScore = Number.MAX_VALUE + for (var i = 0; i < responseData.icon.length; ++i) { + var candidate = responseData.icon[i] + var candidateUrl = normalizedIconUrl(candidate && candidate.src) + if (candidateUrl.length === 0) { + continue + } + + var score = iconScore(candidate) + if (score < bestScore) { + bestScore = score + bestIndex = i + } + } + + if (bestIndex >= 0) { + return normalizedIconUrl(responseData.icon[bestIndex].src) + } } - if (responseData.icon.url) { - return _normalizeResourceUrl(responseData.icon.url, apiHost) + } + + if (responseData.thumbnail) { + if (typeof responseData.thumbnail === "string") { + return normalizedIconUrl(responseData.thumbnail) + } + if (responseData.thumbnail.url) { + return normalizedIconUrl(responseData.thumbnail.url) + } + if (responseData.thumbnail.static_url) { + return normalizedIconUrl(responseData.thumbnail.static_url) } } @@ -192,6 +239,7 @@ AccountCreationAgent { } if (xhr.status < 200 || xhr.status >= 300) { + //% "Failed to register the Fediverse application for %1" _showRegistrationError(qsTrId("settings-accounts-fediverse-la-register_app_failed").arg(context.apiHost), busyPage) return } @@ -200,11 +248,13 @@ AccountCreationAgent { try { response = JSON.parse(xhr.responseText) } catch (err) { + //% "Invalid response while registering the Fediverse application" _showRegistrationError(qsTrId("settings-accounts-fediverse-la-invalid_app_registration_response"), busyPage) return } if (!response.client_id || !response.client_secret) { + //% "Fediverse application registration did not return client credentials" _showRegistrationError(qsTrId("settings-accounts-fediverse-la-app_registration_missing_credentials"), busyPage) return } @@ -215,6 +265,7 @@ AccountCreationAgent { } var postData = [] + //% "SailfishOS Fediverse" postData.push("client_name=" + encodeURIComponent(qsTrId("settings-accounts-fediverse-la-client_name"))) postData.push("redirect_uris=" + encodeURIComponent(callbackUri)) postData.push("scopes=" + encodeURIComponent("read write")) @@ -358,6 +409,7 @@ AccountCreationAgent { _goToSettings(accountId) }) _accountSetup.error.connect(function() { + //% "Failed to finish Fediverse account setup" accountCreationError(qsTrId("settings-accounts-fediverse-la-account_setup_failed")) }) } @@ -427,6 +479,7 @@ AccountCreationAgent { width: parent.width - promptIcon.width - parent.spacing wrapMode: Text.Wrap color: Theme.highlightColor + //% "Enter the server address, then sign in." text: qsTrId("settings-accounts-fediverse-la-enter_server_then_sign_in") } } @@ -435,6 +488,7 @@ AccountCreationAgent { id: instanceField x: Theme.horizontalPageMargin width: parent.width - x * 2 + //% "Server" label: qsTrId("settings-accounts-fediverse-la-server") placeholderText: root.defaultServerHost inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhUrlCharactersOnly @@ -451,6 +505,7 @@ AccountCreationAgent { Component { id: busyComponent AccountBusyPage { + //% "Preparing Fediverse sign-in..." busyDescription: qsTrId("settings-accounts-fediverse-la-preparing_sign_in") onStatusChanged: { if (status === PageStatus.Active && root._pendingApiHost.length > 0) { @@ -532,6 +587,7 @@ AccountCreationAgent { function _effectiveInstanceTitle() { var title = root._trimmedString(instanceTitle) + //% "Fediverse" return title.length > 0 ? title : qsTrId("settings-accounts-fediverse-la-provider_name") } @@ -542,10 +598,6 @@ AccountCreationAgent { function _applyIconPath(iconPath) { instanceIconPath = iconPath newAccount.setConfigurationValue("", "iconPath", _effectiveIconPath()) - var services = _serviceNames() - for (var i = 0; i < services.length; ++i) { - newAccount.setConfigurationValue(services[i], "iconPath", _effectiveIconPath()) - } if (hasConfigured) { newAccount.sync() } @@ -580,7 +632,11 @@ AccountCreationAgent { } for (var i = 0; i < services.length; ++i) { - var service = services[i] + newAccount.enableWithService(services[i]) + } + + for (var j = 0; j < services.length; ++j) { + var service = services[j] newAccount.setConfigurationValue(service, "api/Host", apiHost) newAccount.setConfigurationValue(service, "auth/oauth2/web_server/Host", oauthHost) newAccount.setConfigurationValue(service, "auth/oauth2/web_server/AuthPath", "oauth/authorize") @@ -592,10 +648,6 @@ AccountCreationAgent { newAccount.setConfigurationValue(service, "auth/oauth2/web_server/ClientSecret", clientSecret) } - for (var j = 0; j < services.length; ++j) { - newAccount.enableWithService(services[j]) - } - if (instanceIconUrl.length > 0 && instanceIconPath.length === 0) { instanceIconCache.cacheIcon(apiHost, instanceIconUrl) } diff --git a/transferengine-plugins/fediverseshareplugin/fediverseplugininfo.cpp b/transferengine-plugins/fediverseshareplugin/fediverseplugininfo.cpp index 4e04be1..8829b9f 100644 --- a/transferengine-plugins/fediverseshareplugin/fediverseplugininfo.cpp +++ b/transferengine-plugins/fediverseshareplugin/fediverseplugininfo.cpp @@ -49,7 +49,7 @@ void FediversePluginInfo::serviceReady() info.setSubtitle(details.displayName); info.setAccountId(details.accountId); - info.setMethodId(QLatin1String("Fediverse")); + info.setMethodId(QLatin1String("Mastodon")); info.setMethodIcon(details.iconPath.isEmpty() ? QLatin1String("image://theme/icon-l-fediverse") : details.iconPath); diff --git a/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.cpp b/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.cpp index 18c9c7c..800100d 100644 --- a/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.cpp +++ b/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.cpp @@ -25,5 +25,5 @@ SharingPluginInfo *FediverseSharePlugin::infoObject() QString FediverseSharePlugin::pluginId() const { - return QLatin1String("Fediverse"); + return QLatin1String("Mastodon"); } diff --git a/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.h b/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.h index 0eb7772..332be4b 100644 --- a/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.h +++ b/transferengine-plugins/fediverseshareplugin/fediverseshareplugin.h @@ -14,7 +14,7 @@ class Q_DECL_EXPORT FediverseSharePlugin : public QObject, public SharingPluginInterface { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.sailfishos.share.plugin.fediverse") + Q_PLUGIN_METADATA(IID "org.sailfishos.share.plugin.mastodon") Q_INTERFACES(SharingPluginInterface) public: diff --git a/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.cpp b/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.cpp index bd213f8..4a59f56 100644 --- a/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.cpp +++ b/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.cpp @@ -27,5 +27,5 @@ MediaTransferInterface *FediverseTransferPlugin::transferObject() QString FediverseTransferPlugin::pluginId() const { - return QLatin1String("Fediverse"); + return QLatin1String("Mastodon"); } diff --git a/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.h b/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.h index 163d23f..c506698 100644 --- a/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.h +++ b/transferengine-plugins/fediversetransferplugin/fediversetransferplugin.h @@ -16,7 +16,7 @@ class QNetworkAccessManager; class Q_DECL_EXPORT FediverseTransferPlugin : public QObject, public TransferPluginInterface { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.sailfishos.transfer.plugin.fediverse") + Q_PLUGIN_METADATA(IID "org.sailfishos.transfer.plugin.mastodon") Q_INTERFACES(TransferPluginInterface) public: -- cgit v1.2.3