From 3131ef8c4e59075e9989ea9ea867598a5f3459d2 Mon Sep 17 00:00:00 2001 From: Gregory Velichko Date: Mon, 15 Apr 2024 12:55:34 +0300 Subject: [PATCH] =?UTF-8?q?Neat=20slider=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/settings.dart | 95 +++++++++++++++++++++++++--- lib/providers/settings_provider.dart | 44 ++++--------- pubspec.lock | 28 ++++++-- pubspec.yaml | 1 + 4 files changed, 121 insertions(+), 47 deletions(-) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 68bad3a..51a5029 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,5 +1,6 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:equations/equations.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/components/custom_app_bar.dart'; import 'package:obtainium/components/generated_form.dart'; @@ -23,14 +24,64 @@ class SettingsPage extends StatefulWidget { } class _SettingsPageState extends State { + List updateIntervalNodes = [ + 15, 30, 60, 120, 180, 360, 720, 1440, 4320, 10080, 20160, 43200]; + int updateInterval = 0; + late SplineInterpolation updateIntervalInterpolator; // 🤓 + String updateIntervalLabel = tr('neverManualOnly'); + bool showIntervalLabel = true; + + void initUpdateIntervalInterpolator() { + List nodes = []; + for (final (index, element) in updateIntervalNodes.indexed) { + nodes.add(InterpolationNode(x: index.toDouble()+1, y: element.toDouble())); + } + updateIntervalInterpolator = SplineInterpolation(nodes: nodes); + } + + void processIntervalSliderValue(double val) { + if (val < 0.5) { + updateInterval = 0; + updateIntervalLabel = tr('neverManualOnly'); + return; + } + int valInterpolated = 0; + if (val < 1) { + valInterpolated = 15; + } else { + valInterpolated = updateIntervalInterpolator.compute(val).round(); + } + if (valInterpolated < 60) { + updateInterval = valInterpolated; + updateIntervalLabel = plural('minute', valInterpolated); + } else if (valInterpolated < 8 * 60) { + int valRounded = (valInterpolated / 15).ceil() * 15; + updateInterval = valRounded; + updateIntervalLabel = plural('hour', valRounded ~/ 60); + int mins = valRounded % 60; + if (mins != 0) updateIntervalLabel += " ${plural('minute', mins)}"; + } else if (valInterpolated < 24 * 60) { + int valRounded = (valInterpolated / 30).ceil() * 30; + updateInterval = valRounded; + updateIntervalLabel = plural('hour', valRounded / 60); + } else if (valInterpolated < 7 * 24 * 60){ + int valRounded = (valInterpolated / (12 * 60)).ceil() * 12 * 60; + updateInterval = valRounded; + updateIntervalLabel = plural('day', valRounded / (24 * 60)); + } else { + int valRounded = (valInterpolated / (24 * 60)).ceil() * 24 * 60; + updateInterval = valRounded; + updateIntervalLabel = plural('day', valRounded ~/ (24 * 60)); + } + } + @override Widget build(BuildContext context) { SettingsProvider settingsProvider = context.watch(); SourceProvider sourceProvider = SourceProvider(); - if (settingsProvider.prefs == null) { - settingsProvider.initializeSettings(); - } - + if (settingsProvider.prefs == null) settingsProvider.initializeSettings(); + initUpdateIntervalInterpolator(); + processIntervalSliderValue(settingsProvider.updateIntervalSliderVal); var themeDropdown = DropdownButtonFormField( decoration: InputDecoration(labelText: tr('theme')), value: settingsProvider.theme, @@ -143,7 +194,7 @@ class _SettingsPageState extends State { } }); - var intervalDropdown = DropdownButtonFormField( + /*var intervalDropdown = DropdownButtonFormField( decoration: InputDecoration(labelText: tr('bgUpdateCheckInterval')), value: settingsProvider.updateInterval, items: updateIntervals.map((e) { @@ -166,7 +217,31 @@ class _SettingsPageState extends State { if (value != null) { settingsProvider.updateInterval = value; } + });*/ + + var intervalSlider = Slider( + value: settingsProvider.updateIntervalSliderVal, + max: updateIntervalNodes.length.toDouble(), + divisions: updateIntervalNodes.length * 20, + label: updateIntervalLabel, + onChanged: (double value) { + setState(() { + settingsProvider.updateIntervalSliderVal = value; + processIntervalSliderValue(value); }); + }, + onChangeStart: (double value) { + setState(() { + showIntervalLabel = false; + }); + }, + onChangeEnd: (double value) { + setState(() { + showIntervalLabel = true; + settingsProvider.updateInterval = updateInterval; + }); + }, + ); var sourceSpecificFields = sourceProvider.sources.map((e) { if (e.sourceConfigSettingFormItems.isNotEmpty) { @@ -217,15 +292,19 @@ class _SettingsPageState extends State { fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary), ), - intervalDropdown, + //intervalDropdown, + height16, + if (showIntervalLabel) SizedBox( + child: Text("${tr('bgUpdateCheckInterval')}: $updateIntervalLabel") + ) else const SizedBox(height: 16), + intervalSlider, FutureBuilder( builder: (ctx, val) { - return (val.data?.version.sdkInt ?? 0) >= 30 + return ((val.data?.version.sdkInt ?? 0) >= 30) || settingsProvider.useShizuku ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - height16, Row( mainAxisAlignment: MainAxisAlignment diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index b2596b2..25c69f0 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -28,27 +28,6 @@ enum SortOrderSettings { ascending, descending } const maxAPIRateLimitMinutes = 30; const minUpdateIntervalMinutes = maxAPIRateLimitMinutes + 30; -const maxUpdateIntervalMinutes = 43200; -List updateIntervals = [ - 15, - 30, - 60, - 120, - 180, - 360, - 720, - 1440, - 4320, - 10080, - 20160, - 43200, - 0 -] - .where((element) => - (element >= minUpdateIntervalMinutes && - element <= maxUpdateIntervalMinutes) || - element == 0) - .toList(); class SettingsProvider with ChangeNotifier { SharedPreferences? prefs; @@ -121,21 +100,20 @@ class SettingsProvider with ChangeNotifier { } int get updateInterval { - var min = prefs?.getInt('updateInterval') ?? 360; - if (!updateIntervals.contains(min)) { - var temp = updateIntervals[0]; - for (var i in updateIntervals) { - if (min > i && i != 0) { - temp = i; - } - } - min = temp; - } - return min; + return prefs?.getInt('updateInterval') ?? 360; } set updateInterval(int min) { - prefs?.setInt('updateInterval', (min < 15 && min != 0) ? 15 : min); + prefs?.setInt('updateInterval', min); + notifyListeners(); + } + + double get updateIntervalSliderVal { + return prefs?.getDouble('updateIntervalSliderVal') ?? 6.0; + } + + set updateIntervalSliderVal(double val) { + prefs?.setDouble('updateIntervalSliderVal', val); notifyListeners(); } diff --git a/pubspec.lock b/pubspec.lock index 5b288dc..96f56cb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -235,6 +235,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.2" + equations: + dependency: "direct main" + description: + name: equations + sha256: ae30e977d601e19aa1fc3409736c5eac01559d1d653a4c30141fbc4e86aa605c + url: "https://pub.dev" + source: hosted + version: "5.0.2" fake_async: dependency: transitive description: @@ -345,10 +353,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "31c12de79262b5431c5492e9c89948aa789158435f707d3519a7fdef6af28af7" + sha256: "04c4722cc36ec5af38acc38ece70d22d3c2123c61305d555750a091517bbe504" url: "https://pub.dev" source: hosted - version: "0.6.22+1" + version: "0.6.23" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -375,6 +383,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.5" + fraction: + dependency: transitive + description: + name: fraction + sha256: "09e9504c9177bbd77df56e5d147abfbb3b43360e64bf61510059c14d6a82d524" + url: "https://pub.dev" + source: hosted + version: "5.0.2" gtk: dependency: transitive description: @@ -643,10 +659,10 @@ packages: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "5.4.0" platform: dependency: transitive description: @@ -1025,10 +1041,10 @@ packages: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.3.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 05c3970..0f5796c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,6 +68,7 @@ dependencies: crypto: ^3.0.3 app_links: ^4.0.0 background_fetch: ^1.2.1 + equations: ^5.0.2 android_system_font: git: url: https://github.com/re7gog/android_system_font