mirror of
https://github.com/mastodon/mastodon-ios
synced 2025-04-11 22:58:02 +02:00
Convert NotificationPolicyViewController to SwiftUI
Fixes IOS-396 Fixes IOS-398
This commit is contained in:
parent
fa207e3a44
commit
b72d5f34c5
@ -851,6 +851,7 @@
|
||||
}
|
||||
},
|
||||
"admin_filter": {
|
||||
"title": "Admin Notifications",
|
||||
"reports": {
|
||||
"title": "Admin reports",
|
||||
"subtitle": "Show reports of spam, rule violations, and other complaints on this instance"
|
||||
|
@ -851,6 +851,7 @@
|
||||
}
|
||||
},
|
||||
"admin_filter": {
|
||||
"title": "Admin Notifications",
|
||||
"reports": {
|
||||
"title": "Admin reports",
|
||||
"subtitle": "Show reports of spam, rule violations, and other complaints on this instance"
|
||||
|
@ -508,6 +508,7 @@
|
||||
DBFEEC99279BDCDE004F81DD /* ProfileAboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC98279BDCDE004F81DD /* ProfileAboutViewModel.swift */; };
|
||||
DBFEEC9B279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9A279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift */; };
|
||||
DBFEEC9D279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9C279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift */; };
|
||||
FB0F8E932DA54A180058C09E /* NotificationPolicyHostingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0F8E922DA54A090058C09E /* NotificationPolicyHostingViewController.swift */; };
|
||||
FB7C4CC62CD2CAB000F6129A /* DonationCompletionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CC52CD2CAA800F6129A /* DonationCompletionViewController.swift */; };
|
||||
FB7C4CCC2CD55DEB00F6129A /* NavigationFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CCB2CD55DEB00F6129A /* NavigationFlow.swift */; };
|
||||
FB7C4CCE2CD55DFF00F6129A /* NewDonationNavigationFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7C4CCD2CD55DFE00F6129A /* NewDonationNavigationFlow.swift */; };
|
||||
@ -1261,6 +1262,7 @@
|
||||
DBFEF06726A58D07006D7ED1 /* ShareActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareActionExtension.entitlements; sourceTree = "<group>"; };
|
||||
E9AABD3D26B64B8C00E237DA /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Intents.strings; sourceTree = "<group>"; };
|
||||
E9AABD4026B64B8D00E237DA /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
FB0F8E922DA54A090058C09E /* NotificationPolicyHostingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPolicyHostingViewController.swift; sourceTree = "<group>"; };
|
||||
FB7C4CC52CD2CAA800F6129A /* DonationCompletionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DonationCompletionViewController.swift; sourceTree = "<group>"; };
|
||||
FB7C4CCB2CD55DEB00F6129A /* NavigationFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationFlow.swift; sourceTree = "<group>"; };
|
||||
FB7C4CCD2CD55DFE00F6129A /* NewDonationNavigationFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDonationNavigationFlow.swift; sourceTree = "<group>"; };
|
||||
@ -1843,6 +1845,7 @@
|
||||
D85DF9682C481AF400A01408 /* NotificationPolicyFilterTableViewCell.swift */,
|
||||
D85DF96A2C481AF700A01408 /* NotificationPolicyHeaderView.swift */,
|
||||
D85DF9692C481AF700A01408 /* NotificationPolicyViewController.swift */,
|
||||
FB0F8E922DA54A090058C09E /* NotificationPolicyHostingViewController.swift */,
|
||||
);
|
||||
path = "Notification Filtering";
|
||||
sourceTree = "<group>";
|
||||
@ -3849,6 +3852,7 @@
|
||||
DB63F77B279ACAE500455B82 /* DataSourceFacade+Favorite.swift in Sources */,
|
||||
2DAC9E46262FC9FD0062E1A6 /* SuggestionAccountTableViewCell.swift in Sources */,
|
||||
D8D688F92AB8B970000F651A /* SearchResultOverviewCoordinator.swift in Sources */,
|
||||
FB0F8E932DA54A180058C09E /* NotificationPolicyHostingViewController.swift in Sources */,
|
||||
DB4FFC2C269EC39600D62E92 /* SearchTransitionController.swift in Sources */,
|
||||
2A3D9B7E29A8F33A00F30313 /* StatusHistoryView.swift in Sources */,
|
||||
D81A227B2AB47B9A00905D71 /* SearchResultDefaultSectionTableViewCell.swift in Sources */,
|
||||
|
@ -198,7 +198,7 @@ extension SceneCoordinator {
|
||||
case settings(setting: Setting)
|
||||
|
||||
// Notifications
|
||||
case notificationPolicy(viewModel: NotificationFilterViewModel)
|
||||
case notificationPolicy(viewModel: NotificationPolicyViewModel)
|
||||
case notificationRequests(viewModel: NotificationRequestsViewModel)
|
||||
case accountNotificationTimeline(viewModel: NotificationTimelineViewModel, request: Mastodon.Entity.NotificationRequest)
|
||||
|
||||
@ -548,7 +548,7 @@ private extension SceneCoordinator {
|
||||
case .notificationRequests(let viewModel):
|
||||
viewController = NotificationRequestsTableViewController(viewModel: viewModel)
|
||||
case .notificationPolicy(let viewModel):
|
||||
viewController = NotificationPolicyViewController(viewModel: viewModel)
|
||||
viewController = NotificationPolicyViewController(viewModel)
|
||||
case .accountNotificationTimeline(let viewModel, let request):
|
||||
viewController = AccountNotificationTimelineViewController(viewModel: viewModel, notificationRequest: request)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class NotificationListViewController: UIHostingController<NotificationListView>
|
||||
}
|
||||
}()
|
||||
|
||||
let policyViewModel = await NotificationFilterViewModel(
|
||||
let policyViewModel = await NotificationPolicyViewModel(
|
||||
NotificationFilterSettings(
|
||||
forNotFollowing: policy.forNotFollowing,
|
||||
forNotFollowers: policy.forNotFollowers,
|
||||
|
@ -0,0 +1,446 @@
|
||||
// Copyright © 2025 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
import SwiftUI
|
||||
|
||||
private typealias FilterAction = Mastodon.Entity.NotificationPolicy
|
||||
.NotificationFilterAction
|
||||
|
||||
protocol NotificationPolicyViewControllerDelegate: AnyObject {
|
||||
func policyUpdated(
|
||||
_ viewController: NotificationPolicyViewController,
|
||||
newPolicy: Mastodon.Entity.NotificationPolicy)
|
||||
}
|
||||
|
||||
class NotificationPolicyViewController: UIHostingController<
|
||||
NotificationPolicyView
|
||||
>
|
||||
{
|
||||
let viewModel: NotificationPolicyViewModel
|
||||
weak var delegate: NotificationPolicyViewControllerDelegate?
|
||||
|
||||
init(_ viewModel: NotificationPolicyViewModel) {
|
||||
self.viewModel = viewModel
|
||||
let root = NotificationPolicyView(viewModel: viewModel)
|
||||
super.init(rootView: root)
|
||||
|
||||
viewModel.dismissView = { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
viewModel.didDismissView = { updatedPolicy in
|
||||
self.didUpdatePolicy(updatedPolicy)
|
||||
viewModel.didDismissView = nil // break retain cycle
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init with coder not implemented")
|
||||
}
|
||||
|
||||
private func didUpdatePolicy(
|
||||
_ updatedPolicy: Mastodon.Entity.NotificationPolicy?
|
||||
) {
|
||||
if let updatedPolicy {
|
||||
delegate?.policyUpdated(self, newPolicy: updatedPolicy)
|
||||
}
|
||||
NotificationCenter.default.post(
|
||||
name: .notificationFilteringChanged, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationPolicyView: View {
|
||||
@StateObject var viewModel: NotificationPolicyViewModel
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
.frame(maxWidth: .infinity)
|
||||
Button {
|
||||
viewModel.dismissView?()
|
||||
} label: {
|
||||
Image(systemName: "x.circle")
|
||||
.frame(width: 45, height: 45)
|
||||
.font(.title)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
|
||||
List {
|
||||
ForEach(viewModel.sections, id: \.self) { section in
|
||||
Section(header: Text(section.headerText).font(.title)) {
|
||||
ForEach(section.items, id: \.self) { policyItem in
|
||||
rowView(policyItem)
|
||||
}
|
||||
}
|
||||
.textCase(nil)
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.background(Color(uiColor: .systemGroupedBackground))
|
||||
.onDisappear {
|
||||
Task {
|
||||
let updatedPolicy = try await viewModel.saveChanges()
|
||||
viewModel.didDismissView?(updatedPolicy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func rowView(
|
||||
_ settingType: NotificationPolicyViewModel.NotificationFilterItem
|
||||
) -> some View {
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
// title
|
||||
HStack(alignment: verticalAlignmentForControl(settingType)) {
|
||||
Text(settingType.title)
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.headline)
|
||||
Spacer()
|
||||
// menu or toggle
|
||||
control(settingType)
|
||||
.fixedSize()
|
||||
}
|
||||
|
||||
HStack {
|
||||
Spacer().frame(width: 5)
|
||||
|
||||
// subtitle
|
||||
Text(settingType.subtitle)
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.subheadline)
|
||||
|
||||
Spacer()
|
||||
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
@ViewBuilder func control(_ settingType: NotificationPolicyViewModel.NotificationFilterItem) -> some View {
|
||||
// the control
|
||||
switch settingType {
|
||||
case .notFollowing, .notFollowers, .newAccounts, .privateMentions,
|
||||
.limitedAccounts:
|
||||
Picker("", selection: viewModel.binding(for: settingType)) {
|
||||
ForEach([FilterAction.accept, .filter, .drop], id: \.self) {
|
||||
option in
|
||||
Text(option.displayTitle)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.menu)
|
||||
.tint(Asset.Colors.Brand.blurple.swiftUIColor)
|
||||
.fixedSize()
|
||||
case .adminReports, .adminSignups:
|
||||
Toggle(
|
||||
isOn: Binding(
|
||||
get: {
|
||||
viewModel.value(forItem: settingType) == .accept
|
||||
},
|
||||
set: {
|
||||
viewModel.setValue(
|
||||
$0 ? .accept : .filter, forItem: settingType)
|
||||
})
|
||||
) {}
|
||||
.tint(Asset.Colors.Brand.blurple.swiftUIColor)
|
||||
.fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
func verticalAlignmentForControl(_ settingType: NotificationPolicyViewModel.NotificationFilterItem) -> VerticalAlignment {
|
||||
switch settingType {
|
||||
case .notFollowing, .notFollowers, .newAccounts, .privateMentions, .limitedAccounts:
|
||||
.center
|
||||
case .adminReports, .adminSignups:
|
||||
.top
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class NotificationPolicyViewModel: ObservableObject {
|
||||
|
||||
let sections: [NotificationPolicyViewModel.NotificationFilterSection]
|
||||
|
||||
let originalRegularSettings: NotificationFilterSettings
|
||||
let originalAdminSettings: AdminNotificationFilterSettings?
|
||||
|
||||
var dismissView: (() -> Void)?
|
||||
var didDismissView: ((Mastodon.Entity.NotificationPolicy?) -> Void)?
|
||||
|
||||
@Published var regularFilterSettings: NotificationFilterSettings
|
||||
@Published var adminFilterSettings: AdminNotificationFilterSettings?
|
||||
|
||||
var hasUnsavedChangesToRegularSettings: Bool {
|
||||
return regularFilterSettings != originalRegularSettings
|
||||
}
|
||||
|
||||
var hasUnsavedChangesToAdminSettings: Bool {
|
||||
return adminFilterSettings != originalAdminSettings
|
||||
}
|
||||
|
||||
init(
|
||||
_ regularSettings: NotificationFilterSettings,
|
||||
adminSettings: AdminNotificationFilterSettings?
|
||||
) async {
|
||||
self.originalRegularSettings = regularSettings
|
||||
self.regularFilterSettings = regularSettings
|
||||
self.originalAdminSettings = adminSettings
|
||||
self.adminFilterSettings = adminSettings
|
||||
|
||||
self.sections = [.main, .admin].compactMap { $0 }
|
||||
}
|
||||
|
||||
fileprivate func value(forItem item: NotificationFilterItem) -> FilterAction
|
||||
{
|
||||
switch item {
|
||||
case .notFollowing:
|
||||
return regularFilterSettings.forNotFollowing
|
||||
case .notFollowers:
|
||||
return regularFilterSettings.forNotFollowers
|
||||
case .newAccounts:
|
||||
return regularFilterSettings.forNewAccounts
|
||||
case .privateMentions:
|
||||
return regularFilterSettings.forPrivateMentions
|
||||
case .limitedAccounts:
|
||||
return regularFilterSettings.forLimitedAccounts
|
||||
case .adminReports:
|
||||
return adminFilterSettings?.forReports ?? .drop
|
||||
case .adminSignups:
|
||||
return adminFilterSettings?.forSignups ?? .drop
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setValue(
|
||||
_ value: FilterAction, forItem item: NotificationFilterItem
|
||||
) {
|
||||
switch item {
|
||||
case .notFollowing:
|
||||
regularFilterSettings = NotificationFilterSettings(
|
||||
forNotFollowing: value,
|
||||
forNotFollowers: regularFilterSettings.forNotFollowers,
|
||||
forNewAccounts: regularFilterSettings.forNewAccounts,
|
||||
forPrivateMentions: regularFilterSettings.forPrivateMentions,
|
||||
forLimitedAccounts: regularFilterSettings.forLimitedAccounts)
|
||||
case .notFollowers:
|
||||
regularFilterSettings = NotificationFilterSettings(
|
||||
forNotFollowing: regularFilterSettings.forNotFollowing,
|
||||
forNotFollowers: value,
|
||||
forNewAccounts: regularFilterSettings.forNewAccounts,
|
||||
forPrivateMentions: regularFilterSettings.forPrivateMentions,
|
||||
forLimitedAccounts: regularFilterSettings.forLimitedAccounts)
|
||||
case .newAccounts:
|
||||
regularFilterSettings = NotificationFilterSettings(
|
||||
forNotFollowing: regularFilterSettings.forNotFollowing,
|
||||
forNotFollowers: regularFilterSettings.forNotFollowers,
|
||||
forNewAccounts: value,
|
||||
forPrivateMentions: regularFilterSettings.forPrivateMentions,
|
||||
forLimitedAccounts: regularFilterSettings.forLimitedAccounts)
|
||||
case .privateMentions:
|
||||
regularFilterSettings = NotificationFilterSettings(
|
||||
forNotFollowing: regularFilterSettings.forNotFollowing,
|
||||
forNotFollowers: regularFilterSettings.forNotFollowers,
|
||||
forNewAccounts: regularFilterSettings.forNewAccounts,
|
||||
forPrivateMentions: value,
|
||||
forLimitedAccounts: regularFilterSettings.forLimitedAccounts)
|
||||
case .limitedAccounts:
|
||||
regularFilterSettings = NotificationFilterSettings(
|
||||
forNotFollowing: regularFilterSettings.forNotFollowing,
|
||||
forNotFollowers: regularFilterSettings.forNotFollowers,
|
||||
forNewAccounts: regularFilterSettings.forNewAccounts,
|
||||
forPrivateMentions: regularFilterSettings.forPrivateMentions,
|
||||
forLimitedAccounts: value)
|
||||
|
||||
case .adminReports:
|
||||
guard let adminFilterSettings else { return }
|
||||
self.adminFilterSettings = AdminNotificationFilterSettings(
|
||||
forReports: value,
|
||||
forSignups: adminFilterSettings.forSignups)
|
||||
case .adminSignups:
|
||||
guard let adminFilterSettings else { return }
|
||||
self.adminFilterSettings = AdminNotificationFilterSettings(
|
||||
forReports: adminFilterSettings.forReports,
|
||||
forSignups: value)
|
||||
}
|
||||
}
|
||||
|
||||
func saveChanges() async throws -> Mastodon.Entity.NotificationPolicy? {
|
||||
guard
|
||||
let authenticationBox = AuthenticationServiceProvider.shared
|
||||
.currentActiveUser.value
|
||||
else { return nil }
|
||||
|
||||
if let adminFilterSettings, hasUnsavedChangesToAdminSettings {
|
||||
do {
|
||||
try await BodegaPersistence.Notifications.updatePreferences(
|
||||
adminFilterSettings, for: authenticationBox)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if hasUnsavedChangesToRegularSettings {
|
||||
let updatedPolicy = try await APIService.shared
|
||||
.updateNotificationPolicy(
|
||||
authenticationBox: authenticationBox,
|
||||
forNotFollowing: value(forItem: .notFollowing),
|
||||
forNotFollowers: value(forItem: .notFollowers),
|
||||
forNewAccounts: value(forItem: .newAccounts),
|
||||
forPrivateMentions: value(forItem: .privateMentions),
|
||||
forLimitedAccounts: value(forItem: .limitedAccounts)
|
||||
).value
|
||||
return updatedPolicy
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationPolicyViewModel {
|
||||
fileprivate func binding(for settingItem: NotificationFilterItem)
|
||||
-> Binding<FilterAction>
|
||||
{
|
||||
return Binding(
|
||||
get: { [weak self] in
|
||||
self?.value(forItem: settingItem) ?? ._other("unset")
|
||||
}, set: { [weak self] in self?.setValue($0, forItem: settingItem) })
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationPolicyViewModel {
|
||||
enum NotificationFilterSection: Hashable {
|
||||
case main
|
||||
case admin
|
||||
|
||||
var items: [NotificationFilterItem] {
|
||||
switch self {
|
||||
case .main:
|
||||
return [
|
||||
.notFollowing, .notFollowers, .newAccounts,
|
||||
.privateMentions, .limitedAccounts,
|
||||
]
|
||||
case .admin:
|
||||
return [.adminReports, .adminSignups]
|
||||
}
|
||||
}
|
||||
|
||||
var headerText: String {
|
||||
switch self {
|
||||
case .main:
|
||||
L10n.Scene.Notification.Policy.title
|
||||
case .admin:
|
||||
L10n.Scene.Notification.AdminFilter.title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum NotificationFilterItem: Hashable {
|
||||
case notFollowing
|
||||
case notFollowers
|
||||
case newAccounts
|
||||
case privateMentions
|
||||
case limitedAccounts
|
||||
|
||||
case adminReports
|
||||
case adminSignups
|
||||
|
||||
static let regularOptions = [
|
||||
Self.notFollowing, .notFollowers, .newAccounts, .privateMentions,
|
||||
.limitedAccounts,
|
||||
]
|
||||
static let adminOptions = [Self.adminReports, .adminSignups]
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .notFollowing:
|
||||
return L10n.Scene.Notification.Policy.NotFollowing.title
|
||||
case .notFollowers:
|
||||
return L10n.Scene.Notification.Policy.NoFollower.title
|
||||
case .newAccounts:
|
||||
return L10n.Scene.Notification.Policy.NewAccount.title
|
||||
case .privateMentions:
|
||||
return L10n.Scene.Notification.Policy.PrivateMentions.title
|
||||
case .limitedAccounts:
|
||||
return L10n.Scene.Notification.Policy.ModeratedAccounts.title
|
||||
|
||||
case .adminReports:
|
||||
return L10n.Scene.Notification.AdminFilter.Reports.title
|
||||
case .adminSignups:
|
||||
return L10n.Scene.Notification.AdminFilter.Signups.title
|
||||
}
|
||||
}
|
||||
|
||||
var subtitle: String {
|
||||
switch self {
|
||||
case .notFollowing:
|
||||
return L10n.Scene.Notification.Policy.NotFollowing.subtitle
|
||||
case .notFollowers:
|
||||
return L10n.Scene.Notification.Policy.NoFollower.subtitle
|
||||
case .newAccounts:
|
||||
return L10n.Scene.Notification.Policy.NewAccount.subtitle
|
||||
case .privateMentions:
|
||||
return L10n.Scene.Notification.Policy.PrivateMentions.subtitle
|
||||
case .limitedAccounts:
|
||||
return L10n.Scene.Notification.Policy.ModeratedAccounts.subtitle
|
||||
|
||||
case .adminReports:
|
||||
return L10n.Scene.Notification.AdminFilter.Reports.subtitle
|
||||
case .adminSignups:
|
||||
return L10n.Scene.Notification.AdminFilter.Signups.subtitle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationFilterSettings: Codable, Equatable {
|
||||
let forNotFollowing:
|
||||
Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
let forNotFollowers:
|
||||
Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
let forNewAccounts:
|
||||
Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
let forPrivateMentions:
|
||||
Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
let forLimitedAccounts:
|
||||
Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
}
|
||||
|
||||
struct AdminNotificationFilterSettings: Codable, Equatable {
|
||||
let forReports: Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
let forSignups: Mastodon.Entity.NotificationPolicy.NotificationFilterAction
|
||||
|
||||
var excludedNotificationTypes: [Mastodon.Entity.NotificationType]? {
|
||||
var excluded = [Mastodon.Entity.NotificationType]()
|
||||
if forReports != .accept {
|
||||
excluded.append(.adminReport)
|
||||
}
|
||||
if forSignups != .accept {
|
||||
excluded.append(.adminSignUp)
|
||||
}
|
||||
return excluded.isEmpty ? nil : excluded
|
||||
}
|
||||
}
|
||||
|
||||
extension FilterAction {
|
||||
var displayTitle: String {
|
||||
switch self {
|
||||
case .accept: return L10n.Scene.Notification.Policy.Action.Accept.title
|
||||
case .filter: return L10n.Scene.Notification.Policy.Action.Filter.title
|
||||
case .drop: return L10n.Scene.Notification.Policy.Action.Drop.title
|
||||
case ._other(let string): return string
|
||||
}
|
||||
}
|
||||
|
||||
var displaySubtitle: String {
|
||||
switch self {
|
||||
case .accept: return L10n.Scene.Notification.Policy.Action.Accept.subtitle
|
||||
case .filter: return L10n.Scene.Notification.Policy.Action.Filter.subtitle
|
||||
case .drop: return L10n.Scene.Notification.Policy.Action.Drop.subtitle
|
||||
case ._other: return ""
|
||||
}
|
||||
}
|
||||
}
|
@ -944,6 +944,8 @@ public enum L10n {
|
||||
/// View report
|
||||
public static let viewReport = L10n.tr("Localizable", "Scene.Notification.ViewReport", fallback: "View report")
|
||||
public enum AdminFilter {
|
||||
/// Admin Notifications
|
||||
public static let title = L10n.tr("Localizable", "Scene.Notification.AdminFilter.Title", fallback: "Admin Notifications")
|
||||
public enum Reports {
|
||||
/// Show reports of spam, rule violations, and other complaints
|
||||
public static let subtitle = L10n.tr("Localizable", "Scene.Notification.AdminFilter.Reports.Subtitle", fallback: "Show reports of spam, rule violations, and other complaints")
|
||||
|
@ -400,6 +400,7 @@ Please retry in a few minutes.";
|
||||
"Scene.Notification.Policy.Action.Drop.Title" = "Ignore";
|
||||
"Scene.Notification.Policy.Action.Drop.Subtitle" = "Send to the void, never to be seen again";
|
||||
"Scene.Notification.Policy.Title" = "Filter Notifications from…";
|
||||
"Scene.Notification.AdminFilter.Title" = "Admin Notifications";
|
||||
"Scene.Notification.AdminFilter.Reports.Title" = "Admin reports";
|
||||
"Scene.Notification.AdminFilter.Reports.Subtitle" = "Show reports of spam, rule violations, and other complaints";
|
||||
"Scene.Notification.AdminFilter.Signups.Title" = "Account signups";
|
||||
|
Loading…
x
Reference in New Issue
Block a user