Merge branch 'main' into main

This commit is contained in:
junlin03
2024-02-04 20:59:08 +08:00
committed by GitHub
25 changed files with 612 additions and 238 deletions

View File

@@ -39,11 +39,11 @@ jobs:
targets: exe targets: exe
filename: hiddify-windows-x64 filename: hiddify-windows-x64
- platform: linux-appimage # - platform: linux-appimage
os: ubuntu-20.04 # os: ubuntu-20.04
aarch: amd64 # aarch: amd64
targets: AppImage # targets: AppImage
filename: hiddify-linux-x64 # filename: hiddify-linux-x64
- platform: linux-deb - platform: linux-deb
os: ubuntu-20.04 os: ubuntu-20.04

View File

@@ -1,14 +1,25 @@
include dependencies.properties include dependencies.properties
ifeq ($(OS),Windows_NT)
MKDIR := -mkdir
RM := rmdir /s /q
SEP:=\\
PLATFORM_REQ:= @set /p platform="Run 'make prepare platform=ios' or enter platform name:";
else
MKDIR := mkdir -p
RM := rm -rf
SEP :=/
PLATFORM_REQ:= @read -p "Run make prepare platform=ios or enter platform name: " platform;
endif
BINDIR=./libcore/bin BINDIR=libcore$(SEP)bin
ANDROID_OUT=./android/app/libs ANDROID_OUT=android$(SEP)app$(SEP)libs
IOS_OUT=./ios/Frameworks IOS_OUT=ios$(SEP)Frameworks
DESKTOP_OUT=./libcore/bin DESKTOP_OUT=libcore$(SEP)bin
GEO_ASSETS_DIR=./assets/core GEO_ASSETS_DIR=assets$(SEP)core
CORE_PRODUCT_NAME=hiddify-core CORE_PRODUCT_NAME=hiddify-core
CORE_NAME=$(CORE_PRODUCT_NAME) CORE_NAME=$(CORE_PRODUCT_NAME)
SRV_NAME=hiddify-service SRV_NAME=HiddifyService
ifeq ($(CHANNEL),prod) ifeq ($(CHANNEL),prod)
CORE_URL=https://github.com/hiddify/hiddify-next-core/releases/download/v$(core.version) CORE_URL=https://github.com/hiddify/hiddify-next-core/releases/download/v$(core.version)
else else
@@ -24,6 +35,10 @@ endif
BUILD_ARGS=--dart-define sentry_dsn=$(SENTRY_DSN) BUILD_ARGS=--dart-define sentry_dsn=$(SENTRY_DSN)
DISTRIBUTOR_ARGS=--skip-clean --build-target $(TARGET) --build-dart-define sentry_dsn=$(SENTRY_DSN) DISTRIBUTOR_ARGS=--skip-clean --build-target $(TARGET) --build-dart-define sentry_dsn=$(SENTRY_DSN)
get: get:
flutter pub get flutter pub get
@@ -33,19 +48,23 @@ gen:
translate: translate:
dart run slang dart run slang
prepare: get-geo-assets get gen translate
@echo "Available platforms:"
@echo "android" prepare: #get-geo-assets get gen translate
@echo "windows" @echo use the following commands to prepare the library for each platform:
@echo "linux" @echo make android-prepare
@echo "macos" @echo make windows-prepare
@echo "ios" @echo make linux-prepare
if [ -z "$$platform" ]; then \ @echo make macos-prepare
read -p "run make prepare platform=ios or Enter platform name: " choice; \ @echo make ios-prepare
else \
choice=$$platform; \ windows-prepare: get-geo-assets get gen translate windows-libs
fi; \ ios-prepare: get-geo-assets get gen translate ios-libs
make $$choice-libs macos-prepare: get-geo-assets get gen translate macos-libs
linux-prepare: get-geo-assets get gen translate linux-libs
android-prepare: get-geo-assets get gen translate android-libs
sync_translate: sync_translate:
cd .github && bash sync_translate.sh cd .github && bash sync_translate.sh
@@ -81,18 +100,18 @@ ios-release: #not tested
flutter_distributor package --platform ios --targets ipa --build-export-options-plist ios/exportOptions.plist $(DISTRIBUTOR_ARGS) flutter_distributor package --platform ios --targets ipa --build-export-options-plist ios/exportOptions.plist $(DISTRIBUTOR_ARGS)
android-libs: android-libs:
mkdir -p $(ANDROID_OUT) @$(MKDIR) $(ANDROID_OUT) || echo Folder already exists. Skipping...
curl -L $(CORE_URL)/$(CORE_NAME)-android.tar.gz | tar xz -C $(ANDROID_OUT)/ curl -L $(CORE_URL)/$(CORE_NAME)-android.tar.gz | tar xz -C $(ANDROID_OUT)/
android-apk-libs: android-libs android-apk-libs: android-libs
android-aab-libs: android-libs android-aab-libs: android-libs
windows-libs: windows-libs:
mkdir -p $(DESKTOP_OUT) @$(MKDIR) $(DESKTOP_OUT) || echo Folder already exists. Skipping...
curl -L $(CORE_URL)/$(CORE_NAME)-windows-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/ curl -L $(CORE_URL)/$(CORE_NAME)-windows-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/
linux-libs: linux-libs:
mkdir -p $(DESKTOP_OUT) @$(MKDIR) $(DESKTOP_OUT) || echo Folder already exists. Skipping...
curl -L $(CORE_URL)/$(CORE_NAME)-linux-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/ curl -L $(CORE_URL)/$(CORE_NAME)-linux-amd64.tar.gz | tar xz -C $(DESKTOP_OUT)/
@@ -101,12 +120,12 @@ linux-rpm-libs:linux-libs
linux-appimage-libs:linux-libs linux-appimage-libs:linux-libs
macos-libs: macos-libs:
mkdir -p $(DESKTOP_OUT)/ &&\ @$(MKDIR) $(DESKTOP_OUT) || echo Folder already exists. Skipping...
curl -L $(CORE_URL)/$(CORE_NAME)-macos-universal.tar.gz | tar xz -C $(DESKTOP_OUT)/ curl -L $(CORE_URL)/$(CORE_NAME)-macos-universal.tar.gz | tar xz -C $(DESKTOP_OUT)
ios-libs: #not tested ios-libs: #not tested
mkdir -p $(DESKTOP_OUT)/ && \ @$(MKDIR) $(IOS_OUT) || echo Folder already exists. Skipping...
rm -rf $(IOS_OUT)/Libcore.xcframework && \ @$(RM) $(IOS_OUT)/Libcore.xcframework
curl -L $(CORE_URL)/$(CORE_NAME)-ios.tar.gz | tar xz -C "$(IOS_OUT)" curl -L $(CORE_URL)/$(CORE_NAME)-ios.tar.gz | tar xz -C "$(IOS_OUT)"
get-geo-assets: get-geo-assets:
@@ -136,7 +155,7 @@ build-macos-libs:
mv $(BINDIR)/$(SRV_NAME) $(DESKTOP_OUT)/ mv $(BINDIR)/$(SRV_NAME) $(DESKTOP_OUT)/
build-ios-libs: build-ios-libs:
rm -rf $(IOS_OUT)/Libcore.xcframework && \ @$(RM) $(IOS_OUT)/Libcore.xcframework && \
make -C libcore -f Makefile ios && \ make -C libcore -f Makefile ios && \
mv $(BINDIR)/$(CORE_NAME)-ios.xcframework $(IOS_OUT)/Libcore.xcframework mv $(BINDIR)/$(CORE_NAME)-ios.xcframework $(IOS_OUT)/Libcore.xcframework

