/**************************************************************************** ** ** Copyright (C) 2013-2026 Jolla Ltd. ** ****************************************************************************/ import QtQuick 2.0 import Sailfish.Silica 1.0 import org.nemomobile.socialcache 1.0 import com.jolla.eventsview.mastodon 1.0 import QtQml.Models 2.1 import "shared" import "shared/SocialFeedUtils.js" as FeedUtils SocialMediaAccountDelegate { id: delegateItem //: Mastodon posts //% "Posts" headerText: qsTrId("lipstick-jolla-home-la-mastodon_posts") headerIcon: "image://theme/icon-l-mastodon" showRemainingCount: false services: ["Posts"] socialNetwork: 9 dataType: SocialSync.Posts providerName: "mastodon" periodicSyncLoopEnabled: true MastodonPostActions { id: mastodonPostActions } model: MastodonPostsModel {} delegate: MastodonFeedItem { downloader: delegateItem.downloader imageList: FeedUtils.variantRole(model, ["images", "mediaAttachments", "media"], undefined) avatarSource: FeedUtils.normalizeAvatarUrl(FeedUtils.stringRole(model, ["icon", "avatar", "avatarUrl"], "")) fallbackAvatarSource: FeedUtils.stringRole(model, ["icon", "avatar", "avatarUrl"], "") resolvedStatusUrl: delegateItem.authorizeInteractionUrl(model) postId: FeedUtils.stringRole(model, ["mastodonId", "statusId", "id", "twitterId"], "") postActions: mastodonPostActions accountId: FeedUtils.firstAccountId(model, -1) onTriggered: Qt.openUrlExternally(resolvedStatusUrl) Component.onCompleted: { refreshTimeCount = Qt.binding(function() { return delegateItem.refreshTimeCount }) connectedToNetwork = Qt.binding(function() { return delegateItem.connectedToNetwork }) eventsColumnMaxWidth = Qt.binding(function() { return delegateItem.eventsColumnMaxWidth }) } } //% "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") onViewVisibleChanged: { if (viewVisible) { delegateItem.resetHasSyncableAccounts() delegateItem.model.refresh() if (delegateItem.hasSyncableAccounts) { delegateItem.startPeriodicSyncLoop() } } else { delegateItem.stopPeriodicSyncLoop() } } onConnectedToNetworkChanged: { if (viewVisible) { delegateItem.startPeriodicSyncLoop() } } function statusUrl(modelData) { var directUrl = FeedUtils.stringRole(modelData, ["url", "link", "uri"], "") if (directUrl.length > 0) { return directUrl } var instanceUrl = FeedUtils.stringRole(modelData, ["instanceUrl", "serverUrl", "baseUrl"], "") if (instanceUrl.length === 0) { instanceUrl = "https://mastodon.social" } instanceUrl = FeedUtils.stripTrailingSlashes(instanceUrl) var accountName = FeedUtils.stringRole(modelData, ["accountName", "acct", "screenName", "username"], "") var statusId = FeedUtils.stringRole(modelData, ["mastodonId", "statusId", "id", "twitterId"], "") if (accountName.length > 0 && statusId.length > 0) { accountName = FeedUtils.trimLeadingCharacter(accountName, "@") return instanceUrl + "/@" + accountName + "/" + statusId } return instanceUrl + "/explore" } function authorizeInteractionUrl(modelData) { var targetUrl = statusUrl(modelData) if (targetUrl.length === 0) { return targetUrl } var instanceUrl = FeedUtils.stringRole(modelData, ["instanceUrl", "serverUrl", "baseUrl"], "") if (instanceUrl.length === 0) { return targetUrl } instanceUrl = FeedUtils.stripTrailingSlashes(instanceUrl) // Links on the user's own instance should open directly. var sameServer = /^([a-z][a-z0-9+.-]*):\/\/([^\/?#]+)/i var targetMatch = targetUrl.match(sameServer) var instanceMatch = instanceUrl.match(sameServer) if (targetMatch && instanceMatch && targetMatch.length > 2 && instanceMatch.length > 2 && targetMatch[1].toLowerCase() === instanceMatch[1].toLowerCase() && targetMatch[2].toLowerCase() === instanceMatch[2].toLowerCase()) { return targetUrl } return instanceUrl + "/authorize_interaction?uri=" + encodeURIComponent(targetUrl) } }