| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(linux): **随包中文字体**落地 —— 取字体脚本 + 打包映射 + 打包后布局的端到端读数 P4 的 Linux 缺口最后一块:那份预编译 libpdfium.so **没有字体后端**(ldd 无 fontconfig、FcInit 0 个) ⇒ **非嵌入字体**的中文 PDF(国标 STSong-Light+UniGB-UCS2-H,中文办公软件常见写法)在 Linux 上 **整行不显示**,而 Windows/macOS 有系统字体映射、看不见这个问题。引擎侧治法(随包字体 provider) 已在 dev;这次把**字体本身**补上。 ## 1. scripts/fetch-font.mjs(钉子版本 + 核哈希 + 字体本体不入库) 与 fetch-pdfium.mjs 同一套纪律。走 npm(@expo-google-fonts/noto-sans-sc@0.4.3 = Google Fonts 官方打包) 而不是写死某个镜像地址 ⇒ 各人/CI 自己的 registry 都能用。 钉死:NotoSansSC_400Regular.ttf **10,559,284 字节**,sha256 **d45f67f0a7c0ca3f…7d16**,OFL-1.1(LICENSE-OFL.txt 一起取)。 ## 2. 打包映射:tauri.linux.conf.json 加 "assets/fonts/*": "./" ⚠️ 这一条有两个**实测**坑,都写进注释与 assets/fonts/README.md 了: - **glob 必须至少匹配到一个文件**,否则构建期直接红:移走整个目录后 cargo check 报 glob pattern assets/fonts/* path not found or didn't match any files.(exit 101)。 - 所以**占位 README.md 要入库**、字体本体 .gitignore:**没取字体的机器照样能编译**(实测:只剩 README 时 cargo check 绿)。 ## 3. ★ 端到端读数(用**打包后的布局**跑,不是开发目录) `` cargo tauri build --bundles deb ⇒ ShuyoNote_1.91.10_amd64.deb 42,865,680 字节 dpkg-deb -x ⇒ /usr/lib/ShuyoNote/{libpdfium.so, NotoSansSC-Regular.ttf, LICENSE-OFL.txt, README.md} SHUYONOTE_PDFIUM_DIR=<那份 usr/lib/ShuyoNote> cargo test pdf_engine_compare [pdf] 随包字体就位(NotoSansSC-Regular.ttf) [pdf] 随包字体**首次被 PDFium 问到**(请求名 STSong-Light)⇒ 它真的在用这份字体 cjk.pdf PDFium 墨迹 29084(非矩形墨迹 P2084 ⇒ 文字画出来了;**没字体时是 27000**) 随包字体:被问 4 次、答 1 次 7 passed / 0 failed ` ⇒ 取字体 → 映射 → 随包 → **在包里那一层被 provider 找到** → 中文画出来,整条链有读数。 ## 4. 顺带两件 - release.yml 的 Linux 档加一步 node scripts/fetch-font.mjs(与取 pdfium 并列;if: ubuntu-24.04); - bundled_font_stats 加 #[cfg(test)]:生产构建里没有调用点,打 Linux 包时报 function bundled_font_stats is never used(生产侧的"见证"是首次作答那行 eprintln!)。 ⚠️ 仍未做:**AppImage** 里同一条映射没验(只构建了 deb);**Android** 是否也该随包这份字体 (它的 provider 找的是"动态库同目录",而安卓那边是 jniLibs`,.ttf 未必会被 Gradle 打进包)——另议。 | 14 天前 | |
fix(tauri): 桌面端 AI 调用被权限系统整体拒掉 —— http 插件补作用域(缺陷 #9 根因) 用户报「PDF 阅读器 AI 识别出错」。顺着他给的模型名( deepseek-v4-flash-vision-exp)在本机取到 应用的真实配置(provider=openai / baseUrl=https://api.deepseek.com),然后**直接复现应用的请求形状**: - GET /v1/models(同一把 key)→ 200(这个 key 认 deepseek-flash / deepseek-v4-pro); - POST /v1/chat/completions 带 1×1 小图 → 200(那名字是**别名回落**,响应里是 deepseek-flash,不是 404); - 同一请求带 **4 MB 截图(请求体 5.3 MB)** → 200、6.2 秒,还把截图里的文字读出来了。 ⇒ 端点 / key / 模型名 / 大图载荷 / 超时**全都没问题**。真因在桌面壳的权限: src-tauri/capabilities/default.json 里只写了字符串 "http:default",而 tauri-plugin-http 的 permissions/default.toml 原文是 *"enables all fetch operations but **does not allow explicitly any origins to be fetched**. This needs to be manually configured before usage."* ⇒ **作用域为空 = 一个源 都不许发**(失败关闭)。桌面端所有走 coreFetch(@tauri-apps/plugin-http 那条 native 路)的跨域 AI 调用 —— 视觉识别 / 对话 / 摘要 / 嵌入 —— 一律被拒;Web 版走浏览器 fetch 不受影响 ⇒ 表现成"只有桌面端 AI 不好使",而且只冒一句笼统的「AI 视觉识别失败」。 改动: - capabilities/default.json:给 http:default 显式作用域 https://** + http://**。 为什么全放行而不是白名单:服务商地址是**用户自己填的**(官方 HTTPS 端点,或局域网 / 回环上的 自建模型服务走 http),固定白名单会让"填自己的地址"这条承诺作废。 - 新增判据 capability_scope_tests::http_plugin_scope_allows_user_configured_endpoints: http 插件被授权就必须带 allow scope、且覆盖 https 与 http。**运行时读文件**(不是 include_str!), 这样改了 capability 不重编也测得出来。**变异验证**:把 scope 去掉 ⇒ 立刻红在 「http 插件被授予了权限、却没给任何 allow scope」。 - CHANGELOG.md 的 [Unreleased] 记本条,并写明边界:**判据只证明配置形状**+构建期 schema 校验, "打包后的桌面端真能发出去"仍需真机复验。 判据:cargo test(本机注入 v6 清单后) capability_scope_tests::http_plugin_scope_allows_user_configured_endpoints ... ok。 (cherry picked from commit 03b1e93cca9a0d2d3284382a5573db240ee261c0) | 15 天前 | |
fix(android): 图标里的书缩小到 76%(并拆成"背景层 + 前景层") owner 2026-09-21:「安卓的应用图标中间的书本太大了,小一点」。 **根因不是"书画大了",是层次放错**:原来那份产物是**整枚图标(蓝底+书)当前景**, 而 Android 8 起的自适应图标会被启动器**按它自己的形状裁切**(圆形/圆角方/水滴), 只有中间约 66–72% 是安全区 ⇒ 书跟着蓝底一起顶满,裁完显得更大,竖直方向几乎贴边。 现场读数(前景内容包围盒 / 画布):**53.9% 宽、45.7% 高** ⇒ 可见区内约 **77%**。 改法(按 Android 的规矩重排层次,并把"书多大"变成一个可复现的旋钮): - **背景满幅**: design/logo/android-background.svg(蓝色渐变)→ manifest 的 android_bg; - **前景只放书**:design/logo/android-foreground.svg(两页 + 火花,透明底)→ android_fg; - **旧式图标同尺寸**:design/logo/android-legacy.svg(蓝底 + 同样 76% 的书)→ default; - design/logo/android-icon.json 一份 manifest 把三层喂给 tauri icon。 **读数**(改前 → 改后):前景内容占画布 **53.9% → 41.0%**、可见区内约 **77% → 55%**, 四周留白从约 5% 变成约 30%。scale(0.76) 就是唯一旋钮。 **顺带把"改图标"从手跑命令变成可复现的两步**(以前没有任何入口,所以没人敢动): node scripts/build-android-icons.mjs(生成 src-tauri/icons/android/**,先清空再写,21 个文件; 旧版那个没人引用的 values/ic_launcher_background.xml(#fff)随之删掉) → node scripts/android-app-icon.mjs(铺进 gen/)。源与做法写进 design/logo/README.md, 并放进两张"启动器实际会显示的样子"对照图(docs/media/android-icon/)。 判据:新 scripts/android-icon-art.test.mjs **5 条**(书的大小必须落在 0.6–0.8、旧式图标与自适应 前景同尺寸、缩放后两页仍在 66% 安全区内且内容 ≤ 画布 43%、背景层只有底/前景层只有书、 自适应 XML 同时引用背景图与前景图且不再引用旧的 @color)。 **踩到一个假判据并修掉**:第一版 scaleOf 用 scale\(...\) 裸匹配,先命中了文件头注释里那句解释用的 scale(.76) ⇒ 把真 transform 改成 1.0(顶满)判据**照样绿**;改成锚 <g transform="…"> 后, 变异(scale → 1.0)当场 **2 条红**,恢复后 5/5 绿。 读数:scripts/android-icon-art.test.mjs 5/5 · scripts/android-app-icon.test.mjs 8/8 · check-doc-links ✓(120 个 .md / 671 条链接)。 | 13 天前 | |
fix(installer): 默认安装目录改到 %LOCALAPPDATA%\Programs\ShuyoNote(fork 上游 NSIS 模板,只改 1 行) owner 截图问「程序的安装地址不专业啊?」。查清了:截图里那条 C:\Users\<user>\_archive\shuyonote-install-test **不是产品默认** —— 模板的 RestorePreviousInstallLocation 从 HKCU\Software\shuyo\ShuyoNote 读回上一次安装位置 (那次测试的目录早删了),安装时又把它写回去,所以每次开安装向导都预填它。 但干净机器上的默认值 %LOCALAPPDATA%\ShuyoNote 也确实不像"装了个程序";Tauri 没有 自定义默认安装目录的配置项(只有 installMode,上游 tauri-apps/tauri#11015)⇒ 只能 fork 模板。 为什么不用 perMachine(那才给出 Program Files): - perMachine 的注册表根是 HKLM(SetShellVarContext all),而老用户的"上次装在哪"与卸载项都在 HKCU ⇒ 新安装器**看不见**旧的 per-user 安装,会把新版装到 Program Files、把旧的 AppData 那份 留在原地(两个同名卸载项、快捷方式仍指旧版);而 Tauri 更新完是拿 current_exe() 重启的 ⇒ 又回到旧路径那个 exe,旧版继续跑、继续提示更新。 - perMachine 是 RequestExecutionLevel admin:安装与**每次自动更新**都弹 UAC。 裁定:保持 currentUser(免 UAC、更新静默),只把**全新安装**的默认目录改成 …\Programs\…; 老用户因为那条记忆键仍然留在原路径,不受影响。 - src-tauri/nsis/installer.nsi:fork 自 tauri-bundler 2.9.4(头部记 upstream sha256 与 cli-version), 与上游逐字节相同,只改 $LOCALAPPDATA\${PRODUCTNAME} → $LOCALAPPDATA\Programs\${PRODUCTNAME} - tauri.conf.json:bundle.windows.nsis.template 指向它(相对 src-tauri/ —— CLI 打包前会 chdir 到那里) - scripts/check-nsis-template.mjs(+test):离线三条(文件在、那一行恰好 1 处、cli-version 与 package.json 一致)+ 联网逐行 diff 上游模板;CLI 升级会被这条门禁拦下 - scripts/verify-installer-default-dir.ps1:真机读"预填的安装目录"(跨进程 WM_GETTEXT)后取消, **绝不安装**;-Expect 可断言 - scripts/load-release-credentials.ps1:凭据文件换过格式(访问令牌 / github_pat_ 细粒度令牌)后, 旧的手写加载器会静默失败;这里两种令牌形状都认,且 -Verify 把发版时的 401 提前成两秒 - docs/RELEASING.md:新增该章节(为什么 fork、升级 Tauri 要重做、门禁、真机探针、 以及"本机看到旧路径 ≠ 产品默认错了"这条误判) - .gitignore:/target/(该门禁缓存上游模板用) 读数:pnpm tauri build --bundles nsis 走通(makensis 成功产出 1.91.10 安装包); 真机探针 DEFAULT_INSTALL_DIR=C:\Users\<user>\AppData\Local\Programs\ShuyoNote(PASS,未安装任何东西); check-nsis-template 通过(含与上游 978 行逐行比对);test-report 注册表自测 + 新门禁单测 23/23。 | 14 天前 | |
polish(copy): 打磨「设备直连 / 配对暗号」这一族的界面文案 owner:「优化文案」。只动界面上看得见的几句,代码注释不动。口径三条: ① 一句只说一件事;② 说清"填什么"而不是"机制是什么";③ 不用「对暗号」这种内部词。 改动(前 ⇒ 后): · 输入框提示: 「配对暗号(个人空间:两台设备填一样的字)」 ⇒ 「配对暗号:两台设备填得一模一样(例如:我的两台电脑)」 · 保存成功: 「配对暗号已保存 —— 另一台设备填同一个暗号,就能在同一个网络里互相找到」 ⇒ 「配对暗号已保存。到另一台设备上填「同一个」暗号,两台在同一个网络里就能直接连上,不经过服务器」 · 顶部路由说明:「(个人版不经过服务器)」⇒「(个人空间不经过服务器)」—— 去掉产品内部叫法 · 空间隐私说明:拆成两句,去掉绕口的长从句: 「只有团队空间能绑同步服务器;个人空间(含存量里没标过的老空间)一律按个人处理,只走「附近设备直连」,不经过服务器。」 ⇒ 「只有团队空间能绑同步服务器。个人空间不经过服务器,走「附近设备直连」:填一个配对暗号就行。」 · 后端报错:「这台设备还没填「配对暗号」——个人空间不需要服务器,两台设备填同一个暗号就能互连」 ⇒ 「还没填「配对暗号」。个人空间不走服务器:两台设备填同一个暗号,就能在同一个网络里直连」 读数:cargo check exit 0;tsc exit 0;pnpm verify 59 条全过。 | 15 小时前 | |
test(迁移): 老库夹具 + 通用迁移兜底判据 —— 第一次跑就抓到第 4 个同类 bug owner 2026-09-24 拍板:给"老库"上一道**通用**闸门。动机是连着三个 bug 都属同一类 ( meta.workspaces.kind 漏 ALTER、空间 schema 的 kind 列、convert_space_db 的 SELECT * 拷贝), 而**判据夹具一律是"刚 migrate 过的新库"** ⇒ 全绿也抓不到"只有老库才会中"的缺陷。 新增 - **老库夹具**(src-tauri/tests/legacy-meta.db / legacy-space.db,各 20 KB)+ 生成器 security::tests::gen_legacy_db_fixtures(#[ignore],与 gen_backend_fixture 同族)。 夹具**刻意取最早的列集**(meta 的 workspaces 4 列、空间库的 pages 停在 11 列)—— 比任何真实历史文件都老,判据要的就是"迁移必须把缺的列**一个不落**补上"。 - **通用兜底判据** legacy_databases_survive_the_real_migrations: ① 把两份夹具铺成真实 app 目录;② 走**真实入口** db::open_meta_conn_at / open_space_conn_at(跑完整迁移); ③ 与"全新库迁移后"**逐表逐列**对比:**新库有的列,老库迁移后必须都有**(任何"加列忘配 ALTER"当场红); ④ 再验功能面:老数据还在、space_kind 读得回/写得进、开-关加密转得动。 ★ **第一次跑就抓到第 4 个同类 bug**:meta_migrate 对 theme / icon / sort_order / deleted_at **也只在建表语句里写着、没有幂等 ALTER** ⇒ 老 meta.db 这四列永远补不上。 (判据报的是:meta.db 的表 workspaces 迁移后缺列 ["theme","icon","sort_order","deleted_at"]。) ⇒ 同批补上四条 ALTER(db.rs),并在注释里写明"**加列就要配一条幂等 ALTER**"。 当轮 tip 读数 - Rust 全量 **591 passed / 0 failed / 20 ignored**(win-cargo-test: test exe exit code = 0,308.0 s; ignored 19→20 就是新增的夹具生成器)。 - 夹具由**仓库约定的 Rust 生成器**重新生成(先用 sql.js 造出文件只为解开 include_bytes! 的编译依赖; 最终提交的字节来自 gen_legacy_db_fixtures)。 - npx tsc --noEmit 0;check-web-commands(Rust 255 / web 247 / 契约 257)/ check-doc-facts / check-doc-links(138 篇 / 861 条)/ check-doc-content-access(562 处)/ check-panel-layout(40/0) 全绿。 | 10 天前 | |
feat: ShuyoNote 本地优先类 Notion 笔记应用 基于 Tauri 2 + Lexical + SQLite 的本地优先笔记应用: - 富文本编辑 + 斜杠菜单块系统 + 页面树 + 自动保存 - FTS5 全文检索(中文 trigram) - Markdown 导入导出 - 多设备同步(outbox + LWW + 自建 Axum 同步服务端) | 1 个月前 | |
chore(release): Cargo.toml 版本号变了 —— Cargo.lock 跟着更新 | 14 小时前 | |
release(1.91.28): 发版 —— 个人空间的设备直连、预览与列表打磨、两处 view 修复 版本号五处同步(package.json / Cargo.toml / tauri.conf.json / README 徽章 / docs/README.md), CHANGELOG 把 [Unreleased] 收成 [1.91.28] 并补上本次条目。 ⚠️ 读代码/门禁得出的两条订正: · 版本号是**五处**不是六处 —— docs/README.md 里那句「当前 v1.91.x」也算一处(check-versions 抓到); · CHANGELOG 的小标题**每段只许一个** —— 我新建的「### 变更 / ### 修复」把同段切成两半, check-changelog 直接点出重复行号。 本版内容(详见 CHANGELOG): 新增:个人空间也能用附近设备直连(配对暗号);模板中心并入 view 体系; md/html/txt 预览;PDF 两侧栏记住开合与宽度(按窗口比例)。 变更:个人空间不显示服务器同步相关内容;文件列表行距与列宽;md 顶栏纯图标; 图标收进一处图标源;设备直连说明精简、按钮补 44px 高度。 修复:点文件夹打不开文件管理视图(leaveTemplates 覆盖 view);openPage 同形状一处; check-overlay-registry 的注释误判;改名统一成弹窗。 读数:check-versions / check-changelog / check-release-parity exit 0;pnpm verify 59 条全过。 | 14 小时前 | |
chore(清理): 死代码稽查一轮 —— 编译告警 11 + 7 → **0**,并把「收据」变成门禁 ## 这一轮做了什么 owner 让"清冗余代码"。先做最便宜、也最该先做的一件事:**把编译器的话当真** —— cargo check --lib 报了 11 条、cargo check --lib --tests 报了 7 条,逐条查完之后**两边都是 0**。 但查的过程里发现的不是"几个小毛病",而是**一整类没人管的东西**:#[allow(dead_code)] **不产生任何输出** ⇒ 它什么时候过期了、它挡住了什么,都不会有人看见。四个真现场: | 现场 | 真身 | 处置 | |---|---|---| | sync.rs::IncomingChange.seq 挂着豁免 | 它**被生产代码读了 8 处**(apply_pulled_changes 那一整段)⇒ 豁免早就过期 | 删豁免(**不是**删字段:字段是活的) | | commands.rs::mupdf_compiled() | body 就是 cfg!(feature);**唯一使用者**是一条 assert_eq!(cfg!(f), cfg!(f)) 的判据 —— 恒真、零覆盖 | 函数与那条空转断言一起删;"编没编"改由 ensure_mupdf_available() 的两半真验 | | security.rs 的夹具生成器 | 一次"文档与属性被留在上一个函数下面"事故 ⇒ 一个生成器**被 libtest 注册两遍**(跑两遍),另一个**彻底不可达** | 属性归位 + 新判据 the_manual_fixture_generators_keep_their_attributes_next_to_them 钉住 | | build.rs::find_gm_marker_deprecated | 实现早搬进 gm_patch_probe.rs(好让判据驱动它),**副本还留着**,靠无名无期的豁免挂着 | 删副本(搬走了还留一份,正是两侧漂移的经典形状) | 结构性的一处:gm_patch_probe.rs 原先挂着 8 处逐项豁免,而它**在产品二进制里根本不需要存在** (本 crate 里只有判据用它;build.rs 走的是 include!,那是**另一次编译**,与本行无关) ⇒ lib.rs 改成 #[cfg(test)] mod,8 处豁免一次删清,只留 1 条**跨编译边界**的结构性收据。 hlc.rs 的模块级豁免同理撤掉(丙-③-b 落地后,按文件头那张清单逐条核过):StampedRecord / winner / merge_record / projection / without_stamp / Hlc::counter / Hlc::device_id **只服务判据与仿真夹具** ⇒ 各自 #[cfg(test)]("产品里根本不存在"比"编进来了但没人用"诚实)。 其余无名无期的豁免(net.rs、pairing.rs、crypto.rs ×5、pdfium_native.rs ×2、plugins.rs) 一律**补上日期 + 删除条件**;sync.rs:530 那条则是直接删掉(它什么都没挡)。 ## ★ 稽查查出一处真缺口(不是清理顺手改的,要单独立片) **收侧没有 observe**:sync.rs::apply_pulled_changes 拿到远端戳之后只做了 verdict, **没把本机时钟推过它** ⇒ hlc.rs 文件头那条"因果一定在序里"在**对端时钟快**时不成立: 本机随后的一次编辑可能拿到**小于**刚收到那枚戳的新戳,于是"因果上更晚的改动"在 verdict 里 反而判给远端。Hlc::observe 因此今天**没有产品调用方** —— 它带着一条有日期的收据 (删除条件写在函数上方),**不是**把它 #[cfg(test)] 掉:那正好会把缺口藏起来。 修它要单独一片,且**先立判据**:造一个"时钟快一小时的对端",要求它**压不住**后续本地编辑。 ## 防复发:新门禁 check-dead-code-receipts(contract 组) 纪律只写在文档里会漂,所以把"收据"变成断言:每处 #[allow(dead_code)] 必须**三选一** —— ① 删掉那段死代码;② 只有判据/夹具在用 ⇒ 门进 #[cfg(test)];③ 确实要留 ⇒ 写一句 // ★ YYYY-MM-DD 收据:为什么留 + 什么时候删。 - **它不判**理由好不好、也不判代码该不该留(那要人读):只判"**有没有人会想起来它**"。 - 命中必须**在代码里**(复用 lib/rust-scan.mjs 的区域掩码):仓里有**十几处注释在讲这件事** ("删掉 lib.rs 里那行 #[allow(dead_code)]"),grep 式扫描会把它们全算成违规 —— 自测里有这一格("空输出与零命中是两件事"那一族)。 - 生成物(capabilities_gen.rs,豁免由生成器统一决定)显式列进 EXEMPT,门禁**每次都打印**它, 而不是假装没看见。 - 自测 scripts/check-dead-code-receipts.test.mjs **14 条**,含**三条变异实测**:抹掉真实文件 (hlc.rs)里的日期 ⇒ 那一条当场变红;"缩进过的文档注释"与"注释里的假命中"各有一条 —— 前者是我这次真踩到的假红(#[allow] 上面缩进 4 格的 /// 被判成代码)。 顺带:门禁条数 48 → **49**(docs/TESTING.md 的名字表与「机器事实」块、tests/baseline.json 的 gates.contract 与 note 同步更新)。 ## 读数 - **编译告警**:cargo check --lib **0** / cargo check --lib --tests **0**(此前 **11 / 7**); - **Rust 全量**:**699 passed / 0 failed / 20 ignored**(scripts/win-cargo-test.ps1); - **vitest**:**2367 passed / 12 skipped(0 failed)**(其中新门禁自带判据 **14** 条); - **tsc --noEmit**:**0**;**pnpm verify 默认组**:**32 条门禁全绿**(含新门禁与 check-doc-facts); - 判据计数**只增不减**:tests/baseline.json 的 gates.contract 加一条新门禁(它不按用例数计, 故**不动** counts 的 11 个下限)。 ## ⚠️ 仍然没做(与上一片相同,没有变化) 1. **真机两设备复验**(要人手):两台机器各自填监听地址、开面板点一次「立刻交换一轮」。 本机判据只能到「内核 + 编排 + 门槛 + 发现层口径」这一层(真环回已验,**跨机器**没验)。 2. 可选:把交换并进「同步」按钮或按周期自动跑(今天与甲档一样是手动,**不是缺陷**,是口径)。 ⚠️ 另一条**必须记住的口径**:网格只服务**当前空间那一条档案**(space_id 是它用来对暗号的东西) ⇒ 没有任何 sync_profiles 行的空间暂时用不上网格。 | 9 天前 | |
release(1.91.28): 发版 —— 个人空间的设备直连、预览与列表打磨、两处 view 修复 版本号五处同步(package.json / Cargo.toml / tauri.conf.json / README 徽章 / docs/README.md), CHANGELOG 把 [Unreleased] 收成 [1.91.28] 并补上本次条目。 ⚠️ 读代码/门禁得出的两条订正: · 版本号是**五处**不是六处 —— docs/README.md 里那句「当前 v1.91.x」也算一处(check-versions 抓到); · CHANGELOG 的小标题**每段只许一个** —— 我新建的「### 变更 / ### 修复」把同段切成两半, check-changelog 直接点出重复行号。 本版内容(详见 CHANGELOG): 新增:个人空间也能用附近设备直连(配对暗号);模板中心并入 view 体系; md/html/txt 预览;PDF 两侧栏记住开合与宽度(按窗口比例)。 变更:个人空间不显示服务器同步相关内容;文件列表行距与列宽;md 顶栏纯图标; 图标收进一处图标源;设备直连说明精简、按钮补 44px 高度。 修复:点文件夹打不开文件管理视图(leaveTemplates 覆盖 view);openPage 同形状一处; check-overlay-registry 的注释误判;改名统一成弹窗。 读数:check-versions / check-changelog / check-release-parity exit 0;pnpm verify 59 条全过。 | 14 小时前 | |
feat(linux): **随包中文字体**落地 —— 取字体脚本 + 打包映射 + 打包后布局的端到端读数 P4 的 Linux 缺口最后一块:那份预编译 libpdfium.so **没有字体后端**(ldd 无 fontconfig、FcInit 0 个) ⇒ **非嵌入字体**的中文 PDF(国标 STSong-Light+UniGB-UCS2-H,中文办公软件常见写法)在 Linux 上 **整行不显示**,而 Windows/macOS 有系统字体映射、看不见这个问题。引擎侧治法(随包字体 provider) 已在 dev;这次把**字体本身**补上。 ## 1. scripts/fetch-font.mjs(钉子版本 + 核哈希 + 字体本体不入库) 与 fetch-pdfium.mjs 同一套纪律。走 npm(@expo-google-fonts/noto-sans-sc@0.4.3 = Google Fonts 官方打包) 而不是写死某个镜像地址 ⇒ 各人/CI 自己的 registry 都能用。 钉死:NotoSansSC_400Regular.ttf **10,559,284 字节**,sha256 **d45f67f0a7c0ca3f…7d16**,OFL-1.1(LICENSE-OFL.txt 一起取)。 ## 2. 打包映射:tauri.linux.conf.json 加 "assets/fonts/*": "./" ⚠️ 这一条有两个**实测**坑,都写进注释与 assets/fonts/README.md 了: - **glob 必须至少匹配到一个文件**,否则构建期直接红:移走整个目录后 cargo check 报 glob pattern assets/fonts/* path not found or didn't match any files.(exit 101)。 - 所以**占位 README.md 要入库**、字体本体 .gitignore:**没取字体的机器照样能编译**(实测:只剩 README 时 cargo check 绿)。 ## 3. ★ 端到端读数(用**打包后的布局**跑,不是开发目录) `` cargo tauri build --bundles deb ⇒ ShuyoNote_1.91.10_amd64.deb 42,865,680 字节 dpkg-deb -x ⇒ /usr/lib/ShuyoNote/{libpdfium.so, NotoSansSC-Regular.ttf, LICENSE-OFL.txt, README.md} SHUYONOTE_PDFIUM_DIR=<那份 usr/lib/ShuyoNote> cargo test pdf_engine_compare [pdf] 随包字体就位(NotoSansSC-Regular.ttf) [pdf] 随包字体**首次被 PDFium 问到**(请求名 STSong-Light)⇒ 它真的在用这份字体 cjk.pdf PDFium 墨迹 29084(非矩形墨迹 P2084 ⇒ 文字画出来了;**没字体时是 27000**) 随包字体:被问 4 次、答 1 次 7 passed / 0 failed ` ⇒ 取字体 → 映射 → 随包 → **在包里那一层被 provider 找到** → 中文画出来,整条链有读数。 ## 4. 顺带两件 - release.yml 的 Linux 档加一步 node scripts/fetch-font.mjs(与取 pdfium 并列;if: ubuntu-24.04); - bundled_font_stats 加 #[cfg(test)]:生产构建里没有调用点,打 Linux 包时报 function bundled_font_stats is never used(生产侧的"见证"是首次作答那行 eprintln!)。 ⚠️ 仍未做:**AppImage** 里同一条映射没验(只构建了 deb);**Android** 是否也该随包这份字体 (它的 provider 找的是"动态库同目录",而安卓那边是 jniLibs`,.ttf 未必会被 Gradle 打进包)——另议。 | 14 天前 | |
fix(packaging): 修正 tauri.macos.conf.json 的映射方向(上一条提交方向写反了,打包会红) 上一条(2a4d9e8a)我按"键=源、值=目标"写了 bundle.macOS.files,**方向是反的**。真实语义是 **键 = 包内目标(相对 Contents)、值 = 源文件(相对 config 所在目录)**。这次是本机真打了一次包 才露出来(打包阶段直接失败,报错把方向点得很清楚): `` Bundling ShuyoNote.app failed to bundle project: Failed to copy "Frameworks/libpdfium.dylib" to "vendor/pdfium/mac-univ/lib/libpdfium.dylib". "Frameworks/libpdfium.dylib" does not exist. ` ("copy X to Y" 里 X 是**源** ⇒ 说明它取的是**值**当源、键当目标。) ## 本机真产物读数(macOS,dev 2a4d9e8a + 本提交) ` 构建:node <runner> build --bundles app,dmg --config <无 updater 的覆盖> → target/release/bundle/macos/ShuyoNote.app → target/release/bundle/dmg/ShuyoNote_1.91.3_aarch64.dmg check:macos-bundle → ✅ 通过(identifier / 版本 / 深链 scheme / dmg / **PDFium** 五项全过) PDFium:Contents/Frameworks/libpdfium.dylib(3858ed6a6e78…) · vendor 源:同哈希 ① 包内那份库**真的能用**:SHUYONOTE_PDFIUM_DIR=<.app>/Contents/Frameworks cargo test pdf_engine_compare → 6 passed / 0 failed(四样本对拍全过)⇒ 不只是"文件在",是"能 dlopen + 渲染" ② dmg 里也带着它:挂载 ShuyoNote_1.91.3_aarch64.dmg → Contents/Frameworks/libpdfium.dylib 同样 15,219,824 字节、同哈希 ` ## 教训(写进提交,免得下一个人重犯) **配置文件里的"方向/位置"这类性质,门禁(YAML/链接/单测)抓不到 —— 只有真打一次包才露出来。** 我上一条提交的验证是"23 条门禁全绿",那对配置方向是**无信息**的;这次的报错比任何静态检查都值钱。 (同族:macOS.files 与 bundle.resources 的目标目录不同 —— Resources **不在** Rust 侧 pdfium_native::library_dir() 的搜索路径里,所以 Windows 那套 resources 写法在 macOS 上会"打包成功但加载不到"。) ### 仍然欠着的(P4 macOS 剩余,不在这条提交里) - **签名 / 公证**:等 Apple 证书(外部阻塞)。届时要验两件:① 包内 dylib 是否随 app 一起被签 (nested code 必须逐个签,codesign --verify --deep --strict + spctl -a -vv); ② 签名后 check:macos-bundle` 仍绿(哈希不变)。 - **"装完就能开 PDF" 的真机读数**:需人手装一次并打开一个 PDF(P4 的人工项)。 | 16 天前 | |
fix(packaging): Windows 装包带上 pdfium.dll(此前 resources 是空的,装包里只有 exe) P4 打包收尾时发现: tauri.conf.json 的 bundle.resources 一直为空 ⇒ NSIS 装包里只有 shuyonote.exe(对 09-16 出的 1.91.3 装包 7z l 实测:7 个文件、pdfium.dll 命中 0), 而 PDFium 是 libloading **运行时**加载 ⇒ 真机上 SHUYONOTE_PDF_ENGINE=pdfium 只会得到 「找不到 PDFium 动态库」。 改:新增 src-tauri/tauri.windows.conf.json(**平台专用**,Linux/macOS 不受影响),把 vendor/pdfium/win-x64/bin/pdfium.dll 映射成**装包根目录**的 pdfium.dll——Windows 上 Tauri 的 resource_dir 就等于 exe 所在目录,pdfium_native::library_dir() 正是从那里找。顺带: tauri-build 的 copy_resources 在**构建期**就会把它拷到 target/release/ 的 exe 同级。 判据(都是产物级、可复核的): - 同版本 1.91.3 装包 7z l:7 个文件 → 8 个文件,多出 pdfium.dll; - 从装包 7z e **解出来的** dll 与 vendor/ 源文件 **sha256 一致** (79D4676B656CFB1ABCEA88F9ADE3B4B0826C5200382DB5F4EC72A636C598C118); - target/release/pdfium.dll 的 CreationTime = 本次构建时间(构建期拷贝确实发生了)。 配套(这个 dll **不入库**:.gitignore 里有 src-tauri/vendor/pdfium/): - release.yml 加两步(都只对 windows 档):打包前 node scripts/fetch-pdfium.mjs --platform win-x64 现拉;打包后用 7z l 对**产物**断言装包里真有 dll。**变异实测**:把 09-16 那个没 dll 的同版本 装包换进 bundle/nsis/ 跑那段断言正文(逐字取自在 YAML),当场红——报「装包里没有 pdfium.dll」; 换回真装包即通过。 - pnpm check:win-build-env 增一条硬前置(用 import.meta.url 定位仓库根,与其它脚本的写法一致)。 缺源文件时 tauri-build 的 copy_resources 报 resource path … doesn't exist,出在**构建脚本期** 而非打包期——按已安装的 tauri-build 2.6.3 / tauri-utils 2.9.3 源码与错误串核对过。 - docs/RELEASING.md:本机构建补第 ③ 步、check:win-build-env 表格补一行、CI 一节说明这两步。 - CHANGELOG.md:记在 [Unreleased] 的「修复」。 未做(本机做不了,仍在 P4 交接单里):Linux 装包(Tauri 的 resource_dir 不是 exe 目录,要么给 library_dir() 加探测、要么配 tauri.linux.conf.json)与 macOS(.app/Contents/Frameworks)。 | 16 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 14 天前 | ||
| 15 天前 | ||
| 13 天前 | ||
| 14 天前 | ||
| 15 小时前 | ||
| 10 天前 | ||
| 1 个月前 | ||
| 14 小时前 | ||
| 14 小时前 | ||
| 9 天前 | ||
| 14 小时前 | ||
| 14 天前 | ||
| 16 天前 | ||
| 16 天前 |