diff --git a/lib/main.dart b/lib/main.dart index f383b23..e75a2c6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -299,6 +299,7 @@ class _MainApp extends State with WidgetsBindingObserver { _lifecycleState = WidgetsBinding.instance.lifecycleState; listener.tryEmit("lifecycle", _lifecycleState); } + tasks.init(); } @override diff --git a/lib/task.dart b/lib/task.dart index 6f42b19..e56c99d 100644 --- a/lib/task.dart +++ b/lib/task.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; import 'api/eh.dart'; @@ -20,6 +21,7 @@ class TaskManager { bool _isFetching = false; List peddingGids = []; List peddingTokens = []; + late Timer _pingTimer; void clear() { tasks.clear(); _channel?.stream.drain(); @@ -187,6 +189,9 @@ class TaskManager { } }, onError: (e) { _log.warning("Task websocket error: $e"); + }, onDone: () { + _log.warning( + "WenSocket closed: ${_channel?.closeCode} ${_channel?.closeReason}"); if (_allowReconnect) { _log.info("Reconnecting to task server in 5 seconds"); _reconnectTimer = Timer(const Duration(seconds: 5), () { @@ -214,4 +219,28 @@ class TaskManager { void sendTaskList() { _channel?.sink.add("{\"type\":\"task_list\"}"); } + + void _onLifeCycleChanged(dynamic arg) { + final state = arg as AppLifecycleState?; + if (state == null) return; + if (state == AppLifecycleState.resumed) { + try { + _channel?.sink.add("{\"type\":\"ping\"}"); + } catch (e) { + _log.warning("Failed to send ping when onResumed: $e"); + } + } + } + + void init() { + listener.on("lifecycle", _onLifeCycleChanged); + _pingTimer = Timer.periodic(const Duration(seconds: 30), (timer) { + try { + _channel?.sink.add("{\"type\":\"ping\"}"); + } catch (e) { + _log.warning("Failed to send ping: $e"); + } + _pingTimer = timer; + }); + } }