Skip to content

Commit bf312b0

Browse files
committed
fix(reconnect): stabilize mobile resume and iOS USB
Avoid restarting the embedded Dart WebSocket server when a flog client is still connected, which prevents redundant Android reconnects after lock-screen wake. Keep usbmuxd tracking on a remaining live DeviceID when the currently selected iOS interface detaches, and prepare the v0.8.1 / flog_dart 0.10.1 patch release.
1 parent 695699d commit bf312b0

14 files changed

Lines changed: 180 additions & 29 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
All notable changes to flog. This project follows
44
[Semantic Versioning](https://semver.org/).
55

6+
## 0.8.1 — 2026-06-15
7+
8+
### Fixed
9+
10+
- Avoid forcing a Dart-side WebSocket server restart on mobile resume when a
11+
flog client is still connected, preventing redundant Android reconnects
12+
after lock-screen wake.
13+
- Keep iOS USB reconnects on the live usbmuxd DeviceID when a multi-interface
14+
iPhone or iPad detaches the previously selected interface.
15+
16+
---
17+
618
## 0.6.0 — 2026-06-04
719

820
### What's new

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "flog"
3-
version = "0.8.0"
3+
version = "0.8.1"
44
edition = "2021"
55
description = "Flutter Log Viewer — see your logs, finally."
66
license = "MIT"

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ flog devices # 列出发现的设备和 flog_dart App
401401
- [`docs/PROTOCOL.md`](docs/PROTOCOL.md) — flog ↔ flog_dart 线协议规范。
402402
- [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) — 审计分类 / 测试规约 / commit 约定。
403403

404-
当前版本 **0.8.0** —— 新增 Network Timing 采集和终端时间线,并保留渐进式 `flog ai` 检查命令和
404+
当前版本 **0.8.1** —— 修复移动端恢复前台时的重复重连和 iOS USB 多接口 DeviceID 切换问题,并保留 Network Timing 采集、终端时间线和渐进式 `flog ai` 检查命令。
405405
`flog install-skill` 项目级 AI 使用说明,覆盖 Codex、Claude Code、Cursor,
406406
同时保持 AI 输出默认精简和脱敏。完整审计线索见 `docs/superpowers/`。
407407

‎README_EN.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ once it finds a connectable `flog_dart` app.
346346
- [`docs/PROTOCOL.md`](docs/PROTOCOL.md) — wire protocol spec.
347347
- [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) — audit taxonomy, testing rules, commit format.
348348

349-
Current version (**0.8.0**) — adds Network Timing collection and terminal timelines, plus progressive `flog ai` inspection commands
349+
Current version (**0.8.1**) — fixes redundant mobile resume reconnects and iOS USB multi-interface DeviceID handoff, while keeping Network Timing collection, terminal timelines, progressive `flog ai` inspection commands,
350350
and `flog install-skill` project guidance for Codex, Claude Code, and Cursor,
351351
while keeping AI output compact and redacted by default. See
352352
`docs/superpowers/` for the campaign audit trail.

‎flog_dart/CHANGELOG.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
All notable changes to `flog_dart`. This project follows
44
[Semantic Versioning](https://semver.org/).
55

6+
## 0.10.1 — 2026-06-15
7+
8+
### Fixed
9+
10+
- Avoid restarting the embedded WebSocket server on mobile resume while a flog
11+
TUI client is still connected. This prevents redundant Android reconnects
12+
after lock-screen wake while preserving recovery when no client remains.
13+
14+
---
15+
616
## 0.10.0 — 2026-06-11
717

818
### Added

‎flog_dart/lib/flog_dart.dart‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ class _FlogLifecycleRestarter with WidgetsBindingObserver {
9696

9797
@override
9898
void didChangeAppLifecycleState(AppLifecycleState state) {
99-
if (!_restartPolicy.shouldRestart(state)) return;
99+
if (!_restartPolicy.shouldRestart(
100+
state,
101+
hasConnectedClients: FlogServer.instance.connected,
102+
)) {
103+
return;
104+
}
100105
unawaited(FlogServer.instance.restart(port: _port));
101106
}
102107
}

‎flog_dart/lib/src/lifecycle_restart_policy.dart‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
/// Lifecycle restart policy for the embedded flog WebSocket server.
22
///
3-
/// Mobile suspend/resume can leave app-owned sockets stale, but desktop
4-
/// focus changes often produce `inactive -> resumed` without suspension.
5-
/// Restart only after a real `paused` state so macOS focus does not drop
6-
/// the active flog connection.
3+
/// Mobile suspend/resume can leave app-owned sockets stale, but resume must
4+
/// not tear down an active flog client that is still connected.
75
library;
86

97
import 'package:flutter/widgets.dart' show AppLifecycleState;
108

119
class FlogLifecycleRestartPolicy {
1210
bool _sawPaused = false;
1311

14-
bool shouldRestart(AppLifecycleState state) {
12+
bool shouldRestart(
13+
AppLifecycleState state, {
14+
required bool hasConnectedClients,
15+
}) {
1516
if (state == AppLifecycleState.paused) {
1617
_sawPaused = true;
1718
return false;
1819
}
1920

2021
if (state == AppLifecycleState.resumed) {
21-
final shouldRestart = _sawPaused;
22+
final shouldRestart = _sawPaused && !hasConnectedClients;
2223
_sawPaused = false;
2324
return shouldRestart;
2425
}

‎flog_dart/pubspec.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flog_dart
22
description: Flutter companion for flog terminal log viewer. Structured logging, Network Inspector (HTTP/SSE/WS), FlogDio drop-in, mock interceptor. Tree-shakes to zero in release builds.
3-
version: 0.10.0
3+
version: 0.10.1
44
homepage: https://github.com/shaominngqing/flog
55
repository: https://github.com/shaominngqing/flog/tree/master/flog_dart
66

‎flog_dart/test/lifecycle_restart_policy_test.dart‎

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,110 @@ void main() {
88
test('resumed_without_prior_paused_does_not_restart', () {
99
final policy = FlogLifecycleRestartPolicy();
1010

11-
expect(policy.shouldRestart(AppLifecycleState.resumed), isFalse);
11+
expect(
12+
policy.shouldRestart(
13+
AppLifecycleState.resumed,
14+
hasConnectedClients: false,
15+
),
16+
isFalse,
17+
);
1218
});
1319

1420
test('inactive_then_resumed_does_not_restart', () {
1521
final policy = FlogLifecycleRestartPolicy();
1622

17-
expect(policy.shouldRestart(AppLifecycleState.inactive), isFalse);
18-
expect(policy.shouldRestart(AppLifecycleState.resumed), isFalse);
23+
expect(
24+
policy.shouldRestart(
25+
AppLifecycleState.inactive,
26+
hasConnectedClients: false,
27+
),
28+
isFalse,
29+
);
30+
expect(
31+
policy.shouldRestart(
32+
AppLifecycleState.resumed,
33+
hasConnectedClients: false,
34+
),
35+
isFalse,
36+
);
1937
});
2038

21-
test('paused_then_resumed_restarts_once', () {
39+
test('paused_then_resumed_restarts_once_when_no_client_is_connected', () {
2240
final policy = FlogLifecycleRestartPolicy();
2341

24-
expect(policy.shouldRestart(AppLifecycleState.paused), isFalse);
25-
expect(policy.shouldRestart(AppLifecycleState.resumed), isTrue);
26-
expect(policy.shouldRestart(AppLifecycleState.resumed), isFalse);
42+
expect(
43+
policy.shouldRestart(
44+
AppLifecycleState.paused,
45+
hasConnectedClients: false,
46+
),
47+
isFalse,
48+
);
49+
expect(
50+
policy.shouldRestart(
51+
AppLifecycleState.resumed,
52+
hasConnectedClients: false,
53+
),
54+
isTrue,
55+
);
56+
expect(
57+
policy.shouldRestart(
58+
AppLifecycleState.resumed,
59+
hasConnectedClients: false,
60+
),
61+
isFalse,
62+
);
63+
});
64+
65+
test('paused_then_resumed_does_not_restart_while_client_is_connected', () {
66+
final policy = FlogLifecycleRestartPolicy();
67+
68+
expect(
69+
policy.shouldRestart(
70+
AppLifecycleState.paused,
71+
hasConnectedClients: true,
72+
),
73+
isFalse,
74+
);
75+
expect(
76+
policy.shouldRestart(
77+
AppLifecycleState.resumed,
78+
hasConnectedClients: true,
79+
),
80+
isFalse,
81+
);
82+
expect(
83+
policy.shouldRestart(
84+
AppLifecycleState.resumed,
85+
hasConnectedClients: false,
86+
),
87+
isFalse,
88+
);
2789
});
2890

2991
test('paused_survives_intermediate_inactive_until_resumed', () {
3092
final policy = FlogLifecycleRestartPolicy();
3193

32-
expect(policy.shouldRestart(AppLifecycleState.paused), isFalse);
33-
expect(policy.shouldRestart(AppLifecycleState.inactive), isFalse);
34-
expect(policy.shouldRestart(AppLifecycleState.resumed), isTrue);
94+
expect(
95+
policy.shouldRestart(
96+
AppLifecycleState.paused,
97+
hasConnectedClients: false,
98+
),
99+
isFalse,
100+
);
101+
expect(
102+
policy.shouldRestart(
103+
AppLifecycleState.inactive,
104+
hasConnectedClients: false,
105+
),
106+
isFalse,
107+
);
108+
expect(
109+
policy.shouldRestart(
110+
AppLifecycleState.resumed,
111+
hasConnectedClients: false,
112+
),
113+
isTrue,
114+
);
35115
});
36116
});
37117
}

0 commit comments

Comments
 (0)