mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-10-27 11:43:47 +01:00 
			
		
		
		
	Added settings page
This commit is contained in:
		| @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:obtainium/pages/home.dart'; | ||||
| import 'package:obtainium/services/apps_provider.dart'; | ||||
| import 'package:obtainium/services/settings_provider.dart'; | ||||
| import 'package:obtainium/services/source_service.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:workmanager/workmanager.dart'; | ||||
| @@ -16,8 +17,8 @@ void backgroundUpdateCheck() { | ||||
|       String message = updates.length == 1 | ||||
|           ? '${updates[0].name} has an update.' | ||||
|           : '${(updates.length == 2 ? '${updates[0].name} and ${updates[1].name}' : '${updates[0].name} and ${updates.length - 1} more apps')} have updates.'; | ||||
|       appsProvider.downloaderNotifications.cancel(2); | ||||
|       appsProvider.notify( | ||||
|       await appsProvider.downloaderNotifications.cancel(2); | ||||
|       await appsProvider.notify( | ||||
|           2, | ||||
|           'Updates Available', | ||||
|           message, | ||||
| @@ -45,7 +46,10 @@ void main() async { | ||||
|       initialDelay: const Duration(minutes: 15), | ||||
|       constraints: Constraints(networkType: NetworkType.connected)); | ||||
|   runApp(MultiProvider( | ||||
|     providers: [ChangeNotifierProvider(create: (context) => AppsProvider())], | ||||
|     providers: [ | ||||
|       ChangeNotifierProvider(create: (context) => AppsProvider()), | ||||
|       ChangeNotifierProvider(create: (context) => SettingsProvider()) | ||||
|     ], | ||||
|     child: const MyApp(), | ||||
|   )); | ||||
| } | ||||
| @@ -59,9 +63,34 @@ class MyApp extends StatelessWidget { | ||||
|   Widget build(BuildContext context) { | ||||
|     return DynamicColorBuilder( | ||||
|         builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) { | ||||
|       // Initialize the settings provider (if needed) and perform first-run actions if needed | ||||
|       SettingsProvider settingsProvider = context.watch<SettingsProvider>(); | ||||
|       if (settingsProvider.prefs == null) { | ||||
|         settingsProvider.initializeSettings().then((_) { | ||||
|           bool isFirstRun = settingsProvider.checkAndFlipFirstRun(); | ||||
|           if (isFirstRun) { | ||||
|             AppsProvider appsProvider = context.read<AppsProvider>(); | ||||
|             appsProvider | ||||
|                 .notify( | ||||
|                     3, | ||||
|                     'Permission Notification', | ||||
|                     'This is a transient notification used to trigger the Android 13 notification permission prompt', | ||||
|                     'PERMISSION_NOTIFICATION', | ||||
|                     'Permission Notifications', | ||||
|                     'A transient notification used to trigger the Android 13 notification permission prompt', | ||||
|                     important: false) | ||||
|                 .whenComplete(() { | ||||
|               appsProvider.downloaderNotifications.cancel(3); | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|  | ||||
|       ColorScheme lightColorScheme; | ||||
|       ColorScheme darkColorScheme; | ||||
|       if (lightDynamic != null && darkDynamic != null) { | ||||
|       if (lightDynamic != null && | ||||
|           darkDynamic != null && | ||||
|           settingsProvider.colour == ColourSettings.materialYou) { | ||||
|         lightColorScheme = lightDynamic.harmonized(); | ||||
|         darkColorScheme = darkDynamic.harmonized(); | ||||
|       } else { | ||||
| @@ -74,10 +103,15 @@ class MyApp extends StatelessWidget { | ||||
|           title: 'Obtainium', | ||||
|           theme: ThemeData( | ||||
|               useMaterial3: true, | ||||
|               colorScheme: lightColorScheme, | ||||
|               colorScheme: settingsProvider.theme == ThemeSettings.dark | ||||
|                   ? darkColorScheme | ||||
|                   : lightColorScheme, | ||||
|               fontFamily: 'Metropolis'), | ||||
|           darkTheme: | ||||
|               ThemeData(useMaterial3: true, colorScheme: darkColorScheme), | ||||
|           darkTheme: ThemeData( | ||||
|               useMaterial3: true, | ||||
|               colorScheme: settingsProvider.theme == ThemeSettings.light | ||||
|                   ? lightColorScheme | ||||
|                   : darkColorScheme), | ||||
|           home: const HomePage()); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:obtainium/services/settings_provider.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:url_launcher/url_launcher_string.dart'; | ||||
|  | ||||
| class SettingsPage extends StatefulWidget { | ||||
|   const SettingsPage({super.key}); | ||||
| @@ -10,11 +13,74 @@ class SettingsPage extends StatefulWidget { | ||||
| class _SettingsPageState extends State<SettingsPage> { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Center( | ||||
|         child: Text( | ||||
|       'No Configurable Settings Yet.', | ||||
|       style: Theme.of(context).textTheme.bodyLarge, | ||||
|       textAlign: TextAlign.center, | ||||
|     SettingsProvider settingsProvider = context.watch<SettingsProvider>(); | ||||
|     if (settingsProvider.prefs == null) { | ||||
|       settingsProvider.initializeSettings(); | ||||
|     } | ||||
|     return Padding( | ||||
|         padding: const EdgeInsets.all(16), | ||||
|         child: settingsProvider.prefs == null | ||||
|             ? Container() | ||||
|             : Column( | ||||
|                 children: [ | ||||
|                   DropdownButtonFormField( | ||||
|                       decoration: const InputDecoration(labelText: 'Theme'), | ||||
|                       value: settingsProvider.theme, | ||||
|                       items: const [ | ||||
|                         DropdownMenuItem( | ||||
|                           value: ThemeSettings.dark, | ||||
|                           child: Text('Dark'), | ||||
|                         ), | ||||
|                         DropdownMenuItem( | ||||
|                           value: ThemeSettings.light, | ||||
|                           child: Text('Light'), | ||||
|                         ), | ||||
|                         DropdownMenuItem( | ||||
|                           value: ThemeSettings.system, | ||||
|                           child: Text('Follow System'), | ||||
|                         ) | ||||
|                       ], | ||||
|                       onChanged: (value) { | ||||
|                         if (value != null) { | ||||
|                           settingsProvider.theme = value; | ||||
|                         } | ||||
|                       }), | ||||
|                   const SizedBox( | ||||
|                     height: 16, | ||||
|                   ), | ||||
|                   DropdownButtonFormField( | ||||
|                       decoration: const InputDecoration(labelText: 'Colour'), | ||||
|                       value: settingsProvider.colour, | ||||
|                       items: const [ | ||||
|                         DropdownMenuItem( | ||||
|                           value: ColourSettings.basic, | ||||
|                           child: Text('Obtainium'), | ||||
|                         ), | ||||
|                         DropdownMenuItem( | ||||
|                           value: ColourSettings.materialYou, | ||||
|                           child: Text('Material You'), | ||||
|                         ) | ||||
|                       ], | ||||
|                       onChanged: (value) { | ||||
|                         if (value != null) { | ||||
|                           settingsProvider.colour = value; | ||||
|                         } | ||||
|                       }), | ||||
|                   const Spacer(), | ||||
|                   Row( | ||||
|                     mainAxisAlignment: MainAxisAlignment.end, | ||||
|                     children: [ | ||||
|                       ElevatedButton.icon( | ||||
|                         onPressed: () { | ||||
|                           launchUrlString(settingsProvider.sourceUrl, | ||||
|                               mode: LaunchMode.externalApplication); | ||||
|                         }, | ||||
|                         icon: const Icon(Icons.code), | ||||
|                         label: const Text('Source'), | ||||
|                       ) | ||||
|                     ], | ||||
|                   ), | ||||
|                 ], | ||||
|               )); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -51,7 +51,8 @@ class AppsProvider with ChangeNotifier { | ||||
|   } | ||||
|  | ||||
|   Future<void> notify(int id, String title, String message, String channelCode, | ||||
|       String channelName, String channelDescription) { | ||||
|       String channelName, String channelDescription, | ||||
|       {bool important = true}) { | ||||
|     return downloaderNotifications.show( | ||||
|         id, | ||||
|         title, | ||||
| @@ -59,8 +60,8 @@ class AppsProvider with ChangeNotifier { | ||||
|         NotificationDetails( | ||||
|             android: AndroidNotificationDetails(channelCode, channelName, | ||||
|                 channelDescription: channelDescription, | ||||
|                 importance: Importance.max, | ||||
|                 priority: Priority.max, | ||||
|                 importance: important ? Importance.max : Importance.min, | ||||
|                 priority: important ? Priority.max : Priority.min, | ||||
|                 groupKey: 'dev.imranr.obtainium.$channelCode'))); | ||||
|   } | ||||
|  | ||||
| @@ -98,6 +99,7 @@ class AppsProvider with ChangeNotifier { | ||||
|     } | ||||
|  | ||||
|     if (!isForeground) { | ||||
|       await downloaderNotifications.cancel(1); | ||||
|       await notify( | ||||
|           1, | ||||
|           'Complete App Installation', | ||||
|   | ||||
							
								
								
									
										47
									
								
								lib/services/settings_provider.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lib/services/settings_provider.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
|  | ||||
| enum ThemeSettings { system, light, dark } | ||||
|  | ||||
| enum ColourSettings { basic, materialYou } | ||||
|  | ||||
| class SettingsProvider with ChangeNotifier { | ||||
|   SharedPreferences? prefs; | ||||
|  | ||||
|   String sourceUrl = 'https://github.com/ImranR98/Obtainium'; | ||||
|  | ||||
|   // Not done in constructor as we want to be able to await it | ||||
|   Future<void> initializeSettings() async { | ||||
|     prefs = await SharedPreferences.getInstance(); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   ThemeSettings get theme { | ||||
|     return ThemeSettings | ||||
|         .values[prefs?.getInt('theme') ?? ThemeSettings.system.index]; | ||||
|   } | ||||
|  | ||||
|   set theme(ThemeSettings t) { | ||||
|     print(t); | ||||
|     prefs?.setInt('theme', t.index); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   ColourSettings get colour { | ||||
|     return ColourSettings | ||||
|         .values[prefs?.getInt('colour') ?? ColourSettings.basic.index]; | ||||
|   } | ||||
|  | ||||
|   set colour(ColourSettings t) { | ||||
|     prefs?.setInt('colour', t.index); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   checkAndFlipFirstRun() { | ||||
|     bool result = prefs?.getBool('firstRun') ?? true; | ||||
|     if (result) { | ||||
|       prefs?.setBool('firstRun', false); | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										124
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -172,6 +172,11 @@ packages: | ||||
|     description: flutter | ||||
|     source: sdk | ||||
|     version: "0.0.0" | ||||
|   flutter_web_plugins: | ||||
|     dependency: transitive | ||||
|     description: flutter | ||||
|     source: sdk | ||||
|     version: "0.0.0" | ||||
|   html: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -207,6 +212,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.0.0" | ||||
|   js: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: js | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "0.6.4" | ||||
|   json_annotation: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -340,6 +352,62 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "6.0.3" | ||||
|   shared_preferences: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: shared_preferences | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.15" | ||||
|   shared_preferences_android: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_android | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.12" | ||||
|   shared_preferences_ios: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_ios | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.1.1" | ||||
|   shared_preferences_linux: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_linux | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.1.1" | ||||
|   shared_preferences_macos: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_macos | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.4" | ||||
|   shared_preferences_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_platform_interface | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.0" | ||||
|   shared_preferences_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_web | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.4" | ||||
|   shared_preferences_windows: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: shared_preferences_windows | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.1.1" | ||||
|   sky_engine: | ||||
|     dependency: transitive | ||||
|     description: flutter | ||||
| @@ -401,6 +469,62 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.3.1" | ||||
|   url_launcher: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: url_launcher | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "6.1.5" | ||||
|   url_launcher_android: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_android | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "6.0.17" | ||||
|   url_launcher_ios: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_ios | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "6.0.17" | ||||
|   url_launcher_linux: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_linux | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "3.0.1" | ||||
|   url_launcher_macos: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_macos | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "3.0.1" | ||||
|   url_launcher_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_platform_interface | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.1.0" | ||||
|   url_launcher_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_web | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.13" | ||||
|   url_launcher_windows: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: url_launcher_windows | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "3.0.1" | ||||
|   vector_math: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -37,15 +37,17 @@ dependencies: | ||||
|   # Use with the CupertinoIcons class for iOS style icons. | ||||
|   cupertino_icons: ^1.0.2 | ||||
|   path_provider: ^2.0.11 | ||||
|   flutter_fgbg: ^0.2.0 | ||||
|   flutter_fgbg: ^0.2.0 # Try removing reliance on this | ||||
|   flutter_local_notifications: ^9.7.0 | ||||
|   provider: ^6.0.3 | ||||
|   http: ^0.13.5 | ||||
|   webview_flutter: ^3.0.4 | ||||
|   workmanager: ^0.5.0 | ||||
|   dynamic_color: ^1.5.3 | ||||
|   install_plugin_v2: ^1.0.0 | ||||
|   install_plugin_v2: ^1.0.0 # Try replacing this | ||||
|   html: ^0.15.0 | ||||
|   shared_preferences: ^2.0.15 | ||||
|   url_launcher: ^6.1.5 | ||||
|  | ||||
|  | ||||
| dev_dependencies: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user