From 412f475d1d5bf628561cd65722282db03733f110 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Thu, 15 Aug 2024 22:30:31 +0200 Subject: [PATCH] Connect to notification filters V2 --- .../Sources/Models/NotificationsPolicy.swift | 13 ++- .../NotificationsPolicyView.swift | 110 +++++++++++++----- 2 files changed, 93 insertions(+), 30 deletions(-) diff --git a/Packages/Models/Sources/Models/NotificationsPolicy.swift b/Packages/Models/Sources/Models/NotificationsPolicy.swift index 3d123606..e4990cb9 100644 --- a/Packages/Models/Sources/Models/NotificationsPolicy.swift +++ b/Packages/Models/Sources/Models/NotificationsPolicy.swift @@ -1,10 +1,15 @@ import Foundation public struct NotificationsPolicy: Codable, Sendable { - public var filterNotFollowing: Bool - public var filterNotFollowers: Bool - public var filterNewAccounts: Bool - public var filterPrivateMentions: Bool + public enum Policy: String, Codable, Sendable, CaseIterable, Hashable { + case accept, filter, drop + } + + public var forNotFollowing: Policy + public var forNotFollowers: Policy + public var forNewAccounts: Policy + public var forPrivateMentions: Policy + public var forLimitedAccounts: Policy public let summary: Summary public struct Summary: Codable, Sendable { diff --git a/Packages/Notifications/Sources/Notifications/NotificationsPolicyView.swift b/Packages/Notifications/Sources/Notifications/NotificationsPolicyView.swift index fc637edb..f9ca2904 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationsPolicyView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationsPolicyView.swift @@ -17,34 +17,85 @@ struct NotificationsPolicyView: View { NavigationStack { Form { Section("notifications.content-filter.title-inline") { - Toggle(isOn: .init(get: { policy?.filterNotFollowing == true }, - set: { newValue in - policy?.filterNotFollowing = newValue - Task { await updatePolicy() } - }), label: { + Picker(selection: .init(get: { + policy?.forNotFollowing ?? .drop + }, set: { policy in + self.policy?.forNotFollowing = policy + Task { await updatePolicy() } + })) { + pickerMenu + } label: { + VStack(alignment: .leading) { Text("notifications.content-filter.peopleYouDontFollow") - }) - Toggle(isOn: .init(get: { policy?.filterNotFollowers == true }, - set: { newValue in - policy?.filterNotFollowers = newValue - Task { await updatePolicy() } - }), label: { + Text("Until you manually approve them") + .foregroundStyle(.secondary) + .font(.footnote) + } + } + + Picker(selection: .init(get: { + policy?.forNotFollowers ?? .drop + }, set: { policy in + self.policy?.forNotFollowers = policy + Task { await updatePolicy() } + })) { + pickerMenu + } label: { + VStack(alignment: .leading) { Text("notifications.content-filter.peopleNotFollowingYou") - }) - Toggle(isOn: .init(get: { policy?.filterNewAccounts == true }, - set: { newValue in - policy?.filterNewAccounts = newValue - Task { await updatePolicy() } - }), label: { + Text("And following you for less than 3 days") + .foregroundStyle(.secondary) + .font(.footnote) + } + } + + Picker(selection: .init(get: { + policy?.forNewAccounts ?? .drop + }, set: { policy in + self.policy?.forNewAccounts = policy + Task { await updatePolicy() } + })) { + pickerMenu + } label: { + VStack(alignment: .leading) { Text("notifications.content-filter.newAccounts") - }) - Toggle(isOn: .init(get: { policy?.filterPrivateMentions == true }, - set: { newValue in - policy?.filterPrivateMentions = newValue - Task { await updatePolicy() } - }), label: { + Text("Created within the past 30 days") + .foregroundStyle(.secondary) + .font(.footnote) + } + } + + Picker(selection: .init(get: { + policy?.forPrivateMentions ?? .drop + }, set: { policy in + self.policy?.forPrivateMentions = policy + Task { await updatePolicy() } + })) { + pickerMenu + } label: { + VStack(alignment: .leading) { Text("notifications.content-filter.privateMentions") - }) + Text("Unless it's in reply to your own mention or if you follow the sender") + .foregroundStyle(.secondary) + .font(.footnote) + } + } + + Picker(selection: .init(get: { + policy?.forLimitedAccounts ?? .drop + }, set: { policy in + self.policy?.forLimitedAccounts = policy + Task { await updatePolicy() } + })) { + pickerMenu + } label: { + VStack(alignment: .leading) { + Text("Moderated accounts") + Text("Limited by server moderators") + .foregroundStyle(.secondary) + .font(.footnote) + } + } } #if !os(visionOS) .listRowBackground(theme.primaryBackgroundColor.opacity(0.3)) @@ -59,10 +110,17 @@ struct NotificationsPolicyView: View { .task { await getPolicy() } + .redacted(reason: policy == nil ? .placeholder : []) } .presentationDetents([.medium]) .presentationBackground(.thinMaterial) } + + private var pickerMenu: some View { + ForEach(NotificationsPolicy.Policy.allCases, id: \.self) { policy in + Text(policy.rawValue.capitalized) + } + } private func getPolicy() async { defer { @@ -70,7 +128,7 @@ struct NotificationsPolicyView: View { } do { isUpdating = true - policy = try await client.get(endpoint: Notifications.policy) + policy = try await client.get(endpoint: Notifications.policy, forceVersion: .v2) } catch { dismiss() } @@ -83,7 +141,7 @@ struct NotificationsPolicyView: View { } do { isUpdating = true - self.policy = try await client.put(endpoint: Notifications.putPolicy(policy: policy)) + self.policy = try await client.put(endpoint: Notifications.putPolicy(policy: policy), forceVersion: .v2) } catch {} } }