mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-16 19:58:09 +02: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:flutter/services.dart';
|
||||||
import 'package:obtainium/pages/home.dart';
|
import 'package:obtainium/pages/home.dart';
|
||||||
import 'package:obtainium/services/apps_provider.dart';
|
import 'package:obtainium/services/apps_provider.dart';
|
||||||
|
import 'package:obtainium/services/settings_provider.dart';
|
||||||
import 'package:obtainium/services/source_service.dart';
|
import 'package:obtainium/services/source_service.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:workmanager/workmanager.dart';
|
import 'package:workmanager/workmanager.dart';
|
||||||
@@ -16,8 +17,8 @@ void backgroundUpdateCheck() {
|
|||||||
String message = updates.length == 1
|
String message = updates.length == 1
|
||||||
? '${updates[0].name} has an update.'
|
? '${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.';
|
: '${(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);
|
await appsProvider.downloaderNotifications.cancel(2);
|
||||||
appsProvider.notify(
|
await appsProvider.notify(
|
||||||
2,
|
2,
|
||||||
'Updates Available',
|
'Updates Available',
|
||||||
message,
|
message,
|
||||||
@@ -45,7 +46,10 @@ void main() async {
|
|||||||
initialDelay: const Duration(minutes: 15),
|
initialDelay: const Duration(minutes: 15),
|
||||||
constraints: Constraints(networkType: NetworkType.connected));
|
constraints: Constraints(networkType: NetworkType.connected));
|
||||||
runApp(MultiProvider(
|
runApp(MultiProvider(
|
||||||
providers: [ChangeNotifierProvider(create: (context) => AppsProvider())],
|
providers: [
|
||||||
|
ChangeNotifierProvider(create: (context) => AppsProvider()),
|
||||||
|
ChangeNotifierProvider(create: (context) => SettingsProvider())
|
||||||
|
],
|
||||||
child: const MyApp(),
|
child: const MyApp(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -59,9 +63,34 @@ class MyApp extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DynamicColorBuilder(
|
return DynamicColorBuilder(
|
||||||
builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
|
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 lightColorScheme;
|
||||||
ColorScheme darkColorScheme;
|
ColorScheme darkColorScheme;
|
||||||
if (lightDynamic != null && darkDynamic != null) {
|
if (lightDynamic != null &&
|
||||||
|
darkDynamic != null &&
|
||||||
|
settingsProvider.colour == ColourSettings.materialYou) {
|
||||||
lightColorScheme = lightDynamic.harmonized();
|
lightColorScheme = lightDynamic.harmonized();
|
||||||
darkColorScheme = darkDynamic.harmonized();
|
darkColorScheme = darkDynamic.harmonized();
|
||||||
} else {
|
} else {
|
||||||
@@ -74,10 +103,15 @@ class MyApp extends StatelessWidget {
|
|||||||
title: 'Obtainium',
|
title: 'Obtainium',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: lightColorScheme,
|
colorScheme: settingsProvider.theme == ThemeSettings.dark
|
||||||
|
? darkColorScheme
|
||||||
|
: lightColorScheme,
|
||||||
fontFamily: 'Metropolis'),
|
fontFamily: 'Metropolis'),
|
||||||
darkTheme:
|
darkTheme: ThemeData(
|
||||||
ThemeData(useMaterial3: true, colorScheme: darkColorScheme),
|
useMaterial3: true,
|
||||||
|
colorScheme: settingsProvider.theme == ThemeSettings.light
|
||||||
|
? lightColorScheme
|
||||||
|
: darkColorScheme),
|
||||||
home: const HomePage());
|
home: const HomePage());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 {
|
class SettingsPage extends StatefulWidget {
|
||||||
const SettingsPage({super.key});
|
const SettingsPage({super.key});
|
||||||
@@ -10,11 +13,74 @@ class SettingsPage extends StatefulWidget {
|
|||||||
class _SettingsPageState extends State<SettingsPage> {
|
class _SettingsPageState extends State<SettingsPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
SettingsProvider settingsProvider = context.watch<SettingsProvider>();
|
||||||
child: Text(
|
if (settingsProvider.prefs == null) {
|
||||||
'No Configurable Settings Yet.',
|
settingsProvider.initializeSettings();
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
}
|
||||||
textAlign: TextAlign.center,
|
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,
|
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(
|
return downloaderNotifications.show(
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
@@ -59,8 +60,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
NotificationDetails(
|
NotificationDetails(
|
||||||
android: AndroidNotificationDetails(channelCode, channelName,
|
android: AndroidNotificationDetails(channelCode, channelName,
|
||||||
channelDescription: channelDescription,
|
channelDescription: channelDescription,
|
||||||
importance: Importance.max,
|
importance: important ? Importance.max : Importance.min,
|
||||||
priority: Priority.max,
|
priority: important ? Priority.max : Priority.min,
|
||||||
groupKey: 'dev.imranr.obtainium.$channelCode')));
|
groupKey: 'dev.imranr.obtainium.$channelCode')));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +99,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isForeground) {
|
if (!isForeground) {
|
||||||
|
await downloaderNotifications.cancel(1);
|
||||||
await notify(
|
await notify(
|
||||||
1,
|
1,
|
||||||
'Complete App Installation',
|
'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
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
html:
|
html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -207,6 +212,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.4"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -340,6 +352,62 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.3"
|
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:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -401,6 +469,62 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
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:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@@ -37,15 +37,17 @@ dependencies:
|
|||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
path_provider: ^2.0.11
|
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
|
flutter_local_notifications: ^9.7.0
|
||||||
provider: ^6.0.3
|
provider: ^6.0.3
|
||||||
http: ^0.13.5
|
http: ^0.13.5
|
||||||
webview_flutter: ^3.0.4
|
webview_flutter: ^3.0.4
|
||||||
workmanager: ^0.5.0
|
workmanager: ^0.5.0
|
||||||
dynamic_color: ^1.5.3
|
dynamic_color: ^1.5.3
|
||||||
install_plugin_v2: ^1.0.0
|
install_plugin_v2: ^1.0.0 # Try replacing this
|
||||||
html: ^0.15.0
|
html: ^0.15.0
|
||||||
|
shared_preferences: ^2.0.15
|
||||||
|
url_launcher: ^6.1.5
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Reference in New Issue
Block a user