summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@jolla.com>2026-02-11 17:10:58 +0100
committerAndrew Branson <andrew.branson@jolla.com>2026-02-11 17:10:58 +0100
commit22c763f1ffdc7dc845be03c05851d7b896081cb2 (patch)
treeeab1542f91f758c88d8b3cd43ed2f66276f78119
parentd8ff92c1baf2c9714f21729e7d37c66f59c162ff (diff)
Add post metadata to events view and enhance notification handling
-rw-r--r--README.md1
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp15
-rw-r--r--buteo-plugins/buteo-sync-plugin-mastodon-posts/mastodonpostssyncadaptor.cpp6
-rw-r--r--common/mastodonpostsdatabase.cpp33
-rw-r--r--common/mastodonpostsdatabase.h4
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml36
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp9
-rw-r--r--eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.h3
8 files changed, 93 insertions, 14 deletions
diff --git a/README.md b/README.md
index 6912e9b..726d3a0 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ Sailfish OS account integration for Mastodon.
## Current Notification Behavior
- Events view shows Mastodon posts (not notification entries).
+- Events view post metadata line includes replies, favourites, and boosts alongside elapsed timestamp.
- System notifications are produced by `buteo-sync-plugin-mastodon-notifications`.
- Notifications sync starts from Mastodon server marker (`notifications.last_read_id`) and uses local cursor dedupe via per-account `LastFetchedNotificationId`.
- Each unread Mastodon notification is published as a separate Sailfish system notification.
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
index f4e70ae..d5d1766 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-notifications/mastodonnotificationssyncadaptor.cpp
@@ -38,15 +38,15 @@
#include <algorithm>
-#define OPEN_BROWSER_ACTION(openUrlArgs) \
+#define OPEN_URL_ACTION(openUrl) \
Notification::remoteAction( \
"default", \
"", \
- "org.sailfishos.browser", \
+ "org.sailfishos.fileservice", \
"/", \
- "org.sailfishos.browser", \
+ "org.sailfishos.fileservice", \
"openUrl", \
- QVariantList() << openUrlArgs \
+ QVariantList() << openUrl \
)
namespace {
@@ -655,11 +655,7 @@ void MastodonNotificationsSyncAdaptor::publishSystemNotification(int accountId,
&& !parsedOpenUrl.host().isEmpty()
? openUrl
: fallbackUrl;
- QStringList openUrlArgs;
- openUrlArgs << safeOpenUrl;
-
- notification->setUrgency(Notification::Low);
- notification->setRemoteAction(OPEN_BROWSER_ACTION(openUrlArgs));
+ notification->setRemoteAction(OPEN_URL_ACTION(safeOpenUrl));
notification->publish();
if (notification->replacesId() == 0) {
qCWarning(lcSocialPlugin) << "failed to publish Mastodon notification"
@@ -728,6 +724,7 @@ Notification *MastodonNotificationsSyncAdaptor::createNotification(int accountId
notification->setHintValue("x-nemo.sociald.account-id", accountId);
notification->setHintValue(NotificationIdHint, notificationId);
notification->setHintValue("x-nemo-feedback", QStringLiteral("social"));
+ notification->setHintValue("x-nemo-priority", 100); // Show on lockscreen
notification->setCategory(QLatin1String(NotificationCategory));
m_notificationObjects.insert(objectKey, notification);
diff --git a/buteo-plugins/buteo-sync-plugin-mastodon-posts/mastodonpostssyncadaptor.cpp b/buteo-plugins/buteo-sync-plugin-mastodon-posts/mastodonpostssyncadaptor.cpp
index c7c696e..6165931 100644
--- a/buteo-plugins/buteo-sync-plugin-mastodon-posts/mastodonpostssyncadaptor.cpp
+++ b/buteo-plugins/buteo-sync-plugin-mastodon-posts/mastodonpostssyncadaptor.cpp
@@ -270,6 +270,9 @@ void MastodonPostsSyncAdaptor::finishedPostsHandler()
}
const QString body = sanitizeContent(postObject.value(QStringLiteral("content")).toString());
+ const int repliesCount = postObject.value(QStringLiteral("replies_count")).toInt();
+ const int favouritesCount = postObject.value(QStringLiteral("favourites_count")).toInt();
+ const int reblogsCount = postObject.value(QStringLiteral("reblogs_count")).toInt();
QList<QPair<QString, SocialPostImage::ImageType> > imageList;
const QJsonArray mediaAttachments = postObject.value(QStringLiteral("media_attachments")).toArray();
@@ -304,6 +307,9 @@ void MastodonPostsSyncAdaptor::finishedPostsHandler()
imageList,
url,
boostedBy,
+ repliesCount,
+ favouritesCount,
+ reblogsCount,
apiHost(accountId),
accountId);
}
diff --git a/common/mastodonpostsdatabase.cpp b/common/mastodonpostsdatabase.cpp
index 08fc777..ee04327 100644
--- a/common/mastodonpostsdatabase.cpp
+++ b/common/mastodonpostsdatabase.cpp
@@ -22,6 +22,9 @@ static const char *DB_NAME = "mastodon.db";
static const char *ACCOUNT_NAME_KEY = "account_name";
static const char *URL_KEY = "url";
static const char *BOOSTED_BY_KEY = "boosted_by";
+static const char *REPLIES_COUNT_KEY = "replies_count";
+static const char *FAVOURITES_COUNT_KEY = "favourites_count";
+static const char *REBLOGS_COUNT_KEY = "reblogs_count";
static const char *INSTANCE_URL_KEY = "instance_url";
MastodonPostsDatabase::MastodonPostsDatabase()
@@ -43,6 +46,9 @@ void MastodonPostsDatabase::addMastodonPost(
const QList<QPair<QString, SocialPostImage::ImageType> > &images,
const QString &url,
const QString &boostedBy,
+ int repliesCount,
+ int favouritesCount,
+ int reblogsCount,
const QString &instanceUrl,
int account)
{
@@ -50,6 +56,9 @@ void MastodonPostsDatabase::addMastodonPost(
extra.insert(ACCOUNT_NAME_KEY, accountName);
extra.insert(URL_KEY, url);
extra.insert(BOOSTED_BY_KEY, boostedBy);
+ extra.insert(REPLIES_COUNT_KEY, repliesCount);
+ extra.insert(FAVOURITES_COUNT_KEY, favouritesCount);
+ extra.insert(REBLOGS_COUNT_KEY, reblogsCount);
extra.insert(INSTANCE_URL_KEY, instanceUrl);
addPost(identifier, name, body, timestamp, icon, images, extra, account);
}
@@ -78,6 +87,30 @@ QString MastodonPostsDatabase::boostedBy(const SocialPost::ConstPtr &post)
return post->extra().value(BOOSTED_BY_KEY).toString();
}
+int MastodonPostsDatabase::repliesCount(const SocialPost::ConstPtr &post)
+{
+ if (post.isNull()) {
+ return 0;
+ }
+ return post->extra().value(REPLIES_COUNT_KEY).toInt();
+}
+
+int MastodonPostsDatabase::favouritesCount(const SocialPost::ConstPtr &post)
+{
+ if (post.isNull()) {
+ return 0;
+ }
+ return post->extra().value(FAVOURITES_COUNT_KEY).toInt();
+}
+
+int MastodonPostsDatabase::reblogsCount(const SocialPost::ConstPtr &post)
+{
+ if (post.isNull()) {
+ return 0;
+ }
+ return post->extra().value(REBLOGS_COUNT_KEY).toInt();
+}
+
QString MastodonPostsDatabase::instanceUrl(const SocialPost::ConstPtr &post)
{
if (post.isNull()) {
diff --git a/common/mastodonpostsdatabase.h b/common/mastodonpostsdatabase.h
index b27b626..66d3f09 100644
--- a/common/mastodonpostsdatabase.h
+++ b/common/mastodonpostsdatabase.h
@@ -34,12 +34,16 @@ public:
const QString &icon,
const QList<QPair<QString, SocialPostImage::ImageType> > &images,
const QString &url, const QString &boostedBy,
+ int repliesCount, int favouritesCount, int reblogsCount,
const QString &instanceUrl,
int account);
static QString accountName(const SocialPost::ConstPtr &post);
static QString url(const SocialPost::ConstPtr &post);
static QString boostedBy(const SocialPost::ConstPtr &post);
+ static int repliesCount(const SocialPost::ConstPtr &post);
+ static int favouritesCount(const SocialPost::ConstPtr &post);
+ static int reblogsCount(const SocialPost::ConstPtr &post);
static QString instanceUrl(const SocialPost::ConstPtr &post);
};
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
index c96fb8a..9d86732 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
+++ b/eventsview-plugins/eventsview-plugin-mastodon/MastodonFeedItem.qml
@@ -13,16 +13,17 @@ SocialMediaFeedItem {
id: item
property variant imageList
- property int likeCount
- property int commentCount
- property int boostCount
+ property int likeCount: item.intValue("favouritesCount", "likeCount", "favoriteCount")
+ property int commentCount: item.intValue("repliesCount", "commentCount")
+ property int boostCount: item.intValue("reblogsCount", "boostCount", "repostsCount")
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")
- timestamp: item.stringValue("timestamp", "createdAt", "created_at")
+ timestamp: model.timestamp
+ onRefreshTimeCountChanged: formattedTime = Format.formatDate(model.timestamp, Format.TimeElapsed)
avatar.y: item._booster.length > 0
? topMargin + boosterIcon.height + Theme.paddingSmall
@@ -110,7 +111,7 @@ SocialMediaFeedItem {
wrapMode: Text.Wrap
color: item.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
font.pixelSize: Theme.fontSizeExtraSmall
- text: item.formattedTime
+ text: item.metadataText()
textFormat: Text.PlainText
}
@@ -140,4 +141,29 @@ SocialMediaFeedItem {
}
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 metadataText() {
+ var parts = []
+ parts.push("↩ " + item.commentCount)
+ parts.push("★ " + item.likeCount)
+ parts.push("↻ " + item.boostCount)
+ if (item.formattedTime.length > 0) {
+ parts.push(item.formattedTime)
+ }
+ return parts.join(" | ")
+ }
}
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
index 74d239e..4fe37d9 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
+++ b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.cpp
@@ -63,6 +63,9 @@ QHash<int, QByteArray> MastodonPostsModel::roleNames() const
roleNames.insert(Link, "link");
roleNames.insert(BoostedBy, "boostedBy");
roleNames.insert(RebloggedBy, "rebloggedBy");
+ roleNames.insert(RepliesCount, "repliesCount");
+ roleNames.insert(FavouritesCount, "favouritesCount");
+ roleNames.insert(ReblogsCount, "reblogsCount");
roleNames.insert(InstanceUrl, "instanceUrl");
roleNames.insert(Accounts, "accounts");
return roleNames;
@@ -100,6 +103,9 @@ void MastodonPostsModel::postsChanged()
const QString accountName = d->database.accountName(post);
const QString postUrl = d->database.url(post);
const QString boostedBy = d->database.boostedBy(post);
+ const int repliesCount = d->database.repliesCount(post);
+ const int favouritesCount = d->database.favouritesCount(post);
+ const int reblogsCount = d->database.reblogsCount(post);
eventMap.insert(MastodonPostsModel::MastodonId, post->identifier());
eventMap.insert(MastodonPostsModel::Name, post->name());
@@ -112,6 +118,9 @@ void MastodonPostsModel::postsChanged()
eventMap.insert(MastodonPostsModel::Link, postUrl);
eventMap.insert(MastodonPostsModel::BoostedBy, boostedBy);
eventMap.insert(MastodonPostsModel::RebloggedBy, boostedBy);
+ eventMap.insert(MastodonPostsModel::RepliesCount, repliesCount);
+ eventMap.insert(MastodonPostsModel::FavouritesCount, favouritesCount);
+ eventMap.insert(MastodonPostsModel::ReblogsCount, reblogsCount);
eventMap.insert(MastodonPostsModel::InstanceUrl, d->database.instanceUrl(post));
QVariantList images;
diff --git a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.h b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.h
index 150438a..586d1a0 100644
--- a/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.h
+++ b/eventsview-plugins/eventsview-plugin-mastodon/mastodonpostsmodel.h
@@ -42,6 +42,9 @@ public:
Link,
BoostedBy,
RebloggedBy,
+ RepliesCount,
+ FavouritesCount,
+ ReblogsCount,
InstanceUrl,
Accounts
};