fix(app): make ConnectButton listener lifecycle-safe #4

Merged
Naveax merged 1 commits from pr/fix-connect-button-lifecycle into main 2026-09-06 11:17:20 +03:00
Showing only changes of commit 7ccca5340c - Show all commits
+13 -9
View File
@@ -19,6 +19,7 @@ class _ConnectButtonState extends State<ConnectButton>
DateTime _lastTap = DateTime.fromMillisecondsSinceEpoch(0); DateTime _lastTap = DateTime.fromMillisecondsSinceEpoch(0);
AnimationController? _pulse; AnimationController? _pulse;
Animation<double>? _pulseAnim; Animation<double>? _pulseAnim;
VpnConnection? _vpn;
double get _pulseValue => _pulseAnim?.value ?? 0.0; double get _pulseValue => _pulseAnim?.value ?? 0.0;
@@ -35,20 +36,25 @@ class _ConnectButtonState extends State<ConnectButton>
); );
WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) context.read<VpnConnection>().addListener(_onVpnChanged); if (!mounted || _vpn != null) return;
final vpn = context.read<VpnConnection>();
_vpn = vpn;
vpn.addListener(_onVpnChanged);
_onVpnChanged();
}); });
} }
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
context.read<VpnConnection>().removeListener(_onVpnChanged); _vpn?.removeListener(_onVpnChanged);
_pulse?.dispose(); _pulse?.dispose();
super.dispose(); super.dispose();
} }
void _onVpnChanged() { void _onVpnChanged() {
final vpn = context.read<VpnConnection>(); final vpn = _vpn;
if (vpn == null) return;
if (vpn.status == VpnStatus.connected) { if (vpn.status == VpnStatus.connected) {
_pulse?.repeat(reverse: true); _pulse?.repeat(reverse: true);
} else { } else {
@@ -60,14 +66,12 @@ class _ConnectButtonState extends State<ConnectButton>
@override @override
void didChangeAppLifecycleState(AppLifecycleState state) { void didChangeAppLifecycleState(AppLifecycleState state) {
if (!mounted) return; if (!mounted) return;
if (state == AppLifecycleState.paused || if (state != AppLifecycleState.resumed) {
state == AppLifecycleState.detached) {
_pulse?.stop(); _pulse?.stop();
} else if (state == AppLifecycleState.resumed) { return;
final vpn = context.read<VpnConnection>();
if (vpn.status == VpnStatus.connected) {
_pulse?.repeat(reverse: true);
} }
if (_vpn?.status == VpnStatus.connected) {
_pulse?.repeat(reverse: true);
} }
} }