View File

@@ -11,7 +11,10 @@
}, },
"sort": "Sort", "sort": "Sort",
"sortBy": "Sort by", "sortBy": "Sort by",
"addToClipboard": "Add to clipboard" "addToClipboard": "Add to clipboard",
"notSet": "Not Set",
"agree": "Agree",
"decline": "Decline"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "by continuing you agree with ${tap(@:about.termsAndConditions)}", "termsAndPolicyCaution(rich)": "by continuing you agree with ${tap(@:about.termsAndConditions)}",
@@ -204,8 +207,13 @@
"mux": "Multiplexer", "mux": "Multiplexer",
"outbound": "Outbound Options", "outbound": "Outbound Options",
"tlsTricks": "TLS Tricks", "tlsTricks": "TLS Tricks",
"warp": "WARP Options",
"misc": "Misc Options" "misc": "Misc Options"
}, },
"warpConsent": {
"title": "Cloudflare WARP Consent",
"description(rich)": "Cloudflare WARP is a free WireGuard VPN provider. By enabling this option you are agreeing to the Cloudflare WARP's ${tos(Terms of Service)} and ${privacy(Privacy Policy)}."
},
"pageTitle": "Config Options", "pageTitle": "Config Options",
"logLevel": "Log Level", "logLevel": "Log Level",
"resolveDestination": "Resolve Destination", "resolveDestination": "Resolve Destination",
@@ -243,7 +251,17 @@
"tlsPaddingSize": "TLS Padding", "tlsPaddingSize": "TLS Padding",
"enableMux": "Enable Mux", "enableMux": "Enable Mux",
"muxProtocol": "Mux Protocol", "muxProtocol": "Mux Protocol",
"muxMaxStreams": "Max Concurrent Streams" "muxMaxStreams": "Max Concurrent Streams",
"enableWarp": "Enable WARP",
"warpDetourMode": "Detour Mode",
"warpDetourModes": {
"inbound": "Detour WARP through proxies",
"outbound": "Detour proxies through WARP"
},
"warpLicenseKey": "License Key",
"warpCleanIp": "Clean IP",
"warpPort": "Port",
"warpNoise": "Noise"
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "Routing Assets", "pageTitle": "Routing Assets",

View File

@@ -11,7 +11,10 @@
}, },
"sort": "Clasificar", "sort": "Clasificar",
"sortBy": "Ordenar por", "sortBy": "Ordenar por",
"addToClipboard": "Añadir al portapapeles" "addToClipboard": "Añadir al portapapeles",
"notSet": "No establecido",
"agree": "Aceptar",
"decline": "Rechazar"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "al continuar, aceptas ${tap(@:about.termsAndConditions)}", "termsAndPolicyCaution(rich)": "al continuar, aceptas ${tap(@:about.termsAndConditions)}",
@@ -204,6 +207,7 @@
"mux": "Multiplexer", "mux": "Multiplexer",
"outbound": "Opciones de salida", "outbound": "Opciones de salida",
"tlsTricks": "Trucos TLS", "tlsTricks": "Trucos TLS",
"warp": "WARP Options",
"misc": "Opciones varias" "misc": "Opciones varias"
}, },
"pageTitle": "Opciones de configuración", "pageTitle": "Opciones de configuración",
@@ -243,7 +247,21 @@
"tlsPaddingSize": "Relleno TLS", "tlsPaddingSize": "Relleno TLS",
"enableMux": "Enable Mux", "enableMux": "Enable Mux",
"muxProtocol": "Mux Protocol", "muxProtocol": "Mux Protocol",
"muxMaxStreams": "Max Concurrent Streams" "muxMaxStreams": "Max Concurrent Streams",
"enableWarp": "Enable WARP",
"warpDetourMode": "Detour Mode",
"warpDetourModes": {
"inbound": "Detour WARP through proxies",
"outbound": "Detour proxies through WARP"
},
"warpLicenseKey": "License Key",
"warpCleanIp": "Clean IP",
"warpPort": "Port",
"warpNoise": "Noise",
"warpConsent": {
"title": "Consentimiento WARP de Cloudflare",
"description(rich)": "Cloudflare WARP es un proveedor de VPN WireGuard gratuito. Al habilitar esta opción, acepta los ${tos(Términos de servicio)} y ${privacy(Política de privacidad)} de Cloudflare WARP."
}
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "Activos de enrutamiento", "pageTitle": "Activos de enrutamiento",

View File

@@ -11,7 +11,10 @@
}, },
"sort": "مرتب‌سازی", "sort": "مرتب‌سازی",
"sortBy": "مرتب‌سازی براساس", "sortBy": "مرتب‌سازی براساس",
"addToClipboard": "به کلیپ بورد اضافه کنید" "addToClipboard": "به کلیپ بورد اضافه کنید",
"notSet": "تنظیم نشده",
"agree": "موافق",
"decline": "کاهش می یابد"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "در صورت ادامه با ${tap(@:about.termsAndConditions)} موافقت میکنید", "termsAndPolicyCaution(rich)": "در صورت ادامه با ${tap(@:about.termsAndConditions)} موافقت میکنید",
@@ -204,6 +207,7 @@
"mux": "Multiplexer", "mux": "Multiplexer",
"outbound": "Outbound Options", "outbound": "Outbound Options",
"tlsTricks": "TLS Tricks", "tlsTricks": "TLS Tricks",
"warp": "WARP Options",
"misc": "تنظیمات متفرقه" "misc": "تنظیمات متفرقه"
}, },
"pageTitle": "تنظیمات کانفیگ", "pageTitle": "تنظیمات کانفیگ",
@@ -243,7 +247,21 @@
"tlsPaddingSize": "TLS Padding", "tlsPaddingSize": "TLS Padding",
"enableMux": "Enable Mux", "enableMux": "Enable Mux",
"muxProtocol": "Mux Protocol", "muxProtocol": "Mux Protocol",
"muxMaxStreams": "Max Concurrent Streams" "muxMaxStreams": "Max Concurrent Streams",
"enableWarp": "Enable WARP",
"warpDetourMode": "Detour Mode",
"warpDetourModes": {
"inbound": "Detour WARP through proxies",
"outbound": "Detour proxies through WARP"
},
"warpLicenseKey": "License Key",
"warpCleanIp": "Clean IP",
"warpPort": "Port",
"warpNoise": "Noise",
"warpConsent": {
"title": "رضایت Cloudflare WARP",
"description(rich)": "Cloudflare WARP یک ارائه دهنده رایگان WireGuard VPN است. با فعال کردن این گزینه، با ${tos(شرایط خدمات)} و ${privacy(خط‌مشی رازداری)} Cloudflare WARP موافقت می‌کنید."
}
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "فایل‌های مسیریابی", "pageTitle": "فایل‌های مسیریابی",

