From 15d6e10edc0435a66f0f947e4ec1988ecde0fbbf Mon Sep 17 00:00:00 2001 From: Justin Mazzocchi <2831158+jzzocc@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:50:05 -0700 Subject: [PATCH] The great id cleanup --- .swiftlint.yml | 1 + DB/Sources/DB/Content/AccountList.swift | 8 ++- DB/Sources/DB/Content/AccountListJoin.swift | 5 +- .../DB/Content/AccountPinnedStatusJoin.swift | 5 +- DB/Sources/DB/Content/AccountRecord.swift | 4 +- DB/Sources/DB/Content/ContentDatabase.swift | 60 +++++++++---------- DB/Sources/DB/Content/LoadMoreRecord.swift | 6 +- .../DB/Content/StatusAncestorJoin.swift | 5 +- .../DB/Content/StatusDescendantJoin.swift | 5 +- DB/Sources/DB/Content/StatusRecord.swift | 10 ++-- DB/Sources/DB/Content/TimelineRecord.swift | 6 +- .../DB/Content/TimelineStatusJoin.swift | 5 +- DB/Sources/DB/Entities/Identity.swift | 8 ++- DB/Sources/DB/Entities/IdentityFixture.swift | 4 +- DB/Sources/DB/Entities/LoadMore.swift | 4 +- DB/Sources/DB/Entities/Timeline.swift | 6 +- .../Identity/IdentityDatabase+Migration.swift | 2 +- DB/Sources/DB/Identity/IdentityDatabase.swift | 46 +++++++------- DB/Sources/DB/Identity/IdentityRecord.swift | 2 +- HTTP/Sources/Stubbing/Stubbing.swift | 2 +- .../Sources/Mastodon/Entities/Account.swift | 8 ++- .../Mastodon/Entities/AppAuthorization.swift | 6 +- .../Mastodon/Entities/Attachment.swift | 6 +- .../Sources/Mastodon/Entities/Filter.swift | 8 ++- Mastodon/Sources/Mastodon/Entities/List.swift | 8 ++- .../Sources/Mastodon/Entities/Mention.swift | 2 +- Mastodon/Sources/Mastodon/Entities/Poll.swift | 6 +- .../Sources/Mastodon/Entities/Status.swift | 14 +++-- .../Endpoints/AccessTokenEndpoint.swift | 6 +- .../Endpoints/AccountEndpoint.swift | 2 +- .../Endpoints/AccountsEndpoint.swift | 12 ++-- .../Endpoints/ContextEndpoint.swift | 2 +- .../Endpoints/DeletionEndpoint.swift | 10 ++-- .../Endpoints/FilterEndpoint.swift | 2 +- .../Sources/MastodonAPI/Endpoints/Paged.swift | 26 ++++---- .../Endpoints/StatusEndpoint.swift | 6 +- .../Endpoints/StatusesEndpoint.swift | 4 +- .../MastodonAPI/MastodonAPIClient.swift | 22 +++---- .../NotificationService.swift | 8 +-- Secrets/Sources/Secrets/Secrets.swift | 24 ++++---- .../Services/AccountListService.swift | 14 ++--- .../Services/AllIdentitiesService.swift | 22 +++---- .../Services/AuthenticationService.swift | 7 ++- .../Services/CollectionService.swift | 10 ++-- .../Services/ContextService.swift | 18 +++--- .../Services/IdentityService.swift | 40 ++++++------- .../Services/LoadMoreService.swift | 4 +- .../Services/NavigationService.swift | 40 ++++++------- .../Services/ProfileService.swift | 16 ++--- .../ServiceLayer/Services/StatusService.swift | 4 +- .../Services/TimelineService.swift | 15 +++-- .../InstanceURLServiceTests.swift | 2 +- View Controllers/TableViewController.swift | 6 +- .../PreviewViewModels/PreviewViewModels.swift | 8 +-- .../ViewModels/CollectionItemsViewModel.swift | 22 +++---- .../ViewModels/CollectionViewModel.swift | 4 +- .../ViewModels/EditFilterViewModel.swift | 2 +- .../ViewModels/IdentitiesViewModel.swift | 4 +- .../Sources/ViewModels/ProfileViewModel.swift | 10 ++-- .../Sources/ViewModels/RootViewModel.swift | 16 ++--- .../AddIdentityViewModelTests.swift | 8 +-- Views/AccountHeaderView.swift | 2 +- Views/IdentitiesView.swift | 4 +- 63 files changed, 345 insertions(+), 309 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 901eec4..b3e0b0c 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,5 +1,6 @@ disabled_rules: - identifier_name + - type_name # Swift 5.3 - multiple_closures_with_trailing_closure - no_space_in_method_call diff --git a/DB/Sources/DB/Content/AccountList.swift b/DB/Sources/DB/Content/AccountList.swift index 93b99eb..31ea610 100644 --- a/DB/Sources/DB/Content/AccountList.swift +++ b/DB/Sources/DB/Content/AccountList.swift @@ -4,13 +4,17 @@ import Foundation import GRDB public struct AccountList: Codable, FetchableRecord, PersistableRecord { - let id: UUID + let id: Id public init() { - id = UUID() + id = Id() } } +public extension AccountList { + typealias Id = UUID +} + extension AccountList { static let joins = hasMany(AccountListJoin.self).order(AccountListJoin.Columns.index) static let accounts = hasMany( diff --git a/DB/Sources/DB/Content/AccountListJoin.swift b/DB/Sources/DB/Content/AccountListJoin.swift index fea2a7f..5f266b0 100644 --- a/DB/Sources/DB/Content/AccountListJoin.swift +++ b/DB/Sources/DB/Content/AccountListJoin.swift @@ -2,10 +2,11 @@ import Foundation import GRDB +import Mastodon struct AccountListJoin: Codable, FetchableRecord, PersistableRecord { - let accountId: String - let listId: UUID + let accountId: Account.Id + let listId: AccountList.Id let index: Int static let account = belongsTo(AccountRecord.self) diff --git a/DB/Sources/DB/Content/AccountPinnedStatusJoin.swift b/DB/Sources/DB/Content/AccountPinnedStatusJoin.swift index 123e4b1..1e8d735 100644 --- a/DB/Sources/DB/Content/AccountPinnedStatusJoin.swift +++ b/DB/Sources/DB/Content/AccountPinnedStatusJoin.swift @@ -2,10 +2,11 @@ import Foundation import GRDB +import Mastodon struct AccountPinnedStatusJoin: Codable, FetchableRecord, PersistableRecord { - let accountId: String - let statusId: String + let accountId: Account.Id + let statusId: Status.Id let index: Int } diff --git a/DB/Sources/DB/Content/AccountRecord.swift b/DB/Sources/DB/Content/AccountRecord.swift index d82e761..5e863dd 100644 --- a/DB/Sources/DB/Content/AccountRecord.swift +++ b/DB/Sources/DB/Content/AccountRecord.swift @@ -5,7 +5,7 @@ import GRDB import Mastodon struct AccountRecord: Codable, Hashable { - let id: String + let id: Account.Id let username: String let acct: String let displayName: String @@ -24,7 +24,7 @@ struct AccountRecord: Codable, Hashable { let emojis: [Emoji] let bot: Bool let discoverable: Bool - let movedId: String? + let movedId: Account.Id? } extension AccountRecord { diff --git a/DB/Sources/DB/Content/ContentDatabase.swift b/DB/Sources/DB/Content/ContentDatabase.swift index 7fa3426..cc8810e 100644 --- a/DB/Sources/DB/Content/ContentDatabase.swift +++ b/DB/Sources/DB/Content/ContentDatabase.swift @@ -12,15 +12,15 @@ public struct ContentDatabase { private let databaseWriter: DatabaseWriter - public init(identityID: UUID, inMemory: Bool, keychain: Keychain.Type) throws { + public init(id: Identity.Id, inMemory: Bool, keychain: Keychain.Type) throws { if inMemory { databaseWriter = DatabaseQueue() } else { - let path = try Self.fileURL(identityID: identityID).path + let path = try Self.fileURL(id: id).path var configuration = Configuration() configuration.prepareDatabase { - try $0.usePassphrase(Secrets.databaseKey(identityID: identityID, keychain: keychain)) + try $0.usePassphrase(Secrets.databaseKey(identityId: id, keychain: keychain)) } databaseWriter = try DatabasePool(path: path, configuration: configuration) @@ -39,8 +39,8 @@ public struct ContentDatabase { } public extension ContentDatabase { - static func delete(forIdentityID identityID: UUID) throws { - try FileManager.default.removeItem(at: fileURL(identityID: identityID)) + static func delete(id: Identity.Id) throws { + try FileManager.default.removeItem(at: fileURL(id: id)) } func insert(status: Status) -> AnyPublisher { @@ -58,7 +58,7 @@ public extension ContentDatabase { try timelineRecord.save($0) - let maxIDPresent = try String.fetchOne($0, timelineRecord.statuses.select(max(StatusRecord.Columns.id))) + let maxIdPresent = try String.fetchOne($0, timelineRecord.statuses.select(max(StatusRecord.Columns.id))) for status in statuses { try status.save($0) @@ -66,13 +66,13 @@ public extension ContentDatabase { try TimelineStatusJoin(timelineId: timeline.id, statusId: status.id).save($0) } - if let maxIDPresent = maxIDPresent, - let minIDInserted = statuses.map(\.id).min(), - minIDInserted > maxIDPresent { + if let maxIdPresent = maxIdPresent, + let minIdInserted = statuses.map(\.id).min(), + minIdInserted > maxIdPresent { try LoadMoreRecord( timelineId: timeline.id, - afterStatusId: minIDInserted, - beforeStatusId: maxIDPresent) + afterStatusId: minIdInserted, + beforeStatusId: maxIdPresent) .save($0) } @@ -86,18 +86,18 @@ public extension ContentDatabase { switch direction { case .up: - if let maxIDInserted = statuses.map(\.id).max(), maxIDInserted < loadMore.afterStatusId { + if let maxIdInserted = statuses.map(\.id).max(), maxIdInserted < loadMore.afterStatusId { try LoadMoreRecord( timelineId: loadMore.timeline.id, afterStatusId: loadMore.afterStatusId, - beforeStatusId: maxIDInserted) + beforeStatusId: maxIdInserted) .save($0) } case .down: - if let minIDInserted = statuses.map(\.id).min(), minIDInserted > loadMore.beforeStatusId { + if let minIdInserted = statuses.map(\.id).min(), minIdInserted > loadMore.beforeStatusId { try LoadMoreRecord( timelineId: loadMore.timeline.id, - afterStatusId: minIDInserted, + afterStatusId: minIdInserted, beforeStatusId: loadMore.beforeStatusId) .save($0) } @@ -107,25 +107,25 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func insert(context: Context, parentID: String) -> AnyPublisher { + func insert(context: Context, parentId: Status.Id) -> AnyPublisher { databaseWriter.writePublisher { for (index, status) in context.ancestors.enumerated() { try status.save($0) - try StatusAncestorJoin(parentId: parentID, statusId: status.id, index: index).save($0) + try StatusAncestorJoin(parentId: parentId, statusId: status.id, index: index).save($0) } for (index, status) in context.descendants.enumerated() { try status.save($0) - try StatusDescendantJoin(parentId: parentID, statusId: status.id, index: index).save($0) + try StatusDescendantJoin(parentId: parentId, statusId: status.id, index: index).save($0) } try StatusAncestorJoin.filter( - StatusAncestorJoin.Columns.parentId == parentID + StatusAncestorJoin.Columns.parentId == parentId && !context.ancestors.map(\.id).contains(StatusAncestorJoin.Columns.statusId)) .deleteAll($0) try StatusDescendantJoin.filter( - StatusDescendantJoin.Columns.parentId == parentID + StatusDescendantJoin.Columns.parentId == parentId && !context.descendants.map(\.id).contains(StatusDescendantJoin.Columns.statusId)) .deleteAll($0) } @@ -133,15 +133,15 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func insert(pinnedStatuses: [Status], accountID: String) -> AnyPublisher { + func insert(pinnedStatuses: [Status], accountId: Account.Id) -> AnyPublisher { databaseWriter.writePublisher { for (index, status) in pinnedStatuses.enumerated() { try status.save($0) - try AccountPinnedStatusJoin(accountId: accountID, statusId: status.id, index: index).save($0) + try AccountPinnedStatusJoin(accountId: accountId, statusId: status.id, index: index).save($0) } try AccountPinnedStatusJoin.filter( - AccountPinnedStatusJoin.Columns.accountId == accountID + AccountPinnedStatusJoin.Columns.accountId == accountId && !pinnedStatuses.map(\.id).contains(AccountPinnedStatusJoin.Columns.statusId)) .deleteAll($0) } @@ -185,7 +185,7 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func deleteList(id: String) -> AnyPublisher { + func deleteList(id: List.Id) -> AnyPublisher { databaseWriter.writePublisher(updates: TimelineRecord.filter(TimelineRecord.Columns.listId == id).deleteAll) .ignoreOutput() .eraseToAnyPublisher() @@ -209,7 +209,7 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func deleteFilter(id: String) -> AnyPublisher { + func deleteFilter(id: Filter.Id) -> AnyPublisher { databaseWriter.writePublisher(updates: Filter.filter(Filter.Columns.id == id).deleteAll) .ignoreOutput() .eraseToAnyPublisher() @@ -225,9 +225,9 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func contextObservation(parentID: String) -> AnyPublisher<[[CollectionItem]], Error> { + func contextObservation(id: Status.Id) -> AnyPublisher<[[CollectionItem]], Error> { ValueObservation.tracking( - ContextItemsInfo.request(StatusRecord.filter(StatusRecord.Columns.id == parentID)).fetchOne) + ContextItemsInfo.request(StatusRecord.filter(StatusRecord.Columns.id == id)).fetchOne) .removeDuplicates() .publisher(in: databaseWriter) .combineLatest(activeFiltersPublisher) @@ -252,7 +252,7 @@ public extension ContentDatabase { .eraseToAnyPublisher() } - func accountObservation(id: String) -> AnyPublisher { + func accountObservation(id: Account.Id) -> AnyPublisher { ValueObservation.tracking(AccountInfo.request(AccountRecord.filter(AccountRecord.Columns.id == id)).fetchOne) .removeDuplicates() .publisher(in: databaseWriter) @@ -271,8 +271,8 @@ public extension ContentDatabase { } private extension ContentDatabase { - static func fileURL(identityID: UUID) throws -> URL { - try FileManager.default.databaseDirectoryURL(name: identityID.uuidString) + static func fileURL(id: Identity.Id) throws -> URL { + try FileManager.default.databaseDirectoryURL(name: id.uuidString) } static func clean(_ databaseWriter: DatabaseWriter) throws { diff --git a/DB/Sources/DB/Content/LoadMoreRecord.swift b/DB/Sources/DB/Content/LoadMoreRecord.swift index 9005b2a..5cf319b 100644 --- a/DB/Sources/DB/Content/LoadMoreRecord.swift +++ b/DB/Sources/DB/Content/LoadMoreRecord.swift @@ -5,9 +5,9 @@ import GRDB import Mastodon struct LoadMoreRecord: Codable, Hashable { - let timelineId: String - let afterStatusId: String - let beforeStatusId: String + let timelineId: Timeline.Id + let afterStatusId: Status.Id + let beforeStatusId: Status.Id } extension LoadMoreRecord { diff --git a/DB/Sources/DB/Content/StatusAncestorJoin.swift b/DB/Sources/DB/Content/StatusAncestorJoin.swift index c0cc8b2..45340b1 100644 --- a/DB/Sources/DB/Content/StatusAncestorJoin.swift +++ b/DB/Sources/DB/Content/StatusAncestorJoin.swift @@ -2,10 +2,11 @@ import Foundation import GRDB +import Mastodon struct StatusAncestorJoin: Codable, FetchableRecord, PersistableRecord { - let parentId: String - let statusId: String + let parentId: Status.Id + let statusId: Status.Id let index: Int static let status = belongsTo(StatusRecord.self, using: ForeignKey([Columns.statusId])) diff --git a/DB/Sources/DB/Content/StatusDescendantJoin.swift b/DB/Sources/DB/Content/StatusDescendantJoin.swift index 133bafa..31e3904 100644 --- a/DB/Sources/DB/Content/StatusDescendantJoin.swift +++ b/DB/Sources/DB/Content/StatusDescendantJoin.swift @@ -2,10 +2,11 @@ import Foundation import GRDB +import Mastodon struct StatusDescendantJoin: Codable, FetchableRecord, PersistableRecord { - let parentId: String - let statusId: String + let parentId: Status.Id + let statusId: Status.Id let index: Int static let status = belongsTo(StatusRecord.self, using: ForeignKey([Columns.statusId])) diff --git a/DB/Sources/DB/Content/StatusRecord.swift b/DB/Sources/DB/Content/StatusRecord.swift index f6c9d61..afeabdd 100644 --- a/DB/Sources/DB/Content/StatusRecord.swift +++ b/DB/Sources/DB/Content/StatusRecord.swift @@ -5,10 +5,10 @@ import GRDB import Mastodon struct StatusRecord: Codable, Hashable { - let id: String + let id: Status.Id let uri: String let createdAt: Date - let accountId: String + let accountId: Account.Id let content: HTML let visibility: Status.Visibility let sensitive: Bool @@ -22,9 +22,9 @@ struct StatusRecord: Codable, Hashable { let repliesCount: Int let application: Application? let url: URL? - let inReplyToId: String? - let inReplyToAccountId: String? - let reblogId: String? + let inReplyToId: Status.Id? + let inReplyToAccountId: Account.Id? + let reblogId: Status.Id? let poll: Poll? let card: Card? let language: String? diff --git a/DB/Sources/DB/Content/TimelineRecord.swift b/DB/Sources/DB/Content/TimelineRecord.swift index ca6a229..c3c7a62 100644 --- a/DB/Sources/DB/Content/TimelineRecord.swift +++ b/DB/Sources/DB/Content/TimelineRecord.swift @@ -5,11 +5,11 @@ import GRDB import Mastodon struct TimelineRecord: Codable, Hashable { - let id: String - let listId: String? + let id: Timeline.Id + let listId: List.Id? let listTitle: String? let tag: String? - let accountId: String? + let accountId: Account.Id? let profileCollection: ProfileCollection? } diff --git a/DB/Sources/DB/Content/TimelineStatusJoin.swift b/DB/Sources/DB/Content/TimelineStatusJoin.swift index 8c258e9..8e87649 100644 --- a/DB/Sources/DB/Content/TimelineStatusJoin.swift +++ b/DB/Sources/DB/Content/TimelineStatusJoin.swift @@ -2,10 +2,11 @@ import Foundation import GRDB +import Mastodon struct TimelineStatusJoin: Codable, FetchableRecord, PersistableRecord { - let timelineId: String - let statusId: String + let timelineId: Timeline.Id + let statusId: Status.Id static let status = belongsTo(StatusRecord.self) } diff --git a/DB/Sources/DB/Entities/Identity.swift b/DB/Sources/DB/Entities/Identity.swift index 4d9f3ac..e2b8ef3 100644 --- a/DB/Sources/DB/Entities/Identity.swift +++ b/DB/Sources/DB/Entities/Identity.swift @@ -4,7 +4,7 @@ import Foundation import Mastodon public struct Identity: Codable, Hashable, Identifiable { - public let id: UUID + public let id: Id public let url: URL public let authenticated: Bool public let pending: Bool @@ -17,6 +17,8 @@ public struct Identity: Codable, Hashable, Identifiable { } public extension Identity { + typealias Id = UUID + struct Instance: Codable, Hashable { public let uri: String public let streamingAPI: URL @@ -25,8 +27,8 @@ public extension Identity { } struct Account: Codable, Hashable { - public let id: String - public let identityID: UUID + public let id: Mastodon.Account.Id + public let identityId: Identity.Id public let username: String public let displayName: String public let url: URL diff --git a/DB/Sources/DB/Entities/IdentityFixture.swift b/DB/Sources/DB/Entities/IdentityFixture.swift index 855d6a9..11855c2 100644 --- a/DB/Sources/DB/Entities/IdentityFixture.swift +++ b/DB/Sources/DB/Entities/IdentityFixture.swift @@ -4,12 +4,12 @@ import Foundation import Mastodon public struct IdentityFixture { - public let id: UUID + public let id: Identity.Id public let instanceURL: URL public let instance: Instance? public let account: Account? - public init(id: UUID, instanceURL: URL, instance: Instance?, account: Account?) { + public init(id: Identity.Id, instanceURL: URL, instance: Instance?, account: Account?) { self.id = id self.instanceURL = instanceURL self.instance = instance diff --git a/DB/Sources/DB/Entities/LoadMore.swift b/DB/Sources/DB/Entities/LoadMore.swift index e3bb319..969b6b9 100644 --- a/DB/Sources/DB/Entities/LoadMore.swift +++ b/DB/Sources/DB/Entities/LoadMore.swift @@ -5,8 +5,8 @@ import Mastodon public struct LoadMore: Hashable { public let timeline: Timeline - public let afterStatusId: String - public let beforeStatusId: String + public let afterStatusId: Status.Id + public let beforeStatusId: Status.Id } public extension LoadMore { diff --git a/DB/Sources/DB/Entities/Timeline.swift b/DB/Sources/DB/Entities/Timeline.swift index 6957668..477b41f 100644 --- a/DB/Sources/DB/Entities/Timeline.swift +++ b/DB/Sources/DB/Entities/Timeline.swift @@ -9,10 +9,12 @@ public enum Timeline: Hashable { case federated case list(List) case tag(String) - case profile(accountId: String, profileCollection: ProfileCollection) + case profile(accountId: Account.Id, profileCollection: ProfileCollection) } public extension Timeline { + typealias Id = String + static let unauthenticatedDefaults: [Timeline] = [.local, .federated] static let authenticatedDefaults: [Timeline] = [.home, .local, .federated] @@ -29,7 +31,7 @@ public extension Timeline { } extension Timeline: Identifiable { - public var id: String { + public var id: Id { switch self { case .home: return "home" diff --git a/DB/Sources/DB/Identity/IdentityDatabase+Migration.swift b/DB/Sources/DB/Identity/IdentityDatabase+Migration.swift index 7bfce91..da1713d 100644 --- a/DB/Sources/DB/Identity/IdentityDatabase+Migration.swift +++ b/DB/Sources/DB/Identity/IdentityDatabase+Migration.swift @@ -28,7 +28,7 @@ extension IdentityDatabase { try db.create(table: "account", ifNotExists: true) { t in t.column("id", .text).primaryKey(onConflict: .replace) - t.column("identityID", .text).notNull() + t.column("identityId", .text).notNull() .references("identityRecord", onDelete: .cascade) t.column("username", .text).notNull() t.column("displayName", .text).notNull() diff --git a/DB/Sources/DB/Identity/IdentityDatabase.swift b/DB/Sources/DB/Identity/IdentityDatabase.swift index 61a08c9..15cd4b9 100644 --- a/DB/Sources/DB/Identity/IdentityDatabase.swift +++ b/DB/Sources/DB/Identity/IdentityDatabase.swift @@ -22,7 +22,7 @@ public struct IdentityDatabase { var configuration = Configuration() configuration.prepareDatabase { - try $0.usePassphrase(Secrets.databaseKey(identityID: nil, keychain: keychain)) + try $0.usePassphrase(Secrets.databaseKey(identityId: nil, keychain: keychain)) } databaseWriter = try DatabasePool(path: path, configuration: configuration) @@ -33,7 +33,7 @@ public struct IdentityDatabase { } public extension IdentityDatabase { - func createIdentity(id: UUID, url: URL, authenticated: Bool, pending: Bool) -> AnyPublisher { + func createIdentity(id: Identity.Id, url: URL, authenticated: Bool, pending: Bool) -> AnyPublisher { databaseWriter.writePublisher( updates: IdentityRecord( id: id, @@ -50,23 +50,23 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func deleteIdentity(id: UUID) -> AnyPublisher { + func deleteIdentity(id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher(updates: IdentityRecord.filter(IdentityRecord.Columns.id == id).deleteAll) .ignoreOutput() .eraseToAnyPublisher() } - func updateLastUsedAt(identityID: UUID) -> AnyPublisher { + func updateLastUsedAt(id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher { try IdentityRecord - .filter(IdentityRecord.Columns.id == identityID) + .filter(IdentityRecord.Columns.id == id) .updateAll($0, IdentityRecord.Columns.lastUsedAt.set(to: Date())) } .ignoreOutput() .eraseToAnyPublisher() } - func updateInstance(_ instance: Instance, forIdentityID identityID: UUID) -> AnyPublisher { + func updateInstance(_ instance: Instance, id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher { try Identity.Instance( uri: instance.uri, @@ -75,18 +75,18 @@ public extension IdentityDatabase { thumbnail: instance.thumbnail) .save($0) try IdentityRecord - .filter(IdentityRecord.Columns.id == identityID) + .filter(IdentityRecord.Columns.id == id) .updateAll($0, IdentityRecord.Columns.instanceURI.set(to: instance.uri)) } .ignoreOutput() .eraseToAnyPublisher() } - func updateAccount(_ account: Account, forIdentityID identityID: UUID) -> AnyPublisher { + func updateAccount(_ account: Account, id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher( updates: Identity.Account( id: account.id, - identityID: identityID, + identityId: id, username: account.username, displayName: account.displayName, url: account.url, @@ -100,7 +100,7 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func confirmIdentity(id: UUID) -> AnyPublisher { + func confirmIdentity(id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher { try IdentityRecord .filter(IdentityRecord.Columns.id == id) @@ -110,43 +110,41 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func updatePreferences(_ preferences: Mastodon.Preferences, - forIdentityID identityID: UUID) -> AnyPublisher { + func updatePreferences(_ preferences: Mastodon.Preferences, id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher { - guard let storedPreferences = try IdentityRecord.filter(IdentityRecord.Columns.id == identityID) + guard let storedPreferences = try IdentityRecord.filter(IdentityRecord.Columns.id == id) .fetchOne($0)? .preferences else { throw IdentityDatabaseError.identityNotFound } - try Self.writePreferences(storedPreferences.updated(from: preferences), id: identityID)($0) + try Self.writePreferences(storedPreferences.updated(from: preferences), id: id)($0) } .ignoreOutput() .eraseToAnyPublisher() } - func updatePreferences(_ preferences: Identity.Preferences, - forIdentityID identityID: UUID) -> AnyPublisher { - databaseWriter.writePublisher(updates: Self.writePreferences(preferences, id: identityID)) + func updatePreferences(_ preferences: Identity.Preferences, id: Identity.Id) -> AnyPublisher { + databaseWriter.writePublisher(updates: Self.writePreferences(preferences, id: id)) .ignoreOutput() .eraseToAnyPublisher() } func updatePushSubscription(alerts: PushSubscription.Alerts, deviceToken: Data? = nil, - forIdentityID identityID: UUID) -> AnyPublisher { + id: Identity.Id) -> AnyPublisher { databaseWriter.writePublisher { let data = try IdentityRecord.databaseJSONEncoder( for: IdentityRecord.Columns.pushSubscriptionAlerts.name) .encode(alerts) try IdentityRecord - .filter(IdentityRecord.Columns.id == identityID) + .filter(IdentityRecord.Columns.id == id) .updateAll($0, IdentityRecord.Columns.pushSubscriptionAlerts.set(to: data)) if let deviceToken = deviceToken { try IdentityRecord - .filter(IdentityRecord.Columns.id == identityID) + .filter(IdentityRecord.Columns.id == id) .updateAll($0, IdentityRecord.Columns.lastRegisteredDeviceToken.set(to: deviceToken)) } } @@ -154,7 +152,7 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func identityObservation(id: UUID, immediate: Bool) -> AnyPublisher { + func identityObservation(id: Identity.Id, immediate: Bool) -> AnyPublisher { ValueObservation.tracking( IdentityInfo.request(IdentityRecord.filter(IdentityRecord.Columns.id == id)).fetchOne) .removeDuplicates() @@ -176,7 +174,7 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func recentIdentitiesObservation(excluding: UUID) -> AnyPublisher<[Identity], Error> { + func recentIdentitiesObservation(excluding: Identity.Id) -> AnyPublisher<[Identity], Error> { ValueObservation.tracking( IdentityInfo.request(IdentityRecord.order(IdentityRecord.Columns.lastUsedAt.desc)) .filter(IdentityRecord.Columns.id != excluding) @@ -188,7 +186,7 @@ public extension IdentityDatabase { .eraseToAnyPublisher() } - func immediateMostRecentlyUsedIdentityIDObservation() -> AnyPublisher { + func immediateMostRecentlyUsedIdentityIdObservation() -> AnyPublisher { ValueObservation.tracking( IdentityRecord.select(IdentityRecord.Columns.id) .order(IdentityRecord.Columns.lastUsedAt.desc).fetchOne) @@ -210,7 +208,7 @@ public extension IdentityDatabase { private extension IdentityDatabase { static let name = "identity" - static func writePreferences(_ preferences: Identity.Preferences, id: UUID) -> (Database) throws -> Void { + static func writePreferences(_ preferences: Identity.Preferences, id: Identity.Id) -> (Database) throws -> Void { { let data = try IdentityRecord.databaseJSONEncoder( for: IdentityRecord.Columns.preferences.name).encode(preferences) diff --git a/DB/Sources/DB/Identity/IdentityRecord.swift b/DB/Sources/DB/Identity/IdentityRecord.swift index e51dc67..cc88624 100644 --- a/DB/Sources/DB/Identity/IdentityRecord.swift +++ b/DB/Sources/DB/Identity/IdentityRecord.swift @@ -5,7 +5,7 @@ import GRDB import Mastodon struct IdentityRecord: Codable, Hashable, FetchableRecord, PersistableRecord { - let id: UUID + let id: Identity.Id let url: URL let authenticated: Bool let pending: Bool diff --git a/HTTP/Sources/Stubbing/Stubbing.swift b/HTTP/Sources/Stubbing/Stubbing.swift index 94347ec..6afed61 100644 --- a/HTTP/Sources/Stubbing/Stubbing.swift +++ b/HTTP/Sources/Stubbing/Stubbing.swift @@ -2,7 +2,7 @@ import Foundation -public typealias HTTPStub = Result<(URLResponse, Data), Error> +public typealias HTTPStub = Result<(HTTPURLResponse, Data), Error> public protocol Stubbing { func stub(url: URL) -> HTTPStub? diff --git a/Mastodon/Sources/Mastodon/Entities/Account.swift b/Mastodon/Sources/Mastodon/Entities/Account.swift index 3d492e1..efc0467 100644 --- a/Mastodon/Sources/Mastodon/Entities/Account.swift +++ b/Mastodon/Sources/Mastodon/Entities/Account.swift @@ -9,7 +9,7 @@ public final class Account: Codable, Identifiable { public let verifiedAt: Date? } - public let id: String + public let id: Id public let username: String public let acct: String public let displayName: String @@ -30,7 +30,7 @@ public final class Account: Codable, Identifiable { @DecodableDefault.False public private(set) var discoverable: Bool public var moved: Account? - public init(id: String, + public init(id: Id, username: String, acct: String, displayName: String, @@ -73,6 +73,10 @@ public final class Account: Codable, Identifiable { } } +public extension Account { + typealias Id = String +} + extension Account: Hashable { public static func == (lhs: Account, rhs: Account) -> Bool { return lhs.id == rhs.id && diff --git a/Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift b/Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift index 9a79c62..bc73c6e 100644 --- a/Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift +++ b/Mastodon/Sources/Mastodon/Entities/AppAuthorization.swift @@ -3,7 +3,7 @@ import Foundation public struct AppAuthorization: Codable { - public let id: String + public let id: Id public let clientId: String public let clientSecret: String public let name: String @@ -11,3 +11,7 @@ public struct AppAuthorization: Codable { public let website: String? public let vapidKey: String? } + +public extension AppAuthorization { + typealias Id = String +} diff --git a/Mastodon/Sources/Mastodon/Entities/Attachment.swift b/Mastodon/Sources/Mastodon/Entities/Attachment.swift index d6317e5..7e37668 100644 --- a/Mastodon/Sources/Mastodon/Entities/Attachment.swift +++ b/Mastodon/Sources/Mastodon/Entities/Attachment.swift @@ -32,7 +32,7 @@ public struct Attachment: Codable, Hashable { } // swiftlint:enable nesting - public let id: String + public let id: Id public let type: AttachmentType public let url: URL public let remoteUrl: URL? @@ -41,3 +41,7 @@ public struct Attachment: Codable, Hashable { public let meta: Meta? public let description: String? } + +public extension Attachment { + typealias Id = String +} diff --git a/Mastodon/Sources/Mastodon/Entities/Filter.swift b/Mastodon/Sources/Mastodon/Entities/Filter.swift index 34660b1..62d58e4 100644 --- a/Mastodon/Sources/Mastodon/Entities/Filter.swift +++ b/Mastodon/Sources/Mastodon/Entities/Filter.swift @@ -14,7 +14,7 @@ public struct Filter: Codable, Hashable, Identifiable { public static var unknownCase: Self { .unknown } } - public let id: String + public let id: Id public var phrase: String public var context: [Context] public var expiresAt: Date? @@ -23,8 +23,10 @@ public struct Filter: Codable, Hashable, Identifiable { } public extension Filter { - static let newFilterID: String = "com.metabolist.metatext.new-filter-id" - static let new = Self(id: newFilterID, + typealias Id = String + + static let newFilterId: Id = "com.metabolist.metatext.new-filter-id" + static let new = Self(id: newFilterId, phrase: "", context: [], expiresAt: nil, diff --git a/Mastodon/Sources/Mastodon/Entities/List.swift b/Mastodon/Sources/Mastodon/Entities/List.swift index 53f874f..9ddc2ac 100644 --- a/Mastodon/Sources/Mastodon/Entities/List.swift +++ b/Mastodon/Sources/Mastodon/Entities/List.swift @@ -3,11 +3,15 @@ import Foundation public struct List: Codable, Hashable, Identifiable { - public let id: String + public let id: Id public let title: String - public init(id: String, title: String) { + public init(id: Id, title: String) { self.id = id self.title = title } } + +public extension List { + typealias Id = String +} diff --git a/Mastodon/Sources/Mastodon/Entities/Mention.swift b/Mastodon/Sources/Mastodon/Entities/Mention.swift index 572fa69..1a81b50 100644 --- a/Mastodon/Sources/Mastodon/Entities/Mention.swift +++ b/Mastodon/Sources/Mastodon/Entities/Mention.swift @@ -6,5 +6,5 @@ public struct Mention: Codable, Hashable { public let url: URL public let username: String public let acct: String - public let id: String + public let id: Account.Id } diff --git a/Mastodon/Sources/Mastodon/Entities/Poll.swift b/Mastodon/Sources/Mastodon/Entities/Poll.swift index f42e079..08e80a9 100644 --- a/Mastodon/Sources/Mastodon/Entities/Poll.swift +++ b/Mastodon/Sources/Mastodon/Entities/Poll.swift @@ -8,7 +8,7 @@ public struct Poll: Codable, Hashable { public var votesCount: Int } - public let id: String + public let id: Id public let expiresAt: Date public let expired: Bool public let multiple: Bool @@ -19,3 +19,7 @@ public struct Poll: Codable, Hashable { public let options: [Option] public let emojis: [Emoji] } + +public extension Poll { + typealias Id = String +} diff --git a/Mastodon/Sources/Mastodon/Entities/Status.swift b/Mastodon/Sources/Mastodon/Entities/Status.swift index d7fa6b2..303f43a 100644 --- a/Mastodon/Sources/Mastodon/Entities/Status.swift +++ b/Mastodon/Sources/Mastodon/Entities/Status.swift @@ -13,7 +13,7 @@ public final class Status: Codable, Identifiable { public static var unknownCase: Self { .unknown } } - public let id: String + public let id: Status.Id public let uri: String public let createdAt: Date public let account: Account @@ -30,8 +30,8 @@ public final class Status: Codable, Identifiable { @DecodableDefault.Zero public private(set) var repliesCount: Int public let application: Application? public let url: URL? - public let inReplyToId: String? - public let inReplyToAccountId: String? + public let inReplyToId: Status.Id? + public let inReplyToAccountId: Account.Id? public let reblog: Status? public let poll: Poll? public let card: Card? @@ -44,7 +44,7 @@ public final class Status: Codable, Identifiable { public let pinned: Bool? public init( - id: String, + id: Status.Id, uri: String, createdAt: Date, account: Account, @@ -61,8 +61,8 @@ public final class Status: Codable, Identifiable { repliesCount: Int, application: Application?, url: URL?, - inReplyToId: String?, - inReplyToAccountId: String?, + inReplyToId: Status.Id?, + inReplyToAccountId: Account.Id?, reblog: Status?, poll: Poll?, card: Card?, @@ -106,6 +106,8 @@ public final class Status: Codable, Identifiable { } public extension Status { + typealias Id = String + var displayStatus: Status { reblog ?? self } diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccessTokenEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccessTokenEndpoint.swift index c812384..c79a767 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccessTokenEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccessTokenEndpoint.swift @@ -6,7 +6,7 @@ import Mastodon public enum AccessTokenEndpoint { case oauthToken( - clientID: String, + clientId: String, clientSecret: String, grantType: String, scopes: String, @@ -58,9 +58,9 @@ extension AccessTokenEndpoint: Endpoint { public var jsonBody: [String: Any]? { switch self { - case let .oauthToken(clientID, clientSecret, grantType, scopes, code, redirectURI): + case let .oauthToken(clientId, clientSecret, grantType, scopes, code, redirectURI): var params = [ - "client_id": clientID, + "client_id": clientId, "client_secret": clientSecret, "grant_type": grantType, "scope": scopes] diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountEndpoint.swift index 704bc47..621e4e7 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountEndpoint.swift @@ -6,7 +6,7 @@ import Mastodon public enum AccountEndpoint { case verifyCredentials - case accounts(id: String) + case accounts(id: Account.Id) } extension AccountEndpoint: Endpoint { diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountsEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountsEndpoint.swift index a592317..e6ac297 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountsEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/AccountsEndpoint.swift @@ -5,8 +5,8 @@ import HTTP import Mastodon public enum AccountsEndpoint { - case statusRebloggedBy(id: String) - case statusFavouritedBy(id: String) + case rebloggedBy(id: Status.Id) + case favouritedBy(id: Status.Id) } extension AccountsEndpoint: Endpoint { @@ -14,23 +14,23 @@ extension AccountsEndpoint: Endpoint { public var context: [String] { switch self { - case .statusRebloggedBy, .statusFavouritedBy: + case .rebloggedBy, .favouritedBy: return defaultContext + ["statuses"] } } public var pathComponentsInContext: [String] { switch self { - case let .statusRebloggedBy(id): + case let .rebloggedBy(id): return [id, "reblogged_by"] - case let .statusFavouritedBy(id): + case let .favouritedBy(id): return [id, "favourited_by"] } } public var method: HTTPMethod { switch self { - case .statusRebloggedBy, .statusFavouritedBy: + case .rebloggedBy, .favouritedBy: return .get } } diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/ContextEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/ContextEndpoint.swift index 4e12465..0d6c626 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/ContextEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/ContextEndpoint.swift @@ -5,7 +5,7 @@ import HTTP import Mastodon public enum ContextEndpoint { - case context(id: String) + case context(id: Status.Id) } extension ContextEndpoint: Endpoint { diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/DeletionEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/DeletionEndpoint.swift index c23075c..57e360e 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/DeletionEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/DeletionEndpoint.swift @@ -5,9 +5,9 @@ import HTTP import Mastodon public enum DeletionEndpoint { - case oauthRevoke(token: String, clientID: String, clientSecret: String) - case list(id: String) - case filter(id: String) + case oauthRevoke(token: String, clientId: String, clientSecret: String) + case list(id: List.Id) + case filter(id: Filter.Id) } extension DeletionEndpoint: Endpoint { @@ -44,8 +44,8 @@ extension DeletionEndpoint: Endpoint { public var jsonBody: [String: Any]? { switch self { - case let .oauthRevoke(token, clientID, clientSecret): - return ["token": token, "client_id": clientID, "client_secret": clientSecret] + case let .oauthRevoke(token, clientId, clientSecret): + return ["token": token, "client_id": clientId, "client_secret": clientSecret] case .list, .filter: return nil } diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/FilterEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/FilterEndpoint.swift index 7df4e29..e5e594b 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/FilterEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/FilterEndpoint.swift @@ -12,7 +12,7 @@ public enum FilterEndpoint { wholeWord: Bool, expiresIn: Date?) case update( - id: String, + id: Filter.Id, phrase: String, context: [Filter.Context], irreversible: Bool, diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/Paged.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/Paged.swift index e6c1013..a6adb5c 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/Paged.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/Paged.swift @@ -6,16 +6,16 @@ import Mastodon public struct Paged { public let endpoint: T - public let maxID: String? - public let minID: String? - public let sinceID: String? + public let maxId: String? + public let minId: String? + public let sinceId: String? public let limit: Int? - public init(_ endpoint: T, maxID: String? = nil, minID: String? = nil, sinceID: String? = nil, limit: Int? = nil) { + public init(_ endpoint: T, maxId: String? = nil, minId: String? = nil, sinceId: String? = nil, limit: Int? = nil) { self.endpoint = endpoint - self.maxID = maxID - self.minID = minID - self.sinceID = sinceID + self.maxId = maxId + self.minId = minId + self.sinceId = sinceId self.limit = limit } } @@ -34,9 +34,9 @@ extension Paged: Endpoint { public var queryParameters: [String: String]? { var queryParameters = endpoint.queryParameters ?? [String: String]() - queryParameters["max_id"] = maxID - queryParameters["min_id"] = minID - queryParameters["since_id"] = sinceID + queryParameters["max_id"] = maxId + queryParameters["min_id"] = minId + queryParameters["since_id"] = sinceId if let limit = limit { queryParameters["limit"] = String(limit) @@ -50,9 +50,9 @@ extension Paged: Endpoint { public struct PagedResult: Decodable { public struct Info: Decodable { - public let maxID: String? - public let minID: String? - public let sinceID: String? + public let maxId: String? + public let minId: String? + public let sinceId: String? } public let result: T diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusEndpoint.swift index bd1f2e6..2426b4d 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusEndpoint.swift @@ -5,9 +5,9 @@ import HTTP import Mastodon public enum StatusEndpoint { - case status(id: String) - case favourite(id: String) - case unfavourite(id: String) + case status(id: Status.Id) + case favourite(id: Status.Id) + case unfavourite(id: Status.Id) } extension StatusEndpoint: Endpoint { diff --git a/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusesEndpoint.swift b/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusesEndpoint.swift index 136ca9f..225e549 100644 --- a/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusesEndpoint.swift +++ b/MastodonAPI/Sources/MastodonAPI/Endpoints/StatusesEndpoint.swift @@ -8,8 +8,8 @@ public enum StatusesEndpoint { case timelinesPublic(local: Bool) case timelinesTag(String) case timelinesHome - case timelinesList(id: String) - case accountsStatuses(id: String, excludeReplies: Bool, onlyMedia: Bool, pinned: Bool) + case timelinesList(id: List.Id) + case accountsStatuses(id: Account.Id, excludeReplies: Bool, onlyMedia: Bool, pinned: Bool) } extension StatusesEndpoint: Endpoint { diff --git a/MastodonAPI/Sources/MastodonAPI/MastodonAPIClient.swift b/MastodonAPI/Sources/MastodonAPI/MastodonAPIClient.swift index 35cb0c8..cf0745d 100644 --- a/MastodonAPI/Sources/MastodonAPI/MastodonAPIClient.swift +++ b/MastodonAPI/Sources/MastodonAPI/MastodonAPIClient.swift @@ -39,17 +39,17 @@ extension MastodonAPIClient { public func pagedRequest( _ endpoint: E, - maxID: String? = nil, - minID: String? = nil, - sinceID: String? = nil, + maxId: String? = nil, + minId: String? = nil, + sinceId: String? = nil, limit: Int? = nil) -> AnyPublisher, Error> { - let pagedTarget = target(endpoint: Paged(endpoint, maxID: maxID, minID: minID, sinceID: sinceID, limit: limit)) + let pagedTarget = target(endpoint: Paged(endpoint, maxId: maxId, minId: minId, sinceId: sinceId, limit: limit)) let dataTask = dataTaskPublisher(pagedTarget).share() let decoded = dataTask.map(\.data).decode(type: E.ResultType.self, decoder: decoder) let info = dataTask.map { _, response -> PagedResult.Info in - var maxID: String? - var minID: String? - var sinceID: String? + var maxId: String? + var minId: String? + var sinceId: String? if let links = response.value(forHTTPHeaderField: "Link") { let queryItems = Self.linkDataDetector.matches( @@ -62,12 +62,12 @@ extension MastodonAPIClient { } .reduce([], +) - maxID = queryItems.first { $0.name == "max_id" }?.value - minID = queryItems.first { $0.name == "min_id" }?.value - sinceID = queryItems.first { $0.name == "since_id" }?.value + maxId = queryItems.first { $0.name == "max_id" }?.value + minId = queryItems.first { $0.name == "min_id" }?.value + sinceId = queryItems.first { $0.name == "since_id" }?.value } - return PagedResult.Info(maxID: maxID, minID: minID, sinceID: sinceID) + return PagedResult.Info(maxId: maxId, minId: minId, sinceId: sinceId) } return decoded.zip(info).map(PagedResult.init(result:info:)).eraseToAnyPublisher() diff --git a/Notification Service Extension/NotificationService.swift b/Notification Service Extension/NotificationService.swift index 371a005..47c9342 100644 --- a/Notification Service Extension/NotificationService.swift +++ b/Notification Service Extension/NotificationService.swift @@ -62,7 +62,7 @@ enum NotificationServiceError: Error { } private extension NotificationService { - static let identityIDUserInfoKey = "i" + static let identityIdUserInfoKey = "i" static let encryptedMessageUserInfoKey = "m" static let saltUserInfoKey = "s" static let serverPublicKeyUserInfoKey = "k" @@ -82,8 +82,8 @@ private extension NotificationService { static func extractAndDecrypt(userInfo: [AnyHashable: Any]) throws -> Data { guard - let identityIDString = userInfo[identityIDUserInfoKey] as? String, - let identityID = UUID(uuidString: identityIDString), + let identityIdString = userInfo[identityIdUserInfoKey] as? String, + let identityId = UUID(uuidString: identityIdString), let encryptedMessageBase64 = (userInfo[encryptedMessageUserInfoKey] as? String)?.URLSafeBase64ToBase64(), let encryptedMessage = Data(base64Encoded: encryptedMessageBase64), let saltBase64 = (userInfo[saltUserInfoKey] as? String)?.URLSafeBase64ToBase64(), @@ -92,7 +92,7 @@ private extension NotificationService { let serverPublicKeyData = Data(base64Encoded: serverPublicKeyBase64) else { throw NotificationServiceError.userInfoDataAbsent } - let secretsService = Secrets(identityID: identityID, keychain: LiveKeychain.self) + let secretsService = Secrets(identityId: identityId, keychain: LiveKeychain.self) guard let auth = try secretsService.getPushAuth(), diff --git a/Secrets/Sources/Secrets/Secrets.swift b/Secrets/Sources/Secrets/Secrets.swift index dae3ac0..db9352e 100644 --- a/Secrets/Sources/Secrets/Secrets.swift +++ b/Secrets/Sources/Secrets/Secrets.swift @@ -14,11 +14,11 @@ enum SecretsStorableError: Error { } public struct Secrets { - public let identityID: UUID + public let identityId: UUID private let keychain: Keychain.Type - public init(identityID: UUID, keychain: Keychain.Type) { - self.identityID = identityID + public init(identityId: UUID, keychain: Keychain.Type) { + self.identityId = identityId self.keychain = keychain } } @@ -26,7 +26,7 @@ public struct Secrets { public extension Secrets { enum Item: String, CaseIterable { case instanceURL - case clientID + case clientId case clientSecret case accessToken case pushKey @@ -56,12 +56,12 @@ extension Secrets.Item { public extension Secrets { // https://www.zetetic.net/sqlcipher/sqlcipher-api/#key - static func databaseKey(identityID: UUID?, keychain: Keychain.Type) throws -> String { + static func databaseKey(identityId: UUID?, keychain: Keychain.Type) throws -> String { let passphraseData: Data let scopedSecrets: Secrets? - if let identityID = identityID { - scopedSecrets = Secrets(identityID: identityID, keychain: keychain) + if let identityId = identityId { + scopedSecrets = Secrets(identityId: identityId, keychain: keychain) } else { scopedSecrets = nil } @@ -114,12 +114,12 @@ public extension Secrets { try set(instanceURL, forItem: .instanceURL) } - func getClientID() throws -> String { - try item(.clientID) + func getClientId() throws -> String { + try item(.clientId) } - func setClientID(_ clientID: String) throws { - try set(clientID, forItem: .clientID) + func setClientId(_ clientId: String) throws { + try set(clientId, forItem: .clientId) } func getClientSecret() throws -> String { @@ -200,7 +200,7 @@ private extension Secrets { } func scopedKey(item: Item) -> String { - identityID.uuidString + "." + item.rawValue + identityId.uuidString + "." + item.rawValue } func set(_ data: SecretsStorable, forItem item: Item) throws { diff --git a/ServiceLayer/Sources/ServiceLayer/Services/AccountListService.swift b/ServiceLayer/Sources/ServiceLayer/Services/AccountListService.swift index d91c97b..2d020f8 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/AccountListService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/AccountListService.swift @@ -8,14 +8,14 @@ import MastodonAPI public struct AccountListService { public let sections: AnyPublisher<[[CollectionItem]], Error> - public let nextPageMaxIDs: AnyPublisher + public let nextPageMaxId: AnyPublisher public let navigationService: NavigationService private let list: AccountList private let endpoint: AccountsEndpoint private let mastodonAPIClient: MastodonAPIClient private let contentDatabase: ContentDatabase - private let nextPageMaxIDsSubject = PassthroughSubject() + private let nextPageMaxIdSubject = PassthroughSubject() init(endpoint: AccountsEndpoint, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { list = AccountList() @@ -25,18 +25,18 @@ public struct AccountListService { sections = contentDatabase.accountListObservation(list) .map { [$0.map(CollectionItem.account)] } .eraseToAnyPublisher() - nextPageMaxIDs = nextPageMaxIDsSubject.eraseToAnyPublisher() + nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher() navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } } extension AccountListService: CollectionService { - public func request(maxID: String?, minID: String?) -> AnyPublisher { - mastodonAPIClient.pagedRequest(endpoint, maxID: maxID, minID: minID) + public func request(maxId: String?, minId: String?) -> AnyPublisher { + mastodonAPIClient.pagedRequest(endpoint, maxId: maxId, minId: minId) .handleEvents(receiveOutput: { - guard let maxID = $0.info.maxID else { return } + guard let maxId = $0.info.maxId else { return } - nextPageMaxIDsSubject.send(maxID) + nextPageMaxIdSubject.send(maxId) }) .flatMap { contentDatabase.append(accounts: $0.result, toList: list) } .eraseToAnyPublisher() diff --git a/ServiceLayer/Sources/ServiceLayer/Services/AllIdentitiesService.swift b/ServiceLayer/Sources/ServiceLayer/Services/AllIdentitiesService.swift index 4d69e08..59c82b8 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/AllIdentitiesService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/AllIdentitiesService.swift @@ -8,11 +8,11 @@ import MastodonAPI import Secrets public struct AllIdentitiesService { - public let identitiesCreated: AnyPublisher + public let identitiesCreated: AnyPublisher private let environment: AppEnvironment private let database: IdentityDatabase - private let identitiesCreatedSubject = PassthroughSubject() + private let identitiesCreatedSubject = PassthroughSubject() public init(environment: AppEnvironment) throws { self.environment = environment @@ -30,17 +30,17 @@ public extension AllIdentitiesService { case browsing } - func identityService(id: UUID) throws -> IdentityService { + func identityService(id: Identity.Id) throws -> IdentityService { try IdentityService(id: id, database: database, environment: environment) } - func immediateMostRecentlyUsedIdentityIDObservation() -> AnyPublisher { - database.immediateMostRecentlyUsedIdentityIDObservation() + func immediateMostRecentlyUsedIdentityIdObservation() -> AnyPublisher { + database.immediateMostRecentlyUsedIdentityIdObservation() } func createIdentity(url: URL, kind: IdentityCreation) -> AnyPublisher { let id = environment.uuid() - let secrets = Secrets(identityID: id, keychain: environment.keychain) + let secrets = Secrets(identityId: id, keychain: environment.keychain) do { try secrets.setInstanceURL(url) @@ -76,7 +76,7 @@ public extension AllIdentitiesService { return authenticationPublisher .tryMap { - try secrets.setClientID($0.clientId) + try secrets.setClientId($0.clientId) try secrets.setClientSecret($0.clientSecret) try secrets.setAccessToken($1.accessToken) } @@ -84,13 +84,13 @@ public extension AllIdentitiesService { .eraseToAnyPublisher() } - func deleteIdentity(id: UUID) -> AnyPublisher { + func deleteIdentity(id: Identity.Id) -> AnyPublisher { database.deleteIdentity(id: id) .collect() .tryMap { _ -> AnyPublisher in - try ContentDatabase.delete(forIdentityID: id) + try ContentDatabase.delete(id: id) - let secrets = Secrets(identityID: id, keychain: environment.keychain) + let secrets = Secrets(identityId: id, keychain: environment.keychain) defer { secrets.deleteAllItems() } @@ -100,7 +100,7 @@ public extension AllIdentitiesService { instanceURL: try secrets.getInstanceURL()) .request(DeletionEndpoint.oauthRevoke( token: try secrets.getAccessToken(), - clientID: try secrets.getClientID(), + clientId: try secrets.getClientId(), clientSecret: try secrets.getClientSecret())) .ignoreOutput() .eraseToAnyPublisher() diff --git a/ServiceLayer/Sources/ServiceLayer/Services/AuthenticationService.swift b/ServiceLayer/Sources/ServiceLayer/Services/AuthenticationService.swift index 7662765..9c0c82f 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/AuthenticationService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/AuthenticationService.swift @@ -29,7 +29,8 @@ extension AuthenticationService { .eraseToAnyPublisher() } - func register(_ registration: Registration, id: UUID) -> AnyPublisher<(AppAuthorization, AccessToken), Error> { + func register(_ registration: Registration, + id: Identity.Id) -> AnyPublisher<(AppAuthorization, AccessToken), Error> { let redirectURI = OAuth.registrationCallbackURL.appendingPathComponent(id.uuidString) let authorization = appAuthorization(redirectURI: redirectURI) .share() @@ -38,7 +39,7 @@ extension AuthenticationService { authorization.flatMap { appAuthorization -> AnyPublisher in mastodonAPIClient.request( AccessTokenEndpoint.oauthToken( - clientID: appAuthorization.clientId, + clientId: appAuthorization.clientId, clientSecret: appAuthorization.clientSecret, grantType: OAuth.registrationGrantType, scopes: OAuth.scopes, @@ -134,7 +135,7 @@ private extension AuthenticationService { .flatMap { mastodonAPIClient.request( AccessTokenEndpoint.oauthToken( - clientID: appAuthorization.clientId, + clientId: appAuthorization.clientId, clientSecret: appAuthorization.clientSecret, grantType: OAuth.authorizationCodeGrantType, scopes: OAuth.scopes, diff --git a/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift b/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift index 59459e8..e815f54 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift @@ -4,17 +4,17 @@ import Combine public protocol CollectionService { var sections: AnyPublisher<[[CollectionItem]], Error> { get } - var nextPageMaxIDs: AnyPublisher { get } + var nextPageMaxId: AnyPublisher { get } var title: AnyPublisher { get } var navigationService: NavigationService { get } - var contextParentID: String? { get } - func request(maxID: String?, minID: String?) -> AnyPublisher + var contextParentId: String? { get } + func request(maxId: String?, minId: String?) -> AnyPublisher } extension CollectionService { - public var nextPageMaxIDs: AnyPublisher { Empty().eraseToAnyPublisher() } + public var nextPageMaxId: AnyPublisher { Empty().eraseToAnyPublisher() } public var title: AnyPublisher { Empty().eraseToAnyPublisher() } - public var contextParentID: String? { nil } + public var contextParentId: String? { nil } } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/ContextService.swift b/ServiceLayer/Sources/ServiceLayer/Services/ContextService.swift index b2cfa8d..46a4527 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/ContextService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/ContextService.swift @@ -9,27 +9,27 @@ import MastodonAPI public struct ContextService { public let sections: AnyPublisher<[[CollectionItem]], Error> public let navigationService: NavigationService - public var contextParentID: String? { parentID } + public var contextParentId: String? { id } - private let parentID: String + private let id: Status.Id private let mastodonAPIClient: MastodonAPIClient private let contentDatabase: ContentDatabase - init(parentID: String, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { - self.parentID = parentID + init(id: Status.Id, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { + self.id = id self.mastodonAPIClient = mastodonAPIClient self.contentDatabase = contentDatabase - sections = contentDatabase.contextObservation(parentID: parentID) + sections = contentDatabase.contextObservation(id: id) navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } } extension ContextService: CollectionService { - public func request(maxID: String?, minID: String?) -> AnyPublisher { - mastodonAPIClient.request(StatusEndpoint.status(id: parentID)) + public func request(maxId: String?, minId: String?) -> AnyPublisher { + mastodonAPIClient.request(StatusEndpoint.status(id: id)) .flatMap(contentDatabase.insert(status:)) - .merge(with: mastodonAPIClient.request(ContextEndpoint.context(id: parentID)) - .flatMap { contentDatabase.insert(context: $0, parentID: parentID) }) + .merge(with: mastodonAPIClient.request(ContextEndpoint.context(id: id)) + .flatMap { contentDatabase.insert(context: $0, parentId: id) }) .eraseToAnyPublisher() } } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/IdentityService.swift b/ServiceLayer/Sources/ServiceLayer/Services/IdentityService.swift index 87f342e..5e6514f 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/IdentityService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/IdentityService.swift @@ -9,25 +9,25 @@ import MastodonAPI import Secrets public struct IdentityService { - private let identityID: UUID + private let id: Identity.Id private let identityDatabase: IdentityDatabase private let contentDatabase: ContentDatabase private let environment: AppEnvironment private let mastodonAPIClient: MastodonAPIClient private let secrets: Secrets - init(id: UUID, database: IdentityDatabase, environment: AppEnvironment) throws { - identityID = id + init(id: Identity.Id, database: IdentityDatabase, environment: AppEnvironment) throws { + self.id = id identityDatabase = database self.environment = environment secrets = Secrets( - identityID: id, + identityId: id, keychain: environment.keychain) mastodonAPIClient = MastodonAPIClient(session: environment.session, instanceURL: try secrets.getInstanceURL()) mastodonAPIClient.accessToken = try? secrets.getAccessToken() - contentDatabase = try ContentDatabase(identityID: id, + contentDatabase = try ContentDatabase(id: id, inMemory: environment.inMemoryContent, keychain: environment.keychain) } @@ -35,29 +35,29 @@ public struct IdentityService { public extension IdentityService { func updateLastUse() -> AnyPublisher { - identityDatabase.updateLastUsedAt(identityID: identityID) + identityDatabase.updateLastUsedAt(id: id) } func verifyCredentials() -> AnyPublisher { mastodonAPIClient.request(AccountEndpoint.verifyCredentials) - .flatMap { identityDatabase.updateAccount($0, forIdentityID: identityID) } + .flatMap { identityDatabase.updateAccount($0, id: id) } .eraseToAnyPublisher() } func refreshServerPreferences() -> AnyPublisher { mastodonAPIClient.request(PreferencesEndpoint.preferences) - .flatMap { identityDatabase.updatePreferences($0, forIdentityID: identityID) } + .flatMap { identityDatabase.updatePreferences($0, id: id) } .eraseToAnyPublisher() } func refreshInstance() -> AnyPublisher { mastodonAPIClient.request(InstanceEndpoint.instance) - .flatMap { identityDatabase.updateInstance($0, forIdentityID: identityID) } + .flatMap { identityDatabase.updateInstance($0, id: id) } .eraseToAnyPublisher() } func confirmIdentity() -> AnyPublisher { - identityDatabase.confirmIdentity(id: identityID) + identityDatabase.confirmIdentity(id: id) } func identitiesObservation() -> AnyPublisher<[Identity], Error> { @@ -65,7 +65,7 @@ public extension IdentityService { } func recentIdentitiesObservation() -> AnyPublisher<[Identity], Error> { - identityDatabase.recentIdentitiesObservation(excluding: identityID) + identityDatabase.recentIdentitiesObservation(excluding: id) } func refreshLists() -> AnyPublisher { @@ -80,7 +80,7 @@ public extension IdentityService { .eraseToAnyPublisher() } - func deleteList(id: String) -> AnyPublisher { + func deleteList(id: List.Id) -> AnyPublisher { mastodonAPIClient.request(DeletionEndpoint.list(id: id)) .map { _ in id } .flatMap(contentDatabase.deleteList(id:)) @@ -88,7 +88,7 @@ public extension IdentityService { } func observation(immediate: Bool) -> AnyPublisher { - identityDatabase.identityObservation(id: identityID, immediate: immediate) + identityDatabase.identityObservation(id: id, immediate: immediate) } func listsObservation() -> AnyPublisher<[Timeline], Error> { @@ -122,7 +122,7 @@ public extension IdentityService { .eraseToAnyPublisher() } - func deleteFilter(id: String) -> AnyPublisher { + func deleteFilter(id: Filter.Id) -> AnyPublisher { mastodonAPIClient.request(DeletionEndpoint.filter(id: id)) .flatMap { _ in contentDatabase.deleteFilter(id: id) } .eraseToAnyPublisher() @@ -137,7 +137,7 @@ public extension IdentityService { } func updatePreferences(_ preferences: Identity.Preferences) -> AnyPublisher { - identityDatabase.updatePreferences(preferences, forIdentityID: identityID) + identityDatabase.updatePreferences(preferences, id: id) .collect() .filter { _ in preferences.useServerPostingReadingPreferences } .flatMap { _ in refreshServerPreferences() } @@ -157,7 +157,7 @@ public extension IdentityService { let endpoint = Self.pushSubscriptionEndpointURL .appendingPathComponent(deviceToken.base16EncodedString()) - .appendingPathComponent(identityID.uuidString) + .appendingPathComponent(id.uuidString) return mastodonAPIClient.request( PushSubscriptionEndpoint.create( @@ -165,15 +165,15 @@ public extension IdentityService { publicKey: publicKey, auth: auth, alerts: alerts)) - .map { ($0.alerts, deviceToken, identityID) } - .flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:forIdentityID:)) + .map { ($0.alerts, deviceToken, id) } + .flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:id:)) .eraseToAnyPublisher() } func updatePushSubscription(alerts: PushSubscription.Alerts) -> AnyPublisher { mastodonAPIClient.request(PushSubscriptionEndpoint.update(alerts: alerts)) - .map { ($0.alerts, nil, identityID) } - .flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:forIdentityID:)) + .map { ($0.alerts, nil, id) } + .flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:id:)) .eraseToAnyPublisher() } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/LoadMoreService.swift b/ServiceLayer/Sources/ServiceLayer/Services/LoadMoreService.swift index b316dc3..fe72147 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/LoadMoreService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/LoadMoreService.swift @@ -20,8 +20,8 @@ public extension LoadMoreService { func request(direction: LoadMore.Direction) -> AnyPublisher { mastodonAPIClient.pagedRequest( loadMore.timeline.endpoint, - maxID: direction == .down ? loadMore.afterStatusId : nil, - minID: direction == .up ? loadMore.beforeStatusId : nil) + maxId: direction == .down ? loadMore.afterStatusId : nil, + minId: direction == .up ? loadMore.beforeStatusId : nil) .flatMap { contentDatabase.insert( statuses: $0.result, diff --git a/ServiceLayer/Sources/ServiceLayer/Services/NavigationService.swift b/ServiceLayer/Sources/ServiceLayer/Services/NavigationService.swift index e80ed7d..a53ffe9 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/NavigationService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/NavigationService.swift @@ -36,10 +36,10 @@ public extension NavigationService { mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase))) .eraseToAnyPublisher() - } else if let accountID = accountID(url: url) { - return Just(.profile(profileService(id: accountID))).eraseToAnyPublisher() - } else if mastodonAPIClient.instanceURL.host == url.host, let statusID = url.statusID { - return Just(.collection(contextService(id: statusID))).eraseToAnyPublisher() + } else if let accountId = accountId(url: url) { + return Just(.profile(profileService(id: accountId))).eraseToAnyPublisher() + } else if mastodonAPIClient.instanceURL.host == url.host, let statusId = url.statusId { + return Just(.collection(contextService(id: statusId))).eraseToAnyPublisher() } if url.shouldWebfinger { @@ -49,11 +49,11 @@ public extension NavigationService { } } - func contextService(id: String) -> ContextService { - ContextService(parentID: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) + func contextService(id: Status.Id) -> ContextService { + ContextService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } - func profileService(id: String) -> ProfileService { + func profileService(id: Account.Id) -> ProfileService { ProfileService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } @@ -86,12 +86,12 @@ private extension NavigationService { return nil } - func accountID(url: URL) -> String? { - if let mentionID = status?.mentions.first(where: { $0.url.path.lowercased() == url.path.lowercased() })?.id { - return mentionID + func accountId(url: URL) -> String? { + if let mentionId = status?.mentions.first(where: { $0.url.path.lowercased() == url.path.lowercased() })?.id { + return mentionId } else if mastodonAPIClient.instanceURL.host == url.host { - return url.accountID + return url.accountId } return nil @@ -131,21 +131,21 @@ private extension URL { || (pathComponents.count == 3 && pathComponents[0...1] == ["/", "users"]) } - var accountID: String? { - if let accountID = pathComponents.last, pathComponents == ["/", "web", "accounts", accountID] { - return accountID + var accountId: Account.Id? { + if let accountId = pathComponents.last, pathComponents == ["/", "web", "accounts", accountId] { + return accountId } return nil } - var statusID: String? { - guard let statusID = pathComponents.last else { return nil } + var statusId: Status.Id? { + guard let statusId = pathComponents.last else { return nil } if pathComponents.count == 3, pathComponents[1].starts(with: "@") { - return statusID - } else if pathComponents == ["/", "web", "statuses", statusID] { - return statusID + return statusId + } else if pathComponents == ["/", "web", "statuses", statusId] { + return statusId } return nil @@ -160,6 +160,6 @@ private extension URL { } var shouldWebfinger: Bool { - isAccountURL || accountID != nil || statusID != nil || tag != nil + isAccountURL || accountId != nil || statusId != nil || tag != nil } } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/ProfileService.swift b/ServiceLayer/Sources/ServiceLayer/Services/ProfileService.swift index 27f89a4..0b290df 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/ProfileService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/ProfileService.swift @@ -9,7 +9,7 @@ import MastodonAPI public struct ProfileService { public let accountServicePublisher: AnyPublisher - private let accountID: String + private let id: Account.Id private let mastodonAPIClient: MastodonAPIClient private let contentDatabase: ContentDatabase @@ -21,20 +21,20 @@ public struct ProfileService { contentDatabase: contentDatabase) } - init(id: String, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { + init(id: Account.Id, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { self.init(id: id, account: nil, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } private init( - id: String, + id: Account.Id, account: Account?, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { - accountID = id + self.id = id self.mastodonAPIClient = mastodonAPIClient self.contentDatabase = contentDatabase - var accountPublisher = contentDatabase.accountObservation(id: accountID) + var accountPublisher = contentDatabase.accountObservation(id: id) if let account = account { accountPublisher = accountPublisher @@ -52,7 +52,7 @@ public struct ProfileService { public extension ProfileService { func timelineService(profileCollection: ProfileCollection) -> TimelineService { TimelineService( - timeline: .profile(accountId: accountID, profileCollection: profileCollection), + timeline: .profile(accountId: id, profileCollection: profileCollection), mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } @@ -60,11 +60,11 @@ public extension ProfileService { func fetchPinnedStatuses() -> AnyPublisher { mastodonAPIClient.request( StatusesEndpoint.accountsStatuses( - id: accountID, + id: id, excludeReplies: true, onlyMedia: false, pinned: true)) - .flatMap { contentDatabase.insert(pinnedStatuses: $0, accountID: accountID) } + .flatMap { contentDatabase.insert(pinnedStatuses: $0, accountId: id) } .eraseToAnyPublisher() } } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/StatusService.swift b/ServiceLayer/Sources/ServiceLayer/Services/StatusService.swift index 26a5b32..d4c460c 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/StatusService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/StatusService.swift @@ -34,14 +34,14 @@ public extension StatusService { func rebloggedByService() -> AccountListService { AccountListService( - endpoint: .statusRebloggedBy(id: status.id), + endpoint: .rebloggedBy(id: status.id), mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } func favoritedByService() -> AccountListService { AccountListService( - endpoint: .statusFavouritedBy(id: status.id), + endpoint: .favouritedBy(id: status.id), mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift b/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift index ae4b8a6..092485f 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift @@ -9,14 +9,13 @@ import MastodonAPI public struct TimelineService { public let sections: AnyPublisher<[[CollectionItem]], Error> public let navigationService: NavigationService - public let nextPageMaxIDs: AnyPublisher + public let nextPageMaxId: AnyPublisher public let title: AnyPublisher - public let contextParentID: String? = nil private let timeline: Timeline private let mastodonAPIClient: MastodonAPIClient private let contentDatabase: ContentDatabase - private let nextPageMaxIDsSubject = PassthroughSubject() + private let nextPageMaxIdSubject = PassthroughSubject() init(timeline: Timeline, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { self.timeline = timeline @@ -24,7 +23,7 @@ public struct TimelineService { self.contentDatabase = contentDatabase sections = contentDatabase.observation(timeline: timeline) navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) - nextPageMaxIDs = nextPageMaxIDsSubject.eraseToAnyPublisher() + nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher() if case let .tag(tag) = timeline { title = Just("#".appending(tag)).eraseToAnyPublisher() @@ -35,12 +34,12 @@ public struct TimelineService { } extension TimelineService: CollectionService { - public func request(maxID: String?, minID: String?) -> AnyPublisher { - mastodonAPIClient.pagedRequest(timeline.endpoint, maxID: maxID, minID: minID) + public func request(maxId: String?, minId: String?) -> AnyPublisher { + mastodonAPIClient.pagedRequest(timeline.endpoint, maxId: maxId, minId: minId) .handleEvents(receiveOutput: { - guard let maxID = $0.info.maxID else { return } + guard let maxId = $0.info.maxId else { return } - nextPageMaxIDsSubject.send(maxID) + nextPageMaxIdSubject.send(maxId) }) .flatMap { contentDatabase.insert(statuses: $0.result, timeline: timeline) } .eraseToAnyPublisher() diff --git a/ServiceLayer/Tests/ServiceLayerTests/InstanceURLServiceTests.swift b/ServiceLayer/Tests/ServiceLayerTests/InstanceURLServiceTests.swift index 89c5680..776805d 100644 --- a/ServiceLayer/Tests/ServiceLayerTests/InstanceURLServiceTests.swift +++ b/ServiceLayer/Tests/ServiceLayerTests/InstanceURLServiceTests.swift @@ -42,7 +42,7 @@ class InstanceURLServiceTests: XCTestCase { updatedFilter.insert("instance.filtered") let updatedFilterData = try JSONEncoder().encode(updatedFilter) - let stub: HTTPStub = .success((URLResponse(), updatedFilterData)) + let stub: HTTPStub = .success((HTTPURLResponse(), updatedFilterData)) StubbingURLProtocol.setStub(stub, forURL: URL(string: "https://filter.metabolist.com/filter")!) diff --git a/View Controllers/TableViewController.swift b/View Controllers/TableViewController.swift index 1a9050d..879a867 100644 --- a/View Controllers/TableViewController.swift +++ b/View Controllers/TableViewController.swift @@ -74,7 +74,7 @@ class TableViewController: UITableViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - viewModel.request(maxID: nil, minID: nil) + viewModel.request(maxId: nil, minId: nil) } override func scrollViewDidScroll(_ scrollView: UIScrollView) { @@ -130,13 +130,13 @@ class TableViewController: UITableViewController { extension TableViewController: UITableViewDataSourcePrefetching { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { guard - let maxID = viewModel.nextPageMaxID, + let maxId = viewModel.nextPageMaxId, let indexPath = indexPaths.last, indexPath.section == dataSource.numberOfSections(in: tableView) - 1, indexPath.row == dataSource.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 else { return } - viewModel.request(maxID: maxID, minID: nil) + viewModel.request(maxId: maxId, minId: nil) } } diff --git a/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift b/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift index a9e9d29..67c34a2 100644 --- a/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift +++ b/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift @@ -14,9 +14,9 @@ import ViewModels // swiftlint:disable force_try let db: IdentityDatabase = { - let id = UUID() + let id = Identity.Id() let db = try! IdentityDatabase(inMemory: true, keychain: MockKeychain.self) - let secrets = Secrets(identityID: id, keychain: MockKeychain.self) + let secrets = Secrets(identityId: id, keychain: MockKeychain.self) try! secrets.setInstanceURL(.previewInstanceURL) try! secrets.setAccessToken(UUID().uuidString) @@ -25,11 +25,11 @@ let db: IdentityDatabase = { .receive(on: ImmediateScheduler.shared) .sink { _ in } receiveValue: { _ in } - _ = db.updateInstance(.preview, forIdentityID: id) + _ = db.updateInstance(.preview, id: id) .receive(on: ImmediateScheduler.shared) .sink { _ in } receiveValue: { _ in } - _ = db.updateAccount(.preview, forIdentityID: id) + _ = db.updateAccount(.preview, id: id) .receive(on: ImmediateScheduler.shared) .sink { _ in } receiveValue: { _ in } diff --git a/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift b/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift index 1ef1129..478ea7d 100644 --- a/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift +++ b/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift @@ -7,7 +7,7 @@ import ServiceLayer final public class CollectionItemsViewModel: ObservableObject { @Published public var alertItem: AlertItem? - public private(set) var nextPageMaxID: String? + public private(set) var nextPageMaxId: String? public private(set) var maintainScrollPositionOfItem: CollectionItemIdentifier? private let items = CurrentValueSubject<[[CollectionItem]], Never>([]) @@ -27,8 +27,8 @@ final public class CollectionItemsViewModel: ObservableObject { .sink { _ in } .store(in: &cancellables) - collectionService.nextPageMaxIDs - .sink { [weak self] in self?.nextPageMaxID = $0 } + collectionService.nextPageMaxId + .sink { [weak self] in self?.nextPageMaxId = $0 } .store(in: &cancellables) } } @@ -46,8 +46,8 @@ extension CollectionItemsViewModel: CollectionViewModel { public var navigationEvents: AnyPublisher { navigationEventsSubject.eraseToAnyPublisher() } - public func request(maxID: String? = nil, minID: String? = nil) { - collectionService.request(maxID: maxID, minID: minID) + public func request(maxId: String? = nil, minId: String? = nil) { + collectionService.request(maxId: maxId, minId: minId) .receive(on: DispatchQueue.main) .assignErrorsToAlertItem(to: \.alertItem, on: self) .handleEvents( @@ -80,7 +80,7 @@ extension CollectionItemsViewModel: CollectionViewModel { public func canSelect(indexPath: IndexPath) -> Bool { if case let .status(configuration) = items.value[indexPath.section][indexPath.item], - configuration.status.id == collectionService.contextParentID { + configuration.status.id == collectionService.contextParentId { return false } @@ -102,7 +102,7 @@ extension CollectionItemsViewModel: CollectionViewModel { cache(viewModel: viewModel, forItem: item) } - viewModel.isContextParent = configuration.status.id == collectionService.contextParentID + viewModel.isContextParent = configuration.status.id == collectionService.contextParentId viewModel.isPinned = configuration.pinned viewModel.isReplyInContext = configuration.isReplyInContext viewModel.hasReplyFollowing = configuration.hasReplyFollowing @@ -154,12 +154,12 @@ private extension CollectionItemsViewModel { maintainScrollPositionOfItem = nil // clear old value // Maintain scroll position of parent after initial load of context - if let contextParentID = collectionService.contextParentID { - let contextParentIdentifier = CollectionItemIdentifier(id: contextParentID, kind: .status, info: [:]) - let onlyContextParentID = [[], [contextParentIdentifier], []] + if let contextParentId = collectionService.contextParentId { + let contextParentIdentifier = CollectionItemIdentifier(id: contextParentId, kind: .status, info: [:]) + let onlyContextParentId = [[], [contextParentIdentifier], []] if items.value.isEmpty - || items.value.map({ $0.map(CollectionItemIdentifier.init(item:)) }) == onlyContextParentID { + || items.value.map({ $0.map(CollectionItemIdentifier.init(item:)) }) == onlyContextParentId { maintainScrollPositionOfItem = contextParentIdentifier } } diff --git a/ViewModels/Sources/ViewModels/CollectionViewModel.swift b/ViewModels/Sources/ViewModels/CollectionViewModel.swift index b68a091..bd8b7c4 100644 --- a/ViewModels/Sources/ViewModels/CollectionViewModel.swift +++ b/ViewModels/Sources/ViewModels/CollectionViewModel.swift @@ -9,9 +9,9 @@ public protocol CollectionViewModel { var alertItems: AnyPublisher { get } var loading: AnyPublisher { get } var navigationEvents: AnyPublisher { get } - var nextPageMaxID: String? { get } + var nextPageMaxId: String? { get } var maintainScrollPositionOfItem: CollectionItemIdentifier? { get } - func request(maxID: String?, minID: String?) + func request(maxId: String?, minId: String?) func select(indexPath: IndexPath) func canSelect(indexPath: IndexPath) -> Bool func viewModel(indexPath: IndexPath) -> CollectionItemViewModel diff --git a/ViewModels/Sources/ViewModels/EditFilterViewModel.swift b/ViewModels/Sources/ViewModels/EditFilterViewModel.swift index 37e7dd6..17ae7c4 100644 --- a/ViewModels/Sources/ViewModels/EditFilterViewModel.swift +++ b/ViewModels/Sources/ViewModels/EditFilterViewModel.swift @@ -28,7 +28,7 @@ public final class EditFilterViewModel: ObservableObject { } public extension EditFilterViewModel { - var isNew: Bool { filter.id == Filter.newFilterID } + var isNew: Bool { filter.id == Filter.newFilterId } var isSaveDisabled: Bool { filter.phrase == "" || filter.context.isEmpty } diff --git a/ViewModels/Sources/ViewModels/IdentitiesViewModel.swift b/ViewModels/Sources/ViewModels/IdentitiesViewModel.swift index 7f7ad5a..566d983 100644 --- a/ViewModels/Sources/ViewModels/IdentitiesViewModel.swift +++ b/ViewModels/Sources/ViewModels/IdentitiesViewModel.swift @@ -5,7 +5,7 @@ import Foundation import ServiceLayer public final class IdentitiesViewModel: ObservableObject { - public let currentIdentityID: UUID + public let currentIdentityId: Identity.Id @Published public var authenticated = [Identity]() @Published public var unauthenticated = [Identity]() @Published public var pending = [Identity]() @@ -16,7 +16,7 @@ public final class IdentitiesViewModel: ObservableObject { public init(identification: Identification) { self.identification = identification - currentIdentityID = identification.identity.id + currentIdentityId = identification.identity.id let observation = identification.service.identitiesObservation() .assignErrorsToAlertItem(to: \.alertItem, on: self) diff --git a/ViewModels/Sources/ViewModels/ProfileViewModel.swift b/ViewModels/Sources/ViewModels/ProfileViewModel.swift index bb7048b..cf9e464 100644 --- a/ViewModels/Sources/ViewModels/ProfileViewModel.swift +++ b/ViewModels/Sources/ViewModels/ProfileViewModel.swift @@ -66,23 +66,23 @@ extension ProfileViewModel: CollectionViewModel { .eraseToAnyPublisher() } - public var nextPageMaxID: String? { - collectionViewModel.value.nextPageMaxID + public var nextPageMaxId: String? { + collectionViewModel.value.nextPageMaxId } public var maintainScrollPositionOfItem: CollectionItemIdentifier? { collectionViewModel.value.maintainScrollPositionOfItem } - public func request(maxID: String?, minID: String?) { - if case .statuses = collection, maxID == nil { + public func request(maxId: String?, minId: String?) { + if case .statuses = collection, maxId == nil { profileService.fetchPinnedStatuses() .assignErrorsToAlertItem(to: \.alertItem, on: self) .sink { _ in } .store(in: &cancellables) } - collectionViewModel.value.request(maxID: maxID, minID: minID) + collectionViewModel.value.request(maxId: maxId, minId: minId) } public func select(indexPath: IndexPath) { diff --git a/ViewModels/Sources/ViewModels/RootViewModel.swift b/ViewModels/Sources/ViewModels/RootViewModel.swift index 21411c9..a927b9f 100644 --- a/ViewModels/Sources/ViewModels/RootViewModel.swift +++ b/ViewModels/Sources/ViewModels/RootViewModel.swift @@ -7,7 +7,7 @@ import ServiceLayer public final class RootViewModel: ObservableObject { @Published public private(set) var navigationViewModel: NavigationViewModel? - @Published private var mostRecentlyUsedIdentityID: UUID? + @Published private var mostRecentlyUsedIdentityId: Identity.Id? private let environment: AppEnvironment private let allIdentitiesService: AllIdentitiesService private let userNotificationService: UserNotificationService @@ -21,11 +21,11 @@ public final class RootViewModel: ObservableObject { userNotificationService = UserNotificationService(environment: environment) self.registerForRemoteNotifications = registerForRemoteNotifications - allIdentitiesService.immediateMostRecentlyUsedIdentityIDObservation() + allIdentitiesService.immediateMostRecentlyUsedIdentityIdObservation() .replaceError(with: nil) - .assign(to: &$mostRecentlyUsedIdentityID) + .assign(to: &$mostRecentlyUsedIdentityId) - identitySelected(id: mostRecentlyUsedIdentityID, immediate: true) + identitySelected(id: mostRecentlyUsedIdentityId, immediate: true) allIdentitiesService.identitiesCreated .sink { [weak self] in self?.identitySelected(id: $0) } @@ -42,11 +42,11 @@ public final class RootViewModel: ObservableObject { } public extension RootViewModel { - func identitySelected(id: UUID?) { + func identitySelected(id: Identity.Id?) { identitySelected(id: id, immediate: false) } - func deleteIdentity(id: UUID) { + func deleteIdentity(id: Identity.Id) { allIdentitiesService.deleteIdentity(id: id) .sink { _ in } receiveValue: { _ in } .store(in: &cancellables) @@ -60,7 +60,7 @@ public extension RootViewModel { } private extension RootViewModel { - func identitySelected(id: UUID?, immediate: Bool) { + func identitySelected(id: Identity.Id?, immediate: Bool) { navigationViewModel?.presentingSecondaryNavigation = false guard @@ -74,7 +74,7 @@ private extension RootViewModel { let observation = identityService.observation(immediate: immediate) .catch { [weak self] _ -> Empty in DispatchQueue.main.async { - self?.identitySelected(id: self?.mostRecentlyUsedIdentityID, immediate: false) + self?.identitySelected(id: self?.mostRecentlyUsedIdentityId, immediate: false) } return Empty() diff --git a/ViewModels/Tests/ViewModelsTests/AddIdentityViewModelTests.swift b/ViewModels/Tests/ViewModelsTests/AddIdentityViewModelTests.swift index 120f14a..5c054f0 100644 --- a/ViewModels/Tests/ViewModelsTests/AddIdentityViewModelTests.swift +++ b/ViewModels/Tests/ViewModelsTests/AddIdentityViewModelTests.swift @@ -18,12 +18,12 @@ class AddIdentityViewModelTests: XCTestCase { let sut = AddIdentityViewModel( allIdentitiesService: allIdentitiesService, instanceURLService: InstanceURLService(environment: environment)) - let addedIDRecorder = allIdentitiesService.identitiesCreated.record() + let addedIdRecorder = allIdentitiesService.identitiesCreated.record() sut.urlFieldText = "https://mastodon.social" sut.logInTapped() - _ = try wait(for: addedIDRecorder.next(), timeout: 1) + _ = try wait(for: addedIdRecorder.next(), timeout: 1) } func testAddIdentityWithoutScheme() throws { @@ -33,12 +33,12 @@ class AddIdentityViewModelTests: XCTestCase { let sut = AddIdentityViewModel( allIdentitiesService: allIdentitiesService, instanceURLService: InstanceURLService(environment: environment)) - let addedIDRecorder = allIdentitiesService.identitiesCreated.record() + let addedIdRecorder = allIdentitiesService.identitiesCreated.record() sut.urlFieldText = "mastodon.social" sut.logInTapped() - _ = try wait(for: addedIDRecorder.next(), timeout: 1) + _ = try wait(for: addedIdRecorder.next(), timeout: 1) } func testInvalidURL() throws { diff --git a/Views/AccountHeaderView.swift b/Views/AccountHeaderView.swift index a6f3419..cd57bae 100644 --- a/Views/AccountHeaderView.swift +++ b/Views/AccountHeaderView.swift @@ -81,7 +81,7 @@ private extension AccountHeaderView { segmentedControl.insertSegment( action: UIAction(title: collection.title) { [weak self] _ in self?.viewModel?.collection = collection - self?.viewModel?.request(maxID: nil, minID: nil) + self?.viewModel?.request(maxId: nil, minId: nil) }, at: index, animated: false) diff --git a/Views/IdentitiesView.swift b/Views/IdentitiesView.swift index d78b839..520e68a 100644 --- a/Views/IdentitiesView.swift +++ b/Views/IdentitiesView.swift @@ -47,7 +47,7 @@ private extension IdentitiesView { } label: { row(identity: identity) } - .disabled(identity.id == viewModel.currentIdentityID) + .disabled(identity.id == viewModel.currentIdentityId) .buttonStyle(PlainButtonStyle()) } .onDelete { @@ -94,7 +94,7 @@ private extension IdentitiesView { Spacer() } Spacer() - if identity.id == viewModel.currentIdentityID { + if identity.id == viewModel.currentIdentityId { Image(systemName: "checkmark.circle") } }