Files
umbrix/lib/features/proxy/active/active_proxy_notifier.dart

128 lines
3.8 KiB
Dart
Raw Normal View History

2024-02-17 14:49:44 +03:30
import 'dart:async';
2024-02-09 12:02:52 +03:30
import 'package:dio/dio.dart';
2024-02-16 14:33:03 +03:30
import 'package:hiddify/core/haptic/haptic_service.dart';
2024-02-17 13:11:50 +03:30
import 'package:hiddify/core/preferences/general_preferences.dart';
2024-02-13 16:59:35 +03:30
import 'package:hiddify/core/utils/throttler.dart';
2024-02-09 12:02:52 +03:30
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
import 'package:hiddify/features/proxy/data/proxy_data_providers.dart';
import 'package:hiddify/features/proxy/model/ip_info_entity.dart';
import 'package:hiddify/features/proxy/model/proxy_entity.dart';
import 'package:hiddify/features/proxy/model/proxy_failure.dart';
import 'package:hiddify/utils/riverpod_utils.dart';
import 'package:hiddify/utils/utils.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'active_proxy_notifier.g.dart';
@riverpod
2024-02-13 16:59:35 +03:30
class IpInfoNotifier extends _$IpInfoNotifier with AppLogger {
@override
Future<IpInfo> build() async {
ref.disposeDelay(const Duration(seconds: 20));
final cancelToken = CancelToken();
2024-02-17 14:49:44 +03:30
Timer? timer;
2024-02-13 16:59:35 +03:30
ref.onDispose(() {
loggy.debug("disposing");
cancelToken.cancel();
2024-02-17 14:49:44 +03:30
timer?.cancel();
});
2024-02-17 14:49:44 +03:30
ref.listen(
serviceRunningProvider,
(_, next) => _idle = false,
);
2024-03-02 22:53:14 +03:30
final autoCheck = ref.watch(Preferences.autoCheckIp);
2024-02-13 16:59:35 +03:30
final serviceRunning = await ref.watch(serviceRunningProvider.future);
2024-02-17 14:49:44 +03:30
// loggy.debug(
// "idle? [$_idle], forced? [$_forceCheck], connected? [$serviceRunning]",
// );
if (!_forceCheck && !serviceRunning) {
2024-02-13 16:59:35 +03:30
throw const ServiceNotRunning();
2024-02-17 14:49:44 +03:30
} else if ((_idle && !_forceCheck) ||
(!_forceCheck && serviceRunning && !autoCheck)) {
2024-02-17 13:11:50 +03:30
throw const UnknownIp();
}
2024-02-17 14:49:44 +03:30
_forceCheck = false;
final info = await ref
2024-02-13 16:59:35 +03:30
.watch(proxyRepositoryProvider)
.getCurrentIpInfo(cancelToken)
.getOrElse(
(err) {
2024-02-20 18:49:30 +03:30
loggy.warning("error getting proxy ip info", err, StackTrace.current);
// throw err; //hiddify: remove exception to be logged
throw const UnknownIp();
2024-02-13 16:59:35 +03:30
},
).run();
2024-02-17 14:49:44 +03:30
timer = Timer(
const Duration(seconds: 10),
() {
loggy.debug("entering idle mode");
_idle = true;
ref.invalidateSelf();
},
);
return info;
2024-02-13 16:59:35 +03:30
}
2024-02-09 12:02:52 +03:30
2024-02-17 14:49:44 +03:30
bool _idle = false;
bool _forceCheck = false;
2024-02-17 13:11:50 +03:30
2024-02-13 16:59:35 +03:30
Future<void> refresh() async {
2024-02-17 14:49:44 +03:30
if (state.isLoading) return;
2024-02-13 16:59:35 +03:30
loggy.debug("refreshing");
2024-02-17 14:49:44 +03:30
state = const AsyncLoading();
2024-02-16 14:33:03 +03:30
await ref.read(hapticServiceProvider.notifier).lightImpact();
2024-02-17 14:49:44 +03:30
_forceCheck = true;
2024-02-13 16:59:35 +03:30
ref.invalidateSelf();
2024-02-09 12:02:52 +03:30
}
}
@riverpod
class ActiveProxyNotifier extends _$ActiveProxyNotifier with AppLogger {
@override
2024-02-13 16:59:35 +03:30
Stream<ProxyItemEntity> build() async* {
2024-02-09 12:02:52 +03:30
ref.disposeDelay(const Duration(seconds: 20));
2024-02-10 13:55:31 +03:30
2024-02-13 16:59:35 +03:30
final serviceRunning = await ref.watch(serviceRunningProvider.future);
if (!serviceRunning) {
throw const ServiceNotRunning();
2024-02-09 12:02:52 +03:30
}
2024-02-13 16:59:35 +03:30
yield* ref
.watch(proxyRepositoryProvider)
.watchActiveProxies()
.map((event) => event.getOrElse((l) => throw l))
.map((event) => event.firstOrNull!.items.first);
2024-02-09 12:02:52 +03:30
}
2024-02-10 13:55:31 +03:30
2024-02-13 16:59:35 +03:30
final _urlTestThrottler = Throttler(const Duration(seconds: 2));
Future<void> urlTest(String groupTag_) async {
var groupTag = groupTag_;
2024-02-13 16:59:35 +03:30
_urlTestThrottler(
2024-02-10 13:55:31 +03:30
() async {
loggy.debug("testing group: [$groupTag]");
if (!["auto", "select"].contains(groupTag)) {
loggy.warning("only proxy group can do url test");
groupTag = "select";
}
2024-02-10 13:55:31 +03:30
if (state case AsyncData()) {
2024-02-16 14:33:03 +03:30
await ref.read(hapticServiceProvider.notifier).lightImpact();
2024-02-10 13:55:31 +03:30
await ref
.read(proxyRepositoryProvider)
.urlTest(groupTag)
.getOrElse((err) {
2024-02-20 18:49:30 +03:30
loggy.warning("error testing group", err);
2024-02-10 13:55:31 +03:30
throw err;
}).run();
}
},
);
}
2024-02-09 12:02:52 +03:30
}