summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@jolla.com>2026-03-19 16:48:51 +0100
committerAndrew Branson <andrew.branson@jolla.com>2026-03-19 16:48:51 +0100
commitc08a37b96fec1706a1eb560255d487ec6c8a05dc (patch)
tree5f2c3f059a5bce53e2bd189a40fd50c2a68d555d
parent5fe5ede124da1824fd3b055ec480bf9ce4a5b83f (diff)
Sync with main
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/buteo-sync-plugin-mastodon-notifications.pro27
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodondatatypesyncadaptor.cpp24
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationsplugin.cpp47
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp155
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml94
-rw-r--r--rpm/sailfish-account-mastodon.spec3
-rw-r--r--settings/accounts/accounts.pro2
-rw-r--r--settings/accounts/services/mastodon-microblog.service2
-rw-r--r--settings/accounts/services/mastodon-notifications.service31
-rw-r--r--settings/accounts/ui/MastodonSettingsDisplay.qml25
-rw-r--r--settings/accounts/ui/mastodon-update.qml3
-rw-r--r--settings/accounts/ui/mastodon.qml5
12 files changed, 291 insertions, 127 deletions
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/buteo-sync-plugin-mastodon-notifications.pro b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/buteo-sync-plugin-mastodon-notifications.pro
index 81060b1..3289487 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/buteo-sync-plugin-mastodon-notifications.pro
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/buteo-sync-plugin-mastodon-notifications.pro
@@ -5,6 +5,31 @@ QT -= gui
include($$PWD/../buteo-common/buteo-common.pri)
include($$PWD/../../common/common.pri)
+TS_FILE = $$OUT_PWD/lipstick-jolla-home-mastodon-notifications.ts
+EE_QM = $$OUT_PWD/lipstick-jolla-home-mastodon-notifications_eng_en.qm
+
+ts.commands += lupdate $$PWD -ts $$TS_FILE
+ts.CONFIG += no_check_exist no_link
+ts.output = $$TS_FILE
+ts.input = .
+
+ts_install.files = $$TS_FILE
+ts_install.path = /usr/share/translations/source
+ts_install.CONFIG += no_check_exist
+
+engineering_english.commands += lrelease -idbased $$TS_FILE -qm $$EE_QM
+engineering_english.CONFIG += no_check_exist no_link
+engineering_english.depends = ts
+engineering_english.input = $$TS_FILE
+engineering_english.output = $$EE_QM
+
+engineering_english_install.path = /usr/share/translations
+engineering_english_install.files = $$EE_QM
+engineering_english_install.CONFIG += no_check_exist
+
+QMAKE_EXTRA_TARGETS += ts engineering_english
+PRE_TARGETDEPS += ts engineering_english
+
CONFIG += link_pkgconfig
PKGCONFIG += mlite5 nemonotifications-qt5
@@ -34,4 +59,4 @@ sync.files = mastodon.Notifications.xml
client.path = /etc/buteo/profiles/client
client.files = mastodon-notifications.xml
-INSTALLS += target sync client
+INSTALLS += target sync client ts_install engineering_english_install
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodondatatypesyncadaptor.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodondatatypesyncadaptor.cpp
index 295d7b9..14b3511 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodondatatypesyncadaptor.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodondatatypesyncadaptor.cpp
@@ -20,8 +20,8 @@
#include "mastodondatatypesyncadaptor.h"
#include "mastodonauthutils.h"
-#include "trace.h"
+#include <QtCore/QLoggingCategory>
#include <QtCore/QVariantMap>
#include <QtNetwork/QNetworkRequest>
@@ -36,6 +36,8 @@
#include <SignOn/AuthSession>
#include <SignOn/SessionData>
+Q_LOGGING_CATEGORY(lcMastodonNotificationsSync, "buteo.plugin.mastodon.notifications.sync", QtWarningMsg)
+
MastodonNotificationsDataTypeSyncAdaptor::MastodonNotificationsDataTypeSyncAdaptor(
SocialNetworkSyncAdaptor::DataType dataType,
QObject *parent)
@@ -50,7 +52,7 @@ MastodonNotificationsDataTypeSyncAdaptor::~MastodonNotificationsDataTypeSyncAdap
void MastodonNotificationsDataTypeSyncAdaptor::sync(const QString &dataTypeString, int accountId)
{
if (dataTypeString != SocialNetworkSyncAdaptor::dataTypeName(m_dataType)) {
- qCWarning(lcSocialPlugin) << "Mastodon" << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
+ qCWarning(lcMastodonNotificationsSync) << "Mastodon" << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
<< "sync adaptor was asked to sync" << dataTypeString;
setStatus(SocialNetworkSyncAdaptor::Error);
return;
@@ -58,14 +60,14 @@ void MastodonNotificationsDataTypeSyncAdaptor::sync(const QString &dataTypeStrin
setStatus(SocialNetworkSyncAdaptor::Busy);
updateDataForAccount(accountId);
- qCDebug(lcSocialPlugin) << "successfully triggered sync with profile:" << m_accountSyncProfile->name();
+ qCDebug(lcMastodonNotificationsSync) << "successfully triggered sync with profile:" << m_accountSyncProfile->name();
}
void MastodonNotificationsDataTypeSyncAdaptor::updateDataForAccount(int accountId)
{
Accounts::Account *account = Accounts::Account::fromId(m_accountManager, accountId, this);
if (!account) {
- qCWarning(lcSocialPlugin) << "existing account with id" << accountId << "couldn't be retrieved";
+ qCWarning(lcMastodonNotificationsSync) << "existing account with id" << accountId << "couldn't be retrieved";
setStatus(SocialNetworkSyncAdaptor::Error);
return;
}
@@ -89,7 +91,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::errorHandler(QNetworkReply::Netwo
const int accountId = reply->property("accountId").toInt();
const int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- qCWarning(lcSocialPlugin) << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
+ qCWarning(lcMastodonNotificationsSync) << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
<< "request with account" << accountId
<< "experienced error:" << err
<< "HTTP:" << httpStatus;
@@ -114,7 +116,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::sslErrorsHandler(const QList<QSsl
sslerrs.chop(2);
}
- qCWarning(lcSocialPlugin) << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
+ qCWarning(lcMastodonNotificationsSync) << SocialNetworkSyncAdaptor::dataTypeName(m_dataType)
<< "request with account" << sender()->property("accountId").toInt()
<< "experienced ssl errors:" << sslerrs;
sender()->setProperty("isError", QVariant::fromValue<bool>(true));
@@ -122,7 +124,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::sslErrorsHandler(const QList<QSsl
void MastodonNotificationsDataTypeSyncAdaptor::setCredentialsNeedUpdate(Accounts::Account *account)
{
- qCInfo(lcSocialPlugin) << "sociald:Mastodon: setting CredentialsNeedUpdate to true for account:" << account->id();
+ qCInfo(lcMastodonNotificationsSync) << "sociald:Mastodon: setting CredentialsNeedUpdate to true for account:" << account->id();
Accounts::Service srv(m_accountManager->service(syncServiceName()));
account->selectService(srv);
account->setValue(QStringLiteral("CredentialsNeedUpdate"), QVariant::fromValue<bool>(true));
@@ -145,7 +147,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::signIn(Accounts::Account *account
? SignOn::Identity::existingIdentity(account->credentialsId())
: 0;
if (!identity) {
- qCWarning(lcSocialPlugin) << "account" << accountId << "has no valid credentials, cannot sign in";
+ qCWarning(lcMastodonNotificationsSync) << "account" << accountId << "has no valid credentials, cannot sign in";
decrementSemaphore(accountId);
return;
}
@@ -155,7 +157,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::signIn(Accounts::Account *account
const QString mechanism = accSrv.authData().mechanism();
SignOn::AuthSession *session = identity->createSession(method);
if (!session) {
- qCWarning(lcSocialPlugin) << "could not create signon session for account" << accountId;
+ qCWarning(lcMastodonNotificationsSync) << "could not create signon session for account" << accountId;
identity->deleteLater();
decrementSemaphore(accountId);
return;
@@ -183,7 +185,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::signOnError(const SignOn::Error &
SignOn::Identity *identity = session->property("identity").value<SignOn::Identity*>();
const int accountId = account->id();
- qCWarning(lcSocialPlugin) << "credentials for account with id" << accountId
+ qCWarning(lcMastodonNotificationsSync) << "credentials for account with id" << accountId
<< "couldn't be retrieved:" << error.type() << error.message();
if (error.type() == SignOn::Error::UserInteraction) {
@@ -211,7 +213,7 @@ void MastodonNotificationsDataTypeSyncAdaptor::signOnResponse(const SignOn::Sess
accessToken = MastodonAuthUtils::accessToken(data);
if (accessToken.isEmpty()) {
- qCWarning(lcSocialPlugin) << "signon response for account with id" << accountId
+ qCWarning(lcMastodonNotificationsSync) << "signon response for account with id" << accountId
<< "contained no access token; keys:" << data.keys();
}
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationsplugin.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationsplugin.cpp
index fe9f989..9dd3724 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationsplugin.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationsplugin.cpp
@@ -22,6 +22,52 @@
#include "mastodonnotificationssyncadaptor.h"
#include "socialnetworksyncadaptor.h"
+#include <QCoreApplication>
+#include <QLocale>
+#include <QTranslator>
+
+namespace {
+class AppTranslator : public QTranslator
+{
+public:
+ explicit AppTranslator(QObject *parent)
+ : QTranslator(parent)
+ {
+ qApp->installTranslator(this);
+ }
+
+ ~AppTranslator() override
+ {
+ qApp->removeTranslator(this);
+ }
+};
+
+void ensureNotificationTranslations()
+{
+ static bool initialized = false;
+ if (initialized) {
+ return;
+ }
+
+ QCoreApplication *app = QCoreApplication::instance();
+ if (!app) {
+ return;
+ }
+
+ AppTranslator *engineeringEnglish = new AppTranslator(app);
+ engineeringEnglish->load(QStringLiteral("lipstick-jolla-home-mastodon-notifications_eng_en"),
+ QStringLiteral("/usr/share/translations"));
+
+ AppTranslator *translator = new AppTranslator(app);
+ translator->load(QLocale(),
+ QStringLiteral("lipstick-jolla-home-mastodon-notifications"),
+ QStringLiteral("-"),
+ QStringLiteral("/usr/share/translations"));
+
+ initialized = true;
+}
+}
+
MastodonNotificationsPlugin::MastodonNotificationsPlugin(const QString& pluginName,
const Buteo::SyncProfile& profile,
Buteo::PluginCbInterface *callbackInterface)
@@ -29,6 +75,7 @@ MastodonNotificationsPlugin::MastodonNotificationsPlugin(const QString& pluginNa
QStringLiteral("mastodon"),
SocialNetworkSyncAdaptor::dataTypeName(SocialNetworkSyncAdaptor::Notifications))
{
+ ensureNotificationTranslations();
}
MastodonNotificationsPlugin::~MastodonNotificationsPlugin()
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
index dba8789..8a2c610 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
@@ -19,9 +19,10 @@
****************************************************************************/
#include "mastodonnotificationssyncadaptor.h"
-#include "trace.h"
#include "mastodontextutils.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QLoggingCategory>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonValue>
@@ -50,11 +51,79 @@
)
namespace {
+ Q_LOGGING_CATEGORY(lcMastodonNotifications, "buteo.plugin.mastodon.notifications", QtWarningMsg)
+
const char *const NotificationCategory = "x-nemo.social.mastodon.notification";
const char *const NotificationIdHint = "x-nemo.sociald.notification-id";
const char *const LastFetchedNotificationIdKey = "LastFetchedNotificationId";
const int NotificationsPageLimit = 80;
+ //% "mentioned you"
+ const char *const TrIdMentionedYou = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-mentioned_you");
+ //% "boosted your post"
+ const char *const TrIdBoostedYourPost = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-boosted_your_post");
+ //% "favourited your post"
+ const char *const TrIdFavouritedYourPost = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-favourited_your_post");
+ //% "started following you"
+ const char *const TrIdStartedFollowingYou = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-started_following_you");
+ //% "requested to follow you"
+ const char *const TrIdRequestedToFollowYou = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-requested_to_follow_you");
+ //% "interacted with your poll"
+ const char *const TrIdInteractedWithYourPoll = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-interacted_with_your_poll");
+ //% "posted"
+ const char *const TrIdPosted = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-posted");
+ //% "updated a post"
+ const char *const TrIdUpdatedPost = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-updated_post");
+ //% "signed up"
+ const char *const TrIdSignedUp = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-signed_up");
+ //% "reported an account"
+ const char *const TrIdReportedAccount = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-reported_account");
+ //% "received a moderation warning"
+ const char *const TrIdReceivedModerationWarning = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-received_moderation_warning");
+ //% "quoted your post"
+ const char *const TrIdQuotedYourPost = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-quoted_your_post");
+ //% "updated a post that quoted you"
+ const char *const TrIdUpdatedQuotedPost = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-updated_quoted_post");
+ //% "sent you a notification"
+ const char *const TrIdSentNotification = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-sent_notification");
+
+ //% "An admin blocked an instance"
+ const char *const TrIdAdminBlockedInstance = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-admin_blocked_instance");
+ //% "An admin blocked %1"
+ const char *const TrIdAdminBlockedTarget = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-admin_blocked_target");
+ //% "You blocked an instance"
+ const char *const TrIdYouBlockedInstance = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-you_blocked_instance");
+ //% "You blocked %1"
+ const char *const TrIdYouBlockedTarget = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-you_blocked_target");
+ //% "An account was suspended"
+ const char *const TrIdAccountSuspended = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-account_suspended");
+ //% "%1 was suspended"
+ const char *const TrIdTargetSuspended = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-target_suspended");
+ //% "Some follow relationships were severed"
+ const char *const TrIdRelationshipsSevered = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-relationships_severed");
+ //% "%1 (%2 followers, %3 following removed)"
+ const char *const TrIdRelationshipsSummary = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-relationships_summary");
+
+ //% "A moderator sent you a warning"
+ const char *const TrIdModeratorWarningNone = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_none");
+ //% "A moderator disabled your account"
+ const char *const TrIdModeratorWarningDisable = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_disable");
+ //% "A moderator marked specific posts as sensitive"
+ const char *const TrIdModeratorWarningSpecificSensitive = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_specific_sensitive");
+ //% "A moderator deleted specific posts"
+ const char *const TrIdModeratorWarningDeletePosts = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_delete_posts");
+ //% "A moderator marked all your posts as sensitive"
+ const char *const TrIdModeratorWarningAllSensitive = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_all_sensitive");
+ //% "A moderator limited your account"
+ const char *const TrIdModeratorWarningSilence = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_silence");
+ //% "A moderator suspended your account"
+ const char *const TrIdModeratorWarningSuspend = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-moderator_warning_suspend");
+
+ //% "Mastodon"
+ const char *const TrIdMastodon = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-mastodon");
+ //% "New notification"
+ const char *const TrIdNewNotification = QT_TRID_NOOP("lipstick-jolla-home-la-mastodon-notification-new_notification");
+
QString displayNameForAccount(const QJsonObject &account)
{
const QString displayName = account.value(QStringLiteral("display_name")).toString().trimmed();
@@ -73,34 +142,34 @@ namespace {
QString actionText(const QString &type)
{
if (type == QLatin1String("mention")) {
- return QStringLiteral("mentioned you");
+ return qtTrId(TrIdMentionedYou);
} else if (type == QLatin1String("reblog")) {
- return QStringLiteral("boosted your post");
+ return qtTrId(TrIdBoostedYourPost);
} else if (type == QLatin1String("favourite")) {
- return QStringLiteral("favourited your post");
+ return qtTrId(TrIdFavouritedYourPost);
} else if (type == QLatin1String("follow")) {
- return QStringLiteral("started following you");
+ return qtTrId(TrIdStartedFollowingYou);
} else if (type == QLatin1String("follow_request")) {
- return QStringLiteral("requested to follow you");
+ return qtTrId(TrIdRequestedToFollowYou);
} else if (type == QLatin1String("poll")) {
- return QStringLiteral("interacted with your poll");
+ return qtTrId(TrIdInteractedWithYourPoll);
} else if (type == QLatin1String("status")) {
- return QStringLiteral("posted");
+ return qtTrId(TrIdPosted);
} else if (type == QLatin1String("update")) {
- return QStringLiteral("updated a post");
+ return qtTrId(TrIdUpdatedPost);
} else if (type == QLatin1String("admin.sign_up")) {
- return QStringLiteral("signed up");
+ return qtTrId(TrIdSignedUp);
} else if (type == QLatin1String("admin.report")) {
- return QStringLiteral("reported an account");
+ return qtTrId(TrIdReportedAccount);
} else if (type == QLatin1String("moderation_warning")) {
- return QStringLiteral("received a moderation warning");
+ return qtTrId(TrIdReceivedModerationWarning);
} else if (type == QLatin1String("quote")) {
- return QStringLiteral("quoted your post");
+ return qtTrId(TrIdQuotedYourPost);
} else if (type == QLatin1String("quoted_update")) {
- return QStringLiteral("updated a post that quoted you");
+ return qtTrId(TrIdUpdatedQuotedPost);
}
- return QStringLiteral("sent you a notification");
+ return qtTrId(TrIdSentNotification);
}
bool useSystemSummary(const QString &notificationType)
@@ -119,18 +188,18 @@ namespace {
QString action;
if (eventType == QLatin1String("domain_block")) {
action = targetName.isEmpty()
- ? QStringLiteral("An admin blocked an instance")
- : QStringLiteral("An admin blocked %1").arg(targetName);
+ ? qtTrId(TrIdAdminBlockedInstance)
+ : qtTrId(TrIdAdminBlockedTarget).arg(targetName);
} else if (eventType == QLatin1String("user_domain_block")) {
action = targetName.isEmpty()
- ? QStringLiteral("You blocked an instance")
- : QStringLiteral("You blocked %1").arg(targetName);
+ ? qtTrId(TrIdYouBlockedInstance)
+ : qtTrId(TrIdYouBlockedTarget).arg(targetName);
} else if (eventType == QLatin1String("account_suspension")) {
action = targetName.isEmpty()
- ? QStringLiteral("An account was suspended")
- : QStringLiteral("%1 was suspended").arg(targetName);
+ ? qtTrId(TrIdAccountSuspended)
+ : qtTrId(TrIdTargetSuspended).arg(targetName);
} else {
- action = QStringLiteral("Some follow relationships were severed");
+ action = qtTrId(TrIdRelationshipsSevered);
}
const int affectedCount = followersCount + followingCount;
@@ -138,7 +207,7 @@ namespace {
return action;
}
- return QStringLiteral("%1 (%2 followers, %3 following removed)")
+ return qtTrId(TrIdRelationshipsSummary)
.arg(action)
.arg(followersCount)
.arg(followingCount);
@@ -153,19 +222,19 @@ namespace {
const QString action = warningObject.value(QStringLiteral("action")).toString();
if (action == QLatin1String("none")) {
- return QStringLiteral("A moderator sent you a warning");
+ return qtTrId(TrIdModeratorWarningNone);
} else if (action == QLatin1String("disable")) {
- return QStringLiteral("A moderator disabled your account");
+ return qtTrId(TrIdModeratorWarningDisable);
} else if (action == QLatin1String("mark_statuses_as_sensitive")) {
- return QStringLiteral("A moderator marked specific posts as sensitive");
+ return qtTrId(TrIdModeratorWarningSpecificSensitive);
} else if (action == QLatin1String("delete_statuses")) {
- return QStringLiteral("A moderator deleted specific posts");
+ return qtTrId(TrIdModeratorWarningDeletePosts);
} else if (action == QLatin1String("sensitive")) {
- return QStringLiteral("A moderator marked all your posts as sensitive");
+ return qtTrId(TrIdModeratorWarningAllSensitive);
} else if (action == QLatin1String("silence")) {
- return QStringLiteral("A moderator limited your account");
+ return qtTrId(TrIdModeratorWarningSilence);
} else if (action == QLatin1String("suspend")) {
- return QStringLiteral("A moderator suspended your account");
+ return qtTrId(TrIdModeratorWarningSuspend);
}
return QString();
@@ -231,7 +300,7 @@ MastodonNotificationsSyncAdaptor::~MastodonNotificationsSyncAdaptor()
QString MastodonNotificationsSyncAdaptor::syncServiceName() const
{
- return QStringLiteral("mastodon-microblog");
+ return QStringLiteral("mastodon-notifications");
}
void MastodonNotificationsSyncAdaptor::purgeDataForOldAccount(int oldId, SocialNetworkSyncAdaptor::PurgeMode)
@@ -252,7 +321,7 @@ void MastodonNotificationsSyncAdaptor::beginSync(int accountId, const QString &a
void MastodonNotificationsSyncAdaptor::finalize(int accountId)
{
if (syncAborted()) {
- qCInfo(lcSocialPlugin) << "sync aborted, won't update notifications";
+ qCInfo(lcMastodonNotifications) << "sync aborted, won't update notifications";
}
Q_UNUSED(accountId)
@@ -348,7 +417,7 @@ void MastodonNotificationsSyncAdaptor::requestUnreadMarker(int accountId, const
incrementSemaphore(accountId);
setupReplyTimeout(accountId, reply);
} else {
- qCWarning(lcSocialPlugin) << "unable to request notifications marker from Mastodon account with id" << accountId;
+ qCWarning(lcMastodonNotifications) << "unable to request notifications marker from Mastodon account with id" << accountId;
}
}
@@ -371,7 +440,7 @@ void MastodonNotificationsSyncAdaptor::finishedUnreadMarkerHandler()
bool ok = false;
const QJsonObject markerObject = parseJsonObjectReplyData(replyData, &ok);
if (isError || !ok) {
- qCWarning(lcSocialPlugin) << "unable to parse notifications marker data from request with account"
+ qCWarning(lcMastodonNotifications) << "unable to parse notifications marker data from request with account"
<< accountId << ", got:" << QString::fromUtf8(replyData);
PendingSyncState fallbackState;
fallbackState.accessToken = accessToken;
@@ -435,7 +504,7 @@ void MastodonNotificationsSyncAdaptor::requestNotifications(int accountId,
incrementSemaphore(accountId);
setupReplyTimeout(accountId, reply);
} else {
- qCWarning(lcSocialPlugin) << "unable to request notifications from Mastodon account with id" << accountId;
+ qCWarning(lcMastodonNotifications) << "unable to request notifications from Mastodon account with id" << accountId;
}
}
@@ -463,7 +532,7 @@ void MastodonNotificationsSyncAdaptor::requestMarkRead(int accountId,
incrementSemaphore(accountId);
setupReplyTimeout(accountId, reply);
} else {
- qCWarning(lcSocialPlugin) << "unable to update notifications marker for Mastodon account with id" << accountId;
+ qCWarning(lcMastodonNotifications) << "unable to update notifications marker for Mastodon account with id" << accountId;
}
}
@@ -501,7 +570,7 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
const QJsonArray notifications = parseJsonArrayReplyData(replyData, &ok);
if (!isError && ok) {
if (!notifications.size()) {
- qCDebug(lcSocialPlugin) << "no notifications received for account" << accountId;
+ qCDebug(lcMastodonNotifications) << "no notifications received for account" << accountId;
m_pendingSyncStates.remove(accountId);
decrementSemaphore(accountId);
return;
@@ -596,7 +665,7 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
PendingNotification pendingNotification;
pendingNotification.notificationId = notificationId;
pendingNotification.summary = useSystemSummary(notificationType)
- ? QStringLiteral("Mastodon")
+ ? qtTrId(TrIdMastodon)
: displayName;
pendingNotification.body = body;
pendingNotification.link = url;
@@ -647,7 +716,7 @@ void MastodonNotificationsSyncAdaptor::finishedNotificationsHandler()
requestMarkRead(accountId, state.accessToken, markerId);
}
} else {
- qCWarning(lcSocialPlugin) << "unable to parse notifications data from request with account" << accountId
+ qCWarning(lcMastodonNotifications) << "unable to parse notifications data from request with account" << accountId
<< ", got:" << QString::fromUtf8(replyData);
}
@@ -679,7 +748,7 @@ void MastodonNotificationsSyncAdaptor::finishedMarkReadHandler()
m_lastMarkedReadIds.insert(accountId, lastReadId);
}
} else {
- qCWarning(lcSocialPlugin) << "unable to update notifications marker for account" << accountId
+ qCWarning(lcMastodonNotifications) << "unable to update notifications marker for account" << accountId
<< ", got:" << QString::fromUtf8(replyData);
}
@@ -695,10 +764,10 @@ void MastodonNotificationsSyncAdaptor::publishSystemNotification(int accountId,
? notificationData.timestamp
: QDateTime::currentDateTimeUtc());
notification->setSummary(notificationData.summary.isEmpty()
- ? QStringLiteral("Mastodon")
+ ? qtTrId(TrIdMastodon)
: notificationData.summary);
notification->setBody(notificationData.body.isEmpty()
- ? QStringLiteral("New notification")
+ ? qtTrId(TrIdNewNotification)
: notificationData.body);
notification->setPreviewSummary(notificationData.summary);
notification->setPreviewBody(notificationData.body);
@@ -716,7 +785,7 @@ void MastodonNotificationsSyncAdaptor::publishSystemNotification(int accountId,
notification->setRemoteAction(OPEN_URL_ACTION(authorizeInteractionUrl(apiHost(accountId), safeOpenUrl)));
notification->publish();
if (notification->replacesId() == 0) {
- qCWarning(lcSocialPlugin) << "failed to publish Mastodon notification"
+ qCWarning(lcMastodonNotifications) << "failed to publish Mastodon notification"
<< notificationData.notificationId;
}
}
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
index 293d98b..01cf1f5 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
+++ b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
@@ -41,18 +41,6 @@ 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.
@@ -280,7 +268,7 @@ SocialMediaFeedItem {
}
function shareStatusUrl() {
- return model && model.url ? model.url.toString() : ""
+ return item.stringValue("url", "link", "uri")
}
function topLevelParent() {
@@ -344,38 +332,6 @@ SocialMediaFeedItem {
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
@@ -412,12 +368,12 @@ SocialMediaFeedItem {
width: parent.width
height: Theme.itemSizeMedium
- onXPosChanged: hoveredIndex = xPos < width / 2 ? 0 : 1
+ 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 : (xPos < width / 2 ? 0 : 1)
+ var index = hoveredIndex >= 0 ? hoveredIndex : Math.max(0, Math.min(2, Math.floor((xPos * 3) / Math.max(1, width))))
if (!actionEnabled) {
return
}
@@ -429,19 +385,30 @@ SocialMediaFeedItem {
} else {
item.postActions.favourite(accountId, postId)
}
- } else {
+ } else if (index === 1) {
if (item.isReblogged) {
item.postActions.unboost(accountId, postId)
} else {
item.postActions.boost(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()
}
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
- x: horizontalActions.hoveredIndex === 1 ? parent.width / 2 : 0
- width: parent.width / 2
+ 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)
@@ -451,7 +418,7 @@ SocialMediaFeedItem {
anchors.fill: parent
Label {
- width: parent.width / 2
+ width: parent.width / 3
height: parent.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
@@ -467,7 +434,7 @@ SocialMediaFeedItem {
}
Label {
- width: parent.width / 2
+ width: parent.width / 3
height: parent.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
@@ -481,17 +448,20 @@ SocialMediaFeedItem {
? Theme.secondaryHighlightColor : Theme.primaryColor))
: Theme.rgba(Theme.secondaryColor, 0.4)
}
- } else if (actionName === "share") {
- var shareUrl = item.shareStatusUrl()
- if (shareUrl.length === 0) {
- return
+
+ 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)
}
- item._shareAction.resources = [{
- "data": shareUrl,
- "linkTitle": item._shareLinkTitle,
- "type": "text/x-url"
- }]
- item._shareAction.trigger()
}
}
}
diff --git a/rpm/sailfish-account-mastodon.spec b/rpm/sailfish-account-mastodon.spec
index 389b6a9..6391e9f 100644
--- a/rpm/sailfish-account-mastodon.spec
+++ b/rpm/sailfish-account-mastodon.spec
@@ -73,6 +73,7 @@ fi
%exclude %{_libdir}/libmastodonbuteocommon.so
%{_datadir}/accounts/providers/mastodon.provider
%{_datadir}/accounts/services/mastodon-microblog.service
+%{_datadir}/accounts/services/mastodon-notifications.service
%{_datadir}/accounts/services/mastodon-sharing.service
%{_datadir}/accounts/ui/MastodonSettingsDisplay.qml
%{_datadir}/accounts/ui/mastodon.qml
@@ -91,6 +92,7 @@ fi
%{_datadir}/lipstick/eventfeed/mastodon-delegate.qml
%{_datadir}/lipstick/eventfeed/MastodonFeedItem.qml
%{_datadir}/translations/lipstick-jolla-home-mastodon_eng_en.qm
+%{_datadir}/translations/lipstick-jolla-home-mastodon-notifications_eng_en.qm
%{_libdir}/nemo-transferengine/plugins/sharing/libmastodonshareplugin.so
%{_libdir}/nemo-transferengine/plugins/transfer/libmastodontransferplugin.so
@@ -99,3 +101,4 @@ fi
%files -n sailfish-account-mastodon-ts-devel
%{_datadir}/translations/source/settings-accounts-mastodon.ts
%{_datadir}/translations/source/lipstick-jolla-home-mastodon.ts
+%{_datadir}/translations/source/lipstick-jolla-home-mastodon-notifications.ts
diff --git a/settings/accounts/accounts.pro b/settings/accounts/accounts.pro
index d451438..190ee17 100644
--- a/settings/accounts/accounts.pro
+++ b/settings/accounts/accounts.pro
@@ -28,6 +28,7 @@ PRE_TARGETDEPS += ts engineering_english
OTHER_FILES += \
$$PWD/providers/mastodon.provider \
$$PWD/services/mastodon-microblog.service \
+ $$PWD/services/mastodon-notifications.service \
$$PWD/services/mastodon-sharing.service \
$$PWD/ui/MastodonSettingsDisplay.qml \
$$PWD/ui/mastodon.qml \
@@ -39,6 +40,7 @@ provider.path = /usr/share/accounts/providers/
services.files += \
$$PWD/services/mastodon-microblog.service \
+ $$PWD/services/mastodon-notifications.service \
$$PWD/services/mastodon-sharing.service
services.path = /usr/share/accounts/services/
diff --git a/settings/accounts/services/mastodon-microblog.service b/settings/accounts/services/mastodon-microblog.service
index 6b975f7..6151577 100644
--- a/settings/accounts/services/mastodon-microblog.service
+++ b/settings/accounts/services/mastodon-microblog.service
@@ -8,7 +8,7 @@
<provider>mastodon</provider>
<template>
- <setting name="sync_profile_templates" type="as">["mastodon.Posts", "mastodon.Notifications"]</setting>
+ <setting name="sync_profile_templates" type="as">["mastodon.Posts"]</setting>
<group name="auth">
<setting name="method">oauth2</setting>
<setting name="mechanism">web_server</setting>
diff --git a/settings/accounts/services/mastodon-notifications.service b/settings/accounts/services/mastodon-notifications.service
new file mode 100644
index 0000000..0c41e29
--- /dev/null
+++ b/settings/accounts/services/mastodon-notifications.service
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- Copyright (C) 2013-2026 Jolla Ltd. -->
+<service id="mastodon-notifications">
+ <type>microblogging</type>
+ <translations>/usr/share/translations/settings-accounts-mastodon</translations>
+ <name>Notifications</name>
+ <icon>image://theme/icon-l-mastodon</icon>
+ <provider>mastodon</provider>
+
+ <template>
+ <setting name="sync_profile_templates" type="as">["mastodon.Notifications"]</setting>
+ <group name="auth">
+ <setting name="method">oauth2</setting>
+ <setting name="mechanism">web_server</setting>
+ <group name="oauth2">
+ <group name="web_server">
+ <setting name="Host">mastodon.social</setting>
+ <setting name="AllowedSchemes" type="as">["https"]</setting>
+ <setting name="AuthPath">oauth/authorize</setting>
+ <setting name="TokenPath">oauth/token</setting>
+ <setting name="ResponseType">code</setting>
+ <setting name="Scope" type="as">["read","write"]</setting>
+ <setting name="RedirectUri">http://ipv4.jolla.com/online/status.html</setting>
+ </group>
+ </group>
+ </group>
+ <group name="api">
+ <setting name="Host">https://mastodon.social</setting>
+ </group>
+ </template>
+</service>
diff --git a/settings/accounts/ui/MastodonSettingsDisplay.qml b/settings/accounts/ui/MastodonSettingsDisplay.qml
index 1ee276e..c03221a 100644
--- a/settings/accounts/ui/MastodonSettingsDisplay.qml
+++ b/settings/accounts/ui/MastodonSettingsDisplay.qml
@@ -37,7 +37,8 @@ StandardAccountSettingsDisplay {
var providerDisplayName = root.accountProvider && root.accountProvider.displayName
? root.accountProvider.displayName.toString().trim()
: ""
- return providerDisplayName.length > 0 ? providerDisplayName : "Mastodon"
+ //% "Mastodon"
+ return providerDisplayName.length > 0 ? providerDisplayName : qsTrId("settings-accounts-mastodon-la-provider_name")
}
onAboutToSaveAccount: {
@@ -106,10 +107,20 @@ StandardAccountSettingsDisplay {
id: syncServicesRepeater
TextSwitch {
checked: model.enabled
- text: model.displayName
+ text: model.serviceName === "mastodon-microblog"
+ //% "Posts"
+ ? qsTrId("settings-accounts-mastodon-la-service_posts")
+ : (model.serviceName === "mastodon-notifications"
+ //% "Notifications"
+ ? qsTrId("settings-accounts-mastodon-la-service_notifications")
+ : model.displayName)
description: model.serviceName === "mastodon-microblog"
- ? "Show Mastodon posts in the Events view."
- : ""
+ //% "Show Mastodon posts in the Events view."
+ ? qsTrId("settings-accounts-mastodon-la-service_posts_description")
+ : (model.serviceName === "mastodon-notifications"
+ //% "Show Mastodon notifications."
+ ? qsTrId("settings-accounts-mastodon-la-service_notifications_description")
+ : "")
visible: text.length > 0
onCheckedChanged: {
if (checked) {
@@ -124,8 +135,10 @@ StandardAccountSettingsDisplay {
TextSwitch {
id: eventsSyncSwitch
- text: "Sync Mastodon feed automatically"
- description: "Fetch new posts periodically when browsing Events Mastodon feed."
+ //% "Sync Mastodon feed automatically"
+ text: qsTrId("settings-accounts-mastodon-la-auto_sync_feed")
+ //% "Fetch new posts periodically when browsing Events Mastodon feed."
+ description: qsTrId("settings-accounts-mastodon-la-auto_sync_feed_description")
onCheckedChanged: {
autoSyncConf.value = checked
diff --git a/settings/accounts/ui/mastodon-update.qml b/settings/accounts/ui/mastodon-update.qml
index 98dba8c..75c043d 100644
--- a/settings/accounts/ui/mastodon-update.qml
+++ b/settings/accounts/ui/mastodon-update.qml
@@ -175,7 +175,8 @@ AccountCredentialsAgent {
var clientId = _valueFromServiceConfig(config, "auth/oauth2/web_server/ClientId")
var clientSecret = _valueFromServiceConfig(config, "auth/oauth2/web_server/ClientSecret")
if (clientId.length === 0 || clientSecret.length === 0) {
- credentialsUpdateError("Missing Mastodon OAuth client credentials")
+ //% "Missing Mastodon OAuth client credentials"
+ credentialsUpdateError(qsTrId("settings-accounts-mastodon-la-missing_client_credentials"))
return
}
diff --git a/settings/accounts/ui/mastodon.qml b/settings/accounts/ui/mastodon.qml
index e7cf255..a32f336 100644
--- a/settings/accounts/ui/mastodon.qml
+++ b/settings/accounts/ui/mastodon.qml
@@ -366,12 +366,13 @@ AccountCreationAgent {
function configure() {
hasConfigured = true
- var services = ["mastodon-microblog", "mastodon-sharing"]
+ var services = ["mastodon-microblog", "mastodon-notifications", "mastodon-sharing"]
var providerDisplayName = root.accountProvider && root.accountProvider.displayName
? root.accountProvider.displayName.toString().trim()
: ""
if (providerDisplayName.length === 0) {
- providerDisplayName = "Mastodon"
+ //% "Mastodon"
+ providerDisplayName = qsTrId("settings-accounts-mastodon-la-provider_name")
}
newAccount.displayName = providerDisplayName