mirror of
https://github.com/hiddify/hiddify-next.git
synced 2026-06-05 21:05:07 +08:00
feat(singbox): add foundational models and constants for chain functionality
This commit is contained in:
parent
0a6d4ad9f0
commit
3383d51318
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:hiddify/utils/utils.dart';
|
||||||
|
|
||||||
abstract class Constants {
|
abstract class Constants {
|
||||||
static const appName = "Hiddify";
|
static const appName = "Hiddify";
|
||||||
@ -56,21 +57,49 @@ abstract class IntroConst {
|
|||||||
static const termsAndConditionsKey = 'terms-and-conditions';
|
static const termsAndConditionsKey = 'terms-and-conditions';
|
||||||
static const githubKey = 'github';
|
static const githubKey = 'github';
|
||||||
static const licenseKey = 'license';
|
static const licenseKey = 'license';
|
||||||
static const url = <String, String>{IntroConst.termsAndConditionsKey: Constants.termsAndConditionsUrl, IntroConst.githubKey: Constants.githubUrl, IntroConst.licenseKey: Constants.licenseUrl};
|
static const url = <String, String>{
|
||||||
|
IntroConst.termsAndConditionsKey: Constants.termsAndConditionsUrl,
|
||||||
|
IntroConst.githubKey: Constants.githubUrl,
|
||||||
|
IntroConst.licenseKey: Constants.licenseUrl,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class WarpConst {
|
abstract class WarpConst {
|
||||||
static const warpAccountId = 'warp-account-id';
|
|
||||||
static const warpAccessToken = "warp-access-token";
|
|
||||||
static const warpConsentGiven = "warp-consent-given";
|
static const warpConsentGiven = "warp-consent-given";
|
||||||
static const warpTermsOfServiceKey = 'warp-terms-of-service';
|
static const warpTermsOfServiceKey = 'warp-terms-of-service';
|
||||||
static const warpPrivacyPolicyKey = 'warp-privacy-policy';
|
static const warpPrivacyPolicyKey = 'warp-privacy-policy';
|
||||||
static const url = <String, String>{WarpConst.warpTermsOfServiceKey: Constants.cfWarpTermsOfService, WarpConst.warpPrivacyPolicyKey: Constants.cfWarpPrivacyPolicy};
|
static const url = <String, String>{
|
||||||
|
WarpConst.warpTermsOfServiceKey: Constants.cfWarpTermsOfService,
|
||||||
|
WarpConst.warpPrivacyPolicyKey: Constants.cfWarpPrivacyPolicy,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KeyboardConst {
|
abstract class KeyboardConst {
|
||||||
static final allArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown, LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight};
|
static final allArrows = {
|
||||||
|
LogicalKeyboardKey.arrowUp,
|
||||||
|
LogicalKeyboardKey.arrowDown,
|
||||||
|
LogicalKeyboardKey.arrowLeft,
|
||||||
|
LogicalKeyboardKey.arrowRight,
|
||||||
|
};
|
||||||
static final horizontalArrows = {LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight};
|
static final horizontalArrows = {LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight};
|
||||||
static final verticalArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown};
|
static final verticalArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown};
|
||||||
static final select = {LogicalKeyboardKey.select, LogicalKeyboardKey.enter, LogicalKeyboardKey.tab};
|
static final select = {LogicalKeyboardKey.select, LogicalKeyboardKey.enter, LogicalKeyboardKey.tab};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ChainConst {
|
||||||
|
static IconData iconByPlatform() {
|
||||||
|
if (PlatformUtils.isAndroid) return Icons.phone_android;
|
||||||
|
if (PlatformUtils.isIOS) return Icons.phone_iphone;
|
||||||
|
if (PlatformUtils.isWeb) return Icons.web;
|
||||||
|
// Desktops
|
||||||
|
return Icons.laptop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color finalIpColor(ThemeData theme) =>
|
||||||
|
theme.brightness == Brightness.dark ? const Color(0xFF99AD7A) : const Color.fromARGB(255, 87, 136, 13);
|
||||||
|
static const warpColor = Color(0xFFF6821F);
|
||||||
|
static const psiphonColor = Color(0xFFD52027);
|
||||||
|
static const profileColor = Color(0xFF3282B8);
|
||||||
|
|
||||||
|
static const finalIpDuration = Duration(milliseconds: 500);
|
||||||
|
}
|
||||||
|
|||||||
@ -407,30 +407,30 @@ class HiddifyCoreService with InfraLogger {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskEither<String, WarpResponse> generateWarpConfig({
|
// TaskEither<String, WarpResponse> generateWarpConfig({
|
||||||
required String licenseKey,
|
// required String licenseKey,
|
||||||
required String previousAccountId,
|
// required String previousAccountId,
|
||||||
required String previousAccessToken,
|
// required String previousAccessToken,
|
||||||
}) {
|
// }) {
|
||||||
return TaskEither(() async {
|
// return TaskEither(() async {
|
||||||
loggy.debug("generating warp config");
|
// loggy.debug("generating warp config");
|
||||||
final warpConfig = await core.fgClient.generateWarpConfig(
|
// final warpConfig = await core.fgClient.generateWarpConfig(
|
||||||
GenerateWarpConfigRequest(
|
// GenerateWarpConfigRequest(
|
||||||
licenseKey: licenseKey,
|
// licenseKey: licenseKey,
|
||||||
accountId: previousAccountId,
|
// accountId: previousAccountId,
|
||||||
accessToken: previousAccessToken,
|
// accessToken: previousAccessToken,
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
// if (warpConfig.code != ResponseCode.OK) return left("${warpConfig.code} ${warpConfig.message}");
|
// // if (warpConfig.code != ResponseCode.OK) return left("${warpConfig.code} ${warpConfig.message}");
|
||||||
final WarpResponse warp = (
|
// final WarpResponse warp = (
|
||||||
log: warpConfig.log,
|
// log: warpConfig.log,
|
||||||
accountId: warpConfig.account.accountId,
|
// accountId: warpConfig.account.accountId,
|
||||||
accessToken: warpConfig.account.accessToken,
|
// accessToken: warpConfig.account.accessToken,
|
||||||
wireguardConfig: jsonEncode(warpConfig.config.toProto3Json()),
|
// wireguardConfig: jsonEncode(warpConfig.config.toProto3Json()),
|
||||||
);
|
// );
|
||||||
return right(warp);
|
// return right(warp);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
Stream<CoreStatus> watchStatus() async* {
|
Stream<CoreStatus> watchStatus() async* {
|
||||||
await startListeningStatus("bg", core.bgClient);
|
await startListeningStatus("bg", core.bgClient);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:hiddify/core/localization/translations.dart';
|
import 'package:hiddify/core/localization/translations.dart';
|
||||||
|
import 'package:hiddify/core/model/constants.dart';
|
||||||
import 'package:hiddify/utils/platform_utils.dart';
|
import 'package:hiddify/utils/platform_utils.dart';
|
||||||
|
|
||||||
@JsonEnum(valueField: 'key')
|
@JsonEnum(valueField: 'key')
|
||||||
@ -119,24 +121,147 @@ enum TunImplementation {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MuxProtocol { h2mux, smux, yamux }
|
|
||||||
|
|
||||||
@JsonEnum(valueField: 'key')
|
@JsonEnum(valueField: 'key')
|
||||||
enum WarpDetourMode {
|
enum ChainStatus {
|
||||||
proxyOverWarp("proxy_over_warp"),
|
off('off'),
|
||||||
warpOverProxy("warp_over_proxy");
|
extraSecurity('extra_security'),
|
||||||
|
unblocker('unblocker');
|
||||||
|
|
||||||
const WarpDetourMode(this.key);
|
const ChainStatus(this.key);
|
||||||
|
|
||||||
final String key;
|
final String key;
|
||||||
|
|
||||||
String present(TranslationsEn t) => switch (this) {
|
bool isOff() => this == off;
|
||||||
proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarp,
|
bool isUnblocker() => this == unblocker;
|
||||||
warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxy,
|
bool isExtraSecurity() => this == extraSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonEnum(valueField: 'key')
|
||||||
|
enum ChainMode {
|
||||||
|
psiphon('psiphon'),
|
||||||
|
warp('warp'),
|
||||||
|
profile('profile');
|
||||||
|
|
||||||
|
const ChainMode(this.key);
|
||||||
|
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
String present(Translations t) => switch (this) {
|
||||||
|
psiphon => t.common.psiphon,
|
||||||
|
warp => t.common.warp,
|
||||||
|
profile => t.common.profile,
|
||||||
};
|
};
|
||||||
|
|
||||||
String presentExplain(TranslationsEn t) => switch (this) {
|
IconData icon() => switch (this) {
|
||||||
proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarpExplain,
|
psiphon => Icons.local_parking,
|
||||||
warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxyExplain,
|
warp => Icons.cloud,
|
||||||
|
profile => Icons.link,
|
||||||
|
};
|
||||||
|
|
||||||
|
Color color() => switch (this) {
|
||||||
|
psiphon => ChainConst.psiphonColor,
|
||||||
|
warp => ChainConst.warpColor,
|
||||||
|
profile => ChainConst.profileColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isPsiphon() => this == psiphon;
|
||||||
|
bool isWarp() => this == warp;
|
||||||
|
bool isProfile() => this == profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonEnum(valueField: 'key')
|
||||||
|
enum PsiphonRegion {
|
||||||
|
auto('AUTO'),
|
||||||
|
austria('AT'),
|
||||||
|
australia('AU'),
|
||||||
|
belgium('BE'),
|
||||||
|
bulgaria('BG'),
|
||||||
|
canada('CA'),
|
||||||
|
switzerland('CH'),
|
||||||
|
czechRepublic('CZ'),
|
||||||
|
germany('DE'),
|
||||||
|
denmark('DK'),
|
||||||
|
estonia('EE'),
|
||||||
|
spain('ES'),
|
||||||
|
finland('FI'),
|
||||||
|
france('FR'),
|
||||||
|
unitedKingdom('GB'),
|
||||||
|
croatia('HR'),
|
||||||
|
hungary('HU'),
|
||||||
|
ireland('IE'),
|
||||||
|
india('IN'),
|
||||||
|
italy('IT'),
|
||||||
|
japan('JP'),
|
||||||
|
latvia('LV'),
|
||||||
|
netherlands('NL'),
|
||||||
|
norway('NO'),
|
||||||
|
poland('PL'),
|
||||||
|
portugal('PT'),
|
||||||
|
romania('RO'),
|
||||||
|
serbia('RS'),
|
||||||
|
sweden('SE'),
|
||||||
|
singapore('SG'),
|
||||||
|
slovakia('SK'),
|
||||||
|
unitedStates('US');
|
||||||
|
|
||||||
|
const PsiphonRegion(this.key);
|
||||||
|
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
String present(Translations t) => switch (this) {
|
||||||
|
auto => t.pages.settings.chain.psiphon.regions.auto,
|
||||||
|
austria => t.pages.settings.chain.psiphon.regions.at,
|
||||||
|
australia => t.pages.settings.chain.psiphon.regions.au,
|
||||||
|
belgium => t.pages.settings.chain.psiphon.regions.be,
|
||||||
|
bulgaria => t.pages.settings.chain.psiphon.regions.bg,
|
||||||
|
canada => t.pages.settings.chain.psiphon.regions.ca,
|
||||||
|
switzerland => t.pages.settings.chain.psiphon.regions.ch,
|
||||||
|
czechRepublic => t.pages.settings.chain.psiphon.regions.cz,
|
||||||
|
germany => t.pages.settings.chain.psiphon.regions.de,
|
||||||
|
denmark => t.pages.settings.chain.psiphon.regions.dk,
|
||||||
|
estonia => t.pages.settings.chain.psiphon.regions.ee,
|
||||||
|
spain => t.pages.settings.chain.psiphon.regions.es,
|
||||||
|
finland => t.pages.settings.chain.psiphon.regions.fi,
|
||||||
|
france => t.pages.settings.chain.psiphon.regions.fr,
|
||||||
|
unitedKingdom => t.pages.settings.chain.psiphon.regions.gb,
|
||||||
|
croatia => t.pages.settings.chain.psiphon.regions.hr,
|
||||||
|
hungary => t.pages.settings.chain.psiphon.regions.hu,
|
||||||
|
ireland => t.pages.settings.chain.psiphon.regions.ie,
|
||||||
|
india => t.pages.settings.chain.psiphon.regions.kIn,
|
||||||
|
italy => t.pages.settings.chain.psiphon.regions.it,
|
||||||
|
japan => t.pages.settings.chain.psiphon.regions.jp,
|
||||||
|
latvia => t.pages.settings.chain.psiphon.regions.lv,
|
||||||
|
netherlands => t.pages.settings.chain.psiphon.regions.nl,
|
||||||
|
norway => t.pages.settings.chain.psiphon.regions.no,
|
||||||
|
poland => t.pages.settings.chain.psiphon.regions.pl,
|
||||||
|
portugal => t.pages.settings.chain.psiphon.regions.pt,
|
||||||
|
romania => t.pages.settings.chain.psiphon.regions.ro,
|
||||||
|
serbia => t.pages.settings.chain.psiphon.regions.rs,
|
||||||
|
sweden => t.pages.settings.chain.psiphon.regions.se,
|
||||||
|
singapore => t.pages.settings.chain.psiphon.regions.sg,
|
||||||
|
slovakia => t.pages.settings.chain.psiphon.regions.sk,
|
||||||
|
unitedStates => t.pages.settings.chain.psiphon.regions.us,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MuxProtocol { h2mux, smux, yamux }
|
||||||
|
|
||||||
|
// @JsonEnum(valueField: 'key')
|
||||||
|
// enum WarpDetourMode {
|
||||||
|
// proxyOverWarp("proxy_over_warp"),
|
||||||
|
// warpOverProxy("warp_over_proxy");
|
||||||
|
|
||||||
|
// const WarpDetourMode(this.key);
|
||||||
|
|
||||||
|
// final String key;
|
||||||
|
|
||||||
|
// String present(TranslationsEn t) => switch (this) {
|
||||||
|
// proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarp,
|
||||||
|
// warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxy,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// String presentExplain(TranslationsEn t) => switch (this) {
|
||||||
|
// proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarpExplain,
|
||||||
|
// warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxyExplain,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|||||||
@ -50,8 +50,9 @@ class SingboxConfigOption with _$SingboxConfigOption {
|
|||||||
required List<SingboxRule> rules,
|
required List<SingboxRule> rules,
|
||||||
// required SingboxMuxOption mux,
|
// required SingboxMuxOption mux,
|
||||||
required SingboxTlsTricks tlsTricks,
|
required SingboxTlsTricks tlsTricks,
|
||||||
required SingboxWarpOption warp,
|
required ChainStatus chainStatus,
|
||||||
required SingboxWarpOption warp2,
|
required SingboxExtraSecurityOption extraSecurity,
|
||||||
|
required SingboxUnblockerOption unblocker,
|
||||||
}) = _SingboxConfigOption;
|
}) = _SingboxConfigOption;
|
||||||
|
|
||||||
String format() {
|
String format() {
|
||||||
@ -63,24 +64,90 @@ class SingboxConfigOption with _$SingboxConfigOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class SingboxWarpOption with _$SingboxWarpOption {
|
class SingboxExtraSecurityOption with _$SingboxExtraSecurityOption {
|
||||||
@JsonSerializable(fieldRename: FieldRename.kebab)
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
const factory SingboxWarpOption({
|
const factory SingboxExtraSecurityOption({
|
||||||
required bool enable,
|
required ChainMode mode,
|
||||||
required WarpDetourMode mode,
|
required SingboxExtraSecurityWarpOption warp,
|
||||||
required String wireguardConfig,
|
required SingboxExtraSecurityPsiphonOption psiphon,
|
||||||
|
required SingboxExtraSecurityProfileOption profile,
|
||||||
|
}) = _SingboxExtraSecurityOption;
|
||||||
|
|
||||||
|
factory SingboxExtraSecurityOption.fromJson(Map<String, dynamic> json) => _$SingboxExtraSecurityOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxUnblockerOption with _$SingboxUnblockerOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxUnblockerOption({
|
||||||
|
required ChainMode mode,
|
||||||
|
required SingboxUnblockerWarpOption warp,
|
||||||
|
required SingboxUnblockerPsiphonOption psiphon,
|
||||||
|
required SingboxUnblockerProfileOption profile,
|
||||||
|
}) = _SingboxUnblockerOption;
|
||||||
|
|
||||||
|
factory SingboxUnblockerOption.fromJson(Map<String, dynamic> json) => _$SingboxUnblockerOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxExtraSecurityWarpOption with _$SingboxExtraSecurityWarpOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxExtraSecurityWarpOption({required String licenseKey}) = _SingboxExtraSecurityWarpOption;
|
||||||
|
|
||||||
|
factory SingboxExtraSecurityWarpOption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SingboxExtraSecurityWarpOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxUnblockerWarpOption with _$SingboxUnblockerWarpOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxUnblockerWarpOption({
|
||||||
required String licenseKey,
|
required String licenseKey,
|
||||||
required String accountId,
|
|
||||||
required String accessToken,
|
|
||||||
required String cleanIp,
|
required String cleanIp,
|
||||||
required int cleanPort,
|
required int cleanPort,
|
||||||
@OptionalRangeJsonConverter() required OptionalRange noise,
|
@OptionalRangeJsonConverter() required OptionalRange noise,
|
||||||
@OptionalRangeJsonConverter() required OptionalRange noiseSize,
|
@OptionalRangeJsonConverter() required OptionalRange noiseSize,
|
||||||
@OptionalRangeJsonConverter() required OptionalRange noiseDelay,
|
@OptionalRangeJsonConverter() required OptionalRange noiseDelay,
|
||||||
@OptionalRangeJsonConverter() required String noiseMode,
|
required String noiseMode,
|
||||||
}) = _SingboxWarpOption;
|
}) = _SingboxUnblockerWarpOption;
|
||||||
|
|
||||||
factory SingboxWarpOption.fromJson(Map<String, dynamic> json) => _$SingboxWarpOptionFromJson(json);
|
factory SingboxUnblockerWarpOption.fromJson(Map<String, dynamic> json) => _$SingboxUnblockerWarpOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxExtraSecurityPsiphonOption with _$SingboxExtraSecurityPsiphonOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxExtraSecurityPsiphonOption({required PsiphonRegion region}) = _SingboxExtraSecurityPsiphonOption;
|
||||||
|
|
||||||
|
factory SingboxExtraSecurityPsiphonOption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SingboxExtraSecurityPsiphonOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxUnblockerPsiphonOption with _$SingboxUnblockerPsiphonOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxUnblockerPsiphonOption({required PsiphonRegion region}) = _SingboxUnblockerPsiphonOption;
|
||||||
|
|
||||||
|
factory SingboxUnblockerPsiphonOption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SingboxUnblockerPsiphonOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxExtraSecurityProfileOption with _$SingboxExtraSecurityProfileOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxExtraSecurityProfileOption({required String? id}) = _SingboxExtraSecurityProfileOption;
|
||||||
|
|
||||||
|
factory SingboxExtraSecurityProfileOption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SingboxExtraSecurityProfileOptionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class SingboxUnblockerProfileOption with _$SingboxUnblockerProfileOption {
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||||
|
const factory SingboxUnblockerProfileOption({required String? id}) = _SingboxUnblockerProfileOption;
|
||||||
|
|
||||||
|
factory SingboxUnblockerProfileOption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SingboxUnblockerProfileOptionFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @freezed
|
// @freezed
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user