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/services.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
|
||||
abstract class Constants {
|
||||
static const appName = "Hiddify";
|
||||
@ -56,21 +57,49 @@ abstract class IntroConst {
|
||||
static const termsAndConditionsKey = 'terms-and-conditions';
|
||||
static const githubKey = 'github';
|
||||
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 {
|
||||
static const warpAccountId = 'warp-account-id';
|
||||
static const warpAccessToken = "warp-access-token";
|
||||
static const warpConsentGiven = "warp-consent-given";
|
||||
static const warpTermsOfServiceKey = 'warp-terms-of-service';
|
||||
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 {
|
||||
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 verticalArrows = {LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown};
|
||||
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({
|
||||
required String licenseKey,
|
||||
required String previousAccountId,
|
||||
required String previousAccessToken,
|
||||
}) {
|
||||
return TaskEither(() async {
|
||||
loggy.debug("generating warp config");
|
||||
final warpConfig = await core.fgClient.generateWarpConfig(
|
||||
GenerateWarpConfigRequest(
|
||||
licenseKey: licenseKey,
|
||||
accountId: previousAccountId,
|
||||
accessToken: previousAccessToken,
|
||||
),
|
||||
);
|
||||
// if (warpConfig.code != ResponseCode.OK) return left("${warpConfig.code} ${warpConfig.message}");
|
||||
final WarpResponse warp = (
|
||||
log: warpConfig.log,
|
||||
accountId: warpConfig.account.accountId,
|
||||
accessToken: warpConfig.account.accessToken,
|
||||
wireguardConfig: jsonEncode(warpConfig.config.toProto3Json()),
|
||||
);
|
||||
return right(warp);
|
||||
});
|
||||
}
|
||||
// TaskEither<String, WarpResponse> generateWarpConfig({
|
||||
// required String licenseKey,
|
||||
// required String previousAccountId,
|
||||
// required String previousAccessToken,
|
||||
// }) {
|
||||
// return TaskEither(() async {
|
||||
// loggy.debug("generating warp config");
|
||||
// final warpConfig = await core.fgClient.generateWarpConfig(
|
||||
// GenerateWarpConfigRequest(
|
||||
// licenseKey: licenseKey,
|
||||
// accountId: previousAccountId,
|
||||
// accessToken: previousAccessToken,
|
||||
// ),
|
||||
// );
|
||||
// // if (warpConfig.code != ResponseCode.OK) return left("${warpConfig.code} ${warpConfig.message}");
|
||||
// final WarpResponse warp = (
|
||||
// log: warpConfig.log,
|
||||
// accountId: warpConfig.account.accountId,
|
||||
// accessToken: warpConfig.account.accessToken,
|
||||
// wireguardConfig: jsonEncode(warpConfig.config.toProto3Json()),
|
||||
// );
|
||||
// return right(warp);
|
||||
// });
|
||||
// }
|
||||
|
||||
Stream<CoreStatus> watchStatus() async* {
|
||||
await startListeningStatus("bg", core.bgClient);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/core/model/constants.dart';
|
||||
import 'package:hiddify/utils/platform_utils.dart';
|
||||
|
||||
@JsonEnum(valueField: 'key')
|
||||
@ -119,24 +121,147 @@ enum TunImplementation {
|
||||
};
|
||||
}
|
||||
|
||||
enum MuxProtocol { h2mux, smux, yamux }
|
||||
|
||||
@JsonEnum(valueField: 'key')
|
||||
enum WarpDetourMode {
|
||||
proxyOverWarp("proxy_over_warp"),
|
||||
warpOverProxy("warp_over_proxy");
|
||||
enum ChainStatus {
|
||||
off('off'),
|
||||
extraSecurity('extra_security'),
|
||||
unblocker('unblocker');
|
||||
|
||||
const WarpDetourMode(this.key);
|
||||
const ChainStatus(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,
|
||||
bool isOff() => this == off;
|
||||
bool isUnblocker() => this == unblocker;
|
||||
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) {
|
||||
proxyOverWarp => t.pages.settings.warp.detourModes.proxyOverWarpExplain,
|
||||
warpOverProxy => t.pages.settings.warp.detourModes.warpOverProxyExplain,
|
||||
IconData icon() => switch (this) {
|
||||
psiphon => Icons.local_parking,
|
||||
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 SingboxMuxOption mux,
|
||||
required SingboxTlsTricks tlsTricks,
|
||||
required SingboxWarpOption warp,
|
||||
required SingboxWarpOption warp2,
|
||||
required ChainStatus chainStatus,
|
||||
required SingboxExtraSecurityOption extraSecurity,
|
||||
required SingboxUnblockerOption unblocker,
|
||||
}) = _SingboxConfigOption;
|
||||
|
||||
String format() {
|
||||
@ -63,24 +64,90 @@ class SingboxConfigOption with _$SingboxConfigOption {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class SingboxWarpOption with _$SingboxWarpOption {
|
||||
class SingboxExtraSecurityOption with _$SingboxExtraSecurityOption {
|
||||
@JsonSerializable(fieldRename: FieldRename.kebab)
|
||||
const factory SingboxWarpOption({
|
||||
required bool enable,
|
||||
required WarpDetourMode mode,
|
||||
required String wireguardConfig,
|
||||
const factory SingboxExtraSecurityOption({
|
||||
required ChainMode mode,
|
||||
required SingboxExtraSecurityWarpOption warp,
|
||||
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 accountId,
|
||||
required String accessToken,
|
||||
required String cleanIp,
|
||||
required int cleanPort,
|
||||
@OptionalRangeJsonConverter() required OptionalRange noise,
|
||||
@OptionalRangeJsonConverter() required OptionalRange noiseSize,
|
||||
@OptionalRangeJsonConverter() required OptionalRange noiseDelay,
|
||||
@OptionalRangeJsonConverter() required String noiseMode,
|
||||
}) = _SingboxWarpOption;
|
||||
required String noiseMode,
|
||||
}) = _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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user