ui: better sleep timer ui in player and fix auto turn on settings (#43)

* refactor: enhance sleep timer functionality and improve duration formatting

* refactor: update sleep timer settings handling

* refactor: update cancel icon for sleep timer button

* refactor: implement isBetween method for TimeOfDay and simplify sleep timer logic

* refactor: update alwaysAutoTurnOnTimer default value and improve icon usage in settings

* refactor: remove unused IconButton and update sleep timer preset durations
This commit is contained in:
Dr.Blank 2024-10-02 09:18:06 -04:00 committed by GitHub
parent 933bfc5750
commit 12100ffbcd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 755 additions and 383 deletions

View file

@ -9,14 +9,27 @@ extension DurationFormat on Duration {
final minutes = inMinutes.remainder(60);
final seconds = inSeconds.remainder(60);
if (hours > 0) {
return '${hours}h ${minutes}m';
// skip minutes if it's 0
if (minutes == 0) {
return smartSingleFormat;
}
return '${Duration(hours: hours).smartBinaryFormat} ${Duration(minutes: minutes).smartSingleFormat}';
} else if (minutes > 0) {
return '${minutes}m ${seconds}s';
if (seconds == 0) {
return smartSingleFormat;
}
return '${Duration(minutes: minutes).smartSingleFormat} ${Duration(seconds: seconds).smartSingleFormat}';
} else {
return '${seconds}s';
return smartSingleFormat;
}
}
/// formats the duration using only 1 unit
/// if the duration is more than 1 hour, it will return `10h`
/// if the duration is less than 1 hour, it will return `30m`
/// if the duration is less than 1 minute, it will return `20s`
///
/// rest of the duration will be ignored
String get smartSingleFormat {
if (inHours > 0) {
return '${inHours}h';

View file

@ -2,7 +2,10 @@ import 'package:flutter/material.dart';
extension ToTimeOfDay on Duration {
TimeOfDay toTimeOfDay() {
return TimeOfDay(hour: inHours, minute: inMinutes % 60);
return TimeOfDay(
hour: inHours % 24,
minute: inMinutes % 60,
);
}
}
@ -28,4 +31,16 @@ extension TimeOfDayExtension on TimeOfDay {
bool isBefore(TimeOfDay other) => this < other;
bool isAfter(TimeOfDay other) => this > other;
bool isBetween(TimeOfDay start, TimeOfDay end) {
// needs more logic to handle the case where start is after end
//but on the other day
if (start == end) {
return this == start;
}
if (start < end) {
return this >= start && this <= end;
}
return this >= start || this <= end;
}
}

View file

@ -28,3 +28,64 @@ void useTimer(VoidCallback callback, Duration delay) {
[delay],
);
}
/// Creates [FixedExtentScrollController] that will be disposed automatically.
///
/// See also:
/// - [FixedExtentScrollController]
FixedExtentScrollController useFixedExtentScrollController({
String? debugLabel,
List<Object?>? keys,
int initialItem = 0,
void Function(ScrollPosition)? onAttach,
void Function(ScrollPosition)? onDetach,
}) {
return use(
_FixedExtentScrollControllerHook(
debugLabel: debugLabel,
keys: keys,
initialItem: initialItem,
onAttach: onAttach,
onDetach: onDetach,
),
);
}
class _FixedExtentScrollControllerHook
extends Hook<FixedExtentScrollController> {
const _FixedExtentScrollControllerHook({
this.debugLabel,
super.keys,
required this.initialItem,
this.onAttach,
this.onDetach,
});
final int initialItem;
final void Function(ScrollPosition)? onAttach;
final void Function(ScrollPosition)? onDetach;
final String? debugLabel;
@override
HookState<FixedExtentScrollController, Hook<FixedExtentScrollController>>
createState() => _FixedExtentScrollControllerHookState();
}
class _FixedExtentScrollControllerHookState extends HookState<
FixedExtentScrollController, _FixedExtentScrollControllerHook> {
late final controller = FixedExtentScrollController(
initialItem: hook.initialItem,
onAttach: hook.onAttach,
onDetach: hook.onDetach,
);
@override
FixedExtentScrollController build(BuildContext context) => controller;
@override
void dispose() => controller.dispose();
@override
String get debugLabel => 'useFixedExtentScrollController';
}