From 3ca243fb0f89c9734aec49dc07f1acdf35042f21 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Thu, 18 Jan 2024 21:12:49 +0000 Subject: [PATCH 01/10] Update APILocalSite.swift --- Mlem/API/Models/Site/APILocalSite.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mlem/API/Models/Site/APILocalSite.swift b/Mlem/API/Models/Site/APILocalSite.swift index d48a42ef5..45ca01c9e 100644 --- a/Mlem/API/Models/Site/APILocalSite.swift +++ b/Mlem/API/Models/Site/APILocalSite.swift @@ -23,7 +23,7 @@ struct APILocalSite: Decodable { // let legalInformation: String? // let hideModlogModNames: Bool // let applicationEmailAdmins: Bool -// let slurFilterRegex: String? + let slurFilterRegex: String? // let actorNameMaxLength: Int // let federationEnabled: Bool // let federationDebug: Bool From 6993c0edc6cf2bad700012b04110ad008e8badaa Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Thu, 18 Jan 2024 21:30:25 +0000 Subject: [PATCH 02/10] update --- Mlem/Models/Trackers/SiteInformationTracker.swift | 6 ++++++ Mlem/Views/Shared/Composer/PostComposerView.swift | 2 ++ 2 files changed, 8 insertions(+) diff --git a/Mlem/Models/Trackers/SiteInformationTracker.swift b/Mlem/Models/Trackers/SiteInformationTracker.swift index 0fd58be25..0edce7d16 100644 --- a/Mlem/Models/Trackers/SiteInformationTracker.swift +++ b/Mlem/Models/Trackers/SiteInformationTracker.swift @@ -18,6 +18,7 @@ class SiteInformationTracker: ObservableObject { @Published var version: SiteVersion? @Published private(set) var allLanguages: [APILanguage] = .init() @Published var myUserInfo: APIMyUserInfo? + @Published var slurFilterRegex: Regex? func load(account: SavedAccount) { version = account.siteVersion @@ -35,6 +36,11 @@ class SiteInformationTracker: ObservableObject { } myUserInfo = response.myUser allLanguages = response.allLanguages + + print("REGEX", response.siteView.localSite.slurFilterRegex) + if let regex = response.siteView.localSite.slurFilterRegex { + slurFilterRegex = try .init(regex) + } } catch { errorHandler.handle(error) } diff --git a/Mlem/Views/Shared/Composer/PostComposerView.swift b/Mlem/Views/Shared/Composer/PostComposerView.swift index 1a3bd0daf..4af73a282 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView.swift @@ -63,6 +63,8 @@ struct PostComposerView: View { self._postBody = State(initialValue: editModel.editPost?.post.body ?? "") self._isNSFW = State(initialValue: editModel.editPost?.post.nsfw ?? false) self._attachmentModel = StateObject(wrappedValue: .init(url: editModel.editPost?.post.linkUrl?.description ?? "")) + + print(siteInformation.slurFilterRegex) } var body: some View { From 0c538dbeeaef2190baaf9f4fa31952357e4f5dd4 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:14:56 +0000 Subject: [PATCH 03/10] Update --- .../Trackers/SiteInformationTracker.swift | 4 +- .../Composer/PostComposerView+Logic.swift | 2 +- .../Shared/Composer/PostComposerView.swift | 81 ++++++++++++++----- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/Mlem/Models/Trackers/SiteInformationTracker.swift b/Mlem/Models/Trackers/SiteInformationTracker.swift index 0edce7d16..905463140 100644 --- a/Mlem/Models/Trackers/SiteInformationTracker.swift +++ b/Mlem/Models/Trackers/SiteInformationTracker.swift @@ -18,9 +18,10 @@ class SiteInformationTracker: ObservableObject { @Published var version: SiteVersion? @Published private(set) var allLanguages: [APILanguage] = .init() @Published var myUserInfo: APIMyUserInfo? - @Published var slurFilterRegex: Regex? + @Published var slurFilterRegex: Regex? func load(account: SavedAccount) { + version = account.siteVersion Task { do { @@ -41,6 +42,7 @@ class SiteInformationTracker: ObservableObject { if let regex = response.siteView.localSite.slurFilterRegex { slurFilterRegex = try .init(regex) } + } catch { errorHandler.handle(error) } diff --git a/Mlem/Views/Shared/Composer/PostComposerView+Logic.swift b/Mlem/Views/Shared/Composer/PostComposerView+Logic.swift index c1186399c..a73a3eeef 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView+Logic.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView+Logic.swift @@ -17,7 +17,7 @@ extension PostComposerView { var isReadyToPost: Bool { switch attachmentModel.imageModel?.state { case nil, .uploaded: - return postTitle.trimmed.isNotEmpty + return postTitle.trimmed.isNotEmpty && titleSlurMatch == nil && bodySlurMatch == nil default: return false } diff --git a/Mlem/Views/Shared/Composer/PostComposerView.swift b/Mlem/Views/Shared/Composer/PostComposerView.swift index 4af73a282..3f5ab19ac 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView.swift @@ -19,6 +19,7 @@ extension HorizontalAlignment { static let labelStart = HorizontalAlignment(LabelStart.self) } +// swiftlint:disable type_body_length struct PostComposerView: View { private enum Field: Hashable { case title, url, body @@ -55,6 +56,9 @@ struct PostComposerView: View { @FocusState private var focusedField: Field? + @State var titleSlurMatch: String? + @State var bodySlurMatch: String? + init(editModel: PostEditorModel) { self.postTracker = editModel.postTracker self.editModel = editModel @@ -63,8 +67,6 @@ struct PostComposerView: View { self._postBody = State(initialValue: editModel.editPost?.post.body ?? "") self._isNSFW = State(initialValue: editModel.editPost?.post.nsfw ?? false) self._attachmentModel = StateObject(wrappedValue: .init(url: editModel.editPost?.post.linkUrl?.description ?? "")) - - print(siteInformation.slurFilterRegex) } var body: some View { @@ -77,22 +79,7 @@ struct PostComposerView: View { .edgesIgnoringSafeArea(.bottom) VStack(spacing: 0) { // Community Row - HStack { - CommunityLabelView( - community: editModel.community, - serverInstanceLocation: .bottom, - overrideShowAvatar: true - ) - Spacer() - if let person = siteInformation.myUserInfo?.localUserView.person { - UserLabelView( - person: person, - serverInstanceLocation: .bottom, - overrideShowAvatar: true - ) - .environment(\.layoutDirection, layoutDirection == .leftToRight ? .rightToLeft : .leftToRight) - } - } + headerView .padding(.bottom, 15) .padding(.horizontal) .zIndex(1) @@ -107,6 +94,19 @@ struct PostComposerView: View { } .padding(.top) .padding(.horizontal) + .onChange(of: postTitle) { newValue in + do { + if let regex = siteInformation.slurFilterRegex { + if let output = try regex.firstMatch(in: newValue.lowercased()) { + titleSlurMatch = String(newValue[output.range]) + } else { + titleSlurMatch = nil + } + } + } catch { + print("REGEX FAILED") + } + } if attachmentModel.imageModel != nil || attachmentModel.url.isNotEmpty { VStack { @@ -191,6 +191,19 @@ struct PostComposerView: View { .accessibilityLabel("Post Body") .focused($focusedField, equals: .body) .padding(.horizontal) + .onChange(of: postBody) { newValue in + do { + if let regex = siteInformation.slurFilterRegex { + if let output = try regex.firstMatch(in: newValue.lowercased()) { + bodySlurMatch = String(newValue[output.range]) + } else { + bodySlurMatch = nil + } + } + } catch { + print("REGEX FAILED") + } + } Spacer() } @@ -267,4 +280,36 @@ struct PostComposerView: View { .navigationBarColor() .navigationBarTitleDisplayMode(.inline) } + + @ViewBuilder + var headerView: some View { + HStack { + CommunityLabelView( + community: editModel.community, + serverInstanceLocation: .bottom, + overrideShowAvatar: true + ) + Spacer() + if let person = siteInformation.myUserInfo?.localUserView.person { + UserLabelView( + person: person, + serverInstanceLocation: .bottom, + overrideShowAvatar: true + ) + .environment(\.layoutDirection, layoutDirection == .leftToRight ? .rightToLeft : .leftToRight) + } + } + .overlay { + if let slurMatch = titleSlurMatch == nil ? bodySlurMatch : titleSlurMatch { + ZStack { + Capsule() + .fill(.red) + Text("\"\(slurMatch)\" is disallowed.") + } + .padding(-2) + } + } + .animation(.default, value: titleSlurMatch == nil && bodySlurMatch == nil) + } } +// swiftlint:enable type_body_length From dc69919e7ae78ba24de9f6e3f305b2be63307392 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:02:22 +0000 Subject: [PATCH 04/10] Update --- .../Components/Image Upload/LinkAttachmentModel.swift | 2 +- Mlem/Views/Shared/Composer/ResponseEditorView.swift | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Mlem/Views/Shared/Components/Image Upload/LinkAttachmentModel.swift b/Mlem/Views/Shared/Components/Image Upload/LinkAttachmentModel.swift index 338f7a470..5da57fb92 100644 --- a/Mlem/Views/Shared/Components/Image Upload/LinkAttachmentModel.swift +++ b/Mlem/Views/Shared/Components/Image Upload/LinkAttachmentModel.swift @@ -145,10 +145,10 @@ class LinkAttachmentModel: ObservableObject { if let task = self.uploadTask { task.cancel() } + self.photosPickerItem = nil switch self.imageModel?.state { case .uploaded(file: let file): if let file = file { - self.photosPickerItem = nil Task { do { if let compareUrl { diff --git a/Mlem/Views/Shared/Composer/ResponseEditorView.swift b/Mlem/Views/Shared/Composer/ResponseEditorView.swift index 0aebea587..4b4ae5f17 100644 --- a/Mlem/Views/Shared/Composer/ResponseEditorView.swift +++ b/Mlem/Views/Shared/Composer/ResponseEditorView.swift @@ -33,15 +33,7 @@ struct ResponseEditorView: View { private var isReadyToReply: Bool { editorBody.trimmed.isNotEmpty } - - func uploadImage() { - if editorModel.canUpload { - print("Uploading") - } else { - print("Uploading disabled for this sort of response") - } - } - + var body: some View { ScrollView { VStack(spacing: AppConstants.postAndCommentSpacing) { From 1866825930c820e299b6cc5ca1a7d31067f8f53a Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:12:22 +0000 Subject: [PATCH 05/10] Remove debug print --- Mlem/Models/Trackers/SiteInformationTracker.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Mlem/Models/Trackers/SiteInformationTracker.swift b/Mlem/Models/Trackers/SiteInformationTracker.swift index 905463140..2e51fce6e 100644 --- a/Mlem/Models/Trackers/SiteInformationTracker.swift +++ b/Mlem/Models/Trackers/SiteInformationTracker.swift @@ -38,7 +38,6 @@ class SiteInformationTracker: ObservableObject { myUserInfo = response.myUser allLanguages = response.allLanguages - print("REGEX", response.siteView.localSite.slurFilterRegex) if let regex = response.siteView.localSite.slurFilterRegex { slurFilterRegex = try .init(regex) } From ec06fd8f882bb68122a0645e13d2e35fcb4ee2e3 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 20 Jan 2024 21:40:22 +0000 Subject: [PATCH 06/10] tweaks --- Mlem/Views/Shared/Composer/PostComposerView.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mlem/Views/Shared/Composer/PostComposerView.swift b/Mlem/Views/Shared/Composer/PostComposerView.swift index 3f5ab19ac..0bb43dbdf 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView.swift @@ -113,11 +113,12 @@ struct PostComposerView: View { let url = URL(string: attachmentModel.url) if !(url?.isImage ?? true) { HStack(spacing: AppConstants.postAndCommentSpacing) { - Image(systemName: "link") + Image(systemName: Icons.websiteAddress) .foregroundStyle(.blue) Text(attachmentModel.url) .foregroundStyle(.secondary) .lineLimit(1) + Spacer() Button(action: attachmentModel.removeLinkAction, label: { Image(systemName: Icons.close) .fontWeight(.semibold) @@ -255,7 +256,7 @@ struct PostComposerView: View { } ToolbarItem(placement: .navigationBarTrailing) { LinkUploadOptionsView(model: attachmentModel) { - Label("Attach image or link", systemImage: "link") + Label("Attach Image or Link", systemImage: Icons.websiteAddress) } .disabled(attachmentModel.imageModel != nil || attachmentModel.url.isNotEmpty) } From d9f548717f8db31957071184c2f00895c8ce506c Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 20 Jan 2024 21:42:16 +0000 Subject: [PATCH 07/10] Tweak --- Mlem/Views/Shared/Composer/PostComposerView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Mlem/Views/Shared/Composer/PostComposerView.swift b/Mlem/Views/Shared/Composer/PostComposerView.swift index 0bb43dbdf..2f5f03894 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView.swift @@ -115,6 +115,7 @@ struct PostComposerView: View { HStack(spacing: AppConstants.postAndCommentSpacing) { Image(systemName: Icons.websiteAddress) .foregroundStyle(.blue) + .padding(.leading, 5) Text(attachmentModel.url) .foregroundStyle(.secondary) .lineLimit(1) From 78d26ca0e6beed6cc66b3e301a4c1ee58ab188ed Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 27 Jan 2024 17:32:26 +0000 Subject: [PATCH 08/10] Show filter for comments --- .../EditorModelProtocol.swift | 2 ++ .../Editors/CommentEditor.swift | 1 + .../Replies/ReplyToComment.swift | 1 + .../Replies/ReplyToCommentReply.swift | 1 + .../Replies/ReplyToMention.swift | 1 + .../Replies/ReplyToMessage.swift | 1 + .../Replies/ReplyToPost.swift | 1 + .../Reports/ReportComment.swift | 1 + .../Reports/ReportCommentReply.swift | 1 + .../Reports/ReportMention.swift | 1 + .../Reports/ReportMessage.swift | 1 + .../Reports/ReportPost.swift | 1 + .../Shared/Composer/ResponseEditorView.swift | 36 ++++++++++++++++++- 13 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Mlem/Models/Composers/Response Composers/EditorModelProtocol.swift b/Mlem/Models/Composers/Response Composers/EditorModelProtocol.swift index c26e8d857..c42b904d0 100644 --- a/Mlem/Models/Composers/Response Composers/EditorModelProtocol.swift +++ b/Mlem/Models/Composers/Response Composers/EditorModelProtocol.swift @@ -16,6 +16,8 @@ protocol ResponseEditorModel: Identifiable { var modalName: String { get } // what to title the modal + var showSlurWarning: Bool { get } + var prefillContents: String? { get } // optional, contents to prepopulate the editor with func embeddedView() -> AnyView diff --git a/Mlem/Models/Composers/Response Composers/Editors/CommentEditor.swift b/Mlem/Models/Composers/Response Composers/Editors/CommentEditor.swift index b2b092f94..db116500a 100644 --- a/Mlem/Models/Composers/Response Composers/Editors/CommentEditor.swift +++ b/Mlem/Models/Composers/Response Composers/Editors/CommentEditor.swift @@ -13,6 +13,7 @@ struct CommentEditor: ResponseEditorModel { @Dependency(\.commentRepository) var commentRepository let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "Edit Comment" var prefillContents: String? { comment.comment.content } let comment: APICommentView diff --git a/Mlem/Models/Composers/Response Composers/Replies/ReplyToComment.swift b/Mlem/Models/Composers/Response Composers/Replies/ReplyToComment.swift index 60438090b..0c6fda164 100644 --- a/Mlem/Models/Composers/Response Composers/Replies/ReplyToComment.swift +++ b/Mlem/Models/Composers/Response Composers/Replies/ReplyToComment.swift @@ -14,6 +14,7 @@ struct ReplyToComment: ResponseEditorModel { var id: Int { comment.id } let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "New Comment" let comment: APICommentView let prefillContents: String? diff --git a/Mlem/Models/Composers/Response Composers/Replies/ReplyToCommentReply.swift b/Mlem/Models/Composers/Response Composers/Replies/ReplyToCommentReply.swift index cbf8aac44..a690d4673 100644 --- a/Mlem/Models/Composers/Response Composers/Replies/ReplyToCommentReply.swift +++ b/Mlem/Models/Composers/Response Composers/Replies/ReplyToCommentReply.swift @@ -13,6 +13,7 @@ struct ReplyToCommentReply: ResponseEditorModel { @Dependency(\.commentRepository) var commentRepository let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "New Comment" let prefillContents: String? = nil let commentReply: ReplyModel diff --git a/Mlem/Models/Composers/Response Composers/Replies/ReplyToMention.swift b/Mlem/Models/Composers/Response Composers/Replies/ReplyToMention.swift index e2de9fd11..42cbab91a 100644 --- a/Mlem/Models/Composers/Response Composers/Replies/ReplyToMention.swift +++ b/Mlem/Models/Composers/Response Composers/Replies/ReplyToMention.swift @@ -13,6 +13,7 @@ struct ReplyToMention: ResponseEditorModel { @Dependency(\.commentRepository) var commentRepository let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "New Comment" let prefillContents: String? = nil let mention: MentionModel diff --git a/Mlem/Models/Composers/Response Composers/Replies/ReplyToMessage.swift b/Mlem/Models/Composers/Response Composers/Replies/ReplyToMessage.swift index d2ade39cd..2e88ac81e 100644 --- a/Mlem/Models/Composers/Response Composers/Replies/ReplyToMessage.swift +++ b/Mlem/Models/Composers/Response Composers/Replies/ReplyToMessage.swift @@ -15,6 +15,7 @@ struct ReplyToMessage: ResponseEditorModel { var id: Int { message.id } let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "New Message" let prefillContents: String? = nil let message: MessageModel diff --git a/Mlem/Models/Composers/Response Composers/Replies/ReplyToPost.swift b/Mlem/Models/Composers/Response Composers/Replies/ReplyToPost.swift index 6172df1ba..cd4b7a6c5 100644 --- a/Mlem/Models/Composers/Response Composers/Replies/ReplyToPost.swift +++ b/Mlem/Models/Composers/Response Composers/Replies/ReplyToPost.swift @@ -13,6 +13,7 @@ struct ReplyToPost: ResponseEditorModel { @Dependency(\.commentRepository) var commentRepository let canUpload: Bool = true + let showSlurWarning: Bool = true let modalName: String = "New Comment" let prefillContents: String? let commentTracker: CommentTracker? diff --git a/Mlem/Models/Composers/Response Composers/Reports/ReportComment.swift b/Mlem/Models/Composers/Response Composers/Reports/ReportComment.swift index ca930c145..2f3fc2404 100644 --- a/Mlem/Models/Composers/Response Composers/Reports/ReportComment.swift +++ b/Mlem/Models/Composers/Response Composers/Reports/ReportComment.swift @@ -14,6 +14,7 @@ struct ReportComment: ResponseEditorModel { var id: Int { comment.id } let canUpload: Bool = false + let showSlurWarning: Bool = false let modalName: String = "Report Comment" let prefillContents: String? = nil let comment: APICommentView diff --git a/Mlem/Models/Composers/Response Composers/Reports/ReportCommentReply.swift b/Mlem/Models/Composers/Response Composers/Reports/ReportCommentReply.swift index 03e7ce3ac..435db4fdc 100644 --- a/Mlem/Models/Composers/Response Composers/Reports/ReportCommentReply.swift +++ b/Mlem/Models/Composers/Response Composers/Reports/ReportCommentReply.swift @@ -14,6 +14,7 @@ struct ReportCommentReply: ResponseEditorModel { var id: Int { commentReply.id } let canUpload: Bool = false + let showSlurWarning: Bool = false let modalName: String = "Report Comment" let prefillContents: String? = nil let commentReply: ReplyModel diff --git a/Mlem/Models/Composers/Response Composers/Reports/ReportMention.swift b/Mlem/Models/Composers/Response Composers/Reports/ReportMention.swift index 09a511445..3f0a97399 100644 --- a/Mlem/Models/Composers/Response Composers/Reports/ReportMention.swift +++ b/Mlem/Models/Composers/Response Composers/Reports/ReportMention.swift @@ -14,6 +14,7 @@ struct ReportMention: ResponseEditorModel { var id: Int { mention.id } let canUpload: Bool = false + let showSlurWarning: Bool = false let modalName: String = "Report Comment" let prefillContents: String? = nil let mention: MentionModel diff --git a/Mlem/Models/Composers/Response Composers/Reports/ReportMessage.swift b/Mlem/Models/Composers/Response Composers/Reports/ReportMessage.swift index e6a11ba4d..7b4c950a9 100644 --- a/Mlem/Models/Composers/Response Composers/Reports/ReportMessage.swift +++ b/Mlem/Models/Composers/Response Composers/Reports/ReportMessage.swift @@ -15,6 +15,7 @@ struct ReportMessage: ResponseEditorModel { var id: Int { message.id } let canUpload: Bool = false + let showSlurWarning: Bool = false let modalName: String = "Report Message" let prefillContents: String? = nil let message: MessageModel diff --git a/Mlem/Models/Composers/Response Composers/Reports/ReportPost.swift b/Mlem/Models/Composers/Response Composers/Reports/ReportPost.swift index 4ac39d9d2..9210e5cb2 100644 --- a/Mlem/Models/Composers/Response Composers/Reports/ReportPost.swift +++ b/Mlem/Models/Composers/Response Composers/Reports/ReportPost.swift @@ -15,6 +15,7 @@ struct ReportPost: ResponseEditorModel { var id: Int { post.postId } let canUpload: Bool = false + let showSlurWarning: Bool = false let modalName: String = "Report Post" let prefillContents: String? = nil let post: PostModel diff --git a/Mlem/Views/Shared/Composer/ResponseEditorView.swift b/Mlem/Views/Shared/Composer/ResponseEditorView.swift index 4b4ae5f17..202df21f4 100644 --- a/Mlem/Views/Shared/Composer/ResponseEditorView.swift +++ b/Mlem/Views/Shared/Composer/ResponseEditorView.swift @@ -15,6 +15,7 @@ struct ResponseEditorView: View { } @Dependency(\.errorHandler) var errorHandler + @Dependency(\.siteInformation) var siteInformation let editorModel: any ResponseEditorModel @@ -28,6 +29,8 @@ struct ResponseEditorView: View { @State var editorBody: String @State var isSubmitting: Bool = false + @State var slurMatch: String? + @FocusState private var focusedField: Field? private var isReadyToReply: Bool { @@ -50,11 +53,42 @@ struct ResponseEditorView: View { .onAppear { focusedField = .editorBody } + .onChange(of: editorBody) { newValue in + if editorModel.showSlurWarning { + do { + if let regex = siteInformation.slurFilterRegex { + if let output = try regex.firstMatch(in: newValue.lowercased()) { + slurMatch = String(newValue[output.range]) + } else { + slurMatch = nil + } + } + } catch { + print("REGEX FAILED") + } + } + } Divider() - editorModel.embeddedView() + if let slurMatch { + VStack { + Text("\"\(slurMatch)\" is disallowed.") + .foregroundStyle(.white) + Text("You can still post this comment, but your instance will replace \"\(slurMatch)\" with \"*removed*\".") + .multilineTextAlignment(.center) + .font(.footnote) + .foregroundStyle(.white.opacity(0.8)) + } + .padding() + .frame(maxWidth: .infinity) + .background(RoundedRectangle(cornerRadius: AppConstants.largeItemCornerRadius).fill(.red)) + .padding(.horizontal) + } else { + editorModel.embeddedView() + } } + .animation(.default, value: slurMatch) .padding(.bottom, AppConstants.editorOverscroll) } .scrollDismissesKeyboard(.automatic) From c70ba7eea9eb276386a00f19f1cef99cc48b2bed Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sat, 27 Jan 2024 17:35:10 +0000 Subject: [PATCH 09/10] Tweak --- Mlem/Views/Shared/Composer/ResponseEditorView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mlem/Views/Shared/Composer/ResponseEditorView.swift b/Mlem/Views/Shared/Composer/ResponseEditorView.swift index 202df21f4..b005ba942 100644 --- a/Mlem/Views/Shared/Composer/ResponseEditorView.swift +++ b/Mlem/Views/Shared/Composer/ResponseEditorView.swift @@ -83,7 +83,7 @@ struct ResponseEditorView: View { .padding() .frame(maxWidth: .infinity) .background(RoundedRectangle(cornerRadius: AppConstants.largeItemCornerRadius).fill(.red)) - .padding(.horizontal) + .padding(.horizontal, 10) } else { editorModel.embeddedView() } From 8a963b2fcee73f4b2c945ede87a80f62020b8b79 Mon Sep 17 00:00:00 2001 From: Sjmarf <78750526+Sjmarf@users.noreply.github.com> Date: Sun, 28 Jan 2024 11:59:10 +0000 Subject: [PATCH 10/10] Update --- .../Content/Instance/InstanceModel.swift | 26 ++++++++++++++++++ .../Trackers/SiteInformationTracker.swift | 5 ---- .../Shared/Composer/PostComposerView.swift | 27 +++---------------- .../Shared/Composer/ResponseEditorView.swift | 12 +-------- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/Mlem/Models/Content/Instance/InstanceModel.swift b/Mlem/Models/Content/Instance/InstanceModel.swift index ca396483d..b679ff9f3 100644 --- a/Mlem/Models/Content/Instance/InstanceModel.swift +++ b/Mlem/Models/Content/Instance/InstanceModel.swift @@ -17,6 +17,8 @@ struct InstanceModel { var url: URL! var version: SiteVersion? + var slurFilterRegex: Regex? + init(from response: SiteResponse) { self.update(with: response) } @@ -33,6 +35,17 @@ struct InstanceModel { return user } self.version = SiteVersion(response.version) + + let localSite = response.siteView.localSite + + do { + if let regex = localSite.slurFilterRegex { + self.slurFilterRegex = try .init(regex) + } + } catch { + print("Invalid slur filter regex") + } + self.update(with: response.siteView.site) } @@ -48,6 +61,19 @@ struct InstanceModel { url = components.url } } + + func firstSlurFilterMatch(_ input: String) -> String? { + do { + if let slurFilterRegex { + if let output = try slurFilterRegex.firstMatch(in: input.lowercased()) { + return String(input[output.range]) + } + } + } catch { + print("REGEX FAILED") + } + return nil + } } extension InstanceModel: Identifiable { diff --git a/Mlem/Models/Trackers/SiteInformationTracker.swift b/Mlem/Models/Trackers/SiteInformationTracker.swift index dabce458b..daa7af972 100644 --- a/Mlem/Models/Trackers/SiteInformationTracker.swift +++ b/Mlem/Models/Trackers/SiteInformationTracker.swift @@ -19,7 +19,6 @@ class SiteInformationTracker: ObservableObject { @Published var version: SiteVersion? @Published private(set) var allLanguages: [APILanguage] = .init() @Published var myUserInfo: APIMyUserInfo? - @Published var slurFilterRegex: Regex? func load(account: SavedAccount) { @@ -39,10 +38,6 @@ class SiteInformationTracker: ObservableObject { myUserInfo = response.myUser allLanguages = response.allLanguages - if let regex = response.siteView.localSite.slurFilterRegex { - slurFilterRegex = try .init(regex) - } - } catch { errorHandler.handle(error) } diff --git a/Mlem/Views/Shared/Composer/PostComposerView.swift b/Mlem/Views/Shared/Composer/PostComposerView.swift index dab1d2acc..beac890a5 100644 --- a/Mlem/Views/Shared/Composer/PostComposerView.swift +++ b/Mlem/Views/Shared/Composer/PostComposerView.swift @@ -19,7 +19,6 @@ extension HorizontalAlignment { static let labelStart = HorizontalAlignment(LabelStart.self) } -// swiftlint:disable type_body_length struct PostComposerView: View { private enum Field: Hashable { case title, url, body @@ -93,17 +92,7 @@ struct PostComposerView: View { .padding(.top) .padding(.horizontal) .onChange(of: postTitle) { newValue in - do { - if let regex = siteInformation.slurFilterRegex { - if let output = try regex.firstMatch(in: newValue.lowercased()) { - titleSlurMatch = String(newValue[output.range]) - } else { - titleSlurMatch = nil - } - } - } catch { - print("REGEX FAILED") - } + titleSlurMatch = siteInformation.instance?.firstSlurFilterMatch(newValue) } if attachmentModel.imageModel != nil || attachmentModel.url.isNotEmpty { @@ -191,17 +180,7 @@ struct PostComposerView: View { .focused($focusedField, equals: .body) .padding(.horizontal) .onChange(of: postBody) { newValue in - do { - if let regex = siteInformation.slurFilterRegex { - if let output = try regex.firstMatch(in: newValue.lowercased()) { - bodySlurMatch = String(newValue[output.range]) - } else { - bodySlurMatch = nil - } - } - } catch { - print("REGEX FAILED") - } + bodySlurMatch = siteInformation.instance?.firstSlurFilterMatch(newValue) } Spacer() @@ -303,6 +282,7 @@ struct PostComposerView: View { Capsule() .fill(.red) Text("\"\(slurMatch)\" is disallowed.") + .foregroundStyle(.white) } .padding(-2) } @@ -310,4 +290,3 @@ struct PostComposerView: View { .animation(.default, value: titleSlurMatch == nil && bodySlurMatch == nil) } } -// swiftlint:enable type_body_length diff --git a/Mlem/Views/Shared/Composer/ResponseEditorView.swift b/Mlem/Views/Shared/Composer/ResponseEditorView.swift index b005ba942..1842ee8c0 100644 --- a/Mlem/Views/Shared/Composer/ResponseEditorView.swift +++ b/Mlem/Views/Shared/Composer/ResponseEditorView.swift @@ -55,17 +55,7 @@ struct ResponseEditorView: View { } .onChange(of: editorBody) { newValue in if editorModel.showSlurWarning { - do { - if let regex = siteInformation.slurFilterRegex { - if let output = try regex.firstMatch(in: newValue.lowercased()) { - slurMatch = String(newValue[output.range]) - } else { - slurMatch = nil - } - } - } catch { - print("REGEX FAILED") - } + slurMatch = siteInformation.instance?.firstSlurFilterMatch(newValue) } }