View File

@@ -11,7 +11,10 @@
}, },
"sort": "Сортировка", "sort": "Сортировка",
"sortBy": "Сортировка", "sortBy": "Сортировка",
"addToClipboard": "Копировать в буфер обмена" "addToClipboard": "Копировать в буфер обмена",
"notSet": "Не задано",
"agree": "Соглашаться",
"decline": "Отклонить"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "Продолжая, Вы соглашаетесь с ${tap(@:about.termsAndConditions)}", "termsAndPolicyCaution(rich)": "Продолжая, Вы соглашаетесь с ${tap(@:about.termsAndConditions)}",
@@ -204,6 +207,7 @@
"mux": "Multiplexer", "mux": "Multiplexer",
"outbound": "Outbound Options", "outbound": "Outbound Options",
"tlsTricks": "TLS Tricks", "tlsTricks": "TLS Tricks",
"warp": "WARP Options",
"misc": "Разные параметры" "misc": "Разные параметры"
}, },
"pageTitle": "Параметры конфигурации", "pageTitle": "Параметры конфигурации",
@@ -243,7 +247,21 @@
"tlsPaddingSize": "TLS Padding", "tlsPaddingSize": "TLS Padding",
"enableMux": "Enable Mux", "enableMux": "Enable Mux",
"muxProtocol": "Mux Protocol", "muxProtocol": "Mux Protocol",
"muxMaxStreams": "Max Concurrent Streams" "muxMaxStreams": "Max Concurrent Streams",
"enableWarp": "Enable WARP",
"warpDetourMode": "Detour Mode",
"warpDetourModes": {
"inbound": "Detour WARP through proxies",
"outbound": "Detour proxies through WARP"
},
"warpLicenseKey": "License Key",
"warpCleanIp": "Clean IP",
"warpPort": "Port",
"warpNoise": "Noise",
"warpConsent": {
"title": "Согласие Cloudflare WARP",
"description(rich)": "Cloudflare WARP — бесплатный провайдер WireGuard VPN. Включая эту опцию, вы соглашаетесь с ${tos(Условиями обслуживания)} и ${privacy(Политикой конфиденциальности)} Cloudflare WARP."
}
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "Активы маршрутизации", "pageTitle": "Активы маршрутизации",

View File

@@ -11,7 +11,10 @@
}, },
"sort": "Sırala", "sort": "Sırala",
"sortBy": "Sırala", "sortBy": "Sırala",
"addToClipboard": "Panoya ekle" "addToClipboard": "Panoya ekle",
"notSet": "Ayarlanmadı",
"agree": "Kabul etmek",
"decline": "Reddetmek"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "devam ederek ${tap(@:about.termsAndConditions)} kabul etmiş olursunuz", "termsAndPolicyCaution(rich)": "devam ederek ${tap(@:about.termsAndConditions)} kabul etmiş olursunuz",
@@ -204,6 +207,7 @@
"mux": "Multiplexer", "mux": "Multiplexer",
"outbound": "Outbound Options", "outbound": "Outbound Options",
"tlsTricks": "TLS Tricks", "tlsTricks": "TLS Tricks",
"warp": "WARP Options",
"misc": "Çeşitli Seçenekler" "misc": "Çeşitli Seçenekler"
}, },
"pageTitle": "Yapılandırma Seçenekleri", "pageTitle": "Yapılandırma Seçenekleri",
@@ -243,7 +247,21 @@
"tlsPaddingSize": "TLS Padding", "tlsPaddingSize": "TLS Padding",
"enableMux": "Enable Mux", "enableMux": "Enable Mux",
"muxProtocol": "Mux Protocol", "muxProtocol": "Mux Protocol",
"muxMaxStreams": "Max Concurrent Streams" "muxMaxStreams": "Max Concurrent Streams",
"enableWarp": "Enable WARP",
"warpDetourMode": "Detour Mode",
"warpDetourModes": {
"inbound": "Detour WARP through proxies",
"outbound": "Detour proxies through WARP"
},
"warpLicenseKey": "License Key",
"warpCleanIp": "Clean IP",
"warpPort": "Port",
"warpNoise": "Noise",
"warpConsent": {
"title": "Cloudflare WARP Onayı",
"description(rich)": "Cloudflare WARP ücretsiz bir WireGuard VPN sağlayıcısıdır. Bu seçeneği etkinleştirerek Cloudflare WARP'ın ${tos(Hizmet Şartları)} ve ${privacy(Gizlilik Politikası)}'nı kabul etmiş olursunuz."
}
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "Varlıkları Yönlendirme", "pageTitle": "Varlıkları Yönlendirme",

View File

