mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-12 18:08:10 +02:00
Neat slider ✨
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:equations/equations.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:obtainium/components/custom_app_bar.dart';
|
import 'package:obtainium/components/custom_app_bar.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
import 'package:obtainium/components/generated_form.dart';
|
||||||
@@ -23,14 +24,64 @@ class SettingsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SettingsPageState extends State<SettingsPage> {
|
class _SettingsPageState extends State<SettingsPage> {
|
||||||
|
List<int> 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<InterpolationNode> 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
SettingsProvider settingsProvider = context.watch<SettingsProvider>();
|
SettingsProvider settingsProvider = context.watch<SettingsProvider>();
|
||||||
SourceProvider sourceProvider = SourceProvider();
|
SourceProvider sourceProvider = SourceProvider();
|
||||||
if (settingsProvider.prefs == null) {
|
if (settingsProvider.prefs == null) settingsProvider.initializeSettings();
|
||||||
settingsProvider.initializeSettings();
|
initUpdateIntervalInterpolator();
|
||||||
}
|
processIntervalSliderValue(settingsProvider.updateIntervalSliderVal);
|
||||||
|
|
||||||
var themeDropdown = DropdownButtonFormField(
|
var themeDropdown = DropdownButtonFormField(
|
||||||
decoration: InputDecoration(labelText: tr('theme')),
|
decoration: InputDecoration(labelText: tr('theme')),
|
||||||
value: settingsProvider.theme,
|
value: settingsProvider.theme,
|
||||||
@@ -143,7 +194,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var intervalDropdown = DropdownButtonFormField(
|
/*var intervalDropdown = DropdownButtonFormField(
|
||||||
decoration: InputDecoration(labelText: tr('bgUpdateCheckInterval')),
|
decoration: InputDecoration(labelText: tr('bgUpdateCheckInterval')),
|
||||||
value: settingsProvider.updateInterval,
|
value: settingsProvider.updateInterval,
|
||||||
items: updateIntervals.map((e) {
|
items: updateIntervals.map((e) {
|
||||||
@@ -166,7 +217,31 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
if (value != null) {
|
if (value != null) {
|
||||||
settingsProvider.updateInterval = value;
|
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) {
|
var sourceSpecificFields = sourceProvider.sources.map((e) {
|
||||||
if (e.sourceConfigSettingFormItems.isNotEmpty) {
|
if (e.sourceConfigSettingFormItems.isNotEmpty) {
|
||||||
@@ -217,15 +292,19 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context).colorScheme.primary),
|
color: Theme.of(context).colorScheme.primary),
|
||||||
),
|
),
|
||||||
intervalDropdown,
|
//intervalDropdown,
|
||||||
|
height16,
|
||||||
|
if (showIntervalLabel) SizedBox(
|
||||||
|
child: Text("${tr('bgUpdateCheckInterval')}: $updateIntervalLabel")
|
||||||
|
) else const SizedBox(height: 16),
|
||||||
|
intervalSlider,
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
builder: (ctx, val) {
|
builder: (ctx, val) {
|
||||||
return (val.data?.version.sdkInt ?? 0) >= 30
|
return ((val.data?.version.sdkInt ?? 0) >= 30) || settingsProvider.useShizuku
|
||||||
? Column(
|
? Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
height16,
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment
|
MainAxisAlignment
|
||||||
|
@@ -28,27 +28,6 @@ enum SortOrderSettings { ascending, descending }
|
|||||||
|
|
||||||
const maxAPIRateLimitMinutes = 30;
|
const maxAPIRateLimitMinutes = 30;
|
||||||
const minUpdateIntervalMinutes = maxAPIRateLimitMinutes + 30;
|
const minUpdateIntervalMinutes = maxAPIRateLimitMinutes + 30;
|
||||||
const maxUpdateIntervalMinutes = 43200;
|
|
||||||
List<int> 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 {
|
class SettingsProvider with ChangeNotifier {
|
||||||
SharedPreferences? prefs;
|
SharedPreferences? prefs;
|
||||||
@@ -121,21 +100,20 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get updateInterval {
|
int get updateInterval {
|
||||||
var min = prefs?.getInt('updateInterval') ?? 360;
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set updateInterval(int min) {
|
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();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
pubspec.lock
28
pubspec.lock
@@ -235,6 +235,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.2"
|
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:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -345,10 +353,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
sha256: "31c12de79262b5431c5492e9c89948aa789158435f707d3519a7fdef6af28af7"
|
sha256: "04c4722cc36ec5af38acc38ece70d22d3c2123c61305d555750a091517bbe504"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.22+1"
|
version: "0.6.23"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -375,6 +383,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.2.5"
|
version: "8.2.5"
|
||||||
|
fraction:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fraction
|
||||||
|
sha256: "09e9504c9177bbd77df56e5d147abfbb3b43360e64bf61510059c14d6a82d524"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.2"
|
||||||
gtk:
|
gtk:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -643,10 +659,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: petitparser
|
name: petitparser
|
||||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.2"
|
version: "5.4.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1025,10 +1041,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xml
|
name: xml
|
||||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.5.0"
|
version: "6.3.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@@ -68,6 +68,7 @@ dependencies:
|
|||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
app_links: ^4.0.0
|
app_links: ^4.0.0
|
||||||
background_fetch: ^1.2.1
|
background_fetch: ^1.2.1
|
||||||
|
equations: ^5.0.2
|
||||||
android_system_font:
|
android_system_font:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/re7gog/android_system_font
|
url: https://github.com/re7gog/android_system_font
|
||||||
|
Reference in New Issue
Block a user