2024-04-30 23:38:49 +08:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
2025-09-23 21:02:47 +08:00
|
|
|
import 'package:fl_clash/common/common.dart';
|
2025-05-02 02:24:12 +08:00
|
|
|
import 'package:fl_clash/enum/enum.dart';
|
|
|
|
|
|
2024-04-30 23:38:49 +08:00
|
|
|
class Debouncer {
|
2025-05-02 02:24:12 +08:00
|
|
|
final Map<FunctionTag, Timer?> _operations = {};
|
2024-04-30 23:38:49 +08:00
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
void call(
|
2025-05-02 02:24:12 +08:00
|
|
|
FunctionTag tag,
|
2024-12-09 01:40:39 +08:00
|
|
|
Function func, {
|
|
|
|
|
List<dynamic>? args,
|
2025-07-31 17:09:18 +08:00
|
|
|
Duration? duration,
|
2024-12-09 01:40:39 +08:00
|
|
|
}) {
|
2025-02-03 23:32:00 +08:00
|
|
|
final timer = _operations[tag];
|
2024-12-09 01:40:39 +08:00
|
|
|
if (timer != null) {
|
|
|
|
|
timer.cancel();
|
|
|
|
|
}
|
2025-07-31 17:09:18 +08:00
|
|
|
_operations[tag] = Timer(duration ?? const Duration(milliseconds: 600), () {
|
|
|
|
|
_operations[tag]?.cancel();
|
|
|
|
|
_operations.remove(tag);
|
|
|
|
|
Function.apply(func, args);
|
|
|
|
|
});
|
2024-12-09 01:40:39 +08:00
|
|
|
}
|
2024-04-30 23:38:49 +08:00
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
void cancel(dynamic tag) {
|
2025-02-03 23:32:00 +08:00
|
|
|
_operations[tag]?.cancel();
|
2025-03-12 17:15:31 +08:00
|
|
|
_operations[tag] = null;
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-03 23:32:00 +08:00
|
|
|
class Throttler {
|
2025-05-02 02:24:12 +08:00
|
|
|
final Map<FunctionTag, Timer?> _operations = {};
|
2025-02-03 23:32:00 +08:00
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
bool call(
|
2025-05-02 02:24:12 +08:00
|
|
|
FunctionTag tag,
|
2025-02-03 23:32:00 +08:00
|
|
|
Function func, {
|
|
|
|
|
List<dynamic>? args,
|
|
|
|
|
Duration duration = const Duration(milliseconds: 600),
|
2025-07-31 17:09:18 +08:00
|
|
|
bool fire = false,
|
2025-02-03 23:32:00 +08:00
|
|
|
}) {
|
|
|
|
|
final timer = _operations[tag];
|
|
|
|
|
if (timer != null) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2025-07-31 17:09:18 +08:00
|
|
|
if (fire) {
|
|
|
|
|
Function.apply(func, args);
|
|
|
|
|
_operations[tag] = Timer(duration, () {
|
2025-02-03 23:32:00 +08:00
|
|
|
_operations[tag]?.cancel();
|
|
|
|
|
_operations.remove(tag);
|
2025-07-31 17:09:18 +08:00
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
_operations[tag] = Timer(duration, () {
|
|
|
|
|
Function.apply(func, args);
|
|
|
|
|
_operations[tag]?.cancel();
|
|
|
|
|
_operations.remove(tag);
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-02-03 23:32:00 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-07 01:48:34 +08:00
|
|
|
void cancel(dynamic tag) {
|
2025-02-03 23:32:00 +08:00
|
|
|
_operations[tag]?.cancel();
|
2025-03-12 17:15:31 +08:00
|
|
|
_operations[tag] = null;
|
2025-02-03 23:32:00 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-09 18:39:38 +08:00
|
|
|
Future<T> retry<T>({
|
|
|
|
|
required Future<T> Function() task,
|
|
|
|
|
int maxAttempts = 3,
|
|
|
|
|
required bool Function(T res) retryIf,
|
2025-09-23 21:02:47 +08:00
|
|
|
Duration delay = midDuration,
|
2025-02-09 18:39:38 +08:00
|
|
|
}) async {
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
while (attempts < maxAttempts) {
|
|
|
|
|
final res = await task();
|
|
|
|
|
if (!retryIf(res) || attempts >= maxAttempts) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
attempts++;
|
|
|
|
|
}
|
2025-09-23 21:02:47 +08:00
|
|
|
throw 'retry error';
|
2025-02-09 18:39:38 +08:00
|
|
|
}
|
2025-02-03 23:32:00 +08:00
|
|
|
|
2024-12-09 01:40:39 +08:00
|
|
|
final debouncer = Debouncer();
|
2025-02-03 23:32:00 +08:00
|
|
|
|
2025-02-09 18:39:38 +08:00
|
|
|
final throttler = Throttler();
|