From 623bc085f67f675eb579bf4fec510aabe75cc2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 9 Oct 2026 15:58:26 -0400 Subject: [PATCH] Hosting moves to git.zacharyzhang.com: component dependency, site links, references; GitHub workflows removed --- .github/workflows/engines.yml | 77 ----------------------------------- .github/workflows/release.yml | 58 -------------------------- Cargo.lock | 3 +- Cargo.toml | 2 +- PRD.md | 6 +-- agents.md | 12 +++--- scripts/fetch-references.sh | 2 +- site/e2e/text.spec.ts | 8 ++-- site/src/main.ts | 12 +++--- site/src/release.ts | 2 +- site/src/text.ts | 4 +- site/video/scenes/index.html | 2 +- site/video/type/scenes.js | 2 +- 13 files changed, 29 insertions(+), 161 deletions(-) delete mode 100644 .github/workflows/engines.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/engines.yml b/.github/workflows/engines.yml deleted file mode 100644 index e1248ed..0000000 --- a/.github/workflows/engines.yml +++ /dev/null @@ -1,77 +0,0 @@ -# Builds the patched engines once; release.yml downloads them. -name: engines - -on: - workflow_dispatch: - -permissions: - contents: write - -jobs: - macos: - strategy: - fail-fast: false - matrix: - include: - - runner: macos-15 - arch: arm64 - - runner: macos-15-intel - arch: x86_64 - runs-on: ${{ matrix.runner }} - timeout-minutes: 355 - env: - GH_TOKEN: ${{ github.token }} - CCACHE_DIR: ${{ github.workspace }}/.ccache - CCACHE_MAXSIZE: 6G - steps: - - uses: actions/checkout@v4 - - name: Key - id: key - run: echo "key=$(scripts/engines-key.sh)" >> "$GITHUB_OUTPUT" - - name: Already built? - id: done - run: | - if gh release view "engines-${{ steps.key.outputs.key }}" --json assets \ - --jq '.assets[].name' 2>/dev/null | grep -qx "engines-macos-${{ matrix.arch }}.tar.zst"; then - echo "built=true" >> "$GITHUB_OUTPUT" - fi - - name: Tools - if: steps.done.outputs.built != 'true' - run: brew install make gnu-sed bison flex gettext autoconf automake libtool ccache nasm zstd - - name: Compiler cache - if: steps.done.outputs.built != 'true' - uses: actions/cache/restore@v4 - with: - path: .ccache - key: ccache-macos-${{ matrix.arch }}-${{ steps.key.outputs.key }}-${{ github.run_id }} - restore-keys: ccache-macos-${{ matrix.arch }}- - - name: Upstream sources - if: steps.done.outputs.built != 'true' - run: scripts/fetch-references.sh - - name: LibreOffice (patched) - if: steps.done.outputs.built != 'true' - run: scripts/build-libreoffice.sh - - name: MuPDF (patched), Git, git-lfs, OCR data, CEF - if: steps.done.outputs.built != 'true' - run: | - scripts/build-mupdf.sh - scripts/build-git.sh - scripts/fetch-git-lfs.sh - scripts/fetch-tessdata.sh - scripts/fetch-cef.sh - - name: Keep the compiler cache, even after a timeout - if: always() && steps.done.outputs.built != 'true' - uses: actions/cache/save@v4 - with: - path: .ccache - key: ccache-macos-${{ matrix.arch }}-${{ steps.key.outputs.key }}-${{ github.run_id }} - - name: Publish - if: steps.done.outputs.built != 'true' - run: | - archive=engines-macos-${{ matrix.arch }}.tar.zst - tar -C engines -cf - lo-src/instdir mupdf-build mupdf-src git git-src/COPYING git-src/LGPL-2.1 cef tessdata | - zstd -19 -T0 -o "$archive" - tag=engines-${{ steps.key.outputs.key }} - gh release view "$tag" >/dev/null 2>&1 || - gh release create "$tag" --prerelease --title "$tag" --notes "Pinned, patched engines; built by engines.yml." - gh release upload "$tag" "$archive" --clobber diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index db15d7d..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Builds macOS apps for a release tag and attaches them. -name: release - -on: - workflow_dispatch: - inputs: - tag: - description: Release tag to attach the packages to, such as v0.1.0 - required: true - -permissions: - contents: write - -jobs: - macos: - strategy: - fail-fast: false - matrix: - include: - - runner: macos-15 - arch: arm64 - - runner: macos-15-intel - arch: x86_64 - runs-on: ${{ matrix.runner }} - timeout-minutes: 120 - env: - GH_TOKEN: ${{ github.token }} - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - name: Engines - run: | - brew install zstd - tag=engines-$(scripts/engines-key.sh) - gh release download "$tag" --pattern "engines-macos-${{ matrix.arch }}.tar.zst" || - { echo "::error::no $tag for ${{ matrix.arch }}; run the engines workflow first"; exit 1; } - mkdir -p engines - zstd -dc "engines-macos-${{ matrix.arch }}.tar.zst" | tar -C engines -xf - - - name: Upstream sources and ElyMark's page - run: | - scripts/fetch-references.sh - scripts/build-mark-content.sh - - name: Tests that need no window - run: | - tests/scripts/types.sh - tests/scripts/icons.sh - python3 tests/scripts/comments.py - - name: Packages - run: packaging/macos/release.sh 1 - - name: Attach to the release - run: | - version=${{ inputs.tag }} - gh release view "$version" >/dev/null 2>&1 || gh release create "$version" --title "Ely Office $version" --notes "Built by release.yml." - gh release upload "$version" dist/*.dmg --clobber - if [ "${{ matrix.arch }}" = arm64 ]; then - gh release upload "$version" dist/ElyOffice-*-source.tar.gz dist/ElyOffice-*-upstream-source.tar.gz --clobber - fi diff --git a/Cargo.lock b/Cargo.lock index 9816afa..e6268f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1964,7 +1964,7 @@ dependencies = [ [[package]] name = "ely-gpui-component" version = "0.1.1" -source = "git+https://github.com/ZacharyZhang-NY/Ely-GPUI-Components?rev=f834f55c16b38d86fbc243b2d7719667503f4b01#f834f55c16b38d86fbc243b2d7719667503f4b01" +source = "git+https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components?rev=5d6efd46ec0c93b381ec7578561a1273c366025b#5d6efd46ec0c93b381ec7578561a1273c366025b" dependencies = [ "alacritty_terminal", "anyhow", @@ -2207,6 +2207,7 @@ dependencies = [ "gpui-pre-platform", "log", "notify", + "semver", "serde_json", "tempfile", ] diff --git a/Cargo.toml b/Cargo.toml index c25913f..f7da19f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ encoding_rs = "0.8" jiff = "0.2" anyhow = "1" directories = "6" -ely-gpui-component = { git = "https://github.com/ZacharyZhang-NY/Ely-GPUI-Components", rev = "f834f55c16b38d86fbc243b2d7719667503f4b01" } +ely-gpui-component = { git = "https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components", rev = "5d6efd46ec0c93b381ec7578561a1273c366025b" } env_logger = "0.11" gpui = { package = "gpui-pre", version = "=0.3.8", default-features = false, features = ["stacker"] } gpui_platform = { package = "gpui-pre-platform", version = "=0.3.8", features = ["font-kit"] } diff --git a/PRD.md b/PRD.md index e6af1c7..46bf609 100644 --- a/PRD.md +++ b/PRD.md @@ -529,7 +529,7 @@ AI 或脚本修改文件与其他外部修改使用同一套处理规则。ElyMa ### 15.2 接入基线 -后端以 Kigi CLI(https://github.com/ZacharyZhang-NY/Kigi-CLI,Rust)为基础,以 Rust 依赖直接嵌入,不用 ACP(用户 2026-10-05 定)。提供商登录(订阅账号或 API 密钥)、模型与端点配置沿用 Kigi 的实现,不另写一套。不解析终端装饰文本来伪造结构化事件。 +后端以 Kigi CLI(https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI,Rust)为基础,以 Rust 依赖直接嵌入,不用 ACP(用户 2026-10-05 定)。提供商登录(订阅账号或 API 密钥)、模型与端点配置沿用 Kigi 的实现,不另写一套。不解析终端装饰文本来伪造结构化事件。 会话恢复只在 Kigi 的会话存储支持并通过验证时启用。不能把本地历史回放当成后端会话已经恢复。 @@ -870,10 +870,10 @@ UI 自动测试、内核测试和手工交互测试互相补充。三端的输 核对日期:2026-10-01。来源用于确认接口、项目结构和许可条件,不证明 Ely 已完成接入。产品功能、默认设置与性能目标由本文定义。正式实现应记录所采用版本的固定提交和许可证,而不是只引用默认分支。 [S1] Ely GPUI Components,README,组件库使用方式、主题及许可证。 -`https://github.com/ZacharyZhang-NY/Ely-GPUI-Components/blob/main/README.md` +`https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components/blob/main/README.md` [S2] Ely GPUI Components,TASKS,组件分类与 host/prove 等状态定义。 -`https://github.com/ZacharyZhang-NY/Ely-GPUI-Components/blob/main/TASKS.md` +`https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components/blob/main/TASKS.md` [S3] LibreOfficeKit 官方文档,C/C++ 接口、分块渲染和输入回调。 `https://docs.libreoffice.org/libreofficekit.html` diff --git a/agents.md b/agents.md index 066e7de..fd75fec 100644 --- a/agents.md +++ b/agents.md @@ -39,7 +39,7 @@ site/ 官网(Vite 8、pnpm、TypeScript,无框架;等轴 SVG 积木 ## 组件映射 -依赖 `ely-gpui-component`(pin f834f55,gpui 为 crates.io 的 `gpui-pre` =0.3.8)。名字取自 `reference/Ely-GPUI-Components/src`。gpui 用法规则见该仓库 `AGENTS.md`。`tests/scripts/agents_md.py` 核对下表每个名字都是组件库公开项。 +依赖 `ely-gpui-component`(pin 5d6efd4,gpui 为 crates.io 的 `gpui-pre` =0.3.8)。名字取自 `reference/Ely-GPUI-Components/src`。gpui 用法规则见该仓库 `AGENTS.md`。`tests/scripts/agents_md.py` 核对下表每个名字都是组件库公开项。 | 需要 | 用 | | --- | --- | @@ -160,6 +160,7 @@ tests/scripts/mark-tools.sh 真窗口 ElyMark:查找替换、正则、Tab tests/scripts/comments-rules.sh comments.py 对长注释与跨行注释报错 tests/scripts/bad-settings.sh 通用设置读不出时 ElyDoc 照样启动,文件不被覆盖 tests/scripts/one-instance.sh 第二份 ElyDoc 被拒,第一份的工作目录不动 +tests/scripts/update.sh 装好的 ElyTree 从本机服务的新版下载、替换、重新打开(需辅助功能权限) tests/scripts/settings.sh 真窗口:ElyPDF 设置里选深色,ElyTree 即刻变深;作者名写入、不丢外观;ElyTree 拒绝非 Git 程序;设置文件读不出时提示且不覆盖;主窗口重开回到原处(需辅助功能与屏幕录制权限) tests/scripts/privacy.sh 真窗口 ElyDoc:键入的文字不进日志;worker 的日志进应用日志;设置里的诊断先列出所含内容,导出的文件去掉家目录与姓名、不含正文(需辅助功能权限) tests/scripts/panels.sh 真窗口 ElyDoc:左侧栏默认不宽于 230、拖动内侧边缘变宽、宽度存入设置、重启后照旧(需辅助功能权限) @@ -186,8 +187,8 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely ## 决策 -- 2026-10-01:上游版本以 `scripts/fetch-references.sh` 为准。LibreOffice 26.2.6(8221e31)、MuPDF 1.28.5(8ad45e9)、gpui 为 `gpui-pre` =0.3.8 与 `gpui-pre-platform` =0.3.8(crates.io,2026-10-07 起,随组件库 K01)、组件库 f834f55(2026-10-09 起)。 -- 2026-10-02:组件库 7380afb 起:对话框与面板的 Enter 提交改走字段的 key-down 动作(macOS IME 天然守卫,不再提前提交);面板族文案经组件 `i18n::text`(内建 en/zh-CN,应用目录可覆盖);核心控件带 role/aria;对话框带角色、名称与说明,Cancel/Close 与禁用说明本地化。同仓库 `~/Documents/GitHub/Ely-GPUI-Components` 修复并经 SSH 推送(本机 HTTPS keychain 令牌失效)。2026-10-04 组件库 b6cb94c:`NumberInput::on_commit` 只在 Enter、失焦、步进、拖动时触发,键入不触发;改文档的数值框用它,否则每个键入数字都成一条内核命令与一步撤销。同批带入上游的 Checkbox、Switch、Select 等 role/aria 与 RenderSurface。c0f17ee:`ToggleButton::disabled`(不可按、无 Tab 停靠、说明不可用,提示可写原因)。967d1e4:`ContextMenu::manual`(按属主编号的请求在某点打开,右键不开),供行在按下之后才到的菜单,如内核给的拼写建议。 +- 2026-10-01:上游版本以 `scripts/fetch-references.sh` 为准。LibreOffice 26.2.6(8221e31)、MuPDF 1.28.5(8ad45e9)、gpui 为 `gpui-pre` =0.3.8 与 `gpui-pre-platform` =0.3.8(crates.io,2026-10-07 起,随组件库 K01)、组件库 5d6efd4(2026-10-09 起)。 +- 2026-10-02:组件库 7380afb 起:对话框与面板的 Enter 提交改走字段的 key-down 动作(macOS IME 天然守卫,不再提前提交);面板族文案经组件 `i18n::text`(内建 en/zh-CN,应用目录可覆盖);核心控件带 role/aria;对话框带角色、名称与说明,Cancel/Close 与禁用说明本地化。同仓库 `~/Documents/GitHub/Ely-GPUI-Components` 修复并推送(2026-10-09 起推到 git.zacharyzhang.com,HTTPS,令牌在本机钥匙串)。2026-10-04 组件库 b6cb94c:`NumberInput::on_commit` 只在 Enter、失焦、步进、拖动时触发,键入不触发;改文档的数值框用它,否则每个键入数字都成一条内核命令与一步撤销。同批带入上游的 Checkbox、Switch、Select 等 role/aria 与 RenderSurface。c0f17ee:`ToggleButton::disabled`(不可按、无 Tab 停靠、说明不可用,提示可写原因)。967d1e4:`ContextMenu::manual`(按属主编号的请求在某点打开,右键不开),供行在按下之后才到的菜单,如内核给的拼写建议。 - 2026-10-06:审查者为探针复制的源码树须用自己的 `CARGO_TARGET_DIR`(`scripts/review.sh` 写明);写完结论前删掉这些副本与其构建目录(曾积到 /tmp 近 900 GB,磁盘写满、链接失败):曾编进本仓库 `target/`,ely-lok 里烘焙的源码路径指向已删的副本,单测找不到 worker。 - 2026-10-03:每条任务由 `scripts/review.sh` 在 herdr 分栏里交给 codex(gpt-6.1-sol,effort high;本机 `codex` 别名已带 `--yolo`,重复传参会报错)审查,最多三轮。此前各轮用 gpt-6-astra xhigh。 - 2026-10-01:macOS 的 LOK 用自建 LibreOffice 26.2.6.3 加 `patches/libreoffice/0001-lok-macos-tile-painting.patch`(已验证出图块)。2026-10-03 加 `0002-lok-dispatch-to-document-frame.patch`:`postUnoCommand` 原发往桌面的活动框架,另一文档关闭后命令落空或落到别的文档;改发本文档的框架。2026-10-04 加 `0003-lok-char-style-and-spacing-states.patch`:LOK 原不发当前字符样式与段前段后,属性栏无从同步;补发 `.uno:CharStyle`(界面名,无字符样式为空)与 `.uno:ULSpacing`(`上,下`,1/100 mm);混合选区的状态发 `{"commandName","dontcare":true}`,`ely_lok::MIXED` 表示,段落样式跨段不一致也算混合(原样报首段),字符样式带来的字体、字号、粗斜体等在选区内不一致也算混合(原样只看直接格式)。`.uno:ULSpacing` 缺的成员归零,故两值同发;属性栏记住已发未回显的两值状态(段距、页边距),连续编辑以它为底。同日加 `0004-lok-panel-states.patch`:补发页面尺寸、页面项(横向、版式、页码格式)、页边距、分栏、页眉页脚开关与版式、四种锚点与六种环绕(真假或禁用)、标题行重复;页面项缺的成员同样归零,故转向时页面项与尺寸都发。`0005-jsdialog-skip-disposed-dialogs.patch`:对话框守卫关闭对话框后,JSDialog 空闲任务仍为它生成整窗更新,读已释放窗口崩溃(实测崩溃报告),补丁让已释放的对话框不再生成消息。`0006-page-size-takes-the-page-item.patch`:`.uno:AttributePageSize` 也收页面项,转向是一次改动、一步撤销。`0007-lok-aqua-anyinput-without-peeking.patch`:worker 的请求经主 GCD 队列派发,而 Aqua 的 `AnyInput` 用 `nextEventMatchingMask` 窥探时会转动 run loop、在内核空闲任务中途执行请求(实测:表格删列与排版空闲任务交错,`SwLayIdle::DoIdleJob_` 段错误,约三成全量测试复现);补丁让 LOK 下的 `AnyInput` 改问客户端,worker 以 `registerAnyInputCallback` 报告是否有待处理请求,请求只在顶层让出时执行(补丁后连续十次全绿)。`0008-lok-toc-caption-formula-without-dialogs.patch`:目录、题注、公式在内核只有对话框入口;补丁给 `.uno:InsertMultiIndex` 加 `Title`(默认目录)、`.uno:InsertCaptionDialog` 加 `Category`(程序名)与 `Text`(照内核题注对话框的选项)、`.uno:InsertObjectStarMath` 加 `Formula`(文字转公式,选中公式时整体替换,一步撤销),并加 `getCommandValues(".uno:Formula")` 读选中公式。插入目录后光标落在目录内(内核原样)。`0009-lok-word-count-values.patch`:`getCommandValues(".uno:WordCount")` 给文档与选区的字数、字符数;内核的 `.uno:StateWordCount` 状态是英文串,只作重读的信号。构建加 `--with-myspell-dicts`,随包词典取自 LibreOffice 的 dictionaries 子模块(core 钉的 9925407,来源与许可见各目录 README 与 license),装在 `Resources/extensions`。构建后只留 `dict-en`(25 MB,英语拼写、断词、同义词):界面语言是英文与简体中文,中文无 Hunspell 词典;全部 65 个(473 MB)时 LOK 首启 5.4 秒、再启 2.3 秒,只留英文为 1.1 秒与 0.7 秒(PERF-01 要求 3 秒内可操作)。词典语种已由用户定:英文。`0010-lok-outline-values.patch`:`getCommandValues(".uno:Outline")` 给各标题的文字、级别、位置(twips)与是否当前(光标所在处按文档顺序之前最近的标题,`GetOutlinePos`;分栏时位置比不出先后),`.uno:Bookmarks` 的每项加位置(版面不显示的书签无位置);导航栏的跳转都按位置。`0011-lok-font-lists-present-when-a-member-is-used.patch`:LOK 把以 `;` 连写的字体列表整串当作字体名,列表中有字体已用上也报缺失(实测报出界面字体的回退列表);补丁让列表中任一成员用上即不算缺失,文档里写的列表全缺时照报。`0012-lok-calc-cursor-references-merge.patch`:Calc 在回调注册后补发单元格光标;`.uno:SheetReferences?sheet=N` 给引用某表的公式格数、命名区域数、第一个公式格,以及用 INDIRECT 的公式与名称数(这类引用运行时才知指向,删除说明里单独列出);合并带 `MoveContents` 时不弹对话框,并修上游“多个数据格的 API 合并什么也不做”。worker 以 `SAL_LOK_OPTIONS=sc_print_twips_msgs`(macOS 另加 `unipoll`)运行,Calc 的光标、选区与 `.uno:SheetGeometryData` 同为文档 twips;视图把可见区经 `setClientVisibleArea` 报给内核。`0013-lok-author-option.patch`:`lo_setOption("author", 名)` 设内核用户全名,新批注与修订以此署名。`0014-lok-calc-formula-entry-and-names.patch`:公式语法错误不弹询问、补全不切走编辑、提交清引用标记、名称的可撤销定义删除与列表判定、自动计算状态、xlsx/xls 的手动计算往返。`0015-aqua-no-wait-with-a-due-timer.patch`:Aqua 在直接超时待处理时不阻塞等原生事件(请求块里起的 0 毫秒定时器原会让调度器停到下一个请求)。`0005` 另加存活标记:发送消息的客户端关掉对话框后不再读已释放成员。worker 记下每个文档载入时的内核视图,每次请求先切到该视图(Calc 按当前视图读写,多工作簿时否则会错表)。切表经视图的有序输入队列。视图记录跳转所需的最远点,滚动与图块以内核文档尺寸和它的较大者为界(Calc 空白区随可见区扩展)。视图按内核报的冻结行列(`.uno:FreezePanesColumn/Row`)分格:冻结部分不随滚动,其余照滚,图块按格裁剪,命中与表头同一换算(`view/panes.rs`)。文档占用 Tab 与 Shift-Tab(在 LokView 键位上下文里优先于焦点切换):Writer 插制表符或跳表格,Calc 跳单元格。worker 崩溃时打印本机栈(`worker/fatal.rs`),客户端报出退出信号。官方 macOS 包的 `paintTile` 不出图,上游 master 的修复也不够。Skia 必须开。工作进程在主线程以 unipoll 模式运行,请求经主 GCD 队列派发,环境设 `SAL_FORCE_HIDPI_SCALING=1` 与 `SAL_SKIA=raster`。证据见 `docs/engineering-risks.md` R-01。 @@ -202,8 +203,8 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-01:MailCore 2 的子模块 libetpan 过旧,改钉 libetpan master `4d47862`。 - 2026-10-01:每个应用的全部数据在 `<本机数据目录>/ElyOffice//`,路径由 `ely_platform::data_dir` 给出。卸载只动这里,且先问。用户文档永不碰。 - 2026-10-04(用户定):macOS 包标识前缀 `ely.zacharyzhang.office`(`packaging/macos/bundle.sh`);发布者 ZacharyZhang,网址 zacharyzhang.com(macOS `NSHumanReadableCopyright`,Windows 卸载项 `Publisher` 与 `URLInfoAbout`;Linux 桌面文件无此字段)。界面语言英文与简体中文,以后再加。拼写词典只随英文:LibreOffice 的词典库没有中文(中文不用 Hunspell 拼写)。内核界面语言固定英文,函数名照英文;ElyTable 把内核英文的选区统计(Sum、Average 等七个固定名)换成界面语言,数值照内核。批注与修订的作者取各用户的账户全名(无全名用登录名,与内核自身次序一致),由补丁 0013 的 `setOption("author")` 在 worker 启动时设定;作者设置页随设置任务接入。邮件合并字段写法 `«列名»` 由我定(用户交我决定)。 -- 2026-10-01:更新清单是 JSON:`{"version", "assets": {"-": {"url", "sha256"}}}`,只走 https(本机回环除外)。检查、下载、校验在 `ely_platform::update`,从不静默安装。包管理器安装的 Linux 版本不自更新。清单地址由设置给出,尚未配置。 -- 2026-10-05(用户定):ElyAgent 的后端与内置模型的登录配置以 Kigi CLI(https://github.com/ZacharyZhang-NY/Kigi-CLI,Rust)为基础,以 Rust 依赖直接嵌入,不用 ACP;沿用其提供商登录(订阅账号或 API 密钥)与模型配置。 +- 2026-10-01:更新清单是 JSON:`{"version", "assets": {"-": {"url", "sha256"}}}`,只走 https(本机回环除外)。检查、下载、校验在 `ely_platform::update`,从不静默安装。包管理器安装的 Linux 版本不自更新。2026-10-09 起(用户定:0.1.2 加自动更新):每个应用一份清单,`.json`,随发布上传,应用经 git.zacharyzhang.com 的 API 读最新发布(`api/v1/repos/ZacharyZhang-NY/ElyOffice/releases/latest`),在其文件里找 `.json`(`ely_platform::release::asset_url`;Gitea 没有 `releases/latest/download` 路径;`ELY_UPDATE_MANIFEST` 直接给清单地址,测试用);只在从 `.app` 运行时可用(开发构建没有);照 PRD §4.2 自动检查默认关闭:设置“通用”的“启动时检查更新”(通用设置 `check_updates`)打开后启动时查一次、查不到只记日志,应用菜单的“检查更新…”随时手动查(已是最新或查不到都以提示写明);有新版即在窗口上方显示组件库的 `UpdateBanner`(文案进内建中英目录,组件库 5d6efd4):横幅在标题栏下方(`Shell` 的页眉里,`Updates` 自己是一个视图);下载(进度)、校验散列、“重新启动以更新”只走正常的退出流程(有未保存的照常询问;取消即什么也不装,按钮仍在);应用真正退出时(`on_app_quit`)以本程序的安装模式(`--ely-install-update dmg 包 进程号`,`ely_ui::run` 最先识别)起一个独立进程:等本进程结束,`ely_platform::install` 挂载 dmg、把同名 .app 拷到旁边再换掉原包(换上前失败即放回原包),无论成败都 `open` 该包;失败的原因写在数据目录 `updates/failed.txt`,重开的应用以提示写明。下载完成只归属于它下载的那个版本;下载中或已下载时再查不覆盖。`packaging/macos/release.sh` 为每个应用写出清单(版本、本机架构的 dmg 地址与 SHA-256),dmg 里另有指向“应用程序”的替身,可直接拖入。新包换上即为装好,旧副本删不掉只记警告。`tests/scripts/update.sh`:装好的 ElyMark 在默认设置下启动不发任何请求;按“检查更新…”后从本机服务的 9.9.9 下载;有未保存的文字时“重新启动以更新”先问,取消则原包不动,“不保存”后装上新版并重新打开(新版本身的进程在跑)。 +- 2026-10-05(用户定):ElyAgent 的后端与内置模型的登录配置以 Kigi CLI(https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI,Rust)为基础,以 Rust 依赖直接嵌入,不用 ACP;沿用其提供商登录(订阅账号或 API 密钥)与模型配置。 - 2026-10-05(用户定):八个应用都不许卡顿:键入、选择、滚动、文档渲染都要即时(GPUI 的 120 FPS 手感),树莓派 3 上也要流畅。输入延迟与帧时间是验收项,要实测;界面线程不等内核、不持 worker 锁做同步请求,空闲不做事。 - 2026-10-05:LOK 的输入与事件路径(实测后定)。原样:视图的事件监听长轮询 worker(持 worker 锁最多 50 毫秒,worker 读线程也随之阻塞最多 250 毫秒),按键排在锁后,键入锁等待中位 290 毫秒、最长 9 秒;输入队列在界面执行器上逐条跳回界面线程,每键约一帧,连续键入积压到 1 至 2 秒。现在:worker 有新事件即主动推送(`tag::EVENTS`,推送线程在输出锁下取批,批次即发送时状态),客户端读线程把回复与事件分开,事件存入 `client::Feed`,视图以异步方式等它(`Feed::next`,有新批次时唤醒,不占线程、不碰 worker 锁;原先每个打开的文档阻塞一个后台线程最多一秒,文档多于核数时会饿死输入与图块;监听任务归视图所有,视图释放即停);每个视图一条后台通道(`view/lane.rs`),输入优先、图块其次,连续执行,界面线程只收落地结果;文档尺寸与页框只在内核报尺寸变化时在后台读;批次弄脏的已显示图块即刻重绘,不等下一帧;视图的 `Reported` 事件只在内核回报或输入落地时发出,滚动与图块到达不触发应用的观察钩子;编辑与光标移动后应用要读的内核列表(ElyDoc 导航、字数、审阅,ElyTable 工作表与几何、单元格规则、格式面板)经 `ely_lok::read_off` 在后台读,一次一个,结果按发起者核对。实测(macOS,`tests/scripts/lag.sh`):按打字速度键入时输入落地 0 至 1 毫秒,图块 1 至 3 毫秒,按键到新图块 ElyDoc 中位 19 毫秒、ElyTable 3 毫秒;连续快速键入(脚本一次送出近百字)时,各次运行在 3 至 225 毫秒的中位之间摆动:新文档首次键入时内核有一次 150 至 230 毫秒的冷启动(首块图块与拼写等初始化),同一批字排在它之后;原为中位 1 秒、p95 1.9 秒。树莓派 3 未实测(本机无设备)。界面线程不碰 worker:应用对内核的读取、保存与另存为的导出、导出 PDF、比较、邮件合并都经 `Tabs::read_in`(或 `ely_lok::read_off`)在后台执行,回到窗口时按发起的标签与读取时的状态核对;保存导出期间标签状态为“正在保存”,同一标签的后续保存排队到它结束;另存为在写入前按文件身份再查一次目标是否已被别的标签持有;导出期间又有编辑时,“保存后关闭”不关闭,回到关闭询问;关闭标签时的撤销历史也在后台读;邮件合并预览与比较在发起时就保留自己的标签号与工作目录;读取失败不立即重试,等下一次状态变化;载入时一并在后台读版面与撤销历史(`ely_lok::layout`,`LokView::open` 接收版面)。窗口关闭回调先不放行,在后台逐个读标签的撤销历史并关闭(有改动的照常询问),最后一个标签关闭后移除窗口;内核文档的关闭也在后台(2026-10-06 起,原先同步读历史、在界面线程持 worker 锁关闭)。 - 2026-10-04(用户定):八个应用的内容区一律随系统深浅色:Doc 页面、Table 网格、Show 幻灯片、PDF 页面、邮件正文、Mark 编辑区、Agent 输出。自动颜色随之翻转,文件里写明的颜色照原样;打印与导出 PDF 仍为浅色。各引擎(LOK、MuPDF、CEF)接入应用主题,不留引擎默认色。LOK:`ely.xcd` 定义 `COLOR_SCHEME_ELY_DARK` 与 `COLOR_SCHEME_ELY_LIGHT`(文档底色、自动文字色、网格、链接等取 Ely 默认色板;内核自带的深色方案颜色留空、按应用外观取默认值,传方案名不改外观,所以不用它),`LokView` 在主题深浅变化时经有序队列发 `.uno:ChangeTheme`(不算编辑),页面底色深色取 `surface`、浅色取 `paper`;Omarchy 色板与这两套固定色可能略有差别。导出 PDF 实测仍为白底。图块作废时旧图仍显示,新图到达后替换,编辑与主题切换都不闪。 @@ -276,3 +277,4 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-09:退出(缺陷清单 X-01)。Cmd+Q 与应用菜单的“退出”由应用级动作接收:主窗口的宿主在 `Closing::own_window` 里登记自己的退出流程(`ely_ui::commands::route_quit`),任何窗口(含设置窗口)发出的退出都经它逐个关闭标签、询问未保存的;宿主的窗口已不在时才直接退出;没有宿主的应用(ElyTree)直接退出。`Host::quitting` 在退出开始时运行(ElyMark 先记下打开的标签)。原先只有主窗口根上截退出,设置窗口在前时 Cmd+Q 不问即退,并把这次运行记为干净结束、删掉恢复点。 - 2026-10-09:作者名与读不出的设置(缺陷清单 X-02)。签名用的名字取启动时读入的通用设置(`ely_ui::settings::current`;文件读不出时为默认值,设置窗口另以 Banner 写明),`ely_platform::user::named(作者名)` 为空即用账户名;不再在引擎启动时重读文件(原先 `settings.json` 读不出时 Doc、Table、Show 以致命错误退出)。LOK worker 记下设定的作者名,引擎重启照用它。`tests/scripts/bad-settings.sh` 核对读不出的设置下 ElyDoc 照样启动、文件不被覆盖。 - 2026-10-09:每个应用只跑一份(缺陷清单 X-03)。`ely_ui::run` 在写日志之前取应用数据目录的 `instance.lock`(`ely_platform::instance::hold`;Unix 为 fcntl 记录锁,进程结束即放,被拒时以 `F_GETLK` 向系统问出持锁的进程号,不另存进程号文件,同时启动的几份也报得准;Windows 为 LockFileEx,不报进程号);已有一份在跑时第二份不启动,报“已在运行(进程号)”。原先第二份启动即清空第一份的工作目录、把它的恢复点当作干净结束删掉、改写崩溃锁。macOS 经访达打开文件本就交给运行中的那份;`open -n` 与 Linux 每文件一个进程时第二份被拒,文件须在已开的窗口里打开(未做转交)。`tests/scripts/one-instance.sh` 核对。 +- 2026-10-09(用户定):代码与发布从 GitHub 搬到自建的 Gitea(git.zacharyzhang.com;GitHub 账号被封,推送与发布都被拒)。公开仓库 `ZacharyZhang-NY/ElyOffice`(原样推上 main、缺陷清单分支与 v0.1.0、v0.1.1 标签),组件库为同站的 `ZacharyZhang-NY/Ely-GPUI-Components`(Cargo 的 git 依赖与 `fetch-references.sh` 随之改址,钉的提交不变)。v0.1.1 的六个 dmg 与两个源码包重新发在 Gitea 的 v0.1.1 发布里。官网的下载与源码链接指向 Gitea(`releases/latest` 会跳到最新发布页)。`.github/workflows` 删去(它们靠 GitHub 的 macOS 机器与 `gh`,发布改在本机以 `packaging/macos/release.sh` 构建、经 Gitea API 上传)。发布视频里写的地址已在源文件改为 Gitea,已发布的成片仍是旧地址,重渲染后才更新。上游项目(LibreOffice、MuPDF、git-lfs、tessdata 等)照旧从它们自己的 GitHub 地址取。 diff --git a/scripts/fetch-references.sh b/scripts/fetch-references.sh index 68480a7..fd47e1f 100755 --- a/scripts/fetch-references.sh +++ b/scripts/fetch-references.sh @@ -33,7 +33,7 @@ fetch() { # name url rev [sparse paths...] echo "fetch $name $rev" } -fetch Ely-GPUI-Components https://github.com/ZacharyZhang-NY/Ely-GPUI-Components.git f834f55c16b38d86fbc243b2d7719667503f4b01 +fetch Ely-GPUI-Components https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components.git 5d6efd46ec0c93b381ec7578561a1273c366025b fetch zed https://github.com/zed-industries/zed.git 1a28cff4b409169bac058bca40dfbfeb7621d19b fetch libreoffice-core https://github.com/LibreOffice/core.git 8221e31b3ac356a1623c672912a3d2b492f7e3d1 \ include/LibreOfficeKit libreofficekit desktop/source/lib desktop/inc \ diff --git a/site/e2e/text.spec.ts b/site/e2e/text.spec.ts index cdb11ee..17cd21a 100644 --- a/site/e2e/text.spec.ts +++ b/site/e2e/text.spec.ts @@ -1,7 +1,7 @@ import { expect, test, type Page } from "@playwright/test"; import { TEXT, type Key, type Lang } from "../src/text.ts"; -const REPO = "https://github.com/ZacharyZhang-NY/ElyOffice"; +const REPO = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice"; const APPS = ["ElyDoc", "ElyTable", "ElyShow", "ElyPDF", "ElyTree", "ElyMark"]; const RELEASES = `${REPO}/releases/latest`; @@ -78,13 +78,13 @@ test.describe("English locale", () => { await expect(lang).toHaveText("中文"); }); - test("downloads go to the GitHub release page, never to a file", async ({ page }) => { + test("downloads go to the release page, never to a file", async ({ page }) => { await page.goto("/"); await expect(page.locator(".tour .get")).toHaveCount(APPS.length); for (const i of APPS.keys()) await expect(page.locator(".tour .get").nth(i)).toHaveAttribute("href", RELEASES); await expect(page.locator("#download a")).toHaveCount(1); - await expect(page.locator("#download [data-t=github]")).toHaveAttribute("href", RELEASES); - await expect(page.locator(".hero > a")).toHaveText("GitHub"); + await expect(page.locator("#download [data-t=get]")).toHaveAttribute("href", RELEASES); + await expect(page.locator(".hero > a")).toHaveText("Source"); await expect(page.locator(".hero > a")).toHaveAttribute("href", REPO); const files = await page.locator("a[href]").evaluateAll((as) => as.map((a) => (a as HTMLAnchorElement).href).filter((h) => /\.(dmg|tar\.gz|zip|exe|AppImage)$/.test(h)), diff --git a/site/src/main.ts b/site/src/main.ts index fa63d4f..b02dd87 100644 --- a/site/src/main.ts +++ b/site/src/main.ts @@ -10,7 +10,7 @@ import { film } from "./film.ts"; import { said, speak, type Lang } from "./text.ts"; import { RELEASES, VERSION } from "./release.ts"; -const REPO = "https://github.com/ZacharyZhang-NY/ElyOffice"; +const REPO = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice"; const app = document.querySelector("#app"); if (!app) throw new Error("index.html has no #app"); @@ -18,10 +18,10 @@ if (!app) throw new Error("index.html has no #app"); const hero = document.createElement("header"); const title = document.createElement("h1"); title.textContent = "Ely Office"; -const github = document.createElement("a"); -github.href = REPO; -github.textContent = "GitHub"; -hero.append(title, said("p", "tagline"), said("p", "platforms"), github); +const source = document.createElement("a"); +source.href = REPO; +source.textContent = "Source"; +hero.append(title, said("p", "tagline"), said("p", "platforms"), source); const { section, host, svg } = tour(hero); rhythm(host, svg); @@ -31,7 +31,7 @@ const footer = document.createElement("footer"); footer.id = "download"; const version = document.createElement("h2"); version.textContent = `Ely Office ${VERSION}`; -const get = said("a", "github"); +const get = said("a", "get"); get.href = RELEASES; footer.append(version, said("p", "platforms"), said("p", "needs"), said("p", "unsigned"), get); diff --git a/site/src/release.ts b/site/src/release.ts index f5cf940..11f1573 100644 --- a/site/src/release.ts +++ b/site/src/release.ts @@ -1,3 +1,3 @@ // The published release; downloads live on its GitHub page. export const VERSION = "0.1.1"; -export const RELEASES = "https://github.com/ZacharyZhang-NY/ElyOffice/releases/latest"; +export const RELEASES = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice/releases/latest"; diff --git a/site/src/text.ts b/site/src/text.ts index cfa11dd..3635254 100644 --- a/site/src/text.ts +++ b/site/src/text.ts @@ -16,7 +16,7 @@ const en = { platforms: "Out now for macOS. Windows and Linux are coming soon.", needs: "macOS 14 or later, Apple silicon.", unsigned: "Not notarized. If macOS blocks the app, open System Settings › Privacy & Security and click Open Anyway.", - github: "Download from GitHub", + get: "Download", other: "中文", roads: "Drag a file down the road.", fileDoc: "ElyDoc file", @@ -52,7 +52,7 @@ const zh: typeof en = { platforms: "macOS 版已发布。Windows 与 Linux 版即将推出。", needs: "macOS 14 或更新,Apple 芯片。", unsigned: "未经公证。macOS 拦下应用时,打开“系统设置 › 隐私与安全性”,点“仍要打开”。", - github: "前往 GitHub 下载", + get: "前往下载", other: "English", roads: "把文件沿着路拖过去。", fileDoc: "ElyDoc 文件", diff --git a/site/video/scenes/index.html b/site/video/scenes/index.html index 192b54a..04b4c6a 100644 --- a/site/video/scenes/index.html +++ b/site/video/scenes/index.html @@ -71,7 +71,7 @@

Ely Office

Ely Office 0.1.0

Out now for macOS · Windows and Linux soon macOS 现已推出 · Windows 与 Linux 即将推出

-

github.com/ZacharyZhang-NY/ElyOffice/releases

+

git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice/releases

Works with the network off.

断网照常工作。

Open source, AGPL.

开源,AGPL 许可。

Your files stay in your folders.

文件留在你自己的文件夹里。

diff --git a/site/video/type/scenes.js b/site/video/type/scenes.js index d9ffc74..4c4681c 100644 --- a/site/video/type/scenes.js +++ b/site/video/type/scenes.js @@ -163,7 +163,7 @@ function end(ctx, t) { const line = { x: left, align: "left", a }; text(ctx, { ...line, s: "macOS now · Windows and Linux soon", y, size: 34, color: "#c4c2c0" }); text(ctx, { ...line, s: "macOS 现已推出 · Windows 与 Linux 即将推出", y: y + 46, size: 28, color: "#acaaa8" }); - const url = "github.com/ZacharyZhang-NY/ElyOffice"; + const url = "git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice"; text(ctx, { ...line, s: url, y: y + 122, size: 30, color: "#f5f5f7", a: fade(t0 + BAR), weight: 400 }); }