Skip to content

Commit 078a50b

Browse files
committed
refactor: replace stack-based window title management with a key-based registry
1 parent 26decae commit 078a50b

4 files changed

Lines changed: 62 additions & 38 deletions

File tree

lib/providers/video_player_provider.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
55

66
import 'package:flutter_riverpod/flutter_riverpod.dart';
77
import 'package:path/path.dart' as p;
8+
89
import 'package:fladder/models/media_playback_model.dart';
910
import 'package:fladder/models/playback/playback_model.dart';
1011
import 'package:fladder/providers/settings/client_settings_provider.dart';
Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
import 'dart:io';
22
import 'package:flutter/foundation.dart';
33
import 'package:flutter_riverpod/flutter_riverpod.dart';
4+
import 'package:fladder/models/media_playback_model.dart';
5+
import 'package:fladder/providers/video_player_provider.dart';
46
import 'package:window_manager/window_manager.dart';
57

68
/// Manages the context-aware window title.
79
final windowTitleProvider = StateNotifierProvider<WindowTitleNotifier, String>((ref) {
8-
return WindowTitleNotifier();
10+
return WindowTitleNotifier(ref);
911
});
1012

1113
class WindowTitleNotifier extends StateNotifier<String> {
12-
WindowTitleNotifier() : super('Fladder');
14+
final Ref ref;
15+
WindowTitleNotifier(this.ref) : super('Fladder');
1316

14-
final List<String> _navStack = [];
17+
final Map<Object, String> _titles = {};
18+
final List<Object> _stackKeys = [];
1519
String? _playTitle;
1620

17-
void pushNavTitle(String title) {
18-
_navStack.add(title);
21+
void updateTitle(Object key, String title) {
22+
_stackKeys.remove(key);
23+
_stackKeys.add(key);
24+
_titles[key] = title;
1925
_update();
2026
}
2127

22-
void popNavTitle(String title) {
23-
_navStack.remove(title);
24-
_update();
25-
}
26-
27-
void replaceNavTitle(String oldTitle, String newTitle) {
28-
final index = _navStack.lastIndexOf(oldTitle);
29-
if (index != -1) {
30-
_navStack[index] = newTitle;
31-
} else {
32-
_navStack.add(newTitle);
28+
void removeTitle(Object key) {
29+
final removed = _stackKeys.remove(key);
30+
_titles.remove(key);
31+
if (removed) {
32+
_update();
3333
}
34-
_update();
3534
}
3635

3736
void clearStack() {
38-
_navStack.clear();
37+
_stackKeys.clear();
38+
_titles.clear();
3939
_update();
4040
}
4141

@@ -45,17 +45,30 @@ class WindowTitleNotifier extends StateNotifier<String> {
4545
}
4646

4747
void _update() {
48-
final nav = _navStack.isNotEmpty ? _navStack.last : null;
49-
final title = _playTitle ?? nav;
48+
final nav = _stackKeys.isNotEmpty ? _titles[_stackKeys.last] : null;
49+
final playerState = ref.read(mediaPlaybackProvider).state;
5050

51-
if (kIsWeb) {
52-
state = title != null ? 'Fladder • $title' : 'Fladder';
53-
} else {
54-
state = title ?? 'Fladder';
55-
}
51+
final isPlayerActive = playerState != VideoPlayerState.disposed;
52+
final isPlayerMinimized = playerState == VideoPlayerState.minimized;
53+
54+
// Use playTitle if player is active and expanded/fullscreen.
55+
// If player is minimized or inactive, prefer navigation title.
56+
final title = (isPlayerActive && !isPlayerMinimized)
57+
? (_playTitle ?? nav)
58+
: (nav ?? _playTitle);
59+
60+
final newState = kIsWeb ? (title != null ? 'Fladder • $title' : 'Fladder') : (title ?? 'Fladder');
61+
62+
if (state == newState) return;
63+
64+
Future.microtask(() {
65+
state = newState;
66+
});
5667

5768
if (!kIsWeb && (Platform.isLinux || Platform.isMacOS || Platform.isWindows)) {
58-
windowManager.setTitle(state);
69+
// Setting window title directly is safe even during build
70+
windowManager.setTitle(newState);
5971
}
6072
}
73+
6174
}

lib/screens/shared/detail_scaffold.dart

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,29 +73,40 @@ class _DetailScaffoldState extends ConsumerState<DetailScaffold> {
7373
ImageProvider? _lastRequestedImage;
7474
ImageData? _lastColorImage;
7575

76+
String? _currentTitle;
77+
78+
void _pushTitle() {
79+
final isCurrent = ModalRoute.of(context)?.isCurrent ?? false;
80+
if (!isCurrent) return;
81+
82+
final newTitle = widget.windowTitle ?? widget.item?.windowTitle(context.localized) ?? widget.label;
83+
if (newTitle.isNotEmpty) {
84+
_currentTitle = newTitle;
85+
ref.read(windowTitleProvider.notifier).updateTitle(this, newTitle);
86+
}
87+
}
88+
7689
@override
7790
void initState() {
7891
super.initState();
79-
WidgetsBinding.instance.addPostFrameCallback((_) {
80-
ref.read(windowTitleProvider.notifier).pushNavTitle(widget.windowTitle ?? widget.label);
81-
});
92+
}
93+
94+
@override
95+
void didChangeDependencies() {
96+
super.didChangeDependencies();
97+
_pushTitle();
8298
}
8399

84100
@override
85101
void dispose() {
86-
ref.read(windowTitleProvider.notifier).popNavTitle(widget.windowTitle ?? widget.label);
102+
ref.read(windowTitleProvider.notifier).removeTitle(this);
87103
super.dispose();
88104
}
89105

90106
@override
91107
void didUpdateWidget(covariant DetailScaffold oldWidget) {
92108
super.didUpdateWidget(oldWidget);
93-
if (oldWidget.label != widget.label || oldWidget.windowTitle != widget.windowTitle) {
94-
ref.read(windowTitleProvider.notifier).replaceNavTitle(
95-
oldWidget.windowTitle ?? oldWidget.label,
96-
widget.windowTitle ?? widget.label,
97-
);
98-
}
109+
_pushTitle();
99110
updateImage();
100111
_updateDominantColor();
101112
if (widget.item != null && widget.item?.id != item?.id) {

lib/widgets/navigation_scaffold/navigation_scaffold.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
5252
super.initState();
5353
WidgetsBinding.instance.addPostFrameCallback((value) {
5454
ref.read(viewsProvider.notifier).fetchViews();
55-
ref.read(windowTitleProvider.notifier).clearStack();
5655
});
5756
}
5857

@@ -124,7 +123,7 @@ class _NavigationScaffoldState extends ConsumerState<NavigationScaffold> {
124123
child: Builder(builder: (context) {
125124
return Scaffold(
126125
key: _key,
127-
appBar: fullScreenChildRoute ? null : const FladderAppBar(),
126+
appBar: fullScreenChildRoute ? null : FladderAppBar(label: currentIndex == -1 ? "" : null),
128127
extendBodyBehindAppBar: true,
129128
resizeToAvoidBottomInset: false,
130129
extendBody: true,

0 commit comments

Comments
 (0)