Skip to content

Commit e836a1b

Browse files
authored
Secondary window (#244)
2 parents f842320 + 67e1edc commit e836a1b

File tree

14 files changed

+138
-140
lines changed

14 files changed

+138
-140
lines changed

lib/main.dart

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ Future<void> main(List<String> args) async {
113113
await SettingsProvider.ensureInitialized();
114114
await DesktopViewProvider.ensureInitialized();
115115

116-
final windowType = MultiWindowType.values[int.tryParse(args[0]) ?? 0];
117-
final themeMode = ThemeMode.values[int.tryParse(args[2]) ?? 0];
116+
final windowType = MultiWindowType.values[int.tryParse(args[1]) ?? 0];
117+
final themeMode = ThemeMode.values[int.tryParse(args[3]) ?? 0];
118118

119119
switch (windowType) {
120120
case MultiWindowType.device:
121-
final device = Device.fromJson(json.decode(args[1]));
121+
final device = Device.fromJson(json.decode(args[2]));
122122
configureWindowTitle(device.fullName);
123123

124124
runApp(AlternativeWindow(
@@ -127,7 +127,7 @@ Future<void> main(List<String> args) async {
127127
));
128128
break;
129129
case MultiWindowType.layout:
130-
final layout = Layout.fromJson(args[1]);
130+
final layout = Layout.fromJson(args[2]);
131131
configureWindowTitle(layout.name);
132132

133133
runApp(AlternativeWindow(
@@ -174,7 +174,7 @@ Future<void> main(List<String> args) async {
174174
]);
175175

176176
/// Firebase messaging isn't available on windows nor linux
177-
if (!kIsWeb && (isMobilePlatform || Platform.isMacOS)) {
177+
if (!kIsWeb && isMobilePlatform) {
178178
FirebaseConfiguration.ensureInitialized();
179179
}
180180

@@ -193,6 +193,14 @@ class UnityApp extends StatefulWidget {
193193

194194
@override
195195
State<UnityApp> createState() => _UnityAppState();
196+
197+
static const localizationDelegates = [
198+
AppLocalizations.delegate,
199+
GlobalMaterialLocalizations.delegate,
200+
GlobalWidgetsLocalizations.delegate,
201+
GlobalCupertinoLocalizations.delegate,
202+
LocaleNamesLocalizationsDelegate(),
203+
];
196204
}
197205

198206
class _UnityAppState extends State<UnityApp>
@@ -310,7 +318,9 @@ class _UnityAppState extends State<UnityApp>
310318
Widget build(BuildContext context) {
311319
return MultiProvider(
312320
providers: [
313-
ChangeNotifierProvider(create: (context) => HomeProvider()),
321+
ChangeNotifierProvider<HomeProvider>.value(
322+
value: HomeProvider.instance,
323+
),
314324
ChangeNotifierProvider<SettingsProvider>.value(
315325
value: SettingsProvider.instance,
316326
),
@@ -342,13 +352,7 @@ class _UnityAppState extends State<UnityApp>
342352
navigatorKey: navigatorKey,
343353
navigatorObservers: [navigatorObserver],
344354
locale: settings.kLanguageCode.value,
345-
localizationsDelegates: const [
346-
AppLocalizations.delegate,
347-
GlobalMaterialLocalizations.delegate,
348-
GlobalWidgetsLocalizations.delegate,
349-
GlobalCupertinoLocalizations.delegate,
350-
LocaleNamesLocalizationsDelegate(),
351-
],
355+
localizationsDelegates: UnityApp.localizationDelegates,
352356
supportedLocales: AppLocalizations.supportedLocales,
353357
themeMode: settings.kThemeMode.value,
354358
theme: createTheme(brightness: Brightness.light),

lib/providers/settings_provider.dart

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -89,46 +89,45 @@ class _SettingsOption<T> {
8989
}) {
9090
Future.microtask(() async {
9191
_value = getDefault != null ? await getDefault!() : def;
92+
});
9293

93-
if (saveAs != null) {
94-
this.saveAs = saveAs;
95-
} else if (T == bool) {
96-
this.saveAs = (value) => value.toString();
97-
} else if (T == Duration) {
98-
this.saveAs = (value) => (value as Duration).inMilliseconds.toString();
99-
} else if (T == Enum) {
100-
this.saveAs = (value) => (value as Enum).index.toString();
101-
} else if (T == DateFormat) {
102-
this.saveAs = (value) => (value as DateFormat).pattern ?? '';
103-
} else if (T == Locale) {
104-
this.saveAs = (value) => (value as Locale).toLanguageTag();
105-
} else if (T == DateTime) {
106-
this.saveAs = (value) => (value as DateTime).toIso8601String();
107-
} else {
108-
this.saveAs = (value) => value.toString();
109-
}
94+
if (saveAs != null) {
95+
this.saveAs = saveAs;
96+
} else if (T == bool) {
97+
this.saveAs = (value) => value.toString();
98+
} else if (T == Duration) {
99+
this.saveAs = (value) => (value as Duration).inMilliseconds.toString();
100+
} else if (T == Enum) {
101+
this.saveAs = (value) => (value as Enum).index.toString();
102+
} else if (T == DateFormat) {
103+
this.saveAs = (value) => (value as DateFormat).pattern ?? '';
104+
} else if (T == Locale) {
105+
this.saveAs = (value) => (value as Locale).toLanguageTag();
106+
} else if (T == DateTime) {
107+
this.saveAs = (value) => (value as DateTime).toIso8601String();
108+
} else {
109+
this.saveAs = (value) => value.toString();
110+
}
110111

111-
if (loadFrom != null) {
112-
this.loadFrom = loadFrom;
113-
} else if (T == bool) {
114-
this.loadFrom = (value) => (bool.tryParse(value) ?? def) as T;
115-
} else if (T == Duration) {
116-
this.loadFrom =
117-
(value) => Duration(milliseconds: int.parse(value)) as T;
118-
} else if (T == Enum) {
119-
throw UnsupportedError('Enum type must provide a loadFrom function');
120-
} else if (T == DateFormat) {
121-
this.loadFrom = (value) => DateFormat(value) as T;
122-
} else if (T == Locale) {
123-
this.loadFrom = (value) => Locale.fromSubtags(languageCode: value) as T;
124-
} else if (T == DateTime) {
125-
this.loadFrom = (value) => DateTime.parse(value) as T;
126-
} else if (T == double) {
127-
this.loadFrom = (value) => double.parse(value) as T;
128-
} else {
129-
this.loadFrom = (value) => value as T;
130-
}
131-
});
112+
if (loadFrom != null) {
113+
this.loadFrom = loadFrom;
114+
} else if (T == bool) {
115+
this.loadFrom = (value) => (bool.tryParse(value) ?? def) as T;
116+
} else if (T == Duration) {
117+
this.loadFrom = (value) => Duration(milliseconds: int.parse(value)) as T;
118+
} else if (T == Enum) {
119+
throw UnsupportedError('Enum type must provide a loadFrom function');
120+
} else if (T == DateFormat) {
121+
this.loadFrom = (value) => DateFormat(value) as T;
122+
} else if (T == Locale) {
123+
this.loadFrom = (value) => Locale.fromSubtags(languageCode: value) as T;
124+
} else if (T == DateTime) {
125+
this.loadFrom = (value) => DateTime.parse(value) as T;
126+
} else if (T == double) {
127+
this.loadFrom = (value) => double.parse(value) as T;
128+
} else {
129+
this.loadFrom = (value) => value as T;
130+
}
132131
}
133132

134133
String get defAsString => saveAs(def);

lib/screens/downloads/downloads_manager.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ class _DownloadTileState extends State<DownloadTile> {
142142
super.initState();
143143
if (widget.initiallyExpanded) {
144144
WidgetsBinding.instance.addPostFrameCallback((_) {
145-
if (!mounted) return;
146-
145+
if (!context.mounted) return;
147146
Scrollable.ensureVisible(context);
148147
});
149148
}

lib/screens/events_browser/events_screen_mobile.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ class _EventsScreenMobileState extends State<EventsScreenMobile> {
4545
@override
4646
void initState() {
4747
super.initState();
48-
WidgetsBinding.instance.addPostFrameCallback(
49-
(_) => showFilterSheet(context, loadInitially: true),
50-
);
48+
WidgetsBinding.instance.addPostFrameCallback((_) {
49+
if (!context.mounted) return;
50+
showFilterSheet(context, loadInitially: true);
51+
});
5152
}
5253

5354
@override

lib/screens/events_browser/filter.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class _EventsDevicesPickerState extends State<EventsDevicesPicker> {
5555
void initState() {
5656
super.initState();
5757
WidgetsBinding.instance.addPostFrameCallback((_) {
58+
if (!context.mounted) return;
5859
final eventsProvider = context.read<EventsProvider>();
5960
final serversProvider = context.read<ServersProvider>();
6061

lib/screens/events_timeline/events_playback.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class _EventsPlaybackState extends EventsScreenState<EventsPlayback> {
7272

7373
@override
7474
Future<void> fetch() async {
75+
if (!context.mounted) return;
7576
final eventsProvider = context.read<EventsProvider>();
7677
final settings = context.read<SettingsProvider>();
7778
setState(() {
@@ -199,9 +200,7 @@ class _EventsPlaybackState extends EventsScreenState<EventsPlayback> {
199200
// special case: the width is less than the mobile breakpoint
200201
constraints.maxWidth < 630.0 /* kMobileBreakpoint.width */) {
201202
if (!hasEverFetched) {
202-
WidgetsBinding.instance.addPostFrameCallback((_) {
203-
fetch();
204-
});
203+
WidgetsBinding.instance.addPostFrameCallback((_) => fetch());
205204
}
206205
if (timeline == null) {
207206
return SafeArea(

lib/screens/home.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class _MobileHomeState extends State<Home> {
115115
void initState() {
116116
super.initState();
117117
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
118+
if (!context.mounted) return;
118119
context.read<HomeProvider>().refreshDeviceOrientation(context);
119120
});
120121
}

lib/screens/layouts/desktop/multicast_view.dart

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -138,44 +138,50 @@ class _MulticastViewportState extends State<MulticastViewport> {
138138
}
139139

140140
return LayoutBuilder(builder: (context, constraints) {
141-
return Stack(children: [
141+
return Stack(alignment: Alignment.center, children: [
142142
if (size > 1)
143143
Positioned.fill(
144-
child: GridView.count(
145-
crossAxisCount: size,
146-
childAspectRatio: kHorizontalAspectRatio,
147-
physics: const NeverScrollableScrollPhysics(),
148-
children: List.generate(size * size, (index) {
149-
final row = index ~/ size;
150-
final col = index % size;
151-
152-
return HoverButton(
153-
onDoubleTap: () {
154-
views.updateDevice(
155-
widget.device,
156-
widget.device.copyWith(matrixType: matrixType.next),
144+
child: Center(
145+
child: AspectRatio(
146+
aspectRatio: kHorizontalAspectRatio,
147+
child: GridView.count(
148+
crossAxisCount: size,
149+
childAspectRatio: kHorizontalAspectRatio,
150+
physics: const NeverScrollableScrollPhysics(),
151+
shrinkWrap: true,
152+
children: List.generate(size * size, (index) {
153+
final row = index ~/ size;
154+
final col = index % size;
155+
156+
return HoverButton(
157+
onDoubleTap: () {
158+
views.updateDevice(
159+
widget.device,
160+
widget.device.copyWith(matrixType: matrixType.next),
161+
);
162+
},
163+
onPressed: () {
164+
view.player.crop(row, col);
165+
currentZoom = (row, col);
166+
},
167+
builder: (context, states) => SizedBox.expand(
168+
child: IgnorePointer(
169+
child: states.isHovering
170+
? Container(
171+
decoration: BoxDecoration(
172+
border: Border.all(
173+
color: theme.colorScheme.secondary,
174+
width: 2.25,
175+
),
176+
),
177+
)
178+
: null,
179+
),
180+
),
157181
);
158-
},
159-
onPressed: () {
160-
view.player.crop(row, col);
161-
currentZoom = (row, col);
162-
},
163-
builder: (context, states) => SizedBox.expand(
164-
child: IgnorePointer(
165-
child: states.isHovering
166-
? Container(
167-
decoration: BoxDecoration(
168-
border: Border.all(
169-
color: theme.colorScheme.secondary,
170-
width: 2.25,
171-
),
172-
),
173-
)
174-
: null,
175-
),
176-
),
177-
);
178-
}),
182+
}),
183+
),
184+
),
179185
),
180186
),
181187
for (final overlay in widget.device.overlays)

lib/screens/layouts/desktop/sidebar.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class _DesktopSidebarState extends State<DesktopSidebar> {
5151
final devices = server.devices.sorted(
5252
searchQuery: searchQuery,
5353
);
54-
_servers[server] = devices;
54+
if (devices.isNotEmpty) {
55+
_servers[server] = devices;
56+
}
5557
}
5658
}
5759

@@ -90,11 +92,10 @@ class _DesktopSidebarState extends State<DesktopSidebar> {
9092
child: Material(
9193
type: MaterialType.transparency,
9294
child: CustomScrollView(slivers: [
93-
for (final MapEntry<Server, Iterable<Device>>(
94-
key: server,
95-
value: devices,
96-
) in _servers.entries)
95+
for (final entry in _servers.entries)
9796
() {
97+
final server = entry.key;
98+
final devices = entry.value;
9899
final isLoading = servers.isServerLoading(server);
99100
if (!isLoading &&
100101
devices.isEmpty &&
@@ -466,6 +467,7 @@ class _DeviceSelectorTileState extends State<DeviceSelectorTile> {
466467
child: Text(loc.showFullscreenCamera),
467468
onTap: () async {
468469
WidgetsBinding.instance.addPostFrameCallback((_) async {
470+
if (!context.mounted) return;
469471
var player = UnityPlayers.players[widget.device.uuid];
470472
final isLocalController = player == null;
471473
if (isLocalController) {
@@ -497,6 +499,7 @@ class _DeviceSelectorTileState extends State<DeviceSelectorTile> {
497499
child: Text(loc.deviceInfo),
498500
onTap: () async {
499501
WidgetsBinding.instance.addPostFrameCallback((_) async {
502+
if (!context.mounted) return;
500503
await showDeviceInfoDialog(context, widget.device);
501504
});
502505
},

lib/screens/layouts/video_status_label.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class _VideoStatusLabelState extends State<VideoStatusLabel> {
9898
OverlayEntry? entry;
9999
bool get isOverlayOpen => entry != null;
100100
void showOverlay({bool force = false}) {
101-
if (entry != null && !force) return;
101+
if ((entry != null && !force) || !context.mounted) return;
102102

103103
final box = context.findRenderObject() as RenderBox;
104104
final boxSize = box.size;

0 commit comments

Comments
 (0)