mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: watch sync mechanism (#817)
* opt.: watch sync mechanism Fixes #816 * opt.
This commit is contained in:
@@ -14,13 +14,20 @@ class PhoneConnMgr: NSObject, WCSessionDelegate, ObservableObject {
|
|||||||
set {
|
set {
|
||||||
Store.setCtx(newValue)
|
Store.setCtx(newValue)
|
||||||
updateUrls(newValue)
|
updateUrls(newValue)
|
||||||
|
|
||||||
|
// Notify the view to update, but the [urls] are already published
|
||||||
|
// so the view will automatically update when [urls] changes.
|
||||||
|
// DispatchQueue.main.async {
|
||||||
|
// self.objectWillChange.send()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
get {
|
get {
|
||||||
return _ctx
|
return _ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var userInfo: [String: Any] = [:]
|
||||||
@Published var urls: [String] = []
|
@Published var urls: [String] = []
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
if !WCSession.isSupported() {
|
if !WCSession.isSupported() {
|
||||||
@@ -29,24 +36,85 @@ class PhoneConnMgr: NSObject, WCSessionDelegate, ObservableObject {
|
|||||||
session = WCSession.default
|
session = WCSession.default
|
||||||
session?.delegate = self
|
session?.delegate = self
|
||||||
session?.activate()
|
session?.activate()
|
||||||
|
|
||||||
ctx = Store.getCtx()
|
_ctx = Store.getCtx()
|
||||||
|
updateUrls(_ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUrls(_ val: [String: Any]) {
|
func updateUrls(_ val: [String: Any]) {
|
||||||
if let urls = val["urls"] as? [String] {
|
if let urls = val["urls"] as? [String] {
|
||||||
self.urls = urls.filter { !$0.isEmpty }
|
DispatchQueue.main.async {
|
||||||
|
self.urls = urls.filter { !$0.isEmpty }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
func session(
|
||||||
|
_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState,
|
||||||
|
error: Error?
|
||||||
|
) {
|
||||||
|
// Request latest data when the session is activated
|
||||||
|
if activationState == .activated {
|
||||||
|
requestLatestData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// implement session:didReceiveApplicationContext:
|
// Receive realtime msgs
|
||||||
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
|
func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
|
||||||
ctx = applicationContext
|
DispatchQueue.main.async {
|
||||||
|
self.ctx = message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive UserInfo
|
||||||
|
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any]) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.ctx = userInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive Application Context
|
||||||
|
func session(
|
||||||
|
_ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]
|
||||||
|
) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.ctx = applicationContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func requestLatestData(timeout: TimeInterval = 5.0, maxRetries: Int = 1) {
|
||||||
|
guard let session = session, session.isReachable else { return }
|
||||||
|
|
||||||
|
var didReceiveResponse = false
|
||||||
|
var retries = 0
|
||||||
|
|
||||||
|
func sendRequest() {
|
||||||
|
session.sendMessage(["action": "requestData"]) { response in
|
||||||
|
didReceiveResponse = true
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.ctx = response
|
||||||
|
}
|
||||||
|
} errorHandler: { error in
|
||||||
|
print("Request data failed: \(error)")
|
||||||
|
// Optionally, handle error UI here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeout handling
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if !didReceiveResponse {
|
||||||
|
if retries < maxRetries {
|
||||||
|
retries += 1
|
||||||
|
print("No response, retrying requestLatestData (\(retries))...")
|
||||||
|
sendRequest()
|
||||||
|
} else {
|
||||||
|
print("Request data timed out after \(retries + 1) attempts.")
|
||||||
|
// Optionally, update UI to indicate timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,20 @@ class _IosSettingsPageState extends State<IosSettingsPage> {
|
|||||||
|
|
||||||
final (_, err) = await context.showLoadingDialog(
|
final (_, err) = await context.showLoadingDialog(
|
||||||
fn: () async {
|
fn: () async {
|
||||||
await wc.updateApplicationContext({'urls': result});
|
final data = {'urls': result};
|
||||||
|
|
||||||
|
// Try realtime update (app must be running foreground).
|
||||||
|
try {
|
||||||
|
if (await wc.isReachable) {
|
||||||
|
await wc.sendMessage(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Loggers.app.warning('Failed to send message to watch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
await wc.updateApplicationContext(data);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (err == null) {
|
if (err == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user