Compare commits

95 Commits

Author SHA1 Message Date
shanshanzhong147 a7df3a44a2 chore: 将项目名称从 BearVPN 更新为 HiFastVPN 2025-11-24 00:59:18 -08:00
shanshanzhong147 7956349c0a feat(打包): 添加Windows单文件打包脚本和工具安装脚本
添加install_build_tools.bat用于自动安装构建工具
添加package_windows_single_exe.ps1用于打包Flutter应用为单文件
改进inno_setup.sas增加卸载清理逻辑和进程终止功能
2025-11-24 00:52:28 -08:00
shanshanzhong147 8ccfc6d272 ci(打包): 优化Windows打包流程
- 使用choco统一安装7zip和Enigma Virtual Box
- 改进7zip自解压包的配置和创建方式
- 移除冗余的下载和检查逻辑
2025-11-09 22:39:11 -08:00
shanshanzhong147 f526122f33 docs: 添加自动打包说明并简化工作流脚本
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m34s
Build Windows / build (push) Failing after 7h11m21s
添加详细的自动打包说明文档,介绍工作流功能和打包流程
简化 docker.yml 中的脚本内容,移除冗余代码并优化错误处理
2025-11-09 22:06:42 -08:00
shanshanzhong147 b86d645acf feat(ci): 添加 Windows 单文件打包工作流
Build Windows / build (push) Failing after 7h11m30s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m27s
添加 Enigma Virtual Box 和 7-Zip 备选方案,用于将 Flutter Windows 应用打包为单文件 EXE
包含自动化脚本和文档说明,优化构建产物分发
2025-11-09 21:18:52 -08:00
shanshanzhong147 ef1f3bfb50 修复 Windows 构建产物上传路径,添加构建日志分析文档
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m34s
Build Windows / build (push) Successful in 7h11m38s
- 修复构建产物上传路径,添加缺失的 x64 目录层级
- 创建构建日志分析文档,详细说明构建过程和解决方案
- Windows 构建流程已完全打通,Debug 和 Release 构建均成功
2025-11-09 20:14:17 -08:00
shanshanzhong147 33917e774d fix(kr_home_controller): 将超时时间从Duration改为毫秒数值
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m56s
Build Windows / build (push) Successful in 7h7m9s
将KRLatencyTester.testMultipleNodes方法的timeout参数从Duration类型改为直接使用毫秒数值,保持与接口定义一致
2025-11-09 18:49:33 -08:00
shanshanzhong147 78c20f9ae9 feat(utils): 添加延迟测试工具类用于TCP连接延迟测试
Build Windows / build (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Has been cancelled
新增KRLatencyTester工具类,提供单节点和批量节点的TCP延迟测试功能
支持自定义超时时间和并发数,测试结果包含成功/失败状态和延迟时间
```

```msg
refactor(home): 使用_storage直接保存闪连状态

将_saveQuickConnectStatus方法替换为直接调用_storage.kr_saveBool
简化代码逻辑,保持存储方式的一致性
2025-11-09 05:38:02 -08:00
shanshanzhong147 610eb4f20d feat(CI): 添加 NuGet 安装脚本并优化 CI 流程
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m23s
Build Windows / build (push) Failing after 7h2m36s
添加三个 NuGet 安装脚本(批处理和 PowerShell),支持直接下载和通过 Chocolatey 安装
修改 CI 工作流,优先使用 Chocolatey 安装 NuGet 并更新 PATH 路径
2025-11-09 04:03:40 -08:00
shanshanzhong147 8cc88be5f6 ci(workflows): 添加Windows构建修复步骤到CI流程
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m37s
Build Windows / build (push) Failing after 7h1m43s
添加NuGet安装、长路径支持、清理构建缓存等步骤
确保Windows环境下的Flutter构建能够成功执行
2025-11-08 23:50:07 -08:00
shanshanzhong147 50f4237c74 ci(workflow): 优化Windows构建流程中的Flutter路径配置
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m42s
Build Windows / build (push) Failing after 7h2m38s
简化Flutter路径的配置逻辑,直接使用固定路径C:\flutter\bin
在关键步骤前确保Flutter路径已正确设置
2025-11-08 23:01:24 -08:00
shanshanzhong147 deac0adabd feat(CI): 添加Flutter安装脚本并改进Windows构建流程
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m38s
Build Windows / build (push) Failing after 7h0m26s
添加install_flutter_simple.bat脚本用于在Windows上自动安装Flutter
改进docker.yml中的Windows构建步骤,增加Flutter路径检测和powershell支持
2025-11-08 22:01:00 -08:00
shanshanzhong147 4f9d405c9f ci: 移除无用的Flutter设置步骤
Build Windows / build (push) Failing after 7h0m28s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m37s
2025-11-08 19:40:46 -08:00
shanshanzhong147 88091e84c0 ci: 移除不再需要的Flutter安装脚本并修正CI文件格式
移除install_flutter.bat脚本,因为Flutter安装已不再需要
修正docker.yml文件中的换行符问题
2025-11-08 10:05:31 -08:00
shanshanzhong147 fafad1ff97 ci(workflows): 移除Flutter版本固定并启用Windows桌面支持
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m15s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m17s
Build Windows / build (push) Failing after 7h0m26s
2025-11-08 08:07:28 -08:00
shanshanzhong147 fbcf5f7e61 ci(workflow): 移除不再需要的Flutter容器和版本检查步骤
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m19s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m45s
Build Windows / build (push) Failing after 7h0m25s
2025-11-07 21:25:14 -08:00
shanshanzhong147 b21d189ca1 ci(docker): 添加Flutter容器配置以支持构建
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m18s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 21m25s
Build Windows / build (push) Failing after 6h59m59s
2025-11-07 09:54:12 -08:00
shanshanzhong147 701acd561a ci(workflow): 更新 Flutter 版本至 3.24.3 并添加回退检查
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m20s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m50s
Build Windows / build (push) Failing after 7h0m28s
添加 Windows 平台 Flutter 安装脚本,支持版本 3.35.5
2025-11-07 09:46:37 -08:00
shanshanzhong147 3b419d1e24 ci: 添加测试 Flutter 环境的批处理脚本
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m14s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m38s
Build Windows / build (push) Failing after 7h0m32s
2025-11-07 08:12:46 -08:00
shanshanzhong147 e3b9fea5b2 ci(workflow): 更新Flutter版本至3.35.5并移除旧版本检查步骤 2025-11-07 08:12:19 -08:00
shanshanzhong147 54dd4cbd35 ci(workflow): 更新Flutter版本至3.24.0并添加3.24.5的检出步骤
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m19s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m35s
Build Windows / build (push) Failing after 7h0m30s
2025-11-07 07:34:05 -08:00
shanshanzhong147 77b721df4b ci(workflows): 在Windows环境中添加jq到PATH
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m19s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m34s
Build Windows / build (push) Failing after 7h0m31s
确保在Windows构建环境中能够使用jq工具,以便后续步骤可以正常执行
2025-11-07 06:59:10 -08:00
shanshanzhong147 8937024241 fix: 修复批处理文件中的缩进和错误处理逻辑
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m20s
Build Windows / build (push) Failing after 7h0m33s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m49s
修正 copy_libcore.bat 中的缩进问题,并添加未找到 libcore.dll 时的错误提示
2025-11-07 06:33:15 -08:00
shanshanzhong147 29c6e40940 refactor(copy_libcore): 移除jq安装步骤并简化脚本流程
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m19s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m22s
Build Windows / build (push) Failing after 7h0m26s
2025-11-07 05:18:16 -08:00
shanshanzhong147 f75b109025 ci(docker): 移除Git Extra Header配置并添加jq安装验证
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m14s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m28s
Build Windows / build (push) Failing after 7h0m27s
移除不再需要的Git Extra Header配置步骤,并添加jq工具的安装验证逻辑以确保构建环境依赖完整
2025-11-07 04:54:51 -08:00
shanshanzhong147 eb4db67fa1 ci(docker): 将脚本中的中文注释和输出信息改为英文
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 17s
Build Windows / build (push) Has been skipped
2025-11-07 04:53:22 -08:00
shanshanzhong147 62d3157665 ci(docker): 移除修复Git Extra Header的冗余步骤
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 17s
Build Windows / build (push) Has been skipped
2025-11-07 04:51:43 -08:00
shanshanzhong147 577327c40a ci(workflow): 修复 git extraheader 配置并添加 jq 安装检查
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 15s
Build Windows / build (push) Has been skipped
移除 git 配置中的 extraheader 以避免潜在问题
添加 jq 安装检查并在缺失时通过 Chocolatey 安装
2025-11-07 04:50:51 -08:00
shanshanzhong147 fed0b0e422 fix: 改进jq安装脚本的错误处理和日志输出
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Has been cancelled
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m17s
Build Windows / build (push) Has been cancelled
添加错误日志输出和文件清理逻辑,便于调试安装失败问题
2025-11-07 04:45:09 -08:00
shanshanzhong147 ad5d0c9b7a fix(copy_libcore.bat): 改进jq安装脚本的可靠性和清理逻辑
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m18s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m10s
Build Windows / build (push) Failing after 7h0m29s
将内联的PowerShell命令改为临时脚本文件执行
添加临时文件清理逻辑确保脚本执行后不留残留
2025-11-07 04:10:24 -08:00
shanshanzhong147 9873f670fa ci: 将jq安装步骤移至copy_libcore.bat脚本中
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m16s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m14s
Build Windows / build (push) Failing after 7h0m26s
将jq的安装从docker.yml工作流文件移至copy_libcore.bat脚本中,以简化CI配置并集中管理依赖安装
2025-11-07 03:44:11 -08:00
shanshanzhong147 8b8d29dd00 ci(workflow): 修复docker.yml中的格式问题并保持功能不变
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m6s
Build Windows / build (push) Failing after 7h0m23s
2025-11-07 03:13:12 -08:00
shanshanzhong147 477d4086b2 ci(workflow): 修复Windows环境中jq安装和路径配置问题
修复当choco未安装时jq安装失败的问题,并确保安装后jq可被正确识别
2025-11-07 03:10:06 -08:00
shanshanzhong147 7fc2a60e18 ci(workflow): 添加安装jq步骤并优化libcore复制步骤
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m25s
Build Windows / build (push) Failing after 7h0m22s
2025-11-07 02:34:45 -08:00
shanshanzhong147 41e6ed433a fix(copy_libcore.bat): 增强文件验证逻辑并添加错误处理
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m32s
Build Windows / build (push) Failing after 7h0m22s
添加对 BearVPNCli.exe 和 libcore.dll 的检查,并在验证失败时返回错误码
2025-11-07 01:17:23 -08:00
shanshanzhong147 8b055d9ee1 ci: 修复docker.yml工作流文件的缩进格式
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m14s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m54s
Build Windows / build (push) Failing after 7h0m27s
2025-11-07 00:49:47 -08:00
shanshanzhong147 0808e2db10 ci(workflow): 修复docker.yml中的缩进格式问题 2025-11-07 00:41:21 -08:00
shanshanzhong147 dcc9ad43fe ci: 修复工作流文件中的缩进格式问题 2025-11-07 00:39:58 -08:00
shanshanzhong147 b47e0e984e ci(workflow): 用批处理脚本替换powershell脚本复制libcore文件
简化CI流程中的文件复制操作,使用更简洁的批处理脚本替代原有的powershell脚本
2025-11-07 00:39:16 -08:00
shanshanzhong147 51ed02de1a ci: 修复Windows构建工作流的格式问题并重新组织步骤
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m42s
Build Windows / build (push) Failing after 7h0m20s
2025-11-06 23:57:22 -08:00
shanshanzhong147 e0b1cec87d docs(ci): 修正docker.yml中的注释拼写错误
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m14s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m15s
Build Windows / build (push) Failing after 7h0m25s
2025-11-06 23:28:15 -08:00
shanshanzhong147 a9db68c29b docs(workflow): 修正本地验证作业的注释拼写错误
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m17s
Build Windows / build (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Has been cancelled
2025-11-06 23:17:12 -08:00
shanshanzhong147 db7a776d2b ci(workflow): 修复docker.yml中格式错误并添加Flutter配置
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m17s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m25s
Build Windows / build (push) Failing after 7h0m23s
修复脚本中的格式错误,确保正确换行。同时添加Flutter配置步骤以支持Windows桌面开发
2025-11-06 22:39:06 -08:00
shanshanzhong147 bfa3ec48d6 ci(docker): 更新工作流以兼容不同运行环境
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m16s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m23s
Build Windows / build (push) Failing after 7h0m24s
修改 MinGW 安装脚本以同时支持 GitHub runner 和自托管容器
将 libcore 复制步骤的 shell 从 pwsh 改为 powershell
2025-11-06 22:03:31 -08:00
shanshanzhong147 ca74f9289e ci(docker): 移除 MinGW 安装步骤中的注释
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m12s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m52s
Build Windows / build (push) Failing after 7h0m25s
2025-11-06 21:17:29 -08:00
shanshanzhong147 f9ea310031 ci(workflow): 修复 MinGW 安装步骤的缩进格式 2025-11-06 21:16:47 -08:00
shanshanzhong147 5d849c3b98 ci(workflow): 将powershell改为pwsh以提升兼容性 2025-11-06 21:15:50 -08:00
shanshanzhong147 b7be97f6c1 ci(docker): 为Windows runner添加libcore文件复制条件 2025-11-06 21:14:55 -08:00
shanshanzhong147 7212fd3132 ci(docker): 将powershell命令从pwsh改为powershell 2025-11-06 21:11:19 -08:00
shanshanzhong147 067a715afe ci(docker): 修复工作流中Windows编译任务名称并优化MinGW安装脚本
修复Windows编译任务名称中的多余字符
优化MinGW安装脚本以兼容不同运行环境
2025-11-06 20:23:08 -08:00
shanshanzhong147 ce969a6ad4 ci(workflow): 移除重复的Flutter设置步骤并修复格式
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m15s
Build Windows / 编译 libcore (Windows)1 (20.15.1) (push) Successful in 19m49s
Build Windows / build (push) Failing after 7h0m20s
2025-11-06 20:08:09 -08:00
shanshanzhong147 cea406f660 style(ci): 修正docker.yml中的缩进格式
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m13s
Build Windows / 编译 libcore (Windows)1 (20.15.1) (push) Failing after 10m17s
Build Windows / build (push) Has been skipped
2025-11-06 18:28:08 -08:00
shanshanzhong147 a09245cb3e ci: 移除注释并修复重命名完成消息的格式 2025-11-06 18:23:17 -08:00
shanshanzhong147 bbc1c03cca ci: 移除Windows构建流程中的冗余注释 2025-11-06 18:21:26 -08:00
shanshanzhong147 b3935f8516 ci(workflow): 更新Windows构建流程的分支触发条件
添加dev分支到触发条件中,并优化workflow文件格式
2025-11-06 18:19:11 -08:00
shanshanzhong147 14b95b07b4 chore: 移除旧的GitHub Actions文档并迁移Windows构建配置到Gitea
refactor: 更新Windows构建工作流配置
2025-11-06 18:16:56 -08:00
shanshanzhong147 0e1c043e34 ci(workflow): 将Windows libcore编译任务运行环境改为client-server
Build Windows / 编译 libcore (Windows) (push) Failing after 2m6s
Build Windows / 构建 Windows (push) Has been skipped
2025-11-06 18:09:53 -08:00
shanshanzhong147 cc5a732fa5 ci: 移除废弃的构建工作流并简化多平台构建
Build Windows / 构建 Windows (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
移除 build-clash-core.yml 和 build-android-apk.yml 工作流文件
将 build-multiplatform.yml 重命名为 build-windows.yml 并仅保留 Windows 构建
2025-11-06 18:05:11 -08:00
shanshanzhong147 0e9d1bc157 docs(workflow): 修正构建平台描述中的错别字
Build Android APK / 编译 libcore.aar (push) Failing after 3m32s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been skipped
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
2025-11-06 17:59:33 -08:00
shanshanzhong147 6dfad4544d ci: 添加多平台构建工作流
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Clash Core / Build Android (arm64) (push) Failing after 7s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been skipped
Build Android APK / 编译 libcore.aar (push) Failing after 10s
Build Clash Core / Build Android (armv7) (push) Failing after 7s
Build Clash Core / Build Android (x86_64) (push) Failing after 8s
Build Clash Core / Create Release (push) Has been skipped
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been skipped
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
添加三个 GitHub Actions 工作流文件:
1. build-clash-core.yml - 构建 Android 核心库
2. build-android-apk.yml - 构建 Android APK
3. build-multiplatform.yml - 支持多平台构建(Android/iOS/Windows/macOS/Linux)

工作流支持自动触发和手动触发,包含构建、测试、打包和发布功能
2025-11-06 17:27:25 -08:00
shanshanzhong147 2eaa15cc8f ci: 修复Windows构建工作流中的任务名称错误 2025-11-06 17:18:26 -08:00
shanshanzhong147 5c1449155e ci: 移除旧的构建工作流文件
清理不再使用的 GitHub Actions 工作流文件,包括:
- build-clash-core.yml
- build-android-apk.yml
- build-multiplatform.yml
2025-11-06 17:16:59 -08:00
shanshanzhong147 cc8744a188 ci(workflow): 修复 Windows 构建脚本中的路径分隔符问题
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 6s
Build Android APK / 编译 libcore.aar (push) Failing after 8s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 构建 macOS (push) Has been cancelled
2025-11-06 17:15:54 -08:00
shanshanzhong147 f72ffa6443 chore: 更新logo图片文件命名格式
Build Android APK / 编译 libcore.aar (push) Failing after 7s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Waiting to run
Build Windows / ACT Windows Checkout Verification (push) Successful in 7h0m16s
Build Windows / build (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
删除旧格式的logo图片文件并添加新命名的文件
2025-11-06 09:08:32 -08:00
shanshanzhong147 5e84fea7d0 ci(workflow): 优化 Windows 构建工作流的稀疏检出配置
Build Windows / build (push) Failing after 7h0m16s
Build Android APK / 编译 libcore.aar (push) Failing after 9s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m6s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m17s
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
移除不必要的稀疏检出规则,并针对本地 act 验证优化目录级稀疏检出配置
2025-11-06 09:02:01 -08:00
shanshanzhong147 dce32e706b ci(workflow): 修复 Windows 工作流中稀疏检出配置问题
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m6s
Build Android APK / 编译 libcore.aar (push) Failing after 8s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 10s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
调整稀疏检出配置以解决 Windows 无法签出包含 '*' 的文件名的问题
2025-11-06 08:41:42 -08:00
shanshanzhong147 7e19e2cdb8 ci(workflow): 在Windows构建工作流中添加稀疏检出配置
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m3s
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m5s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 8s
Build Android APK / 编译 libcore.aar (push) Failing after 7s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Windows / build (push) Failing after 7h0m10s
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
排除assets/images/logo-1024*024.png文件以优化检出速度
2025-11-06 05:58:42 -08:00
shanshanzhong147 0e062a275a ci(workflow): 更新 Windows 构建工作流配置
Build Android APK / 编译 libcore.aar (push) Failing after 7s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m5s
Build Windows / build (push) Failing after 7h0m10s
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m7s
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
添加 persist-credentials 选项并允许子模块验证失败
2025-11-06 05:40:58 -08:00
shanshanzhong147 4cc3f98b0f ci(workflows): 添加本地act验证作业以检查Git路径和子模块
Build Android APK / 编译 libcore.aar (push) Failing after 7s
Build Windows / ACT Windows Checkout Verification (push) Failing after 7h0m6s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m38s
Build Windows / build (push) Failing after 7h0m11s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
2025-11-06 05:03:54 -08:00
shanshanzhong147 a6527d822b ci(workflow): 更新Windows构建工作流的Git路径检测逻辑
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 9s
Build Android APK / 编译 libcore.aar (push) Failing after 8s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Windows / build (push) Failing after 7h0m11s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m37s
Build Android APK / 创建 GitHub Release (push) Has been cancelled
扩展Git可执行文件和路径的检测范围,包括32位程序目录
移除冗余的输出信息,简化脚本逻辑
2025-11-06 03:58:56 -08:00
shanshanzhong147 aac7d84602 ci(workflows): 修复Windows构建中Git路径和PATH更新的问题
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m47s
Build Windows / build (push) Failing after 7h0m4s
Build Android APK / 编译 libcore.aar (push) Failing after 8s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
修复Git路径检查使用绝对路径以避免PATH传播时序问题,并确保PATH更新立即生效
2025-11-06 03:32:50 -08:00
shanshanzhong147 f738ba9245 ci(workflow): 在Windows构建流程中添加Git到PATH
Build Android APK / 编译 libcore.aar (push) Failing after 9s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m56s
Build Windows / build (push) Failing after 7h0m4s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
添加PowerShell步骤以将Git的可执行路径添加到系统PATH环境变量中,确保在Windows环境下可以正常使用git命令
2025-11-06 02:55:16 -08:00
shanshanzhong147 89e02cc707 ci: 移除 Windows 构建作业中的冗余条件判断
Build Android APK / 编译 libcore.aar (push) Failing after 10s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 19m50s
Build Windows / build (push) Failing after 7h0m4s
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
2025-11-06 00:54:13 -08:00
shanshanzhong147 d1e45f0254 ci(workflow): 移除 Windows 构建中的 Node.js 安装步骤并添加 runner 条件
Build Android APK / 编译 libcore.aar (push) Failing after 9s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 8s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m6s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Windows / build (push) Has been skipped
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
2025-11-06 00:32:10 -08:00
shanshanzhong147 dbf6175ad9 ci(workflow): 将actions/upload-artifact和actions/download-artifact从v4降级到v3
Build Android APK / 编译 libcore.aar (push) Failing after 8s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 6s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m0s
Build Windows / build (push) Failing after 7h1m17s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
2025-11-06 00:05:46 -08:00
shanshanzhong147 251564a5de ci(workflow): 改进 MinGW 安装脚本以兼容无 sudo 环境
Build Android APK / 编译 libcore.aar (push) Failing after 9s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 6s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 13m53s
Build Windows / build (push) Has been skipped
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
使 MinGW 安装步骤在 GitHub 托管 runner 和 act/自托管容器中均可运行
2025-11-05 23:48:01 -08:00
shanshanzhong147 ef8bba71d5 ci(workflow): 在 Windows 构建流程中添加 Node.js 容器配置
Build Android APK / 编译 libcore.aar (push) Failing after 11s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 8s
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Failing after 5m40s
Build Windows / build (push) Has been skipped
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 构建 macOS (push) Has been cancelled
添加 Node.js 20 容器配置以支持 libcore 的编译环境
2025-11-05 23:40:02 -08:00
shanshanzhong147 961c655a92 docs(workflow): 更新Windows构建工作流的注释
Build Android APK / 编译 libcore.aar (push) Failing after 10s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 9s
Build Windows / 编译 libcore (Windows) (push) Failing after 5s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
2025-11-05 23:33:09 -08:00
shanshanzhong147 4389770821 ci(workflow): 在 Windows 构建流程中添加 Node.js 便携版安装
Build Android APK / 编译 libcore.aar (push) Failing after 12s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 6s
Build Windows / 编译 libcore (Windows) (push) Failing after 5s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
新增 Node.js 便携版安装步骤,避免全局安装依赖
设置 job 级 PATH 确保所有步骤都能访问 Node.js
同时更新代码检出配置以包含子模块
2025-11-05 18:33:00 -08:00
shanshanzhong147 7c9b23edbd ci(workflow): 移除 Windows 构建流程中的 Node.js 相关步骤
Build Android APK / 编译 libcore.aar (push) Failing after 9s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Windows / 编译 libcore (Windows) (push) Failing after 5s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
2025-11-05 18:29:45 -08:00
shanshanzhong147 90fd476c45 ci(workflow): 更新 Windows 构建工作流配置
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Windows / 编译 libcore (Windows) (push) Failing after 9s
Build Android APK / 编译 libcore.aar (push) Failing after 10s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 6s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
- 使用 Node.js 20.x 确保最新稳定补丁
- 添加 npm 缓存以加速构建
- 增加 Node.js 安装验证步骤
2025-11-05 18:25:33 -08:00
shanshanzhong147 7cd360e61e ci(workflow): 调整构建步骤顺序并添加 Node.js 设置
Build Android APK / 编译 libcore.aar (push) Failing after 12s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (push) Failing after 7s
Build Windows / build (push) Has been skipped
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
将 Node.js 设置步骤提前到构建流程的开始,确保后续步骤能正确使用 Node.js 环境
2025-11-05 18:14:17 -08:00
shanshanzhong147 6e189671c7 ci: 将工作流的运行环境从默认改为client-server
Build Android APK / 编译 libcore.aar (push) Failing after 3m16s
Build Android APK / 编译 Android APK (release) (push) Has been skipped
Build Clash Core / Build Android (arm64) (push) Failing after 20s
Build Clash Core / Build Android (armv7) (push) Failing after 6s
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Failing after 7s
Build Windows / 编译 libcore (Windows) (push) Failing after 6s
Build Windows / build (push) Has been skipped
Build Clash Core / Create Release (push) Has been skipped
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Clash Core / Build Android (x86_64) (push) Failing after 8s
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
2025-11-05 18:06:45 -08:00
greatsage 4fbdb331d4 优化节点列表拉取可能存在失败的可能
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
(cherry picked from commit f59e70ed8b9084d29f792280d94f1c49719842a1)
2025-11-04 03:11:56 -08:00
sepakeloudest 6131a80b2c feat: 优化未连接节点时候批量节点测速功能,修复网络初始化报错后,导致的连锁反应界面出现错乱和DioExceptionType.unknown报错信息,直连模式,不依赖未初始化的核心
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
2025-11-04 03:08:24 -08:00
sepakeloudest 33f45aa4a5 feat: macos启动
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
2025-11-04 02:51:28 -08:00
sepakeloudest 4dbcaff187 feat: ios启动
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
2025-11-03 23:55:09 -08:00
sepakeloudest 9e05a17fc4 feat: ios启动
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
2025-11-03 23:54:18 -08:00
sepakeloudest 1a9f0d79ac 1. 删除了 _kr_handleSelectorProxy 中会导致死循环的重选逻辑
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
2. 简化了 _kr_handleManualMode,只更新 UI 不触发重选
2025-11-03 00:48:15 -08:00
sepakeloudest c7b77c1ad8 解决kr_start() 方法中缺少对分组数据流的订阅
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
2025-11-02 17:41:31 -08:00
greatsage 7cd022093b 修改 KRSecureStorage 类,确保每次操作前 box 都是打开状态。目前解决了从新打开app登录状态失效
(cherry picked from commit ab22be112a1753e5063799b5424f5d3feef06e2d)
2025-11-02 05:13:01 -08:00
greatsage 7a223d614b 安卓15部分机型出现界面不兼容并且UI库有BUG,MD
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
(cherry picked from commit 010405edda74bdb0251dcff2e32482edae2c9976)
2025-11-02 02:50:55 -08:00
greatsage 0ec2f72a93 彻底解决在安卓15部分机型出现界面不兼容等问题
(cherry picked from commit fc31fc6e5ee3a7aefa8928bb40d164282e4edf90)
2025-11-02 02:48:03 -08:00
greatsage 1a1c692ae0 update
(cherry picked from commit e2afe9f5080258d62873034b7ae372f2d813ca5d)
2025-11-02 02:46:37 -08:00
greatsage dee7f0a591 优化部分安卓机型可能存在连接超时等问题新增日志排查
(cherry picked from commit e0fcc27f28f27321a49115df86507e3ac55e8ef8)
2025-11-02 02:46:36 -08:00
111 changed files with 3112 additions and 3833 deletions
+434
View File
@@ -0,0 +1,434 @@
name: Build Windows
run-name: 构建Win流程
on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev
jobs:
# 先编译 libcore
build-libcore:
name: 编译 libcore (Windows)
runs-on: client-server
container:
image: node:20
strategy:
matrix:
# 只有node支持版本号别名
node: ['20.15.1']
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 安装 MinGW
run: |
# 在 GitHub 托管 runner(有 sudo)与 act/自托管容器(无 sudo)均可运行
if command -v sudo >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y mingw-w64
else
echo "sudo 不存在,按 root 用户直接执行 apt-get"
export DEBIAN_FRONTEND=noninteractive
apt-get update || apt update
apt-get install -y mingw-w64 || apt install -y mingw-w64
fi
- name: 📦 编译 libcore.dll
working-directory: libcore
run: |
echo "🚀 开始编译 Windows libcore..."
make windows-amd64
if [ -f "bin/libcore.dll" ] && [ -f "bin/HiddifyCli.exe" ]; then
echo "✅ Windows libcore 编译成功"
ls -lh bin/
else
echo "❌ Windows libcore 编译失败"
exit 1
fi
- name: 📤 上传 Windows libcore
uses: actions/upload-artifact@v3
with:
name: libcore-windows
path: |
libcore/bin/libcore.dll
libcore/bin/HiddifyCli.exe
libcore/bin/webui/**
retention-days: 7
# 构建 Windows 应用
build:
runs-on: windows-latest
needs: build-libcore
steps:
- name: 🔧 Add Git to PATH (Windows)
if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
$paths = @(
'C:\Program Files\Git\cmd',
'C:\Program Files\Git\bin',
'C:\Program Files (x86)\Git\cmd',
'C:\Program Files (x86)\Git\bin'
)
foreach ($p in $paths) {
if (Test-Path $p) {
Add-Content -Path $env:GITHUB_PATH -Value $p
$env:PATH = "$p;$env:PATH"
Write-Host ("Added to PATH: {0}" -f $p)
}
}
$candidates = @(
'C:\Program Files\Git\cmd\git.exe',
'C:\Program Files\Git\bin\git.exe',
'C:\Program Files (x86)\Git\cmd\git.exe',
'C:\Program Files (x86)\Git\bin\git.exe'
)
$found = $false
foreach ($g in $candidates) {
if (Test-Path $g) {
& $g --version
$found = $true
break
}
}
if (-not $found) {
Write-Host "Git executable not found in common locations; continuing."
}
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 📥 下载 libcore
uses: actions/download-artifact@v3
with:
name: libcore-windows
path: .
- name: 🔧 复制 libcore 文件到正确位置并重命名
shell: cmd
run: call copy_libcore.bat
- name: 🔍 Verify jq Installation (ACT)
shell: powershell
run: |
# Check if jq is available
$jqFound = $false
try {
$version = jq --version 2>&1
if ($version -match 'jq-[\d\.]+') {
Write-Host "jq is already installed: $version"
$jqFound = $true
}
} catch {
Write-Host "jq not installed or not in PATH"
}
if (-not $jqFound) {
Write-Host "Preparing to install jq..."
# Check if Chocolatey is available
$chocoFound = $false
try {
choco --version 2>&1 | Out-Null
$chocoFound = $true
} catch {}
if (-not $chocoFound) {
Write-Host "Installing Chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
# Refresh PATH
$env:PATH = [System.Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';' + [System.Environment]::GetEnvironmentVariable('PATH', 'User')
Write-Host "Chocolatey installed successfully"
}
Write-Host "Installing jq using Chocolatey..."
choco install jq -y
if ($LASTEXITCODE -eq 0) {
Write-Host "jq installed successfully"
# Verify again
$version = jq --version 2>&1
Write-Host "jq version: $version"
} else {
Write-Host "jq installation failed, exit code: $LASTEXITCODE"
exit 1
}
}
- name: Add jq to PATH
shell: powershell
run: |
$jqPath = "C:\ProgramData\chocolatey\bin"
if (Test-Path $jqPath) {
Add-Content -Path $env:GITHUB_PATH -Value $jqPath
$env:PATH = "$jqPath;$env:PATH"
Write-Host "Added jq path to GITHUB_PATH and current PATH"
} else {
Write-Host "jq installation path not found"
exit 1
}
- name: Add Flutter to PATH
shell: powershell
run: |
# Add Flutter to PATH for current session and GitHub Actions
$flutterPath = "C:\flutter\bin"
if (Test-Path $flutterPath) {
Write-Host "Adding Flutter to PATH: $flutterPath"
$env:PATH = "$flutterPath;$env:PATH"
Add-Content -Path $env:GITHUB_PATH -Value $flutterPath
# Verify Flutter is accessible
$flutterVersion = flutter --version 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "Flutter verified: $flutterVersion"
} else {
Write-Host "Flutter not found at $flutterPath"
exit 1
}
} else {
Write-Host "ERROR: Flutter not found at C:\flutter\bin"
exit 1
}
- name: Enable Windows desktop
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;$env:PATH"
flutter config --enable-windows-desktop
- name: Get dependencies
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;$env:PATH"
flutter pub get
- name: Generate code
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;$env:PATH"
dart run build_runner build --delete-conflicting-outputs
- name: Install NuGet
shell: powershell
run: |
Write-Host "Installing NuGet..."
# Check if NuGet is already available
$nugetPath = Get-Command nuget -ErrorAction SilentlyContinue
if ($nugetPath) {
Write-Host "NuGet already installed: $($nugetPath.Source)"
$nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
Write-Host "NuGet version: $nugetVersion"
return
}
# Use Chocolatey to install NuGet (proven to work)
Write-Host "Installing NuGet via Chocolatey..."
choco install nuget.commandline -y
# Update PATH to include Chocolatey
$env:PATH = "C:\ProgramData\chocolatey\bin;$env:PATH"
Add-Content -Path $env:GITHUB_PATH -Value "C:\ProgramData\chocolatey\bin"
# Verify installation
if (Get-Command nuget -ErrorAction SilentlyContinue) {
Write-Host "NuGet installed successfully via Chocolatey"
$nugetVersion = nuget help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
Write-Host "NuGet version: $nugetVersion"
} else {
Write-Host "WARNING: NuGet installation may have failed, but continuing..."
}
- name: Fix long paths
shell: powershell
run: |
Write-Host "Enabling long path support..."
# Enable long paths in Windows
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force
# Also set for current user
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\AppModel\StateRepository\Cache\Package\Data\" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force -ErrorAction SilentlyContinue
Write-Host "Long path support enabled"
- name: Clean build cache
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;$env:PATH"
Write-Host "Cleaning build cache..."
flutter clean
Write-Host "Removing old build directories..."
if (Test-Path "build") {
Remove-Item -Path "build" -Recurse -Force
}
if (Test-Path "windows") {
Remove-Item -Path "windows" -Recurse -Force
}
Write-Host "Recreating Windows project..."
flutter create --platforms=windows .
- name: Build Windows Debug
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
flutter build windows
- name: Build Windows Release
shell: powershell
run: |
$env:PATH = "C:\flutter\bin;C:\ProgramData\chocolatey\bin;$env:PATH"
flutter build windows --release
- name: Upload Debug build artifacts
uses: actions/upload-artifact@v3
with:
name: windows-debug-build
path: build/windows/x64/runner/Debug/
- name: Upload Release build artifacts
uses: actions/upload-artifact@v3
with:
name: windows-release-build
path: build/windows/x64/runner/Release/
- name: Install Build Tools
shell: powershell
run: |
choco install 7zip -y
choco install enigma-virtual-box -y
- name: Package Single EXE
shell: powershell
run: |
Write-Host "=== 开始打包单文件 EXE ==="
$buildPath = "build\windows\x64\runner\Release"
$outputPath = "dist"
$enigmaPath = "C:\Program Files\Enigma Virtual Box\enigmavb.exe"
# 创建输出目录
if (-not (Test-Path $outputPath)) {
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
}
# 获取主程序
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
if (-not $exeFile) {
Write-Host "❌ 未找到可执行文件"
exit 1
}
$inputExe = $exeFile.FullName
$outputExe = "$outputPath\$($exeFile.BaseName)_Single.exe"
Write-Host "主程序: $inputExe"
Write-Host "输出: $outputExe"
# 尝试使用 Enigma Virtual Box
if (Test-Path $enigmaPath) {
Write-Host "使用 Enigma Virtual Box 打包..."
# 创建配置文件
$configContent = "[Config]`nInputFile=$inputExe`nOutputFile=$outputExe`nFiles=%DEFAULT FOLDER%`nVirtualizationMode=Never Write To Disk`nCompression=Yes`nShareVirtualSystem=Yes`n`n[Files]`nFolder=$buildPath\*"
$configFile = "$outputPath\package_config.evb"
Set-Content -Path $configFile -Value $configContent
# 执行打包
$process = Start-Process -FilePath $enigmaPath -ArgumentList "/sf", $inputExe, "/lf", $outputExe, "/folder", $buildPath, "/compress" -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0) {
Write-Host "✅ 单文件打包成功!"
# 显示压缩信息
$originalSize = (Get-Item $inputExe).Length / 1MB
$packedSize = (Get-Item $outputExe).Length / 1MB
Write-Host "原始大小: $([math]::Round($originalSize, 2)) MB"
Write-Host "打包大小: $([math]::Round($packedSize, 2)) MB"
} else {
Write-Host "⚠️ Enigma 打包失败,使用备选方案"
exit 1
}
} else {
Write-Host "⚠️ Enigma 未找到,使用 7-Zip 自解压方案"
exit 1
}
- name: Package with 7-Zip Alternative
if: failure()
shell: powershell
run: |
Write-Host "使用 7-Zip 自解压方案..."
$buildPath = "build\windows\x64\runner\Release"
$outputPath = "dist"
# 检查 7-Zip
$7zipPath = "C:\Program Files\7-Zip\7z.exe"
# 获取主程序名称
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
$outputSfx = "$outputPath\$($exeFile.BaseName)_Package.exe"
Write-Host "创建自解压包..."
# 创建配置文件
$configContent = @"
;!@Install@!UTF-8!
Title="HostExecutor Windows Package"
BeginPrompt="正在解压 HostExecutor..."
ExtractDialogText="请稍候,正在解压文件..."
ExtractPathText="解压路径:"
ExtractTitle="解压中"
FinishMessage="解压完成!"
GUIFlags="8"
;!@InstallEnd@!
"@
$configFile = "$outputPath\config.txt"
Set-Content -Path $configFile -Value $configContent -Encoding UTF8
# 创建压缩包
& $7zipPath a -sfx7z.sfx -r "$outputSfx" "$buildPath\*" -scsUTF-8 -y
Copy-Item "$configFile" -Destination "$outputSfx" -Force
if (Test-Path $outputSfx) {
Write-Host "✅ 7-Zip 自解压包创建成功!"
Write-Host "输出文件: $outputSfx"
$size = (Get-Item $outputSfx).Length / 1MB
Write-Host "文件大小: $([math]::Round($size, 2)) MB"
} else {
Write-Host "❌ 7-Zip 打包失败"
}
- name: Upload Single EXE Package
uses: actions/upload-artifact@v3
with:
name: windows-single-exe
path: dist/*.exe
if: always()
-311
View File
@@ -1,311 +0,0 @@
# 📖 GitHub Actions 构建完全指南
## 🎯 功能概述
本 workflow 支持:
**自动编译 libcore.aar** - sing-box 核心库
**Release 构建** - 默认生成正式版 APK
**可配置 API 域名** - 支持自定义后端域名
**可配置 OSS 地址** - 支持自定义配置文件 CDN
**分架构打包** - 生成 arm64-v8a / armeabi-v7a / x86_64 版本
**自动创建 Release** - 推送标签自动发布
---
## 🚀 使用方法
### 方法一:手动触发(推荐,支持自定义配置)
1. **打开 Actions 页面**
- 进入 GitHub 仓库
- 点击顶部 **Actions** 标签
2. **选择 Workflow**
- 左侧选择 **Build Android APK**
- 右侧点击 **Run workflow** 下拉框
3. **配置参数**
| 参数 | 说明 | 默认值 |
|-----|------|--------|
| **构建类型** | debug 或 release | `release` |
| **API 域名** | 后端 API 服务器域名 | `api.maodag.top` |
| **OSS 地址 1** | 配置文件 CDN 地址(香港) | `https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt` |
| **OSS 地址 2** | 配置文件 CDN 地址(东京) | `https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt` |
| **OSS 地址 3** | 配置文件 CDN 地址(首尔) | `https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt` |
| **OSS 地址 4** | 配置文件 CDN 地址(新加坡) | `https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt` |
4. **开始构建**
- 点击绿色 **Run workflow** 按钮
- 等待约 30 分钟完成
5. **下载 APK**
- 构建完成后,在运行记录页面找到 **Artifacts** 区域
- 下载对应架构的 APK
---
### 方法二:推送代码自动构建(使用默认配置)
```bash
# 提交代码
git add .
git commit -m "feat: 新功能"
# 推送到 main 分支
git push origin main
```
**注意:** 自动触发的构建使用默认配置(`api.maodag.top` 和默认 OSS 地址)
---
### 方法三:创建 Release 版本
```bash
# 1. 打标签(必须以 v 开头)
git tag v1.0.0
# 2. 推送标签
git push origin v1.0.0
# 3. 自动触发构建并创建 Release
# 访问 https://github.com/你的用户名/LighthouseApp/releases 查看
```
---
## 📦 构建产物
### APK 命名规则
```
BearVPN-{架构}-{类型}-{日期}-{提交哈希}.apk
```
**示例:**
```
BearVPN-arm64-v8a-release-20251027-abc1234.apk
BearVPN-armeabi-v7a-release-20251027-abc1234.apk
BearVPN-x86_64-release-20251027-abc1234.apk
```
### 架构说明
| 架构 | 适用设备 | 推荐度 |
|------|---------|-------|
| **arm64-v8a** | 2017年后的现代手机 | ⭐⭐⭐⭐⭐ |
| **armeabi-v7a** | 2012-2017年的老旧手机 | ⭐⭐ |
| **x86_64** | Android 模拟器 | ⭐⭐⭐ |
**大多数用户应下载 `arm64-v8a` 版本**
---
## 🔧 配置示例
### 示例 1:修改 API 域名
如果你的后端部署在 `api.example.com`
1. 手动触发 workflow
2.**API 域名** 改为 `api.example.com`
3. OSS 地址保持默认
4. 点击 Run workflow
### 示例 2:使用自己的 CDN
如果你有自己的配置文件 CDN
1. 手动触发 workflow
2. API 域名保持默认
3. 修改 **OSS 地址 1-4** 为你的 CDN 地址,例如:
- OSS 地址 1: `https://cdn1.example.com/config.txt`
- OSS 地址 2: `https://cdn2.example.com/config.txt`
- OSS 地址 3: `https://cdn3.example.com/config.txt`
- OSS 地址 4: `https://cdn4.example.com/config.txt`
4. 点击 Run workflow
### 示例 3:完全自定义配置
```yaml
构建类型: release
API 域名: api.mycompany.com
OSS 地址 1: https://config.mycdn.com/v1/nodes.txt
OSS 地址 2: https://backup1.mycdn.com/v1/nodes.txt
OSS 地址 3: https://backup2.mycdn.com/v1/nodes.txt
OSS 地址 4: https://backup3.mycdn.com/v1/nodes.txt
```
---
## ⏱️ 构建时间
| 阶段 | 时间 |
|-----|------|
| 编译 libcore.aar | 10-15 分钟 |
| 编译 Flutter APK | 15-20 分钟 |
| **总计** | **约 30 分钟** |
---
## 🔍 查看构建日志
1. 打开 Actions 页面
2. 点击对应的运行记录
3. 点击具体的 job(如 "编译 Android APK"
4. 展开步骤查看详细日志
**关键步骤:**
- `⚙️ 配置 API 域名和 OSS 地址` - 查看配置是否正确替换
- `🔨 构建 APK` - 查看编译过程
- `📦 重命名 APK 文件` - 查看生成的文件名和 MD5
---
## 🐛 常见问题
### Q1: 如何验证配置是否生效?
**A:** 查看 `⚙️ 配置 API 域名和 OSS 地址` 步骤的日志:
```
🔧 配置构建参数:
API 域名: api.example.com
OSS 地址 1: https://cdn1.example.com/config.txt
...
✅ 配置替换完成
📄 查看修改后的配置:
static List<String> kr_baseDomains = ["api.example.com","api.example.com"];
static String kr_currentDomain = "api.example.com";
```
如果看到你设置的域名,说明配置成功。
---
### Q2: Release 构建和 Debug 构建有什么区别?
| 特性 | Debug | Release |
|-----|-------|---------|
| **文件大小** | 较大 | 较小(优化后) |
| **性能** | 较慢 | 快 |
| **调试信息** | 包含 | 移除 |
| **代码混淆** | 无 | 有 |
| **适用场景** | 开发测试 | 正式发布 |
**推荐:** 生产环境使用 **release** 构建
---
### Q3: 如何使用环境变量配置(不想每次手动输入)?
在仓库 **Settings → Secrets and variables → Actions → Variables** 添加:
| 变量名 | 值 |
|-------|---|
| `DEFAULT_API_DOMAIN` | `api.example.com` |
| `DEFAULT_OSS_URL_1` | `https://cdn1.example.com/config.txt` |
| `DEFAULT_OSS_URL_2` | `https://cdn2.example.com/config.txt` |
| `DEFAULT_OSS_URL_3` | `https://cdn3.example.com/config.txt` |
| `DEFAULT_OSS_URL_4` | `https://cdn4.example.com/config.txt` |
然后修改 workflow 文件,将默认值改为:
```yaml
default: ${{ vars.DEFAULT_API_DOMAIN || 'api.maodag.top' }}
```
---
### Q4: 构建失败 - "libcore.aar not found"
**原因:** libcore 编译失败
**解决:**
1. 检查 `build-libcore` job 的日志
2. 确认 Go 环境和 gomobile 安装成功
3. 确认 libcore 子模块已正确初始化
---
### Q5: 如何配置签名(Release 构建必需)?
详见主文档 `.github/workflows/README.md` 的签名配置章节。
---
## 💡 高级技巧
### 技巧 1:同时构建多个版本
修改 `build-apk` job
```yaml
strategy:
matrix:
build_type: [debug, release]
api_domain: ['api.maodag.top', 'api.example.com']
```
这样会生成 4 个 APK(2种类型 × 2个域名)
---
### 技巧 2:添加构建完成通知
在 workflow 最后添加:
```yaml
- name: 📢 发送 Telegram 通知
if: success()
run: |
curl -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \
-d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} \
-d text="✅ BearVPN 构建成功!下载: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
```
需要先配置 `TELEGRAM_BOT_TOKEN``TELEGRAM_CHAT_ID` Secrets。
---
### 技巧 3:缓存加速构建
workflow 已配置 Go 和 Flutter 缓存,首次构建约 30 分钟,后续构建可缩短至 15-20 分钟。
---
## 📊 构建状态徽章
在 README.md 中添加:
```markdown
![Build Status](https://github.com/你的用户名/LighthouseApp/actions/workflows/build-android-apk.yml/badge.svg)
```
效果:![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
---
## 🔗 相关文件
- **主 Workflow:** `.github/workflows/build-android-apk.yml`
- **配置文件:** `lib/app/common/app_config.dart`
- **libcore 源码:** `libcore/` 子模块
---
## 📞 需要帮助?
- 查看 [GitHub Actions 文档](https://docs.github.com/actions)
- 查看构建日志排查问题
- 提交 Issue 到仓库
---
**生成时间:** 2025-10-27
**作者:** Claude Code
**版本:** 1.0.0
-366
View File
@@ -1,366 +0,0 @@
# 🎯 如何在 GitHub 上构建你的应用
## 📋 前提条件
✅ 已将配置推送到 GitHub
✅ 有 GitHub 账号访问权限
---
## 🚀 方法一:手动触发构建(推荐新手)
### 步骤 1: 访问 GitHub Actions 页面
1. 打开浏览器,访问你的仓库:
```
https://github.com/你的用户名/LighthouseApp
```
2. 点击顶部导航栏的 **Actions** 标签
```
Code Issues Pull requests Actions Projects Wiki Security Insights
↑ 点这里
```
---
### 步骤 2: 选择 Workflow
在左侧栏看到可用的 workflows:
```
All workflows
├── Build Android APK ← 仅构建 Android
├── Build Multi-Platform ← 构建所有平台 ⭐推荐
└── Build Clash Core
```
**选择建议:**
- 🟢 **首次测试:** 选择 **Build Android APK**(快速)
- 🔵 **正式发布:** 选择 **Build Multi-Platform**(全平台)
---
### 步骤 3: 运行 Workflow
1. 点击选择的 workflow 名称
2. 右侧出现 **"Run workflow"** 下拉按钮
```
[Run workflow ▼]
```
3. 点击下拉按钮,展开配置面板
---
### 步骤 4: 配置参数
#### 如果选择 "Build Android APK"
```yaml
┌─────────────────────────────────────────┐
│ Run workflow │
├─────────────────────────────────────────┤
│ Use workflow from │
│ Branch: main [▼] │
│ │
│ 构建类型 │
│ ○ debug │
│ ● release │
│ │
│ API 域名 │
│ [api.maodag.top________________] │
│ │
│ OSS 配置地址 1 │
│ [https://ppp2.oss-cn-hongkong...] │
│ │
│ OSS 配置地址 2 │
│ [https://xgp3.oss-ap-northeast-1...] │
│ │
│ OSS 配置地址 3 │
│ [https://xpp4.oss-ap-northeast-2...] │
│ │
│ OSS 配置地址 4 │
│ [https://xpp5.oss-ap-southeast-1...] │
│ │
│ [Cancel] [Run workflow] │
└─────────────────────────────────────────┘
```
**配置说明:**
- **构建类型:** 选择 `release`(生产环境)
- **API 域名:** 填写你的后端域名(默认 `api.maodag.top`
- **OSS 地址:** 保持默认或填写你的 CDN 地址
#### 如果选择 "Build Multi-Platform"
额外多一个参数:
```yaml
│ 构建平台 │
│ [android,windows,macos,linux______] │
```
**选项:**
- `android` - 仅 Android
- `windows` - 仅 Windows
- `macos` - 仅 macOS
- `linux` - 仅 Linux
- `android,windows` - Android + Windows
- `android,windows,macos,linux` - 全部平台 ⭐
---
### 步骤 5: 开始构建
1. 检查所有参数是否正确
2. 点击绿色的 **"Run workflow"** 按钮
3. 页面刷新,顶部出现黄色进度条:
```
⚠️ Build Android APK #1
Queued - This workflow is in queue waiting to run
```
4. 几秒后变为蓝色(运行中):
```
🔵 Build Android APK #1
In progress - This workflow is currently running
```
---
### 步骤 6: 监控构建进度
1. 点击运行记录(蓝色行)
2. 看到构建阶段:
```
编译 libcore.aar 🔵 Running (15分钟)
编译 Android APK ⏸️ Pending
```
3. 可以展开查看实时日志:
```
▼ 编译 libcore.aar
▼ 📦 编译 libcore.aar
🚀 开始编译 libcore...
[gomobile] installing...
✅ libcore.aar 生成成功
```
4. 等待所有阶段完成(约 30-85 分钟)
---
### 步骤 7: 下载构建产物
构建成功后:
1. 向下滚动到 **Artifacts** 区域
```
📦 Artifacts
Produced during runtime
Name Size Expires
apk-arm64-v8a-release 42.5 MB in 30 days [Download]
apk-armeabi-v7a-release 38.2 MB in 30 days [Download]
apk-x86_64-release 45.1 MB in 30 days [Download]
```
2. 点击 **[Download]** 下载对应文件
3. 下载的是 ZIP 文件,解压后得到 APK:
```
apk-arm64-v8a-release.zip
└── BearVPN-android-arm64-v8a-release-20251027-abc1234.apk
```
---
## 🏷️ 方法二:推送标签自动构建
这种方式会自动构建并创建 GitHub Release。
### 步骤 1: 在本地打标签
```bash
cd /Users/mac/Project/Dart/LighthouseApp
# 创建标签(版本号必须以 v 开头)
git tag v1.0.0
# 查看标签
git tag
```
---
### 步骤 2: 推送标签到 GitHub
```bash
git push origin v1.0.0
```
**输出:**
```
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 160 bytes | 160.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To github.com:你的用户名/LighthouseApp.git
* [new tag] v1.0.0 -> v1.0.0
```
---
### 步骤 3: 自动触发构建
1. 推送标签后,GitHub 自动检测到标签
2. 触发 **Build Multi-Platform** workflow
3. 使用默认配置构建所有平台
---
### 步骤 4: 查看构建进度
1. 访问 Actions 页面
2. 看到自动创建的构建任务:
```
🔵 Build Multi-Platform
v1.0.0
```
---
### 步骤 5: 下载 Release
构建成功后:
1. 访问 **Releases** 页面:
```
https://github.com/你的用户名/LighthouseApp/releases
```
2. 看到新创建的 Release
```
📦 v1.0.0
Latest Pre-release
🎉 BearVPN 多平台版本发布
Assets (7)
├── BearVPN-android-arm64-v8a-release-*.apk 42.5 MB
├── BearVPN-android-armeabi-v7a-release-*.apk 38.2 MB
├── BearVPN-android-x86_64-release-*.apk 45.1 MB
├── BearVPN-windows-x64-release-*.zip 52.3 MB
├── BearVPN-macos-release-*.zip 48.7 MB
├── BearVPN-linux-x64-release-*.tar.gz 45.9 MB
└── Source code (zip)
```
3. 直接下载需要的文件
---
## ⏱️ 构建时间参考
| Workflow | 平台 | 时间 |
|---------|------|------|
| Build Android APK | Android | 30 分钟 |
| Build Multi-Platform | Android | 35 分钟 |
| Build Multi-Platform | Windows | 30 分钟 |
| Build Multi-Platform | macOS | 35 分钟 |
| Build Multi-Platform | Linux | 30 分钟 |
| Build Multi-Platform | 全部平台 | **60-85 分钟** |
**提示:** 平台是并行构建的,不是累加时间。
---
## 🎯 推荐流程
### 首次测试(验证流程)
```
1. 选择 "Build Android APK"
2. 使用默认配置
3. 运行构建
4. 等待 30 分钟
5. 下载 arm64-v8a APK
6. 安装测试
```
### 正式发布(生产环境)
```
1. 确保代码已测试
2. 本地打标签: git tag v1.0.0
3. 推送标签: git push origin v1.0.0
4. 等待 60-85 分钟
5. 在 Releases 页面下载所有平台
6. 分发给用户
```
---
## 🐛 常见问题
### Q1: 找不到 "Run workflow" 按钮
**原因:** 可能还在查看历史运行记录
**解决:**
1. 点击左侧的 workflow 名称
2. 确保在 workflow 主页面
3. 右侧会出现 "Run workflow" 按钮
---
### Q2: 构建失败
**排查步骤:**
1. 点击失败的运行记录
2. 展开红色的步骤
3. 查看错误日志
4. 常见错误:
- libcore 编译失败 → 检查 Go 环境
- APK 构建失败 → 检查 Flutter 依赖
---
### Q3: Artifacts 下载后是空的
**原因:** 构建可能失败
**解决:**
1. 检查构建日志
2. 确保所有步骤都是绿色 ✅
3. 重新运行构建
---
### Q4: 如何修改 API 域名
**方法 1:** 手动触发时修改参数
**方法 2:** 修改代码中的默认值
```dart
// lib/app/common/app_config.dart
static String kr_currentDomain = "api.example.com";
```
---
## 📞 需要帮助?
- **查看详细文档:** `.github/workflows/INDEX.md`
- **快速开始:** `.github/workflows/QUICKSTART.md`
- **问题反馈:** GitHub Issues
---
**准备好了吗?立即开始构建!** 🚀
-318
View File
@@ -1,318 +0,0 @@
# 📚 GitHub Actions 构建系统总览
## 🎯 快速导航
| 文档 | 用途 | 适合人群 |
|-----|------|---------|
| **[QUICKSTART.md](./QUICKSTART.md)** | 3步快速开始 | 新手 |
| **[README.md](./README.md)** | 基础说明 | 所有人 |
| **[BUILD_GUIDE.md](./BUILD_GUIDE.md)** | Android 详细指南 | Android 开发者 |
| **[MULTIPLATFORM_GUIDE.md](./MULTIPLATFORM_GUIDE.md)** | 多平台构建指南 | 全平台开发者 |
---
## 📋 可用的 Workflows
### 1. `build-android-apk.yml` - Android 专用构建
**功能:**
- ✅ 编译 libcore.aar
- ✅ 构建 Android APK (arm64/armv7/x86_64)
- ✅ 配置 API 域名和 OSS 地址
- ✅ Release 构建
**触发条件:**
- 推送到 main/develop 分支
- 创建 v* 标签
- 手动触发
**文档:** [BUILD_GUIDE.md](./BUILD_GUIDE.md)
---
### 2. `build-multiplatform.yml` - 多平台构建 ⭐推荐
**功能:**
- ✅ Android APK
- ✅ Windows 可执行文件
- ✅ macOS 应用
- ✅ Linux 可执行文件
- ✅ 可选择构建平台
- ✅ 统一配置管理
**触发条件:**
- 推送到 main/develop 分支
- 创建 v* 标签
- 手动触发
**文档:** [MULTIPLATFORM_GUIDE.md](./MULTIPLATFORM_GUIDE.md)
---
### 3. `build-clash-core.yml` - Clash 核心编译
**功能:**
- 编译 Clash Meta 核心
- 支持多架构 (arm64/armv7/x86_64)
**触发条件:**
- core/ 目录变更
- 手动触发
---
## 🚀 使用建议
### 场景 1: 日常开发(仅 Android
**使用:** `build-android-apk.yml`
```bash
# 推送代码自动触发
git push origin main
```
**时间:** 约 30 分钟
**产物:** 3 个 Android APK
---
### 场景 2: 正式发布(所有平台)
**使用:** `build-multiplatform.yml`
```bash
# 1. 打标签
git tag v1.0.0
git push origin v1.0.0
# 2. 自动构建所有平台并创建 Release
```
**时间:** 约 60-85 分钟(并行)
**产物:** Android + Windows + macOS + Linux
---
### 场景 3: 测试特定平台
**使用:** `build-multiplatform.yml` 手动触发
```yaml
构建平台: android,windows # 只构建这两个
```
**时间:** 约 35 分钟
**产物:** 指定平台
---
## 📦 构建产物对比
### Android 专用构建
```
BearVPN-android-arm64-v8a-release-20251027-abc1234.apk
BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk
BearVPN-android-x86_64-release-20251027-abc1234.apk
```
### 多平台构建
```
# Android
BearVPN-android-arm64-v8a-release-20251027-abc1234.apk
BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk
BearVPN-android-x86_64-release-20251027-abc1234.apk
# Windows
BearVPN-windows-x64-release-20251027-abc1234.zip
# macOS
BearVPN-macos-release-20251027-abc1234.zip
# Linux
BearVPN-linux-x64-release-20251027-abc1234.tar.gz
```
---
## ⚙️ 配置参数说明
### 所有 Workflow 通用参数
| 参数 | 默认值 | 说明 |
|-----|-------|------|
| **构建类型** | `release` | debug 或 release |
| **API 域名** | `api.maodag.top` | 后端服务器地址 |
| **OSS 地址 1** | 香港 CDN | 配置文件源 |
| **OSS 地址 2** | 东京 CDN | 备用配置源 |
| **OSS 地址 3** | 首尔 CDN | 备用配置源 |
| **OSS 地址 4** | 新加坡 CDN | 备用配置源 |
### 多平台专用参数
| 参数 | 默认值 | 说明 |
|-----|-------|------|
| **构建平台** | `android,windows,macos,linux` | 选择构建的平台 |
---
## ⏱️ 构建时间对比
| Workflow | 单平台 | 全平台 |
|---------|-------|-------|
| **Android 专用** | 30分钟 | - |
| **多平台** | 30-40分钟 | 60-85分钟 |
---
## 🎯 选择 Workflow 的建议
### 选择 `build-android-apk.yml` 如果:
- ✅ 只需要 Android 版本
- ✅ 快速迭代开发
- ✅ CI/CD 自动触发
### 选择 `build-multiplatform.yml` 如果:
- ✅ 需要桌面版本
- ✅ 正式版本发布
- ✅ 需要灵活选择平台
---
## 🔧 环境配置
### 必需的 Secrets(用于 Release 签名)
**Android:**
```
KEYSTORE_BASE64
KEYSTORE_PASSWORD
KEY_ALIAS
KEY_PASSWORD
```
**macOS:**
```
MACOS_CERTIFICATE_BASE64
MACOS_CERTIFICATE_PASSWORD
```
**Windows:**
```
WINDOWS_CERTIFICATE_BASE64
WINDOWS_CERTIFICATE_PASSWORD
```
**说明:** 如果不配置签名,可以使用 debug 构建。
---
## 📊 构建流程图
### Android 专用
```
Checkout 代码
编译 libcore.aar (15min)
配置 API/OSS
构建 APK (20min)
上传产物
```
### 多平台
```
Checkout 代码
编译 libcore.aar (15min)
├─→ Android (20min) ─┐
├─→ Windows (15min) ─┤
├─→ macOS (20min) ─┼─→ 创建 Release
└─→ Linux (15min) ─┘
```
---
## 🐛 故障排查
### 问题 1: libcore 编译失败
**检查:**
1. Go 环境是否正常
2. gomobile 是否安装
3. 网络连接(下载依赖)
**日志位置:** `build-libcore` job
---
### 问题 2: Android 构建失败
**常见原因:**
- libcore.aar 未生成
- Gradle 依赖问题
- 签名配置错误
**解决:** 查看 `build-android` job 日志
---
### 问题 3: macOS 构建失败
**常见原因:**
- 签名证书未配置
- Xcode 版本不兼容
**解决:**
- 使用 debug 构建
- 或配置签名证书
---
## 💡 高级用法
### 1. 定时构建
添加到 workflow:
```yaml
on:
schedule:
- cron: '0 2 * * *' # 每天UTC 2:00
```
### 2. PR 自动构建
已配置:推送 PR 到 main 分支自动触发
### 3. 构建通知
可集成 Telegram/Slack/钉钉通知
---
## 📞 获取帮助
- **查看文档:** 本目录下的 Markdown 文件
- **查看日志:** GitHub Actions 页面
- **提交问题:** Issues 页面
---
## 🔗 相关链接
- [GitHub Actions 文档](https://docs.github.com/actions)
- [Flutter CI/CD](https://docs.flutter.dev/deployment/cd)
- [sing-box 文档](https://sing-box.sagernet.org/)
---
**版本:** 1.0.0
**更新:** 2025-10-27
**作者:** Claude Code
-407
View File
@@ -1,407 +0,0 @@
# 🌐 多平台构建完全指南
## 📋 支持的平台
**Android** - arm64-v8a / armeabi-v7a / x86_64
**Windows** - x64
**macOS** - Universal (Intel + Apple Silicon)
**Linux** - x64
---
## 🚀 快速开始
### 方法 1: 构建所有平台(推荐)
1. 打开 GitHub Actions 页面
2. 选择 **Build Multi-Platform**
3. 点击 **Run workflow**
4. 配置参数:
```yaml
构建类型: release
API 域名: api.maodag.top
OSS 地址 1-4: 使用默认值
构建平台: android,windows,macos,linux # 构建所有平台
```
5. 点击 **Run workflow** 开始
---
### 方法 2: 仅构建指定平台
**场景:** 只需要 Android 和 Windows 版本
```yaml
构建平台: android,windows # 只构建这两个平台
```
**可选值:**
- `android` - 仅 Android
- `windows` - 仅 Windows
- `macos` - 仅 macOS
- `linux` - 仅 Linux
- `android,windows` - Android + Windows
- `android,windows,macos,linux` - 全部平台
---
## ⏱️ 构建时间估算
| 平台 | 时间 | 说明 |
|-----|------|-----|
| **libcore** | 10-15分钟 | Android 依赖 |
| **Android** | 15-20分钟 | 3个架构APK |
| **Windows** | 10-15分钟 | x64可执行文件 |
| **macOS** | 15-20分钟 | Universal应用 |
| **Linux** | 10-15分钟 | x64可执行文件 |
| **总计(全平台)** | **60-85分钟** | 并行构建 |
---
## 📦 构建产物
### Android
```
BearVPN-android-arm64-v8a-release-20251027-abc1234.apk (推荐)
BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk (老设备)
BearVPN-android-x86_64-release-20251027-abc1234.apk (模拟器)
```
**安装:** 直接点击APK安装
---
### Windows
```
BearVPN-windows-x64-release-20251027-abc1234.zip
```
**内容结构:**
```
BearVPN.exe # 主程序
flutter_windows.dll # Flutter运行时
data/ # 资源文件
```
**运行:**
1. 解压 ZIP 文件
2. 双击 `BearVPN.exe` 运行
3. 如提示缺少依赖,安装 [VC++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe)
---
### macOS
```
BearVPN-macos-release-20251027-abc1234.zip
```
**内容:**
```
BearVPN.app # 应用程序包(Universal
```
**安装:**
1. 解压 ZIP 文件
2.`BearVPN.app` 拖到 **应用程序** 文件夹
3. 首次运行右键点击 → 打开(绕过 Gatekeeper
**支持架构:**
- Intel (x86_64)
- Apple Silicon (arm64)
---
### Linux
```
BearVPN-linux-x64-release-20251027-abc1234.tar.gz
```
**内容结构:**
```
bearvpn # 可执行文件
lib/ # 共享库
data/ # 资源文件
```
**运行:**
```bash
# 1. 解压
tar -xzf BearVPN-linux-x64-release-*.tar.gz
cd bundle
# 2. 添加执行权限
chmod +x bearvpn
# 3. 运行
./bearvpn
```
**依赖要求:**
- GTK+ 3
- libstdc++12
**安装依赖(Ubuntu/Debian):**
```bash
sudo apt-get install libgtk-3-0 libstdc++6
```
**安装依赖(Fedora/RHEL):**
```bash
sudo dnf install gtk3 libstdc++
```
---
## 🔧 配置说明
### 所有平台通用配置
| 参数 | 默认值 | 说明 |
|-----|-------|------|
| **构建类型** | `release` | debug 或 release |
| **API 域名** | `api.maodag.top` | 后端服务器 |
| **OSS 地址 1** | 香港 CDN | 配置文件源 |
| **OSS 地址 2** | 东京 CDN | 备用源 |
| **OSS 地址 3** | 首尔 CDN | 备用源 |
| **OSS 地址 4** | 新加坡 CDN | 备用源 |
| **构建平台** | `android,windows,macos,linux` | 选择平台 |
---
## 📥 下载构建产物
### 从 Actions 页面下载
1. 打开运行记录
2. 滚动到 **Artifacts** 区域
3. 下载对应平台:
- `android-apk` - Android APK (所有架构)
- `windows-x64` - Windows 可执行程序
- `macos-app` - macOS 应用
- `linux-x64` - Linux 可执行程序
### 从 Releases 下载(推送标签时)
1. 访问 Releases 页面
2. 选择版本
3. 在 Assets 中下载对应平台文件
---
## 🎯 使用场景
### 场景 1: 开发测试(仅 Android
```yaml
构建类型: debug
构建平台: android
API 域名: api.test.com
```
**优点:** 快速,约20分钟
---
### 场景 2: 正式发布(全平台)
```yaml
构建类型: release
构建平台: android,windows,macos,linux
API 域名: api.maodag.top
```
**优点:** 一次构建,覆盖所有用户
---
### 场景 3: 仅桌面平台
```yaml
构建类型: release
构建平台: windows,macos,linux
```
**用途:** 桌面版更新
---
## 🐛 常见问题
### Q1: Windows 构建失败 - "7z command not found"
**原因:** Windows runner 默认有 7z
**解决:** 检查构建日志,可能是其他错误
---
### Q2: macOS 构建失败 - "Code signing required"
**原因:** Release 构建需要签名
**解决方案:**
**方法 1** 使用 debug 构建(测试用)
**方法 2** 配置签名证书(生产用)
```yaml
# 在 Secrets 中添加
MACOS_CERTIFICATE_BASE64
MACOS_CERTIFICATE_PASSWORD
MACOS_KEYCHAIN_PASSWORD
PROVISIONING_PROFILE_BASE64
```
---
### Q3: Linux 运行时提示缺少库
**错误:**
```
error while loading shared libraries: libgtk-3.so.0
```
**解决:**
```bash
sudo apt-get update
sudo apt-get install libgtk-3-0
```
---
### Q4: 如何只更新某个平台?
**方法 1** 手动触发指定平台
```yaml
构建平台: android # 只构建 Android
```
**方法 2** 创建平台专用 workflow(推荐)
---
### Q5: 构建时间太长怎么办?
**优化方案:**
1. **仅构建需要的平台**
```yaml
构建平台: android # 而不是全部
```
2. **使用缓存**(已配置)
- Flutter SDK 缓存
- Gradle 缓存
- Go modules 缓存
3. **分批构建**
- 白天构建 Android/Windows
- 晚上构建 macOS/Linux
---
## 💡 高级用法
### 技巧 1: 矩阵构建多个配置
修改 workflow:
```yaml
strategy:
matrix:
api_domain: ['api.prod.com', 'api.test.com']
platform: ['android', 'windows', 'macos', 'linux']
```
**效果:** 生成 8 个版本(2域名 × 4平台)
---
### 技巧 2: 定时自动构建
添加到 workflow:
```yaml
on:
schedule:
- cron: '0 2 * * *' # 每天凌晨2点(UTC
```
---
### 技巧 3: 构建完成通知
添加 Telegram 通知:
```yaml
- name: 📢 通知
run: |
curl -X POST "https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/sendMessage" \
-d chat_id=${{ secrets.TG_CHAT_ID }} \
-d text="✅ 多平台构建完成!"
```
---
## 📊 构建并行示意图
```
libcore (15min)
├─→ Android (20min) ─┐
├─→ Windows (15min) ─┤
├─→ macOS (20min) ─┼─→ Release (2min)
└─→ Linux (15min) ─┘
总时间: 约 35-40分钟(并行)
如果串行: 约 85分钟
```
---
## 🔐 安全建议
### Release 版本签名
**Android:**
```yaml
# Secrets 配置
KEYSTORE_BASE64
KEYSTORE_PASSWORD
KEY_ALIAS
KEY_PASSWORD
```
**macOS:**
```yaml
# Secrets 配置
MACOS_CERTIFICATE_BASE64
MACOS_CERTIFICATE_PASSWORD
```
**Windows:**
```yaml
# Secrets 配置
WINDOWS_CERTIFICATE_BASE64
WINDOWS_CERTIFICATE_PASSWORD
```
---
## 📞 需要帮助?
- 查看 [GitHub Actions 文档](https://docs.github.com/actions)
- 查看 [Flutter 桌面支持](https://docs.flutter.dev/desktop)
- 提交 Issue
---
**版本:** 1.0.0
**更新:** 2025-10-27
**作者:** Claude Code
-78
View File
@@ -1,78 +0,0 @@
# 🚀 GitHub Actions 快速开始
## 📋 3 步开始使用
### 步骤 1: 推送配置文件
```bash
cd /Users/mac/Project/Dart/LighthouseApp
git add .github/workflows/
git commit -m "feat: 添加 GitHub Actions 自动构建配置"
git push origin main
```
### 步骤 2: 手动触发构建
1. 打开 GitHub 仓库页面
2. 点击 **Actions** 标签
3. 左侧选择 **Build Android APK**
4. 右侧点击 **Run workflow** 下拉按钮
5. 配置参数(可以使用默认值):
```
构建类型: release
API 域名: api.maodag.top
OSS 地址 1-4: 使用默认值
```
6. 点击绿色 **Run workflow** 按钮
### 步骤 3: 下载 APK
- 等待约 30 分钟
- 在构建记录页面找到 **Artifacts**
- 下载 `apk-arm64-v8a-release`(推荐)
---
## 🎯 自定义配置示例
### 场景 1: 更换 API 域名
```yaml
构建类型: release
API 域名: api.example.com ← 修改这里
OSS 地址: 保持默认
```
### 场景 2: 使用自己的 CDN
```yaml
构建类型: release
API 域名: api.maodag.top
OSS 地址 1: https://your-cdn.com/config1.txt ← 修改这里
OSS 地址 2: https://your-cdn.com/config2.txt ← 修改这里
OSS 地址 3: https://your-cdn.com/config3.txt ← 修改这里
OSS 地址 4: https://your-cdn.com/config4.txt ← 修改这里
```
---
## 📖 详细文档
- **完整指南:** [BUILD_GUIDE.md](./BUILD_GUIDE.md)
- **基础说明:** [README.md](./README.md)
---
## ✅ 核心功能
**Release 构建** - 生产环境优化版本
**可配置域名** - 支持自定义 API 和 CDN
**分架构打包** - arm64/armv7/x86_64
**自动 Release** - 推送标签自动发布
---
**需要帮助?** 查看 [BUILD_GUIDE.md](./BUILD_GUIDE.md)
-90
View File
@@ -1,90 +0,0 @@
# GitHub Actions 构建说明
## 📋 工作流概览
### `build-android-apk.yml` - Android APK 自动构建
**触发条件:**
- ✅ 推送到 `main``develop` 分支
- ✅ 打 `v*` 标签时自动创建 Release
- ✅ 手动触发(Actions 页面点击 "Run workflow"
**构建产物:**
- `libcore.aar` - sing-box 核心库
- `BearVPN-arm64-v8a-*.apk` - 64位 ARM 版本(推荐)
- `BearVPN-armeabi-v7a-*.apk` - 32位 ARM 版本
- `BearVPN-x86_64-*.apk` - 模拟器版本
---
## 🚀 使用方法
### 方法一:推送代码自动构建
```bash
git add .
git commit -m "feat: 新功能"
git push origin main
```
### 方法二:手动触发
1. 打开仓库 **Actions** 页面
2. 点击 **Build Android APK**
3. 点击 **Run workflow**
### 方法三:创建 Release
```bash
git tag v1.0.0
git push origin v1.0.0
```
---
## 📦 下载构建产物
- **Actions 页面:** 点击运行记录 → Artifacts 区域下载
- **Releases 页面:** 选择版本 → Assets 下载
---
## 🔧 配置 Release 签名(可选)
1. 生成密钥:
```bash
keytool -genkey -v -keystore release.keystore -alias bearvpn -keyalg RSA -keysize 2048 -validity 10000
```
2. 转换为 Base64
```bash
base64 release.keystore > keystore.base64.txt
```
3. 在 GitHub 仓库 **Settings → Secrets** 添加:
- `KEYSTORE_BASE64`
- `KEYSTORE_PASSWORD`
- `KEY_ALIAS`
- `KEY_PASSWORD`
---
## ⏱️ 构建时间
- libcore.aar: 10-15 分钟
- Flutter APK: 15-20 分钟
- **总计: 约 30 分钟**
---
## 🐛 常见问题
**Q: 构建失败 "libcore.aar not found"**
A: 检查 libcore 子模块是否正确初始化
**Q: Release 未创建**
A: 标签必须以 `v` 开头,如 `v1.0.0`
---
生成时间: 2025-10-27
-319
View File
@@ -1,319 +0,0 @@
name: Build Android APK
on:
push:
branches:
- main
- develop
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch: # 允许手动触发
inputs:
build_type:
description: '构建类型'
required: true
default: 'release'
type: choice
options:
- debug
- release
api_domain:
description: 'API 域名'
required: true
default: 'api.maodag.top'
type: string
oss_url_1:
description: 'OSS 配置地址 1'
required: true
default: 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt'
type: string
oss_url_2:
description: 'OSS 配置地址 2'
required: true
default: 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt'
type: string
oss_url_3:
description: 'OSS 配置地址 3'
required: true
default: 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt'
type: string
oss_url_4:
description: 'OSS 配置地址 4'
required: true
default: 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt'
type: string
jobs:
build-libcore:
name: 编译 libcore.aar
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js 环境
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 🔧 设置 Java 环境
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: 🔧 安装 gomobile
run: |
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
- name: 📦 编译 libcore.aar
working-directory: libcore
run: |
echo "🚀 开始编译 libcore..."
make android
echo "✅ 编译完成,检查产物..."
ls -lh bin/
if [ -f "bin/libcore.aar" ]; then
echo "✅ libcore.aar 生成成功"
cp bin/libcore.aar ../android/app/libs/
else
echo "❌ libcore.aar 未找到"
exit 1
fi
- name: 📤 上传 libcore.aar
uses: actions/upload-artifact@v4
with:
name: libcore-aar
path: android/app/libs/libcore.aar
retention-days: 7
build-apk:
name: 编译 Android APK
needs: build-libcore
runs-on: ubuntu-latest
strategy:
matrix:
build_type: [release] # 默认 release 构建
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Java 环境
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: 🔧 设置 Flutter 环境
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 libcore.aar
uses: actions/download-artifact@v4
with:
name: libcore-aar
path: android/app/libs/
- name: ⚙️ 配置 API 域名和 OSS 地址
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
# 获取参数(手动触发时使用输入值,自动触发时使用默认值)
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
echo "🔧 配置构建参数:"
echo " API 域名: $API_DOMAIN"
echo " OSS 地址 1: $OSS_URL_1"
echo " OSS 地址 2: $OSS_URL_2"
echo " OSS 地址 3: $OSS_URL_3"
echo " OSS 地址 4: $OSS_URL_4"
# 替换 API 域名
sed -i "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
# 替换 OSS 地址
sed -i "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
echo "✅ 配置替换完成"
echo ""
echo "📄 查看修改后的配置:"
grep -A 15 "kr_baseDomains" "$CONFIG_FILE" || true
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
- name: 🔨 构建 APK (Release)
run: |
flutter build apk --release --split-per-abi
- name: 📋 生成构建信息
id: build_info
run: |
BUILD_DATE=$(date '+%Y-%m-%d %H:%M:%S')
COMMIT_SHA=${GITHUB_SHA::7}
echo "build_date=$BUILD_DATE" >> $GITHUB_OUTPUT
echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
echo "📊 构建信息:"
echo " - 日期: $BUILD_DATE"
echo " - 提交: $COMMIT_SHA"
echo " - 分支: ${GITHUB_REF#refs/heads/}"
- name: 📦 重命名 APK 文件
run: |
COMMIT_SHA=${{ steps.build_info.outputs.commit_sha }}
DATE=$(date '+%Y%m%d')
cd build/app/outputs/flutter-apk/
for file in app-*-release.apk; do
if [ -f "$file" ]; then
# 提取架构名称 (arm64-v8a, armeabi-v7a, x86_64)
ARCH=$(echo "$file" | sed "s/app-\(.*\)-release.apk/\1/")
NEW_NAME="BearVPN-${ARCH}-release-${DATE}-${COMMIT_SHA}.apk"
mv "$file" "$NEW_NAME"
# 计算文件大小和 MD5
SIZE=$(ls -lh "$NEW_NAME" | awk '{print $5}')
MD5=$(md5sum "$NEW_NAME" | awk '{print $1}')
echo "✅ $NEW_NAME"
echo " 大小: $SIZE"
echo " MD5: $MD5"
fi
done
ls -lh
- name: 📤 上传 APK (arm64-v8a)
uses: actions/upload-artifact@v4
with:
name: apk-arm64-v8a-release
path: build/app/outputs/flutter-apk/*arm64-v8a*.apk
retention-days: 30
- name: 📤 上传 APK (armeabi-v7a)
uses: actions/upload-artifact@v4
with:
name: apk-armeabi-v7a-release
path: build/app/outputs/flutter-apk/*armeabi-v7a*.apk
retention-days: 30
- name: 📤 上传 APK (x86_64)
uses: actions/upload-artifact@v4
with:
name: apk-x86_64-release
path: build/app/outputs/flutter-apk/*x86_64*.apk
retention-days: 30
create-release:
name: 创建 GitHub Release
needs: build-apk
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: 📥 下载所有 APK
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: apk-*
- name: 📋 生成 Release 说明
id: release_notes
run: |
cat > release_notes.md << 'EOF'
## 🎉 BearVPN Android 版本发布
### 📦 安装包说明
| 架构 | 适用设备 | 文件大小 |
|------|----------|----------|
| arm64-v8a | 64位 ARM 设备(推荐,现代手机) | ~40MB |
| armeabi-v7a | 32位 ARM 设备(老旧手机) | ~35MB |
| x86_64 | x86_64 模拟器 | ~45MB |
### ✨ 主要特性
- ✅ 支持 Shadowsocks/VLESS/Trojan/Hysteria2 等协议
- ✅ 内置 sing-box 核心
- ✅ 支持自定义路由规则
- ✅ 支持 URL Test 节点延迟测试
### 📥 下载建议
**不确定选哪个?** 下载 `arm64-v8a` 版本即可,适用于绝大多数现代 Android 手机。
### 🔒 文件校验
下载后请验证 MD5 以确保文件完整性(见下方 Assets 描述)。
---
**构建信息:**
- 提交: ${GITHUB_SHA::7}
- 构建时间: $(date '+%Y-%m-%d %H:%M:%S UTC')
- Flutter: 3.24.5
- sing-box: latest
EOF
echo "release_notes<<EOF" >> $GITHUB_OUTPUT
cat release_notes.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: 🚀 创建 GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/apk-arm64-v8a-*/*.apk
artifacts/apk-armeabi-v7a-*/*.apk
artifacts/apk-x86_64-*/*.apk
body: ${{ steps.release_notes.outputs.release_notes }}
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 📢 构建成功通知
run: |
echo "✅ 构建完成!"
echo "📦 Release 已创建: ${{ github.ref }}"
echo "🔗 查看: https://github.com/${{ github.repository }}/releases"
-142
View File
@@ -1,142 +0,0 @@
name: Build Clash Core
on:
push:
paths:
- 'core/**'
- '.github/workflows/build-clash-core.yml'
pull_request:
paths:
- 'core/**'
workflow_dispatch: # 允许手动触发
jobs:
build-android:
name: Build Android (${{ matrix.arch }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
abi: arm64-v8a
cc: aarch64-linux-android29-clang
- arch: armv7
abi: armeabi-v7a
cc: armv7a-linux-androideabi29-clang
- arch: x86_64
abi: x86_64
cc: x86_64-linux-android29-clang
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
cache: true
cache-dependency-path: core/go.sum
- name: Setup Android NDK
uses: nttld/setup-ndk@v1
with:
ndk-version: r25c
add-to-path: true
- name: Build Core
working-directory: core
run: make android-${{ matrix.arch }}
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
- name: Verify Build
run: |
echo "📦 检查编译产物..."
ls -lh android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so
file android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so
echo "🔍 验证导出函数..."
nm -D android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so | grep -E "(quickStart|getAndroidVpnOptions|startTUN)"
- name: Calculate MD5
id: md5
run: |
MD5=$(md5sum android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so | awk '{print $1}')
echo "md5=$MD5" >> $GITHUB_OUTPUT
echo "📋 MD5: $MD5"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: libclash-${{ matrix.abi }}
path: android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so
retention-days: 30
if-no-files-found: error
- name: Comment Build Info
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const stats = fs.statSync('android/app/src/main/jniLibs/${{ matrix.abi }}/libclash.so');
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `### 🔨 Clash Core 构建完成 (${{ matrix.abi }})
- **架构:** ${{ matrix.abi }}
- **大小:** ${sizeMB} MB
- **MD5:** ${{ steps.md5.outputs.md5 }}
- **提交:** ${context.sha.substring(0, 7)}
[下载构建产物](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`
});
create-release:
name: Create Release
needs: build-android
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create Release Archive
run: |
cd artifacts
tar -czf clash-core-android-all.tar.gz libclash-*/*.so
ls -lh clash-core-android-all.tar.gz
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: artifacts/clash-core-android-all.tar.gz
body: |
## Clash Meta 核心 Android 构建
此版本包含所有 Android 架构的预编译二进制文件:
- arm64-v8a (ARM64)
- armeabi-v7a (ARMv7)
- x86_64 (模拟器)
**使用方法:**
```bash
tar -xzf clash-core-android-all.tar.gz
cp libclash-*/libclash.so android/app/src/main/jniLibs/
```
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-950
View File
@@ -1,950 +0,0 @@
name: Build Multi-Platform
on:
push:
branches:
- main
- develop
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch:
inputs:
build_type:
description: '构建类型'
required: true
default: 'release'
type: choice
options:
- debug
- release
api_domain:
description: 'API 域名'
required: true
default: 'api.maodag.top'
type: string
oss_url_1:
description: 'OSS 配置地址 1'
required: true
default: 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt'
type: string
oss_url_2:
description: 'OSS 配置地址 2'
required: true
default: 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt'
type: string
oss_url_3:
description: 'OSS 配置地址 3'
required: true
default: 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt'
type: string
oss_url_4:
description: 'OSS 配置地址 4'
required: true
default: 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt'
type: string
encryption_key:
description: '加密密钥'
required: true
default: 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx'
type: string
platforms:
description: '构建平台 (多选: android,windows,macos,linux,ios)'
required: true
default: 'android,windows,macos,linux'
type: string
jobs:
# ==================== 编译 libcore (iOS/tvOS) ====================
build-libcore-ios:
name: 编译 libcore (iOS/tvOS)
runs-on: macos-latest
if: contains(inputs.platforms || 'ios', 'ios')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 📦 编译 libcore.xcframework (支持 iOS/tvOS)
working-directory: libcore
run: |
echo "🚀 开始编译 iOS/tvOS libcore..."
make ios-full
if [ -d "bin/Libcore.xcframework" ]; then
echo "✅ iOS/tvOS libcore 编译成功"
ls -lh bin/
else
echo "❌ iOS/tvOS libcore 编译失败"
exit 1
fi
- name: 📤 上传 iOS libcore
uses: actions/upload-artifact@v4
with:
name: libcore-ios
path: libcore/bin/Libcore.xcframework
retention-days: 7
# ==================== 编译 libcore (Android) ====================
build-libcore-android:
name: 编译 libcore (Android)
runs-on: ubuntu-latest
if: contains(inputs.platforms || 'android', 'android')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 🔧 设置 Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: 🔧 安装 gomobile
run: |
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
- name: 📦 编译 libcore.aar
working-directory: libcore
run: |
echo "🚀 开始编译 Android libcore..."
make android
if [ -f "bin/libcore.aar" ]; then
echo "✅ libcore.aar 生成成功"
ls -lh bin/libcore.aar
else
echo "❌ libcore.aar 未找到"
exit 1
fi
- name: 📤 上传 libcore.aar
uses: actions/upload-artifact@v4
with:
name: libcore-android
path: libcore/bin/libcore.aar
retention-days: 7
# ==================== 编译 libcore (Windows) ====================
build-libcore-windows:
name: 编译 libcore (Windows)
runs-on: ubuntu-latest
if: contains(inputs.platforms || 'windows', 'windows')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 🔧 安装 MinGW (交叉编译工具)
run: |
sudo apt-get update
sudo apt-get install -y mingw-w64
- name: 📦 编译 libcore.dll
working-directory: libcore
run: |
echo "🚀 开始编译 Windows libcore..."
make windows-amd64
if [ -f "bin/libcore.dll" ] && [ -f "bin/HiddifyCli.exe" ]; then
echo "✅ Windows libcore 编译成功"
ls -lh bin/libcore.dll bin/HiddifyCli.exe
else
echo "❌ Windows libcore 编译失败"
exit 1
fi
- name: 📤 上传 Windows libcore
uses: actions/upload-artifact@v4
with:
name: libcore-windows
path: |
libcore/bin/libcore.dll
libcore/bin/HiddifyCli.exe
libcore/bin/webui/**
retention-days: 7
# ==================== 编译 libcore (macOS) ====================
build-libcore-macos:
name: 编译 libcore (macOS)
runs-on: macos-latest
if: contains(inputs.platforms || 'macos', 'macos')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 📦 编译 libcore.dylib
working-directory: libcore
run: |
echo "🚀 开始编译 macOS libcore..."
make macos-universal
if [ -f "bin/libcore.dylib" ] && [ -f "bin/HiddifyCli" ]; then
echo "✅ macOS libcore 编译成功"
ls -lh bin/libcore.dylib bin/HiddifyCli
else
echo "❌ macOS libcore 编译失败"
exit 1
fi
- name: 📤 上传 macOS libcore
uses: actions/upload-artifact@v4
with:
name: libcore-macos
path: |
libcore/bin/libcore.dylib
libcore/bin/HiddifyCli
retention-days: 7
# ==================== 编译 libcore (Linux) ====================
build-libcore-linux:
name: 编译 libcore (Linux)
runs-on: ubuntu-latest
if: contains(inputs.platforms || 'linux', 'linux')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 📦 编译 libcore.so
working-directory: libcore
run: |
echo "🚀 开始编译 Linux libcore..."
make linux-amd64
if [ -f "bin/lib/libcore.so" ] && [ -f "bin/HiddifyCli" ]; then
echo "✅ Linux libcore 编译成功"
ls -lh bin/lib/libcore.so bin/HiddifyCli
else
echo "❌ Linux libcore 编译失败"
exit 1
fi
- name: 📤 上传 Linux libcore
uses: actions/upload-artifact@v4
with:
name: libcore-linux
path: |
libcore/bin/lib/libcore.so
libcore/bin/HiddifyCli
libcore/bin/webui/**
retention-days: 7
# ==================== Android 构建 ====================
build-android:
name: 构建 Android APK
needs: build-libcore-android
runs-on: ubuntu-latest
if: contains(inputs.platforms || 'android', 'android')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: 🔧 设置 Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 libcore.aar
uses: actions/download-artifact@v4
with:
name: libcore-android
path: android/app/libs/
- name: ⚙️ 配置 API、OSS 和加密密钥
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
ENCRYPTION_KEY="${{ inputs.encryption_key || 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx' }}"
echo "🔧 配置参数:"
echo " API: $API_DOMAIN"
echo " OSS: $OSS_URL_1"
echo " 密钥: ${ENCRYPTION_KEY:0:10}..."
# 转义密钥中的特殊字符(使用 perl 兼容所有平台)
ENCRYPTION_KEY_ESCAPED=$(echo "$ENCRYPTION_KEY" | perl -pe 's/([\[\].*^$()+?{|\\])/\\$1/g')
sed -i "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
sed -i "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
sed -i "s|c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx|$ENCRYPTION_KEY_ESCAPED|g" "$CONFIG_FILE"
echo "✅ 配置完成"
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
- name: 🔨 构建 APK (Release)
run: |
flutter build apk --release --split-per-abi
- name: 📦 重命名 APK
run: |
COMMIT_SHA=${GITHUB_SHA::7}
DATE=$(date '+%Y%m%d')
cd build/app/outputs/flutter-apk/
for file in app-*-release.apk; do
if [ -f "$file" ]; then
ARCH=$(echo "$file" | sed "s/app-\(.*\)-release.apk/\1/")
NEW_NAME="BearVPN-android-${ARCH}-release-${DATE}-${COMMIT_SHA}.apk"
mv "$file" "$NEW_NAME"
echo "✅ $NEW_NAME"
fi
done
- name: 📤 上传 APK
uses: actions/upload-artifact@v4
with:
name: android-apk
path: build/app/outputs/flutter-apk/*.apk
retention-days: 30
# ==================== Windows 构建 ====================
build-windows:
name: 构建 Windows
needs: build-libcore-windows
runs-on: windows-latest
if: contains(inputs.platforms || 'windows', 'windows')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 Windows libcore
uses: actions/download-artifact@v4
with:
name: libcore-windows
path: libcore_windows_temp
- name: 🔧 复制 libcore 文件到正确位置并重命名
run: |
Write-Host "📋 开始复制 libcore 文件..."
# 显示下载的文件结构
Write-Host "🔍 检查下载的文件结构:"
Get-ChildItem -Recurse libcore_windows_temp -ErrorAction SilentlyContinue | Format-Table Name, FullName
# 确保目标目录存在
New-Item -ItemType Directory -Force -Path "libcore\bin" | Out-Null
# 查找 libcore.dll(可能在 libcore_windows_temp/bin/ 或 libcore_windows_temp/libcore/bin/
$dllFiles = Get-ChildItem -Path libcore_windows_temp -Recurse -Filter "libcore.dll" -ErrorAction SilentlyContinue
if ($dllFiles) {
$sourceDll = $dllFiles[0].FullName
Write-Host "✅ 找到 libcore.dll: $sourceDll"
Copy-Item $sourceDll "libcore\bin\libcore.dll" -Force
} else {
Write-Host "❌ 未找到 libcore.dll"
Write-Host "当前目录内容:"
Get-ChildItem -Path . -Recurse | Select-Object -First 20 | Format-Table Name, FullName
exit 1
}
# 查找并复制 HiddifyCli.exe,重命名为 BearVPNCli.exe
$exeFiles = Get-ChildItem -Path libcore_windows_temp -Recurse -Filter "HiddifyCli.exe" -ErrorAction SilentlyContinue
if ($exeFiles) {
$sourceExe = $exeFiles[0].FullName
Write-Host "✅ 找到 HiddifyCli.exe: $sourceExe"
Write-Host "📝 复制并重命名为 BearVPNCli.exe"
Copy-Item $sourceExe "libcore\bin\BearVPNCli.exe" -Force
Write-Host "✅ 重命名完成:HiddifyCli.exe → BearVPNCli.exe"
} else {
Write-Host "⚠️ 未找到 HiddifyCli.exe(这不是致命错误)"
}
# 复制 webui 目录
$webuiDir = Get-ChildItem -Path libcore_windows_temp -Recurse -Filter "webui" -Directory -ErrorAction SilentlyContinue
if ($webuiDir) {
Write-Host "✅ 找到 webui 目录: $($webuiDir[0].FullName)"
Copy-Item -Path $webuiDir[0].FullName -Destination "libcore\bin\webui" -Recurse -Force
} else {
Write-Host "⚠️ 未找到 webui 目录(这不是致命错误)"
}
Write-Host ""
Write-Host "📄 验证复制后的文件结构:"
if (Test-Path "libcore\bin") {
Get-ChildItem libcore\bin\ -Recurse | Format-Table Name, FullName, Length
} else {
Write-Host "❌ libcore\bin 目录不存在"
}
if (-not (Test-Path "libcore\bin\libcore.dll")) {
Write-Host "❌ libcore.dll 未正确复制到 libcore\bin\"
exit 1
}
Write-Host "✅ libcore 文件复制完成"
shell: pwsh
- name: ⚙️ 配置 API、OSS 和加密密钥
shell: bash
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
ENCRYPTION_KEY="${{ inputs.encryption_key || 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx' }}"
ENCRYPTION_KEY_ESCAPED=$(echo "$ENCRYPTION_KEY" | perl -pe 's/([\[\].*^$()+?{|\\])/\\$1/g')
sed -i "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
sed -i "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
sed -i "s|c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx|$ENCRYPTION_KEY_ESCAPED|g" "$CONFIG_FILE"
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
- name: 🔧 生成代码文件 (build_runner)
run: |
echo "🔧 开始运行 build_runner..."
flutter pub run build_runner build --delete-conflicting-outputs
echo ""
echo "✅ build_runner 完成,检查生成的文件..."
if (Test-Path "lib\singbox\model\singbox_status.freezed.dart") {
echo "✅ singbox_status.freezed.dart 已生成"
} else {
echo "❌ singbox_status.freezed.dart 未生成"
exit 1
}
if (Test-Path "lib\singbox\service\singbox_service_provider.g.dart") {
echo "✅ singbox_service_provider.g.dart 已生成"
} else {
echo "❌ singbox_service_provider.g.dart 未生成"
exit 1
}
shell: pwsh
- name: 🔧 验证 libcore 文件存在
run: |
Write-Host "📋 验证 libcore 文件是否存在..."
if (Test-Path "libcore\bin\libcore.dll") {
$dllInfo = Get-Item "libcore\bin\libcore.dll"
Write-Host "✅ libcore.dll 存在: $($dllInfo.FullName) - 大小: $($dllInfo.Length) bytes"
} else {
Write-Host "❌ libcore.dll 不存在"
Write-Host "当前 libcore\bin 目录内容:"
if (Test-Path "libcore\bin") {
Get-ChildItem "libcore\bin" | Format-Table Name, FullName, Length
} else {
Write-Host "libcore\bin 目录不存在"
}
exit 1
}
if (Test-Path "libcore\bin\BearVPNCli.exe") {
$exeInfo = Get-Item "libcore\bin\BearVPNCli.exe"
Write-Host "✅ BearVPNCli.exe 存在: $($exeInfo.FullName) - 大小: $($exeInfo.Length) bytes"
} else {
Write-Host "⚠️ BearVPNCli.exe 不存在"
}
shell: pwsh
- name: 🔨 构建 Windows (Release)
run: |
flutter build windows --release
- name: 🔍 验证 Windows 文件结构
run: |
Write-Host "📋 检查 Release 目录文件结构..."
$releaseDir = "build\windows\x64\runner\Release"
if (Test-Path $releaseDir) {
Write-Host "✅ Release 目录存在"
Write-Host ""
Write-Host "📄 文件列表:"
Get-ChildItem $releaseDir | Format-Table Name, Length, LastWriteTime
# 检查关键文件
if (Test-Path "$releaseDir\BearVPN.exe") {
Write-Host "✅ BearVPN.exe 存在"
} else {
Write-Host "❌ BearVPN.exe 不存在"
}
if (Test-Path "$releaseDir\BearVPNCli.exe") {
Write-Host "✅ BearVPNCli.exe 存在"
} else {
Write-Host "⚠️ BearVPNCli.exe 不存在"
}
if (Test-Path "$releaseDir\libcore.dll") {
Write-Host "✅ libcore.dll 存在"
} else {
Write-Host "❌ libcore.dll 不存在"
}
} else {
Write-Host "❌ Release 目录不存在"
}
shell: pwsh
- name: 📦 打包 Windows
shell: bash
run: |
COMMIT_SHA=${GITHUB_SHA::7}
DATE=$(date '+%Y%m%d')
cd build/windows/x64/runner/Release
7z a -tzip "../../../../../BearVPN-windows-x64-release-${DATE}-${COMMIT_SHA}.zip" ./*
- name: 📤 上传 Windows
uses: actions/upload-artifact@v4
with:
name: windows-x64
path: BearVPN-windows-*.zip
retention-days: 30
# ==================== macOS 构建 ====================
build-macos:
name: 构建 macOS
needs: build-libcore-macos
runs-on: macos-latest
if: contains(inputs.platforms || 'macos', 'macos')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 macOS libcore
uses: actions/download-artifact@v4
with:
name: libcore-macos
path: libcore/bin/
- name: 🔧 设置 libcore 执行权限
run: |
chmod +x libcore/bin/HiddifyCli
- name: ⚙️ 配置 API、OSS 和加密密钥
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
ENCRYPTION_KEY="${{ inputs.encryption_key || 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx' }}"
# macOS 使用 BSD sed,转义特殊字符
# 使用 perl 来转义特殊字符,更可靠
ENCRYPTION_KEY_ESCAPED=$(echo "$ENCRYPTION_KEY" | perl -pe 's/([\[\].*^$()+?{|\\])/\\$1/g')
echo "🔧 配置参数:"
echo " API: $API_DOMAIN"
echo " 密钥: ${ENCRYPTION_KEY:0:10}..."
# macOS sed 需要使用 -i '' 和正确的语法
sed -i '' "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
sed -i '' "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i '' "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i '' "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i '' "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
# 使用不同的分隔符避免转义问题
sed -i '' "s|c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx|$ENCRYPTION_KEY_ESCAPED|g" "$CONFIG_FILE"
echo "✅ 配置完成"
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
- name: 🔨 构建 macOS (Release)
run: |
flutter build macos --release
- name: 📦 打包 macOS
run: |
COMMIT_SHA=${GITHUB_SHA::7}
DATE=$(date '+%Y%m%d')
cd build/macos/Build/Products/Release
zip -r -y "../../../../../BearVPN-macos-release-${DATE}-${COMMIT_SHA}.zip" BearVPN.app
- name: 📤 上传 macOS
uses: actions/upload-artifact@v4
with:
name: macos-app
path: BearVPN-macos-*.zip
retention-days: 30
# ==================== Linux 构建 ====================
build-linux:
name: 构建 Linux
needs: build-libcore-linux
runs-on: ubuntu-latest
if: contains(inputs.platforms || 'linux', 'linux')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 安装 Linux 依赖
run: |
sudo apt-get update
sudo apt-get install -y \
clang \
cmake \
ninja-build \
pkg-config \
libgtk-3-dev \
liblzma-dev \
libstdc++-12-dev \
libayatana-appindicator3-dev
- name: 🔧 设置 Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 Linux libcore
uses: actions/download-artifact@v4
with:
name: libcore-linux
path: libcore/bin/
- name: 🔧 设置 libcore 执行权限
run: |
chmod +x libcore/bin/HiddifyCli
- name: ⚙️ 配置 API、OSS 和加密密钥
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
ENCRYPTION_KEY="${{ inputs.encryption_key || 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx' }}"
ENCRYPTION_KEY_ESCAPED=$(echo "$ENCRYPTION_KEY" | perl -pe 's/([\[\].*^$()+?{|\\])/\\$1/g')
sed -i "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
sed -i "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
sed -i "s|c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx|$ENCRYPTION_KEY_ESCAPED|g" "$CONFIG_FILE"
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
- name: 🔨 构建 Linux (Release)
run: |
flutter build linux --release
- name: 📦 打包 Linux
run: |
COMMIT_SHA=${GITHUB_SHA::7}
DATE=$(date '+%Y%m%d')
cd build/linux/x64/release/bundle
tar -czf "../../../../../BearVPN-linux-x64-release-${DATE}-${COMMIT_SHA}.tar.gz" ./*
- name: 📤 上传 Linux
uses: actions/upload-artifact@v4
with:
name: linux-x64
path: BearVPN-linux-*.tar.gz
retention-days: 30
# ==================== iOS 构建 ====================
build-ios:
name: 构建 iOS
needs: build-libcore-ios
runs-on: macos-latest
if: contains(inputs.platforms || 'ios', 'ios')
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
cache: true
- name: 📥 下载 iOS libcore
uses: actions/download-artifact@v4
with:
name: libcore-ios
path: ios/Frameworks/
- name: ⚙️ 配置 API、OSS 和加密密钥
run: |
CONFIG_FILE="lib/app/common/app_config.dart"
API_DOMAIN="${{ inputs.api_domain || 'api.maodag.top' }}"
OSS_URL_1="${{ inputs.oss_url_1 || 'https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt' }}"
OSS_URL_2="${{ inputs.oss_url_2 || 'https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt' }}"
OSS_URL_3="${{ inputs.oss_url_3 || 'https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt' }}"
OSS_URL_4="${{ inputs.oss_url_4 || 'https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt' }}"
ENCRYPTION_KEY="${{ inputs.encryption_key || 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx' }}"
# 使用 perl 转义特殊字符
ENCRYPTION_KEY_ESCAPED=$(echo "$ENCRYPTION_KEY" | perl -pe 's/([\[\].*^$()+?{|\\])/\\$1/g')
sed -i '' "s|api\.maodag\.top|$API_DOMAIN|g" "$CONFIG_FILE"
sed -i '' "s|https://ppp2\.oss-cn-hongkong\.aliyuncs\.com/bear1\.txt|$OSS_URL_1|g" "$CONFIG_FILE"
sed -i '' "s|https://xgp3\.oss-ap-northeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_2|g" "$CONFIG_FILE"
sed -i '' "s|https://xpp4\.oss-ap-northeast-2\.aliyuncs\.com/bear1\.txt|$OSS_URL_3|g" "$CONFIG_FILE"
sed -i '' "s|https://xpp5\.oss-ap-southeast-1\.aliyuncs\.com/bear1\.txt|$OSS_URL_4|g" "$CONFIG_FILE"
sed -i '' "s|c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx|$ENCRYPTION_KEY_ESCAPED|g" "$CONFIG_FILE"
- name: 📦 安装 Flutter 依赖
run: |
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
- name: 🔨 构建 iOS (Release)
run: |
flutter build ios --release --no-codesign
- name: 📦 打包 iOS
run: |
COMMIT_SHA=${GITHUB_SHA::7}
DATE=$(date '+%Y%m%d')
cd build/ios/iphoneos
# 创建 Payload 目录
mkdir -p Payload
cp -r Runner.app Payload/
# 创建 IPA 文件
zip -r "../../../../BearVPN-ios-release-${DATE}-${COMMIT_SHA}.ipa" Payload
echo "✅ iOS IPA 创建完成"
ls -lh BearVPN-ios-*.ipa
- name: 📤 上传 iOS
uses: actions/upload-artifact@v4
with:
name: ios-app
path: BearVPN-ios-*.ipa
retention-days: 30
# ==================== 创建 Release ====================
create-release:
name: 创建 Release
needs: [build-android, build-windows, build-macos, build-linux, build-ios]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: 📥 下载所有构建产物
uses: actions/download-artifact@v4
with:
path: artifacts
- name: 📋 生成 Release 说明
id: release_notes
run: |
cat > release_notes.md << 'EOF'
## 🎉 BearVPN 多平台版本发布
### 📦 平台支持
| 平台 | 架构 | 文件 |
|-----|------|-----|
| **Android** | arm64-v8a | BearVPN-android-arm64-v8a-*.apk |
| **Android** | armeabi-v7a | BearVPN-android-armeabi-v7a-*.apk |
| **Android** | x86_64 | BearVPN-android-x86_64-*.apk |
| **iOS** | Universal | BearVPN-ios-*.ipa |
| **Windows** | x64 | BearVPN-windows-x64-*.zip |
| **macOS** | Universal | BearVPN-macos-*.zip |
| **Linux** | x64 | BearVPN-linux-x64-*.tar.gz |
### ✨ 主要特性
- ✅ 支持 Shadowsocks/VLESS/Trojan/Hysteria2
- ✅ 内置 sing-box 核心 v3.1.7
- ✅ 跨平台支持
- ✅ 自定义路由规则
### 📥 安装指南
**Android:** 下载 APK 直接安装
**iOS:** 下载 IPA 使用 AltStore/Sideloadly 安装
**Windows:** 解压 ZIP 运行 BearVPN.exe
**macOS:** 解压 ZIP 拖拽到应用程序
**Linux:** 解压 tar.gz 运行可执行文件
---
**构建信息:**
- 提交: ${GITHUB_SHA::7}
- 时间: $(date '+%Y-%m-%d %H:%M:%S UTC')
- Flutter: 3.24.5
- sing-box: v3.1.7
EOF
echo "release_notes<<EOF" >> $GITHUB_OUTPUT
cat release_notes.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: 🚀 创建 Release
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/android-apk/*.apk
artifacts/ios-app/*.ipa
artifacts/windows-x64/*.zip
artifacts/macos-app/*.zip
artifacts/linux-x64/*.tar.gz
body: ${{ steps.release_notes.outputs.release_notes }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 📢 构建完成
run: |
echo "✅ 所有平台构建完成!"
echo "📦 Release: ${{ github.ref }}"
echo "🔗 https://github.com/${{ github.repository }}/releases"
-145
View File
@@ -1,145 +0,0 @@
name: Build Windows
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
workflow_dispatch:
jobs:
# 先编译 libcore
build-libcore:
name: 编译 libcore (Windows)
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 🔧 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
cache-dependency-path: libcore/go.sum
- name: 🔧 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 🔧 安装 MinGW
run: |
sudo apt-get update
sudo apt-get install -y mingw-w64
- name: 📦 编译 libcore.dll
working-directory: libcore
run: |
echo "🚀 开始编译 Windows libcore..."
make windows-amd64
if [ -f "bin/libcore.dll" ] && [ -f "bin/HiddifyCli.exe" ]; then
echo "✅ Windows libcore 编译成功"
ls -lh bin/
else
echo "❌ Windows libcore 编译失败"
exit 1
fi
- name: 📤 上传 Windows libcore
uses: actions/upload-artifact@v4
with:
name: libcore-windows
path: |
libcore/bin/libcore.dll
libcore/bin/HiddifyCli.exe
libcore/bin/webui/**
retention-days: 7
# 构建 Windows 应用
build:
runs-on: windows-latest
needs: build-libcore
steps:
- name: 📥 Checkout 代码
uses: actions/checkout@v4
- name: 📥 下载 libcore
uses: actions/download-artifact@v4
with:
name: libcore-windows
path: .
- name: 🔧 复制 libcore 文件到正确位置并重命名
run: |
Write-Host "📋 复制 libcore 文件..."
# 创建目标目录
New-Item -ItemType Directory -Force -Path libcore\bin
# 查找并复制 HiddifyCli.exe,重命名为 BearVPNCli.exe
$exeFiles = Get-ChildItem -Recurse -Filter "HiddifyCli.exe" -ErrorAction SilentlyContinue
if ($exeFiles) {
$sourceExe = $exeFiles[0].FullName
Write-Host "✅ 找到 HiddifyCli.exe: $sourceExe"
Write-Host "📝 复制并重命名为 BearVPNCli.exe"
Copy-Item $sourceExe libcore\bin\BearVPNCli.exe
Write-Host "✅ 重命名完成:HiddifyCli.exe → BearVPNCli.exe"
} else {
Write-Host "⚠️ 未找到 HiddifyCli.exe"
}
# 复制 libcore.dll
$dllFiles = Get-ChildItem -Recurse -Filter "libcore.dll" -ErrorAction SilentlyContinue
if ($dllFiles) {
$sourceDll = $dllFiles[0].FullName
Write-Host "✅ 找到 libcore.dll: $sourceDll"
Copy-Item $sourceDll libcore\bin\libcore.dll
} else {
Write-Host "⚠️ 未找到 libcore.dll"
}
Write-Host ""
Write-Host "📄 验证文件:"
if (Test-Path libcore\bin) {
Get-ChildItem libcore\bin\ -ErrorAction SilentlyContinue | Format-Table Name, Length
}
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.24.5'
channel: 'stable'
- name: Enable Windows desktop
run: flutter config --enable-windows-desktop
- name: Get dependencies
run: flutter pub get
- name: Generate code
run: dart run build_runner build --delete-conflicting-outputs
- name: Build Windows Debug
run: flutter build windows
- name: Build Windows Release
run: flutter build windows --release
- name: Upload Debug build artifacts
uses: actions/upload-artifact@v4
with:
name: windows-debug-build
path: build/windows/runner/Debug/
- name: Upload Release build artifacts
uses: actions/upload-artifact@v4
with:
name: windows-release-build
path: build/windows/runner/Release/
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 24 KiB

@@ -14,7 +14,7 @@ class ActiveGroupsChannel(private val scope: CoroutineScope) : FlutterPlugin,
CommandClient.Handler {
companion object {
const val TAG = "A/ActiveGroupsChannel"
const val CHANNEL = "com.baer.app/active-groups"
const val CHANNEL = "com.hi.app/active-groups"
val gson = Gson()
}
@@ -12,8 +12,8 @@ class EventHandler : FlutterPlugin {
companion object {
const val TAG = "A/EventHandler"
const val SERVICE_STATUS = "com.baer.app/service.status"
const val SERVICE_ALERTS = "com.baer.app/service.alerts"
const val SERVICE_STATUS = "com.hi.app/service.status"
const val SERVICE_ALERTS = "com.hi.app/service.alerts"
}
private var statusChannel: EventChannel? = null
@@ -12,7 +12,7 @@ import kotlinx.coroutines.CoroutineScope
class GroupsChannel(private val scope: CoroutineScope) : FlutterPlugin, CommandClient.Handler {
companion object {
const val TAG = "A/GroupsChannel"
const val CHANNEL = "com.baer.app/groups"
const val CHANNEL = "com.hi.app/groups"
val gson = Gson()
}
@@ -9,7 +9,7 @@ class LogHandler : FlutterPlugin {
companion object {
const val TAG = "A/LogHandler"
const val SERVICE_LOGS = "com.baer.app/service.logs"
const val SERVICE_LOGS = "com.hi.app/service.logs"
}
private lateinit var logsChannel: EventChannel
@@ -21,7 +21,7 @@ class MethodHandler(private val scope: CoroutineScope) : FlutterPlugin,
companion object {
const val TAG = "A/MethodHandler"
const val channelName = "com.baer.app/method"
const val channelName = "com.hi.app/method"
enum class Trigger(val method: String) {
Setup("setup"),
@@ -33,7 +33,7 @@ class PlatformSettingsHandler : FlutterPlugin, MethodChannel.MethodCallHandler,
private lateinit var ignoreRequestResult: MethodChannel.Result
companion object {
const val channelName = "com.baer.app/platform"
const val channelName = "com.hi.app/platform"
const val REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = 44
val gson = Gson()
@@ -11,7 +11,7 @@ import kotlinx.coroutines.CoroutineScope
class StatsChannel(private val scope: CoroutineScope) : FlutterPlugin, CommandClient.Handler{
companion object {
const val TAG = "A/StatsChannel"
const val STATS_CHANNEL = "com.baer.app/stats"
const val STATS_CHANNEL = "com.hi.app/stats"
}
private val commandClient =
@@ -1,7 +1,7 @@
package com.hiddify.hiddify.constant
object Action {
const val SERVICE = "com.baer.app.SERVICE"
const val SERVICE_CLOSE = "com.baer.app.SERVICE_CLOSE"
const val SERVICE_RELOAD = "com.baer.app.sfa.SERVICE_RELOAD"
const val SERVICE = "com.hi.app.SERVICE"
const val SERVICE_CLOSE = "com.hi.app.SERVICE_CLOSE"
const val SERVICE_RELOAD = "com.hi.app.sfa.SERVICE_RELOAD"
}
+1 -1
View File
@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xlint:-options
org.gradle.jvmargs=-Xmx4048m -Dfile.encoding=UTF-8
android.useAndroidX=true
android.enableJetifier=true
# org.gradle.java.home=/Users/mac/Library/Java/JavaVirtualMachines/ms-17.0.16/Contents/Home
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -75,7 +75,7 @@
"codeSentCountdown": "验证码已发送 {seconds}s",
"and": "和",
"enterInviteCode": "请输入邀请码",
"registerSuccess": "注册成功"
"registerSuccess": "注册成功",
"search": "搜索",
"selectOtherRegion": "选择其他地区"
},
+50
View File
@@ -0,0 +1,50 @@
@echo off
echo 📋 复制 libcore 文件...
:: 创建目标目录
mkdir libcore\bin >nul 2>&1
:: 查找并复制 HiddifyCli.exe,重命名为 HiFastVPNCli.exe
for /r %%f in (HiddifyCli.exe) do (
if exist "%%f" (
echo ✅ 找到 HiddifyCli.exe: %%f
echo 📝 复制并重命名为 HiFastVPNCli.exe
copy "%%f" libcore\bin\HiFastVPNCli.exe
echo ✅ 重命名完成
goto :dll
)
)
echo ⚠️ 未找到 HiddifyCli.exe
:dll
:: 复制 libcore.dll
for /r %%f in (libcore.dll) do (
if exist "%%f" (
echo ✅ 找到 libcore.dll: %%f
copy "%%f" libcore\bin\libcore.dll
goto :verify
)
)
echo ⚠️ 未找到 libcore.dll
:verify
echo.
echo 📄 验证文件:
if exist libcore\bin (
dir libcore\bin
if exist libcore\bin\HiFastVPNCli.exe (
if exist libcore\bin\libcore.dll (
echo ✅ 验证成功:所有文件已正确复制
exit /b 0
) else (
echo ❌ 验证失败:libcore.dll 不存在
exit /b 1
)
) else (
echo ❌ 验证失败:HiFastVPNCli.exe 不存在
exit /b 1
)
) else (
echo ⚠️ libcore\bin 目录不存在
exit /b 1
)
+35
View File
@@ -0,0 +1,35 @@
@echo off
REM Fix NuGet installation using Chocolatey
echo Installing NuGet via Chocolatey...
REM Check if Chocolatey is available
where choco >nul 2>nul
if %errorlevel% neq 0 (
echo Chocolatey not found, installing Chocolatey first...
powershell -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"
)
echo Installing NuGet via Chocolatey...
choco install nuget.commandline -y
if %errorlevel% equ 0 (
echo SUCCESS: NuGet installed via Chocolatey
echo Updating PATH...
set PATH=C:\ProgramData\chocolatey\bin;%PATH%
setx PATH "C:\ProgramData\chocolatey\bin;%PATH%"
echo Verifying installation...
nuget help | findstr "NuGet"
if %errorlevel% equ 0 (
echo NuGet is working correctly!
) else (
echo WARNING: NuGet installed but not accessible
)
) else (
echo ERROR: NuGet installation failed
exit /b 1
)
pause
+67
View File
@@ -0,0 +1,67 @@
# NuGet 安装脚本 - 解决 SSL 问题
Write-Host "=== 安装 NuGet ===" -ForegroundColor Green
# 设置 TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# 检查是否已安装
$nugetExists = Get-Command nuget -ErrorAction SilentlyContinue
if ($nugetExists) {
Write-Host "NuGet 已安装: $($nugetExists.Source)" -ForegroundColor Green
exit 0
}
# 下载 NuGet
Write-Host "下载 NuGet CLI..." -ForegroundColor Yellow
$downloadUrls = @(
"https://dist.nuget.org/win-x86-commandline/latest/nuget.exe",
"https://dist.nuget.org/win-x86-commandline/v6.7.0/nuget.exe",
"http://dist.nuget.org/win-x86-commandline/v6.7.0/nuget.exe"
)
$downloaded = $false
foreach ($url in $downloadUrls) {
try {
Write-Host "尝试下载: $url"
$webClient = New-Object System.Net.WebClient
$webClient.DownloadFile($url, "C:\nuget.exe")
$downloaded = $true
Write-Host "下载成功!" -ForegroundColor Green
break
} catch {
Write-Host "下载失败: $($_.Exception.Message)" -ForegroundColor Red
continue
}
}
if (-not $downloaded) {
Write-Host "所有下载都失败了,尝试使用 Chocolatey..." -ForegroundColor Yellow
try {
choco install nuget.commandline -y
if (Get-Command nuget -ErrorAction SilentlyContinue) {
Write-Host "通过 Chocolatey 安装成功!" -ForegroundColor Green
exit 0
}
} catch {
Write-Host "Chocolatey 安装也失败了: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host "NuGet 安装失败,但继续构建..." -ForegroundColor Yellow
exit 0
}
# 验证安装
if (Test-Path "C:\nuget.exe") {
$env:PATH = "C:\;$env:PATH"
Write-Host "NuGet 安装完成" -ForegroundColor Green
# 测试
try {
$version = & "C:\nuget.exe" help | Select-String -Pattern "NuGet Version" | Select-Object -First 1
Write-Host "版本信息: $version" -ForegroundColor Green
} catch {
Write-Host "NuGet 可用,但版本检查失败" -ForegroundColor Yellow
}
} else {
Write-Host "NuGet 文件不存在" -ForegroundColor Red
}
+64
View File
@@ -0,0 +1,64 @@
# Windows 构建修复脚本
# 以管理员身份运行
Write-Host "=== Windows Flutter 构建修复 ===" -ForegroundColor Green
# 1. 安装 NuGet
Write-Host "`n1. 安装 NuGet..." -ForegroundColor Yellow
$nugetPath = "C:\nuget.exe"
if (-not (Test-Path $nugetPath)) {
try {
Write-Host "下载 NuGet..."
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile $nugetPath
$env:PATH = "C:\;$env:PATH"
Write-Host "NuGet 安装成功" -ForegroundColor Green
} catch {
Write-Host "NuGet 下载失败: $_" -ForegroundColor Red
exit 1
}
} else {
Write-Host "NuGet 已存在" -ForegroundColor Green
}
# 2. 启用长路径支持
Write-Host "`n2. 启用长路径支持..." -ForegroundColor Yellow
try {
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Type DWORD -Force
Write-Host "长路径支持已启用" -ForegroundColor Green
} catch {
Write-Host "长路径设置失败: $_" -ForegroundColor Red
}
# 3. 清理构建缓存
Write-Host "`n3. 清理构建缓存..." -ForegroundColor Yellow
if (Test-Path "build") {
Remove-Item -Path "build" -Recurse -Force
Write-Host "Build 目录已清理" -ForegroundColor Green
}
if (Test-Path "windows") {
Remove-Item -Path "windows" -Recurse -Force
Write-Host "Windows 目录已清理" -ForegroundColor Green
}
# 4. 重新创建 Windows 项目
Write-Host "`n4. 重新创建 Windows 项目..." -ForegroundColor Yellow
flutter create --platforms=windows .
# 5. 获取依赖
Write-Host "`n5. 获取依赖..." -ForegroundColor Yellow
flutter pub get
# 6. 构建 Debug 版本
Write-Host "`n6. 构建 Debug 版本..." -ForegroundColor Yellow
flutter build windows
if ($LASTEXITCODE -eq 0) {
Write-Host "`n=== 构建成功! ===" -ForegroundColor Green
Write-Host "输出目录: build\windows\runner\Debug\" -ForegroundColor Cyan
} else {
Write-Host "`n=== 构建失败 ===" -ForegroundColor Red
Write-Host "请检查错误信息并尝试手动修复" -ForegroundColor Red
}
Write-Host "`n修复完成!" -ForegroundColor Green
+64
View File
@@ -0,0 +1,64 @@
@echo off
:: This script checks for and installs all necessary tools for building and packaging the Flutter application on Windows.
:: 1. Check for Administrator Privileges
net session >nul 2>&1
if %errorLevel% == 0 (
echo Administrator privileges detected. Continuing...
) else (
echo Requesting Administrator privileges to install tools...
powershell -Command "Start-Process cmd.exe -ArgumentList '/c %~s0' -Verb RunAs" >nul 2>&1
exit /b
)
:: 2. Check for and Install Chocolatey
echo.
echo === Checking for Chocolatey ===
where choco >nul 2>&1
if %errorlevel% equ 0 (
echo Chocolatey is already installed.
) else (
echo Chocolatey not found. Installing now...
powershell -NoProfile -ExecutionPolicy Bypass -Command "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"
if %errorlevel% neq 0 (
echo ERROR: Failed to install Chocolatey. Please install it manually from https://chocolatey.org
pause
exit /b 1
)
echo Chocolatey installed successfully.
:: Add Chocolatey to the PATH for the current session
set "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
)
:: 3. Install Required Tools via Chocolatey
echo.
echo === Installing Build Tools (7-Zip and Enigma Virtual Box) ===
:: Install 7-Zip
echo Installing 7-Zip...
choco install 7zip -y
if %errorlevel% neq 0 (
echo ERROR: Failed to install 7-Zip.
pause
exit /b 1
)
echo 7-Zip installed successfully.
:: Install Enigma Virtual Box
echo Installing Enigma Virtual Box...
choco install enigma-virtual-box -y
if %errorlevel% neq 0 (
echo ERROR: Failed to install Enigma Virtual Box.
pause
exit /b 1
)
echo Enigma Virtual Box installed successfully.
echo.
echo =======================================================
echo All required build tools have been installed.
echo You can now use 'package_windows_single_exe.ps1' to build your single-file executable.
echo =======================================================
echo.
pause
+44
View File
@@ -0,0 +1,44 @@
@echo off
REM Simple Flutter installer for Windows Gitea Runner
echo Installing Flutter for Windows...
REM Create flutter directory
mkdir C:\flutter 2>nul
REM Download Flutter stable version
echo Downloading Flutter...
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.24.5-stable.zip', 'C:\flutter.zip')"
if %errorlevel% neq 0 (
echo Download failed, trying alternative...
powershell -Command "Invoke-WebRequest -Uri 'https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.24.5-stable.zip' -OutFile 'C:\flutter.zip'"
)
REM Extract Flutter
echo Extracting Flutter...
powershell -Command "Expand-Archive -Path 'C:\flutter.zip' -DestinationPath 'C:\' -Force"
REM Set PATH
echo Setting PATH...
set PATH=C:\flutter\bin;%PATH%
setx PATH "C:\flutter\bin;%PATH%"
REM Clean up
del C:\flutter.zip
REM Verify installation
echo Verifying Flutter installation...
C:\flutter\bin\flutter --version
if %errorlevel% equ 0 (
echo SUCCESS: Flutter installed successfully
echo Running flutter doctor...
C:\flutter\bin\flutter doctor
) else (
echo ERROR: Flutter installation failed
exit /b 1
)
echo Flutter installation complete!
pause
+39
View File
@@ -0,0 +1,39 @@
@echo off
REM Simple NuGet installer for Windows
echo Installing NuGet...
REM Check if NuGet exists
where nuget >nul 2>nul
if %errorlevel% == 0 (
echo NuGet already installed
nuget help | findstr "NuGet"
pause
exit /b 0
)
REM Download NuGet using PowerShell
echo Downloading NuGet CLI...
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://dist.nuget.org/win-x86-commandline/v6.7.0/nuget.exe', 'C:\nuget.exe')"
if %errorlevel% neq 0 (
echo Download failed, trying alternative...
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/v6.7.0/nuget.exe', 'C:\nuget.exe')"
)
REM Add to PATH
set PATH=C:\;%PATH%
setx PATH "C:\;%PATH%"
REM Verify installation
echo Verifying NuGet installation...
C:\nuget.exe help | findstr "NuGet"
if %errorlevel% equ 0 (
echo SUCCESS: NuGet installed successfully
) else (
echo ERROR: NuGet installation failed
exit /b 1
)
pause
+2 -2
View File
@@ -5,6 +5,6 @@
// Created by GFWFighter on 7/24/1402 AP.
//
BASE_BUNDLE_IDENTIFIER=app.baer.com
SERVICE_IDENTIFIER=com.baer.app
BASE_BUNDLE_IDENTIFIER=app.hi.com
SERVICE_IDENTIFIER=com.hi.app
DEVELOPMENT_TEAM=3UR892FAP3
@@ -10,7 +10,7 @@
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.baer.com</string>
<string>group.app.hi.com</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
+10 -10
View File
@@ -75,21 +75,21 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
EasyPermissionX: ff4c438f6ee80488f873b4cb921e32d982523067
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_udid: b2417673f287ee62817a1de3d1643f47b9f508ab
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
webview_flutter_wkwebview: a4af96a051138e28e29f60101d094683b9f82188
PODFILE CHECKSUM: 579a354deb8d6fdc55c12799569018594328642e
COCOAPODS: 1.16.2
COCOAPODS: 1.15.2
+9 -15
View File
@@ -814,11 +814,9 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnelRelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3UR892FAP3;
DEVELOPMENT_TEAM = Q5PC7SNX27;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
EXCLUDED_ARCHS = armv7;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -844,7 +842,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = hitoPacketTunnel;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
@@ -868,11 +865,9 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/HiddifyPacketTunnel.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3UR892FAP3;
DEVELOPMENT_TEAM = Q5PC7SNX27;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
EXCLUDED_ARCHS = armv7;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -898,7 +893,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = hitoPacketTunnel;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
@@ -986,6 +980,7 @@
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
@@ -1216,6 +1211,7 @@
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
@@ -1261,15 +1257,14 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3UR892FAP3;
DEVELOPMENT_TEAM = Q5PC7SNX27;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = armv7;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(PROJECT_DIR)/build/ios/framework/$(CONFIGURATION)",
"$(PROJECT_DIR)/../build/ios/framework/$(CONFIGURATION)",
@@ -1295,7 +1290,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = rls;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 844 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

+3 -3
View File
@@ -9,7 +9,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>BearVPN</string>
<string>Hi快VPN</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -30,10 +30,10 @@
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.BearVPN.ios</string>
<string>com.hi.ios</string>
<key>CFBundleURLSchemes</key>
<array>
<string>hiddify</string>
<string>HiFastVPN</string>
</array>
</dict>
</array>
+1 -1
View File
@@ -12,7 +12,7 @@
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.$(BASE_BUNDLE_IDENTIFIER)</string>
<string>group.app.hi.com</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
+1 -1
View File
@@ -12,7 +12,7 @@
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.baer.com</string>
<string>group.app.hi.com</string>
</array>
<key>com.apple.security.network.client</key>
<true/>
+1 -1
View File
@@ -102,7 +102,7 @@ class VPNManager: ObservableObject {
`protocol`.providerBundleIdentifier = Bundle.main.baseBundleIdentifier + ".PacketTunnel"
`protocol`.serverAddress = "localhost"
newManager.protocolConfiguration = `protocol`
newManager.localizedDescription = "BearVPN"
newManager.localizedDescription = "HiFastVPN"
try await newManager.saveToPreferences()
try await newManager.loadFromPreferences()
self.manager = newManager
+1 -1
View File
@@ -1255,7 +1255,7 @@ class AppConfig {
/// 建议:
/// - 测试版本、Beta 版本:设置为 true
/// - 正式生产版本:根据需要设置为 false(或在遇到问题时临时开启)
static const bool enableInitLogCollection = true;
static const bool enableInitLogCollection = false;
/// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/// 加密密钥配置
@@ -29,14 +29,15 @@ class HINodeListView extends GetView<HINodeListController> {
/// 获取用于显示的延迟值
int _getDisplayDelay(HINodeListController controller, KROutboundItem item) {
if (controller.homeController.kr_isConnected.value) {
return item.urlTestDelay.value;
}
if (!_fakeDelays.containsKey(item.tag)) {
final random = Random();
_fakeDelays[item.tag] = 30 + random.nextInt(71); // 30-100ms
}
return _fakeDelays[item.tag] ?? 0;
return item.urlTestDelay.value;
// if (controller.homeController.kr_isConnected.value) {
//
// }
// if (!_fakeDelays.containsKey(item.tag)) {
// final random = Random();
// _fakeDelays[item.tag] = 30 + random.nextInt(71); // 30-100ms
// }
// return _fakeDelays[item.tag] ?? 0;
}
/// 获取分组内最快节点的延迟值(单位:ms)
File diff suppressed because it is too large Load Diff
@@ -7,6 +7,8 @@ import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:kaer_with_panels/app/services/global_overlay_service.dart';
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';
///
class HIAnimatedConnectButton extends GetView<KRHomeController> {
@@ -20,9 +22,18 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
@override
Widget build(BuildContext context) {
return Obx(() {
final isConnected = controller.kr_isConnected.value;
final delay = controller.kr_currentNodeLatency.value;
print('当前连接情况$delay----$isConnected');
// 🔧 : observable
final _ = KRSingBoxImp.instance.kr_status.value; //
final isConnected = controller.kr_isConnected.value; // 使 controller
//
final status = KRSingBoxImp.instance.kr_status.value;
final isSwitching = status is SingboxStarting || status is SingboxStopping;
print('🔵 Switch UI 更新: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
final isShow = isConnected; // delay == -1 || isConnected;
final Color buttonColor = Theme.of(context).primaryColor;
@@ -71,6 +82,10 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
if(isSwitching) {
print('🔵 Switch UI 正在更新,切换中点击了按钮: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
return;
}
final hasValidSubscription =
controller.kr_subscribeService.kr_availableSubscribes.isNotEmpty;
if (hasValidSubscription) {
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../localization/app_translations.dart';
import '../../../widgets/kr_app_text_style.dart';
import '../../../widgets/kr_loading_animation.dart';
@@ -107,6 +106,7 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
//
Builder(builder: (context) {
KRLogUtil.kr_i('🔹 渲染订阅卡片,margin: top=${12}, left=${12}, right=${12}', tag: 'HomeBottomPanel');
return Container(
margin: EdgeInsets.only(top: 12, left: 12, right: 12),
child: const KRSubscriptionCard(),
@@ -160,7 +160,7 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Get.context!.theme.cardColor,
borderRadius: BorderRadius.circular(12.r),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
@@ -180,7 +180,7 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
Text(
'正在加载...',
style: TextStyle(
fontSize: 14.sp,
fontSize: 14,
color: Get.context!.theme.textTheme.bodyMedium?.color,
),
),
@@ -233,7 +233,7 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
foregroundColor: Theme.of(context).colorScheme.onPrimary,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
borderRadius: BorderRadius.circular(8),
),
),
child: Text(
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../widgets/kr_simple_loading.dart';
import 'package:kaer_with_panels/app/widgets/kr_country_flag.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
@@ -1,7 +1,5 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:kaer_with_panels/app/widgets/kr_country_flag.dart';
@@ -27,24 +25,17 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
static const Color krModernGreen = Color(0xFF4CAF50);
static const Color krModernGreenLight = Color(0xFF81C784);
//
static final Map<String, int> _fakeDelays = {};
// 🔧
static bool _hasTriggeredAutoTest = false;
///
/// TCP
int _getDisplayDelay(KRHomeController controller, KROutboundItem item) {
// 使
if (controller.kr_isConnected.value) {
return item.urlTestDelay.value;
}
// 使
if (!_fakeDelays.containsKey(item.tag)) {
// 30ms-100ms之间的随机延迟
final random = Random();
_fakeDelays[item.tag] = 30 + random.nextInt(71); // 30 + (0-70) = 30-100ms
}
return _fakeDelays[item.tag] ?? 0;
//
// VPN使 item.urlTestDelay.value
// - SingBox
// - TCP Socket
return item.urlTestDelay.value;
}
@override
@@ -71,20 +62,20 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
///
Widget _buildServerList(BuildContext context) {
return Container(
width: ScreenUtil().screenWidth,
height: 360.h, //
width: MediaQuery.of(context).size.width,
height: 360, //
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.w),
topRight: Radius.circular(20.w),
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
children: [
//
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -103,7 +94,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
},
child: Icon(
Icons.close,
size: 24.w,
size: 24,
color: Theme.of(context).textTheme.bodyMedium?.color,
),
),
@@ -125,19 +116,19 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
);
}
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: controller.kr_subscribeService.groupOutboundList.length,
itemBuilder: (context, index) {
final group =
controller.kr_subscribeService.groupOutboundList[index];
return Container(
margin: EdgeInsets.only(bottom: 8.w),
margin: EdgeInsets.only(bottom: 8),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(12.w),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Theme.of(context).dividerColor.withOpacity(0.1),
width: 1.w,
width: 1,
),
),
child: InkWell(
@@ -146,18 +137,18 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
controller.kr_currentListStatus.value =
KRHomeViewsListStatus.kr_serverSubscribeList;
},
borderRadius: BorderRadius.circular(12.w),
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: EdgeInsets.all(12.w),
padding: EdgeInsets.all(12),
child: Row(
children: [
KRNetworkImage(
kr_imageUrl: group.icon,
kr_width: 32.w,
kr_height: 32.w,
kr_width: 32,
kr_height: 32,
kr_fit: BoxFit.cover,
),
SizedBox(width: 12.w),
SizedBox(width: 12),
Expanded(
child: Text(
group.tag,
@@ -171,7 +162,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
Icon(
Icons.arrow_forward_ios,
size: 16.w,
size: 16,
color: Theme.of(context).textTheme.bodySmall?.color,
),
],
@@ -208,7 +199,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
return _kr_buildListContainer(
context,
child: ListView.builder(
padding: EdgeInsets.fromLTRB(16.w, 8.w, 16.w, 0),
padding: EdgeInsets.fromLTRB(16, 8, 16, 0),
itemCount:
controller.kr_subscribeService.countryOutboundList.length,
itemBuilder: (context, index) {
@@ -222,15 +213,15 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
country.isExpand.value = !country.isExpand.value;
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 12.h),
padding: EdgeInsets.symmetric(vertical: 12),
child: Row(
children: [
KRCountryFlag(
countryCode: country.country,
width: 40.w,
height: 40.w,
width: 40,
height: 40,
),
SizedBox(width: 12.w),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -255,7 +246,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
country.isExpand.value
? Icons.keyboard_arrow_down
: Icons.arrow_forward_ios,
size: 16.w,
size: 16,
color:
Theme.of(context).textTheme.bodySmall?.color,
);
@@ -272,7 +263,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.only(left: 24.w),
padding: EdgeInsets.only(left: 24),
itemCount: country.outboundList.length,
itemBuilder: (context, index) {
final server = country.outboundList[index];
@@ -311,13 +302,13 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
},
child: Container(
padding: EdgeInsets.symmetric(
vertical: 8.h,
horizontal: 16.w,
vertical: 8,
horizontal: 16,
),
decoration: BoxDecoration(
//
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(8.w),
borderRadius: BorderRadius.circular(8),
),
child: _kr_buildNodeListItem(
context,
@@ -328,9 +319,9 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
// 线
if (index < country.outboundList.length - 1)
Divider(
height: 1.w,
indent: 16.w,
endIndent: 16.w,
height: 1,
indent: 16,
endIndent: 16,
color: Theme.of(context)
.dividerColor
.withOpacity(0.1),
@@ -341,7 +332,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
);
}),
Divider(
height: 1.w,
height: 1,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
],
@@ -377,7 +368,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
return _kr_buildListContainer(
context,
child: ListView.builder(
padding: EdgeInsets.fromLTRB(16.w, 16.w, 16.w, 0),
padding: EdgeInsets.fromLTRB(16, 16, 16, 0),
itemCount: servers.length,
itemBuilder: (context, index) {
final server = servers[index];
@@ -406,7 +397,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
}
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 4.h),
padding: EdgeInsets.symmetric(vertical: 4),
child: _kr_buildNodeListItem(
context,
item: server,
@@ -415,7 +406,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
if (index < servers.length - 1)
Divider(
height: 1.w,
height: 1,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
],
@@ -435,12 +426,12 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
required Widget listContent,
}) {
return Container(
width: ScreenUtil().screenWidth,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.w),
topRight: Radius.circular(20.w),
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
@@ -453,13 +444,13 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
onClose: () =>
controller.kr_currentListStatus.value = KRHomeViewsListStatus.kr_none,
),
SizedBox(height: 16.h),
SizedBox(height: 16),
Expanded(
child: Column(
children: [
Expanded(child: listContent),
//
SizedBox(height: 12.h),
SizedBox(height: 12),
],
),
),
@@ -476,7 +467,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
VoidCallback? onClose,
}) {
return Padding(
padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 16.w),
padding: EdgeInsets.only(left: 16, right: 16, top: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -487,11 +478,11 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
onTap: onBack,
child: Icon(
Icons.arrow_back_ios,
size: 20.w,
size: 20,
color: Theme.of(context).textTheme.bodyMedium?.color,
),
),
SizedBox(width: 8.w),
SizedBox(width: 8),
],
Text(
title,
@@ -508,7 +499,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
onTap: onClose,
child: Icon(
Icons.close,
size: 24.w,
size: 24,
color: Theme.of(context).textTheme.bodyMedium?.color,
),
),
@@ -524,10 +515,10 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
required Widget child,
}) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
margin: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(12.w),
borderRadius: BorderRadius.circular(12),
),
child: child,
);
@@ -553,17 +544,17 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
return Container(
key: ValueKey(item.id),
padding: EdgeInsets.symmetric(vertical: 8.h),
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 🔧
KRCountryFlag(
countryCode: item.country,
width: 36.w,
height: 36.w,
width: 36,
height: 36,
),
SizedBox(width: 8.w),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -582,12 +573,12 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
Obx(
() => controller.kr_cutTag.value == item.tag
? Container(
margin: EdgeInsets.only(left: 4.w),
margin: EdgeInsets.only(left: 4),
padding: EdgeInsets.symmetric(
horizontal: 4.w, vertical: 1.h),
horizontal: 4, vertical: 1),
decoration: BoxDecoration(
color: krModernGreenLight.withOpacity(0.1),
borderRadius: BorderRadius.circular(4.w),
borderRadius: BorderRadius.circular(4),
),
child: Text(
AppTranslations.kr_home.selected,
@@ -602,7 +593,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
],
),
SizedBox(height: 2.h),
SizedBox(height: 2),
Text(
item.city,
style: KrAppTextStyle(
@@ -659,30 +650,33 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
);
}
//
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!controller.kr_isConnected.value && !controller.kr_isLatency.value) {
KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试', tag: 'NodeListView');
controller.kr_urlTest();
}
});
// 🔧
if (!_hasTriggeredAutoTest) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!controller.kr_isConnected.value && !controller.kr_isLatency.value && !_hasTriggeredAutoTest) {
_hasTriggeredAutoTest = true; //
KRLogUtil.kr_i('🔄 节点列表显示 - 自动触发延迟测试(首次)', tag: 'NodeListView');
controller.kr_urlTest();
}
});
}
return _kr_buildListContainer(
context,
child: ListView(
padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 0),
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
children: [
//
InkWell(
onTap: () => controller.kr_urlTest(),
child: Container(
padding: EdgeInsets.symmetric(vertical: 8.h),
margin: EdgeInsets.only(top: 8.w), //
padding: EdgeInsets.symmetric(vertical: 8),
margin: EdgeInsets.only(top: 8), //
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 36.w,
height: 36.w,
width: 36,
height: 36,
decoration: BoxDecoration(
color: krModernGreenLight.withOpacity(0.1),
shape: BoxShape.circle,
@@ -691,17 +685,17 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
child: controller.kr_isLatency.value
? KRSimpleLoading(
color: krModernGreen,
size: 24.w,
size: 24,
duration: const Duration(milliseconds: 800),
)
: Icon(
Icons.speed,
size: 24.w,
size: 24,
color: krModernGreen,
),
),
),
SizedBox(width: 8.w),
SizedBox(width: 8),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -728,7 +722,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
),
if (!controller.kr_isLatency.value) ...[
SizedBox(height: 2.h),
SizedBox(height: 2),
Text(
AppTranslations.kr_home.refreshLatencyDesc,
style: KrAppTextStyle(
@@ -746,7 +740,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
if (!controller.kr_isLatency.value)
Icon(
Icons.arrow_forward_ios,
size: 12.w,
size: 12,
color: Theme.of(context).textTheme.bodySmall?.color,
),
],
@@ -755,7 +749,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
// 线
Divider(
height: 16.w,
height: 16,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
// Auto
@@ -775,19 +769,19 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
}
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 8.h),
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
KrLocalImage(
imageName: "home_list_location",
width: 36.w,
height: 36.w,
width: 36,
height: 36,
color: controller.kr_cutTag.value == 'auto'
? Colors.green
: null,
),
SizedBox(width: 8.w),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -808,13 +802,13 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
if (controller.kr_cutTag.value == 'auto')
Container(
margin: EdgeInsets.only(left: 4.w),
margin: EdgeInsets.only(left: 4),
padding: EdgeInsets.symmetric(
horizontal: 4.w, vertical: 1.h),
horizontal: 4, vertical: 1),
decoration: BoxDecoration(
color:
krModernGreenLight.withOpacity(0.1),
borderRadius: BorderRadius.circular(4.w),
borderRadius: BorderRadius.circular(4),
),
child: Text(
AppTranslations.kr_home.selected,
@@ -827,7 +821,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
],
),
SizedBox(height: 2.h),
SizedBox(height: 2),
Obx(() {
//
String selectedNode =
@@ -903,7 +897,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
),
// 线
Divider(
height: 16.w,
height: 16,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
//
@@ -929,7 +923,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
}
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 4.h),
padding: EdgeInsets.symmetric(vertical: 4),
child: _kr_buildNodeListItem(
context,
item: node,
@@ -939,7 +933,7 @@ class KRHomeNodeListView extends GetView<KRHomeController> {
if (node !=
controller.kr_subscribeService.allList.last)
Divider(
height: 1.w,
height: 1,
color: Theme.of(context)
.dividerColor
.withOpacity(0.1),
@@ -1,11 +1,8 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart';
import 'package:kaer_with_panels/app/utils/kr_subscribe_navigation_util.dart';
import '../../../widgets/kr_app_text_style.dart';
///
@@ -24,13 +21,6 @@ class KRSubscriptionCard extends StatelessWidget {
//
Widget _kr_buildSubscriptionCard(BuildContext context) {
// 🔧
print('🎴 [SubscriptionCard] 开始构建订阅卡片');
print('🎴 [SubscriptionCard] 卡片颜色: ${Theme.of(context).cardColor}');
print('🎴 [SubscriptionCard] 主题亮度: ${Theme.of(context).brightness}');
print('🎴 [SubscriptionCard] 文本颜色: ${Theme.of(context).textTheme.bodyMedium?.color}');
print('🎴 [SubscriptionCard] ScreenUtil 测试 - 12.w=${12.w}, 16.h=${16.h}, 44.w=${44.w}');
// 🔧 ScreenUtil使
return Container(
//
@@ -82,7 +72,6 @@ class KRSubscriptionCard extends StatelessWidget {
height: 46,
child: ElevatedButton(
onPressed: () {
print('🎴 [SubscriptionCard] 订阅按钮被点击');
KRSubscribeNavigationUtil.navigateToPurchase(tag: 'SubscriptionCard');
},
style: ElevatedButton.styleFrom(
@@ -114,10 +103,10 @@ class KRSubscriptionCard extends StatelessWidget {
bool addBottomPadding = true,
}) {
return Container(
margin: margin ?? EdgeInsets.symmetric(horizontal: 16.w),
margin: margin ?? EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(12.w),
borderRadius: BorderRadius.circular(12),
),
child: IntrinsicWidth(
child: child,
@@ -5,6 +5,8 @@ import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import '../../../common/app_run_data.dart';
import '../../../common/app_config.dart';
@@ -13,6 +15,7 @@ import '../../../model/response/kr_payment_methods.dart';
import '../../../routes/app_pages.dart';
import '../../../services/api_service/kr_api.user.dart';
import '../../../utils/kr_event_bus.dart';
import '../../../network/http_util.dart';
import 'package:flutter/foundation.dart';
///
@@ -47,8 +50,28 @@ class KRPurchaseMembershipController extends GetxController {
RxInt _kr_balance = 0.obs;
@override
void onInit() {
void onInit() async {
super.onInit();
print('💳 [PurchaseMembership] ========== Controller.onInit 被调用 ==========');
print('💳 [PurchaseMembership] 当前时间: ${DateTime.now()}');
// 🔧 Controller被初始化
try {
final dir = await getApplicationDocumentsDirectory();
final debugFile = File('${dir.path}/PURCHASE_CONTROLLER_DEBUG.txt');
await debugFile.writeAsString(
'=' * 60 + '\n'
'💳 PurchaseMembershipController.onInit 被调用!\n'
'时间: ${DateTime.now()}\n'
'版本标识: Android15_Fix_v6_Final\n'
'=' * 60 + '\n',
mode: FileMode.append,
);
print('💳 [PurchaseMembership] ✅ 调试日志已写入文件: ${debugFile.path}');
} catch (e) {
print('💳 [PurchaseMembership] ❌ 写入调试日志失败: $e');
}
kr_initializeData();
}
@@ -60,14 +83,24 @@ class KRPurchaseMembershipController extends GetxController {
///
Future<void> kr_initializeData() async {
print('💳 [PurchaseMembership] initializeData 开始');
kr_userEmail.value = KRAppRunData.getInstance().kr_account.toString();
await kr_getPackageList();
print('💳 [PurchaseMembership] 用户邮箱: ${kr_userEmail.value}');
// 🔧 onInit await
// API
print('💳 [PurchaseMembership] 开始异步加载套餐数据...');
kr_getPackageList().catchError((e) {
print('💳 [PurchaseMembership] ❌ 加载套餐数据异常: $e');
KRLogUtil.kr_e('加载套餐数据失败: $e', tag: 'PurchaseMembership');
});
//
_kr_eventWorker = KREventBus().kr_listenMessages(
[KRMessageType.kr_payment, KRMessageType.kr_subscribe_update],
_kr_handleMessage,
);
print('💳 [PurchaseMembership] initializeData 完成');
}
///
@@ -94,23 +127,102 @@ class KRPurchaseMembershipController extends GetxController {
///
Future<void> kr_getPackageList() async {
print('💳 [PurchaseMembership] ========== 开始获取套餐列表 ==========');
print('💳 [PurchaseMembership] 当前时间: ${DateTime.now()}');
kr_isLoading.value = true;
kr_selectedPlanIndex.value = 0; //
kr_selectedDiscountIndex.value = -1; //
kr_selectedPaymentMethodIndex.value = -1; //
await _iniUserInfo();
await kr_getAlreadySubscribe();
await kr_fetchPackages();
// await kr_fetchPaymentMethods(); // /v1/app/payment/methods
try {
// 🔧 API
print('💳 [PurchaseMembership] 步骤1: 开始初始化用户信息...');
await _iniUserInfo().timeout(
const Duration(seconds: 5),
onTimeout: () {
print('💳 [PurchaseMembership] ⚠️ 初始化用户信息超时');
KRLogUtil.kr_w('初始化用户信息超时', tag: 'PurchaseMembership');
},
);
print('💳 [PurchaseMembership] ✓ 步骤1完成');
//
await _kr_fetchPublicPaymentMethods();
print('💳 [PurchaseMembership] 步骤2: 开始获取已订阅套餐...');
await kr_getAlreadySubscribe().timeout(
const Duration(seconds: 5),
onTimeout: () {
print('💳 [PurchaseMembership] ⚠️ 获取已订阅套餐超时');
KRLogUtil.kr_w('获取已订阅套餐超时', tag: 'PurchaseMembership');
},
);
print('💳 [PurchaseMembership] ✓ 步骤2完成');
//
kr_showPlanSelector.value = kr_plans.length > 1;
print('💳 [PurchaseMembership] 步骤3: 开始获取套餐列表...');
await kr_fetchPackages().timeout(
const Duration(seconds: 8),
onTimeout: () {
print('💳 [PurchaseMembership] ❌ 获取套餐列表超时');
KRLogUtil.kr_e('获取套餐列表超时', tag: 'PurchaseMembership');
KRCommonUtil.kr_showToast('获取套餐列表超时,请检查网络');
},
);
print('💳 [PurchaseMembership] ✓ 步骤3完成,套餐数量: ${kr_plans.length}');
kr_isLoading.value = false;
//
print('💳 [PurchaseMembership] 步骤4: 开始获取支付方式...');
await _kr_fetchPublicPaymentMethods().timeout(
const Duration(seconds: 5),
onTimeout: () {
print('💳 [PurchaseMembership] ⚠️ 获取支付方式超时');
KRLogUtil.kr_w('获取支付方式超时', tag: 'PurchaseMembership');
},
);
print('💳 [PurchaseMembership] ✓ 步骤4完成,支付方式数量: ${kr_paymentMethods.length}');
//
kr_showPlanSelector.value = kr_plans.length > 1;
print('💳 [PurchaseMembership] ========== 所有步骤完成 ==========');
} catch (e, stackTrace) {
print('💳 [PurchaseMembership] ❌❌❌ 获取套餐数据失败: $e');
print('💳 [PurchaseMembership] StackTrace: $stackTrace');
KRLogUtil.kr_e('获取套餐数据失败: $e', tag: 'PurchaseMembership');
// 🔧 API失败时,
print('💳 [PurchaseMembership] 🔄 尝试切换域名并重试...');
bool domainSwitched = await KRDomain.kr_switchToNextDomain();
if (domainSwitched) {
print('💳 [PurchaseMembership] ✓ 域名切换成功,当前域名: ${KRDomain.kr_currentDomain}');
print('💳 [PurchaseMembership] 🔄 使用新域名重试...');
// HttpUtil baseUrl
HttpUtil.getInstance().updateBaseUrl();
// 500ms让域名生效
await Future.delayed(const Duration(milliseconds: 500));
//
try {
await kr_fetchPackages().timeout(
const Duration(seconds: 8),
onTimeout: () {
print('💳 [PurchaseMembership] ❌ 使用新域名后仍然超时');
KRLogUtil.kr_e('使用新域名后仍然超时', tag: 'PurchaseMembership');
},
);
print('💳 [PurchaseMembership] ✓ 使用新域名重试成功,套餐数量: ${kr_plans.length}');
} catch (retryError) {
print('💳 [PurchaseMembership] ❌ 使用新域名重试仍然失败: $retryError');
kr_errorMessage.value = '网络连接失败,请检查网络设置';
}
} else {
print('💳 [PurchaseMembership] ❌ 域名切换失败,所有域名都不可用');
kr_errorMessage.value = '无法连接服务器,请稍后重试';
}
} finally {
kr_isLoading.value = false;
print('💳 [PurchaseMembership] 加载状态设置为: false');
}
}
///
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
@@ -16,6 +15,7 @@ import 'package:kaer_with_panels/app/widgets/dialogs/kr_dialog.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'dart:convert';
import 'package:flutter_screenutil/flutter_screenutil.dart';
@@ -28,7 +28,7 @@ import 'package:kaer_with_panels/app/modules/kr_home/controllers/kr_home_control
import 'package:kaer_with_panels/app/modules/kr_home/models/kr_home_views_status.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';
// import 'package:kaer_with_panels/app/utils/kr_init_log_collector.dart';
import 'package:kaer_with_panels/app/utils/kr_init_log_collector.dart';
class KRSplashController extends GetxController {
// 🔧
@@ -311,6 +311,115 @@ class KRSplashController extends GetxController {
}
}
/// 🔧 Android 15
/// 使
Future<void> _executeMinimalInitialization() async {
try {
_initLog.logPhaseStart('降级初始化(Minimal Initialization');
_initLog.logWarning('网络初始化失败,执行降级策略', tag: 'Splash');
KRLogUtil.kr_i('🛡️ 执行最小化初始化(降级模式)', tag: 'SplashController');
if (kDebugMode) {
print('🛡️ 执行最小化初始化(降级模式)');
}
// 1.
try {
_initLog.log('步骤1: 设置默认域名', tag: 'Minimal');
if (KRDomain.kr_currentDomain.isEmpty && KRDomain.kr_baseDomains.isNotEmpty) {
KRDomain.kr_currentDomain = KRDomain.kr_baseDomains[0];
_initLog.logSuccess('设置默认域名: ${KRDomain.kr_currentDomain}', tag: 'Minimal');
KRLogUtil.kr_i('✅ 设置默认域名: ${KRDomain.kr_currentDomain}', tag: 'SplashController');
if (kDebugMode) {
print('✅ 设置默认域名: ${KRDomain.kr_currentDomain}');
}
} else {
_initLog.log('当前域名: ${KRDomain.kr_currentDomain}', tag: 'Minimal');
}
} catch (e) {
_initLog.logError('设置默认域名失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ 设置默认域名失败: $e', tag: 'SplashController');
}
// 2. SingBox
try {
_initLog.log('步骤2: 初始化 SingBox', tag: 'Minimal');
await KRSingBoxImp.instance.init().timeout(
const Duration(seconds: 3),
onTimeout: () {
_initLog.logWarning('SingBox 初始化超时(3秒)', tag: 'Minimal');
KRLogUtil.kr_w('SingBox 初始化超时', tag: 'SplashController');
if (kDebugMode) {
print('⏱️ SingBox 初始化超时');
}
},
);
_initLog.logSuccess('SingBox 初始化完成', tag: 'Minimal');
KRLogUtil.kr_i('✅ SingBox 初始化完成', tag: 'SplashController');
if (kDebugMode) {
print('✅ SingBox 初始化完成');
}
} catch (e) {
_initLog.logError('SingBox 初始化失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ SingBox 初始化失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('⚠️ SingBox 初始化失败: $e');
}
}
// 3.
try {
_initLog.log('步骤3: 加载本地用户信息', tag: 'Minimal');
await KRAppRunData.getInstance().kr_initializeUserInfo().timeout(
const Duration(seconds: 2),
onTimeout: () {
_initLog.logWarning('用户信息加载超时(2秒)', tag: 'Minimal');
KRLogUtil.kr_w('用户信息加载超时', tag: 'SplashController');
if (kDebugMode) {
print('⏱️ 用户信息加载超时');
}
},
);
_initLog.logSuccess('本地用户信息加载完成', tag: 'Minimal');
KRLogUtil.kr_i('✅ 本地用户信息加载完成', tag: 'SplashController');
if (kDebugMode) {
print('✅ 本地用户信息加载完成');
}
} catch (e) {
_initLog.logError('用户信息加载失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ 用户信息加载失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('⚠️ 用户信息加载失败: $e');
}
}
_initLog.logPhaseEnd('降级初始化(Minimal Initialization', success: true);
_initLog.log('应用将以降级模式启动,用户将看到基本UI', tag: 'Minimal');
_initLog.log('预期显示:订阅卡片 + 连接选项', tag: 'Minimal');
KRLogUtil.kr_i('✅ 最小化初始化完成,应用将以降级模式启动', tag: 'SplashController');
if (kDebugMode) {
print('✅ 最小化初始化完成,应用将以降级模式启动');
}
if (kDebugMode) {
print('📱 用户将看到基本UI(订阅卡片 + 连接选项)');
}
// 🔧
// await _initLog.finalize(); //
if (kDebugMode && _initLog.getLogFilePath() != null) {
print('📁 初始化日志文件(保持打开): ${_initLog.getLogFilePath()}');
}
} catch (e) {
_initLog.logError('最小化初始化也失败', tag: 'Minimal', error: e);
KRLogUtil.kr_e('❌ 最小化初始化也失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('❌ 最小化初始化也失败: $e');
}
// 使
// await _initLog.finalize(); //
}
}
///
void _handleError(String title, String message) {
kr_hasError.value = true;
+37 -6
View File
@@ -14,6 +14,7 @@ import 'package:kaer_with_panels/app/localization/kr_language_utils.dart';
import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';
// import 'package:crypto/crypto.dart';
// import 'package:encrypt/encrypt.dart';
@@ -79,14 +80,44 @@ class HttpUtil {
createHttpClient: () {
KRLogUtil.kr_i('📱 createHttpClient 回调被调用', tag: 'HttpUtil');
final client = HttpClient();
// 退
client.findProxy = (url) {
final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule();
KRLogUtil.kr_i(
'🔍 findProxy 被调用, url: $url, proxy: $proxyConfig',
tag: 'HttpUtil',
);
return proxyConfig;
try {
// SingBox
final singBoxStatus = KRSingBoxImp.instance.kr_status;
final isProxyAvailable = singBoxStatus == SingboxStatus.started();
if (!isProxyAvailable) {
// 使
KRLogUtil.kr_i(
'🔄 代理未运行,使用直连模式: $url',
tag: 'HttpUtil',
);
return 'DIRECT';
}
// 使
final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule();
KRLogUtil.kr_i(
'✅ 使用代理模式, url: $url, proxy: $proxyConfig',
tag: 'HttpUtil',
);
return proxyConfig;
} catch (e) {
// 退
KRLogUtil.kr_w(
'⚠️ 代理配置异常,回退到直连: $e',
tag: 'HttpUtil',
);
return 'DIRECT';
}
};
// 退
client.connectionTimeout = const Duration(seconds: 10);
client.badCertificateCallback = (cert, host, port) => true;
return client;
},
);
+10 -14
View File
@@ -17,21 +17,17 @@ class KRSiteConfigService extends ChangeNotifier {
_dio.options.sendTimeout = const Duration(seconds: 20);
_dio.options.receiveTimeout = const Duration(seconds: 20);
// 🔧 HttpClientAdapter使用sing-box的mixed代理
_dio.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () {
final client = HttpClient();
client.findProxy = (url) {
final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule();
KRLogUtil.kr_i(
'🔍 KRSiteConfigService 请求使用代理: $proxyConfig, url: $url',
tag: 'KRSiteConfigService',
);
return proxyConfig;
};
return client;
},
// 🔧 使
// SingBox
//
// DioExceptionType.unknown
KRLogUtil.kr_i(
'🌐 网站配置服务:使用直连模式(不通过代理)',
tag: 'KRSiteConfigService',
);
if (kDebugMode) {
print('🌐 网站配置服务:使用直连模式,避免 SingBox 未初始化问题');
}
}
KRSiteConfig? _siteConfig;
+75 -23
View File
@@ -95,6 +95,48 @@ class KRSubscribeService {
///
final kr_currentStatus = KRSubscribeServiceStatus.kr_none.obs;
/// 4 -
bool _isRefreshing = false;
/// 5
String _kr_getFriendlyErrorMessage(int errorCode, String originalMsg) {
switch (errorCode) {
case -90001:
return '连接超时,请检查网络连接';
case -90002:
return '发送数据超时,请稍后重试';
case -90003:
return '接收数据超时,网络较慢,请稍后重试';
case -90004:
return '服务器响应异常:$originalMsg';
case -90006:
return '网络连接失败,请检查网络设置';
case -90007:
return '安全证书验证失败';
case -90008:
return '网络连接被中断,请重试';
case 401:
return '登录已过期,请重新登录';
case 403:
return '没有访问权限';
case 404:
return '请求的资源不存在';
case 500:
return '服务器内部错误,请稍后重试';
case 503:
return '服务暂时不可用,请稍后重试';
default:
if (errorCode >= 500 && errorCode < 600) {
return '服务器错误($errorCode),请稍后重试';
} else if (errorCode >= 400 && errorCode < 500) {
return '请求错误($errorCode):$originalMsg';
} else if (errorCode < 0) {
return '网络请求失败,请检查网络连接';
}
return originalMsg.isNotEmpty ? originalMsg : '未知错误,请重试';
}
}
///
Future<void> kr_resetSubscribePeriod() async {
if (kr_currentSubscribe.value == null) {
@@ -290,31 +332,19 @@ class KRSubscribeService {
return;
}
// 使 API isTryOut
// 🔧 API isTryOut
// "试用中"
final currentSubscribe = kr_currentSubscribe.value!;
// 1. 使 API isTryOut
// 1. 使 API isTryOut
kr_isTrial.value = currentSubscribe.isTryOut;
KRLogUtil.kr_i('步骤1 - API isTryOut 字段: ${currentSubscribe.isTryOut}', tag: 'SubscribeService');
// 2. API
if (!kr_isTrial.value) {
final bool kr_isSubscribed = kr_alreadySubscribe.any(
(subscribe) => currentSubscribe.id == subscribe.userSubscribeId
);
KRLogUtil.kr_i('步骤2 - 检查购买记录: $kr_isSubscribed', tag: 'SubscribeService');
//
if (!kr_isSubscribed) {
kr_isTrial.value = true;
KRLogUtil.kr_i('步骤2 - 没有购买记录,判定为试用', tag: 'SubscribeService');
}
}
// 3. "试用"
// 2. API
// API "试用"
if (!kr_isTrial.value && currentSubscribe.name.contains('试用')) {
kr_isTrial.value = true;
KRLogUtil.kr_i('步骤3 - 订阅名称包含"试用"关键字,判定为试用', tag: 'SubscribeService');
KRLogUtil.kr_i('步骤2 - 订阅名称包含"试用"关键字,判定为试用', tag: 'SubscribeService');
}
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SubscribeService');
@@ -456,12 +486,23 @@ class KRSubscribeService {
///
Future<void> kr_refreshAll() async {
try {
// 4 -
if (_isRefreshing) {
KRLogUtil.kr_w('⚠️ 正在刷新中,忽略重复请求', tag: 'SubscribeService');
return;
}
//
_isRefreshing = true;
KRLogUtil.kr_i('🔄 开始刷新订阅数据...', tag: 'SubscribeService');
// 🔧 2: -
if (!KRAppRunData().kr_isLogin.value) {
KRLogUtil.kr_e('❌ 未登录用户,无法刷新订阅数据', tag: 'SubscribeService');
kr_availableSubscribes.clear();
kr_currentSubscribe.value = null;
kr_currentStatus.value = KRSubscribeServiceStatus.kr_error;
_isRefreshing = false; //
return;
}
@@ -474,8 +515,10 @@ class KRSubscribeService {
await kr_subscribeApi.kr_getAlreadySubscribe();
alreadySubscribeResult.fold(
(error) {
KRLogUtil.kr_e('获取已订阅列表失败: ${error.msg}', tag: 'SubscribeService');
throw Exception('获取已订阅列表失败: ${error.msg}');
// 5使
final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg);
KRLogUtil.kr_e('获取已订阅列表失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService');
throw Exception('获取已订阅列表失败: $friendlyMsg');
},
(subscribes) {
kr_alreadySubscribe.value = subscribes;
@@ -498,7 +541,10 @@ class KRSubscribeService {
//
final subscribes = await subscribeResult.fold(
(error) {
throw Exception('获取可用订阅失败: ${error.msg}');
// 5使
final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg);
KRLogUtil.kr_e('获取可用订阅失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService');
throw Exception('获取可用订阅失败: $friendlyMsg');
},
(subscribes) => subscribes,
);
@@ -591,7 +637,10 @@ class KRSubscribeService {
//
final nodes = await nodeResult.fold(
(error) {
throw Exception('获取节点列表失败: ${error.msg}');
// 5使
final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg);
KRLogUtil.kr_e('获取节点列表失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService');
throw Exception('获取节点列表失败: $friendlyMsg');
},
(nodes) => nodes,
);
@@ -626,7 +675,10 @@ class KRSubscribeService {
} catch (err, stackTrace) {
kr_currentStatus.value = KRSubscribeServiceStatus.kr_error;
KRLogUtil.kr_e('刷新数据异常: $err\n$stackTrace', tag: 'SubscribeService');
rethrow;
} finally {
// 4
_isRefreshing = false;
KRLogUtil.kr_i('✅ 刷新完成,重置刷新标志', tag: 'SubscribeService');
}
}
@@ -77,8 +77,6 @@ class KRSingBoxImp {
/// 线
final kr_isAutoOutbound = false.obs;
bool _initialized = false;
///
final kr_connectionType = KRConnectionType.rule.obs;
@@ -148,12 +146,6 @@ class KRSingBoxImp {
}
try {
if (_initialized) {
KRLogUtil.kr_i('SingBox 已经初始化,跳过重复初始化');
return;
}
_initialized = true;
KRLogUtil.kr_i('开始初始化 SingBox');
//
await KRCountryUtil.kr_init();
@@ -620,8 +612,7 @@ class KRSingBoxImp {
///
void _kr_subscribeToGroups() {
KRLogUtil.kr_i('🛰 启动分组监听 watchActiveGroups / watchGroups', tag: 'SingBox');
print('[_kr_subscribeToGroups] 🚀 开始订阅分组数据流');
//
for (var sub in _kr_subscriptions) {
if (sub.hashCode.toString().contains('Groups')) {
@@ -634,6 +625,7 @@ class KRSingBoxImp {
_kr_subscriptions.add(
kr_singBox.watchActiveGroups().listen(
(groups) {
print('[watchActiveGroups] 📡 收到活动组更新,数量: ${groups.length}');
KRLogUtil.kr_i('📡 收到活动组更新,数量: ${groups.length}', tag: 'SingBox');
kr_activeGroups.value = groups;
@@ -650,6 +642,7 @@ class KRSingBoxImp {
KRLogUtil.kr_i('✅ 活动组处理完成', tag: 'SingBox');
},
onError: (error) {
print('[watchActiveGroups] ❌ 活动分组监听错误: $error');
KRLogUtil.kr_e('❌ 活动分组监听错误: $error', tag: 'SingBox');
},
cancelOnError: false,
@@ -659,14 +652,22 @@ class KRSingBoxImp {
_kr_subscriptions.add(
kr_singBox.watchGroups().listen(
(groups) {
print('[watchGroups] 📡 收到所有组更新,数量: ${groups.length}');
kr_allGroups.value = groups;
//
for (int i = 0; i < groups.length; i++) {
final group = groups[i];
print('[watchGroups] 组[$i]: tag=${group.tag}, type=${group.type}, selected=${group.selected}');
}
},
onError: (error) {
print('[watchGroups] ❌ 所有分组监听错误: $error');
KRLogUtil.kr_e('所有分组监听错误: $error');
},
cancelOnError: false,
),
);
print('[_kr_subscribeToGroups] ✅ 分组数据流订阅完成,当前订阅数: ${_kr_subscriptions.length}');
}
///
@@ -1128,7 +1129,7 @@ class KRSingBoxImp {
KRLogUtil.kr_i('✅ SingBox 核心已启动,开始初始化 command client', tag: 'SingBox');
// 🔑 UI
// 🔑 UI
Future.delayed(const Duration(milliseconds: 1000), () async {
try {
KRLogUtil.kr_i('📊 开始订阅统计数据流...', tag: 'SingBox');
@@ -1147,6 +1148,24 @@ class KRSingBoxImp {
});
}
// 🔧
try {
KRLogUtil.kr_i('📋 开始订阅分组数据流...', tag: 'SingBox');
_kr_subscribeToGroups();
KRLogUtil.kr_i('✅ 分组数据流订阅成功', tag: 'SingBox');
} catch (e) {
KRLogUtil.kr_w('⚠️ 分组数据流订阅失败(稍后重试): $e', tag: 'SingBox');
//
Future.delayed(const Duration(milliseconds: 2000), () {
try {
_kr_subscribeToGroups();
KRLogUtil.kr_i('✅ 分组数据流重试订阅成功', tag: 'SingBox');
} catch (e2) {
KRLogUtil.kr_e('❌ 分组数据流重试订阅失败: $e2', tag: 'SingBox');
}
});
}
// 🔧
try {
final selectedNode = await KRSecureStorage().kr_readData(key: _keySelectedNode);
+127
View File
@@ -0,0 +1,127 @@
import 'dart:io';
import 'dart:async';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
///
/// TCP
class KRLatencyTester {
///
///
/// :
/// - host:
/// - port:
/// - timeout:
///
/// :
/// - 65535
static Future<int> testNode({
required String host,
required int port,
int timeout = 5000,
}) async {
try {
final stopwatch = Stopwatch()..start();
final socket = await Socket.connect(
host,
port,
timeout: Duration(milliseconds: timeout),
).timeout(Duration(milliseconds: timeout));
stopwatch.stop();
//
await socket.close();
socket.destroy();
final latency = stopwatch.elapsedMilliseconds;
KRLogUtil.kr_i('✅ 延迟测试成功: $host:$port = ${latency}ms', tag: 'KRLatencyTester');
return latency;
} catch (e) {
KRLogUtil.kr_w('❌ 延迟测试失败: $host:$port - $e', tag: 'KRLatencyTester');
return 65535; //
}
}
///
///
/// :
/// - nodes: [{"host": "example.com", "port": 443}]
/// - concurrency:
/// - timeout:
///
/// :
/// - "host:port"
static Future<Map<String, int>> testMultipleNodes({
required List<MapEntry<String, SocketAddress>> nodes,
int concurrency = 10,
int timeout = 5000,
}) async {
final results = <String, int>{};
final semaphore = Completer<void>();
var activeCount = 0;
var completedCount = 0;
KRLogUtil.kr_i('🚀 开始批量延迟测试,共 ${nodes.length} 个节点,并发数: $concurrency', tag: 'KRLatencyTester');
Future<void> processNode(MapEntry<String, SocketAddress> node) async {
try {
final host = node.value.address;
final port = node.value.port;
final key = node.key;
final latency = await testNode(
host: host,
port: port,
timeout: timeout,
);
results[key] = latency;
} catch (e) {
results[node.key] = 65535;
KRLogUtil.kr_e('❌ 节点测试异常: ${node.key} - $e', tag: 'KRLatencyTester');
} finally {
completedCount++;
activeCount--;
if (completedCount >= nodes.length) {
semaphore.complete();
}
}
}
//
for (var i = 0; i < nodes.length; i += concurrency) {
final batch = nodes.skip(i).take(concurrency);
for (final node in batch) {
activeCount++;
processNode(node);
}
//
if (i + concurrency < nodes.length) {
await Future.delayed(Duration(milliseconds: 100));
}
}
//
await semaphore.future;
KRLogUtil.kr_i('✅ 批量延迟测试完成,成功: ${results.length}', tag: 'KRLatencyTester');
return results;
}
}
/// Socket
///
class SocketAddress {
final String address;
final int port;
SocketAddress(this.address, this.port);
@override
String toString() => '$address:$port';
}
+19 -15
View File
@@ -2,16 +2,20 @@ import 'package:flutter/foundation.dart';
import 'package:loggy/loggy.dart';
///
/// 🔒 Release模式下所有日志都不会输出
/// 🔧 Android 15 Release
class KRLogUtil {
static final KRLogUtil _instance = KRLogUtil._internal();
factory KRLogUtil() => _instance;
KRLogUtil._internal();
/// 🔧 Release Android 15
/// false
static const bool _forceEnableReleaseLogging = true;
///
static void kr_init() {
// Debug
if (kDebugMode) {
// Debug
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy.initLoggy(
logPrinter: PrettyPrinter(),
);
@@ -19,49 +23,49 @@ class KRLogUtil {
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_d(String message, {String? tag}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'KRLogUtil'}').debug(message);
}
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_i(String message, {String? tag}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'KRLogUtil'}').info(message);
}
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_w(String message, {String? tag}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'KRLogUtil'}').warning(message);
}
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_e(String message, {String? tag, Object? error, StackTrace? stackTrace}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'KRLogUtil'}').error(message, error, stackTrace);
}
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_network(String message, {String? tag}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'Network'}').info(message);
}
}
///
/// 🔒 Debug
/// 🔧 Debug
static void kr_performance(String message, {String? tag}) {
if (kDebugMode) {
if (kDebugMode || _forceEnableReleaseLogging) {
Loggy('${tag ?? 'Performance'}').info(message);
}
}
+43 -20
View File
@@ -100,24 +100,38 @@ class KRSecureStorage {
return hash.bytes;
}
//
Box<dynamic> get _box => Hive.box(_boxName);
// 🔧 box
Future<Box<dynamic>> _ensureBoxOpen() async {
if (!Hive.isBoxOpen(_boxName)) {
KRLogUtil.kr_w('⚠️ Box 未打开,重新打开: $_boxName', tag: 'SecureStorage');
final key = HiveAesCipher(_generateKey());
await Hive.openBox(_boxName, encryptionCipher: key);
KRLogUtil.kr_i('✅ Box 已重新打开', tag: 'SecureStorage');
}
return Hive.box(_boxName);
}
//
Future<void> kr_saveData({required String key, required String value}) async {
try {
await _box.put(key, value);
final box = await _ensureBoxOpen();
await box.put(key, value);
KRLogUtil.kr_i('✅ 数据已保存: $key', tag: 'SecureStorage');
} catch (e) {
KRLogUtil.kr_e('存储数据失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('存储数据失败: $e', tag: 'SecureStorage');
rethrow; //
}
}
//
Future<String?> kr_readData({required String key}) async {
try {
return _box.get(key) as String?;
final box = await _ensureBoxOpen();
final value = box.get(key) as String?;
KRLogUtil.kr_i('📖 读取数据: $key = ${value != null ? "存在" : "null"}', tag: 'SecureStorage');
return value;
} catch (e) {
KRLogUtil.kr_e('读取数据失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('读取数据失败: $e', tag: 'SecureStorage');
return null;
}
}
@@ -125,27 +139,32 @@ class KRSecureStorage {
//
Future<void> kr_deleteData({required String key}) async {
try {
await _box.delete(key);
final box = await _ensureBoxOpen();
await box.delete(key);
KRLogUtil.kr_i('🗑️ 数据已删除: $key', tag: 'SecureStorage');
} catch (e) {
KRLogUtil.kr_e('删除数据失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('删除数据失败: $e', tag: 'SecureStorage');
}
}
//
Future<void> kr_clearAllData() async {
try {
await _box.clear();
final box = await _ensureBoxOpen();
await box.clear();
KRLogUtil.kr_i('🧹 所有数据已清除', tag: 'SecureStorage');
} catch (e) {
KRLogUtil.kr_e('清除数据失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('清除数据失败: $e', tag: 'SecureStorage');
}
}
//
Future<bool> kr_hasKey({required String key}) async {
try {
return _box.containsKey(key);
final box = await _ensureBoxOpen();
return box.containsKey(key);
} catch (e) {
KRLogUtil.kr_e('检查键失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('检查键失败: $e', tag: 'SecureStorage');
return false;
}
}
@@ -153,18 +172,20 @@ class KRSecureStorage {
//
Future<void> kr_saveBool({required String key, required bool value}) async {
try {
await _box.put(key, value);
final box = await _ensureBoxOpen();
await box.put(key, value);
} catch (e) {
KRLogUtil.kr_e('存储布尔值失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('存储布尔值失败: $e', tag: 'SecureStorage');
}
}
//
Future<bool?> kr_getBool({required String key}) async {
try {
return _box.get(key) as bool?;
final box = await _ensureBoxOpen();
return box.get(key) as bool?;
} catch (e) {
KRLogUtil.kr_e('读取布尔值失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('读取布尔值失败: $e', tag: 'SecureStorage');
return null;
}
}
@@ -172,18 +193,20 @@ class KRSecureStorage {
//
Future<void> kr_saveInt({required String key, required int value}) async {
try {
await _box.put(key, value);
final box = await _ensureBoxOpen();
await box.put(key, value);
} catch (e) {
KRLogUtil.kr_e('存储整数失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('存储整数失败: $e', tag: 'SecureStorage');
}
}
//
Future<int?> kr_getInt({required String key}) async {
try {
return _box.get(key) as int?;
final box = await _ensureBoxOpen();
return box.get(key) as int?;
} catch (e) {
KRLogUtil.kr_e('读取整数失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('读取整数失败: $e', tag: 'SecureStorage');
return null;
}
}
+16 -17
View File
@@ -23,31 +23,30 @@ class KRSubscribeNavigationUtil {
KRLogUtil.kr_i('是否设备登录: $isDeviceLogin', tag: tag);
if (isDeviceLogin) {
//
KRLogUtil.kr_i('检测到设备登录,显示绑定提示', tag: tag);
KRDialog.show(
title: AppTranslations.kr_dialog.deviceLoginBindingTitle,
message: AppTranslations.kr_dialog.deviceLoginBindingMessage,
confirmText: AppTranslations.kr_dialog.kr_ok,
cancelText: AppTranslations.kr_dialog.kr_cancel,
onConfirm: () {
Get.back(); //
//
Future.delayed(const Duration(milliseconds: 300), () {
// -
KRLogUtil.kr_i('设备登录用户,显示绑定提示', tag: tag);
try {
KRDialog.show(
title: AppTranslations.kr_dialog.deviceLoginBindingTitle,
message: AppTranslations.kr_dialog.deviceLoginBindingMessage,
confirmText: AppTranslations.kr_dialog.kr_ok,
onConfirm: () {
Get.toNamed(Routes.MR_LOGIN);
});
},
onCancel: () => Get.back(),
);
},
);
} catch (e) {
KRLogUtil.kr_e('显示绑定提示对话框失败: $e', tag: tag);
}
} else {
// -
// -
KRLogUtil.kr_i('普通用户,跳转到购买页面', tag: tag);
try {
// 🔧
Get.toNamed(Routes.KR_PURCHASE_MEMBERSHIP);
} catch (e) {
KRLogUtil.kr_e('跳转购买页面失败: $e', tag: tag);
//
KRDialog.show(
title: AppTranslations.kr_dialog.error,
+1 -1
View File
@@ -45,7 +45,7 @@ class KRWindowManager with WindowListener, TrayListener {
// Windows
if (Platform.isWindows) {
await windowManager.setTitleBarStyle(TitleBarStyle.normal);
await windowManager.setTitle('BearVPN');
await windowManager.setTitle('HiFastVPN');
await windowManager.setSize(const Size(800, 668));
await windowManager.setMinimumSize(const Size(800, 668));
await windowManager.center();
+27 -26
View File
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
@@ -51,35 +50,36 @@ class KRDialog extends StatelessWidget {
}
Widget _buildConfirmButton() {
// 🔧 Android 15 ScreenUtil使
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(23.r),
borderRadius: BorderRadius.circular(23),
boxShadow: [
BoxShadow(
color: const Color(0xFF1797FF).withOpacity(0.25),
blurRadius: 8.r,
offset: Offset(0, 2.w),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: TextButton(
onPressed: () {
Get.back();
Get.back();
onConfirm?.call();
},
style: TextButton.styleFrom(
backgroundColor: const Color(0xFF1797FF),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
borderRadius: BorderRadius.circular(23),
),
padding: EdgeInsets.zero,
minimumSize: Size.fromHeight(46.w),
minimumSize: const Size.fromHeight(46),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
confirmText ?? AppTranslations.kr_dialog.kr_confirm,
style: TextStyle(
fontSize: 15.sp,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: Colors.white,
fontFamily: 'AlibabaPuHuiTi-Medium',
@@ -94,26 +94,27 @@ class KRDialog extends StatelessWidget {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
// 🔧 Android 15 ScreenUtil使
return Dialog(
backgroundColor: theme.cardColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
borderRadius: BorderRadius.circular(12),
),
child: Container(
width: 280.w,
padding: EdgeInsets.all(24.w),
width: 280,
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
icon!,
SizedBox(height: 20.h),
const SizedBox(height: 20),
],
if (title != null) ...[
Text(
title!,
style: TextStyle(
fontSize: 17.sp,
fontSize: 17,
fontWeight: FontWeight.w600,
color: isDark ? Colors.white : const Color(0xFF333333),
fontFamily: 'AlibabaPuHuiTi-Medium',
@@ -121,17 +122,17 @@ class KRDialog extends StatelessWidget {
),
textAlign: TextAlign.center,
),
SizedBox(height: 12.h),
const SizedBox(height: 12),
],
if (message != null || customMessageWidget != null) ...[
Container(
constraints: BoxConstraints(maxHeight: 200.h),
constraints: const BoxConstraints(maxHeight: 200),
child: SingleChildScrollView(
child: customMessageWidget ?? Text(
message!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14.sp,
fontSize: 14,
color: isDark ? const Color(0xFFCCCCCC) : const Color(0xFF666666),
fontFamily: 'AlibabaPuHuiTi-Regular',
height: 1.4,
@@ -139,7 +140,7 @@ class KRDialog extends StatelessWidget {
),
),
),
SizedBox(height: 28.h),
const SizedBox(height: 28),
],
if (cancelText != null) ...[
Row(
@@ -147,33 +148,33 @@ class KRDialog extends StatelessWidget {
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(23.r),
borderRadius: BorderRadius.circular(23),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 4.r,
offset: Offset(0, 2.w),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: TextButton(
onPressed: () {
Get.back();
Get.back();
onCancel?.call();
},
style: TextButton.styleFrom(
backgroundColor: isDark ? const Color(0xFF222222) : const Color(0xFFEEEEEE),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
borderRadius: BorderRadius.circular(23),
),
padding: EdgeInsets.zero,
minimumSize: Size.fromHeight(46.w),
minimumSize: const Size.fromHeight(46),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
cancelText ?? AppTranslations.kr_dialog.kr_cancel,
style: TextStyle(
fontSize: 15.sp,
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? const Color(0xFFBBBBBB) : const Color(0xFF666666),
fontFamily: 'AlibabaPuHuiTi-Medium',
@@ -182,7 +183,7 @@ class KRDialog extends StatelessWidget {
),
),
),
SizedBox(width: 12.w),
const SizedBox(width: 12),
Expanded(child: _buildConfirmButton()),
],
),
@@ -14,7 +14,7 @@ import 'package:kaer_with_panels/utils/custom_loggers.dart';
import 'package:rxdart/rxdart.dart';
class PlatformSingboxService with InfraLogger implements SingboxService {
static const channelPrefix = "com.baer.app";
static const channelPrefix = "com.hi.app";
static const methodChannel = MethodChannel("$channelPrefix/method");
static const statusChannel =
+12 -12
View File
@@ -78,22 +78,22 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
SPEC CHECKSUMS:
connectivity_plus: e74b9f74717d2d99d45751750e266e55912baeb5
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215
flutter_inappwebview_macos: bdf207b8f4ebd58e86ae06cd96b147de99a67c9b
flutter_udid: 2e7b3da4b5fdfba86a396b97898f5fe8f4ec1a52
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f
tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c
screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
webview_flutter_wkwebview: a4af96a051138e28e29f60101d094683b9f82188
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
PODFILE CHECKSUM: 04e3af9980f29522a03273385f61d561da92c2fb
COCOAPODS: 1.16.2
COCOAPODS: 1.15.2
+9 -9
View File
@@ -71,7 +71,7 @@
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* BearVPN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BearVPN.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* HiFastVPN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HiFastVPN.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@@ -161,7 +161,7 @@
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* BearVPN.app */,
33CC10ED2044A3C60003C045 /* HiFastVPN.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
@@ -252,7 +252,7 @@
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* BearVPN.app */;
productReference = 33CC10ED2044A3C60003C045 /* HiFastVPN.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -577,13 +577,13 @@
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = BearVPN;
INFOPLIST_KEY_CFBundleDisplayName = HiFastVPN;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = app.baer.com;
PRODUCT_BUNDLE_IDENTIFIER = app.hi.com;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
@@ -710,13 +710,13 @@
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = BearVPN;
INFOPLIST_KEY_CFBundleDisplayName = HiFastVPN;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = app.baer.com;
PRODUCT_BUNDLE_IDENTIFIER = app.hi.com;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -737,13 +737,13 @@
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = BearVPN;
INFOPLIST_KEY_CFBundleDisplayName = HiFastVPN;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = app.baer.com;
PRODUCT_BUNDLE_IDENTIFIER = app.hi.com;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
@@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "BearVPN.app"
BuildableName = "HiFastVPN.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@@ -31,7 +31,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "BearVPN.app"
BuildableName = "HiFastVPN.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@@ -66,7 +66,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "BearVPN.app"
BuildableName = "HiFastVPN.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@@ -83,7 +83,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "BearVPN.app"
BuildableName = "HiFastVPN.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
+65 -65
View File
@@ -1,68 +1,68 @@
{
"images" : [
{
"filename" : "icon-16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "icon-16@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "icon-32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "icon-32@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "icon-128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "icon-128@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon-256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "icon-256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "icon-512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "icon-512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
"images": [
{
"size": "16x16",
"idiom": "mac",
"filename": "icon-16.png",
"scale": "1x"
},
{
"size": "16x16",
"idiom": "mac",
"filename": "icon-16@2x.png",
"scale": "2x"
},
{
"size": "32x32",
"idiom": "mac",
"filename": "icon-32.png",
"scale": "1x"
},
{
"size": "32x32",
"idiom": "mac",
"filename": "icon-32@2x.png",
"scale": "2x"
},
{
"size": "128x128",
"idiom": "mac",
"filename": "icon-128.png",
"scale": "1x"
},
{
"size": "128x128",
"idiom": "mac",
"filename": "icon-128@2x.png",
"scale": "2x"
},
{
"size": "256x256",
"idiom": "mac",
"filename": "icon-256.png",
"scale": "1x"
},
{
"size": "256x256",
"idiom": "mac",
"filename": "icon-256@2x.png",
"scale": "2x"
},
{
"size": "512x512",
"idiom": "mac",
"filename": "icon-512.png",
"scale": "1x"
},
{
"size": "512x512",
"idiom": "mac",
"filename": "icon-512@2x.png",
"scale": "2x"
}
],
"info": {
"version": 1,
"author": "icon.wuruihong.com"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 962 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 962 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 13 KiB

+2 -2
View File
@@ -13,7 +13,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="BearVPN" customModuleProvider="target">
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="HiFastVPN" customModuleProvider="target">
<connections>
<outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
<outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
@@ -330,7 +330,7 @@
</items>
<point key="canvasLocation" x="142" y="-258"/>
</menu>
<window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="BearVPN" customModuleProvider="target">
<window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="HiFastVPN" customModuleProvider="target">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="335" y="390" width="800" height="600"/>
<rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
+3 -3
View File
@@ -5,10 +5,10 @@
// 'flutter create' template.
// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = BearVPN
PRODUCT_NAME = HiFastVPN
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = app.baer.com
PRODUCT_BUNDLE_IDENTIFIER = app.hi.com
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2023 BearVPN.com. All rights reserved.
PRODUCT_COPYRIGHT = Copyright © 2025 HiFastVPN.com. All rights reserved.
+137
View File
@@ -0,0 +1,137 @@
# Flutter Windows 单文件 EXE 打包指南
## 🎯 目标
将 Flutter Windows 应用打包成单个可执行文件,便于分发和部署。
## 📋 当前状态
### 现有构建输出
```
build/windows/x64/runner/Release/
├── hostexecutor.exe # 主程序
├── flutter_windows.dll # Flutter 引擎
├── msvcp140.dll # Visual C++ 运行时
├── vcruntime140.dll # Visual C++ 运行时
├── vcruntime140_1.dll # Visual C++ 运行时
└── data/ # 应用数据文件夹
├── app.so # Dart 代码编译结果
└── flutter_assets/ # 资源文件
```
### 问题分析
Flutter 默认构建会生成多个文件,因为:
1. **Flutter 引擎** (`flutter_windows.dll`) - 必须包含
2. **Visual C++ 运行时** - 系统依赖
3. **应用数据** (`data` 文件夹) - 包含资源和 Dart 代码
## 🔧 解决方案
### 方案一:使用 Enigma Virtual Box(推荐)
#### 步骤 1:下载安装
1. 下载 [Enigma Virtual Box](https://enigmaprotector.com/en/downloads.html)
2. 安装并运行
#### 步骤 2:打包配置
1. **主程序文件**: 选择 `build/windows/x64/runner/Release/hostexecutor.exe`
2. **添加文件夹**: 选择整个 `Release` 文件夹
3. **输出文件**: 设置输出路径和文件名
4. **文件选项**: 勾选"压缩文件"
#### 步骤 3:生成单文件
点击"Process"生成单个可执行文件。
### 方案二:使用 Inno Setup(安装程序)
#### 步骤 1:下载安装
1. 下载 [Inno Setup](https://jrsoftware.org/isinfo.php)
2. 安装并运行
#### 步骤 2:创建脚本
```ini
[Setup]
AppName=HostExecutor
AppVersion=1.0.0
DefaultDirName={autopf}\HostExecutor
OutputBaseFilename=HostExecutor_Setup
[Files]
Source: "build\windows\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Icons]
Name: "{group}\HostExecutor"; Filename: "{app}\hostexecutor.exe"
```
#### 步骤 3:编译生成
编译脚本生成安装程序。
### 方案三:使用 Windows 自带工具(高级)
#### 使用 `dotnet publish`(需要 .NET 包装)
```bash
# 需要创建 .NET 包装器项目
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true
```
## 🚀 自动化脚本
### Enigma Virtual Box 自动化脚本
```powershell
# package_single_exe.ps1
$enigmaPath = "C:\Program Files\Enigma Virtual Box\enigmavb.exe"
$inputFile = "build\windows\x64\runner\Release\hostexecutor.exe"
$outputFile = "dist\HostExecutor_Single.exe"
$folderPath = "build\windows\x64\runner\Release"
& $enigmaPath /sf $inputFile /lf $outputFile /folder $folderPath /compress
```
## 📦 打包后文件结构
### 单文件输出
```
dist/
└── HostExecutor_Single.exe # 单个可执行文件(50-100MB)
```
### 文件大小分析
- **原始文件**: 约 30-50MB
- **压缩后**: 约 25-40MB(取决于压缩率)
- **最终大小**: 50-100MB(包含所有依赖)
## ⚠️ 注意事项
### 运行时依赖
1. **Windows 版本**: Windows 10 版本 1903+ 或 Windows 11
2. **系统组件**: 确保目标系统有最新的 Windows 更新
3. **防病毒软件**: 单文件可能被误报,需要添加信任
### 性能影响
- **启动时间**: 单文件启动会稍慢(需要解压)
- **内存使用**: 运行时内存占用相同
- **文件大小**: 比多文件版本大约 10-20%
## 🎯 推荐方案
### 开发阶段
使用多文件版本,便于调试和更新。
### 分发阶段
使用 Enigma Virtual Box 创建单文件版本:
1. **简单易用** - 图形化界面
2. **压缩率高** - 有效减小文件大小
3. **兼容性好** - 支持所有 Windows 版本
4. **免费** - 个人和商业使用都免费
## 📋 下一步行动
1. **安装 Enigma Virtual Box**
2. **测试单文件打包**
3. **验证运行效果**
4. **创建自动化打包流程**
## 🔗 相关资源
- [Enigma Virtual Box 官网](https://enigmaprotector.com/en/downloads.html)
- [Inno Setup 官网](https://jrsoftware.org/isinfo.php)
- [Flutter Windows 文档](https://docs.flutter.dev/desktop)
+168
View File
@@ -0,0 +1,168 @@
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Builds and packages a Flutter Windows application into a single executable.
.DESCRIPTION
This script automates the entire process of creating a single-file executable for a Flutter Windows project.
It performs the following steps:
1. Checks for and installs Chocolatey if not present.
2. Installs Enigma Virtual Box and 7-Zip using Chocolatey.
3. Builds the Flutter application in release mode.
4. Packages the build output into a single EXE using Enigma Virtual Box.
5. If Enigma fails, it falls back to creating a 7-Zip self-extracting archive.
6. Places the final packaged executable in the 'dist' directory.
.NOTES
- This script must be run with Administrator privileges to install software.
- An internet connection is required for the first run to download and install dependencies.
#>
# --- Configuration ---
$ErrorActionPreference = "Stop"
$buildPath = ".\build\windows\x64\runner\Release"
$outputPath = ".\dist"
# --- Helper Functions ---
function Test-CommandExists {
param($command)
return (Get-Command $command -ErrorAction SilentlyContinue)
}
function Install-Chocolatey {
if (Test-CommandExists "choco") {
Write-Host "✅ Chocolatey is already installed."
return
}
Write-Host "Chocolatey not found. Installing..."
try {
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
Write-Host "✅ Chocolatey installed successfully."
} catch {
Write-Host "❌ Failed to install Chocolatey. Please install it manually and re-run the script."
exit 1
}
}
function Install-Tools {
Write-Host "Checking for required tools (Enigma Virtual Box, 7-Zip)..."
$tools = @("enigma-virtual-box", "7zip")
foreach ($tool in $tools) {
if (choco list --local-only --exact $tool) {
Write-Host "$tool is already installed."
} else {
Write-Host "Installing $tool..."
try {
choco install $tool -y --force
Write-Host "$tool installed successfully."
} catch {
Write-Host "❌ Failed to install $tool."
exit 1
}
}
}
}
# --- Main Script ---
# 1. Setup Environment
Write-Host "=== 1/4: Setting up build environment ==="
Install-Chocolatey
Install-Tools
# 2. Build Flutter App
Write-Host "=== 2/4: Building Flutter Windows application (Release) ==="
try {
flutter build windows --release
} catch {
Write-Host "❌ Flutter build failed."
exit 1
}
# 3. Package Application
Write-Host "=== 3/4: Packaging into a single executable ==="
if (-not (Test-Path $buildPath)) {
Write-Host "❌ Build directory not found: $buildPath"
exit 1
}
# Create output directory
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
# Get main executable
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
if (-not $exeFile) {
Write-Host "❌ No executable found in build directory."
exit 1
}
$inputExe = $exeFile.FullName
$outputExe = "$outputPath\$($exeFile.BaseName)_Single.exe"
$enigmaCliPath = "C:\Program Files\Enigma Virtual Box\enigmavb.exe"
$packageSuccess = $false
# Attempt to package with Enigma Virtual Box
if (Test-Path $enigmaCliPath) {
Write-Host "Attempting to package with Enigma Virtual Box..."
try {
& $enigmaCliPath /quiet /project "$outputPath\project.evb" /input "$inputExe" /output "$outputExe" /folder "$buildPath" /compress 3 /deleteext
if ($?) {
Write-Host "✅ Enigma Virtual Box packaging successful."
$packageSuccess = $true
} else {
Write-Host "⚠️ Enigma Virtual Box packaging failed. Exit code: $lastexitcode"
}
} catch {
Write-Host "⚠️ An error occurred during Enigma Virtual Box packaging."
}
} else {
Write-Host "⚠️ Enigma Virtual Box not found at $enigmaCliPath."
}
# 4. Fallback to 7-Zip if Enigma failed
if (-not $packageSuccess) {
Write-Host "=== 4/4: Fallback: Packaging with 7-Zip SFX ==="
$7zipCliPath = "C:\Program Files\7-Zip\7z.exe"
$outputSfx = "$outputPath\$($exeFile.BaseName)_Package.exe"
if (-not (Test-Path $7zipCliPath)) {
Write-Host "❌ 7-Zip not found. Cannot create self-extracting archive."
exit 1
}
$sfxConfig = @'
;!@Install@!UTF-8!
Title="Flutter Application"
BeginPrompt="Do you want to extract and run the application?"
RunProgram="%%T\%%S\$($exeFile.Name)"
;!@InstallEnd@!
'@
$sfxConfigFile = "$outputPath\sfx_config.txt"
Set-Content -Path $sfxConfigFile -Value $sfxConfig
try {
& $7zipCliPath a -sfx7z.sfx "$outputSfx" "$buildPath\*" -r "-i!$sfxConfigFile"
Write-Host "✅ 7-Zip self-extracting archive created successfully."
$outputExe = $outputSfx
$packageSuccess = $true
} catch {
Write-Host "❌ 7-Zip packaging failed."
exit 1
}
}
# --- Final Summary ---
if ($packageSuccess) {
$finalSize = (Get-Item $outputExe).Length / 1MB
Write-Host "================================================"
Write-Host "✅ Packaging Complete!"
Write-Host " Output file: $outputExe"
Write-Host " Size: $([math]::Round($finalSize, 2)) MB"
Write-Host "================================================"
} else {
Write-Host "❌ All packaging attempts failed."
}

Some files were not shown because too many files have changed in this diff Show More