Skip to content

Commit

Permalink
Properly quit tr session when closing app
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Ray committed Jan 14, 2025
1 parent 4a8f4f9 commit c061aca
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 11 deletions.
13 changes: 13 additions & 0 deletions app/lib/dialogs/quitting.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:flutter/material.dart';

class QuittingDialog extends StatelessWidget {
const QuittingDialog({super.key});

@override
Widget build(BuildContext context) {
return const AlertDialog(
title: Text('Quitting'),
content: Text('Please wait while PikaTorrent is stopping...'),
);
}
}
62 changes: 53 additions & 9 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ void main() async {
class PikaTorrent extends StatelessWidget {
const PikaTorrent({super.key});

// App root
@override
Widget build(BuildContext context) {
return MultiProvider(
Expand All @@ -104,14 +103,59 @@ class PikaTorrent extends StatelessWidget {
ChangeNotifierProvider(create: (context) => TorrentsModel()),
ChangeNotifierProvider(create: (context) => SessionModel())
],
child: Consumer<AppModel>(
builder: (context, app, child) => MaterialApp.router(
title: 'PikaTorrent',
theme: _lightTheme,
darkTheme: _darkTheme,
themeMode: app.theme,
routerConfig: router,
)),
child: const PikaTorrentApp(),
);
}
}

class PikaTorrentApp extends StatefulWidget {
const PikaTorrentApp({super.key});

@override
State<PikaTorrentApp> createState() => _PikaTorrentAppState();
}

class _PikaTorrentAppState extends State<PikaTorrentApp> with WindowListener {
@override
void initState() {
super.initState();
windowManager.addListener(this);
_init();
}

@override
void dispose() {
windowManager.removeListener(this);
super.dispose();
}

void _init() async {
if (isDesktop()) {
// Add this line to override the default close handler
await windowManager.setPreventClose(true);
setState(() {});
}
}

@override
void onWindowClose() async {
var appModel = Provider.of<AppModel>(context, listen: false);
appModel.setQuitting(true);
//FIXME: Workaround to call sync quit function *after* quitting dialog is shown
await Future.delayed(const Duration(milliseconds: 500));
appModel.quit();
}

// App root
@override
Widget build(BuildContext context) {
return Consumer<AppModel>(
builder: (context, app, child) => MaterialApp.router(
title: 'PikaTorrent',
theme: _lightTheme,
darkTheme: _darkTheme,
themeMode: app.theme,
routerConfig: router,
));
}
}
13 changes: 13 additions & 0 deletions app/lib/models/app.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pikatorrent/main.dart';
import 'package:pikatorrent/storage/shared_preferences.dart';
import 'package:window_manager/window_manager.dart';

class AppModel extends ChangeNotifier {
ThemeMode theme = ThemeMode.system;
bool termsOfUseAccepted = false;
bool checkForUpdate = true;
bool loaded = false;
bool quitting = false;
String version = '';

AppModel() {
Expand Down Expand Up @@ -51,4 +54,14 @@ class AppModel extends ChangeNotifier {
checkForUpdate = value;
notifyListeners();
}

void setQuitting(bool value) {
quitting = value;
notifyListeners();
}

void quit() async {
engine.dispose();
await windowManager.destroy();
}
}
21 changes: 21 additions & 0 deletions app/lib/navigation/app_shell_route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'package:pikatorrent/dialogs/add_torrent.dart';
import 'package:pikatorrent/dialogs/quitting.dart';
import 'package:pikatorrent/dialogs/terms_of_use.dart';
import 'package:pikatorrent/dialogs/update_available.dart';
import 'package:pikatorrent/models/app.dart';
Expand All @@ -24,6 +25,7 @@ class _AppShellRouteState extends State<AppShellRoute> {
late AppLinks _appLinks;
bool isTermsOfUseDialogDisplayed = false;
bool hasShownUpdateDialog = false;
bool showQuittingDialog = false;

@override
void initState() {
Expand Down Expand Up @@ -115,13 +117,32 @@ class _AppShellRouteState extends State<AppShellRoute> {
}
}

_openQuittingDialog(AppModel appModel) {
if (!showQuittingDialog) {
showQuittingDialog = true;
WidgetsBinding.instance.addPostFrameCallback((_) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return const QuittingDialog();
});
});
}
}

@override
Widget build(BuildContext context) {
return Consumer<AppModel>(builder: (context, appModel, child) {
if (appModel.loaded) {
_openTermsOfUseDialog(appModel);
_checkForUpdate();
}

if (appModel.quitting && !showQuittingDialog) {
_openQuittingDialog(appModel);
}

return Navigation(child: widget.child);
});
}
Expand Down
2 changes: 1 addition & 1 deletion app/lib/platforms/android/foreground_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ void onDidReceiveNotificationResponse(
NotificationResponse notificationResponse) async {
if (notificationResponse.actionId == 'exit') {
// Close BitTorrent engine
engine.dispose();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
Expand All @@ -15,6 +14,7 @@ void onDidReceiveNotificationResponse(
?.stopForegroundService();
// Exit app
SystemNavigator.pop();
engine.dispose();
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/test/widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'package:pikatorrent/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const PikaTorrent());
await tester.pumpWidget(const PikaTorrentApp());

// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
Expand Down

0 comments on commit c061aca

Please sign in to comment.