Merge branch 'main' of hiddify-github:hiddify/hiddify-next

This commit is contained in:
Hiddify
2023-10-06 09:02:37 +02:00
19 changed files with 103 additions and 40 deletions

View File

@@ -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

View File

@@ -1 +1 @@
core.version=0.4.1
core.version=0.5.0

View File

@@ -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);
},
);

View File

@@ -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);
},
);

View File

@@ -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);
}

View File

@@ -4,6 +4,7 @@ enum ProxyType {
dns("DNS"),
socks("SOCKS"),
http("HTTP"),
shadowsocks("Shadowsocks"),
vmess("VMess"),
trojan("Trojan"),
naive("Naive"),

View File

@@ -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),

View File

@@ -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(

View File

@@ -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),
),

View File

@@ -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,

View File

@@ -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();
}

View File

@@ -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(

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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";
},
);

View File

@@ -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) {

View File

@@ -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;

Submodule libcore updated: 75e342b6ba...dced5a30d0

View File

@@ -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"