Skip to content

Commit

Permalink
新增功能: 桌面小部件, 展示最近消息, 支持收到推送自动刷新;
Browse files Browse the repository at this point in the history
新增功能: 1分钟内删除两条消息, 会提示是否一键清空全部消息.
  • Loading branch information
Hext123 committed Apr 18, 2022
1 parent a685433 commit c3d0cd1
Show file tree
Hide file tree
Showing 31 changed files with 1,199 additions and 19 deletions.
13 changes: 13 additions & 0 deletions ios/PushDeer-iOS/Notification/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?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>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
</dict>
</plist>
10 changes: 10 additions & 0 deletions ios/PushDeer-iOS/Notification/Notification.entitlements
Original file line number Diff line number Diff line change
@@ -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.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
39 changes: 39 additions & 0 deletions ios/PushDeer-iOS/Notification/NotificationService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// NotificationService.swift
// Notification
//
// Created by HEXT on 2022/4/19.
//

import UserNotifications
import WidgetKit

class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
// bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"

contentHandler(bestAttemptContent)
}

// 刷新所有桌面小部件
WidgetCenter.shared.reloadAllTimelines()
}

override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}

}
5 changes: 5 additions & 0 deletions ios/PushDeer-iOS/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ target 'PushDeerClip' do

end

target 'PushDeerWidgetExtension' do
# Pods for PushDeerWidgetExtension
pod 'Moya', '~> 15.0'
end

# define unsupported pods
def unsupported_pods
# macCatalyst 不支持的库
Expand Down
2 changes: 1 addition & 1 deletion ios/PushDeer-iOS/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ SPEC CHECKSUMS:
WechatOpenSDK: 6a4d1436c15b3b5fe2a0bd383f3046010186da44
WoodPeckeriOS: 12ec7f38c695e51cd94a476228888dfe85d9d916

PODFILE CHECKSUM: 1b349626994062a8291e3db07d3dbf087894c4d2
PODFILE CHECKSUM: 42e3d8abd976589c1043ff9f9e864c275a490160

COCOAPODS: 1.11.2
494 changes: 493 additions & 1 deletion ios/PushDeer-iOS/PushDeer.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions ios/PushDeer-iOS/PushDeer/Env.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,13 @@ struct Env {
static let wxUniversalLink = "https://vip.pushdeer.com/app/"
/// PushDeer 官网地址
static let officialWebsite = "https://www.pushdeer.com"
/// 共享组名, 使用它来访问 App Clip Widget 共享数据
static let appGroupId: String = {
#if SELFHOSTED
return "group.com.pushdeer.self.ios"
#else
return "group.com.pushdeer.app.ios"
#endif
}()

}
13 changes: 13 additions & 0 deletions ios/PushDeer-iOS/PushDeer/Model/MessageModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ extension MessageModel {
static let _viewContext = PersistenceController.shared.container.viewContext
static let _fetchRequest = MessageModel.fetchRequest()

/// 删除本地持久化的所有消息
static func deleteAll() throws -> Void {
// let fetchRequest: NSFetchRequest<NSFetchRequestResult> = MessageModel.fetchRequest()
// let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
// try _viewContext.execute(deleteRequest)
let fetchRequest = MessageModel.fetchRequest()
let models = try _viewContext.fetch(fetchRequest)
models.forEach { model in
_viewContext.delete(model)
}
try _viewContext.save()
}

/// 持久化保存和更新
static func saveAndUpdate(messageItems: [MessageItem]) throws -> Void {
try messageItems.forEach(saveAndUpdate)
Expand Down
4 changes: 4 additions & 0 deletions ios/PushDeer-iOS/PushDeer/PushDeer-SelfHosted.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.pushdeer.self.ios</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.personal-information.photos-library</key>
Expand Down
4 changes: 4 additions & 0 deletions ios/PushDeer-iOS/PushDeer/PushDeer.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.pushdeer.app.ios</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.personal-information.photos-library</key>
Expand Down
5 changes: 5 additions & 0 deletions ios/PushDeer-iOS/PushDeer/PushDeerApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import SwiftUI
import WidgetKit

@main
struct PushDeerApp: App {
Expand Down Expand Up @@ -39,6 +40,10 @@ struct PushDeerApp: App {
}
}
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification), perform: { _ in
// APP将要进入非活跃状态时, 刷新小部件
WidgetCenter.shared.reloadAllTimelines()
})
.environmentObject(store)
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
Expand Down
77 changes: 60 additions & 17 deletions ios/PushDeer-iOS/PushDeer/Service/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import AuthenticationServices

