下拉或长按推送,可以选择对推送分组暂时静音1小时。

close: #138
This commit is contained in:
Fin 2024-11-06 14:16:09 +08:00
parent e7abff51c9
commit 58d56a2d55
9 changed files with 160 additions and 11 deletions

View File

@ -122,6 +122,10 @@
06BBB8C12567B3EF0076F63E /* BaseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */; };
06BBB8C92567B6730076F63E /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8C82567B6730076F63E /* Operators.swift */; };
06BBB8CE2567B8E60076F63E /* silence.caf in Resources */ = {isa = PBXBuildFile; fileRef = 06BBB8CD2567B8E60076F63E /* silence.caf */; };
06BCAE562CDB19260092867A /* GroupMuteSettingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BCAE552CDB19260092867A /* GroupMuteSettingManager.swift */; };
06BCAE572CDB19420092867A /* GroupMuteSettingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BCAE552CDB19260092867A /* GroupMuteSettingManager.swift */; };
06BCAE582CDB19420092867A /* GroupMuteSettingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BCAE552CDB19260092867A /* GroupMuteSettingManager.swift */; };
06BCAE5B2CDB25120092867A /* MuteProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BCAE5A2CDB25120092867A /* MuteProcessor.swift */; };
06BD4DAA2901352E003364DB /* Object+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BD4DA92901352E003364DB /* Object+Dictionary.swift */; };
06C2CF232685B88D0034B127 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C2CF222685B88D0034B127 /* TextCell.swift */; };
06C2CF252685BDB80034B127 /* SpacerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C2CF242685BDB80034B127 /* SpacerCell.swift */; };
@ -348,6 +352,9 @@
06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTableViewCell.swift; sourceTree = "<group>"; };
06BBB8C82567B6730076F63E /* Operators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
06BBB8CD2567B8E60076F63E /* silence.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = silence.caf; sourceTree = "<group>"; };
06BCAE552CDB19260092867A /* GroupMuteSettingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMuteSettingManager.swift; sourceTree = "<group>"; };
06BCAE592CDB19590092867A /* NotificationContentExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationContentExtension.entitlements; sourceTree = "<group>"; };
06BCAE5A2CDB25120092867A /* MuteProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MuteProcessor.swift; sourceTree = "<group>"; };
06BD4DA92901352E003364DB /* Object+Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Object+Dictionary.swift"; sourceTree = "<group>"; };
06C2CF222685B88D0034B127 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
06C2CF242685BDB80034B127 /* SpacerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpacerCell.swift; sourceTree = "<group>"; };
@ -555,6 +562,7 @@
0632CE2120EC9098003FDF46 /* NotificationContentExtension */ = {
isa = PBXGroup;
children = (
06BCAE592CDB19590092867A /* NotificationContentExtension.entitlements */,
0632CE2220EC9098003FDF46 /* NotificationViewController.swift */,
0632CE2420EC9098003FDF46 /* MainInterface.storyboard */,
0632CE2720EC9098003FDF46 /* Info.plist */,
@ -587,6 +595,7 @@
06F08EAB29B1DECD006AB9CA /* NSLocalizedString+Extension.swift */,
06E944742C07012E00AC86AB /* RealmConfiguration.swift */,
0687F2A72CCB791A00B2A52F /* UIFont+Extension.swift */,
06BCAE552CDB19260092867A /* GroupMuteSettingManager.swift */,
);
path = Common;
sourceTree = "<group>";
@ -667,6 +676,7 @@
06E9447B2C07052F00AC86AB /* ImageProcessor.swift */,
06D69E402C11983E00161A35 /* CallProcessor.swift */,
06E944792C0704E500AC86AB /* ImageDownloader.swift */,
06BCAE5A2CDB25120092867A /* MuteProcessor.swift */,
);
path = Processor;
sourceTree = "<group>";
@ -1110,6 +1120,7 @@
files = (
0687F2AA2CCB7FA500B2A52F /* UIFont+Extension.swift in Sources */,
0632CE2320EC9098003FDF46 /* NotificationViewController.swift in Sources */,
06BCAE572CDB19420092867A /* GroupMuteSettingManager.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1146,6 +1157,7 @@
06F08EA729B1DDFE006AB9CA /* Error+Extension.swift in Sources */,
0687F2A82CCB791A00B2A52F /* UIFont+Extension.swift in Sources */,
06B1158F247BB1FB006D91FB /* Message.swift in Sources */,
06BCAE562CDB19260092867A /* GroupMuteSettingManager.swift in Sources */,
06172FDA27F6DAEF002333A4 /* ServerListTableViewCell.swift in Sources */,
0653677829B727A60038BDB8 /* CryptoSettingRelay.swift in Sources */,
06FB04042C53575400F3A213 /* SharedDefines.swift in Sources */,
@ -1215,6 +1227,8 @@
06F08EAD29B1DED6006AB9CA /* NSLocalizedString+Extension.swift in Sources */,
0653677629B719BC0038BDB8 /* CryptoSettingManager.swift in Sources */,
06E9446F2C06FF1E00AC86AB /* BadgeProcessor.swift in Sources */,
06BCAE582CDB19420092867A /* GroupMuteSettingManager.swift in Sources */,
06BCAE5B2CDB25120092867A /* MuteProcessor.swift in Sources */,
06E9446D2C06FEC900AC86AB /* LevelProcessor.swift in Sources */,
06E944682C06E40600AC86AB /* NotificationContentProcessor.swift in Sources */,
06F08EA529B1DDA7006AB9CA /* Algorithm.swift in Sources */,
@ -1283,6 +1297,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_ENTITLEMENTS = NotificationContentExtension/NotificationContentExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
@ -1304,6 +1319,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_ENTITLEMENTS = NotificationContentExtension/NotificationContentExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;

View File

@ -90,10 +90,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
self.window?.makeKeyAndVisible()
UNUserNotificationCenter.current().delegate = self
var actions = [
UNNotificationAction(identifier: "copy", title: NSLocalizedString("Copy2"), options: UNNotificationActionOptions.foreground)
]
if #available(iOSApplicationExtension 15.0, *) {
actions.append(UNNotificationAction(identifier: "mute", title: NSLocalizedString("muteGroup1Hour"), options: UNNotificationActionOptions.foreground))
}
UNUserNotificationCenter.current().setNotificationCategories([
UNNotificationCategory(identifier: "myNotificationCategory", actions: [
UNNotificationAction(identifier: "copy", title: NSLocalizedString("Copy2"), options: UNNotificationActionOptions.foreground)
], intentIdentifiers: [], options: .customDismissAction)
UNNotificationCategory(identifier: "myNotificationCategory", actions: actions, intentIdentifiers: [], options: .customDismissAction)
])
UNUserNotificationCenter.current().getNotificationSettings { settings in

View File

@ -1350,6 +1350,23 @@
}
}
},
"groupMuted" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Group \"%@\" muted!"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "分组 \"%@\" 已静音"
}
}
}
},
"hideAllGroups" : {
"extractionState" : "manual",
"localizations" : {
@ -1764,6 +1781,23 @@
}
}
},
"muteGroup1Hour" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mute this group for 1 Hour"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "1小时内不再提醒此分组"
}
}
}
},
"Notice1" : {
"extractionState" : "manual",
"localizations" : {

View File

@ -0,0 +1,35 @@
//
// GroupMuteSettingManager.swift
// Bark
//
// Created by huangfeng on 11/6/24.
// Copyright © 2024 Fin. All rights reserved.
//
import UIKit
let kGroupMuteSettingKey = "groupMuteSettings"
/// NotificationServiceExtension NotificationContentExtension
class GroupMuteSettingManager: NSObject {
let defaults = UserDefaults(suiteName: "group.bark")
var settings: [String: Date] = [:] {
didSet {
defaults?.set(settings, forKey: kGroupMuteSettingKey)
}
}
override init() {
super.init()
if let settings = defaults?.dictionary(forKey: kGroupMuteSettingKey) as? [String: Date] {
self.settings = settings
}
//
for setting in settings {
if setting.value < Date() {
self.settings.removeValue(forKey: setting.key)
}
}
}
}

View File

@ -33,6 +33,7 @@ class NotificationService: UNNotificationServiceExtension {
.archive,
.setIcon,
.setImage,
.mute,
.call
]

View File

@ -0,0 +1,23 @@
//
// MuteProcessor.swift
// NotificationServiceExtension
//
// Created by huangfeng on 11/6/24.
// Copyright © 2024 Fin. All rights reserved.
//
import UIKit
class MuteProcessor: NotificationContentProcessor {
func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
let groupName = bestAttemptContent.threadIdentifier
guard let date = GroupMuteSettingManager().settings[groupName], date > Date() else {
return bestAttemptContent
}
//
if #available(iOSApplicationExtension 15.0, *) {
bestAttemptContent.interruptionLevel = .passive
}
return bestAttemptContent
}
}

