添加未读消息的后台更新逻辑
This commit is contained in:
parent
ea022e56d3
commit
b0c89d9998
@ -10,6 +10,11 @@
|
|||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
|
<string>fetch</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||||
|
<array>
|
||||||
|
<string>com.jihe.dimensionhub.refresh</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -8,28 +8,31 @@ import SwiftUI
|
|||||||
|
|
||||||
// 自定义修饰符
|
// 自定义修饰符
|
||||||
extension View {
|
extension View {
|
||||||
func autoDismiss(after seconds: Double) -> some View {
|
func autoDismiss(isHidden: Binding<Bool>, after seconds: Double) -> some View {
|
||||||
modifier(AutoDismissModifier(seconds: seconds))
|
modifier(AutoDismissModifier(isHidden: isHidden, seconds: seconds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AutoDismissModifier: ViewModifier {
|
struct AutoDismissModifier: ViewModifier {
|
||||||
|
@Binding var isHidden: Bool
|
||||||
let seconds: Double
|
let seconds: Double
|
||||||
@State private var isVisible = true
|
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
if isVisible {
|
content
|
||||||
content
|
.opacity(isHidden ? 0 : 1)
|
||||||
.onAppear {
|
.frame(height: isHidden ? 0 : nil)
|
||||||
Task {
|
.onAppear {
|
||||||
try? await Task.sleep(for: .seconds(seconds))
|
Task {
|
||||||
withAnimation(.easeOut) {
|
print("call me task: \(isHidden)")
|
||||||
isVisible = false
|
try? await Task.sleep(for: .seconds(seconds))
|
||||||
}
|
withAnimation(.easeOut) {
|
||||||
|
isHidden = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
EmptyView()
|
.onChange(of: isHidden) { oldValue, newValue in
|
||||||
}
|
print("curernt value is: \(isHidden)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ struct IndexMainView: View {
|
|||||||
@State private var showDateNavPopover: Bool = false
|
@State private var showDateNavPopover: Bool = false
|
||||||
|
|
||||||
// 前向刷新提示信息
|
// 前向刷新提示信息
|
||||||
@State private var noMoreNewest: Bool = false
|
@State private var hasMoreNewest: Bool = true
|
||||||
@State private var hasMoreOldest: Bool = false
|
@State private var hasMoreOldest: Bool = false
|
||||||
|
|
||||||
// 刷新逻辑
|
// 刷新逻辑
|
||||||
@ -72,10 +72,15 @@ struct IndexMainView: View {
|
|||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
ScrollViewOffsetReader(offset: $scrollOffset)
|
ScrollViewOffsetReader(offset: $scrollOffset)
|
||||||
|
|
||||||
if noMoreNewest {
|
if !hasMoreNewest {
|
||||||
Text("没有了")
|
Text("没有了")
|
||||||
.foregroundColor(.black)
|
.foregroundColor(.black)
|
||||||
.autoDismiss(after: 1.5)
|
.task {
|
||||||
|
try? await Task.sleep(for: .seconds(1.5))
|
||||||
|
withAnimation(.easeOut) {
|
||||||
|
hasMoreNewest = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MixGroupLabelView(fixedDramaGroup: indexModel.fixedDramaGroup) {
|
MixGroupLabelView(fixedDramaGroup: indexModel.fixedDramaGroup) {
|
||||||
@ -125,15 +130,13 @@ struct IndexMainView: View {
|
|||||||
|
|
||||||
// 上拉刷新功能
|
// 上拉刷新功能
|
||||||
self.headerRefreshing = true
|
self.headerRefreshing = true
|
||||||
self.noMoreNewest = false
|
|
||||||
|
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
await self.indexModel.loadPrevUpdateDramasTask(userId: self.userId) { hasData in
|
let loadNum = await self.indexModel.loadPrevUpdateDramasTask(userId: self.userId) { _ in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.headerRefreshing = false
|
self.headerRefreshing = false
|
||||||
self.noMoreNewest = !hasData
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.hasMoreNewest = loadNum > 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: scrollID) { _, newValue in
|
.onChange(of: scrollID) { _, newValue in
|
||||||
@ -174,7 +177,7 @@ struct IndexMainView: View {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Task { @MainActor in
|
let task = Task { @MainActor in
|
||||||
let num = await indexModel.loadMoreUpdateDramasTask(userId: self.userId)
|
let num = await indexModel.loadMoreUpdateDramasTask(userId: self.userId)
|
||||||
if num > 3 {
|
if num > 3 {
|
||||||
self.hasMoreOldest = true
|
self.hasMoreOldest = true
|
||||||
|
|||||||
@ -262,13 +262,15 @@ final class IndexModel {
|
|||||||
return loadNum
|
return loadNum
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPrevUpdateDramasTask(userId: String, callback: (Bool) -> Void) async {
|
func loadPrevUpdateDramasTask(userId: String, callback: (Bool) -> Void) async -> Int {
|
||||||
guard !self.isMoreLoading else {
|
guard !self.isMoreLoading else {
|
||||||
return
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按照id来判断不一定正确,需要借助其他值
|
// 按照id来判断不一定正确,需要借助其他值
|
||||||
let dramaIds = self.getDramaIds(self.updateDramaGroups)
|
let dramaIds = self.getDramaIds(self.updateDramaGroups)
|
||||||
|
|
||||||
|
var loadNum: Int = 0
|
||||||
// 查找最小的id
|
// 查找最小的id
|
||||||
if let firstId = dramaIds.first {
|
if let firstId = dramaIds.first {
|
||||||
self.isMoreLoading = true
|
self.isMoreLoading = true
|
||||||
@ -283,6 +285,9 @@ final class IndexModel {
|
|||||||
|
|
||||||
self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
|
self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
|
||||||
displayDramaGroups(self.updateDramaGroups, label: "after")
|
displayDramaGroups(self.updateDramaGroups, label: "after")
|
||||||
|
|
||||||
|
loadNum = groups.reduce(0, { acc, group in acc + group.items.count })
|
||||||
|
|
||||||
// 处理回调
|
// 处理回调
|
||||||
callback(true)
|
callback(true)
|
||||||
} else {
|
} else {
|
||||||
@ -293,6 +298,8 @@ final class IndexModel {
|
|||||||
}
|
}
|
||||||
self.isMoreLoading = false
|
self.isMoreLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return loadNum
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换成显示的元素信息
|
// 转换成显示的元素信息
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftData
|
import SwiftData
|
||||||
import Observation
|
import Observation
|
||||||
|
import BackgroundTasks
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct dimensionhubApp: App {
|
struct dimensionhubApp: App {
|
||||||
@ -97,7 +98,14 @@ struct dimensionhubApp: App {
|
|||||||
|
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
|
||||||
|
|
||||||
|
let taskId = "com.jihe.dimensionhub.refresh"
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
|
|
||||||
|
BGTaskScheduler.shared.register(forTaskWithIdentifier: taskId, using: nil) { task in
|
||||||
|
self.handleAppRefresh(task: task as! BGAppRefreshTask)
|
||||||
|
}
|
||||||
|
|
||||||
Task.detached {
|
Task.detached {
|
||||||
await self.registerForPushNotifications()
|
await self.registerForPushNotifications()
|
||||||
|
|
||||||
@ -124,6 +132,42 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleAppRefresh(task: BGAppRefreshTask) {
|
||||||
|
self.scheduleAppRefresh()
|
||||||
|
|
||||||
|
task.expirationHandler = {
|
||||||
|
// 清理未完成的操作
|
||||||
|
task.setTaskCompleted(success: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
Task {@MainActor in
|
||||||
|
if let unreadNum = await self.fetchUserUnreadCount(), unreadNum > 0 {
|
||||||
|
do {
|
||||||
|
try await UNUserNotificationCenter.current().setBadgeCount(unreadNum)
|
||||||
|
task.setTaskCompleted(success: true)
|
||||||
|
NSLog("Refresh setBadgeCount num: \(unreadNum)")
|
||||||
|
} catch let err {
|
||||||
|
NSLog("Refresh setBadgeCount get error: \(err)")
|
||||||
|
task.setTaskCompleted(success: false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task.setTaskCompleted(success: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func scheduleAppRefresh() {
|
||||||
|
let request = BGAppRefreshTaskRequest(identifier: taskId)
|
||||||
|
|
||||||
|
// 设置下次执行时间(建议 1-4 小时)
|
||||||
|
request.earliestBeginDate = Date(timeIntervalSinceNow: 900)
|
||||||
|
do {
|
||||||
|
try BGTaskScheduler.shared.submit(request)
|
||||||
|
} catch {
|
||||||
|
NSLog("无法安排后台任务: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func registerForPushNotifications() {
|
private func registerForPushNotifications() {
|
||||||
// 请求通知权限
|
// 请求通知权限
|
||||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {granted, error in
|
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {granted, error in
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user