Reworked social notifications

This commit is contained in:
Thomas Ricouard 2023-02-14 12:17:27 +01:00
parent 27065619d2
commit dbbd33ba88
22 changed files with 250 additions and 29 deletions

View file

@ -80,6 +80,11 @@
9FD542E72962D2FF0045321A /* Lists in Frameworks */ = {isa = PBXBuildFile; productRef = 9FD542E62962D2FF0045321A /* Lists */; }; 9FD542E72962D2FF0045321A /* Lists in Frameworks */ = {isa = PBXBuildFile; productRef = 9FD542E62962D2FF0045321A /* Lists */; };
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE151A5293C90F900E9683D /* IconSelectorView.swift */; }; 9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE151A5293C90F900E9683D /* IconSelectorView.swift */; };
9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; }; 9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; };
9FFF677C299B7B2C00FE700A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677B299B7B2C00FE700A /* Notifications */; };
9FFF677E299B7D2800FE700A /* Status in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677D299B7D2800FE700A /* Status */; };
9FFF6780299B7D2B00FE700A /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677F299B7D2B00FE700A /* DesignSystem */; };
9FFF6782299B7D3A00FE700A /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF6781299B7D3A00FE700A /* Account */; };
9FFF6784299B7D4400FE700A /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF6783299B7D4400FE700A /* LRUCache */; };
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */; }; C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */; };
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08A9C3429956CFA00204A4A /* SwipeActionsSettingsView.swift */; }; D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08A9C3429956CFA00204A4A /* SwipeActionsSettingsView.swift */; };
E92817FA298443D600875FD1 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = E92817F9298443D600875FD1 /* Models */; }; E92817FA298443D600875FD1 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = E92817F9298443D600875FD1 /* Models */; };
@ -248,9 +253,14 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
9FFF677C299B7B2C00FE700A /* Notifications in Frameworks */,
9F7D93942980063100EE6B7A /* AppAccount in Frameworks */, 9F7D93942980063100EE6B7A /* AppAccount in Frameworks */,
9FFF6780299B7D2B00FE700A /* DesignSystem in Frameworks */,
9FFF6784299B7D4400FE700A /* LRUCache in Frameworks */,
9F2A5428296AB683009B2D7C /* Models in Frameworks */, 9F2A5428296AB683009B2D7C /* Models in Frameworks */,
9FFF6782299B7D3A00FE700A /* Account in Frameworks */,
9F2A5426296AB67E009B2D7C /* KeychainSwift in Frameworks */, 9F2A5426296AB67E009B2D7C /* KeychainSwift in Frameworks */,
9FFF677E299B7D2800FE700A /* Status in Frameworks */,
9F2A5424296AB67A009B2D7C /* Env in Frameworks */, 9F2A5424296AB67A009B2D7C /* Env in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -526,6 +536,11 @@
9F2A5425296AB67E009B2D7C /* KeychainSwift */, 9F2A5425296AB67E009B2D7C /* KeychainSwift */,
9F2A5427296AB683009B2D7C /* Models */, 9F2A5427296AB683009B2D7C /* Models */,
9F7D93932980063100EE6B7A /* AppAccount */, 9F7D93932980063100EE6B7A /* AppAccount */,
9FFF677B299B7B2C00FE700A /* Notifications */,
9FFF677D299B7D2800FE700A /* Status */,
9FFF677F299B7D2B00FE700A /* DesignSystem */,
9FFF6781299B7D3A00FE700A /* Account */,
9FFF6783299B7D4400FE700A /* LRUCache */,
); );
productName = IceCubesNotifications; productName = IceCubesNotifications;
productReference = 9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */; productReference = 9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */;
@ -895,7 +910,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -925,7 +940,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -956,7 +971,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -986,7 +1001,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1152,7 +1167,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto; SDKROOT = auto;
@ -1204,7 +1219,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto; SDKROOT = auto;
@ -1237,7 +1252,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1268,7 +1283,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.4.9; MARKETING_VERSION = 1.5.0;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1473,6 +1488,27 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = AppAccount; productName = AppAccount;
}; };
9FFF677B299B7B2C00FE700A /* Notifications */ = {
isa = XCSwiftPackageProductDependency;
productName = Notifications;
};
9FFF677D299B7D2800FE700A /* Status */ = {
isa = XCSwiftPackageProductDependency;
productName = Status;
};
9FFF677F299B7D2B00FE700A /* DesignSystem */ = {
isa = XCSwiftPackageProductDependency;
productName = DesignSystem;
};
9FFF6781299B7D3A00FE700A /* Account */ = {
isa = XCSwiftPackageProductDependency;
productName = Account;
};
9FFF6783299B7D4400FE700A /* LRUCache */ = {
isa = XCSwiftPackageProductDependency;
package = 065FA1FC29866CD600012EA0 /* XCRemoteSwiftPackageReference "LRUCache" */;
productName = LRUCache;
};
E92817F9298443D600875FD1 /* Models */ = { E92817F9298443D600875FD1 /* Models */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = Models; productName = Models;

View file

@ -57,10 +57,20 @@ struct IceCubesApp: App {
.edgesIgnoringSafeArea(.bottom) .edgesIgnoringSafeArea(.bottom)
.background(TransparentBackground()) .background(TransparentBackground())
}) })
.onChange(of: pushNotificationsService.handleNotification) { notification in .onChange(of: pushNotificationsService.handledNotification) { notification in
if notification != nil { if notification != nil {
pushNotificationsService.handleNotification = nil pushNotificationsService.handledNotification = nil
selectedTab = .notifications if appAccountsManager.currentAccount.oauthToken?.accessToken != notification?.account.token.accessToken,
let account = appAccountsManager.availableAccounts.first(where:
{ $0.oauthToken?.accessToken == notification?.account.token.accessToken }) {
appAccountsManager.currentAccount = account
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
selectedTab = .notifications
pushNotificationsService.handledNotification = notification
}
} else {
selectedTab = .notifications
}
} }
} }
} }

