|
@@ -10,10 +10,10 @@ enum ExecutionState {
|
|
|
}
|
|
|
|
|
|
typedef OnChangedCallBack = Future<void> Function();
|
|
|
-typedef ValueCallBack = bool Function();
|
|
|
+typedef FutureValueCallBack = Future<bool> Function();
|
|
|
|
|
|
class ToggleSwitchWidget extends StatefulWidget {
|
|
|
- final ValueCallBack value;
|
|
|
+ final FutureValueCallBack value;
|
|
|
final OnChangedCallBack onChanged;
|
|
|
const ToggleSwitchWidget({
|
|
|
required this.value,
|
|
@@ -26,12 +26,15 @@ class ToggleSwitchWidget extends StatefulWidget {
|
|
|
}
|
|
|
|
|
|
class _ToggleSwitchWidgetState extends State<ToggleSwitchWidget> {
|
|
|
+ late Future<bool> futureToggleValue;
|
|
|
late bool toggleValue;
|
|
|
ExecutionState executionState = ExecutionState.idle;
|
|
|
final _debouncer = Debouncer(const Duration(milliseconds: 300));
|
|
|
@override
|
|
|
void initState() {
|
|
|
- toggleValue = widget.value.call();
|
|
|
+ futureToggleValue = widget.value.call();
|
|
|
+//need to assign correct intiial value of toggleValue here
|
|
|
+ toggleValue = true;
|
|
|
super.initState();
|
|
|
}
|
|
|
|
|
@@ -40,68 +43,78 @@ class _ToggleSwitchWidgetState extends State<ToggleSwitchWidget> {
|
|
|
final enteColorScheme = Theme.of(context).colorScheme.enteTheme.colorScheme;
|
|
|
final Widget stateIcon = _stateIcon(enteColorScheme);
|
|
|
|
|
|
- return Row(
|
|
|
- children: [
|
|
|
- Padding(
|
|
|
- padding: const EdgeInsets.only(right: 2),
|
|
|
- child: AnimatedSwitcher(
|
|
|
- duration: const Duration(milliseconds: 175),
|
|
|
- switchInCurve: Curves.easeInExpo,
|
|
|
- switchOutCurve: Curves.easeOutExpo,
|
|
|
- child: stateIcon,
|
|
|
- ),
|
|
|
- ),
|
|
|
- SizedBox(
|
|
|
- height: 31,
|
|
|
- child: FittedBox(
|
|
|
- fit: BoxFit.contain,
|
|
|
- child: Switch.adaptive(
|
|
|
- activeColor: enteColorScheme.primary400,
|
|
|
- inactiveTrackColor: enteColorScheme.fillMuted,
|
|
|
- materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
|
- value: toggleValue,
|
|
|
- onChanged: (negationOfToggleValue) async {
|
|
|
- setState(() {
|
|
|
- toggleValue = negationOfToggleValue;
|
|
|
- //start showing inProgress statu icons if toggle takes more than debounce time
|
|
|
- _debouncer.run(
|
|
|
- () => Future(
|
|
|
- () {
|
|
|
- setState(() {
|
|
|
- executionState = ExecutionState.inProgress;
|
|
|
- });
|
|
|
- },
|
|
|
- ),
|
|
|
- );
|
|
|
- });
|
|
|
- final Stopwatch stopwatch = Stopwatch()..start();
|
|
|
- await widget.onChanged.call();
|
|
|
- //for toggle feedback on short unsuccessful onChanged
|
|
|
- await _feedbackOnUnsuccessfulToggle(stopwatch);
|
|
|
- //debouncer gets canceled if onChanged takes less than debounce time
|
|
|
- _debouncer.cancelDebounce();
|
|
|
- setState(() {
|
|
|
- final newValue = widget.value.call();
|
|
|
- //if onchanged on toggle is successful
|
|
|
- if (toggleValue == newValue) {
|
|
|
- if (executionState == ExecutionState.inProgress) {
|
|
|
- executionState = ExecutionState.successful;
|
|
|
- Future.delayed(const Duration(seconds: 2), () {
|
|
|
- setState(() {
|
|
|
+ return FutureBuilder(
|
|
|
+ future: futureToggleValue,
|
|
|
+ builder: (context, snapshot) {
|
|
|
+ return Row(
|
|
|
+ children: [
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.only(right: 2),
|
|
|
+ child: AnimatedSwitcher(
|
|
|
+ duration: const Duration(milliseconds: 175),
|
|
|
+ switchInCurve: Curves.easeInExpo,
|
|
|
+ switchOutCurve: Curves.easeOutExpo,
|
|
|
+ child: stateIcon,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(
|
|
|
+ height: 31,
|
|
|
+ child: FittedBox(
|
|
|
+ fit: BoxFit.contain,
|
|
|
+ child: Switch.adaptive(
|
|
|
+ activeColor: enteColorScheme.primary400,
|
|
|
+ inactiveTrackColor: enteColorScheme.fillMuted,
|
|
|
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
|
+ value: toggleValue,
|
|
|
+ onChanged: (negationOfToggleValue) async {
|
|
|
+ setState(() {
|
|
|
+ toggleValue = negationOfToggleValue;
|
|
|
+ //start showing inProgress statu icons if toggle takes more than debounce time
|
|
|
+ _debouncer.run(
|
|
|
+ () => Future(
|
|
|
+ () {
|
|
|
+ setState(() {
|
|
|
+ executionState = ExecutionState.inProgress;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ });
|
|
|
+ final Stopwatch stopwatch = Stopwatch()..start();
|
|
|
+ await widget.onChanged.call();
|
|
|
+ //for toggle feedback on short unsuccessful onChanged
|
|
|
+ await _feedbackOnUnsuccessfulToggle(stopwatch);
|
|
|
+ //debouncer gets canceled if onChanged takes less than debounce time
|
|
|
+ _debouncer.cancelDebounce();
|
|
|
+
|
|
|
+ widget.value.call().then((newValue) {
|
|
|
+ setState(() {
|
|
|
+ //if onchanged on toggle is successful
|
|
|
+ // print('here');
|
|
|
+ // print(toggleValue);
|
|
|
+ // print("newValue : $newValue");
|
|
|
+ if (toggleValue == newValue) {
|
|
|
+ if (executionState == ExecutionState.inProgress) {
|
|
|
+ executionState = ExecutionState.successful;
|
|
|
+ Future.delayed(const Duration(seconds: 2), () {
|
|
|
+ setState(() {
|
|
|
+ executionState = ExecutionState.idle;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ toggleValue = !toggleValue;
|
|
|
executionState = ExecutionState.idle;
|
|
|
- });
|
|
|
+ }
|
|
|
});
|
|
|
- }
|
|
|
- } else {
|
|
|
- toggleValue = !toggleValue;
|
|
|
- executionState = ExecutionState.idle;
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
+ });
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ),
|
|
|
),
|
|
|
- ),
|
|
|
- ),
|
|
|
- ],
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ },
|
|
|
);
|
|
|
}
|
|
|
|