主题:下载 / DNS 治本 · 设置页重做 · 悬浮元素让路 · 动画泄漏治理与分级预加载。
Content-Range;
分片成品按显式 path 读回;暂停 / 重试后进度与失败原因归零;dispose 后回调不再改状态。kOgLSettingsRowPadding 类型写成 EdgeInsets 却赋值 EdgeInsetsDirectional(9 条编译错误、整包构建失败)——已修正。OgLReveal 整个类没有 dispose()(错峰闭包拖着已卸载 State);
每个路由每帧泄漏 2 个 CurvedAnimation(死监听者永不摘除)——均已修复,观感零变化。ScrollAwareAction):下滑收边只露 1/4、点击弹出、上滑自动弹回、
近底部半屏收起;覆盖首页 / 仓库页 4 个标签页 / 发布页共 7 处。完整说明见 release_notes/v8.0.0.md。
主题:仓库文件操作接入文件操作服务 + 遗留缺陷修复批。
RepoFileService:新建 / 删除 / 重命名与目录递归删除改调服务 —— 路径经服务规则校验、单文件写入带文件级基线(create 不覆盖、delete 不删错版本);目录删除由服务自动分批(≤200/批、基线链式推进),页面级 200 文件硬上限移除;整体成败以 result.ok 判定,失败按 result.items 逐项提示(同一文案只报一次)。onProgress 回调更新代码标签顶部状态行(阶段 + 已处理 / 总数),进行中不再整页转圈、把内容藏起来。RepoFileService 每个写操作在条目真正落定后调用 GhApi.invalidateReadCache(),随后的读取回源(失效失败不改变「写入已成功」的事实,只记诊断)。languageCodes 由 15 种收敛为 6 种(简中 / 繁中 / 英 / 德 / 法 / 俄),注释同步说明与 OgLI18n.locales、assets/i18n/ 目录、pubspec 声明三处一致。OgLPreviewKind.text:文本文件仍判定为 unknown(既有行为由测试锁定),file_preview_page 的对应分支一并删除。readme.md / changelog.md 分支(md 扩展名在扩展名分支已先返回)。https://(无主机)不再放行 —— 它会把「加速已开」伪装成直连(新增键 accelUrlHost,6 语言)。aux.tar.gz 等多扩展名不再绕过(补测试用例)。ghs_ / ghr_ 前缀(6 语言):提示与实际接受的 6 种前缀一致。raw 回退拉全文失败时把「可能被截断」如实带进 _GistFile.truncated,卡片标注(新增键 truncatedWarning,6 语言),不再把残缺内容当完整展示。title + detail 先查去重再落盘,重复条目不再写入磁盘日志。OgLNoticeDelivery 注明接线状态:当前调用点均走默认 auto,参数尚未接线(逻辑未变)。flutter_svg / window_manager / saf_util / saf_stream / flutter_local_notifications / yaml 六项,顺序声明改为与 pubspec.yaml 的 dependencies 逐项一致。finally 中冗余的未挂载分支;_openOnboarding 改用已取得的 navigator。pubspec.yaml 7.3.1+70310 → 7.4.0+70400;kOgLAppVersion 同步升至 7.4.0。主题:界面细节修复批 —— 弹层闭场动效 / 表单返回保护 / 动效与无障碍覆盖 / 多语言文案。
ogLShowSheet)的闭场动画不再被掐断:不再自建动画控制器(关闭同帧释放会取消出场动画),改用 sheetAnimationStyle 按档位给时长。showSnackBar 收敛到 OgLNotifier;「取消文件夹授权」改告警语气、「下载并发数」改成功语气。ExpansionTile,默认收起);账户行、日志空态 / 正文补 AnimatedSize 过渡,加速通道增删沿用外层 AnimatedSize。Semantics(header: true);滑块行加 MergeSemantics;色板与加速通道声明 inMutuallyExclusiveGroup。onboardingLicenseHighlights 补 de / fr / ru;6 语言清除指向已删内置通道的表述;德文(Protokolldatei / Projektinformationen)与俄文(登录 / 公开 / 文件访问)拼写修正。kOgLAppVersion 与 pubspec 同步升至 7.3.1。主题:新增文件操作服务(移动 / 复制 / 批量)+ 传输层健全 + 界面与交互修复。
RepoFileService):统一 create / delete / rename(=move) / copy / batchDelete / batchMove / batchCopy;支持文本与二进制(Blobs API / sha 引用,不限 1 MB);目录操作递归展开;>200 文件自动分批 + 基线链式推进 + 进度回调 + 取消;目标已存在拒绝覆盖。IxDownloadError):网络 / 磁盘 / 校验 / 取消 / 不支持 / 需认证——取代裸字符串。net_transport.dart 默认可重试方法移除 PUT / DELETE(非幂等操作)。types.dart 的 9 条 export 路径修正(此前解析到仓库外)。IxPresign 补传令牌(此前漏传导致签名族加速静默失效)。kOgLAppVersion 对齐 pubspec 版本号。atHome 判定收窄:引导/登录阶段不再触发「再按一次退出」。主题:修复一轮界面与交互审查发现的问题。
主题:调整平台架构兼容性。
app/<版本数字>/,不产生 GitHub Release。本项目各版本的变更记录,新版本在前。
主题:新增 Web 版(浏览器),并把它作为正式平台之一。 桌面与移动端的代码通过条件导入收敛平台差异,Web 侧另有一套实现。 同时新增「按版本发布到
app/」的部署结构。
app/index.html 用 iframe 包裹当前版本,地址长期不变;
各版本产物放在 app/v<版本号去点>/(如 v700),app/versions.json 为清单。web/index.html 手写入口页,含 PWA 清单与 apple-* 标签。assets/icon/ogl_icon.svg 光栅化生成。beforeinstallprompt(平台限制),因此 iOS 上给出
「共享 → 添加到主屏幕」的引导。已安装(standalone)时不再提示。
可在 设置 → Web 版 关闭该提示。tool/web_publish.py:把构建产物按版本发布到 app/,并重写入口页与清单。import 'dart:io',
浏览器里没有该库。现改为
import 'x_io.dart' if (dart.library.js_interop) 'x_web.dart';,
能用 kIsWeb + defaultTargetPlatform 解决的一律不再引入 dart:io。http: ^1.2.2(自带浏览器实现,供 Web 传输层使用)。web.yml 在 main 与 web 两条分支上构建 Web;其成败不阻塞五平台发布。localStorage,文件类存储为会话内有效
的内存表;SecureDiskVault(令牌保险库)在 Web 上仅内存持有,刷新需重新登录 ——
这是为了避免把长期令牌明文留在 localStorage。BrowserClient。自定义 DNS 与 DoH 在 Web 上不可用
(浏览器不提供裸 socket,也无法把解析结果回灌给连接),设置页会如实显示这一点。background_downloader 没有 Web 实现,因此 Web 上的下载交给浏览器。
由此暂停、续传、多连接分片、进度、文件大小、保存路径、成品 sha256 校验均不可用,
界面与日志如实标注,不做假动作(例如「暂停」不会被伪装成已暂停)。Authorization 头的下载在 Web 上会明确失败(浏览器不允许页面设置跨域鉴权头),
原因是能否成功取决于目标站点是否允许跨域,这里不猜。fetch 读不到跨域重定向的 Location。
实现如实返回「解不出签名」,不会改成跟随重定向(那会绕过「令牌只用于第一跳」的设计)。OgLLogFile.isEnabled == false,保留浏览器控制台输出。Link 头、SAF 二次下载不导出、探测期任务复活、
完整性校验失败不删坏文件、SSRF 归一化、19 处文案取错语言分片等。docs/ARCHITECTURE.md 等 5 份被注释引用的文档仍不存在(已逐处标注「以源码为准」)。ARCH
环境变量未被接受。三种包在 zip / 7z 里都齐全。主题:修复一轮全量代码审查发现的问题。 审查用 4 个子代理并行覆盖加速链路、平台与底座、展示层、领域层与工具, 结论逐条经人工复核(
docs/NETWORK.md与release_notes/的措辞同期校准)。
Image.network 没有 headers 参数,
无法携带令牌,而私有 raw 匿名访问返回 404。此前「私有 + 已知情接受」会
走到该分支;现在私有仓库一律回退到 API 取字节(那条带令牌)。ReadmeView 的字节缓存只以仓库内相对路径为键,
assets/logo.png 这类同名文件在两个仓库间会命中同一份缓存。键改为
仓库@分支:路径。headers 为空,
而翻页依赖 Link 头。现在缓存条目连同 link 一起存储并在命中时回填。connectionFactory 只在传输层
构造时安装一次,而 DNS 模式的写入发生在模块注册之后。现在每次发送前按当前
策略校正(模式变化才重装;切回系统 DNS 时把 factory 摘掉)。kOgLAppVersion 停在 6.0.0,与 pubspec.yaml 相差三个小版本。
该常量会写入日志与内核报告。已对齐。_runRanged 在 await probe 之后
无条件写回快照。现在探测返回后先确认任务仍在,否则直接退出(也不会再落盘)。remove() 与 clearFinished() 漏清 _urlCandidates、
_rangeConnections、_lastSample、_expectedSha256、_exportedToSaf,
造成会话级累积。现统一收口。dispose() 不取消进行中的分片下载:分片任务是 fire-and-forget,管理器
回收后引擎仍在下载并调用已释放的通知器。现取消全部令牌并加 _disposed 守卫。ix_presign 在 200 直链分支先 drain() 再注释说明「不能 drain」:
每个直链下载都会多跑一遍全量流量。已移除该 drain。isForbiddenHost 存在绕过形式:只识别点分十进制与 fe80: 前缀。
现在先做归一化(整数形式的 IPv4、IPv4-mapped IPv6、去掉方括号与尾点),
IPv6 段判断改为按位(fc00::/7、fe80::/10),并支持 127.1 这类缩写。finally 只删分片,不删 target。
现按契约在未成功合并时删除目标文件。abs() 未拒绝绝对路径与空串(注释称会拒绝):/etc/passwd 会被静默
剥掉前导斜杠塞进根目录。现显式拒绝。previewSvg / previewUnknown 两个键在 6 种语言里都不存在(「打开方式」
弹窗的 SVG 与未知类型条目显示裸键)。已补齐。common.unknown)。i18n_scan.py 的分类规则收紧:LOG_CONTEXT 原含 log\w*(,
该模式会命中 AlertDialog(、showDialog(、catalog( 与 login(,
使对话框附近的用户可见文案被计为开发者日志。现改为只列精确的日志入口。docs/NETWORK.md 更正与代码不符的表述(原写传输层有「主机冷却 / DoH 回落」,
实际不存在),并补上「加速适用范围」与 web 端 CORS 实测表。docs/README.md 补入 NETWORK.md 索引;文中路径改为可点击链接。platform.dart 的平台分派范围、
download_proxy.dart / readme_view.dart / file_preview_page.dart 的
私有仓库口径、net_bridge.dart 的模块描述、ix_task.dart 的 auto 语义、
日志文件名格式、诊断中的并发数文案。IoBootFileSystem;对仅测试使用的 ScriptedTransport 与
无调用方的 DiskPaths 加注说明。docs/ARCHITECTURE.md、BOOT.md、CONSISTENCY.md、DURABILITY.md、
NAMING.md 被代码注释引用,但仓库中并不存在;引用未清理。api.github.com),加速适用范围没有它。Authorization,而 Release 附件的签名地址不带 CORS 头)。ARCH
环境变量未被接受。三种包在 zip / 7z 里都齐全。主题:删掉内置代理,只留自定义通道;同时去掉一切静默降级。
这个项目的定位是本地工具:不收集数据、令牌不出设备。而「内置加速通道」 是一台由项目维护的代理服务器 —— 无论协议怎么写,它都在信任链上: 它知道你请求了什么文件,也能在签名地址的有效期内自行取走文件。 这与上面的定位冲突,因此移除。
加速适用范围可逐项开关(设置 → 网络 → 加速):前缀式代理开放的端点有限, 有的能转发 Release 附件却转发不了仓库内图片,”哪些资源加速”写死必然有人用不了。 现在由用户指定,只有 4 类(清单来自代码,不凭印象添端点):
| 适用范围 | 资源 | 代码位置 |
|---|---|---|
| Release 附件 | release_detail_page.dart |
签名族 |
| Action 构建产物 | action_run_page.dart |
签名族 |
| 仓库文件(下载与预览) | surface_bridge.planRepoFileDownload、file_preview_page.dart |
raw 族 |
| README 仓库内图片 | repo_page.dart |
raw 族 |
默认全开(与历史行为一致),可逐项关闭;全关也合法(等于不加速)。
Action 运行日志不走加速,因此没有对应开关。
各调用点只声明”我是哪一类”,是否加速统一由 OgLSettings.accelPrefixesFor 判定,
避免同一资源出现两处不同结论。
proxy.344977.xyz):通道列表不再包含任何内置项,
kOgLAccelBuiltinChannel / kOgLAccelBuiltinId / kOgLAccelBuiltinBaseUrls
一并删除。要加速需自行添加通道地址;不添加就一直走直连。defaultMirrorChannels 里的 ghproxy.net 换主机规则):
它们是”我们替你选的第三方代理”,同样予以清空。镜像机制本身保留但当前不生效。ogLAccelCandidates 现在至多返回一项 —— 加速就是
前缀 + 原址,不加速就是原址,不再垫一个直连候选。
此后不会出现「界面显示在加速、实际走的直连」这种谁也说不清的状态;
失败就如实报错。accelThirdPartyBody 重写 ——
删去「本应用提供/维护通道」的表述,明确「本应用不预置任何通道,也不提供
代理服务」,并把「失败不静默回落直连」写进正文。
内置通道专属的协议文本(accelBuiltinBody 等)与相关界面文案一并删除。README / docs/USAGE.md / docs/NETWORK.md 同步订正;
NETWORK.md 补入 web 端 CORS 实测表(哪些路在浏览器上走得通)。accelAddHint。i18n_scan.py 的失效豁免(accel.dart 的内置通道展示名)已清除,
并记录其 UI/日志分类跨度过宽的已知盲区。主题:图标改由
assets/icon统一生成,并修复两个自 v5.6.0 起存在的缺陷。起因是「更新图标为 assets/icon 的,全平台自动适配」。查管线时发现: 声明与实际不一致。一个是从来没跟过源图,一个是整张图是空的。
desktop_icon.render_rgba 解析出的图层里存的是 url(#bodyGrad) 这样的引用串,
而渐变表的键是 bodyGrad,查表写成 grads.get(layer["fill"].strip()) ——
永远查不到,于是每个图层都被 continue 跳过,输出是一张全透明的图。
症状不是报错,而是一个看不见的图标;构建全程”成功”。
_resolve_paint() 正确解析 url(#id) 引用,并顺带支持
#RRGGBB 纯色(用同色双停靠点表示),避免源 SVG 换写法又静默变空。inject_platform_spec.py 里是一段
硬编码的矢量前景(盾牌 + 蓝色三角),与 assets/icon/ogl_icon.svg
(深色多边形 + 金色双眼)不一致 —— 此前所称的「唯一事实来源」与实际不符。
注释还指向一个早已删除的脚本。
tool/svg_vector.py 把源 SVG 转成
VectorDrawable,Android 改为真实转换。assets/icon/ogl_icon.svg 是唯一来源):
VectorDrawable(自适应前景收在安全区内 + 传统图标矢量
放 mipmap-anydpi/),不再有手写 XML;mipmap-anydpi/:anydpi 的优先级高于具体密度,因此会
盖过 flutter create 生成的五套模板 PNG —— 无需删除那些文件,也不会在
API < 26 的设备上残留 Flutter 默认图标。desktop_icon._parse_svg 更名公开为 parse_svg:Android 的矢量转换也用它,
两个平台必须从同一份解析结果出发,否则”同一个图标”会各处一个样。tool/svg_vector.py:SVG → Android VectorDrawable(polygon + linearGradient,
纯标准库;渐变按 SVG 的 objectBoundingBox 语义换算成 Android 的绝对坐标)。主题:私有仓库也可以加速了 —— 但必须先过一道知情警告。
上一版把私有仓库的 raw 一律排除在加速之外,理由是「raw 没有签名机制, 交给代理等于送令牌」。这个理由成立,但用户可能愿意承担这个风险换速度。 所以改为把选择权还给用户,并且让这个选择真的被看见。
accelPrivateRepoAccepted,默认 false):
docs/NETWORK.md:全仓库网络连接清单。出口主机 × 资源类型 × 取法 ×
公私差异 × 复现命令。文档里点到的每个符号都已逐条核验存在。ogLAccelCandidates 新增 privateAccelAccepted:私有 + raw 族只在用户
知情接受后才加速;公开仓库不受影响。proxied || !repoPrivate 在「私有 + 已接受」时给出空头,必然 404。SurfaceBridge.repoFileAccelerated、
预览页大文件面板的弹窗条件与提示文案条件。ogLAccelCandidates 在上一笔提交中被误删的 repoPrivate 参数
(改签名时替换掉了,函数体却仍在引用它)—— 曾导致 9 条构建腿与质量门全红。主题:把界面语言从 15 种收到 6 种 —— 保留全部键均有实际译文的那 6 种。
这不是一次功能更新。上一版埋着的隐患是:15 种语言里有 12 种的法律类正文 实际是英文占位(键在、目录在、值与英文一模一样)。用户切到自己的语言, 看到的仍是看不懂的法律说明。
OgLI18n.locales(Dart 运行时清单)、
assets/i18n/ 下的目录、pubspec.yaml 的 assets 声明,三者必须逐项一致。
tool/i18n_scan.py --check 新增该项检查(实测:故意加一个不存在的语言目录
→ 退出码 1)。
这是本版在根因层面的防护:两边不同步会分别造成两种方向相反的故障 ——
pubspec 多声明 → 构建期资源缺失直接失败;pubspec 少声明 → 构建通过、
运行时该语言全是裸键名。后者尤其难查。zh(源)/ zh_TW / en / de / fr / ru。
移除 ja ko es pt ar hi th vi id 九个语言目录,并同步
OgLI18n.locales、pubspec.yaml、README.md、docs/USAGE.md、docs/I18N.md。
加回某个语种的前提是全部键都是真译文,而不是把英文复制一遍。zh / zh_TW:Code / Issues / Pull requests / Actions 保留英文,
其余(分支 / 提交 / 设置)照常用中文。de / fr / ru:全部译为各自语言的对应词(如 ru 的 Issues → Задачи、
Releases → Релизы)。此前这些语言里混着英文残留 —— 例如 fr 的
pulls 仍是 Pull Requests、releases 仍是 Releases。test/surface/i18n_test.dart 相应更新:语种数 15 → 6,并保留
「中文语境下 GitHub 术语必须保持英文」这条断言。Gist 片段 → Gist 程式碼片段、
我的加速 → 我的加速節點(用词差异,非字形转换)。OgLProjectInfo.licenseUrl 仍指向 AGPL-3.0:v6.3.0 换了许可,标识
(licenseId)与名称(licenseName)都改了,地址漏改,还指向
www.gnu.org/licenses/agpl-3.0.html。该常量目前无引用(死常量),但一旦将来
有人用它生成「查看许可」链接,就会把用户送到一份与实际许可无关的全文。
已改为 https://www.apache.org/licenses/LICENSE-2.0。headers: proxied || !repoPrivate ? null : const <String, String>{} ——
注释说「未走代理且私有仓库才带认证头」,实际给的是空 map,一个头都没带。
私有仓库必然 404,而界面把结果显示成「文件过大,无法在内置预览中加载」,
把认证失败误报成文件过大。现在真的去取一步令牌
(downloadAuthHeaders);走代理时依旧一律不带(把令牌交给代理等于送令牌)。height: 460:小屏、大字体或横屏下会超出 AlertDialog
可用高度而溢出。改为按视口比例给上限(MediaQuery.sizeOf(context).height * 0.6)。common.previewLoadFailed,用于把「加载失败」与「文件过大」区分开 ——
超过 1 MB 已有专门的面板处理,走到 errorBuilder 说明是认证 / 限流 / 网络问题,
说成「文件过大」会让人往错误方向排查。该键已补齐 6 语言。ARCH 环境变量而退出码 1。三种包在 zip / 7z 里都齐全,功能上不缺,
只是未裸放直传。raw 端点
没有签名机制,交给代理等于送令牌。这是硬约束,不是取舍。LICENSE;新增 NOTICE(Apache-2.0 第 4(d) 条要求)。pubspec.yaml 的 resources,随构建产物分发。
此前 AGPL 全文只存在于源码仓库,构建产物中没有,严格说不满足
「随分发提供许可副本」的要求 —— 本次一并修正。README / docs/USAGE.md / tool/linux_packages.py 的包元数据 /
OgLProjectInfo / 15 语言界面文案(AGPL-3.0 → Apache-2.0,免责条款
引用由第 15、16 条改为第 7、8 条)。licenseIntro 原写「第二部分是保证」、
accelLangNote 原写「仅中文译本具有法律效力」,均与「本文不产生法律
效力」直接矛盾;现统一为「中文为原始表述,其他语言仅供理解参考」。_logout:被「我的」页的账号移除功能取代的重复实现,
删除后账号注销统一走 SurfaceBridge.forgetAccount。
(该重复实现还掩盖了一次功能退化:v4.4.0 曾要求「切换/移除账号时清空
全部缓存」,后来在「我的」页退化成了只清仓库缓存,会留下 DNS 缓存与
页面分页快照,多账号下造成串台。已恢复。)// ignore: unused_element 压着 analyze。已在设置页补上入口,
并移除 3 处 ignore 注释。主题:无障碍补全 + 恢复 UI 截屏矩阵 + 消除两套「可见性」定义。 本版没有新增功能,是把前两版欠的工程质量补齐 —— 尤其是两处 结论相反且未经验证一致的定义分叉。
Semantics 为 0。50 个图标按钮虽都有
tooltip(Flutter 会自动取作语义标签),但自定义可点击区域没有任何语义标注,
屏幕阅读器只能念出”按钮”,用户不知道点了会怎样。
Semantics(button: true, label: …)Semantics(button: true, selected: …, label: 颜色 #rrggbb)Semantics(toggled: …, button: true, label: 消息内容)Semantics(button: true, label: 选择分支)OgLStoragePlan.userVisible:mode != internal(按档位)OgLAppDirs.isUserVisible:tier ∈ {public, desktop}(按路径分级)两者在「桌面文档目录不可写、最终落到应用支持目录」时给出相反结论。 界面接的是前者、测试锁的是后者,两者的一致性未被验证过。 现统一成路径分级(唯一来源),SAF 档作为例外单列(用户授权过就可见)。 新增测试把「无论什么档位,可见性都等于按路径分级的结论」钉成回归。
OgLAppDirs.categoryFolder 补上 artifact 映射。此前漏了 Action 构建产物,
一旦被用到会静默落到 other/ —— 用户看不到任何异常,只是分类目录不对。
补上映射,并新增测试把底座与中枢两份映射逐枚举比对(新增分类漏改一侧立刻红灯)。
死代码转为防漂移护栏。window_windows.dart 缩进损坏:第 27/29/30 行等顶格,Linux 同位置正常。
应是 v6.0.1 删除注入脚本那次重构的残留。app_dirs.dart 注释与代码矛盾:_resolveRoot() ② 档注释原说应用外部目录
「文件管理器可见」,而 isUserVisible() 明确判为不可见(Android 11+ 隐藏
Android/data/)。注释会误导后续维护,已改为准确描述并说明为何仍选它作退路。appTitle 三份字面量重复(windows / linux / macos):值上收到
window_capability.dart 的 kOgLAppTitle,各平台保留同名常量指向它
(不删符号),消除标题悄悄分叉的可能。ARCH 环境变量而退出码 1。
三种包在 zip / 7z 里都齐全,功能不缺,只是未裸放直传。详见「产物」一节。raw 端点
没有签名机制,交给代理等于送令牌。这是硬约束。主题:下载链路重做(端点 / 路由 / 完整性)+ 文件预览 + 隐私承诺。 三个此前”看起来能用、实际私有仓库用不了”的缺陷一并修掉。
re_editor 的 CodeEditor
没有 contextMenuBuilder,只接受 SelectionToolbarController(抽象类),
不传就没有菜单 —— 这正是「长按没有复制菜单」的根因。已用官方 factory
MobileSelectionToolbarController 接上;文案取自 MaterialLocalizations,
15 种语言由 Flutter 官方提供,无需自建词条。https://proxy.344977.xyz/(单前缀,转发完整原始链接)。
同意协议版本 1 → 2 —— 地址变更属实质修改,必须重新征求同意。ogLAccelCandidates):
/repos/{o}/{r}/contents/{path} + Accept: application/vnd.github.raw),
加速才把 raw 链接交给代理。端点经实测选定:raw 媒体类型是 1MB–100MB 文件的
唯一取法(JSON 形式对 >1MB 返回空 content),且支持 Range
(实测 206 + content-range),多连接分片下载不退化。label getter 渲染到界面,非中文用户会看到「已完成」「仓库文件」。
i18n_scan 只扫 lib/surface/,域层不参与,这类问题门禁永远抓不到,
只能靠「界面文案一律经 _t()」这条纪律守住。fileName 的来源之一是 Release 附件名(仓库所有者可自行指定),
直接交给第三方下载库等于把路径构造外包给无法审计的实现。新增净化:只取末段、
剔控制字符、拒 ..、绕开 Windows 保留设备名、限长 120 并保住扩展名。169.254.169.254)。> / | 块),与 PyYAML 结果逐字段一致。android/app/build.gradle.kts,而 spec 仍指向 build.gradle,注入被静默跳过,
导致 compileSdk 停在 36(插件要求 37)且 desugaring 未开。注入器现在缺目标
文件即报错退出,失败点从编译期前移到注入期,日志直接指出缺哪个文件。actions/checkout,工作目录是空的,tool/linux_packages.py 不存在;
而该步骤带 || true,错误被吞掉。实测 v5.6.0 / v6.0.0 / v6.2.0 的 Release
里裸放安装包数量均为 0,而 README 一直承诺提供它们。已补上签出步骤,并把
「脚本不存在」改为非零退出码失败(单个格式打包失败仍只告警,不拖垮发布)。.github/workflows/web.yml(挂在 push:[main],每次推 main
都白跑一遍,且带 contents: write 权限)、tool/web_build.py、docs/WEB.md。
v6.0.1 的 changelog 声称已删除,但从未真正推上去。platform_spec.yaml + 统一注入器取代的旧脚本。docs/README.md 自身”一次性规划落地后即移除”的约定)。raw 端点没有签名机制。ARCH 环境变量而退出码 1。
三种包在 zip / 7z 里都齐全,功能上不缺,只是未裸放直传。主题:内置加速通道换新代理 + 架构决策:Web 端独立成支。 加速通道面向所有正式平台;Web 从此不在 main 上,走独立分支。
web + 独立 lib/ + 独立 workflows):
lib/,另起一套原生实现;build.yml / ci.yml,有自己的工作流;Web lives on its own branch with its own
lib/and its own workflows — no shared code, no shared actions, and it may fail as often as it needs without ever affecting the five-platform release.
lib/platform/ 平台实现层 —— 每个平台一份真实 Dart 实现
(window_windows.dart / window_linux.dart / window_macos.dart /
window_mobile.dart),契约在 window_capability.dart,
选平台只发生在 platform.dart 一处(全项目唯一的 Platform.isXxx)。surface/app/desktop_window.dart 退化为桥接:函数名 / 枚举 / 常量
原样转发,上层调用点零改动。windowManager.setTitle() 写的
就是窗口管理器读的那个标题,inject_desktop_shell.py 是重复劳动,
已删除。tool/platform_spec.yaml,由 tool/inject_platform_spec.py 在构建期注入。why(为什么不能用 Dart),
脚本强制校验,缺 why 直接拒绝执行;自检
(inject_platform_spec_selftest.py,22 项,含幂等性与仓库不被污染)已挂 CI。inject_android_gradle.py / inject_android_manifest.py /
inject_windows_cmake.py / inject_desktop_shell.py / inject_android_icon.py
五个脚本,由 spec 驱动的注入器统一接管。gh.felicity.ac.cn 转发完整 GitHub 链接
(lib/surface/util/accel.dart):
https://gh.344977.xyz/ 改为
https://gh.felicity.ac.cn/https://github.com/,即拼出
https://gh.felicity.ac.cn/https://github.com/… 这种转发完整链接的形式;https://gh.felicity.ac.cn/ 保留为降级备选,仍按序探测、静默降级,
最后永远保留直连兜底;test/surface/path_rules_test.dart)。changed/)全部 Release 下载链接由旧式镜像前缀改为
https://gh.felicity.ac.cn/https://github.com/… 形式;生成器
changed/generate_posts.py 的 ACCEL_HOST 同步更新,保证后续重新生成一致。.github/workflows/web.yml、
tool/web_build.py、docs/WEB.md):该管线在 main 上是死代码(wasm 因
dart:ffi 依赖必然失败),留着只会混淆职责。Web 改由独立分支承接。合并说明:本版包含 v5.9.0(未发布成功 · 构建失败)的全部功能,以及 v5.7.0 / v5.8.0 跳号期间准备的跨平台硬化内容。
LICENSE、docs/x.md、#锚点、裸域名)先按仓库基址解析成绝对地址再交给系统浏览器;解析不了会明确提示,不再”点了没反应”。Image.memory 渲染,不经过 raw.githubusercontent.com,避开 DNS 污染;<img src=…> 也会渲染成图;单次上限 40 张,超出或失败退化为 alt 文本(不静默丢图)。ubuntu-22.04 / ubuntu-24.04-arm 宿主上直接构建以锁定该下限)ci.yml → ai_audit job):用 Agnes(agnes-2.5-flash 高智能)对架构 / 安全 / i18n / 性能 / 变更记录做补正则盲区的复核;密钥走 Secret AGNES_API_KEY,缺失则跳过并显式标注(不锁死 CI)。.github/workflows/quality-audit-hourly.yml):cron 每小时触发,tool/ai_quality_audit.py 逐个文件审查 lib/**/*.dart(5 rpm 限速,防撞 API 上限),结果 TXT 发布到独立 tag CI-cat-<北京时间>-cst8。w9.xzdio(xz 级别上限 9,w10 非法)。release_notes/v6.0.0.md 生成(中英对照)。ubuntu-22.04、arm64 腿 ubuntu-24.04-arm,宿主直编。20.04 容器已 EOL、archive 源超时,且容器失败后的回退等于把全量编译跑两遍——曾把 Linux 腿挂死 5h50m;同时给 build job 加 timeout-minutes: 45 兜底。glibc 下限随之由 2.31 抬到 2.35。主题:跨平台差异面硬化 —— 直面 Windows / Linux / Android 三系差异, 把”能跑”变成”在真实发行版上也能跑”。
\\?\ 前缀绕过 MAX_PATH → 仍失败则把超长部分
收纳为 TooLongRoad_<8位随机编号>.zip(落在最近可用父目录,包内保留完整相对路径)
→ 根目录 .ogl_toolong.json 索引,read / exists / delete / list 全部贯通。tool/inject_desktop_shell.py):Windows 出 256 单帧 ICO
并写入 Runner.rc 版本信息,Linux 出 2048 PNG 母版;两者都把原生窗口标题
写为 OhGithubLost(任务栏 / Alt-Tab / 任务管理器读的是它)。tool/desktop_icon.py):直接解析图标几何源 SVG,
扫描线填充 + 抗锯齿 + 自编码 PNG/ICO,CI 无需 cairo / Pillow。scope|path,
而 | 在 Windows 是非法文件名字符 → 一律 FileSystemException。
现改为 sha256(编码键),purgeOrphans 同步(否则会误删有效缓存)。ubuntu:20.04 容器内构建以锁定该下限)未发布。5.7 → 5.8 之间没有独立变更面,直接进入 v5.9.0。 Not released. No independent scope between 5.7 and 5.8; the line moved straight to v5.9.0.
未发布。版本号被保留但未投入使用(当时正在做跨平台差异面硬化,准备合并成一个大版本)。 Not released. The number was reserved but never used — the cross-platform hardening was being prepared as one bigger release.
主题:存储三档(公共目录 → SAF → 内部) + 网络独立成页 + 引导页重做(语言/外观前置)+ 加速通道内置优先链。 Three-tier storage (public dir → SAF → internal), network settings as its own page, reworked onboarding (language & appearance first), and a built-in acceleration priority chain.
/storage/emulated/0/ogl | ✅ | 过 |
| ② SAF 文件夹 | 用户授权了文件夹 | 私有目录 → 导出粘贴到该文件夹 | ✅ | 过 |
| ③ 应用内部 | 两者都没有 | 应用私有目录 | ❌ | 不过(不阻断) |SafStream.pasteLocalFile 粘贴到用户选的文件夹。新增依赖
saf_util / saf_stream(仅 Android 生效)。OGL-DL-301(已导出到所选文件夹)。assets/icon/ogl_icon.svg;
Android 用矢量 XML(VectorDrawable 前景 + 自适应图标,透明背景)。armeabi-v7a)。.zip 与 .7z 双份、极限压缩(zip -9 / 7z -mx=9)。gh.344977.xyz(优先)+ gh.felicity.ac.cn(降级),
用户不可调整;下载时逐个探测,静默降级,最后永远保留直连兜底。gh.344977.xyz(优先)+ gh.felicity.ac.cn(降级备选);
界面上仍是一个「内置通道」(不出地址、不可删、不可改)。pages/network_page.dart)。common 分片),此前可能显示成键名。Android/data/...(Android 11+ 起被系统
隐藏)与内部存储一律不算可见,如实报告 needsUserAction。invalidate() 并重新解析,授权后
立刻切到系统可见的 ogl 目录。OgLStorageTier(公共 / 应用外部 / 内部 / 桌面)与
isUserVisible()、location()、invalidate()。Android/data / 内部存储一律不算“用户可见”)。主题 · Theme — 权限网关与 SAF 三档存储的开发迭代:未单独发版,内容全部并入 v5.6.0。 Development iteration for the permission gateway and the three-tier SAF storage. Never released on its own; all of it shipped in v5.6.0.
pasteLocalFile),下载完成自动导出——不必重写下载引擎。
After the user grants a directory, local files can be pasted into the SAF tree and downloads are exported automatically.主题 · Theme — 网络与下载通道改造:未单独发版,内容并入 v5.6.0。 Network and download-channel rework. Never released on its own; shipped in v5.6.0.
gh.344977.xyz 优先、gh.felicity.ac.cn 降级;内置通道用户不可调整,失败时静默降级,不打断浏览。
gh.344977.xyz first, gh.felicity.ac.cn as fallback. Built-in channels are not user-editable and degrade silently on failure.主题:动效全面升级(自然减速 + 物理弹簧 + 全覆盖)与仓库统计曲线重构。 Motion overhaul (natural deceleration + physics springs + full coverage) and rebuilt repository stat charts.
OgLSurfaceSwitch:大体积内容切换(快速淡入 + 极轻缩放,低档只淡入);
ogLShowSheet<T>():底部弹层统一定速入口(overlays.dart),
5 处 showModalBottomSheet 已改用它。Curves.linear):三档统一走 ease-out 阶梯
(easeOut → easeOutCubic → easeOutQuart,大体积再各进一档到
easeOutQuint)——起手快、落位柔,符合直觉而不再”机械 / 死板”;
切 tab 的整页位移也从”控制器直驱匀速”改为走档位曲线(曲线只改落位节奏,
时长不变,因此对操作的影响不变)。新增门禁:tool/motion_audit.py
禁止白名单外出现 Curves.linear。OgLSpring(SpringSimulation 驱动),切 tab
改用弹簧——由刚度 / 阻尼而非固定时长决定运动,天然可打断 / 可续跑
(”跟手”);阻尼比逐档递减(档位 1 临界阻尼不振荡,档位 2/3 轻微回弹)。settleCurve,只作用在位移 / 缩放上
(拉满档用 easeOutBack);透明度插值保持单调,绝不回弹。OgLSharedTitle,把仓库列表的名称与
仓库详情的标题连成一次 Hero 飞行(”空间连续感”);标准档及以上启用。revealAll(覆盖面)。
revealOffset = 0、不缩放),只保证”每个控件都有动画”;OgLAnim.staggerOf:超出错峰范围的项在全覆盖档位仍参与动画
(只是不再错峰),不再是”直接静态渲染”。AsyncView 数据态加入场:加载 → 数据不再”硬切”,整片内容淡入
(用单子层的 OgLReveal,放进 Expanded 也不会无界)。settings / about / login / 四个 new_*
/ code_editor / issue / pull / commit / release_detail 的页面内容
统一包一层入场动画;Gist 列表逐项入场。OgLRevealList.of(context, children):把一串子控件逐个包上入场
动画(自动错峰),用于整栏 / 整页覆盖。
min..max 满高绘制:3→4 也能画成”垂直暴涨”,且星标图与提交图
各自满高、量纲不同却看起来同量级。现在从 0 起、上限取整齐刻度
(1 / 2 / 2.5 / 5 × 10ⁿ)、5 条刻度线并标注数值。STARS (COUNT) / COMMITS (COUNT))、纵轴单位、5 条纵轴刻度、
横轴时间刻度、最新值标记与”来源”说明——不再依赖 README 图注去猜。MM-DD HH:MM(首 / 中 / 尾)。--selftest:不联网核对刻度上限(含 1/2/2.5/5 阶梯)、刻度单调、
时间轴按真实间隔映射、单点落中、降采样保留首尾、历史点容错、字体字符齐全、
PNG 头部与尺寸正确——已接入 stats.yml 与 ci.yml。主题:动效严格按档位分级 —— 降档 = 降质量,而不是在各处写死或直接砍掉效果。 Animations are strictly tiered: lowering the tier now reduces quality instead of hard-coding or cutting effects.
档位语义改为「质量」· Tiers now mean quality
每一档都有完整的动画,只是开销逐级更低(1 最保守 → 2 标准 → 3 拉满),
档位 0 为静默(时长归零、无位移/缩放,内容依旧完整呈现——不是”功能更少”):
| 档位 | 时长(快/中/慢) | 入场效果 | 错峰项数 | 过渡位移 | 缩放 | 模糊 |
|---|---|---|---|---|---|---|
| 0 静默 | 0 / 0 / 0 | 无 | 0 | 0 | 无 | 无 |
| 1 保守 | 110 / 150 / 190 ms | 只淡入 | 前 4 项 | 0.012 | 无 | 无 |
| 2 标准 | 170 / 220 / 280 ms | 淡入 + 轻位移 | 前 9 项 | 0.035 | 无 | 无 |
| 3 拉满 | 220 / 300 / 380 ms | 淡入 + 位移 + 轻微缩放 | 前 17 项 | 0.06 | 0.99 / 0.985 | 允许(≤6) |
Every tier keeps the full animation vocabulary; only the cost drops with the tier. Tier 0 is silent but still shows all content.
设置项文案随语义更新 · Settings copy updated 动效档位标签由「最小 / 当前 / 标准 / 增强」改为 静默 / 保守 / 标准 / 拉满, 说明写清每档具体做了什么(15 语言同步)。
OgLOAnimQuality:把某档位下的全部动画参数
(时长、错峰步长、错峰项数上限、入场位移/缩放、过渡位移/缩放、模糊上限、缓动)
收进一张表,成为唯一事实来源;isNotHeavierThan 把”降档 = 降质量”钉成可测约束。OgLAnim.staggerOf() 对超出档位上限的序号返回 null,
OgLReveal 见到 null 直接静态渲染。此前长列表的每一项都会挂动画
(越靠后的项越晚、且同时起跳),是”列表滑动发涩”的常见来源。OgLReveal 自带 RepaintBoundary:入场期间每帧只重合成,不重绘列表项内容。tool/motion_audit.py(已接入 CI):lib/surface/** 里禁止
硬编码 Duration(milliseconds: …)、ScaleTransition/AnimatedScale、
BackdropFilter/ImageFilter.blur(档位表与工具箱白名单除外;
节流 / 缓存 TTL / 草稿防抖 / 双击退出窗口等等待类时长可豁免)。扫描出 5 类反模式(tool/perf_audit.py),按”确定性收益”排序处理:
OgLAsyncSliver(AsyncView 的 sliver 版):静态头部留在
SliverToBoxAdapter,数据行交给 SliverList.builder 按需构建。
此前 ListView(children:[…]) 里套
AsyncView(builder: (c, files) => Column(children: [for …])) ——
一次 PR 改 300 个文件就是一次性构建 300 个 ExpansionTile;
PR 页与提交页已改用它(其余数据驱动列表按同一模式推进)。
ListView(children:) + for 的写法只报告不拦截(循环长度是语义问题,
硬拦会逼出无意义白名单),门禁只保留客观项。OgLAnim.enabled 由 MediaQuery.of(context) 改为
MediaQuery.disableAnimationsOf(context):列表项不再因为键盘弹出 / 旋转 /
insets 变化而整列重建(长列表里这条最明显)。TickerMode(enabled: false):不可见页面不再推进动画
(下载进度、入场动画等),避免”看不见的页面在偷偷烧帧”。SurfaceBridge.themeFor(brightness, motionLevel:) 按
(亮度 + 种子色 + 密度 + 动效档位)缓存 ThemeData;键不变就复用同一实例,
顺带让 AnimatedTheme 不再把”等价主题”当成变化(每次 setState 都重建主题是隐性开销)。日志通知合并 · Coalesced notifications
OgLAppLog.add 批量写日志时把 notifyListeners 合并为最多 200ms 一次
(数据仍逐条立即入表,只是通知延后——不改变任何可见内容),
避免通知中心整表反复重建。
repo_page):ListView(children:[…]) → CustomScrollView +
SliverList.builder——目录动辄上百个文件,此前一次性构建全部行;issue_page)→ OgLAsyncSliver;action_run_page)→ SliverList.builder(作业 + 步骤)。
手法统一:行内容原样保留,只是移进 itemBuilder 闭包并用 index 取当前行
(不抽方法、不改视觉),减少回归面。perf_audit.py 的 REVIEWED_BOUNDED 里逐条登记
理由,避免”看起来像待办”。门禁:tool/perf_audit.py --fatal 已接入 CI,拦截 shrinkWrap: true
与过宽的 MediaQuery.of(context)(必要例外逐个登记并写明理由);
新增 test/surface/async_sliver_test.dart(500 行只构建视口附近的行)。
主题 · Theme — 动画严格按档位分级(降档 = 降质量、不删效果)、一轮性能优化,以及一次被对抗性探针发现的内核一致性硬化。 Strictly tiered animations (lowering a tier reduces cost, never removes effects), a performance pass, and a kernel-consistency hardening found by an adversarial probe.
动效改成「按档位给质量」· Animation tiers now mean quality
每档都保留完整动效,只是开销逐级降低;档位 0 静默但内容依旧完整呈现:
| 档位 | 快/中/慢 | 入场效果 | 错峰项数 | 过渡位移 | 缩放 | 模糊 |
|---|---|---|---|---|---|---|
| 0 静默 | 0 / 0 / 0 | 无 | 0 | 0 | 无 | 无 |
| 1 保守(默认) | 110 / 150 / 190 ms | 只淡入 | 前 4 项 | 0.012 | 无 | 无 |
| 2 标准 | 170 / 220 / 280 ms | 淡入 + 轻位移 | 前 9 项 | 0.035 | 无 | 无 |
| 3 拉满 | 220 / 300 / 380 ms | 淡入 + 位移 + 轻微缩放 | 前 17 项 | 0.06 | 0.99 / 0.985 | ≤ 6 |
设置项文案随之改为 静默 / 保守 / 标准 / 拉满(15 种语言同步)。 Every tier keeps the full vocabulary; only cost drops. Tier 0 is silent but shows all content.
OgLAnim.staggerOf() 对超出档位上限的序号返回 null,OgLReveal 见到 null 直接静态渲染——长列表不再”越靠后越晚”。MediaQuery 选择器 · Narrow selectors
OgLAnim.enabled 改用 MediaQuery.disableAnimationsOf:列表项不再因为键盘 / 旋转 / insets 变化整列重建。TickerMode(enabled: false)。ThemeData。OGL-BOOT-108(warn 级诊断 + 引导信任告警)——仍可启动,但一定留痕。附回归用例。layer_audit(依赖只能向下)、i18n_scan(界面文案 0 遗漏)、motion_audit(动画必须走档位)、perf_audit(反模式)。主题:5.x 的第一个正式版 —— 5.0 的交互打磨全部内容 + 一次被探针发现的内核一致性硬化。 First stable of the 5.x line: everything from 5.0 plus a kernel-consistency hardening found by an adversarial probe.
v5.0.0-beta 的全部内容(多连接分片下载 / 页面过渡修复 / 长日志虚拟化 /
通知中心去符号 / 返回键统一 / 权限每次启动自检)+ 内核「清单 ↔ 运行期模块」交叉校验。OGL-BOOT-108
(诊断 warn + 引导信任告警)——能启动,但一定留痕,不误伤可用性。
Found by a throwaway adversarial probe running on its own CI branch: a module declared
in the boot manifest but never assembled was previously accepted silently. The kernel now
cross-checks manifest against runtime modules and records OGL-BOOT-108 (warn-level
diagnostic + boot trust warning) — boot still succeeds, but never silently.test/kernel/kernel_test.dart:清单声明但未提供 → 必须出现
OGL-BOOT-108)。Covered by a regression test.Range 并发拉取 + 顺序合并;每片独立临时文件(规避共用句柄错位),
任一分片失败即清理全部分片(不交付半成品);不支持 Range 自动回退单连接。
新增「下载并发连接数」设置(1/2/4/8,默认 4)与进度/速度动画。ZoomPageTransitionsBuilder 的整页重光栅化正是根因),
改为单层淡入 + 轻位移并强制 RepaintBoundary。ListView.builder 按需渲染,显示「共 N 行」。✔ / ▶ / ✗ / ★ 等 emoji 风格符号(改由图标与 level 承载),
详情展开带动画。OGL-PERM-001/002/000)上报通知中心。Range 能力判定,不支持则回退)。v5.0.0-beta 的产物构建于内核硬化之前;如需完整修复请使用本版。主题:交互与体验打磨(不加新功能面)。用户明确的 5.0 范围已全部实现,见下。
kernel/contract/download_engine.dart:把「分片下载能力」写成接口
(probe / fetch / 取消令牌 / 失败语义),逻辑层只认契约 —— 依赖方向不破。base/net/range_download.dart:
Range 请求把文件切成至多 N 片并发拉取,最后顺序合并;<目标>.partN)而非共用文件句柄 —— 直接规避项目早期
“多 worker 共用 RandomAccessFile 导致错位写坏”的老问题;OgLChunkPlan 是纯函数(不重不漏、余数进最后一片、小文件不开一堆连接),
有 7 条边界用例(含逐字节覆盖校验)。IxDownloadManager.enqueue(connections:);服务端不支持 Range
(或探测失败)自动回退到库任务(同一 taskId,页面无感),
回退与失败分别记 OGL-DL-201 / OGL-DL-202。
暂停 / 取消 / 重试对分片任务走取消令牌(不留半个文件)。TweenAnimationBuilder 补间 220ms(不再”跳格子”);
速率量化到 0.1 MB/s 后经 AnimatedSwitcher 淡入淡出;分片任务在列表里带
「多连接」图标标记。ZoomPageTransitionsBuilder),
缩放要求整页在过渡期间反复重新光栅化 —— 页面越重越卡,而小控件动画不受影响,
所以表现为”只有页面过渡卡”。RepaintBoundary(过渡期间只重合成、不重绘页面内容)。_OgLShellSlide 同样补上 RepaintBoundary(此前整棵页面树每帧重绘)。test/surface/page_transitions_test.dart:锁死”必须包 RepaintBoundary、
不得出现任何缩放、不得回退默认缩放过渡、全平台都要配到”。surface/widgets/log_body.dart:按行分块(默认 120 行/块)交给
ListView.builder 虚拟化渲染;上万行日志不再一次性排版。SelectionArea)。test/surface/log_body_test.dart:断言 1200 行时只渲染视口附近的分块
(虚拟化失效会被测出来)。✔ / ▶ / ✗ / ★ / → / ← 不再出现在用户可见文案里
(它们在 Android 上会被当 emoji 呈现,正是用户说的”emoji 撕裂”)。
结构化信息改由 level 承载(新增 STEP 级别),可见性交给图标。{count} 星标。AnimatedSize),并新增会旋转的展开指示图标;
「未读」也走 i18n(不再硬编码中文)。surface/app/back_guard.dart:把”按一次返回键应该做什么”抽成纯状态机
(可单测);ClientShell 用 PopScope 统一接管。test/surface/back_guard_test.dart(7 条时序用例,含窗口过期与状态清理)。surface/app/permission_selftest.dart:每次启动都实测权限
(存储走真实写入探针,通知向系统查询),只复核不弹窗,5 秒超时兜底。OGL-PERM-001 存储 / OGL-PERM-002 通知 /
OGL-PERM-000 自检失败)→ 通知中心;就绪项只留日志。test/surface/permission_selftest_test.dart(含”自检自身失败也不抛”用例)。本版本 = 结构与多语言工程(不含新功能)。
surface → domain → base → kernel,只允许向下。lib/surface/types.dart:UI 只能看到 DTO / 枚举 / 异常,
服务类(GhClient / GhAuthService / IxDownloadManager / IxSession /
IxNotificationCenter)被 hide,只能经 SurfaceBridge 取用。directives_ordering 重排。SurfaceBridge 提供 downloadTasks / downloadsListenable /
pauseDownload / resumeDownload / retryDownload / cancelDownload /
removeDownload / clearFinishedDownloads,下载页不再接触管理器实现。tool/layer_audit.py(四层审计):当前违规 0。disk_store.dart / disk_types.dart /
net_types.dart 移入 kernel/contract/(原路径保留转发导出,硬件层内部零改动),
逻辑层改依赖契约 → 待收敛项由 11 处降至 2 处(仅剩 RepositoryCache /
NetBridge 两个实现类,下一批以契约接口收敛)。assets/i18n/<locale>/<page>.json(2 空格缩进 + 键排序):
27 个页面 / 848 条中文文案由人工按语境撰写;术语(GitHub / Release /
Actions / Pull request / Token / Pages / Commit…)不译,描述不加额外语句。t(page, key, {args}) 支持 {name} 占位符,
兜底顺序 = 当前语言 → 英文基线 → 键名(绝不返回空串);
新增 tool/i18n_wire.py(按 zh 分片反查、占位符按位绑定、自动补 import/助手、
剥掉会失效的 const)与 tool/sort_imports.py。tool/layer_audit.py --fatal(依赖只能向下)与
tool/i18n_scan.py --check(界面文案 0 遗漏 / 分片键集合与 zh 一致)
已接入 CI —— 结构回退与漏翻会在合并前被挡下。// i18n-allow 显式豁免)。
https://server.344977.xyz:9999/(HTTPS;此前明文
http://…:5000/ 会被 Android 9+ 拦截,正是 4.4.0 那次下载故障的根因)。/ 结尾;明文 http 会被直接拒绝并说明原因。util/accel.dart):
test/surface/path_rules_test.dart(路径规则 / 空文件 / .gitkeep /
通道地址 / 地址拼接 / 协议区分)。.gitkeep 不允许重命名。flutter_local_notifications,后台/allChannels 通知改为真正发系统通知
(Android / Windows / Linux / macOS / iOS);失败只留痕并回退到”落盘 + 回前台补发”。tool/inject_android_gradle.py 现在幂等注入
compileOptions.isCoreLibraryDesugaringEnabled 与 desugar_jdk_libs:2.1.4,并在自检中校验。themeAnimationDuration):换明暗 / 主题色不再”硬切”;
系统关闭动画时自动为 0(与 R11 一致)。
R3 / 文件细节 / 通知 / 外观修正(多语言仍留待下一版本):
/ 结尾时自动创建 <目录>/.gitkeep 占位
(Git 不跟踪空目录)。.gitkeep 占位例外)。util/path_rules.dart,新建/重命名共用):只允许
A-Z a-z 0-9 . _ - 与 /;禁止中文与全角字符、空格与特殊字符;
禁止 ..、//、以 / 开头、以点/空格结尾、Windows 保留名、单级 > 100 字符。permissions.push,不做降级)GhRepo 新增 canPush / canAdmin(解析 permissions)与 isWritable。initState 补拉单仓库详情(只有该接口返回 permissions,
列表/收藏/搜索都没有);拿不到详情时留痕并按不可写处理。OgLNoticeDelivery{auto, inAppOnly, allChannels},report() 可指定投递方式。OgLNoticeHost 接入 WidgetsBindingObserver:后台不弹应用内提示,
allChannels / critical 走系统通道,其余排队并在回到前台时补发(不丢消息)。ChoiceChip 选中态改为 primary/onPrimary,明环境下对比度提升;
主题色芯片不再用勾号顶掉色点。第三阶段(工程与交互):
on.workflow_dispatch.inputs,把必选参数 / 默认值 / 选项渲染成表单
(字符串 / 数字 / 布尔 / 下拉选择),必选缺失会在提交前拦下并提示;
保留「高级:直接输入」入口(JSON 或每行 key=value)。新增纯 Dart 依赖 yaml。IndexedStack 的状态与懒挂载);关闭动画时瞬时切换。待办:R6 多语言(其余页面仍有硬编码中文)体量较大,需要单独排期 逐页抽取文案 + 补齐各语言分片,本次未纳入,以免产出半成品的一致性问题。
第二阶段(体验)修复:
GhReadCache),为 Releases /
分支 / 提交 / Issues / PR / Actions / 仓库详情等只读端点设定缓存时长
(30–60 秒),账号维度隔离;下拉刷新 / 写后重读会让缓存失效并回源;
切换账号时清空。搜索、用户、限流端点不缓存(必须新鲜)。写操作令整体失效。修复(设备实测反馈)
Cleartext HTTP traffic to ... not permitted)。设置项已从界面
移除;通道地址仍只存在于实现内部常量,不对外暴露。0 B;现于完成时以磁盘文件大小回填(读不到则按事件码 OGL-DL-101 上报)。下载
本版:网络传输弃用 dio、代码编辑与高亮换用成熟库、并批量修复设备日志排查出的 问题(P2–P7)。
代码查看与编辑(换用成熟库)
re_editor(编辑器内核)+ re_highlight(语法高亮,highlight.js 的 Dart
移植);删除自研词法器与自绘渲染 lib/surface/widgets/code_view.dart。OgLCodeViewer /
OgLCodeField);超大文本改由库的 CodeHighlightThemeMode.maxSize 兜底。下载(background_downloader,本就是库实现)
threadsActive 字段(从未赋值);网络(弃用 dio)
dio 改为直接使用 dart:io HttpClient(新增 lib/base/net/io_net_transport.dart,
删除 dio_net_transport.dart),pubspec.yaml 移除 dio 依赖;Actions 日志下载(IxActionLogs)
同步改为 HttpClient。理由:Dio 把”连接策略”藏进适配器层,排查与修都无法直接动手。request.persistentConnection = false,
即请求头带 connection: close):
设备日志实证 Connection closed before full header was received 反复出现,
而同一时刻原生自检全绿——差别只在”是否复用连接”。禁用复用后每个请求走新连接,
从根上消除该类故障。SocketException / HttpException)统一归为可重试的连接错误,
并在重试前清空 DNS 缓存(避免钉在坏 IP 上)。test/base/net_transport_reconnect_test.dart:
对端”响应后即关闭连接”时,连续请求必须全部成功;并断言连接策略已禁用复用。日志排查后续修复(P2–P7)
dart:io 把”连接在接收中被关闭”等场景归入
unknown,此前不可重试,大响应中途失败即终止;现纳入可重试类别
(是否真正重试仍受”仅幂等方法”约束,POST 依旧不会自动重试)。refresh: true,
使底座缓存永不命中、每次切目录/切标签都重新下载;现默认走缓存,
仅下拉刷新 / 写操作后强制回源。TabBarView 销毁重建时秒开、不再重复请求;
用户下拉刷新与写后重载不受影响(始终回源)。readme() 改为直接请求 /readme,去掉”先探测 README.md“的额外一次 404。本版聚焦「仓库浏览」的补齐与控件/布局的 Material 3 规范化。
仓库浏览
FloatingActionButton 入口(路径 + 内容);GhApi.workflowRuns 新增 branch / page 参数。控件与布局(Material 3)
FloatingActionButton.extended
(新建仓库 / 新建议题 / 新建发布 / 新建分支 / 新建文件);PopupMenuButton:仓库(复刻 / 复制克隆地址 / 浏览器打开)、
文件(复制路径 / 浏览器打开 / 删除)、分支(重命名 / 删除);ListTile + OgLReveal;已知限制(客观)
验证
analyze --fatal-infos --fatal-warnings + 全量测试)
与全平台构建矩阵(Android ×5 / Windows ×2 / Linux ×2 / macOS ×2 / iOS ×2)。可靠性重构版:自底向上逐层修复,并将多个自研模块替换为成熟库。
验证状态
flutter analyze --fatal-infos --fatal-warnings + 全量单元/渲染测试;依赖变更
permission_handler ^13.0.2(运行时权限)、background_downloader ^9.6.3(下载)、archive ^3.6.1(日志解压);dependency_overrides: connectivity_plus: 6.1.4:background_downloader 依赖 connectivity_plus '>=6.1.3 <8.0.0',
其 7.x 的 macOS / iOS Swift 使用了构建环境 SDK 尚未提供的 NWPath.isUltraConstrained,导致 iOS / macOS 构建失败;
固定到 6.1.4(仍满足上游约束)后恢复;highlight / flutter_highlight / flutter_code_editor:其 SDK 约束为 Dart < 3,与当前 Dart 3.13 不兼容。权限
permission_handler:Android / iOS / macOS 会真正调起系统权限弹窗;
此前实现只执行”写入探针 + 打开设置”,且使用 iOS 专用的 app-settings: URI(在 Android 上无效);manageExternalStorage;Android 13+ 运行时请求 POST_NOTIFICATIONS;tool/inject_android_gradle.py:幂等提升宿主 compileSdk(平台目录由 CI 现场生成);tool/inject_windows_cmake.py:为 permission_handler_windows 注入 MSVC 兼容宏
_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS。通知
KernelDiagnostics 的 error 与引导层信任告警经 sink 转发到 OgLNoticeCenter,
各层(含无 BuildContext 的底座 / 中枢)的告警均可触达界面;认证
GhAuthService 改为 ChangeNotifier 并引入 GhAuthState(unknown / signedOut / signingIn / signedIn / expired / guest);草稿
DraftStore 改为 ChangeNotifier,并通过 GhApi.draftsChanged 暴露;
草稿箱与「我的」页订阅后实时刷新(此前为一次性查询)。编辑器
highlight 系库的原因见上);UndoHistoryController(替换自研防抖快照栈)。下载
background_downloader(断点续传 / 队列 / 暂停 / 继续 / 取消);IxDownloadManager / IxDownloadTask / IxDownloadCategory / IxDownloadStatus 对外契约不变,相关页面未改动;Actions
archive 解压,按 job 展示与搜索
(ix_action_logs.dart + action_log_page.dart);动效
OgLReveal 与动效档位;本次覆盖搜索等页面。其他
permission_handler / background_downloader / archive;POST_NOTIFICATIONS 断言;PYTHONIOENCODING=utf-8
(此前在 Windows 默认码页下打印非 ASCII 会抛 UnicodeEncodeError 并使该构建目标失败)。已知限制
background_downloader 9.6.3 的 flutter.plugin.platforms 仅声明 android / ios;桌面端(Windows / Linux / macOS)
不注册该插件,桌面端下载功能不可用;动效(与设置里的「动效档位」联动)
其他
docs/ANIMATION_PLAN.md(3.2 任务与性能对应);下载
ogl/download/<分类>/。文件与日志
ogl:日志落到 ogl/logging,下载按分类存放;草稿
可靠性与权限
其他
界面
功能
可靠性
其他
主题 · Theme — 第二阶段(W0–W8):界面与功能重写。 Stage two (W0–W8): a rewrite of both the interface and the feature set.
OgLActionRow(含自绘开关),清掉所有 Material ListTile / SwitchListTile / ChoiceChip。主题 · Theme — 首个公开发布:Linux 内核式分层架构的 GitHub 第三方客户端(Flutter 全平台)。 The first public release: a GitHub client with a Linux-kernel-style layered architecture, built with Flutter for every platform.
签名:自本版起使用固定证书;由旧随机证书构建的安装包请先卸载再安装。