From 030c3e126006e89c63f9a141a53141874c2584ee Mon Sep 17 00:00:00 2001 From: shannon Date: Wed, 2 Apr 2025 13:24:58 -0400 Subject: [PATCH] Distinguish between different types of admin reports in the notifications screen --- Localization/app.json | 4 ++ .../NotificationInfo.swift | 2 +- .../NotificationRowView.swift | 41 +++++++++++++++---- .../NotificationRowViewModel.swift | 4 +- .../Generated/Strings.swift | 16 ++++++++ .../Resources/Base.lproj/Localizable.strings | 4 ++ .../Entity/Mastodon+Entity+Notification.swift | 8 ++-- .../Entity/Mastodon+Entity+Report.swift | 24 +++++++++++ 8 files changed, 89 insertions(+), 14 deletions(-) diff --git a/Localization/app.json b/Localization/app.json index f48d048cd..f30b1afe2 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -769,6 +769,10 @@ "single_name_signed_up": "%@ signed up", "someone_reported_account_for_rule_violation": "Someone reported %@ for rule violation.", "someone_reported_posts_from_account_for_rule_violation": "Someone reported %@ from %@ for rule violation." + "someone_reported_account_for_spam": "Someone reported %@ for spam.", + "someone_reported_posts_from_account_for_spam": "Someone reported %@ from %@ for spam." + "someone_reported_account": "Someone reported %@.", + "someone_reported_posts_from_account": "Someone reported %@ from %@." }, "notification_description": { "followed_you": "followed you", diff --git a/Mastodon/In Progress New Layout and Datamodel/NotificationInfo.swift b/Mastodon/In Progress New Layout and Datamodel/NotificationInfo.swift index 51f056197..9dae79f62 100644 --- a/Mastodon/In Progress New Layout and Datamodel/NotificationInfo.swift +++ b/Mastodon/In Progress New Layout and Datamodel/NotificationInfo.swift @@ -16,7 +16,7 @@ protocol NotificationInfo { var authorAvatarUrls: [URL] { get } func availableRelationshipElement() async -> RelationshipElement? func fetchRelationshipElement() async -> RelationshipElement - var ruleViolationReport: Mastodon.Entity.Report? { get } + var adminReport: Mastodon.Entity.Report? { get } var relationshipSeveranceEvent: Mastodon.Entity.RelationshipSeveranceEvent? { get } } diff --git a/Mastodon/In Progress New Layout and Datamodel/NotificationRowView.swift b/Mastodon/In Progress New Layout and Datamodel/NotificationRowView.swift index 1a9c1c4f5..41c65c2d4 100644 --- a/Mastodon/In Progress New Layout and Datamodel/NotificationRowView.swift +++ b/Mastodon/In Progress New Layout and Datamodel/NotificationRowView.swift @@ -163,15 +163,42 @@ extension GroupedNotificationType { extension Mastodon.Entity.Report { // "Someone reported X posts from someone else for rule violation" + // "Someone reported X posts from someone else for spam" + // "Someone reported X posts from someone else" var summary: AttributedString { if let targetedAccountName = targetAccount?.displayNameWithFallback { - let summaryPlainstring: String - if let postCount = flaggedStatusIDs?.count { - let postsString = L10n.Plural.Count.post(postCount) - summaryPlainstring = L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedPostsFromAccountForRuleViolation(postsString, targetedAccountName) - } else { - summaryPlainstring = L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedAccountForRuleViolation(targetedAccountName) - } + + let postCountString: String? = { + if let postCount = flaggedStatusIDs?.count { + return L10n.Plural.Count.post(postCount) + } else { + return nil + } + }() + + let summaryPlainstring: String = { + switch category { + case .spam: + if let postCountString { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedPostsFromAccountForSpam(postCountString, targetedAccountName) + } else { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedAccountForSpam(targetedAccountName) + } + case .violation: + if let postCountString { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedPostsFromAccountForRuleViolation(postCountString, targetedAccountName) + } else { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedAccountForRuleViolation(targetedAccountName) + } + case ._other, nil: + if let postCountString { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedPostsFromAccount(postCountString, targetedAccountName) + } else { + return L10n.Scene.Notification.GroupedNotificationDescription.someoneReportedAccount(targetedAccountName) + } + } + }() + var attributedString = AttributedString(summaryPlainstring) let boldedName = styledNameComponent(targetedAccountName, style: AttributeContainer.font( .system(.body, weight: .bold)), emojis: targetAccount?.emojiMeta) diff --git a/Mastodon/In Progress New Layout and Datamodel/NotificationRowViewModel.swift b/Mastodon/In Progress New Layout and Datamodel/NotificationRowViewModel.swift index fbebfaba5..967bd19aa 100644 --- a/Mastodon/In Progress New Layout and Datamodel/NotificationRowViewModel.swift +++ b/Mastodon/In Progress New Layout and Datamodel/NotificationRowViewModel.swift @@ -838,7 +838,7 @@ extension GroupedNotificationType { case .adminSignUp: self = .adminSignUp case .adminReport: - self = .adminReport(notification.ruleViolationReport) + self = .adminReport(notification.adminReport) case .severedRelationships: let url = severedRelationshipsUrl( forDomain: myAccountDomain, @@ -883,7 +883,7 @@ extension GroupedNotificationType { case .adminSignUp: self = .adminSignUp case .adminReport: - self = .adminReport(notificationGroup.ruleViolationReport) + self = .adminReport(notificationGroup.adminReport) case .severedRelationships: let url = severedRelationshipsUrl(forDomain: myAccountDomain, notificationID: String(notificationGroup.mostRecentNotificationID)) self = .severedRelationships( diff --git a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift index 1ea692d79..6676e5c52 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift +++ b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift @@ -1012,14 +1012,30 @@ public enum L10n { public static func singleNameSignedUp(_ p1: Any) -> String { return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SingleNameSignedUp", String(describing: p1), fallback: "%@ signed up") } + /// Someone reported %@. + public static func someoneReportedAccount(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccount", String(describing: p1), fallback: "Someone reported %@.") + } /// Someone reported %@ for rule violation. public static func someoneReportedAccountForRuleViolation(_ p1: Any) -> String { return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccountForRuleViolation", String(describing: p1), fallback: "Someone reported %@ for rule violation.") } + /// Someone reported %@ for spam. + public static func someoneReportedAccountForSpam(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccountForSpam", String(describing: p1), fallback: "Someone reported %@ for spam.") + } + /// Someone reported %@ from %@. + public static func someoneReportedPostsFromAccount(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccount", String(describing: p1), String(describing: p2), fallback: "Someone reported %@ from %@.") + } /// Someone reported %@ from %@ for rule violation. public static func someoneReportedPostsFromAccountForRuleViolation(_ p1: Any, _ p2: Any) -> String { return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccountForRuleViolation", String(describing: p1), String(describing: p2), fallback: "Someone reported %@ from %@ for rule violation.") } + /// Someone reported %@ from %@ for spam. + public static func someoneReportedPostsFromAccountForSpam(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccountForSpam", String(describing: p1), String(describing: p2), fallback: "Someone reported %@ from %@ for spam.") + } /// Your poll has ended public static let yourPollHasEnded = L10n.tr("Localizable", "Scene.Notification.GroupedNotificationDescription.YourPollHasEnded", fallback: "Your poll has ended") } diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings index 3d75feab5..8ea4515e9 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings @@ -357,6 +357,10 @@ Please retry in a few minutes."; "Scene.Notification.GroupedNotificationDescription.SingleNameSignedUp" = "%@ signed up"; "Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccountForRuleViolation" = "Someone reported %@ for rule violation."; "Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccountForRuleViolation" = "Someone reported %@ from %@ for rule violation."; +"Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccountForSpam" = "Someone reported %@ from %@ for spam."; +"Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccountForSpam" = "Someone reported %@ for spam."; +"Scene.Notification.GroupedNotificationDescription.SomeoneReportedPostsFromAccount" = "Someone reported %@ from %@."; +"Scene.Notification.GroupedNotificationDescription.SomeoneReportedAccount" = "Someone reported %@."; "Scene.Notification.GroupedNotificationDescription.YourPollHasEnded" = "Your poll has ended"; "Scene.Notification.Headers.Boost" = "Boost"; "Scene.Notification.Headers.Edit" = "Edit"; diff --git a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Notification.swift b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Notification.swift index dd3fd4a7a..b4125607a 100644 --- a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Notification.swift +++ b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Notification.swift @@ -25,7 +25,7 @@ extension Mastodon.Entity { public let groupKey: String? public let account: Account public let status: Status? - public let ruleViolationReport: Report? + public let adminReport: Report? public let relationshipSeveranceEvent: RelationshipSeveranceEvent? public let accountWarning: AccountWarning? @@ -36,7 +36,7 @@ extension Mastodon.Entity { case createdAt = "created_at" case account case status - case ruleViolationReport = "report" + case adminReport = "report" case accountWarning = "moderation_warning" case relationshipSeveranceEvent = "event" } @@ -62,7 +62,7 @@ extension Mastodon.Entity { public let latestPageNotificationAt: Date? // Date at which the most recent notification from this group within the current page has been created. This is only returned when paginating through notification groups. public let sampleAccountIDs: [String] // IDs of some of the accounts who most recently triggered notifications in this group. public let statusID: ID? - public let ruleViolationReport: Report? // Attached when type of the notification is admin.report + public let adminReport: Report? // Attached when type of the notification is admin.report public let relationshipSeveranceEvent: RelationshipSeveranceEvent? // Attached when type of the notification is severed_relationships public let accountWarning: AccountWarning? @@ -76,7 +76,7 @@ extension Mastodon.Entity { case latestPageNotificationAt = "latest_page_notification_at" case sampleAccountIDs = "sample_account_ids" case statusID = "status_id" - case ruleViolationReport = "report" + case adminReport = "report" case accountWarning = "moderation_warning" case relationshipSeveranceEvent = "event" } diff --git a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Report.swift b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Report.swift index c9f0b1d35..8ca41524f 100644 --- a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Report.swift +++ b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Report.swift @@ -24,6 +24,7 @@ extension Mastodon.Entity { public let targetAccount: Account? // The account that was reported. public let flaggedStatusIDs: [String]? // IDs of statuses that have been attached to this report for additional context. public let comment: String? // The reason for the report. + public let category: Category? // the type of report enum CodingKeys: String, CodingKey { case id @@ -31,6 +32,29 @@ extension Mastodon.Entity { case targetAccount = "target_account" case flaggedStatusIDs = "status_ids" case comment + case category + } + + public enum Category: RawRepresentable, Codable, Sendable { + case spam + case violation + case _other(String) + + public init?(rawValue: String) { + switch rawValue { + case "spam": self = .spam + case "violation": self = .violation + default: self = ._other(rawValue) + } + } + + public var rawValue: RawValue { + switch self { + case .spam: return "spam" + case .violation: return "violation" + case ._other(let string): return string + } + } } } }