View File

@ -18,6 +18,7 @@ enum NotificationContentProcessorItem {
case setIcon
case setImage
case call
case mute
var processor: NotificationContentProcessor {
switch self {
@ -37,6 +38,8 @@ enum NotificationContentProcessorItem {
return ImageProcessor()
case .call:
return CallProcessor()
case .mute:
return MuteProcessor()
}
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.bark</string>
</array>
</dict>
</plist>

View File

@ -14,7 +14,6 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
let noticeLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor(named: "notification_copy_color")
label.text = NSLocalizedString("Copy", comment: "")
label.font = UIFont.preferredFont(ofSize: 16)
label.adjustsFontForContentSizeCategory = true
label.textAlignment = .center
@ -45,25 +44,49 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
}
if let copy = notification.request.content.userInfo["copy"] as? String {
UIPasteboard.general.string = copy
}
else {
} else {
UIPasteboard.general.string = notification.request.content.body
}
}
func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
switch response.actionIdentifier {
case "copy":
self.copyAction(response, completionHandler: completion)
case "mute":
self.muteAction(response, completionHandler: completion)
default:
completion(.dismiss)
}
}
///
func copyAction(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
let userInfo = response.notification.request.content.userInfo
if let copy = userInfo["copy"] as? String {
UIPasteboard.general.string = copy
}
else {
} else {
UIPasteboard.general.string = response.notification.request.content.body
}
self.preferredContentSize = CGSize(width: 0, height: 40)
self.noticeLabel.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 40)
showTips(text: NSLocalizedString("Copy", comment: ""))
completion(.doNotDismiss)
}
///
func muteAction(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
let groupName = response.notification.request.content.threadIdentifier
//
GroupMuteSettingManager().settings[groupName] = Date() + 60 * 60
showTips(text: String(format: NSLocalizedString("groupMuted", comment: ""), groupName.isEmpty ? "default" : groupName))
completion(.doNotDismiss)
}
func showTips(text: String) {
self.preferredContentSize = CGSize(width: 0, height: 40)
self.noticeLabel.text = text
self.noticeLabel.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 40)
}
}