simplify and fix background loading (#288)
* simplify and fix background loading * start receive loop in the main chat
This commit is contained in:
committed by
GitHub
parent
5c24089f9f
commit
86c36f53e4
@@ -14,22 +14,25 @@ private let receiveTaskId = "chat.simplex.app.receive"
|
||||
// TCP timeout + 2 sec
|
||||
private let waitForMessages: TimeInterval = 6
|
||||
|
||||
class BGManager {
|
||||
private var bgTimer: Timer?
|
||||
private let bgRefreshInterval: TimeInterval = 450
|
||||
|
||||
class BGManager {
|
||||
static let shared = BGManager()
|
||||
var chatReceiver: ChatReceiver?
|
||||
var bgTimer: Timer?
|
||||
var completed = false
|
||||
|
||||
func register() {
|
||||
logger.debug("BGManager.register")
|
||||
BGTaskScheduler.shared.register(forTaskWithIdentifier: receiveTaskId, using: nil) { task in
|
||||
self.handleRefresh(RefreshTask(task as! BGAppRefreshTask))
|
||||
self.handleRefresh(task as! BGAppRefreshTask)
|
||||
}
|
||||
}
|
||||
|
||||
func schedule() {
|
||||
logger.debug("BGManager.schedule")
|
||||
let request = BGAppRefreshTaskRequest(identifier: receiveTaskId)
|
||||
request.earliestBeginDate = Date(timeIntervalSinceNow: 10 * 60)
|
||||
request.earliestBeginDate = Date(timeIntervalSinceNow: bgRefreshInterval)
|
||||
do {
|
||||
try BGTaskScheduler.shared.submit(request)
|
||||
} catch {
|
||||
@@ -37,61 +40,41 @@ class BGManager {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRefresh(_ task: RefreshTask) {
|
||||
private func handleRefresh(_ task: BGAppRefreshTask) {
|
||||
logger.debug("BGManager.handleRefresh")
|
||||
schedule()
|
||||
task.expirationHandler = {
|
||||
logger.debug("BGManager.handleRefresh expirationHandler")
|
||||
ChatReceiver.shared.stop()
|
||||
task.setTaskCompleted(success: true)
|
||||
self.completed = false
|
||||
|
||||
let completeTask: (String) -> Void = { reason in
|
||||
logger.debug("BGManager.handleRefresh completeTask: \(reason)")
|
||||
if !self.completed {
|
||||
self.completed = true
|
||||
self.chatReceiver?.stop()
|
||||
self.chatReceiver = nil
|
||||
self.bgTimer?.invalidate()
|
||||
self.bgTimer = nil
|
||||
task.setTaskCompleted(success: true)
|
||||
}
|
||||
}
|
||||
|
||||
task.expirationHandler = { completeTask("expirationHandler") }
|
||||
DispatchQueue.main.async {
|
||||
initializeChat()
|
||||
if ChatModel.shared.currentUser == nil {
|
||||
task.setTaskCompleted(success: true)
|
||||
completeTask("no current user")
|
||||
return
|
||||
}
|
||||
logger.debug("BGManager.handleRefresh: starting chat")
|
||||
ChatReceiver.shared.start(bgTask: task)
|
||||
let cr = ChatReceiver()
|
||||
self.chatReceiver = cr
|
||||
cr.start()
|
||||
RunLoop.current.add(Timer(timeInterval: 2, repeats: true) { timer in
|
||||
self.bgTimer = timer
|
||||
logger.debug("BGManager.handleRefresh: timer")
|
||||
if ChatReceiver.shared.lastMsgTime.distance(to: Date.now) >= waitForMessages {
|
||||
logger.debug("BGManager.handleRefresh: timer: stopping")
|
||||
ChatReceiver.shared.stop()
|
||||
task.setTaskCompleted(success: true)
|
||||
timer.invalidate()
|
||||
self.bgTimer = nil
|
||||
self.bgTimer = timer
|
||||
if cr.lastMsgTime.distance(to: Date.now) >= waitForMessages {
|
||||
completeTask("timer (no messages after \(waitForMessages) seconds)")
|
||||
}
|
||||
}, forMode: .default)
|
||||
}
|
||||
}
|
||||
|
||||
func invalidateStopTimer() {
|
||||
logger.debug("BGManager.invalidateStopTimer?")
|
||||
if let timer = bgTimer {
|
||||
timer.invalidate()
|
||||
bgTimer = nil
|
||||
logger.debug("BGManager.invalidateStopTimer: done")
|
||||
}
|
||||
}
|
||||
|
||||
class RefreshTask {
|
||||
private let task: BGAppRefreshTask
|
||||
var completed = false
|
||||
|
||||
internal init(_ task: BGAppRefreshTask) {
|
||||
self.task = task
|
||||
}
|
||||
|
||||
var expirationHandler: (() -> Void)? {
|
||||
set { task.expirationHandler = newValue }
|
||||
get { task.expirationHandler }
|
||||
}
|
||||
|
||||
func setTaskCompleted(success: Bool) {
|
||||
if !completed { task.setTaskCompleted(success: success) }
|
||||
completed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,19 +345,15 @@ func initializeChat() {
|
||||
class ChatReceiver {
|
||||
private var receiveLoop: DispatchWorkItem?
|
||||
private var receiveMessages = true
|
||||
private var wasStarted = false
|
||||
private var _canStop = false
|
||||
private var _lastMsgTime = Date.now
|
||||
|
||||
static let shared = ChatReceiver()
|
||||
|
||||
var lastMsgTime: Date { get { _lastMsgTime } }
|
||||
|
||||
func start(bgTask: BGManager.RefreshTask? = nil) {
|
||||
func start() {
|
||||
logger.debug("ChatReceiver.start")
|
||||
wasStarted = true
|
||||
receiveMessages = true
|
||||
_canStop = true
|
||||
_lastMsgTime = .now
|
||||
if receiveLoop != nil { return }
|
||||
let loop = DispatchWorkItem(qos: .default, flags: []) {
|
||||
@@ -369,25 +365,16 @@ class ChatReceiver {
|
||||
logger.error("ChatReceiver.start chatRecvMsg error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
if let task = bgTask { task.setTaskCompleted(success: true) }
|
||||
}
|
||||
receiveLoop = loop
|
||||
DispatchQueue.global().async(execute: loop)
|
||||
}
|
||||
|
||||
func stop() {
|
||||
logger.debug("ChatReceiver.stop?")
|
||||
if !_canStop { return }
|
||||
logger.debug("ChatReceiver.stop")
|
||||
receiveMessages = false
|
||||
receiveLoop?.cancel()
|
||||
receiveLoop = nil
|
||||
logger.debug("ChatReceiver.stop: done")
|
||||
}
|
||||
|
||||
func restart() {
|
||||
logger.debug("ChatReceiver.restart?")
|
||||
if wasStarted && receiveLoop == nil { start() }
|
||||
_canStop = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ struct SimpleXApp: App {
|
||||
.onChange(of: scenePhase) { phase in
|
||||
if phase == .background {
|
||||
BGManager.shared.schedule()
|
||||
} else {
|
||||
BGManager.shared.invalidateStopTimer()
|
||||
ChatReceiver.shared.restart()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user