From 5d99ff799eb4d7f599393eb4fe47d48d12a14057 Mon Sep 17 00:00:00 2001 From: Anna Zakharova Date: Tue, 27 May 2025 18:47:46 +0100 Subject: [PATCH 1/2] IOS-4691 Make separate NotificationsCore package --- Anytype.xcodeproj/project.pbxproj | 30 +++++++++------ .../ApplicationLayer/AppDelegate.swift | 1 + .../EncryptionKeyEventHandler.swift | 1 + .../NotificationService.swift | 9 +---- .../Generated/FeatureFlags+Flags.swift | 5 --- .../FeatureDescription+Flags.swift | 6 --- Modules/NotificationsCore/.gitignore | 8 ++++ Modules/NotificationsCore/Package.swift | 37 +++++++++++++++++++ .../NotificationsCore}/CryptoService.swift | 4 +- .../DecryptedPushContent.swift | 0 .../DecryptedPushKeys.swift | 0 .../DecryptionPushContentService.swift | 12 +++--- .../EncryptionKeyService.swift | 10 +++-- .../NotificationsCoreTests.swift | 6 +++ Modules/Services/Package.swift | 6 ++- Modules/Services/Sources/ServicesDI.swift | 9 +---- 16 files changed, 94 insertions(+), 50 deletions(-) create mode 100644 Modules/NotificationsCore/.gitignore create mode 100644 Modules/NotificationsCore/Package.swift rename Modules/{Services/Sources/Services/CryptoService => NotificationsCore/Sources/NotificationsCore}/CryptoService.swift (87%) rename Modules/{Services/Sources/Models => NotificationsCore/Sources/NotificationsCore}/DecryptedPushContent.swift (100%) rename Modules/{Services/Sources/Models => NotificationsCore/Sources/NotificationsCore}/DecryptedPushKeys.swift (100%) rename Modules/{Services/Sources/Services/DecryptionPushContentService => NotificationsCore/Sources/NotificationsCore}/DecryptionPushContentService.swift (72%) rename Modules/{Services/Sources/Services/EncryptionKeyService => NotificationsCore/Sources/NotificationsCore}/EncryptionKeyService.swift (74%) create mode 100644 Modules/NotificationsCore/Tests/NotificationsCoreTests/NotificationsCoreTests.swift diff --git a/Anytype.xcodeproj/project.pbxproj b/Anytype.xcodeproj/project.pbxproj index 30d4896e78..ee2c9ce0e3 100644 --- a/Anytype.xcodeproj/project.pbxproj +++ b/Anytype.xcodeproj/project.pbxproj @@ -49,12 +49,12 @@ 2AB511AE29093CB4005D0A91 /* InlineMarkdownListenerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB511AD29093CB4005D0A91 /* InlineMarkdownListenerTests.swift */; }; 2ADB57862CB6B6FE00BFC386 /* Cache in Frameworks */ = {isa = PBXBuildFile; productRef = 2ADB57852CB6B6FE00BFC386 /* Cache */; }; 2ADD66782CB57036009ED95E /* MessageAttachmentsGridLayoutBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ADD66772CB57036009ED95E /* MessageAttachmentsGridLayoutBuilderTests.swift */; }; + 2E074C4C2DE620E800260ABD /* NotificationsCore in Frameworks */ = {isa = PBXBuildFile; productRef = 2E074C4B2DE620E800260ABD /* NotificationsCore */; }; + 2E074C4E2DE623DB00260ABD /* NotificationsCore in Frameworks */ = {isa = PBXBuildFile; productRef = 2E074C4D2DE623DB00260ABD /* NotificationsCore */; }; 2E3058142D81DF7F00BF4F25 /* AnytypeNotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2E30580D2D81DF7E00BF4F25 /* AnytypeNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 2E428A262DA836B900B849EF /* Factory in Frameworks */ = {isa = PBXBuildFile; productRef = 2E428A252DA836B900B849EF /* Factory */; }; 2E63D9B72D56520C008A733A /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 2E63D9B62D56520C008A733A /* FirebaseMessaging */; }; 2ED425D22DDE3CF5008C7AD3 /* Loc in Frameworks */ = {isa = PBXBuildFile; productRef = 2ED425D12DDE3CF5008C7AD3 /* Loc */; }; 2ED5E1542DAFE2A700B59485 /* AnytypeCore in Frameworks */ = {isa = PBXBuildFile; productRef = 2ED5E1532DAFE2A700B59485 /* AnytypeCore */; }; - 2EDD08442DA833720050397F /* Services in Frameworks */ = {isa = PBXBuildFile; productRef = 2EDD08432DA833720050397F /* Services */; }; 2EEE411E2C1080AD000AB88B /* CachedAsyncImage in Frameworks */ = {isa = PBXBuildFile; productRef = 2EEE411D2C1080AD000AB88B /* CachedAsyncImage */; }; 3D24B09C2C1A2DAF00795BAA /* ConfettiSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3D24B09B2C1A2DAF00795BAA /* ConfettiSwiftUI */; }; 3D30407727D66E7E00FFE0EB /* InfoContainerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D30407627D66E7E00FFE0EB /* InfoContainerMock.swift */; }; @@ -329,6 +329,7 @@ 538ABD4E284F9F88000D3CCC /* Collections in Frameworks */, 7411879B2D9ADD200006EA41 /* Loc in Frameworks */, 2A94B5D329B88E95009AE2A7 /* Sentry in Frameworks */, + 2E074C4C2DE620E800260ABD /* NotificationsCore in Frameworks */, 1259300E26F3A6AE00B115CD /* Kingfisher in Frameworks */, 2ADB57862CB6B6FE00BFC386 /* Cache in Frameworks */, 538ABD50284F9F88000D3CCC /* DequeModule in Frameworks */, @@ -373,9 +374,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 2EDD08442DA833720050397F /* Services in Frameworks */, + 2E074C4E2DE623DB00260ABD /* NotificationsCore in Frameworks */, 2ED425D22DDE3CF5008C7AD3 /* Loc in Frameworks */, - 2E428A262DA836B900B849EF /* Factory in Frameworks */, 2ED5E1542DAFE2A700B59485 /* AnytypeCore in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -695,6 +695,7 @@ 74EB806B2D79D3EA003F8D84 /* Assets */, 7411879A2D9ADD200006EA41 /* Loc */, 746F06002DB8E712005795F7 /* DesignKit */, + 2E074C4B2DE620E800260ABD /* NotificationsCore */, ); productName = Anytype; productReference = 0303ECFB22D8EDAA005C552B /* Anytype.app */; @@ -865,6 +866,7 @@ 2ADB57842CB6B6FE00BFC386 /* XCRemoteSwiftPackageReference "Cache" */, 2E63D9B52D56520C008A733A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 74B35D242D5B39C500AC9879 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */, + 2E074C4A2DE620E800260ABD /* XCLocalSwiftPackageReference "Modules/NotificationsCore" */, ); preferredProjectObjectVersion = 52; productRefGroup = 0303ECFC22D8EDAA005C552B /* Products */; @@ -2844,6 +2846,13 @@ }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 2E074C4A2DE620E800260ABD /* XCLocalSwiftPackageReference "Modules/NotificationsCore" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Modules/NotificationsCore; + }; +/* End XCLocalSwiftPackageReference section */ + /* Begin XCRemoteSwiftPackageReference section */ 1259300326F3A5C500B115CD /* XCRemoteSwiftPackageReference "Highlightr" */ = { isa = XCRemoteSwiftPackageReference; @@ -3125,10 +3134,13 @@ package = 2ADB57842CB6B6FE00BFC386 /* XCRemoteSwiftPackageReference "Cache" */; productName = Cache; }; - 2E428A252DA836B900B849EF /* Factory */ = { + 2E074C4B2DE620E800260ABD /* NotificationsCore */ = { isa = XCSwiftPackageProductDependency; - package = 2AC1262B2B90F65F003A4A8D /* XCRemoteSwiftPackageReference "Factory" */; - productName = Factory; + productName = NotificationsCore; + }; + 2E074C4D2DE623DB00260ABD /* NotificationsCore */ = { + isa = XCSwiftPackageProductDependency; + productName = NotificationsCore; }; 2E63D9B62D56520C008A733A /* FirebaseMessaging */ = { isa = XCSwiftPackageProductDependency; @@ -3143,10 +3155,6 @@ isa = XCSwiftPackageProductDependency; productName = AnytypeCore; }; - 2EDD08432DA833720050397F /* Services */ = { - isa = XCSwiftPackageProductDependency; - productName = Services; - }; 2EEE411D2C1080AD000AB88B /* CachedAsyncImage */ = { isa = XCSwiftPackageProductDependency; package = 2EEE411C2C1080AD000AB88B /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */; diff --git a/Anytype/Sources/ApplicationLayer/AppDelegate.swift b/Anytype/Sources/ApplicationLayer/AppDelegate.swift index 9748f35558..e1f9d06add 100644 --- a/Anytype/Sources/ApplicationLayer/AppDelegate.swift +++ b/Anytype/Sources/ApplicationLayer/AppDelegate.swift @@ -2,6 +2,7 @@ import UIKit import AnytypeCore import FirebaseMessaging import Services +import NotificationsCore class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { diff --git a/Anytype/Sources/ServiceLayer/EncryptionKeyEventHandler/EncryptionKeyEventHandler.swift b/Anytype/Sources/ServiceLayer/EncryptionKeyEventHandler/EncryptionKeyEventHandler.swift index 5f3b89cea0..e5f11f73b3 100644 --- a/Anytype/Sources/ServiceLayer/EncryptionKeyEventHandler/EncryptionKeyEventHandler.swift +++ b/Anytype/Sources/ServiceLayer/EncryptionKeyEventHandler/EncryptionKeyEventHandler.swift @@ -1,5 +1,6 @@ import Services import AnytypeCore +import NotificationsCore protocol EncryptionKeyEventHandlerProtocol: AnyObject, Sendable { func startSubscription() async diff --git a/AnytypeNotificationServiceExtension/NotificationService.swift b/AnytypeNotificationServiceExtension/NotificationService.swift index f8c5df7747..195015e018 100644 --- a/AnytypeNotificationServiceExtension/NotificationService.swift +++ b/AnytypeNotificationServiceExtension/NotificationService.swift @@ -1,22 +1,17 @@ import UserNotifications -import Services import AnytypeCore import Loc +import NotificationsCore class NotificationService: UNNotificationServiceExtension { - private let decryptionPushContentService: any DecryptionPushContentServiceProtocol = Container.shared.decryptionPushContentService() - private let basicUserInfoStorage: any BasicUserInfoStorageProtocol = Container.shared.basicUserInfoStorage() + private let decryptionPushContentService: any DecryptionPushContentServiceProtocol = DecryptionPushContentService() var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { - if FeatureFlags.checkLoginInNotificationService, basicUserInfoStorage.usersId.isEmpty { - return - } - self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) diff --git a/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift b/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift index aff5f8ed1e..3b09a258c0 100644 --- a/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift +++ b/Modules/AnytypeCore/AnytypeCore/Generated/FeatureFlags+Flags.swift @@ -130,10 +130,6 @@ public extension FeatureFlags { value(for: .chatWidget) } - static var checkLoginInNotificationService: Bool { - value(for: .checkLoginInNotificationService) - } - static var rainbowViews: Bool { value(for: .rainbowViews) } @@ -231,7 +227,6 @@ public extension FeatureFlags { .binScreenEmptyAction, .openFullscreenObjectsFromSetWidget, .chatWidget, - .checkLoginInNotificationService, .rainbowViews, .showAlertOnAssert, .analytics, diff --git a/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift b/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift index d7c25476aa..df8a941211 100644 --- a/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift +++ b/Modules/AnytypeCore/AnytypeCore/Utils/FeatureFlags/FeatureDescription+Flags.swift @@ -223,12 +223,6 @@ public extension FeatureDescription { defaultValue: false ) - static let checkLoginInNotificationService = FeatureDescription( - title: "Check login in NotificationService", - type: .feature(author: "joe_pusya@anytype.io", releaseVersion: "11"), - defaultValue: true - ) - // MARK: - Debug static let rainbowViews = FeatureDescription( diff --git a/Modules/NotificationsCore/.gitignore b/Modules/NotificationsCore/.gitignore new file mode 100644 index 0000000000..0023a53406 --- /dev/null +++ b/Modules/NotificationsCore/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Modules/NotificationsCore/Package.swift b/Modules/NotificationsCore/Package.swift new file mode 100644 index 0000000000..952aba8013 --- /dev/null +++ b/Modules/NotificationsCore/Package.swift @@ -0,0 +1,37 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "NotificationsCore", + platforms: [ + .iOS(.v16), + ], + products: [ + .library( + name: "NotificationsCore", + type: .dynamic, + targets: ["NotificationsCore"]), + ], + dependencies: [ + .package(path: "../AnytypeCore"), + .package(path: "../SecureService"), + ], + targets: [ + .target( + name: "NotificationsCore", + dependencies: [ + "AnytypeCore", + "SecureService" + ], + swiftSettings: [ + .swiftLanguageMode(.v6) + ] + ), + .testTarget( + name: "NotificationsCoreTests", + dependencies: ["NotificationsCore"] + ), + ] +) diff --git a/Modules/Services/Sources/Services/CryptoService/CryptoService.swift b/Modules/NotificationsCore/Sources/NotificationsCore/CryptoService.swift similarity index 87% rename from Modules/Services/Sources/Services/CryptoService/CryptoService.swift rename to Modules/NotificationsCore/Sources/NotificationsCore/CryptoService.swift index 5b09380821..be632b9ca2 100644 --- a/Modules/Services/Sources/Services/CryptoService/CryptoService.swift +++ b/Modules/NotificationsCore/Sources/NotificationsCore/CryptoService.swift @@ -1,7 +1,7 @@ import Foundation import CryptoKit -public protocol CryptoServiceProtocol: AnyObject, Sendable { +protocol CryptoServiceProtocol: AnyObject, Sendable { func decryptAESGCM(data: Data, keyData: Data) throws -> Data } @@ -22,6 +22,6 @@ final class CryptoService: CryptoServiceProtocol { } } -public enum CryptoError: Error { +enum CryptoError: Error { case decryptionFailed } diff --git a/Modules/Services/Sources/Models/DecryptedPushContent.swift b/Modules/NotificationsCore/Sources/NotificationsCore/DecryptedPushContent.swift similarity index 100% rename from Modules/Services/Sources/Models/DecryptedPushContent.swift rename to Modules/NotificationsCore/Sources/NotificationsCore/DecryptedPushContent.swift diff --git a/Modules/Services/Sources/Models/DecryptedPushKeys.swift b/Modules/NotificationsCore/Sources/NotificationsCore/DecryptedPushKeys.swift similarity index 100% rename from Modules/Services/Sources/Models/DecryptedPushKeys.swift rename to Modules/NotificationsCore/Sources/NotificationsCore/DecryptedPushKeys.swift diff --git a/Modules/Services/Sources/Services/DecryptionPushContentService/DecryptionPushContentService.swift b/Modules/NotificationsCore/Sources/NotificationsCore/DecryptionPushContentService.swift similarity index 72% rename from Modules/Services/Sources/Services/DecryptionPushContentService/DecryptionPushContentService.swift rename to Modules/NotificationsCore/Sources/NotificationsCore/DecryptionPushContentService.swift index 46cd287c57..0db71b37bc 100644 --- a/Modules/Services/Sources/Services/DecryptionPushContentService/DecryptionPushContentService.swift +++ b/Modules/NotificationsCore/Sources/NotificationsCore/DecryptionPushContentService.swift @@ -5,13 +5,15 @@ public protocol DecryptionPushContentServiceProtocol: AnyObject, Sendable { func decrypt(_ encryptedData: Data, keyId: String) -> DecryptedPushContent? } -final class DecryptionPushContentService: DecryptionPushContentServiceProtocol { +public final class DecryptionPushContentService: DecryptionPushContentServiceProtocol { - private let cryptoService: any CryptoServiceProtocol = Container.shared.cryptoService() - private let encryptionKeyService: any EncryptionKeyServiceProtocol = Container.shared.encryptionKeyService() + private let cryptoService: any CryptoServiceProtocol = CryptoService() + private let encryptionKeyService: any EncryptionKeyServiceProtocol = EncryptionKeyService() private let decoder = JSONDecoder() - func decrypt(_ encryptedData: Data, keyId: String) -> DecryptedPushContent? { + public init() {} + + public func decrypt(_ encryptedData: Data, keyId: String) -> DecryptedPushContent? { do { let keyString = try encryptionKeyService.obtainKeyById(keyId) @@ -30,6 +32,6 @@ final class DecryptionPushContentService: DecryptionPushContentServiceProtocol { } -public enum DecryptionPushContentError: Error { +enum DecryptionPushContentError: Error { case keyEncodeFailed } diff --git a/Modules/Services/Sources/Services/EncryptionKeyService/EncryptionKeyService.swift b/Modules/NotificationsCore/Sources/NotificationsCore/EncryptionKeyService.swift similarity index 74% rename from Modules/Services/Sources/Services/EncryptionKeyService/EncryptionKeyService.swift rename to Modules/NotificationsCore/Sources/NotificationsCore/EncryptionKeyService.swift index 9259e5c924..e000a670b7 100644 --- a/Modules/Services/Sources/Services/EncryptionKeyService/EncryptionKeyService.swift +++ b/Modules/NotificationsCore/Sources/NotificationsCore/EncryptionKeyService.swift @@ -7,15 +7,17 @@ public protocol EncryptionKeyServiceProtocol: AnyObject, Sendable { func saveKey(_ key: String, keyId: String) throws } -final class EncryptionKeyService: EncryptionKeyServiceProtocol { +public final class EncryptionKeyService: EncryptionKeyServiceProtocol { - private let keychainStore: any KeychainStoreProtocol = Container.shared.keychainStore() + private let keychainStore: any KeychainStoreProtocol = KeychainStore() - func obtainKeyById(_ keyId: String) throws -> String { + public init() {} + + public func obtainKeyById(_ keyId: String) throws -> String { try keychainStore.retreiveItem(queryable: query(with: keyId)) } - func saveKey(_ key: String, keyId: String) throws { + public func saveKey(_ key: String, keyId: String) throws { try keychainStore.storeItem(item: key, queryable: query(with: keyId)) } diff --git a/Modules/NotificationsCore/Tests/NotificationsCoreTests/NotificationsCoreTests.swift b/Modules/NotificationsCore/Tests/NotificationsCoreTests/NotificationsCoreTests.swift new file mode 100644 index 0000000000..caed41cd8e --- /dev/null +++ b/Modules/NotificationsCore/Tests/NotificationsCoreTests/NotificationsCoreTests.swift @@ -0,0 +1,6 @@ +import Testing +@testable import NotificationsCore + +@Test func example() async throws { + // Write your test here and use APIs like `#expect(...)` to check expected conditions. +} diff --git a/Modules/Services/Package.swift b/Modules/Services/Package.swift index be3d83fe2b..37b8fe34a8 100644 --- a/Modules/Services/Package.swift +++ b/Modules/Services/Package.swift @@ -17,7 +17,8 @@ let package = Package( .package(url: "https://github.com/hmlongco/Factory", revision: "2.3.1"), .package(path: "../ProtobufMessages"), .package(path: "../AnytypeCore"), - .package(path: "../SecureService") + .package(path: "../SecureService"), + .package(path: "../NotificationsCore") ], targets: [ .target( @@ -27,7 +28,8 @@ let package = Package( "Factory", "ProtobufMessages", "AnytypeCore", - "SecureService" + "SecureService", + "NotificationsCore" ], path: "Sources", swiftSettings: [ diff --git a/Modules/Services/Sources/ServicesDI.swift b/Modules/Services/Sources/ServicesDI.swift index 721c681bf2..ec496f70e5 100644 --- a/Modules/Services/Sources/ServicesDI.swift +++ b/Modules/Services/Sources/ServicesDI.swift @@ -1,5 +1,6 @@ import Foundation import SecureService +import NotificationsCore // Automatically export Factory when import Servies @_exported import Factory @@ -165,14 +166,6 @@ public extension Container { self { EncryptionKeyService() }.shared } - var cryptoService: Factory { - self { CryptoService() }.shared - } - - var decryptionPushContentService: Factory { - self { DecryptionPushContentService() }.shared - } - var basicUserInfoStorage: Factory { self { BasicUserInfoStorage() }.singleton } From 143deb97939bf29fc670d01eae9a332ee89cff23 Mon Sep 17 00:00:00 2001 From: Anna Zakharova Date: Tue, 27 May 2025 18:55:28 +0100 Subject: [PATCH 2/2] IOS-4691 Fix proj --- Anytype.xcodeproj/project.pbxproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Anytype.xcodeproj/project.pbxproj b/Anytype.xcodeproj/project.pbxproj index ee2c9ce0e3..1c6c63e615 100644 --- a/Anytype.xcodeproj/project.pbxproj +++ b/Anytype.xcodeproj/project.pbxproj @@ -866,7 +866,6 @@ 2ADB57842CB6B6FE00BFC386 /* XCRemoteSwiftPackageReference "Cache" */, 2E63D9B52D56520C008A733A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 74B35D242D5B39C500AC9879 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */, - 2E074C4A2DE620E800260ABD /* XCLocalSwiftPackageReference "Modules/NotificationsCore" */, ); preferredProjectObjectVersion = 52; productRefGroup = 0303ECFC22D8EDAA005C552B /* Products */; @@ -2846,13 +2845,6 @@ }; /* End XCConfigurationList section */ -/* Begin XCLocalSwiftPackageReference section */ - 2E074C4A2DE620E800260ABD /* XCLocalSwiftPackageReference "Modules/NotificationsCore" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = Modules/NotificationsCore; - }; -/* End XCLocalSwiftPackageReference section */ - /* Begin XCRemoteSwiftPackageReference section */ 1259300326F3A5C500B115CD /* XCRemoteSwiftPackageReference "Highlightr" */ = { isa = XCRemoteSwiftPackageReference;