Merge branch 'main' of hiddify-github:hiddify/hiddify-next
This commit is contained in:
26
changelog.md
26
changelog.md
@@ -1,7 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## 0.7.2 (2023-10-04)
|
||||
## 0.8.0 (2023-10-05)
|
||||
|
||||
#### New
|
||||
|
||||
* Add russian lang.
|
||||
|
||||
#### Other
|
||||
|
||||
* Add proxy tag sanitization.
|
||||
|
||||
* Fix bugs.
|
||||
|
||||
* Add ignore app update version.
|
||||
|
||||
* Add new protocols to link parser.
|
||||
|
||||
* Auto update translations on release.
|
||||
|
||||
* Update translation.
|
||||
|
||||
* Remove param in ru translation.
|
||||
|
||||
|
||||
|
||||
## v0.7.2 (2023-10-04)
|
||||
|
||||
#### Other
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
core.version=0.4.1
|
||||
core.version=0.5.0
|
||||
@@ -137,7 +137,7 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade {
|
||||
}).toList();
|
||||
}).handleExceptions(
|
||||
(error, stackTrace) {
|
||||
loggy.warning("error watching outbounds", error, stackTrace);
|
||||
loggy.error("error watching outbounds", error, stackTrace);
|
||||
return CoreServiceFailure.unexpected(error, stackTrace);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ class ProfilesRepositoryImpl
|
||||
Stream<Either<ProfileFailure, Profile?>> watchActiveProfile() {
|
||||
return profilesDao.watchActiveProfile().handleExceptions(
|
||||
(error, stackTrace) {
|
||||
loggy.warning("error watching active profile", error, stackTrace);
|
||||
loggy.error("error watching active profile", error, stackTrace);
|
||||
return ProfileUnexpectedFailure(error, stackTrace);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -21,6 +21,8 @@ class OutboundGroup with _$OutboundGroup {
|
||||
|
||||
@freezed
|
||||
class OutboundGroupItem with _$OutboundGroupItem {
|
||||
const OutboundGroupItem._();
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||
const factory OutboundGroupItem({
|
||||
required String tag,
|
||||
@@ -28,6 +30,9 @@ class OutboundGroupItem with _$OutboundGroupItem {
|
||||
required int urlTestDelay,
|
||||
}) = _OutboundGroupItem;
|
||||
|
||||
String get sanitizedTag =>
|
||||
tag.replaceFirst(RegExp(r"\§[^]*"), "").trimRight();
|
||||
|
||||
factory OutboundGroupItem.fromJson(Map<String, dynamic> json) =>
|
||||
_$OutboundGroupItemFromJson(json);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ enum ProxyType {
|
||||
dns("DNS"),
|
||||
socks("SOCKS"),
|
||||
http("HTTP"),
|
||||
shadowsocks("Shadowsocks"),
|
||||
vmess("VMess"),
|
||||
trojan("Trojan"),
|
||||
naive("Naive"),
|
||||
|
||||
@@ -24,7 +24,8 @@ class AboutPage extends HookConsumerWidget {
|
||||
(_, next) async {
|
||||
if (!context.mounted) return;
|
||||
switch (next) {
|
||||
case AppUpdateStateAvailable(:final versionInfo):
|
||||
case AppUpdateStateAvailable(:final versionInfo) ||
|
||||
AppUpdateStateIgnored(:final versionInfo):
|
||||
return NewVersionDialog(
|
||||
appInfo.presentVersion,
|
||||
versionInfo,
|
||||
@@ -108,6 +109,7 @@ class AboutPage extends HookConsumerWidget {
|
||||
.check();
|
||||
},
|
||||
),
|
||||
if (PlatformUtils.isDesktop)
|
||||
ListTile(
|
||||
title: Text(t.settings.general.openWorkingDir),
|
||||
trailing: const Icon(Icons.arrow_outward_outlined),
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:hiddify/data/data_providers.dart';
|
||||
import 'package:hiddify/domain/app/app.dart';
|
||||
import 'package:hiddify/features/common/new_version_dialog.dart';
|
||||
import 'package:hiddify/services/service_providers.dart';
|
||||
import 'package:hiddify/utils/pref_notifier.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
@@ -20,6 +21,8 @@ class AppUpdateState with _$AppUpdateState {
|
||||
const factory AppUpdateState.error(AppFailure error) = AppUpdateStateError;
|
||||
const factory AppUpdateState.available(RemoteVersionInfo versionInfo) =
|
||||
AppUpdateStateAvailable;
|
||||
const factory AppUpdateState.ignored(RemoteVersionInfo versionInfo) =
|
||||
AppUpdateStateIgnored;
|
||||
const factory AppUpdateState.notAvailable() = AppUpdateStateNotAvailable;
|
||||
}
|
||||
|
||||
@@ -31,6 +34,12 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {
|
||||
return const AppUpdateState.initial();
|
||||
}
|
||||
|
||||
Pref<String?, dynamic> get _ignoreReleasePref => Pref(
|
||||
ref.read(sharedPreferencesProvider),
|
||||
'ignored_release_version',
|
||||
null,
|
||||
);
|
||||
|
||||
Future<AppUpdateState> check() async {
|
||||
loggy.debug("checking for update");
|
||||
state = const AppUpdateState.checking();
|
||||
@@ -54,7 +63,10 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {
|
||||
return state = AppUpdateState.error(err);
|
||||
},
|
||||
(remote) {
|
||||
if (remote.version.compareTo(currentVersion) > 0) {
|
||||
if (remote.version == _ignoreReleasePref.getValue()) {
|
||||
loggy.debug("ignored release [${remote.version}]");
|
||||
return state = AppUpdateStateIgnored(remote);
|
||||
} else if (remote.version.compareTo(currentVersion) > 0) {
|
||||
loggy.debug("new version available: $remote");
|
||||
return state = AppUpdateState.available(remote);
|
||||
}
|
||||
@@ -66,6 +78,12 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {
|
||||
).run();
|
||||
}
|
||||
|
||||
Future<void> ignoreRelease(RemoteVersionInfo versionInfo) async {
|
||||
loggy.debug("ignoring release [${versionInfo.version}]");
|
||||
await _ignoreReleasePref.update(versionInfo.version);
|
||||
state = AppUpdateStateIgnored(versionInfo);
|
||||
}
|
||||
|
||||
Future<void> _schedule() async {
|
||||
loggy.debug("scheduling app update checker");
|
||||
return ref.read(cronServiceProvider).schedule(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:gap/gap.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hiddify/core/core_providers.dart';
|
||||
import 'package:hiddify/domain/app/app.dart';
|
||||
import 'package:hiddify/features/common/app_update_notifier.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
@@ -11,7 +12,6 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
NewVersionDialog(
|
||||
this.currentVersion,
|
||||
this.newVersion, {
|
||||
// super.key,
|
||||
this.canIgnore = true,
|
||||
}) : super(key: _dialogKey);
|
||||
|
||||
@@ -79,9 +79,11 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
actions: [
|
||||
if (canIgnore)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// TODO add prefs for ignoring version
|
||||
context.pop();
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(appUpdateNotifierProvider.notifier)
|
||||
.ignoreRelease(newVersion);
|
||||
if (context.mounted) context.pop();
|
||||
},
|
||||
child: Text(t.appUpdate.ignoreBtnTxt),
|
||||
),
|
||||
|
||||
@@ -73,7 +73,7 @@ class IntroPage extends HookConsumerWidget with PresLogger {
|
||||
try {
|
||||
await Sentry.close();
|
||||
} catch (error, stackTrace) {
|
||||
loggy.warning(
|
||||
loggy.error(
|
||||
"could not disable analytics",
|
||||
error,
|
||||
stackTrace,
|
||||
|
||||
@@ -123,7 +123,7 @@ class ProxiesNotifier extends _$ProxiesNotifier with AppLogger {
|
||||
loggy.debug("testing group: [$groupTag]");
|
||||
if (state case AsyncData()) {
|
||||
await ref.read(coreFacadeProvider).urlTest(groupTag).getOrElse((err) {
|
||||
loggy.warning("error testing group", err);
|
||||
loggy.error("error testing group", err);
|
||||
throw err;
|
||||
}).run();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class ProxyTile extends HookConsumerWidget {
|
||||
return ListTile(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
title: Text(
|
||||
proxy.tag,
|
||||
proxy.sanitizedTag,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
leading: Padding(
|
||||
|
||||
@@ -26,7 +26,7 @@ Future<List<InstalledPackageInfo>> installedPackagesInfo(
|
||||
.watch(platformSettingsProvider)
|
||||
.getInstalledPackages()
|
||||
.getOrElse((err) {
|
||||
_logger.warning("error getting installed packages", err);
|
||||
_logger.error("error getting installed packages", err);
|
||||
throw err;
|
||||
}).run();
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ class FFISingboxService
|
||||
_logger.debug("stopping status command client");
|
||||
final err = _box.stopCommandClient(1).cast<Utf8>().toDartString();
|
||||
if (err.isNotEmpty) {
|
||||
_logger.warning("error stopping status client");
|
||||
_logger.error("error stopping status client");
|
||||
}
|
||||
receiver.close();
|
||||
_statusStream = null;
|
||||
@@ -200,12 +200,12 @@ class FFISingboxService
|
||||
(event) {
|
||||
if (event case String _) {
|
||||
if (event.startsWith('error:')) {
|
||||
loggy.warning("[status client] error received: $event");
|
||||
loggy.error("[status client] error received: $event");
|
||||
throw event.replaceFirst('error:', "");
|
||||
}
|
||||
return event;
|
||||
}
|
||||
loggy.warning("[status client] unexpected type, msg: $event");
|
||||
loggy.error("[status client] unexpected type, msg: $event");
|
||||
throw "invalid type";
|
||||
},
|
||||
);
|
||||
@@ -215,7 +215,7 @@ class FFISingboxService
|
||||
.cast<Utf8>()
|
||||
.toDartString();
|
||||
if (err.isNotEmpty) {
|
||||
loggy.warning("error starting status command: $err");
|
||||
loggy.error("error starting status command: $err");
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ class FFISingboxService
|
||||
_logger.debug("stopping group command client");
|
||||
final err = _box.stopCommandClient(4).cast<Utf8>().toDartString();
|
||||
if (err.isNotEmpty) {
|
||||
_logger.warning("error stopping group client");
|
||||
_logger.error("error stopping group client");
|
||||
}
|
||||
receiver.close();
|
||||
_groupsStream = null;
|
||||
@@ -240,12 +240,12 @@ class FFISingboxService
|
||||
(event) {
|
||||
if (event case String _) {
|
||||
if (event.startsWith('error:')) {
|
||||
loggy.warning("[group client] error received: $event");
|
||||
loggy.error("[group client] error received: $event");
|
||||
throw event.replaceFirst('error:', "");
|
||||
}
|
||||
return event;
|
||||
}
|
||||
loggy.warning("[group client] unexpected type, msg: $event");
|
||||
loggy.error("[group client] unexpected type, msg: $event");
|
||||
throw "invalid type";
|
||||
},
|
||||
);
|
||||
@@ -255,7 +255,7 @@ class FFISingboxService
|
||||
.cast<Utf8>()
|
||||
.toDartString();
|
||||
if (err.isNotEmpty) {
|
||||
loggy.warning("error starting group command: $err");
|
||||
loggy.error("error starting group command: $err");
|
||||
throw err;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class MobileSingboxService
|
||||
if (event case String _) {
|
||||
return event;
|
||||
}
|
||||
loggy.warning("[group client] unexpected type, msg: $event");
|
||||
loggy.error("[group client] unexpected type, msg: $event");
|
||||
throw "invalid type";
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:hiddify/domain/clash/clash.dart';
|
||||
import 'package:hiddify/domain/singbox/singbox.dart';
|
||||
import 'package:hiddify/utils/validators.dart';
|
||||
|
||||
typedef ProfileLink = ({String url, String name});
|
||||
@@ -9,7 +9,15 @@ typedef ProfileLink = ({String url, String name});
|
||||
abstract class LinkParser {
|
||||
// protocols schemas
|
||||
static const protocols = {'clash', 'clashmeta', 'sing-box', 'hiddify'};
|
||||
static const rawProtocols = {'vmess', 'vless', 'trojan', 'ss', 'tuic'};
|
||||
static const rawProtocols = {
|
||||
'ss',
|
||||
'vmess',
|
||||
'vless',
|
||||
'trojan',
|
||||
'tuic',
|
||||
'hysteria2',
|
||||
'ssh',
|
||||
};
|
||||
|
||||
static ProfileLink? parse(String link) {
|
||||
return simple(link) ?? deep(link);
|
||||
@@ -32,10 +40,13 @@ abstract class LinkParser {
|
||||
final fragment =
|
||||
uri.hasFragment ? Uri.decodeComponent(uri.fragment) : null;
|
||||
final name = switch (uri.scheme) {
|
||||
'ss' => fragment ?? ProxyType.shadowSocks.label,
|
||||
'vless' => fragment ?? ProxyType.vless.label,
|
||||
'tuic' => fragment ?? ProxyType.tuic.label,
|
||||
'ss' => fragment ?? ProxyType.shadowsocks.label,
|
||||
'vmess' => ProxyType.vmess.label,
|
||||
'vless' => fragment ?? ProxyType.vless.label,
|
||||
'trojan' => fragment ?? ProxyType.trojan.label,
|
||||
'tuic' => fragment ?? ProxyType.tuic.label,
|
||||
'hy2' || 'hysteria2' => fragment ?? ProxyType.hysteria.label,
|
||||
'ssh' => fragment ?? ProxyType.ssh.label,
|
||||
_ => null,
|
||||
};
|
||||
if (name != null) {
|
||||
|
||||
@@ -7,7 +7,7 @@ class SentryLoggyIntegration extends LoggyPrinter
|
||||
implements Integration<SentryOptions> {
|
||||
SentryLoggyIntegration({
|
||||
LogLevel minBreadcrumbLevel = LogLevel.info,
|
||||
LogLevel minEventLevel = LogLevel.warning,
|
||||
LogLevel minEventLevel = LogLevel.error,
|
||||
}) : _minBreadcrumbLevel = minBreadcrumbLevel,
|
||||
_minEventLevel = minEventLevel;
|
||||
|
||||
|
||||
2
libcore
2
libcore
Submodule libcore updated: 75e342b6ba...dced5a30d0
@@ -1,7 +1,7 @@
|
||||
name: hiddify
|
||||
description: A Proxy Frontend.
|
||||
publish_to: "none"
|
||||
version: 0.7.2+702
|
||||
version: 0.8.0+800
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.5 <4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user