diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 30f9c0c2d..9a38be2b6 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -345,7 +345,7 @@ DB8F7076279E954700E1225B /* DataSourceFacade+Follow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8F7075279E954700E1225B /* DataSourceFacade+Follow.swift */; }; DB8FABC726AEC7B2008E5AF4 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB8FAB9E26AEC3A2008E5AF4 /* Intents.framework */; }; DB8FABCA26AEC7B2008E5AF4 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8FABC926AEC7B2008E5AF4 /* IntentHandler.swift */; }; - DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = DB8FABC626AEC7B2008E5AF4 /* MastodonIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */; }; DB938EE62623F50700E5B6C1 /* ThreadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */; }; DB938EED2623F79B00E5B6C1 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */; }; @@ -420,7 +420,7 @@ DBBF1DCB2652539E00E5B703 /* AutoCompleteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBF1DCA2652539E00E5B703 /* AutoCompleteItem.swift */; }; DBC6461526A170AB00B0E31B /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC6461426A170AB00B0E31B /* ShareViewController.swift */; }; DBC6461826A170AB00B0E31B /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DBC6461626A170AB00B0E31B /* MainInterface.storyboard */; }; - DBC6461C26A170AB00B0E31B /* ShareActionExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DBC6461226A170AB00B0E31B /* ShareActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + DBC6461C26A170AB00B0E31B /* ShareActionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = DBC6461226A170AB00B0E31B /* ShareActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; DBC6462326A1712000B0E31B /* ShareViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC6462226A1712000B0E31B /* ShareViewModel.swift */; }; DBC6462826A1736300B0E31B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DB427DDE25BAA00100D1B89D /* Assets.xcassets */; }; DBC7A672260C897100E57475 /* StatusContentWarningEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC7A671260C897100E57475 /* StatusContentWarningEditorView.swift */; }; @@ -466,7 +466,7 @@ DBF3B73F2733EAED00E21627 /* local-codes.json in Resources */ = {isa = PBXBuildFile; fileRef = DBF3B73E2733EAED00E21627 /* local-codes.json */; }; DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */; }; DBF8AE16263293E400C9C23C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF8AE15263293E400C9C23C /* NotificationService.swift */; }; - DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DBF8AE13263293E400C9C23C /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = DBF8AE13263293E400C9C23C /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; DBF96326262EC0A6001D8D25 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DBF96325262EC0A6001D8D25 /* AuthenticationServices.framework */; }; DBF9814A265E24F500E4BA07 /* ProfileFieldCollectionViewHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF98149265E24F500E4BA07 /* ProfileFieldCollectionViewHeaderFooterView.swift */; }; DBF9814C265E339500E4BA07 /* ProfileFieldAddEntryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF9814B265E339500E4BA07 /* ProfileFieldAddEntryCollectionViewCell.swift */; }; @@ -533,17 +533,17 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; - DBF8AE1B263293E400C9C23C /* Embed App Extensions */ = { + DBF8AE1B263293E400C9C23C /* Embed Foundation Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed App Extensions */, - DBC6461C26A170AB00B0E31B /* ShareActionExtension.appex in Embed App Extensions */, - DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed App Extensions */, + DB8FABCE26AEC7B2008E5AF4 /* MastodonIntent.appex in Embed Foundation Extensions */, + DBC6461C26A170AB00B0E31B /* ShareActionExtension.appex in Embed Foundation Extensions */, + DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed Foundation Extensions */, ); - name = "Embed App Extensions"; + name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ @@ -2916,7 +2916,7 @@ DB427DCE25BAA00100D1B89D /* Sources */, DB427DCF25BAA00100D1B89D /* Frameworks */, DB89BA0825C10FD0008580ED /* Embed Frameworks */, - DBF8AE1B263293E400C9C23C /* Embed App Extensions */, + DBF8AE1B263293E400C9C23C /* Embed Foundation Extensions */, DB3D100425BAA71500EAA174 /* ShellScript */, DB025B8E278D6448002F581E /* ShellScript */, DB697DD2278F48D5004EF2F7 /* ShellScript */, @@ -3042,7 +3042,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1250; - LastUpgradeCheck = 1250; + LastUpgradeCheck = 1400; TargetAttributes = { DB427DD125BAA00100D1B89D = { CreatedOnToolsVersion = 12.4; @@ -3237,7 +3237,8 @@ }; DB025B8E278D6448002F581E /* ShellScript */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + alwaysOutOfDate = 1; + buildActionMask = 8; files = ( ); inputFileListPaths = ( @@ -3248,13 +3249,14 @@ ); outputPaths = ( ); - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/Sourcery/bin/sourcery\" ]]; then\n \"${PODS_ROOT}/Sourcery/bin/sourcery\" --config ./MastodonSDK/Sources/CoreDataStack\nelse\n echo \"warning: Sourcery is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; DB3D100425BAA71500EAA174 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + alwaysOutOfDate = 1; + buildActionMask = 8; files = ( ); inputFileListPaths = ( @@ -3265,13 +3267,14 @@ ); outputPaths = ( ); - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" ]]; then\n \"${PODS_ROOT}/SwiftGen/bin/swiftgen\" \nelse\n echo \"warning: SwiftGen is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; DB697DD2278F48D5004EF2F7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; + alwaysOutOfDate = 1; + buildActionMask = 8; files = ( ); inputFileListPaths = ( @@ -3282,7 +3285,7 @@ ); outputPaths = ( ); - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; shellScript = "if [[ -f \"${PODS_ROOT}/Sourcery/bin/sourcery\" ]]; then\n \"${PODS_ROOT}/Sourcery/bin/sourcery\" --config ./Mastodon\nelse\n echo \"warning: Sourcery is not installed. Run 'pod install --repo-update' to install it.\"\nfi\n"; }; diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme index f88978596..87410f779 100644 --- a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme @@ -1,6 +1,6 @@ UICollectionViewCell? in - guard let self = self else { return UICollectionViewCell() } + guard let _ = self else { return UICollectionViewCell() } switch item { - case .attachment(let attachmentService): + case .attachment: let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusAttachmentCollectionViewCell.self), for: indexPath) as! ComposeStatusAttachmentCollectionViewCell cell.contentConfiguration = UIHostingConfigurationBackport { HStack { diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 095a362bf..b287f3b71 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -384,7 +384,7 @@ extension HomeTimelineViewController { @objc private func manuallySearchButtonPressed(_ sender: UIButton) { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - let searchDetailViewModel = SearchDetailViewModel() + let searchDetailViewModel = SearchDetailViewModel(authContext: viewModel.authContext) coordinator.present(scene: .searchDetail(viewModel: searchDetailViewModel), from: self, transition: .modal(animated: true, completion: nil)) } diff --git a/Mastodon/Scene/Profile/Bookmark/BookmarkViewModel+State.swift b/Mastodon/Scene/Profile/Bookmark/BookmarkViewModel+State.swift index 21cb8e021..8c9fd1150 100644 --- a/Mastodon/Scene/Profile/Bookmark/BookmarkViewModel+State.swift +++ b/Mastodon/Scene/Profile/Bookmark/BookmarkViewModel+State.swift @@ -48,7 +48,7 @@ extension BookmarkViewModel { extension BookmarkViewModel.State { class Initial: BookmarkViewModel.State { override func isValidNextState(_ stateClass: AnyClass) -> Bool { - guard let viewModel = viewModel else { return false } + guard let _ = viewModel else { return false } switch stateClass { case is Reloading.Type: return true @@ -132,7 +132,7 @@ extension BookmarkViewModel.State { override func didEnter(from previousState: GKState?) { super.didEnter(from: previousState) - guard let viewModel = viewModel, let stateMachine = stateMachine else { return } + guard let viewModel = viewModel, let _ = stateMachine else { return } if previousState is Reloading { maxID = nil diff --git a/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift b/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift index 590b85652..bea08059d 100644 --- a/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift @@ -185,41 +185,36 @@ extension StatusView { .assign(to: \.locked, on: viewModel) .store(in: &disposeBag) // isMuting - Publishers.CombineLatest( - viewModel.$userIdentifier, - author.publisher(for: \.mutingBy) - ) - .map { userIdentifier, mutingBy in - guard let userIdentifier = userIdentifier else { return false } - return mutingBy.contains(where: { - $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain - }) - } - .assign(to: \.isMuting, on: viewModel) - .store(in: &disposeBag) + author.publisher(for: \.mutingBy) + .map { [weak viewModel] mutingBy in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return mutingBy.contains(where: { + $0.id == authContext.mastodonAuthenticationBox.userID && $0.domain == authContext.mastodonAuthenticationBox.domain + }) + } + .assign(to: \.isMuting, on: viewModel) + .store(in: &disposeBag) // isBlocking - Publishers.CombineLatest( - viewModel.$userIdentifier, - author.publisher(for: \.blockingBy) - ) - .map { userIdentifier, blockingBy in - guard let userIdentifier = userIdentifier else { return false } - return blockingBy.contains(where: { - $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain - }) - } - .assign(to: \.isBlocking, on: viewModel) - .store(in: &disposeBag) + author.publisher(for: \.blockingBy) + .map { [weak viewModel] blockingBy in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return blockingBy.contains(where: { + $0.id == authContext.mastodonAuthenticationBox.userID && $0.domain == authContext.mastodonAuthenticationBox.domain + }) + } + .assign(to: \.isBlocking, on: viewModel) + .store(in: &disposeBag) // isMyself - Publishers.CombineLatest3( - viewModel.$userIdentifier, + Publishers.CombineLatest( author.publisher(for: \.domain), author.publisher(for: \.id) ) - .map { userIdentifier, domain, id in - guard let userIdentifier = userIdentifier else { return false } - return userIdentifier.domain == domain - && userIdentifier.userID == id + .map { [weak viewModel] domain, id in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return authContext.mastodonAuthenticationBox.domain == domain && authContext.mastodonAuthenticationBox.userID == id } .assign(to: \.isMyself, on: viewModel) .store(in: &disposeBag) @@ -317,15 +312,15 @@ extension StatusView { .store(in: &disposeBag) // isVotable if let poll = status.poll { - Publishers.CombineLatest3( + Publishers.CombineLatest( poll.publisher(for: \.votedBy), - poll.publisher(for: \.expired), - viewModel.$userIdentifier + poll.publisher(for: \.expired) ) - .map { votedBy, expired, userIdentifier in - guard let userIdentifier = userIdentifier else { return false } - let domain = userIdentifier.domain - let userID = userIdentifier.userID + .map { [weak viewModel] votedBy, expired in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + let domain = authContext.mastodonAuthenticationBox.domain + let userID = authContext.mastodonAuthenticationBox.userID let isVoted = votedBy?.contains(where: { $0.domain == domain && $0.id == userID }) ?? false return !isVoted && !expired } @@ -372,44 +367,38 @@ extension StatusView { .store(in: &disposeBag) // relationship - Publishers.CombineLatest( - viewModel.$userIdentifier, - status.publisher(for: \.rebloggedBy) - ) - .map { userIdentifier, rebloggedBy in - guard let userIdentifier = userIdentifier else { return false } - return rebloggedBy.contains(where: { - $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain - }) - } - .assign(to: \.isReblog, on: viewModel) - .store(in: &disposeBag) + status.publisher(for: \.rebloggedBy) + .map { [weak viewModel] rebloggedBy in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return rebloggedBy.contains(where: { + $0.id == authContext.mastodonAuthenticationBox.userID && $0.domain == authContext.mastodonAuthenticationBox.domain + }) + } + .assign(to: \.isReblog, on: viewModel) + .store(in: &disposeBag) - Publishers.CombineLatest( - viewModel.$userIdentifier, - status.publisher(for: \.favouritedBy) - ) - .map { userIdentifier, favouritedBy in - guard let userIdentifier = userIdentifier else { return false } - return favouritedBy.contains(where: { - $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain - }) - } - .assign(to: \.isFavorite, on: viewModel) - .store(in: &disposeBag) - - Publishers.CombineLatest( - viewModel.$userIdentifier, - status.publisher(for: \.bookmarkedBy) - ) - .map { userIdentifier, bookmarkedBy in - guard let userIdentifier = userIdentifier else { return false } - return bookmarkedBy.contains(where: { - $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain - }) - } - .assign(to: \.isBookmark, on: viewModel) - .store(in: &disposeBag) + status.publisher(for: \.favouritedBy) + .map { [weak viewModel]favouritedBy in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return favouritedBy.contains(where: { + $0.id == authContext.mastodonAuthenticationBox.userID && $0.domain == authContext.mastodonAuthenticationBox.domain + }) + } + .assign(to: \.isFavorite, on: viewModel) + .store(in: &disposeBag) + + status.publisher(for: \.bookmarkedBy) + .map { [weak viewModel] bookmarkedBy in + guard let viewModel = viewModel else { return false } + guard let authContext = viewModel.authContext else { return false } + return bookmarkedBy.contains(where: { + $0.id == authContext.mastodonAuthenticationBox.userID && $0.domain == authContext.mastodonAuthenticationBox.domain + }) + } + .assign(to: \.isBookmark, on: viewModel) + .store(in: &disposeBag) } private func configureFilter(status: Status) { diff --git a/MastodonSDK/Package.swift b/MastodonSDK/Package.swift index 7b0fe6af6..ac968754d 100644 --- a/MastodonSDK/Package.swift +++ b/MastodonSDK/Package.swift @@ -42,7 +42,7 @@ let package = Package( .package(url: "https://github.com/slackhq/PanModal.git", from: "1.2.7"), .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "5.0.0"), .package(url: "https://github.com/TimOliver/TOCropViewController.git", from: "2.6.1"), - .package(url: "https://github.com/TwidereProject/MetaTextKit.git", .exact("2.2.5")), + .package(url: "https://github.com/TwidereProject/MetaTextKit.git", exact: "2.2.5"), .package(url: "https://github.com/TwidereProject/TabBarPager.git", from: "0.1.0"), .package(url: "https://github.com/uias/Tabman", from: "2.13.0"), .package(url: "https://github.com/vtourraine/ThirdPartyMailer.git", from: "2.1.0"),