From 3a0bb140a30807319affc95240292a54f77fd440 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 13:15:45 +0100 Subject: [PATCH 01/19] add new radio button component --- Nos.xcodeproj/project.pbxproj | 4 ++ Nos/Views/Components/NosRadioButtonView.swift | 71 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 Nos/Views/Components/NosRadioButtonView.swift diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index c9e351985..05387ff5d 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -99,6 +99,7 @@ 03FE3F8C2C87BC9500D25810 /* text_note_multiple_media.json in Resources */ = {isa = PBXBuildFile; fileRef = 03FE3F8A2C87BC9500D25810 /* text_note_multiple_media.json */; }; 042406F32C907A15008F2A21 /* NosToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042406F22C907A15008F2A21 /* NosToggle.swift */; }; 04368D2B2C99A2C400DEAA2E /* FlagOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */; }; + 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */; }; 2D06BB9D2AE249D70085F509 /* ThreadRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */; }; 2D4010A22AD87DF300F93AD4 /* KnownFollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */; }; 3A1C296F2B2A537C0020B753 /* Moderation.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */; }; @@ -623,6 +624,7 @@ 03FE3F8A2C87BC9500D25810 /* text_note_multiple_media.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = text_note_multiple_media.json; sourceTree = ""; }; 042406F22C907A15008F2A21 /* NosToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosToggle.swift; sourceTree = ""; }; 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOption.swift; sourceTree = ""; }; + 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButtonView.swift; sourceTree = ""; }; 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadRootView.swift; sourceTree = ""; }; 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KnownFollowersView.swift; sourceTree = ""; }; 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Moderation.xcstrings; sourceTree = ""; }; @@ -1411,6 +1413,7 @@ 3F60F42829B27D3E000D62C4 /* ThreadView.swift */, C913DA0D2AEB3265003BDD6D /* WarningView.swift */, C9CE5B132A0172CF008E198C /* WebView.swift */, + 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */, 03618C642C8267A900BCBC55 /* Author */, 03618C232C82668600BCBC55 /* Button */, 03618C7E2C82685500BCBC55 /* Event */, @@ -2177,6 +2180,7 @@ C987F81A29BA4D0E00B44E7A /* ActionButton.swift in Sources */, C9E37E122A1E7EC5003D4B0A /* PreviewContainer.swift in Sources */, C9A0DAF829C92F4500466635 /* UNSAPI.swift in Sources */, + 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */, 5B79F60B2B98ACA0002DA9BE /* PickYourUsernameSheet.swift in Sources */, 5BFF66B62A58A8A000AA79DD /* MutesView.swift in Sources */, C913DA0A2AEAF52B003BDD6D /* NoteWarningController.swift in Sources */, diff --git a/Nos/Views/Components/NosRadioButtonView.swift b/Nos/Views/Components/NosRadioButtonView.swift new file mode 100644 index 000000000..a9ccde00d --- /dev/null +++ b/Nos/Views/Components/NosRadioButtonView.swift @@ -0,0 +1,71 @@ +import SwiftUI +/// A view that represents a radio button. +struct NosRadioButtonView: View { + var isSelected: Bool + var body: some View { + ZStack { + RadioButtonBackgroundView() + if isSelected { + RadioButtonSelectorView() + } + } + } +} + +struct RadioButtonBackgroundView: View { + var body: some View { + ZStack { + Circle() + .fill( + LinearGradient( + colors: [Color.radioButtonBgTop, Color.radioButtonBgBottom], + startPoint: .top, + endPoint: .bottom + ) + ) + .frame(width: 25, height: 25) + // Inner shadow effect + .overlay( + Circle() + .fill( + LinearGradient( + colors: [Color.radioButtonBgTop, Color.radioButtonBgBottom], + startPoint: .top, + endPoint: .bottom + ) + ) + .stroke(Color.radioButtonInnerDropShadow, lineWidth: 1) + .blur(radius: 1.67) + .offset(x: 0, y: 0.67) + .mask(Circle()) // Ensures the inner shadow stays within the circle's shape + ) + + // Outer shadow effect + .shadow(color: Color.radioButtonOuterDropShadow, radius: 0, x: 0, y: 0.99) + } + } +} + +struct RadioButtonSelectorView: View { + var body: some View { + Circle() + .fill( + LinearGradient( + colors: [Color.radioButtonSelectorTop, Color.radioButtonSelectorBottom], + startPoint: .top, + endPoint: .bottom + ) + ) + .frame(width: 17, height: 17) + } +} + +#Preview { + NosRadioButtonView(isSelected: true) + .previewDisplayName("Selected") +} + +#Preview { + NosRadioButtonView(isSelected: false) + .previewDisplayName("Not Selected") +} From 63ae0d62d12a62859c325e08f2d2052f7ac4aa36 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 13:36:43 +0100 Subject: [PATCH 02/19] add flagOptionPicker view --- Nos.xcodeproj/project.pbxproj | 4 + Nos/Views/FlagOptionPickerView.swift | 117 +++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 Nos/Views/FlagOptionPickerView.swift diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 05387ff5d..35c51f179 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 042406F32C907A15008F2A21 /* NosToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042406F22C907A15008F2A21 /* NosToggle.swift */; }; 04368D2B2C99A2C400DEAA2E /* FlagOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */; }; 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */; }; + 0496D6312C975E6900D29375 /* FlagOptionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */; }; 2D06BB9D2AE249D70085F509 /* ThreadRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */; }; 2D4010A22AD87DF300F93AD4 /* KnownFollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */; }; 3A1C296F2B2A537C0020B753 /* Moderation.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */; }; @@ -625,6 +626,7 @@ 042406F22C907A15008F2A21 /* NosToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosToggle.swift; sourceTree = ""; }; 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOption.swift; sourceTree = ""; }; 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButtonView.swift; sourceTree = ""; }; + 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOptionPickerView.swift; sourceTree = ""; }; 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadRootView.swift; sourceTree = ""; }; 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KnownFollowersView.swift; sourceTree = ""; }; 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Moderation.xcstrings; sourceTree = ""; }; @@ -1843,6 +1845,7 @@ 03618BDF2C8265CF00BCBC55 /* Settings */, 03618BF42C82661400BCBC55 /* SideMenu */, C905EA362A33620A006F1E99 /* UNS */, + 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, ); path = Views; sourceTree = ""; @@ -2231,6 +2234,7 @@ C9EE3E632A053910008A7491 /* ExpirationTimeOption.swift in Sources */, C9A0DAE029C697A100466635 /* AboutView.swift in Sources */, C9E8C1132B081E9C002D46B0 /* UNSNameView.swift in Sources */, + 0496D6312C975E6900D29375 /* FlagOptionPickerView.swift in Sources */, A351E1A229BA92240009B7F6 /* ProfileEditView.swift in Sources */, C9DFA969299BEC33006929C1 /* CardStyle.swift in Sources */, C95D68AD299E721700429F86 /* ProfileView.swift in Sources */, diff --git a/Nos/Views/FlagOptionPickerView.swift b/Nos/Views/FlagOptionPickerView.swift new file mode 100644 index 000000000..88491abe1 --- /dev/null +++ b/Nos/Views/FlagOptionPickerView.swift @@ -0,0 +1,117 @@ +import SwiftUI +/// Displays a list of selectable flag options +struct FlagOptionPickerView: View { + @Binding private var selectedFlag: FlagOption? + var options: [FlagOption] + var title: String + var subTitle: String? + + init(selectedFlag: Binding, options: [FlagOption], title: String, subTitle: String?) { + self._selectedFlag = selectedFlag + self.options = options + self.title = title + self.subTitle = subTitle + } + + var body: some View { + ScrollView { + VStack(alignment: .leading) { + HeaderView(text: title) + + if let subTitle = subTitle { + HeaderView(text: subTitle) + } + flagOptionsListView + } + .padding() + } + .background(Color.appBg) + } + + private var flagOptionsListView: some View { + VStack(alignment: .leading) { + ForEach(options) { flag in + FlagPickerRow(flag: flag, selection: $selectedFlag) + BeveledSeparator() + } + } + .background( + LinearGradient( + colors: [Color.cardBgTop, Color.cardBgBottom], + startPoint: .top, + endPoint: .bottom + ) + ) + .clipShape(RoundedRectangle(cornerRadius: 15)) + } +} + +/// A single row for a single flag option +struct FlagPickerRow: View { + var flag: FlagOption + @Binding var selection: FlagOption? + + var isSelected: Bool { + selection?.id == flag.id + } + + var body: some View { + HStack(alignment: .center) { + VStack(alignment: .leading, spacing: 8) { + Text(flag.title) + .foregroundColor(.primaryTxt) + .font(.clarity(.regular)) + + if let description = flag.description { + Text(description) + .foregroundColor(.secondaryTxt) + .font(.clarity(.regular, textStyle: .footnote)) + .lineSpacing(8) + } + } + + Spacer() + + Button { + selection = flag + } label: { + NosRadioButtonView(isSelected: isSelected) + } + } + .padding(12) + } +} + +private struct HeaderView: View { + var text: String + var body: some View { + Text(text) + .lineSpacing(5) + .foregroundColor(.primaryTxt) + .font(.clarity(.bold)) + .padding(.bottom, 28) + } +} + +struct FlagOptionPickerView_Previews: PreviewProvider { + struct PreviewWrapper: View { + @State private var selectedFlag: FlagOption? + + var body: some View { + FlagOptionPickerView( + selectedFlag: $selectedFlag, + options: FlagOption.flagContentCategories, + title: "Create a tag for this content that other people in your network can see.", + subTitle: "Select a tag for the content" + ) + .onAppear { + selectedFlag = FlagOption.flagContentCategories.first + } + .background(Color.appBg) + } + } + + static var previews: some View { + PreviewWrapper() + } +} From 44fda1fb81637fc28898ad79772eed402dc2f4e0 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 13:38:12 +0100 Subject: [PATCH 03/19] update radio button comments --- Nos/Views/Components/NosRadioButtonView.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Nos/Views/Components/NosRadioButtonView.swift b/Nos/Views/Components/NosRadioButtonView.swift index a9ccde00d..e62c5d901 100644 --- a/Nos/Views/Components/NosRadioButtonView.swift +++ b/Nos/Views/Components/NosRadioButtonView.swift @@ -1,5 +1,5 @@ import SwiftUI -/// A view that represents a radio button. +/// A custom radio button. struct NosRadioButtonView: View { var isSelected: Bool var body: some View { @@ -12,6 +12,7 @@ struct NosRadioButtonView: View { } } +/// A custom background for a radio button. struct RadioButtonBackgroundView: View { var body: some View { ZStack { @@ -46,6 +47,7 @@ struct RadioButtonBackgroundView: View { } } +/// A colorful selector (inner circle) of a radio button with a gradient fill. struct RadioButtonSelectorView: View { var body: some View { Circle() @@ -60,12 +62,10 @@ struct RadioButtonSelectorView: View { } } -#Preview { +#Preview("Selected") { NosRadioButtonView(isSelected: true) - .previewDisplayName("Selected") } -#Preview { +#Preview("Not Selected") { NosRadioButtonView(isSelected: false) - .previewDisplayName("Not Selected") } From 390681060f2b425be6c437aae0a3849b57cd8879 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 15:04:23 +0100 Subject: [PATCH 04/19] update ReportMenuModifier --- Nos/Views/Modifiers/ReportMenuModifier.swift | 63 +++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index 2cd9a27a5..10c69001f 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -15,11 +15,68 @@ struct ReportMenuModifier: ViewModifier { @State private var confirmReport = false @State private var showMuteDialog = false @State private var confirmationDialogState: ConfirmationDialogState? - + @State private var selectedFlagOption: FlagOption? + @Environment(\.managedObjectContext) private var viewContext - - // swiftlint:disable function_body_length + @Dependency(\.featureFlags) private var featureFlags + func body(content: Content) -> some View { + Group { + if featureFlags.isEnabled(.newModerationFlow) { + newModerationFlow(content: content) + } else { + oldModerationFlow(content: content) + } + } + } + + /// Displays the moderation flow based on the reported object type. The old flow is still displayed for the author. + @ViewBuilder + private func newModerationFlow(content: Content) -> some View { + switch reportedObject { + case .note: + content + .sheet(isPresented: $isPresented) { + flagOptionPickerForSelection(userSelection) + } + case .author: + oldModerationFlow(content: content) + } + } + + /// Provides the flag option picker based on the user's selection. + /// - Parameter userSelection: The optional user selection that determines the flagging options. + /// - Returns: A view containing the flag option picker for the current selection. + private func flagOptionPickerForSelection(_ userSelection: UserSelection?) -> some View { + var title = String(localized: .localizable.reportContent) + var subTitle = String(localized: .localizable.reportContentMessage) + + guard let userSelection = userSelection else { + return FlagOptionPickerView( + selectedFlag: $selectedFlagOption, + options: FlagOption.flagContentCategories, + title: title, + subTitle: subTitle + ) + } + + switch userSelection { + default: + title = String(localized: .localizable.reportContent) + subTitle = String(localized: .localizable.reportContentMessage) + } + + return FlagOptionPickerView( + selectedFlag: $selectedFlagOption, + options: FlagOption.flagContentCategories, + title: title, + subTitle: subTitle + ) + } + + // swiftlint:enable function_body_length + @ViewBuilder + func oldModerationFlow(content: Content) -> some View { content // ReportCategory menu .confirmationDialog(unwrapping: $confirmationDialogState, action: processUserSelection) From 0945dd8dbe7f3781e62f55a65ea3684188f64729 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 15:21:35 +0100 Subject: [PATCH 05/19] move view to components folder --- Nos.xcodeproj/project.pbxproj | 2 +- Nos/Views/{ => Components}/FlagOptionPickerView.swift | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Nos/Views/{ => Components}/FlagOptionPickerView.swift (100%) diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 35c51f179..7d08bc3d2 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -1390,6 +1390,7 @@ 5B79F6402BA11618002DA9BE /* Components */ = { isa = PBXGroup; children = ( + 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, C98DC9BA2A795CAD004E5F0F /* ActionBanner.swift */, C9A0DAE929C6A34200466635 /* ActivityView.swift */, 3FFB1D88299FF37C002A755D /* AvatarView.swift */, @@ -1845,7 +1846,6 @@ 03618BDF2C8265CF00BCBC55 /* Settings */, 03618BF42C82661400BCBC55 /* SideMenu */, C905EA362A33620A006F1E99 /* UNS */, - 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, ); path = Views; sourceTree = ""; diff --git a/Nos/Views/FlagOptionPickerView.swift b/Nos/Views/Components/FlagOptionPickerView.swift similarity index 100% rename from Nos/Views/FlagOptionPickerView.swift rename to Nos/Views/Components/FlagOptionPickerView.swift From 2afbd3a3d77c7f7e9279c9217f5ace38c7882ad4 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 15:42:11 +0100 Subject: [PATCH 06/19] fix swiftlint warning --- Nos/Views/Modifiers/ReportMenuModifier.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index 10c69001f..01b3571e3 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -74,7 +74,7 @@ struct ReportMenuModifier: ViewModifier { ) } - // swiftlint:enable function_body_length + // swiftlint:disable function_body_length @ViewBuilder func oldModerationFlow(content: Content) -> some View { content @@ -142,7 +142,7 @@ struct ReportMenuModifier: ViewModifier { } } // swiftlint:enable function_body_length - + func processUserSelection(_ userSelection: UserSelection?) { self.userSelection = userSelection From dc6a4455e188391b35b6f938c2856478f8e4f6cf Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 16:10:31 +0100 Subject: [PATCH 07/19] create contentFlagView --- Nos.xcodeproj/project.pbxproj | 14 +++++++++++- Nos/Views/Moderation/ContentFlagView.swift | 23 ++++++++++++++++++++ Nos/Views/Modifiers/ReportMenuModifier.swift | 10 ++++----- 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 Nos/Views/Moderation/ContentFlagView.swift diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 7d08bc3d2..41db5b922 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 042406F32C907A15008F2A21 /* NosToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042406F22C907A15008F2A21 /* NosToggle.swift */; }; 04368D2B2C99A2C400DEAA2E /* FlagOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */; }; 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */; }; + 04368D4B2C99CFC700DEAA2E /* ContentFlagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */; }; 0496D6312C975E6900D29375 /* FlagOptionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */; }; 2D06BB9D2AE249D70085F509 /* ThreadRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */; }; 2D4010A22AD87DF300F93AD4 /* KnownFollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */; }; @@ -626,6 +627,7 @@ 042406F22C907A15008F2A21 /* NosToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosToggle.swift; sourceTree = ""; }; 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOption.swift; sourceTree = ""; }; 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButtonView.swift; sourceTree = ""; }; + 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFlagView.swift; sourceTree = ""; }; 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOptionPickerView.swift; sourceTree = ""; }; 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadRootView.swift; sourceTree = ""; }; 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KnownFollowersView.swift; sourceTree = ""; }; @@ -1331,6 +1333,14 @@ path = NostrIdentifier; sourceTree = ""; }; + 04368D542C99D32B00DEAA2E /* Moderation */ = { + isa = PBXGroup; + children = ( + 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */, + ); + path = Moderation; + sourceTree = ""; + }; 3AAB61B12B24CC8A00717A07 /* Extensions */ = { isa = PBXGroup; children = ( @@ -1390,12 +1400,12 @@ 5B79F6402BA11618002DA9BE /* Components */ = { isa = PBXGroup; children = ( - 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, C98DC9BA2A795CAD004E5F0F /* ActionBanner.swift */, C9A0DAE929C6A34200466635 /* ActivityView.swift */, 3FFB1D88299FF37C002A755D /* AvatarView.swift */, C95D68A0299E6D3E00429F86 /* BioView.swift */, C9DFA968299BEC33006929C1 /* CardStyle.swift */, + 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, C9B678E629F01A8500303F33 /* FullscreenProgressView.swift */, C9CDBBA329A8FA2900C555C7 /* GoldenPostView.swift */, C930E0562BA49DAD002B5776 /* GridPattern.swift */, @@ -1836,6 +1846,7 @@ 65BD8DC12BDAF2C300802039 /* Discover */, 03618B112C825D8700BCBC55 /* Fixtures */, C96877B32B4EDCCF0051ED2F /* Home */, + 04368D542C99D32B00DEAA2E /* Moderation */, C9CFF6D02AB241EB00D4B368 /* Modifiers */, 03618C6D2C8267E600BCBC55 /* Note */, C9EE3E652A053CF1008A7491 /* NoteComposer */, @@ -2248,6 +2259,7 @@ 5BFBB28B2BD9D79F002E909F /* URLParser.swift in Sources */, C930055F2A6AF8320098CA9E /* LoadingContent.swift in Sources */, 5B79F6462BA11725002DA9BE /* WizardSheetVStack.swift in Sources */, + 04368D4B2C99CFC700DEAA2E /* ContentFlagView.swift in Sources */, C930E0572BA49DAD002B5776 /* GridPattern.swift in Sources */, C9A6C74D2AD98E2A001F9500 /* UNSNameTakenView.swift in Sources */, C92F015B2AC4D74E00972489 /* NosTextEditor.swift in Sources */, diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift new file mode 100644 index 000000000..53fa91d7b --- /dev/null +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -0,0 +1,23 @@ +import SwiftUI + +/// Displays pickers for selecting content flag option category, with additional stages shown based on previous selections. +struct ContentFlagView: View { + @Binding var selectedFlagOptionCategory: FlagOption? + var title: String + var subTitle: String? + + var body: some View { + VStack { + FlagOptionPickerView( + selectedFlag: $selectedFlagOptionCategory, + options: FlagOption.flagContentCategories, + title: title, + subTitle: subTitle + ) + } + } +} + +#Preview { + ContentFlagView(selectedFlagOptionCategory: .constant(nil), title: "Title") +} diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index 01b3571e3..8a520543e 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -52,9 +52,8 @@ struct ReportMenuModifier: ViewModifier { var subTitle = String(localized: .localizable.reportContentMessage) guard let userSelection = userSelection else { - return FlagOptionPickerView( - selectedFlag: $selectedFlagOption, - options: FlagOption.flagContentCategories, + return ContentFlagView( + selectedFlagOptionCategory: $selectedFlagOption, title: title, subTitle: subTitle ) @@ -66,9 +65,8 @@ struct ReportMenuModifier: ViewModifier { subTitle = String(localized: .localizable.reportContentMessage) } - return FlagOptionPickerView( - selectedFlag: $selectedFlagOption, - options: FlagOption.flagContentCategories, + return ContentFlagView( + selectedFlagOptionCategory: $selectedFlagOption, title: title, subTitle: subTitle ) From 54d2d39dbb9e0cd6de34ad872a32505dae5c2885 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Tue, 17 Sep 2024 16:14:53 +0100 Subject: [PATCH 08/19] fix swiftlint warning --- Nos/Views/Moderation/ContentFlagView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index 53fa91d7b..af5cf1e17 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -1,6 +1,7 @@ import SwiftUI -/// Displays pickers for selecting content flag option category, with additional stages shown based on previous selections. +/// Displays pickers for selecting content flag option category, with additional stages shown +/// based on previous selections. struct ContentFlagView: View { @Binding var selectedFlagOptionCategory: FlagOption? var title: String From 94555512373dfde4ed866160f571a0f238748213 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:07:49 +0100 Subject: [PATCH 09/19] update NosRadioButton --- ...oButtonView.swift => NosRadioButton.swift} | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) rename Nos/Views/Components/{NosRadioButtonView.swift => NosRadioButton.swift} (75%) diff --git a/Nos/Views/Components/NosRadioButtonView.swift b/Nos/Views/Components/NosRadioButton.swift similarity index 75% rename from Nos/Views/Components/NosRadioButtonView.swift rename to Nos/Views/Components/NosRadioButton.swift index e62c5d901..bfcf7d100 100644 --- a/Nos/Views/Components/NosRadioButtonView.swift +++ b/Nos/Views/Components/NosRadioButton.swift @@ -1,19 +1,19 @@ import SwiftUI /// A custom radio button. -struct NosRadioButtonView: View { +struct NosRadioButton: View { var isSelected: Bool var body: some View { ZStack { - RadioButtonBackgroundView() + RadioButtonBackground() if isSelected { - RadioButtonSelectorView() + RadioButtonSelectedIndicator() } } } } /// A custom background for a radio button. -struct RadioButtonBackgroundView: View { +private struct RadioButtonBackground: View { var body: some View { ZStack { Circle() @@ -48,24 +48,18 @@ struct RadioButtonBackgroundView: View { } /// A colorful selector (inner circle) of a radio button with a gradient fill. -struct RadioButtonSelectorView: View { +private struct RadioButtonSelectedIndicator: View { var body: some View { Circle() - .fill( - LinearGradient( - colors: [Color.radioButtonSelectorTop, Color.radioButtonSelectorBottom], - startPoint: .top, - endPoint: .bottom - ) - ) + .fill(LinearGradient.verticalAccentPrimary) .frame(width: 17, height: 17) } } #Preview("Selected") { - NosRadioButtonView(isSelected: true) + NosRadioButton(isSelected: true) } #Preview("Not Selected") { - NosRadioButtonView(isSelected: false) + NosRadioButton(isSelected: false) } From 7323d7d9c7e3bb2cd754dde4ce0bc5c3186d1ea1 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:08:29 +0100 Subject: [PATCH 10/19] update FlagOptionPicker --- Nos.xcodeproj/project.pbxproj | 37 ++++++++-------- ...ickerView.swift => FlagOptionPicker.swift} | 43 ++++++++----------- 2 files changed, 35 insertions(+), 45 deletions(-) rename Nos/Views/Components/{FlagOptionPickerView.swift => FlagOptionPicker.swift} (69%) diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 2a64eb093..685c9245b 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -111,9 +111,9 @@ 03FE3F8C2C87BC9500D25810 /* text_note_multiple_media.json in Resources */ = {isa = PBXBuildFile; fileRef = 03FE3F8A2C87BC9500D25810 /* text_note_multiple_media.json */; }; 042406F32C907A15008F2A21 /* NosToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042406F22C907A15008F2A21 /* NosToggle.swift */; }; 04368D2B2C99A2C400DEAA2E /* FlagOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */; }; - 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */; }; + 04368D312C99A78800DEAA2E /* NosRadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButton.swift */; }; 04368D4B2C99CFC700DEAA2E /* ContentFlagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */; }; - 0496D6312C975E6900D29375 /* FlagOptionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */; }; + 0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0496D6302C975E6900D29375 /* FlagOptionPicker.swift */; }; 2D06BB9D2AE249D70085F509 /* ThreadRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */; }; 2D4010A22AD87DF300F93AD4 /* KnownFollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */; }; 3A1C296F2B2A537C0020B753 /* Moderation.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */; }; @@ -141,13 +141,13 @@ 3FFB1D9729A6BBEC002A755D /* Collection+SafeSubscript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FFB1D9529A6BBEC002A755D /* Collection+SafeSubscript.swift */; }; 3FFB1D9C29A7DF9D002A755D /* StackedAvatarsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FFB1D9B29A7DF9D002A755D /* StackedAvatarsView.swift */; }; 3FFF3BD029A9645F00DD0B72 /* AuthorReference+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F43C47529A9625700E896A0 /* AuthorReference+CoreDataClass.swift */; }; + 500899F32C95C1F900834588 /* PushNotificationRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */; }; 50089A012C9712EF00834588 /* JSONEvent+Kinds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A002C9712EF00834588 /* JSONEvent+Kinds.swift */; }; 50089A022C9712EF00834588 /* JSONEvent+Kinds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A002C9712EF00834588 /* JSONEvent+Kinds.swift */; }; 50089A0C2C97182200834588 /* CurrentUser+PublishEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */; }; 50089A0D2C97182200834588 /* CurrentUser+PublishEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */; }; - 500899F32C95C1F900834588 /* PushNotificationRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */; }; - 502B6C3D2C9462A400446316 /* PushNotificationRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */; }; 50089A172C98678600834588 /* View+ListRowGradientBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A162C98678600834588 /* View+ListRowGradientBackground.swift */; }; + 502B6C3D2C9462A400446316 /* PushNotificationRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */; }; 5044546E2C90726A00251A7E /* Event+Fetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546D2C90726A00251A7E /* Event+Fetching.swift */; }; 504454702C90728500251A7E /* Event+Hydration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546F2C90728500251A7E /* Event+Hydration.swift */; }; 504454712C90728E00251A7E /* Event+Fetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546D2C90726A00251A7E /* Event+Fetching.swift */; }; @@ -652,9 +652,9 @@ 03FE3F8A2C87BC9500D25810 /* text_note_multiple_media.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = text_note_multiple_media.json; sourceTree = ""; }; 042406F22C907A15008F2A21 /* NosToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosToggle.swift; sourceTree = ""; }; 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOption.swift; sourceTree = ""; }; - 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButtonView.swift; sourceTree = ""; }; + 04368D302C99A78800DEAA2E /* NosRadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButton.swift; sourceTree = ""; }; 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFlagView.swift; sourceTree = ""; }; - 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOptionPickerView.swift; sourceTree = ""; }; + 0496D6302C975E6900D29375 /* FlagOptionPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOptionPicker.swift; sourceTree = ""; }; 2D06BB9C2AE249D70085F509 /* ThreadRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadRootView.swift; sourceTree = ""; }; 2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KnownFollowersView.swift; sourceTree = ""; }; 3A1C296E2B2A537C0020B753 /* Moderation.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Moderation.xcstrings; sourceTree = ""; }; @@ -677,8 +677,8 @@ 3FFB1D9B29A7DF9D002A755D /* StackedAvatarsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackedAvatarsView.swift; sourceTree = ""; }; 50089A002C9712EF00834588 /* JSONEvent+Kinds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONEvent+Kinds.swift"; sourceTree = ""; }; 50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CurrentUser+PublishEvents.swift"; sourceTree = ""; }; - 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationRegistrar.swift; sourceTree = ""; }; 50089A162C98678600834588 /* View+ListRowGradientBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ListRowGradientBackground.swift"; sourceTree = ""; }; + 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationRegistrar.swift; sourceTree = ""; }; 5044546D2C90726A00251A7E /* Event+Fetching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Event+Fetching.swift"; sourceTree = ""; }; 5044546F2C90728500251A7E /* Event+Hydration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Event+Hydration.swift"; sourceTree = ""; }; 5045540C2C81E10C0044ECAE /* EditableAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableAvatarView.swift; sourceTree = ""; }; @@ -1394,21 +1394,21 @@ path = NostrIdentifier; sourceTree = ""; }; - 04368D542C99D32B00DEAA2E /* Moderation */ = { + 03E7118B2C936DE5000B6F96 /* OpenGraph */ = { isa = PBXGroup; children = ( - 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */, + 03E711802C936DD1000B6F96 /* OpenGraphParser.swift */, + 03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */, ); - path = Moderation; + path = OpenGraph; sourceTree = ""; }; - 03E7118B2C936DE5000B6F96 /* OpenGraph */ = { + 04368D542C99D32B00DEAA2E /* Moderation */ = { isa = PBXGroup; children = ( - 03E711802C936DD1000B6F96 /* OpenGraphParser.swift */, - 03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */, + 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */, ); - path = OpenGraph; + path = Moderation; sourceTree = ""; }; 3AAB61B12B24CC8A00717A07 /* Extensions */ = { @@ -1475,7 +1475,7 @@ 3FFB1D88299FF37C002A755D /* AvatarView.swift */, C95D68A0299E6D3E00429F86 /* BioView.swift */, C9DFA968299BEC33006929C1 /* CardStyle.swift */, - 0496D6302C975E6900D29375 /* FlagOptionPickerView.swift */, + 0496D6302C975E6900D29375 /* FlagOptionPicker.swift */, C9B678E629F01A8500303F33 /* FullscreenProgressView.swift */, C9CDBBA329A8FA2900C555C7 /* GoldenPostView.swift */, C930E0562BA49DAD002B5776 /* GridPattern.swift */, @@ -1496,7 +1496,7 @@ 3F60F42829B27D3E000D62C4 /* ThreadView.swift */, C913DA0D2AEB3265003BDD6D /* WarningView.swift */, C9CE5B132A0172CF008E198C /* WebView.swift */, - 04368D302C99A78800DEAA2E /* NosRadioButtonView.swift */, + 04368D302C99A78800DEAA2E /* NosRadioButton.swift */, 03618C642C8267A900BCBC55 /* Author */, 03618C232C82668600BCBC55 /* Button */, 03618C7E2C82685500BCBC55 /* Event */, @@ -1834,7 +1834,6 @@ 5B6EB48D29EDBE0E006E750C /* NoteParser.swift */, C9AC31AC2A55E0BD00A94E5A /* NotificationViewModel.swift */, C9CF23162A38A58B00EBEC31 /* ParseQueue.swift */, - 5BCA95D12C8A5F0D00A52D1A /* PreviewEventRepository.swift */, C9F0BB6A29A503D6000547FC /* PublicKey.swift */, C96D39262B61B6D200D3D0A1 /* RawNostrID.swift */, C9C2B78429E073E300548B4A /* RelaySubscription.swift */, @@ -2275,7 +2274,7 @@ C987F81A29BA4D0E00B44E7A /* ActionButton.swift in Sources */, C9E37E122A1E7EC5003D4B0A /* PreviewContainer.swift in Sources */, C9A0DAF829C92F4500466635 /* UNSAPI.swift in Sources */, - 04368D312C99A78800DEAA2E /* NosRadioButtonView.swift in Sources */, + 04368D312C99A78800DEAA2E /* NosRadioButton.swift in Sources */, 5B79F60B2B98ACA0002DA9BE /* PickYourUsernameSheet.swift in Sources */, 5BFF66B62A58A8A000AA79DD /* MutesView.swift in Sources */, C913DA0A2AEAF52B003BDD6D /* NoteWarningController.swift in Sources */, @@ -2329,7 +2328,7 @@ C9EE3E632A053910008A7491 /* ExpirationTimeOption.swift in Sources */, C9A0DAE029C697A100466635 /* AboutView.swift in Sources */, C9E8C1132B081E9C002D46B0 /* UNSNameView.swift in Sources */, - 0496D6312C975E6900D29375 /* FlagOptionPickerView.swift in Sources */, + 0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */, A351E1A229BA92240009B7F6 /* ProfileEditView.swift in Sources */, C9DFA969299BEC33006929C1 /* CardStyle.swift in Sources */, C95D68AD299E721700429F86 /* ProfileView.swift in Sources */, diff --git a/Nos/Views/Components/FlagOptionPickerView.swift b/Nos/Views/Components/FlagOptionPicker.swift similarity index 69% rename from Nos/Views/Components/FlagOptionPickerView.swift rename to Nos/Views/Components/FlagOptionPicker.swift index 88491abe1..3fe8b0722 100644 --- a/Nos/Views/Components/FlagOptionPickerView.swift +++ b/Nos/Views/Components/FlagOptionPicker.swift @@ -1,47 +1,38 @@ import SwiftUI /// Displays a list of selectable flag options -struct FlagOptionPickerView: View { - @Binding private var selectedFlag: FlagOption? +struct FlagOptionPicker: View { + @Binding private var selectedOption: FlagOption? var options: [FlagOption] var title: String var subTitle: String? - init(selectedFlag: Binding, options: [FlagOption], title: String, subTitle: String?) { - self._selectedFlag = selectedFlag + init(selectedOption: Binding, options: [FlagOption], title: String, subTitle: String?) { + self._selectedOption = selectedOption self.options = options self.title = title self.subTitle = subTitle } var body: some View { - ScrollView { - VStack(alignment: .leading) { - HeaderView(text: title) - - if let subTitle = subTitle { - HeaderView(text: subTitle) - } - flagOptionsListView + VStack(alignment: .leading) { + HeaderView(text: title) + + if let subTitle = subTitle { + HeaderView(text: subTitle) } - .padding() + flagOptionsListView } - .background(Color.appBg) + .padding() } private var flagOptionsListView: some View { VStack(alignment: .leading) { ForEach(options) { flag in - FlagPickerRow(flag: flag, selection: $selectedFlag) + FlagPickerRow(flag: flag, selection: $selectedOption) BeveledSeparator() } } - .background( - LinearGradient( - colors: [Color.cardBgTop, Color.cardBgBottom], - startPoint: .top, - endPoint: .bottom - ) - ) + .background(LinearGradient.cardBackground) .clipShape(RoundedRectangle(cornerRadius: 15)) } } @@ -75,7 +66,7 @@ struct FlagPickerRow: View { Button { selection = flag } label: { - NosRadioButtonView(isSelected: isSelected) + NosRadioButton(isSelected: isSelected) } } .padding(12) @@ -93,13 +84,13 @@ private struct HeaderView: View { } } -struct FlagOptionPickerView_Previews: PreviewProvider { +struct FlagOptionPicker_Previews: PreviewProvider { struct PreviewWrapper: View { @State private var selectedFlag: FlagOption? var body: some View { - FlagOptionPickerView( - selectedFlag: $selectedFlag, + FlagOptionPicker( + selectedOption: $selectedFlag, options: FlagOption.flagContentCategories, title: "Create a tag for this content that other people in your network can see.", subTitle: "Select a tag for the content" From f094723339d0ba52f08b95a22b27374c5c15bc09 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:08:48 +0100 Subject: [PATCH 11/19] update ContentFlagView --- Nos/Views/Moderation/ContentFlagView.swift | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index af5cf1e17..db9f8d341 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -8,14 +8,17 @@ struct ContentFlagView: View { var subTitle: String? var body: some View { - VStack { - FlagOptionPickerView( - selectedFlag: $selectedFlagOptionCategory, - options: FlagOption.flagContentCategories, - title: title, - subTitle: subTitle - ) + ScrollView { + VStack { + FlagOptionPickerView( + selectedFlag: $selectedFlagOptionCategory, + options: FlagOption.flagContentCategories, + title: title, + subTitle: subTitle + ) + } } + .background(Color.appBg) } } From 557caaaffa5e0fa6ac91462808ee59f8fdb77afc Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:23:40 +0100 Subject: [PATCH 12/19] update view name --- Nos/Views/Moderation/ContentFlagView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index db9f8d341..20c650c37 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -10,8 +10,8 @@ struct ContentFlagView: View { var body: some View { ScrollView { VStack { - FlagOptionPickerView( - selectedFlag: $selectedFlagOptionCategory, + FlagOptionPicker( + selectedOption: $selectedFlagOptionCategory, options: FlagOption.flagContentCategories, title: title, subTitle: subTitle From 701f99d7d69dee5e5dd7c3ca5219743c490dffab Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:43:08 +0100 Subject: [PATCH 13/19] fix copy changes --- Nos/Views/Components/FlagOptionPicker.swift | 14 +++++++------- Nos/Views/Moderation/ContentFlagView.swift | 4 ++-- Nos/Views/Modifiers/ReportMenuModifier.swift | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Nos/Views/Components/FlagOptionPicker.swift b/Nos/Views/Components/FlagOptionPicker.swift index 3fe8b0722..738346c1e 100644 --- a/Nos/Views/Components/FlagOptionPicker.swift +++ b/Nos/Views/Components/FlagOptionPicker.swift @@ -4,21 +4,21 @@ struct FlagOptionPicker: View { @Binding private var selectedOption: FlagOption? var options: [FlagOption] var title: String - var subTitle: String? + var subtitle: String? - init(selectedOption: Binding, options: [FlagOption], title: String, subTitle: String?) { + init(selectedOption: Binding, options: [FlagOption], title: String, subtitle: String?) { self._selectedOption = selectedOption self.options = options self.title = title - self.subTitle = subTitle + self.subtitle = subtitle } var body: some View { VStack(alignment: .leading) { HeaderView(text: title) - if let subTitle = subTitle { - HeaderView(text: subTitle) + if let subtitle = subtitle { + HeaderView(text: subtitle) } flagOptionsListView } @@ -37,7 +37,7 @@ struct FlagOptionPicker: View { } } -/// A single row for a single flag option +/// A single row for a single flag option struct FlagPickerRow: View { var flag: FlagOption @Binding var selection: FlagOption? @@ -93,7 +93,7 @@ struct FlagOptionPicker_Previews: PreviewProvider { selectedOption: $selectedFlag, options: FlagOption.flagContentCategories, title: "Create a tag for this content that other people in your network can see.", - subTitle: "Select a tag for the content" + subtitle: "Select a tag for the content" ) .onAppear { selectedFlag = FlagOption.flagContentCategories.first diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index 20c650c37..8ec74af60 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -5,7 +5,7 @@ import SwiftUI struct ContentFlagView: View { @Binding var selectedFlagOptionCategory: FlagOption? var title: String - var subTitle: String? + var subtitle: String? var body: some View { ScrollView { @@ -14,7 +14,7 @@ struct ContentFlagView: View { selectedOption: $selectedFlagOptionCategory, options: FlagOption.flagContentCategories, title: title, - subTitle: subTitle + subtitle: subtitle ) } } diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index 8a520543e..c5c6d4c79 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -49,26 +49,26 @@ struct ReportMenuModifier: ViewModifier { /// - Returns: A view containing the flag option picker for the current selection. private func flagOptionPickerForSelection(_ userSelection: UserSelection?) -> some View { var title = String(localized: .localizable.reportContent) - var subTitle = String(localized: .localizable.reportContentMessage) + var subtitle = String(localized: .localizable.reportContentMessage) guard let userSelection = userSelection else { return ContentFlagView( selectedFlagOptionCategory: $selectedFlagOption, title: title, - subTitle: subTitle + subtitle: subtitle ) } switch userSelection { default: title = String(localized: .localizable.reportContent) - subTitle = String(localized: .localizable.reportContentMessage) + subtitle = String(localized: .localizable.reportContentMessage) } return ContentFlagView( selectedFlagOptionCategory: $selectedFlagOption, title: title, - subTitle: subTitle + subtitle: subtitle ) } From c386970ec5d4706fa760f7cee6fb70db3fb9431b Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 16:45:54 +0100 Subject: [PATCH 14/19] use new preview syntax --- Nos/Views/Components/FlagOptionPicker.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Nos/Views/Components/FlagOptionPicker.swift b/Nos/Views/Components/FlagOptionPicker.swift index 738346c1e..a6722c288 100644 --- a/Nos/Views/Components/FlagOptionPicker.swift +++ b/Nos/Views/Components/FlagOptionPicker.swift @@ -84,7 +84,7 @@ private struct HeaderView: View { } } -struct FlagOptionPicker_Previews: PreviewProvider { +#Preview { struct PreviewWrapper: View { @State private var selectedFlag: FlagOption? @@ -101,8 +101,5 @@ struct FlagOptionPicker_Previews: PreviewProvider { .background(Color.appBg) } } - - static var previews: some View { - PreviewWrapper() - } + return PreviewWrapper() } From 13a20ce59a74d1d7c9ba78f69877e008f8620c38 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Wed, 18 Sep 2024 22:07:12 +0100 Subject: [PATCH 15/19] remove redundant code --- Nos/Views/Moderation/ContentFlagView.swift | 8 ++--- Nos/Views/Modifiers/ReportMenuModifier.swift | 32 ++------------------ 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index 8ec74af60..dbf7da6cc 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -4,8 +4,6 @@ import SwiftUI /// based on previous selections. struct ContentFlagView: View { @Binding var selectedFlagOptionCategory: FlagOption? - var title: String - var subtitle: String? var body: some View { ScrollView { @@ -13,8 +11,8 @@ struct ContentFlagView: View { FlagOptionPicker( selectedOption: $selectedFlagOptionCategory, options: FlagOption.flagContentCategories, - title: title, - subtitle: subtitle + title: String(localized: .localizable.reportContent), + subtitle: String(localized: .localizable.reportContentMessage) ) } } @@ -23,5 +21,5 @@ struct ContentFlagView: View { } #Preview { - ContentFlagView(selectedFlagOptionCategory: .constant(nil), title: "Title") + ContentFlagView(selectedFlagOptionCategory: .constant(nil)) } diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index c5c6d4c79..7edd42d40 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -37,40 +37,14 @@ struct ReportMenuModifier: ViewModifier { case .note: content .sheet(isPresented: $isPresented) { - flagOptionPickerForSelection(userSelection) + ContentFlagView( + selectedFlagOptionCategory: $selectedFlagOption + ) } case .author: oldModerationFlow(content: content) } } - - /// Provides the flag option picker based on the user's selection. - /// - Parameter userSelection: The optional user selection that determines the flagging options. - /// - Returns: A view containing the flag option picker for the current selection. - private func flagOptionPickerForSelection(_ userSelection: UserSelection?) -> some View { - var title = String(localized: .localizable.reportContent) - var subtitle = String(localized: .localizable.reportContentMessage) - - guard let userSelection = userSelection else { - return ContentFlagView( - selectedFlagOptionCategory: $selectedFlagOption, - title: title, - subtitle: subtitle - ) - } - - switch userSelection { - default: - title = String(localized: .localizable.reportContent) - subtitle = String(localized: .localizable.reportContentMessage) - } - - return ContentFlagView( - selectedFlagOptionCategory: $selectedFlagOption, - title: title, - subtitle: subtitle - ) - } // swiftlint:disable function_body_length @ViewBuilder From ffddb13074958c01fa695c061e607bb217dc20f1 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Thu, 19 Sep 2024 09:56:32 -0400 Subject: [PATCH 16/19] remove stray localizable string --- Nos/Assets/Localization/Localizable.xcstrings | 3 --- 1 file changed, 3 deletions(-) diff --git a/Nos/Assets/Localization/Localizable.xcstrings b/Nos/Assets/Localization/Localizable.xcstrings index 6c717fed9..886fe3e60 100644 --- a/Nos/Assets/Localization/Localizable.xcstrings +++ b/Nos/Assets/Localization/Localizable.xcstrings @@ -5508,9 +5508,6 @@ } } }, - "Key" : { - "extractionState" : "manual" - }, "keys" : { "extractionState" : "manual", "localizations" : { From 16f06c0447e6ca946b2e950b3b72f6b25058d546 Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Thu, 19 Sep 2024 17:05:38 +0100 Subject: [PATCH 17/19] make entire row clickable --- Nos/Views/Components/FlagOptionPicker.swift | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Nos/Views/Components/FlagOptionPicker.swift b/Nos/Views/Components/FlagOptionPicker.swift index a6722c288..ec78c17d9 100644 --- a/Nos/Views/Components/FlagOptionPicker.swift +++ b/Nos/Views/Components/FlagOptionPicker.swift @@ -47,6 +47,15 @@ struct FlagPickerRow: View { } var body: some View { + Button(action: { + selection = flag + }, label: { + buttonLabel + }) + .padding(14) + } + + private var buttonLabel: some View { HStack(alignment: .center) { VStack(alignment: .leading, spacing: 8) { Text(flag.title) @@ -56,20 +65,15 @@ struct FlagPickerRow: View { if let description = flag.description { Text(description) .foregroundColor(.secondaryTxt) + .multilineTextAlignment(.leading) .font(.clarity(.regular, textStyle: .footnote)) .lineSpacing(8) } } - Spacer() - Button { - selection = flag - } label: { - NosRadioButton(isSelected: isSelected) - } + NosRadioButton(isSelected: isSelected) } - .padding(12) } } From 78cce9b2e4b1aeafddec7ff1e3bd31193269332d Mon Sep 17 00:00:00 2001 From: Itunu Raimi Date: Thu, 19 Sep 2024 17:06:07 +0100 Subject: [PATCH 18/19] update category strings --- Nos/Assets/Localization/Localizable.xcstrings | 22 +++++++++++++++++++ Nos/Views/Moderation/ContentFlagView.swift | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Nos/Assets/Localization/Localizable.xcstrings b/Nos/Assets/Localization/Localizable.xcstrings index 886fe3e60..209691122 100644 --- a/Nos/Assets/Localization/Localizable.xcstrings +++ b/Nos/Assets/Localization/Localizable.xcstrings @@ -4350,6 +4350,28 @@ } } }, + "flagContentCategoryDescription" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Select a tag for the content" + } + } + } + }, + "flagContentCategoryTitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Create a content flag for this post that other users in the network can see." + } + } + } + }, "flagContentHarassmentDescription" : { "extractionState" : "manual", "localizations" : { diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index dbf7da6cc..4b83a428f 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -11,8 +11,8 @@ struct ContentFlagView: View { FlagOptionPicker( selectedOption: $selectedFlagOptionCategory, options: FlagOption.flagContentCategories, - title: String(localized: .localizable.reportContent), - subtitle: String(localized: .localizable.reportContentMessage) + title: String(localized: .localizable.flagContentCategoryTitle), + subtitle: String(localized: .localizable.flagContentCategoryDescription) ) } } From b4c9bbe4fa63cc226af1f27ae7bcf6d7170e0586 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Thu, 19 Sep 2024 16:41:23 -0400 Subject: [PATCH 19/19] fix spacing issue in FlagOptionsPicker --- Nos/Views/Components/FlagOptionPicker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nos/Views/Components/FlagOptionPicker.swift b/Nos/Views/Components/FlagOptionPicker.swift index ec78c17d9..3ca54f68b 100644 --- a/Nos/Views/Components/FlagOptionPicker.swift +++ b/Nos/Views/Components/FlagOptionPicker.swift @@ -26,7 +26,7 @@ struct FlagOptionPicker: View { } private var flagOptionsListView: some View { - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 0) { ForEach(options) { flag in FlagPickerRow(flag: flag, selection: $selectedOption) BeveledSeparator()