Merge pull request #316 from Nedlinin/linux-crash-fixes

Blank UI during desktop window shutdown
This commit is contained in:
edde746
2026-01-21 19:52:02 +01:00
committed by GitHub
2 changed files with 41 additions and 1 deletions
+13
View File
@@ -57,6 +57,8 @@ void _absorbZeroOffsetPointerEvent(PointerEvent event) {
}
}
final ValueNotifier<bool> appClosing = ValueNotifier<bool>(false);
void main() async {
WidgetsFlutterBinding.ensureInitialized();
_installZeroOffsetPointerGuard(); // Workaround for iPadOS 26.1+ modal dismissal bug
@@ -255,6 +257,17 @@ class _MainAppState extends State<MainApp> with WidgetsBindingObserver {
darkTheme: themeProvider.darkTheme,
themeMode: themeProvider.materialThemeMode,
navigatorObservers: [routeObserver],
builder: (context, child) {
return ValueListenableBuilder<bool>(
valueListenable: appClosing,
builder: (context, closing, _) {
if (!closing) {
return child ?? const SizedBox.shrink();
}
return const SizedBox.expand(child: ColoredBox(color: Colors.black));
},
);
},
home: const OrientationAwareSetup(),
),
),
+28 -1
View File
@@ -1,7 +1,10 @@
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:window_manager/window_manager.dart';
import '../../services/plex_client.dart';
import '../i18n/strings.g.dart';
import '../services/update_service.dart';
@@ -64,7 +67,8 @@ class MainScreen extends StatefulWidget {
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> with RouteAware {
class _MainScreenState extends State<MainScreen> with RouteAware, WindowListener {
bool _isClosing = false;
late int _currentIndex;
String? _selectedLibraryGlobalKey;
@@ -97,6 +101,11 @@ class _MainScreenState extends State<MainScreen> with RouteAware {
super.initState();
_isOffline = widget.isOfflineMode;
if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
windowManager.addListener(this);
windowManager.setPreventClose(true);
}
// Start on Downloads tab when in offline mode
// In offline mode: visual index 0 = Downloads (screen 3), 1 = Settings (screen 4)
// In online mode: indices match directly
@@ -277,12 +286,30 @@ class _MainScreenState extends State<MainScreen> with RouteAware {
@override
void dispose() {
routeObserver.unsubscribe(this);
if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
windowManager.removeListener(this);
windowManager.setPreventClose(false);
}
_offlineModeProvider?.removeListener(_handleOfflineStatusChanged);
_sidebarFocusScope.dispose();
_contentFocusScope.dispose();
super.dispose();
}
@override
void onWindowClose() {
if (_isClosing) return;
_isClosing = true;
appClosing.value = true;
// Give the UI a brief moment to settle before tearing down the window.
Future<void>.delayed(const Duration(milliseconds: 150), () async {
await windowManager.setPreventClose(false);
await windowManager.destroy();
});
}
List<Widget> _buildScreens(bool offline) {
// In offline mode, only show Downloads and Settings
// In online mode, show all 5 screens