View file

@ -54,14 +54,14 @@ struct NotificationsTab: View {
routerPath.path = [] routerPath.path = []
} }
} }
.onChange(of: pushNotificationsService.handleNotification) { notification in .onChange(of: pushNotificationsService.handledNotification) { notification in
if let notification, let type = notification.supportedType { if let notification, let type = notification.notification.supportedType {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
switch type { switch type {
case .follow, .follow_request: case .follow, .follow_request:
routerPath.navigate(to: .accountDetailWithAccount(account: notification.account)) routerPath.navigate(to: .accountDetailWithAccount(account: notification.notification.account))
default: default:
if let status = notification.status { if let status = notification.notification.status {
routerPath.navigate(to: .statusDetailWithStatus(status: status)) routerPath.navigate(to: .statusDetailWithStatus(status: status))
} }
} }

View file

@ -333,6 +333,14 @@
"notifications.tab.all" = "Totes"; "notifications.tab.all" = "Totes";
"notifications.tab.mentions" = "Mencions"; "notifications.tab.mentions" = "Mencions";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federada"; "timeline.federated" = "Federada";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -331,6 +331,14 @@
"notifications.tab.all" = "Alle"; "notifications.tab.all" = "Alle";
"notifications.tab.mentions" = "Erwähnungen"; "notifications.tab.mentions" = "Erwähnungen";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Föderiert"; "timeline.federated" = "Föderiert";
"timeline.latest" = "Zum Neuesten springen"; "timeline.latest" = "Zum Neuesten springen";

View file

@ -336,6 +336,14 @@
"notifications.tab.all" = "All"; "notifications.tab.all" = "All";
"notifications.tab.mentions" = "Mentions"; "notifications.tab.mentions" = "Mentions";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federated"; "timeline.federated" = "Federated";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -335,6 +335,14 @@
"notifications.tab.all" = "All"; "notifications.tab.all" = "All";
"notifications.tab.mentions" = "Mentions"; "notifications.tab.mentions" = "Mentions";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federated"; "timeline.federated" = "Federated";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -335,6 +335,14 @@
"notifications.tab.all" = "Todo"; "notifications.tab.all" = "Todo";
"notifications.tab.mentions" = "Menciones"; "notifications.tab.mentions" = "Menciones";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federado"; "timeline.federated" = "Federado";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -337,6 +337,14 @@
"notifications.tab.all" = "Guztia"; "notifications.tab.all" = "Guztia";
"notifications.tab.mentions" = "Aipamenak"; "notifications.tab.mentions" = "Aipamenak";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federatua"; "timeline.federated" = "Federatua";
"timeline.latest" = "Egin salto berrienera"; "timeline.latest" = "Egin salto berrienera";

View file

@ -330,6 +330,14 @@
"notifications.tab.all" = "Tout"; "notifications.tab.all" = "Tout";
"notifications.tab.mentions" = "Mentions"; "notifications.tab.mentions" = "Mentions";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Fédéré"; "timeline.federated" = "Fédéré";
"timeline.latest" = "Aller au plus récent"; "timeline.latest" = "Aller au plus récent";

View file

@ -335,6 +335,14 @@
"notifications.tab.all" = "Tutto"; "notifications.tab.all" = "Tutto";
"notifications.tab.mentions" = "Menzioni"; "notifications.tab.mentions" = "Menzioni";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federazione"; "timeline.federated" = "Federazione";
"timeline.latest" = "Vai all'ultimo post"; "timeline.latest" = "Vai all'ultimo post";

View file

@ -334,6 +334,14 @@
"notifications.tab.all" = "全て"; "notifications.tab.all" = "全て";
"notifications.tab.mentions" = "返信"; "notifications.tab.mentions" = "返信";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "連合"; "timeline.federated" = "連合";
"timeline.latest" = "最新情報までジャンプ"; "timeline.latest" = "最新情報までジャンプ";

View file

@ -336,6 +336,14 @@
"notifications.tab.all" = "모든 알림"; "notifications.tab.all" = "모든 알림";
"notifications.tab.mentions" = "언급"; "notifications.tab.mentions" = "언급";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "연합"; "timeline.federated" = "연합";
"timeline.latest" = "최신 타임라인 다시 불러오기"; "timeline.latest" = "최신 타임라인 다시 불러오기";

View file

@ -334,6 +334,14 @@
"notifications.tab.all" = "Alle"; "notifications.tab.all" = "Alle";
"notifications.tab.mentions" = "Omtaler"; "notifications.tab.mentions" = "Omtaler";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Federert"; "timeline.federated" = "Federert";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -328,6 +328,14 @@
"notifications.tab.all" = "Alle"; "notifications.tab.all" = "Alle";
"notifications.tab.mentions" = "Vermeldingen"; "notifications.tab.mentions" = "Vermeldingen";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Gefedereerd"; "timeline.federated" = "Gefedereerd";
"timeline.latest" = "Spring naar meest recent"; "timeline.latest" = "Spring naar meest recent";

View file

@ -331,6 +331,14 @@
"notifications.tab.all" = "Wszystko"; "notifications.tab.all" = "Wszystko";
"notifications.tab.mentions" = "Wzmianki"; "notifications.tab.mentions" = "Wzmianki";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Strumień globalny"; "timeline.federated" = "Strumień globalny";
"timeline.latest" = "Najnowsze posty"; "timeline.latest" = "Najnowsze posty";

View file

@ -334,6 +334,14 @@
"notifications.tab.all" = "Todos"; "notifications.tab.all" = "Todos";
"notifications.tab.mentions" = "Menções"; "notifications.tab.mentions" = "Menções";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Linha global"; "timeline.federated" = "Linha global";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -330,6 +330,14 @@
"notifications.tab.all" = "Tamamı"; "notifications.tab.all" = "Tamamı";
"notifications.tab.mentions" = "Bahsetmeler"; "notifications.tab.mentions" = "Bahsetmeler";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "Birleştirilmiş"; "timeline.federated" = "Birleştirilmiş";
"timeline.latest" = "Jump to Latest"; "timeline.latest" = "Jump to Latest";

View file

@ -335,6 +335,14 @@
"notifications.tab.all" = "全部"; "notifications.tab.all" = "全部";
"notifications.tab.mentions" = "提及"; "notifications.tab.mentions" = "提及";
"notifications.label.status.push" = "🖊️ Posted: ";
"notifications.label.reblog.push" = "🚀 Boosted: ";
"notifications.label.follow.push" = "👋 Followed you: ";
"notifications.label.follow-request.push" = "🔒 Requested to follow you: ";
"notifications.label.favorite.push" = "⭐️ Starred: ";
"notifications.label.poll.push" = "📈 Poll ended: ";
"notifications.label.update.push" = "Updated: ";
// MARK: Package: Timeline // MARK: Package: Timeline
"timeline.federated" = "跨站"; "timeline.federated" = "跨站";
"timeline.latest" = "跳转到最新"; "timeline.latest" = "跳转到最新";

View file

@ -7,6 +7,7 @@ import UIKit
import UserNotifications import UserNotifications
import Intents import Intents
import Network import Network
import Notifications
@MainActor @MainActor
class NotificationService: UNNotificationServiceExtension { class NotificationService: UNNotificationServiceExtension {
@ -81,14 +82,16 @@ class NotificationService: UNNotificationServiceExtension {
if let image = UIImage(data: data) { if let image = UIImage(data: data) {
try? image.pngData()?.write(to: fileURL) try? image.pngData()?.write(to: fileURL)
if let remoteNotification = await toRemoteNotification(localNotification: notification) { if let remoteNotification = await toRemoteNotification(localNotification: notification),
let intent = buildMessageIntent(remoteNotification: remoteNotification, avatarURL: fileURL) let type = remoteNotification.supportedType {
let intent = buildMessageIntent(remoteNotification: remoteNotification,
currentUser: bestAttemptContent.userInfo["i"] as? String ?? "",
avatarURL: fileURL)
bestAttemptContent = try bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent bestAttemptContent = try bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent
if AppAccountsManager.shared.availableAccounts.count > 1 { if type == .mention {
let newBody = "\(bestAttemptContent.userInfo["i"] as? String ?? "") \n\(notification.title)\n\(notification.body.escape())" bestAttemptContent.body = notification.body.escape()
bestAttemptContent.body = newBody
} else { } else {
let newBody = "\(notification.title)\n\(notification.body.escape())" let newBody = "\(NSLocalizedString(type.notificationKey(), bundle: .main, comment: ""))\(notification.body.escape())"
bestAttemptContent.body = newBody bestAttemptContent.body = newBody
} }
} else { } else {
@ -121,7 +124,9 @@ class NotificationService: UNNotificationServiceExtension {
return nil return nil
} }
private func buildMessageIntent(remoteNotification: Models.Notification, avatarURL: URL) -> INSendMessageIntent { private func buildMessageIntent(remoteNotification: Models.Notification,
currentUser: String,
avatarURL: URL) -> INSendMessageIntent {
let handle = INPersonHandle(value: remoteNotification.account.id, type: .unknown) let handle = INPersonHandle(value: remoteNotification.account.id, type: .unknown)
let avatar = INImage(url: avatarURL) let avatar = INImage(url: avatarURL)
let sender = INPerson(personHandle: handle, let sender = INPerson(personHandle: handle,
@ -130,14 +135,29 @@ class NotificationService: UNNotificationServiceExtension {
image: avatar, image: avatar,
contactIdentifier: nil, contactIdentifier: nil,
customIdentifier: nil) customIdentifier: nil)
let intent = INSendMessageIntent(recipients: nil, var recipents: [INPerson]?
var groupName: INSpeakableString?
if AppAccountsManager.shared.availableAccounts.count > 1 {
let me = INPerson(personHandle: .init(value: currentUser, type: .unknown),
nameComponents: nil,
displayName: currentUser,
image: nil,
contactIdentifier: nil,
customIdentifier: nil)
recipents = [me, sender]
groupName = .init(spokenPhrase: currentUser)
}
let intent = INSendMessageIntent(recipients: recipents,
outgoingMessageType: .outgoingMessageText, outgoingMessageType: .outgoingMessageText,
content: nil, content: nil,
speakableGroupName: nil, speakableGroupName: groupName,
conversationIdentifier: remoteNotification.account.id, conversationIdentifier: remoteNotification.account.id,
serviceName: nil, serviceName: nil,
sender: sender, sender: sender,
attachments: nil) attachments: nil)
if groupName != nil {
intent.setImage(avatar, forParameterNamed: \.speakableGroupName)
}
return intent return intent
} }
} }

View file

@ -6,7 +6,7 @@ import Network
import SwiftUI import SwiftUI
import UserNotifications import UserNotifications
public struct PushAccount { public struct PushAccount: Equatable {
public let server: String public let server: String
public let token: OauthToken public let token: OauthToken
public let accountName: String? public let accountName: String?
@ -18,6 +18,11 @@ public struct PushAccount {
} }
} }
public struct HandledNotification: Equatable {
public let account: PushAccount
public let notification: Models.Notification
}
@MainActor @MainActor
public class PushNotificationsService: NSObject, ObservableObject { public class PushNotificationsService: NSObject, ObservableObject {
enum Constants { enum Constants {
@ -31,7 +36,8 @@ public class PushNotificationsService: NSObject, ObservableObject {
public private(set) var subscriptions: [PushNotificationSubscriptionSettings] = [] public private(set) var subscriptions: [PushNotificationSubscriptionSettings] = []
@Published public var pushToken: Data? @Published public var pushToken: Data?
@Published public var handleNotification: Models.Notification?
@Published public var handledNotification: HandledNotification?
override init() { override init() {
super.init() super.init()
@ -139,7 +145,7 @@ extension PushNotificationsService: UNUserNotificationCenterDelegate {
let client = Client(server: account.account.server, oauthToken: account.account.token) let client = Client(server: account.account.server, oauthToken: account.account.token)
let notification: Models.Notification = let notification: Models.Notification =
try await client.get(endpoint: Notifications.notification(id:String(mastodonPushNotification.notificationID))) try await client.get(endpoint: Notifications.notification(id:String(mastodonPushNotification.notificationID)))
self.handleNotification = notification self.handledNotification = .init(account: account.account, notification: notification)
} catch { } } catch { }
} }
} }

View file

@ -3,7 +3,7 @@ import Models
import SwiftUI import SwiftUI
extension Models.Notification.NotificationType { extension Models.Notification.NotificationType {
func label(count: Int) -> LocalizedStringKey { public func label(count: Int) -> LocalizedStringKey {
switch self { switch self {
case .status: case .status:
return "notifications.label.status" return "notifications.label.status"
@ -24,6 +24,27 @@ extension Models.Notification.NotificationType {
} }
} }
public func notificationKey() -> String {
switch self {
case .status:
return "notifications.label.status.push"
case .mention:
return ""
case .reblog:
return "notifications.label.reblog.push"
case .follow:
return "notifications.label.follow.push"
case .follow_request:
return "notifications.label.follow-request.push"
case .favourite:
return "notifications.label.favorite.push"
case .poll:
return "notifications.label.poll.push"
case .update:
return "notifications.label.update.push"
}
}
func iconName() -> String { func iconName() -> String {
switch self { switch self {
case .status: case .status: