From 332543aa3da33e246724329cf490acbce9454f2d Mon Sep 17 00:00:00 2001 From: shannon Date: Wed, 5 Mar 2025 16:00:51 -0500 Subject: [PATCH] Remove Boutique Not appropriate for this use case. --- Mastodon.xcodeproj/project.pbxproj | 19 +-- .../BoutiqueStores.swift | 136 ------------------ .../LastReadMarkers.swift | 71 +++++++++ .../NotificationsCacheManager.swift | 5 +- 4 files changed, 74 insertions(+), 157 deletions(-) delete mode 100644 Mastodon/In Progress New Layout and Datamodel/BoutiqueStores.swift create mode 100644 Mastodon/In Progress New Layout and Datamodel/LastReadMarkers.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index f97558913..ff2118b9e 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -509,7 +509,6 @@ DBFEEC99279BDCDE004F81DD /* ProfileAboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC98279BDCDE004F81DD /* ProfileAboutViewModel.swift */; }; DBFEEC9B279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9A279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift */; }; DBFEEC9D279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9C279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift */; }; - FB24973A2D6771D500A508B2 /* Boutique in Frameworks */ = {isa = PBXBuildFile; productRef = FB2497392D6771D500A508B2 /* Boutique */; }; FB7C4CC62CD2CAB000F6129A /* DonationCompletionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CC52CD2CAA800F6129A /* DonationCompletionViewController.swift */; }; FB7C4CCC2CD55DEB00F6129A /* NavigationFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CCB2CD55DEB00F6129A /* NavigationFlow.swift */; }; FB7C4CCE2CD55DFF00F6129A /* NewDonationNavigationFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CCD2CD55DFE00F6129A /* NewDonationNavigationFlow.swift */; }; @@ -1276,9 +1275,9 @@ FBBEA04F2D3819080000A900 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - BoutiqueStores.swift, GroupedNotificationFeedLoader.swift, InlinePostPreview.swift, + LastReadMarkers.swift, NotificationInfo.swift, NotificationListViewController.swift, NotificationRowView.swift, @@ -1328,7 +1327,6 @@ DBF96326262EC0A6001D8D25 /* AuthenticationServices.framework in Frameworks */, D84FA0932AE6915800987F47 /* MBProgressHUD in Frameworks */, D87364F92AE28DB500C8F919 /* Kanna in Frameworks */, - FB24973A2D6771D500A508B2 /* Boutique in Frameworks */, 2AAAA34E2B04DE21004C6672 /* VisionKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3186,7 +3184,6 @@ 357FEEAE29523D470021C9DC /* MastodonSDKDynamic */, D87364F82AE28DB500C8F919 /* Kanna */, D84FA0922AE6915800987F47 /* MBProgressHUD */, - FB2497392D6771D500A508B2 /* Boutique */, ); productName = Mastodon; productReference = DB427DD225BAA00100D1B89D /* Mastodon.app */; @@ -3372,7 +3369,6 @@ 2AB501192992322500346092 /* XCRemoteSwiftPackageReference "LightChart" */, D87364F72AE28DB500C8F919 /* XCRemoteSwiftPackageReference "Kanna" */, D84FA0912AE6915800987F47 /* XCRemoteSwiftPackageReference "MBProgressHUD" */, - FB2497382D67704100A508B2 /* XCRemoteSwiftPackageReference "Boutique" */, ); productRefGroup = DB427DD325BAA00100D1B89D /* Products */; projectDirPath = ""; @@ -5455,14 +5451,6 @@ minimumVersion = 5.2.7; }; }; - FB2497382D67704100A508B2 /* XCRemoteSwiftPackageReference "Boutique" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/mergesort/Boutique.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 2.4.9; - }; - }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -5509,11 +5497,6 @@ package = D87364F72AE28DB500C8F919 /* XCRemoteSwiftPackageReference "Kanna" */; productName = Kanna; }; - FB2497392D6771D500A508B2 /* Boutique */ = { - isa = XCSwiftPackageProductDependency; - package = FB2497382D67704100A508B2 /* XCRemoteSwiftPackageReference "Boutique" */; - productName = Boutique; - }; /* End XCSwiftPackageProductDependency section */ }; rootObject = DB427DCA25BAA00100D1B89D /* Project object */; diff --git a/Mastodon/In Progress New Layout and Datamodel/BoutiqueStores.swift b/Mastodon/In Progress New Layout and Datamodel/BoutiqueStores.swift deleted file mode 100644 index 71a390749..000000000 --- a/Mastodon/In Progress New Layout and Datamodel/BoutiqueStores.swift +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright © 2025 Mastodon gGmbH. All rights reserved. - -import MastodonSDK -import Boutique -import MastodonCore - -extension MastodonFeedKind { - var storageTag: String? { - switch self { - case .notificationsAll: - return "all" - case .notificationsMentionsOnly: - return "mentions" - case .notificationsWithAccount: - return nil - } - } -} - -fileprivate let storageFileNameComponentSeparator = "_" - -fileprivate func storeFilenameFromBasename(_ basename: String, kind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> String { - assert(kind.storageTag != nil, "ATTEMPTING TO CACHE A FEED TYPE THAT SHOULD NOT BE CACHED") - let components = [userIdentifier.globallyUniqueUserIdentifier, - basename, - (kind.storageTag ?? "UNEXPECTED")] - return components.joined(separator: storageFileNameComponentSeparator) -} - -extension Store where Item == Mastodon.Entity.Notification { - static func ungroupedNotificationStore(forKind feedKind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: storeFilenameFromBasename("ungrouped_notification_store", kind: feedKind, forUser: userIdentifier)), cacheIdentifier: \.id) - } -} - -extension Store where Item == Mastodon.Entity.NotificationGroup { - static func notificationGroupStore(forKind feedKind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: storeFilenameFromBasename("notification_group_store", kind: feedKind, forUser: userIdentifier)), cacheIdentifier: \.id) - } -} - -extension Store where Item == Mastodon.Entity.Account { - static func notificationRelevantFullAccountStore(forKind feedKind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: storeFilenameFromBasename("notification_relevant_full_account_store", kind: feedKind, forUser: userIdentifier)), cacheIdentifier: \.id) - } -} - -extension Store where Item == Mastodon.Entity.PartialAccountWithAvatar { - static func notificationRelevantPartialAccountStore(forKind feedKind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: storeFilenameFromBasename("notification_relevant_partial_account_store", kind: feedKind, forUser: userIdentifier)), cacheIdentifier: \.id) - } -} - -extension Store where Item == Mastodon.Entity.Status { - static func notificationRelevantStatusStore(forKind feedKind: MastodonFeedKind, forUser userIdentifier: MastodonUserIdentifier) -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: storeFilenameFromBasename("notification_relevant_status_store", kind: feedKind, forUser: userIdentifier)), cacheIdentifier: \.id) - } -} - -extension Store where Item == LastReadMarkers { - static func lastReadMarkersStore() -> Store { - return Store( - storage: SQLiteStorageEngine.default(appendingPath: "last_read_markers_store"), cacheIdentifier: \.id) - } -} - -struct LastReadMarkers: Identifiable, Codable { - enum MarkerPosition: Codable { - case local(lastReadID: String) - case fromServer(Mastodon.Entity.Marker.Position) - - var lastReadID: String { - switch self { - case .local(let lastReadID): - return lastReadID - case .fromServer(let position): - return position.lastReadID - } - } - } - - let userGUID: String - let homeTimelineLastRead: MarkerPosition? - let notificationsLastRead: MarkerPosition? - let mentionsLastRead: MarkerPosition? - - var id: String { - return userGUID - } - - init(userGUID: String, home: MarkerPosition?, notifications: MarkerPosition?, mentions: MarkerPosition?) { - self.userGUID = userGUID - self.homeTimelineLastRead = home - self.notificationsLastRead = notifications - if let notifications, let mentions { - if mentions.lastReadID > notifications.lastReadID { - self.mentionsLastRead = mentions - } else { - self.mentionsLastRead = nil - } - } else { - self.mentionsLastRead = mentions - } - } - - func lastRead(forKind kind: MastodonFeedKind) -> MarkerPosition? { - switch kind { - case .notificationsAll: - return notificationsLastRead - case .notificationsMentionsOnly: - return mentionsLastRead ?? notificationsLastRead - case .notificationsWithAccount: - return nil - } - } - - func bySettingLastRead(_ newPosition: MarkerPosition, forKind kind: MastodonFeedKind) -> LastReadMarkers { - if let previous = lastRead(forKind: kind) { - guard previous.lastReadID < newPosition.lastReadID else { return self } - } - switch kind { - case .notificationsAll: - return LastReadMarkers(userGUID: userGUID, home: homeTimelineLastRead, notifications: newPosition, mentions: mentionsLastRead) - case .notificationsMentionsOnly: - return LastReadMarkers(userGUID: userGUID, home: homeTimelineLastRead, notifications: notificationsLastRead, mentions: newPosition) - case .notificationsWithAccount: - return self - } - } -} - diff --git a/Mastodon/In Progress New Layout and Datamodel/LastReadMarkers.swift b/Mastodon/In Progress New Layout and Datamodel/LastReadMarkers.swift new file mode 100644 index 000000000..99eabb96b --- /dev/null +++ b/Mastodon/In Progress New Layout and Datamodel/LastReadMarkers.swift @@ -0,0 +1,71 @@ +// Copyright © 2025 Mastodon gGmbH. All rights reserved. + +import MastodonSDK +import MastodonCore +import Foundation + +struct LastReadMarkers: Identifiable, Codable { + enum MarkerPosition: Codable { + case local(lastReadID: String) + case fromServer(Mastodon.Entity.Marker.Position) + + var lastReadID: String { + switch self { + case .local(let lastReadID): + return lastReadID + case .fromServer(let position): + return position.lastReadID + } + } + } + + let userGUID: String + let homeTimelineLastRead: MarkerPosition? + let notificationsLastRead: MarkerPosition? + let mentionsLastRead: MarkerPosition? + + var id: String { + return userGUID + } + + init(userGUID: String, home: MarkerPosition?, notifications: MarkerPosition?, mentions: MarkerPosition?) { + self.userGUID = userGUID + self.homeTimelineLastRead = home + self.notificationsLastRead = notifications + if let notifications, let mentions { + if mentions.lastReadID > notifications.lastReadID { + self.mentionsLastRead = mentions + } else { + self.mentionsLastRead = nil + } + } else { + self.mentionsLastRead = mentions + } + } + + func lastRead(forKind kind: MastodonFeedKind) -> MarkerPosition? { + switch kind { + case .notificationsAll: + return notificationsLastRead + case .notificationsMentionsOnly: + return mentionsLastRead ?? notificationsLastRead + case .notificationsWithAccount: + return nil + } + } + + func bySettingLastRead(_ newPosition: MarkerPosition, forKind kind: MastodonFeedKind) -> LastReadMarkers { + if let previous = lastRead(forKind: kind) { + guard previous.lastReadID < newPosition.lastReadID else { return self } + } + switch kind { + case .notificationsAll: + return LastReadMarkers(userGUID: userGUID, home: homeTimelineLastRead, notifications: newPosition, mentions: mentionsLastRead) + case .notificationsMentionsOnly: + return LastReadMarkers(userGUID: userGUID, home: homeTimelineLastRead, notifications: notificationsLastRead, mentions: newPosition) + case .notificationsWithAccount: + return self + } + } +} + diff --git a/Mastodon/In Progress New Layout and Datamodel/NotificationsCacheManager.swift b/Mastodon/In Progress New Layout and Datamodel/NotificationsCacheManager.swift index e589992c5..a24ba4fc4 100644 --- a/Mastodon/In Progress New Layout and Datamodel/NotificationsCacheManager.swift +++ b/Mastodon/In Progress New Layout and Datamodel/NotificationsCacheManager.swift @@ -1,6 +1,5 @@ // Copyright © 2025 Mastodon gGmbH. All rights reserved. -import Boutique import MastodonSDK import MastodonCore @@ -61,7 +60,7 @@ class UngroupedNotificationCacheManager: NotificationsCacheManager { staleResults = try PersistenceManager.shared.cached(.notificationsAll(userIdentifier)) case .notificationsMentionsOnly: staleResults = try PersistenceManager.shared.cached(.notificationsMentions(userIdentifier)) - case .notificationsWithAccount(let string): + case .notificationsWithAccount: staleResults = nil } } catch { @@ -294,7 +293,7 @@ class GroupedNotificationCacheManager: NotificationsCacheManager { accounts = (try? PersistenceManager.shared.cached(.groupedNotificationsMentionsAccounts(userIdentifier))) ?? [] partialAccounts = (try? PersistenceManager.shared.cached(.groupedNotificationsMentionsPartialAccounts(userIdentifier))) ?? [] statuses = (try? PersistenceManager.shared.cached(.groupedNotificationsMentionsStatuses(userIdentifier))) ?? [] - case .notificationsWithAccount(let string): + case .notificationsWithAccount: return mostRecentlyFetchedResults } staleResults = Mastodon.Entity.GroupedNotificationsResults(notificationGroups: notificationGroups, fullAccounts: accounts, partialAccounts: partialAccounts, statuses: statuses)