class AppState: ObservableObject {
/// 账号 token
@Published var token : String {
@Published var token : String = "" {
didSet {
UserDefaults.standard.set(token, forKey: "PushDeer_token")
getUserDefaults().set(token, forKey: "PushDeer_token")
}
}
/// 设备列表
Expand All @@ -22,38 +22,38 @@ class AppState: ObservableObject {
/// 消息列表
// @Published var messages: [MessageItem] = []
/// 选中的 tab 下标
@Published var tabSelectedIndex: Int {
@Published var tabSelectedIndex: Int = 2 {
didSet {
UserDefaults.standard.set(tabSelectedIndex, forKey: "PushDeer_tabSelectedIndex")
getUserDefaults().set(tabSelectedIndex, forKey: "PushDeer_tabSelectedIndex")
}
}
/// 设备推送 token
@Published var deviceToken: String = ""
/// 用户信息
@Published var userInfo: UserInfoContent?
/// 是否显示测试发推送的 UI
@Published var isShowTestPush: Bool {
@Published var isShowTestPush: Bool = true {
didSet {
UserDefaults.standard.set(isShowTestPush, forKey: "PushDeer_isShowTestPush")
getUserDefaults().set(isShowTestPush, forKey: "PushDeer_isShowTestPush")
}
}
/// 是否使用内置浏览器打开链接
@Published var isUseBuiltInBrowser: Bool {
@Published var isUseBuiltInBrowser: Bool = true {
didSet {
UserDefaults.standard.set(isUseBuiltInBrowser, forKey: "PushDeer_isUseBuiltInBrowser")
getUserDefaults().set(isUseBuiltInBrowser, forKey: "PushDeer_isUseBuiltInBrowser")
}
}
/// MarkDown BaseURL
@Published var markDownBaseURL: String? {
didSet {
UserDefaults.standard.set(markDownBaseURL, forKey: "PushDeer_markDownBaseURL")
getUserDefaults().set(markDownBaseURL, forKey: "PushDeer_markDownBaseURL")
}
}

/// API endpoint
@Published var api_endpoint : String {
@Published var api_endpoint : String = "" {
didSet {
UserDefaults.standard.set(api_endpoint, forKey: "PushDeer_api_endpoint")
getUserDefaults().set(api_endpoint, forKey: "PushDeer_api_endpoint")
}
}

Expand All @@ -68,12 +68,26 @@ class AppState: ObservableObject {

static let shared = AppState()
private init() {
let _token = UserDefaults.standard.string(forKey: "PushDeer_token")
let _tabSelectedIndex = UserDefaults.standard.integer(forKey: "PushDeer_tabSelectedIndex")
let _isShowTestPush = UserDefaults.standard.object(forKey: "PushDeer_isShowTestPush")
let _isUseBuiltInBrowser = UserDefaults.standard.object(forKey: "PushDeer_isUseBuiltInBrowser")
let _markDownBaseURL = UserDefaults.standard.string(forKey: "PushDeer_markDownBaseURL")
let _api_endpoint = UserDefaults.standard.string(forKey: "PushDeer_api_endpoint")
reloadUserDefaults()
moveOldUserDefaults()
}

func getUserDefaults() -> UserDefaults {
let ud = UserDefaults(suiteName: Env.appGroupId)
if let ud = ud {
return ud
} else {
return UserDefaults.standard
}
}

func reloadUserDefaults() -> Void {
let _token = getUserDefaults().string(forKey: "PushDeer_token")
let _tabSelectedIndex = getUserDefaults().integer(forKey: "PushDeer_tabSelectedIndex")
let _isShowTestPush = getUserDefaults().object(forKey: "PushDeer_isShowTestPush")
let _isUseBuiltInBrowser = getUserDefaults().object(forKey: "PushDeer_isUseBuiltInBrowser")
let _markDownBaseURL = getUserDefaults().string(forKey: "PushDeer_markDownBaseURL")
let _api_endpoint = getUserDefaults().string(forKey: "PushDeer_api_endpoint")
token = _token ?? ""
tabSelectedIndex = _tabSelectedIndex
isShowTestPush = _isShowTestPush as? Bool ?? true
Expand All @@ -82,6 +96,35 @@ class AppState: ObservableObject {
api_endpoint = _api_endpoint ?? ""
}

/// 迁移老版本数据, 老版本不是存在共享组中, 需要迁移到共享组
func moveOldUserDefaults() -> Void {
let oldUserDefaults = UserDefaults.standard
if let _token = oldUserDefaults.string(forKey: "PushDeer_token") {
oldUserDefaults.removeObject(forKey: "PushDeer_token")
token = _token
}
if let _tabSelectedIndex = oldUserDefaults.object(forKey: "PushDeer_tabSelectedIndex") as? Int {
oldUserDefaults.removeObject(forKey: "PushDeer_tabSelectedIndex")
tabSelectedIndex = _tabSelectedIndex
}
if let _isShowTestPush = oldUserDefaults.object(forKey: "PushDeer_isShowTestPush") as? Bool {
oldUserDefaults.removeObject(forKey: "PushDeer_isShowTestPush")
isShowTestPush = _isShowTestPush
}
if let _isUseBuiltInBrowser = oldUserDefaults.object(forKey: "PushDeer_isUseBuiltInBrowser") as? Bool {
oldUserDefaults.removeObject(forKey: "PushDeer_isUseBuiltInBrowser")
isUseBuiltInBrowser = _isUseBuiltInBrowser
}
if let _markDownBaseURL = oldUserDefaults.string(forKey: "PushDeer_markDownBaseURL") {
oldUserDefaults.removeObject(forKey: "PushDeer_markDownBaseURL")
markDownBaseURL = _markDownBaseURL
}
if let _api_endpoint = oldUserDefaults.string(forKey: "PushDeer_api_endpoint") {
oldUserDefaults.removeObject(forKey: "PushDeer_api_endpoint")
api_endpoint = _api_endpoint
}
}

func appleIdLogin(_ result: Result<ASAuthorization, Error>) async throws -> TokenContent {
switch result {
case let .success(authorization):
Expand Down
4 changes: 4 additions & 0 deletions ios/PushDeer-iOS/PushDeer/Service/HttpRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,8 @@ struct HttpRequest {
static func rmMessage(id: Int) async throws -> ActionContent {
return try await request(.rmMessage(token: AppState.shared.token, id: id), resultType: ActionContent.self)
}

static func rmAllMessage() async throws -> ActionContent {
return try await request(.rmAllMessage(token: AppState.shared.token), resultType: ActionContent.self)
}
}
5 changes: 5 additions & 0 deletions ios/PushDeer-iOS/PushDeer/Service/PushDeerApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum PushDeerApi {

case getMessages(token: String, limit: Int)
case rmMessage(token: String, id: Int)
case rmAllMessage(token: String)

}

Expand Down Expand Up @@ -91,6 +92,8 @@ extension PushDeerApi: TargetType {
return "/message/list"
case .rmMessage:
return "/message/remove"
case .rmAllMessage:
return "/message/clean"
}
}
var method: Moya.Method {
Expand Down Expand Up @@ -139,6 +142,8 @@ extension PushDeerApi: TargetType {
return .requestParameters(parameters: ["token": token, "limit": limit],encoding: URLEncoding.queryString)
case let .rmMessage(token, id):
return .requestParameters(parameters: ["token": token, "id": id],encoding: URLEncoding.queryString)
case let .rmAllMessage(token):
return .requestParameters(parameters: ["token": token],encoding: URLEncoding.queryString)

}
}
Expand Down
Loading

0 comments on commit c3d0cd1

Please sign in to comment.