From 33c939f546cd4ed4c9e2e4a855497032881df356 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sun, 15 Dec 2024 16:13:02 +0000 Subject: [PATCH 1/3] Fix bug --- Mlem/App/Models/Account/UserAccount.swift | 1 + Mlem/App/Models/Session/UserSession.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Mlem/App/Models/Account/UserAccount.swift b/Mlem/App/Models/Account/UserAccount.swift index 2ed4e2059..abb16590b 100644 --- a/Mlem/App/Models/Account/UserAccount.swift +++ b/Mlem/App/Models/Account/UserAccount.swift @@ -96,6 +96,7 @@ class UserAccount: Account, CommunityOrPersonStub { getKeychainId(actorId: actorId) } + @MainActor func update(person: Person4, instance: Instance3) { var shouldSave = false if avatar != person.avatar { diff --git a/Mlem/App/Models/Session/UserSession.swift b/Mlem/App/Models/Session/UserSession.swift index c5b59e8b7..0eeafa4e0 100644 --- a/Mlem/App/Models/Session/UserSession.swift +++ b/Mlem/App/Models/Session/UserSession.swift @@ -38,7 +38,7 @@ class UserSession: Session { try await self.api.fetchSiteVersion(task: Task { let (person, instance, blocks) = try await self.api.getMyPerson() if let person { - self.account.update(person: person, instance: instance) + await self.account.update(person: person, instance: instance) self.person = person } self.blocks = blocks From 7052a90c339adb9da91a6e1ddc5cfd382ce16499 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:09:14 +0000 Subject: [PATCH 2/3] Update --- Mlem.xcodeproj/project.pbxproj | 8 +++++-- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- Mlem/App/Models/Account/GuestAccount.swift | 1 + Mlem/App/Models/Action/BasicAction.swift | 8 +++++++ .../Comment1Providing+Extensions.swift | 4 ++-- .../Community1Providing+Extensions.swift | 6 +++++ .../Interactable1Providing+Extensions.swift | 16 -------------- .../Post1Providing+Extensions.swift | 4 ++-- .../RemovableProviding+Extensions.swift | 22 +++++++++++++++++++ .../Views/Pages/Community/CommunityView.swift | 21 +++++++++++++----- .../Pages/ContentRemovalEditorView.swift | 12 +++++----- .../Shared/Navigation/NavigationPage.swift | 16 ++++++++++++-- Mlem/Localizable.xcstrings | 3 +++ 13 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 Mlem/App/Utility/Extensions/Content Models/RemovableProviding+Extensions.swift diff --git a/Mlem.xcodeproj/project.pbxproj b/Mlem.xcodeproj/project.pbxproj index b10d68493..065e791ed 100644 --- a/Mlem.xcodeproj/project.pbxproj +++ b/Mlem.xcodeproj/project.pbxproj @@ -81,6 +81,7 @@ 033FCB292C5E3933007B7CD1 /* IconSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033FCB252C5E3933007B7CD1 /* IconSettingsView.swift */; }; 033FCB2A2C5E3933007B7CD1 /* AlternateIconCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033FCB232C5E3933007B7CD1 /* AlternateIconCell.swift */; }; 033FCB3E2C5E7FA9007B7CD1 /* View+OutdatedFeedPopup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033FCB3D2C5E7FA9007B7CD1 /* View+OutdatedFeedPopup.swift */; }; + 034690932D0F4D720073E664 /* RemovableProviding+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034690922D0F4D720073E664 /* RemovableProviding+Extensions.swift */; }; 034B947F2C091EDD00039AF4 /* ProfileHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034B947E2C091EDD00039AF4 /* ProfileHeaderView.swift */; }; 034B94812C09306D00039AF4 /* CommunityOrPersonStub+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034B94802C09306D00039AF4 /* CommunityOrPersonStub+Extensions.swift */; }; 034B94832C09340A00039AF4 /* MarkdownConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034B94822C09340A00039AF4 /* MarkdownConfiguration+Extensions.swift */; }; @@ -504,6 +505,7 @@ 033FCB242C5E3933007B7CD1 /* AlternateIconLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlternateIconLabel.swift; sourceTree = ""; }; 033FCB252C5E3933007B7CD1 /* IconSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSettingsView.swift; sourceTree = ""; }; 033FCB3D2C5E7FA9007B7CD1 /* View+OutdatedFeedPopup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+OutdatedFeedPopup.swift"; sourceTree = ""; }; + 034690922D0F4D720073E664 /* RemovableProviding+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RemovableProviding+Extensions.swift"; sourceTree = ""; }; 034B947E2C091EDD00039AF4 /* ProfileHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileHeaderView.swift; sourceTree = ""; }; 034B94802C09306D00039AF4 /* CommunityOrPersonStub+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommunityOrPersonStub+Extensions.swift"; sourceTree = ""; }; 034B94822C09340A00039AF4 /* MarkdownConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownConfiguration+Extensions.swift"; sourceTree = ""; }; @@ -1760,6 +1762,7 @@ 03AFD0E42C3C14D50054B8AD /* InstanceStubProviding+Extensions.swift */, 035394962CA1AFAF00795AA5 /* InstanceStubProviding+Uptime.swift */, CDC199E92BE449790077B4F1 /* Interactable1Providing+Extensions.swift */, + 034690922D0F4D720073E664 /* RemovableProviding+Extensions.swift */, 0397D4852C6A24D2002C6CDC /* ReportableProviding+Extensions.swift */, 03CBD1922C61369A00E870BC /* Interactable2Providing+Extensions.swift */, 0389DDC22C38907C0005B808 /* Message1Providing+Extensions.swift */, @@ -2198,6 +2201,7 @@ CDB41E8E2C84CFA200BD2DE9 /* FixedImageView.swift in Sources */, 033F84C12C2AD072002E3EDF /* CommentWrapper.swift in Sources */, 034B94832C09340A00039AF4 /* MarkdownConfiguration+Extensions.swift in Sources */, + 034690932D0F4D720073E664 /* RemovableProviding+Extensions.swift in Sources */, 039F58952C7B618F00C61658 /* InboxSettingsView.swift in Sources */, CD4D58CF2B86DDEC00B82964 /* AccountSortMode.swift in Sources */, CDE1F18F2C63D75A008AF042 /* Settings.swift in Sources */, @@ -2942,8 +2946,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/mlemgroup/MlemMiddleware"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 0.52.0; + branch = "sjmarf/purge-community"; + kind = branch; }; }; CDE4AC402CA3706400981010 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { diff --git a/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 53c8be7e0..0dd6cd8cc 100644 --- a/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mlemgroup/MlemMiddleware", "state" : { - "revision" : "51db2875046e216fb01c8233cc43eadd147dd240", - "version" : "0.52.0" + "branch" : "sjmarf/purge-community", + "revision" : "a20590dbe7d70576021d92d55dc2a73d51babf62" } }, { diff --git a/Mlem/App/Models/Account/GuestAccount.swift b/Mlem/App/Models/Account/GuestAccount.swift index 2d6467658..7839d5abb 100644 --- a/Mlem/App/Models/Account/GuestAccount.swift +++ b/Mlem/App/Models/Account/GuestAccount.swift @@ -71,6 +71,7 @@ class GuestAccount: Account { try container.encode(api.baseUrl, forKey: .instanceLink) } + @MainActor func update(instance: Instance3) { var shouldSave = false if avatar != instance.avatar { diff --git a/Mlem/App/Models/Action/BasicAction.swift b/Mlem/App/Models/Action/BasicAction.swift index ea3acf39f..7455e0e07 100644 --- a/Mlem/App/Models/Action/BasicAction.swift +++ b/Mlem/App/Models/Action/BasicAction.swift @@ -53,4 +53,12 @@ struct BasicAction: Action { } } } + + func disabled(_ value: Bool) -> BasicAction { + var new = self + if value { + new.callback = nil + } + return new + } } diff --git a/Mlem/App/Utility/Extensions/Content Models/Comment1Providing+Extensions.swift b/Mlem/App/Utility/Extensions/Content Models/Comment1Providing+Extensions.swift index e88fb1d76..b0118c0a9 100644 --- a/Mlem/App/Utility/Extensions/Content Models/Comment1Providing+Extensions.swift +++ b/Mlem/App/Utility/Extensions/Content Models/Comment1Providing+Extensions.swift @@ -98,7 +98,7 @@ extension Comment1Providing { @ActionBuilder func moderatorMenuActions(feedback: Set = [.haptic, .toast]) -> [any Action] { if let self2, !isOwnComment { - self2.removeAction() + self2.removeAction().disabled(!canModerate) banActions() } if api.isAdmin { @@ -126,7 +126,7 @@ extension Comment1Providing { case .share: shareAction() case .selectText: selectTextAction() case .report: reportAction(communityContext: communityContext) - case .remove: removeAction() + case .remove: removeAction().disabled(!canModerate) } } diff --git a/Mlem/App/Utility/Extensions/Content Models/Community1Providing+Extensions.swift b/Mlem/App/Utility/Extensions/Content Models/Community1Providing+Extensions.swift index 90ba08908..46a5cd857 100644 --- a/Mlem/App/Utility/Extensions/Content Models/Community1Providing+Extensions.swift +++ b/Mlem/App/Utility/Extensions/Content Models/Community1Providing+Extensions.swift @@ -121,6 +121,12 @@ extension Community1Providing { copyNameAction() shareAction() blockAction(feedback: feedback) + if api.isAdmin { + ActionGroup { + removeAction() + purgeAction() + } + } } func swipeActions(behavior: SwipeBehavior) -> SwipeConfiguration { diff --git a/Mlem/App/Utility/Extensions/Content Models/Interactable1Providing+Extensions.swift b/Mlem/App/Utility/Extensions/Content Models/Interactable1Providing+Extensions.swift index eb56e2fcc..ec66b1087 100644 --- a/Mlem/App/Utility/Extensions/Content Models/Interactable1Providing+Extensions.swift +++ b/Mlem/App/Utility/Extensions/Content Models/Interactable1Providing+Extensions.swift @@ -86,14 +86,6 @@ extension Interactable1Providing { } } } - - func showRemoveSheet() { - guard let self2 else { - print("DEBUG no self2 found in toggleRemoved!") - return - } - NavigationModel.main.openSheet(.remove(self2)) - } // MARK: Counters @@ -173,14 +165,6 @@ extension Interactable1Providing { ) } - func removeAction(feedback: Set = []) -> BasicAction { - .init( - id: "remove\(uid)", - appearance: .remove(isOn: self2?.removed ?? false, isInProgress: !(self2?.removedManager.isInSync ?? true)), - callback: api.canInteract && (self2?.canModerate ?? false) ? showRemoveSheet : nil - ) - } - func banActions() -> [any Action] { let isModerator: Bool if let myPerson = api.myPerson, let community = community_ { diff --git a/Mlem/App/Utility/Extensions/Content Models/Post1Providing+Extensions.swift b/Mlem/App/Utility/Extensions/Content Models/Post1Providing+Extensions.swift index e6b8c02f0..d258307c7 100644 --- a/Mlem/App/Utility/Extensions/Content Models/Post1Providing+Extensions.swift +++ b/Mlem/App/Utility/Extensions/Content Models/Post1Providing+Extensions.swift @@ -185,7 +185,7 @@ extension Post1Providing { } lockAction(feedback: feedback) if let self2, !isOwnPost { - self2.removeAction() + self2.removeAction().disabled(!canModerate) banActions() } if api.isAdmin { @@ -219,7 +219,7 @@ extension Post1Providing { // in parenthesis, but the pre-commit hook removed the paranthesis // swiftlint:disable:next void_function_in_ternary case .pin: api.isAdmin ? pinAction(feedback: feedback) : pinToCommunityAction(feedback: feedback) - case .remove: removeAction(feedback: feedback) + case .remove: removeAction(feedback: feedback).disabled(!canModerate) } } diff --git a/Mlem/App/Utility/Extensions/Content Models/RemovableProviding+Extensions.swift b/Mlem/App/Utility/Extensions/Content Models/RemovableProviding+Extensions.swift new file mode 100644 index 000000000..165361a28 --- /dev/null +++ b/Mlem/App/Utility/Extensions/Content Models/RemovableProviding+Extensions.swift @@ -0,0 +1,22 @@ +// +// RemovableProviding+Extensions.swift +// Mlem +// +// Created by Sjmarf on 2024-12-15. +// + +import MlemMiddleware + +extension RemovableProviding { + func showRemoveSheet() { + NavigationModel.main.openSheet(.remove(self)) + } + + func removeAction(feedback: Set = []) -> BasicAction { + .init( + id: "remove\(uid)", + appearance: .remove(isOn: removed, isInProgress: !removedManager.isInSync), + callback: api.canInteract ? showRemoveSheet : nil + ) + } +} diff --git a/Mlem/App/Views/Pages/Community/CommunityView.swift b/Mlem/App/Views/Pages/Community/CommunityView.swift index d8c5ba3ac..3def5d5cd 100644 --- a/Mlem/App/Views/Pages/Community/CommunityView.swift +++ b/Mlem/App/Views/Pages/Community/CommunityView.swift @@ -128,12 +128,23 @@ struct CommunityView: View { @ViewBuilder func postsTab(community: any Community, postFeedLoader: CommunityPostFeedLoader) -> some View { - PostGridView(postFeedLoader: postFeedLoader) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - FeedSortPicker(feedLoader: postFeedLoader) - } + if community.removed { + VStack(spacing: Constants.main.standardSpacing) { + Image(systemName: Icons.remove) + .font(.title) + Text("This community has been removed.") + .fontWeight(.semibold) } + .foregroundStyle(palette.warning) + .padding(.top, Constants.main.doubleSpacing) + } else { + PostGridView(postFeedLoader: postFeedLoader) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + FeedSortPicker(feedLoader: postFeedLoader) + } + } + } } @ViewBuilder diff --git a/Mlem/App/Views/Pages/ContentRemovalEditorView.swift b/Mlem/App/Views/Pages/ContentRemovalEditorView.swift index e5266cc1e..8b7a48f30 100644 --- a/Mlem/App/Views/Pages/ContentRemovalEditorView.swift +++ b/Mlem/App/Views/Pages/ContentRemovalEditorView.swift @@ -17,18 +17,18 @@ struct ContentRemovalEditorView: View { case remove, restore } - let target: any Interactable2Providing + let target: any RemovableProviding @State var mode: Mode - @State var community: any Community + @State var community: (any Community)? @State var reason: String = "" @FocusState var reasonFocused: Bool @State var presentationSelection: PresentationDetent = .large - init(target: any Interactable2Providing) { + init(target: any RemovableProviding) { self.target = target self._mode = .init(wrappedValue: target.removed ? .restore : .remove) - self._community = .init(wrappedValue: target.community) + self._community = .init(wrappedValue: (target as? any Interactable2Providing)?.community) } var body: some View { @@ -41,7 +41,9 @@ struct ContentRemovalEditorView: View { Section { ReasonShortcutView(reason: $reason) } - RulesListView(model: community, reason: $reason) + if let community { + RulesListView(model: community, reason: $reason) + } if let instance = appState.firstSession.instance { RulesListView(model: instance, reason: $reason) } diff --git a/Mlem/App/Views/Shared/Navigation/NavigationPage.swift b/Mlem/App/Views/Shared/Navigation/NavigationPage.swift index 9216f3a61..74d0f95ca 100644 --- a/Mlem/App/Views/Shared/Navigation/NavigationPage.swift +++ b/Mlem/App/Views/Shared/Navigation/NavigationPage.swift @@ -37,7 +37,7 @@ enum NavigationPage: Hashable { case createComment(_ context: CommentEditorView.Context, commentTreeTracker: CommentTreeTracker? = nil) case editComment(_ comment: Comment2, context: CommentEditorView.Context?) case report(_ interactable: ReportableHashWrapper, community: AnyCommunity? = nil) - case remove(_ interactable: Interactable2HashWrapper) + case remove(_ removable: RemovableHashWrapper) case purge(_ purgable: PurgableHashWrapper) case ban(_ person: AnyPerson, isBannedFromCommunity: Bool, shouldBan: Bool, community: AnyCommunity?) case createPost( @@ -211,7 +211,7 @@ enum NavigationPage: Hashable { return report(.init(wrappedValue: interactable), community: anyCommunity) } - static func remove(_ interactable: any Interactable2Providing) -> NavigationPage { + static func remove(_ interactable: any RemovableProviding) -> NavigationPage { remove(.init(wrappedValue: interactable)) } @@ -313,6 +313,18 @@ struct ReportableHashWrapper: Hashable { } } +struct RemovableHashWrapper: Hashable { + var wrappedValue: any RemovableProviding + + func hash(into hasher: inout Hasher) { + hasher.combine(wrappedValue.hashValue) + } + + static func == (lhs: RemovableHashWrapper, rhs: RemovableHashWrapper) -> Bool { + lhs.hashValue == rhs.hashValue + } +} + struct PurgableHashWrapper: Hashable { var wrappedValue: any PurgableProviding diff --git a/Mlem/Localizable.xcstrings b/Mlem/Localizable.xcstrings index 0e94e522b..cda73f91a 100644 --- a/Mlem/Localizable.xcstrings +++ b/Mlem/Localizable.xcstrings @@ -1588,6 +1588,9 @@ } } } + }, + "This community has been removed." : { + }, "This community likely contains graphic or explicit content." : { From 9c97a8dd0da3f0b6c4f202691bc6422ac3a8321b Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:37:16 +0000 Subject: [PATCH 3/3] MlemMiddleware version --- Mlem.xcodeproj/project.pbxproj | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mlem.xcodeproj/project.pbxproj b/Mlem.xcodeproj/project.pbxproj index 065e791ed..c07acadd4 100644 --- a/Mlem.xcodeproj/project.pbxproj +++ b/Mlem.xcodeproj/project.pbxproj @@ -2946,8 +2946,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/mlemgroup/MlemMiddleware"; requirement = { - branch = "sjmarf/purge-community"; - kind = branch; + kind = upToNextMinorVersion; + minimumVersion = 0.53.0; }; }; CDE4AC402CA3706400981010 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { diff --git a/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0dd6cd8cc..47278bd4e 100644 --- a/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mlem.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mlemgroup/MlemMiddleware", "state" : { - "branch" : "sjmarf/purge-community", - "revision" : "a20590dbe7d70576021d92d55dc2a73d51babf62" + "revision" : "a4dc838d0ff82ea76b71ee9e9568743d957e15a0", + "version" : "0.53.0" } }, {