@@ -11,7 +11,10 @@
}, },
"sort": "排序", "sort": "排序",
"sortBy": "排序方式", "sortBy": "排序方式",
"addToClipboard": "添加到剪贴板" "addToClipboard": "添加到剪贴板",
"notSet": "没有设置",
"agree": "同意",
"decline": "衰退"
}, },
"intro": { "intro": {
"termsAndPolicyCaution(rich)": "继续即表示您同意 ${tap(@:about.termsAndConditions)}", "termsAndPolicyCaution(rich)": "继续即表示您同意 ${tap(@:about.termsAndConditions)}",
@@ -204,7 +207,9 @@
"mux": "复用器", "mux": "复用器",
"outbound": "出站选项", "outbound": "出站选项",
"tlsTricks": "TLS Tricks", "tlsTricks": "TLS Tricks",
"misc": "其他选项" "misc": "其他选项",
"warp": "WARP 选项",
"misc": "其它选项",
}, },
"pageTitle": "配置选项", "pageTitle": "配置选项",
"logLevel": "日志级别", "logLevel": "日志级别",
@@ -244,6 +249,23 @@
"enableMux": "启用复用器", "enableMux": "启用复用器",
"muxProtocol": "复用器控制", "muxProtocol": "复用器控制",
"muxMaxStreams": "最大并发数" "muxMaxStreams": "最大并发数"
"enableMux": "启用 Mux",
"muxProtocol": "Mux 控制",
"muxMaxStreams": "最大并发数",
"enableWarp": "启用 WARP",
"warpDetourMode": "迂回模式",
"warpDetourModes": {
"inbound": "通过代理绕过 WARP",
"outbound": "通过 WARP 绕过代理"
},
"warpLicenseKey": "许可证密钥",
"warpCleanIp": "干净 IP",
"warpPort": "端口",
"warpNoise": "噪音",
"warpConsent": {
"title": "Cloudflare WARP 同意",
"description(rich)": "Cloudflare WARP 是免费的 WireGuard VPN 提供商。启用此选项即表示您同意 Cloudflare WARP 的 ${tos(服务条款)} 和 ${privacy(隐私政策)}"
}
}, },
"geoAssets": { "geoAssets": {
"pageTitle": "路由资源文件", "pageTitle": "路由资源文件",

View File

@@ -34,7 +34,7 @@
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
54EA599BF9C050F2827533D5 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */; }; 59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */; };
6836D3FD2B57FE4300A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D3FC2B57FE4300A79D75 /* Libcore */; }; 6836D3FD2B57FE4300A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D3FC2B57FE4300A79D75 /* Libcore */; };
6836D4022B57FEFF00A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D4012B57FEFF00A79D75 /* Libcore */; }; 6836D4022B57FEFF00A79D75 /* Libcore in Frameworks */ = {isa = PBXBuildFile; productRef = 6836D4012B57FEFF00A79D75 /* Libcore */; };
68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */; }; 68885DD72B4EF33400D214BA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */; };
@@ -89,6 +89,7 @@
032158B72ADDF8BF008D943B /* VPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNManager.swift; sourceTree = "<group>"; }; 032158B72ADDF8BF008D943B /* VPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNManager.swift; sourceTree = "<group>"; };
032158B92ADDFCC9008D943B /* TrafficReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficReader.swift; sourceTree = "<group>"; }; 032158B92ADDFCC9008D943B /* TrafficReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficReader.swift; sourceTree = "<group>"; };
032158BB2ADDFD09008D943B /* SingBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingBox.swift; sourceTree = "<group>"; }; 032158BB2ADDFD09008D943B /* SingBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingBox.swift; sourceTree = "<group>"; };
0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
03B516662AE6B93A00EA47E2 /* MethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodHandler.swift; sourceTree = "<group>"; }; 03B516662AE6B93A00EA47E2 /* MethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodHandler.swift; sourceTree = "<group>"; };
03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEventHandler.swift; sourceTree = "<group>"; }; 03B516682AE7306B00EA47E2 /* StatusEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEventHandler.swift; sourceTree = "<group>"; };
03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsEventHandler.swift; sourceTree = "<group>"; }; 03B5166A2AE7315E00EA47E2 /* AlertsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsEventHandler.swift; sourceTree = "<group>"; };
@@ -109,6 +110,7 @@
03E392CE2ADDEFC8000ADF15 /* FilePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePath.swift; sourceTree = "<group>"; }; 03E392CE2ADDEFC8000ADF15 /* FilePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePath.swift; sourceTree = "<group>"; };
03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionPlatformInterface.swift; sourceTree = "<group>"; }; 03E392D12ADDF1F4000ADF15 /* ExtensionPlatformInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionPlatformInterface.swift; sourceTree = "<group>"; };
03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+RunBlocking.swift"; sourceTree = "<group>"; }; 03E392D32ADDF262000ADF15 /* Extension+RunBlocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+RunBlocking.swift"; sourceTree = "<group>"; };
040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = mobile_scanner.xcframework; path = ../build/ios/framework/Release/mobile_scanner.xcframework; sourceTree = "<group>"; }; 0736954E2B1FEB3E007249BE /* mobile_scanner.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = mobile_scanner.xcframework; path = ../build/ios/framework/Release/mobile_scanner.xcframework; sourceTree = "<group>"; };
0736958A2B3AC96D007249BE /* Bundle+Properties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Properties.swift"; sourceTree = "<group>"; }; 0736958A2B3AC96D007249BE /* Bundle+Properties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Properties.swift"; sourceTree = "<group>"; };
0736958C2B3B79E0007249BE /* StatsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsEventHandler.swift; sourceTree = "<group>"; }; 0736958C2B3B79E0007249BE /* StatsEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsEventHandler.swift; sourceTree = "<group>"; };
@@ -138,9 +140,9 @@
07A63A9F2B1E72FC00CAFA4D /* path_provider_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = path_provider_foundation.xcframework; path = ../build/ios/framework/release/path_provider_foundation.xcframework; sourceTree = "<group>"; }; 07A63A9F2B1E72FC00CAFA4D /* path_provider_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = path_provider_foundation.xcframework; path = ../build/ios/framework/release/path_provider_foundation.xcframework; sourceTree = "<group>"; };
07A63AA02B1E72FC00CAFA4D /* shared_preferences_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared_preferences_foundation.xcframework; path = ../build/ios/framework/release/shared_preferences_foundation.xcframework; sourceTree = "<group>"; }; 07A63AA02B1E72FC00CAFA4D /* shared_preferences_foundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared_preferences_foundation.xcframework; path = ../build/ios/framework/release/shared_preferences_foundation.xcframework; sourceTree = "<group>"; };
07A63AA12B1E72FC00CAFA4D /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../build/ios/framework/release/Sentry.xcframework; sourceTree = "<group>"; }; 07A63AA12B1E72FC00CAFA4D /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../build/ios/framework/release/Sentry.xcframework; sourceTree = "<group>"; };
0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
@@ -151,7 +153,7 @@
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; sourceTree = "<group>"; }; 7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.debug.xcconfig"; sourceTree = "<group>"; };
7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; }; 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; 90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
@@ -160,10 +162,8 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; sourceTree = "<group>"; }; 9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.release.xcconfig"; sourceTree = "<group>"; };
C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; sourceTree = "<group>"; }; F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; path = "Target Support Files/Pods-Runner-SingBoxPacketTunnel/Pods-Runner-SingBoxPacketTunnel.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -181,7 +181,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
54EA599BF9C050F2827533D5 /* Pods_RunnerTests.framework in Frameworks */, 59E8864FB99B37076B22F32B /* Pods_RunnerTests.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -276,12 +276,12 @@
574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */, 574F12C7748958784380337F /* Pods-Runner.debug.xcconfig */,
90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */, 90E93DE403BDFA627F3AA51E /* Pods-Runner.release.xcconfig */,
C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */, C20A211B58CE31B2738D133C /* Pods-Runner.profile.xcconfig */,
7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */,
9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */,
0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */,
7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */, 7CA62594950187FCFE36B54C /* Pods-Runner-SingBoxPacketTunnel.debug.xcconfig */,
9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */, 9AC67B4DCF829F5B6F63AA7D /* Pods-Runner-SingBoxPacketTunnel.release.xcconfig */,
F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */, F3FFE1D9C2D5629FACC123EE /* Pods-Runner-SingBoxPacketTunnel.profile.xcconfig */,
0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */,
808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */,
040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -388,8 +388,8 @@
07A63A842B1E72AE00CAFA4D /* App.xcframework */, 07A63A842B1E72AE00CAFA4D /* App.xcframework */,
07A63A832B1E728C00CAFA4D /* Release */, 07A63A832B1E728C00CAFA4D /* Release */,
60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */, 60F1D4AAC33ACF5C8307310D /* Pods_Runner.framework */,
DDA50BDF2E5E5DDA3995F24D /* Pods_RunnerTests.framework */,
03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */, 03E392B72ADDA00E000ADF15 /* NetworkExtension.framework */,
30560DB3EFDF5E86AAD00AB8 /* Pods_RunnerTests.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -424,7 +424,7 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = ( buildPhases = (
F63DAC79B8A3B6681959DBC1 /* [CP] Check Pods Manifest.lock */, 2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */, 331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */, 331C807F294A63A400263BE5 /* Resources */,
531FE8242BCD501C24C8E9FA /* Frameworks */, 531FE8242BCD501C24C8E9FA /* Frameworks */,
@@ -546,6 +546,28 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
2058E420D1A8B6F0E5E03873 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1; alwaysOutOfDate = 1;
@@ -599,28 +621,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
F63DAC79B8A3B6681959DBC1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FBEFD3291AEA65EDE2F5AEF6 /* [CP] Embed Pods Frameworks */ = { FBEFD3291AEA65EDE2F5AEF6 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -800,6 +800,8 @@
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)",
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
@@ -847,6 +849,8 @@
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)",
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
@@ -942,49 +946,18 @@
DEVELOPMENT_TEAM = 3JFTY5BP58; DEVELOPMENT_TEAM = 3JFTY5BP58;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/MLImage/Frameworks\"",
"\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"",
"\"${PODS_ROOT}/MLKitCommon/Frameworks\"",
"\"${PODS_ROOT}/MLKitVision/Frameworks\"",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)/Frameworks/**",
"$(PROJECT_DIR)/..",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift", "$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)",
"$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks",
"@executable_path/../libcore/", "@executable_path/../libcore/",
"@executable_path/libcore", "@executable_path/libcore/",
); );
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
@@ -1010,7 +983,7 @@
}; };
331C8088294A63A400263BE5 /* Debug */ = { 331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7E8B7AF73AD416B8FAA5E9B0 /* Pods-RunnerTests.debug.xcconfig */; baseConfigurationReference = 0337C822BEDF7A95576475B3 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@@ -1028,7 +1001,7 @@
}; };
331C8089294A63A400263BE5 /* Release */ = { 331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 9A37A927A1A9458918B3C12A /* Pods-RunnerTests.release.xcconfig */; baseConfigurationReference = 808A94F72872B54716770416 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@@ -1044,7 +1017,7 @@
}; };
331C808A294A63A400263BE5 /* Profile */ = { 331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 0F7E04B7207513677AF77112 /* Pods-RunnerTests.profile.xcconfig */; baseConfigurationReference = 040FA3EB0673B72D60CC7145 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@@ -1194,49 +1167,18 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64"; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/MLImage/Frameworks\"",
"\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"",
"\"${PODS_ROOT}/MLKitCommon/Frameworks\"",
"\"${PODS_ROOT}/MLKitVision/Frameworks\"",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)/Frameworks/**",
"$(PROJECT_DIR)/..",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift", "$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)",
"$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks",
"@executable_path/../libcore/", "@executable_path/../libcore/",
"@executable_path/libcore", "@executable_path/libcore/",
); );
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
"-fcxx-modules", "-fcxx-modules",
@@ -1273,49 +1215,18 @@
DEVELOPMENT_TEAM = 3JFTY5BP58; DEVELOPMENT_TEAM = 3JFTY5BP58;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7; "EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilitiesComponents\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/Sentry\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/SentryPrivate\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cupertino_http\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_native_splash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/mobile_scanner\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/protocol_handler\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sentry_flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/shared_preferences_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/sqlite3_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/MLImage/Frameworks\"",
"\"${PODS_ROOT}/MLKitBarcodeScanning/Frameworks\"",
"\"${PODS_ROOT}/MLKitCommon/Frameworks\"",
"\"${PODS_ROOT}/MLKitVision/Frameworks\"",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)/Frameworks/**",
"$(PROJECT_DIR)/..",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)", "$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift", "$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.5/$(PLATFORM_NAME)",
"$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks",
"@executable_path/../libcore/", "@executable_path/../libcore/",
"@executable_path/libcore", "@executable_path/libcore/",
); );
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (

View File

@@ -1,31 +1,72 @@
//
// LogsEventHandler.swift
// Runner
//
// Created by GFWFighter on 10/24/23.
//
import Foundation import Foundation
import Combine
import Libcore
public class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler { class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler, LibboxCommandClientHandlerProtocol {
static let name = "\(Bundle.main.serviceIdentifier)/service.logs" static let name = "\(Bundle.main.serviceIdentifier)/service.logs"
private var channel: FlutterEventChannel? private var channel: FlutterEventChannel?
private var commandClient: LibboxCommandClient?
private var events: FlutterEventSink?
private var maxLines: Int
private var logList: [String] = []
private var lock: NSLock = NSLock()
public static func register(with registrar: FlutterPluginRegistrar) { public static func register(with registrar: FlutterPluginRegistrar) {
let instance = LogsEventHandler() let instance = LogsEventHandler()
instance.channel = FlutterEventChannel(name: Self.name, binaryMessenger: registrar.messenger()) instance.channel = FlutterEventChannel(name: Self.name, binaryMessenger: registrar.messenger())
instance.channel?.setStreamHandler(instance) instance.channel?.setStreamHandler(instance)
} }
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { init(maxLines: Int = 32) {
if VPNManager.shared.logCallback { self.maxLines = maxLines
events(VPNManager.shared.logList) super.init()
let opts = LibboxCommandClientOptions()
opts.command = LibboxCommandLog
opts.statusInterval = Int64(2 * NSEC_PER_SEC)
commandClient = LibboxCommandClient(self, options: opts)
try? commandClient?.connect()
} }
deinit {
try? commandClient?.disconnect()
}
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
events(logList)
self.events = events
return nil return nil
} }
public func onCancel(withArguments arguments: Any?) -> FlutterError? { public func onCancel(withArguments arguments: Any?) -> FlutterError? {
events = nil
return nil return nil
} }
func writeLog(_ message: String?) {
guard let message else {
return
}
lock.withLock { [self] in
if logList.count > maxLines {
logList.removeFirst()
}
logList.append(message)
DispatchQueue.main.async { [self] () in
events?(logList)
}
}
}
}
extension LogsEventHandler {
public func clearLog() {}
public func connected() {}
public func disconnected(_ message: String?) {}
public func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {}
public func updateClashMode(_ newMode: String?) {}
public func writeGroups(_ message: LibboxOutboundGroupIteratorProtocol?) {}
public func writeStatus(_ message: LibboxStatusMessage?) {}
} }

View File

@@ -39,8 +39,6 @@ class VPNManager: ObservableObject {
@Published private(set) var upload: Int64 = 0 @Published private(set) var upload: Int64 = 0
@Published private(set) var download: Int64 = 0 @Published private(set) var download: Int64 = 0
@Published private(set) var elapsedTime: TimeInterval = 0 @Published private(set) var elapsedTime: TimeInterval = 0
@Published private(set) var logList: [String] = []
@Published private(set) var logCallback = false
private var _connectTime: Date? private var _connectTime: Date?
private var connectTime: Date? { private var connectTime: Date? {
@@ -88,7 +86,7 @@ class VPNManager: ObservableObject {
do { do {
try await loadVPNPreference() try await loadVPNPreference()
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
} }
@@ -109,7 +107,7 @@ class VPNManager: ObservableObject {
try await newManager.loadFromPreferences() try await newManager.loadFromPreferences()
self.manager = newManager self.manager = newManager
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
} }
@@ -119,7 +117,7 @@ class VPNManager: ObservableObject {
try await manager.saveToPreferences() try await manager.saveToPreferences()
try await manager.loadFromPreferences() try await manager.loadFromPreferences()
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
} }
@@ -159,7 +157,7 @@ class VPNManager: ObservableObject {
} }
try await self?.loadVPNPreference() try await self?.loadVPNPreference()
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
} }
}.store(in: &cancelBag) }.store(in: &cancelBag)
@@ -190,7 +188,7 @@ class VPNManager: ObservableObject {
} }
} }
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
} }
@@ -204,7 +202,7 @@ class VPNManager: ObservableObject {
"DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString, "DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString,
]) ])
} catch { } catch {
onServiceWriteLog(message: error.localizedDescription) LogsEventHandler().writeLog(error.localizedDescription)
} }
connectTime = .now connectTime = .now
} }
@@ -213,17 +211,4 @@ class VPNManager: ObservableObject {
guard state == .connected else { return } guard state == .connected else { return }
manager.connection.stopVPNTunnel() manager.connection.stopVPNTunnel()
} }
func onServiceWriteLog(message: String) {
logCallback = true
if logList.count > 300 {
logList.removeFirst()
}
logList.append(message)
}
func onServiceResetLogs() {
logCallback = false
logList.removeAll()
}
} }

View File

@@ -10,4 +10,8 @@ abstract class Constants {
static const telegramChannelUrl = "https://t.me/hiddify"; static const telegramChannelUrl = "https://t.me/hiddify";
static const privacyPolicyUrl = "https://hiddify.com/privacy-policy/"; static const privacyPolicyUrl = "https://hiddify.com/privacy-policy/";
static const termsAndConditionsUrl = "https://hiddify.com/terms/"; static const termsAndConditionsUrl = "https://hiddify.com/terms/";
static const cfWarpPrivacyPolicy =
"https://www.cloudflare.com/application/privacypolicy/";
static const cfWarpTermsOfService =
"https://www.cloudflare.com/application/terms/";
} }

View File

@@ -1,4 +1,6 @@
import 'package:dartx/dartx.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hiddify/core/localization/translations.dart';
part 'range.freezed.dart'; part 'range.freezed.dart';
@@ -7,14 +9,21 @@ class RangeWithOptionalCeil with _$RangeWithOptionalCeil {
const RangeWithOptionalCeil._(); const RangeWithOptionalCeil._();
const factory RangeWithOptionalCeil({ const factory RangeWithOptionalCeil({
required int min, int? min,
int? max, int? max,
}) = _RangeWithOptionalCeil; }) = _RangeWithOptionalCeil;
String format() => "$min${max != null ? "-$max" : ""}"; String format() => [min, max].whereNotNull().join("-");
String present(TranslationsEn t) =>
format().isEmpty ? t.general.notSet : format();
factory RangeWithOptionalCeil.fromString(String input) => factory RangeWithOptionalCeil._fromString(
String input, {
bool allowEmpty = true,
}) =>
switch (input.split("-")) { switch (input.split("-")) {
[final String val] when val.isEmpty && allowEmpty =>
const RangeWithOptionalCeil(),
[final String min] => RangeWithOptionalCeil(min: int.parse(min)), [final String min] => RangeWithOptionalCeil(min: int.parse(min)),
[final String min, final String max] => RangeWithOptionalCeil( [final String min, final String max] => RangeWithOptionalCeil(
min: int.parse(min), min: int.parse(min),
@@ -23,9 +32,12 @@ class RangeWithOptionalCeil with _$RangeWithOptionalCeil {
_ => throw Exception("Invalid range: $input"), _ => throw Exception("Invalid range: $input"),
}; };
static RangeWithOptionalCeil? tryParse(String input) { static RangeWithOptionalCeil? tryParse(
String input, {
bool allowEmpty = false,
}) {
try { try {
return RangeWithOptionalCeil.fromString(input); return RangeWithOptionalCeil._fromString(input);
} catch (_) { } catch (_) {
return null; return null;
} }
@@ -38,7 +50,7 @@ class RangeWithOptionalCeilJsonConverter
@override @override
RangeWithOptionalCeil fromJson(String json) => RangeWithOptionalCeil fromJson(String json) =>
RangeWithOptionalCeil.fromString(json); RangeWithOptionalCeil._fromString(json);
@override @override
String toJson(RangeWithOptionalCeil object) => object.format(); String toJson(RangeWithOptionalCeil object) => object.format();

View File

@@ -117,6 +117,12 @@ class ConfigOptionRepositoryImpl
muxPadding: persisted.muxPadding, muxPadding: persisted.muxPadding,
muxMaxStreams: persisted.muxMaxStreams, muxMaxStreams: persisted.muxMaxStreams,
muxProtocol: persisted.muxProtocol, muxProtocol: persisted.muxProtocol,
enableWarp: persisted.enableWarp,
warpDetourMode: persisted.warpDetourMode,
warpLicenseKey: persisted.warpLicenseKey,
warpCleanIp: persisted.warpCleanIp,
warpPort: persisted.warpPort,
warpNoise: persisted.warpNoise,
geoipPath: geoAssetPathResolver.relativePath( geoipPath: geoAssetPathResolver.relativePath(
geoAssets.geoip.providerName, geoAssets.geoip.providerName,
geoAssets.geoip.fileName, geoAssets.geoip.fileName,

View File

@@ -57,6 +57,14 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
@Default(false) bool muxPadding, @Default(false) bool muxPadding,
@Default(8) int muxMaxStreams, @Default(8) int muxMaxStreams,
@Default(MuxProtocol.h2mux) MuxProtocol muxProtocol, @Default(MuxProtocol.h2mux) MuxProtocol muxProtocol,
@Default(false) bool enableWarp,
@Default(WarpDetourMode.outbound) WarpDetourMode warpDetourMode,
@Default("") String warpLicenseKey,
@Default("auto") String warpCleanIp,
@Default(0) int warpPort,
@RangeWithOptionalCeilJsonConverter()
@Default(RangeWithOptionalCeil())
RangeWithOptionalCeil warpNoise,
}) = _ConfigOptionEntity; }) = _ConfigOptionEntity;
static ConfigOptionEntity initial = ConfigOptionEntity( static ConfigOptionEntity initial = ConfigOptionEntity(
@@ -67,7 +75,11 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
if (PlatformUtils.isDesktop && serviceMode == ServiceMode.tun) { if (PlatformUtils.isDesktop && serviceMode == ServiceMode.tun) {
return true; return true;
} }
if (enableTlsFragment || enableTlsMixedSniCase || enableTlsPadding||enableMux) { if (enableTlsFragment ||
enableTlsMixedSniCase ||
enableTlsPadding ||
enableMux ||
enableWarp) {
return true; return true;
} }
@@ -117,6 +129,12 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
muxPadding: patch.muxPadding ?? muxPadding, muxPadding: patch.muxPadding ?? muxPadding,
muxMaxStreams: patch.muxMaxStreams ?? muxMaxStreams, muxMaxStreams: patch.muxMaxStreams ?? muxMaxStreams,
muxProtocol: patch.muxProtocol ?? muxProtocol, muxProtocol: patch.muxProtocol ?? muxProtocol,
enableWarp: patch.enableWarp ?? enableWarp,
warpDetourMode: patch.warpDetourMode ?? warpDetourMode,
warpLicenseKey: patch.warpLicenseKey ?? warpLicenseKey,
warpCleanIp: patch.warpCleanIp ?? warpCleanIp,
warpPort: patch.warpPort ?? warpPort,
warpNoise: patch.warpNoise ?? warpNoise,
); );
} }

View File

@@ -47,6 +47,12 @@ class ConfigOptionPatch with _$ConfigOptionPatch {
bool? muxPadding, bool? muxPadding,
int? muxMaxStreams, int? muxMaxStreams,
MuxProtocol? muxProtocol, MuxProtocol? muxProtocol,
bool? enableWarp,
WarpDetourMode? warpDetourMode,
String? warpLicenseKey,
String? warpCleanIp,
int? warpPort,
@RangeWithOptionalCeilJsonConverter() RangeWithOptionalCeil? warpNoise,
}) = _ConfigOptionPatch; }) = _ConfigOptionPatch;
factory ConfigOptionPatch.fromJson(Map<String, dynamic> json) => factory ConfigOptionPatch.fromJson(Map<String, dynamic> json) =>

View File

@@ -0,0 +1,26 @@
import 'package:hiddify/core/preferences/preferences_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'warp_option_notifier.g.dart';
@Riverpod(keepAlive: true)
class WarpOptionNotifier extends _$WarpOptionNotifier {
@override
bool build() {
return ref
.read(sharedPreferencesProvider)
.requireValue
.getBool(warpConsentGiven) ??
false;
}
Future<void> agree() async {
await ref
.read(sharedPreferencesProvider)
.requireValue
.setBool(warpConsentGiven, true);
state = true;
}
static const warpConsentGiven = "warp_consent_given";
}

View File

@@ -9,6 +9,7 @@ import 'package:hiddify/core/widget/tip_card.dart';
import 'package:hiddify/features/config_option/model/config_option_entity.dart'; import 'package:hiddify/features/config_option/model/config_option_entity.dart';
import 'package:hiddify/features/config_option/model/config_option_patch.dart'; import 'package:hiddify/features/config_option/model/config_option_patch.dart';
import 'package:hiddify/features/config_option/notifier/config_option_notifier.dart'; import 'package:hiddify/features/config_option/notifier/config_option_notifier.dart';
import 'package:hiddify/features/config_option/overview/warp_options_widgets.dart';
import 'package:hiddify/features/log/model/log_level.dart'; import 'package:hiddify/features/log/model/log_level.dart';
import 'package:hiddify/features/settings/widgets/sections_widgets.dart'; import 'package:hiddify/features/settings/widgets/sections_widgets.dart';
import 'package:hiddify/features/settings/widgets/settings_input_dialog.dart'; import 'package:hiddify/features/settings/widgets/settings_input_dialog.dart';
@@ -319,7 +320,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
title: Text(t.settings.config.tlsFragmentSize), title: Text(t.settings.config.tlsFragmentSize),
subtitle: Text(options.tlsFragmentSize.format()), subtitle: Text(options.tlsFragmentSize.present(t)),
onTap: () async { onTap: () async {
final range = await SettingsInputDialog( final range = await SettingsInputDialog(
title: t.settings.config.tlsFragmentSize, title: t.settings.config.tlsFragmentSize,
@@ -336,7 +337,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
title: Text(t.settings.config.tlsFragmentSleep), title: Text(t.settings.config.tlsFragmentSleep),
subtitle: Text(options.tlsFragmentSleep.format()), subtitle: Text(options.tlsFragmentSleep.present(t)),
onTap: () async { onTap: () async {
final range = await SettingsInputDialog( final range = await SettingsInputDialog(
title: t.settings.config.tlsFragmentSleep, title: t.settings.config.tlsFragmentSleep,
@@ -368,7 +369,7 @@ class ConfigOptionsPage extends HookConsumerWidget {
), ),
ListTile( ListTile(
title: Text(t.settings.config.tlsPaddingSize), title: Text(t.settings.config.tlsPaddingSize),
subtitle: Text(options.tlsPaddingSize.format()), subtitle: Text(options.tlsPaddingSize.present(t)),
onTap: () async { onTap: () async {
final range = await SettingsInputDialog( final range = await SettingsInputDialog(
title: t.settings.config.tlsPaddingSize, title: t.settings.config.tlsPaddingSize,
@@ -384,6 +385,13 @@ class ConfigOptionsPage extends HookConsumerWidget {
}, },
), ),
const SettingsDivider(), const SettingsDivider(),
SettingsSection(experimental(t.settings.config.section.warp)),
WarpOptionsTiles(
options: options,
defaultOptions: defaultOptions,
onChange: changeOption,
),
const SettingsDivider(),
SettingsSection(t.settings.config.section.misc), SettingsSection(t.settings.config.section.misc),
ListTile( ListTile(
title: Text(t.settings.config.connectionTestUrl), title: Text(t.settings.config.connectionTestUrl),

View File

@@ -0,0 +1,199 @@
import 'package:dartx/dartx.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/core/model/constants.dart';
import 'package:hiddify/core/model/range.dart';
import 'package:hiddify/features/config_option/model/config_option_entity.dart';
import 'package:hiddify/features/config_option/model/config_option_patch.dart';
import 'package:hiddify/features/config_option/notifier/warp_option_notifier.dart';
import 'package:hiddify/features/settings/widgets/settings_input_dialog.dart';
import 'package:hiddify/singbox/model/singbox_config_enum.dart';
import 'package:hiddify/utils/uri_utils.dart';
import 'package:hiddify/utils/validators.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class WarpOptionsTiles extends HookConsumerWidget {
const WarpOptionsTiles({
required this.options,
required this.defaultOptions,
required this.onChange,
super.key,
});
final ConfigOptionEntity options;
final ConfigOptionEntity defaultOptions;
final Future<void> Function(ConfigOptionPatch patch) onChange;
@override
Widget build(BuildContext context, WidgetRef ref) {
final t = ref.watch(translationsProvider);
final warpPrefaceCompleted = ref.watch(warpOptionNotifierProvider);
final canChangeOptions = warpPrefaceCompleted && options.enableWarp;
return Column(
children: [
SwitchListTile.adaptive(
title: Text(t.settings.config.enableWarp),
value: options.enableWarp,
onChanged: (value) async {
if (!warpPrefaceCompleted) {
final agreed = await showAdaptiveDialog<bool>(
context: context,
builder: (context) => const WarpLicenseAgreementModal(),
);
if (agreed ?? false) {
await ref.read(warpOptionNotifierProvider.notifier).agree();
await onChange(ConfigOptionPatch(enableWarp: value));
}
} else {
await onChange(ConfigOptionPatch(enableWarp: value));
}
},
),
ListTile(
title: Text(t.settings.config.warpDetourMode),
subtitle: Text(options.warpDetourMode.present(t)),
enabled: canChangeOptions,
onTap: () async {
final warpDetourMode = await SettingsPickerDialog(
title: t.settings.config.warpDetourMode,
selected: options.warpDetourMode,
options: WarpDetourMode.values,
getTitle: (e) => e.present(t),
resetValue: defaultOptions.warpDetourMode,
).show(context);
if (warpDetourMode == null) return;
await onChange(
ConfigOptionPatch(warpDetourMode: warpDetourMode),
);
},
),
ListTile(
title: Text(t.settings.config.warpLicenseKey),
subtitle: Text(
options.warpLicenseKey.isEmpty
? t.general.notSet
: options.warpLicenseKey,
),
enabled: canChangeOptions,
onTap: () async {
final licenseKey = await SettingsInputDialog(
title: t.settings.config.warpLicenseKey,
initialValue: options.warpLicenseKey,
resetValue: defaultOptions.warpLicenseKey,
).show(context);
if (licenseKey == null) return;
await onChange(ConfigOptionPatch(warpLicenseKey: licenseKey));
},
),
ListTile(
title: Text(t.settings.config.warpCleanIp),
subtitle: Text(options.warpCleanIp),
enabled: canChangeOptions,
onTap: () async {
final warpCleanIp = await SettingsInputDialog(
title: t.settings.config.warpCleanIp,
initialValue: options.warpCleanIp,
resetValue: defaultOptions.warpCleanIp,
).show(context);
if (warpCleanIp == null || warpCleanIp.isBlank) return;
await onChange(ConfigOptionPatch(warpCleanIp: warpCleanIp));
},
),
ListTile(
title: Text(t.settings.config.warpPort),
subtitle: Text(options.warpPort.toString()),
enabled: canChangeOptions,
onTap: () async {
final warpPort = await SettingsInputDialog(
title: t.settings.config.warpPort,
initialValue: options.warpPort,
resetValue: defaultOptions.warpPort,
validator: isPort,
mapTo: int.tryParse,
digitsOnly: true,
).show(context);
if (warpPort == null) return;
await onChange(
ConfigOptionPatch(warpPort: warpPort),
);
},
),
ListTile(
title: Text(t.settings.config.warpNoise),
subtitle: Text(options.warpNoise.present(t)),
enabled: canChangeOptions,
onTap: () async {
final warpNoise = await SettingsInputDialog(
title: t.settings.config.warpNoise,
initialValue: options.warpNoise.format(),
resetValue: defaultOptions.warpNoise.format(),
).show(context);
if (warpNoise == null) return;
await onChange(
ConfigOptionPatch(
warpNoise: RangeWithOptionalCeil.tryParse(
warpNoise,
allowEmpty: true,
),
),
);
},
),
],
);
}
}
class WarpLicenseAgreementModal extends HookConsumerWidget {
const WarpLicenseAgreementModal({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final t = ref.watch(translationsProvider);
return AlertDialog.adaptive(
title: Text(t.settings.config.warpConsent.title),
content: Text.rich(
t.settings.config.warpConsent.description(
tos: (text) => TextSpan(
text: text,
style: const TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()
..onTap = () async {
await UriUtils.tryLaunch(
Uri.parse(Constants.cfWarpTermsOfService),
);
},
),
privacy: (text) => TextSpan(
text: text,
style: const TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()
..onTap = () async {
await UriUtils.tryLaunch(
Uri.parse(Constants.cfWarpPrivacyPolicy),
);
},
),
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(false);
},
child: Text(t.general.decline),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: Text(t.general.agree),
),
],
);
}
}

View File

@@ -170,11 +170,11 @@ class ConnectionPlatformSourceImpl
fullPath = "libcore"; fullPath = "libcore";
} }
if (Platform.isWindows) { if (Platform.isWindows) {
fullPath = p.join(fullPath, "hiddify-service.exe"); fullPath = p.join(fullPath, "HiddifyService.exe");
} else if (Platform.isMacOS) { } else if (Platform.isMacOS) {
fullPath = p.join(fullPath, "hiddify-service"); fullPath = p.join(fullPath, "HiddifyService");
} else { } else {
fullPath = p.join(fullPath, "hiddify-service"); fullPath = p.join(fullPath, "HiddifyService");
} }
return "$binFolder/$fullPath"; return "$binFolder/$fullPath";

View File

@@ -78,3 +78,13 @@ enum MuxProtocol {
smux, smux,
yamux; yamux;
} }
enum WarpDetourMode {
outbound,
inbound;
String present(TranslationsEn t) => switch (this) {
outbound => t.settings.config.warpDetourModes.outbound,
inbound => t.settings.config.warpDetourModes.inbound,
};
}

View File

@@ -52,6 +52,13 @@ class SingboxConfigOption with _$SingboxConfigOption {
required bool muxPadding, required bool muxPadding,
required int muxMaxStreams, required int muxMaxStreams,
required MuxProtocol muxProtocol, required MuxProtocol muxProtocol,
required bool enableWarp,
required WarpDetourMode warpDetourMode,
required String warpLicenseKey,
required String warpCleanIp,
required int warpPort,
@RangeWithOptionalCeilJsonConverter()
required RangeWithOptionalCeil warpNoise,
required String geoipPath, required String geoipPath,
required String geositePath, required String geositePath,
required List<SingboxRule> rules, required List<SingboxRule> rules,

View File

@@ -120,8 +120,11 @@ install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
install(FILES "../libcore/bin/libcore.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "../libcore/bin/libcore.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime) COMPONENT Runtime)
install(FILES "../libcore/bin/hiddify-service" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(
COMPONENT Runtime) FILES "../libcore/bin/HiddifyService"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime
)
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}" install(FILES "${bundled_library}"

View File

@@ -87,9 +87,9 @@ set(HIDDIFY_NEXT_LIB "../libcore/bin/libcore.dll")
install(FILES "${HIDDIFY_NEXT_LIB}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${HIDDIFY_NEXT_LIB}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime RENAME libcore.dll) COMPONENT Runtime RENAME libcore.dll)
set(HIDDIFY_NEXT_LIB "../libcore/bin/hiddify-service.exe") set(HIDDIFY_NEXT_LIB "../libcore/bin/HiddifyService.exe")
install(FILES "${HIDDIFY_NEXT_LIB}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${HIDDIFY_NEXT_LIB}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime RENAME hiddify-service.exe) COMPONENT Runtime RENAME HiddifyService.exe)
if(PLUGIN_BUNDLED_LIBRARIES) if(PLUGIN_BUNDLED_LIBRARIES)

View File

@@ -2,9 +2,16 @@ app_id: 6L903538-42B1-4596-G479-BJ779F21A65D
publisher: Hiddify publisher: Hiddify
publisher_url: https://github.com/hiddify/hiddify-next publisher_url: https://github.com/hiddify/hiddify-next
display_name: Hiddify Next display_name: Hiddify Next
executable_name: HiddifyNext.exe
output_base_file_name: HiddifyNext.exe
create_desktop_icon: true create_desktop_icon: true
install_dir_name: "{autopf64}\\hiddify" install_dir_name: "{autopf64}\\hiddify"
setup_icon_file: ..\..\windows\runner\resources\app_icon.ico setup_icon_file: ..\..\windows\runner\resources\app_icon.ico
locales: locales:
- en - en
- fa - fa
- zh
- ru
- pt
- tr
#script_template: inno_setup.sas