Skip to content

Releases: Dyse-Sofqi/SyncHub

0.2.4

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 10 Oct 06:03

这一版把「深度清理」(重写历史)从一条半截流程补成一条能走完、能中断、能续做、
并且说清代价的完整流程。修了四个真 bug,其中两个会丢东西;顺手把清理相关的
报错全部改成了中文。

起因是三条实测反馈:清理完之后点「立即同步」报一句英文的
refusing to merge unrelated histories;第二次清理直接失败;
以及「清理完 .gitignore 多出目录,那这些目录以后岂不是不进同步了?」——
最后这个问题界面从来没回答过,而它恰恰是这个动作最要紧的后果。

修复

  • 重写不再删掉你的本地文件。 git filter-branch 的最后一步会把工作区对齐到
    改写后的 HEAD,于是被剔除的目录会从磁盘上消失 —— 与「只清历史」的承诺正好相反。
    勾一个装着笔记的目录,笔记就没了。现在重写之后会把它们放回磁盘(内容与重写前
    一模一样),确认页也把这条写成了明确的承诺。
  • 第二次深度清理不再必然失败。 filter-branch 见到上一次重写留下的
    refs/original/ 就拒绝开始,而插件只在「丢弃备份并回收」里清它 —— 等于
    「清理两次之间必须先丢弃备份」,与「备份引用带时间戳(因为用户可能清理多次)」
    的设计意图相矛盾。现在重写时会自动覆盖那份中间引用。
  • 重写报错不再等于「什么都没发生」。 引用是边改写边更新的,收尾那次工作区同步
    失败会让命令报错、但历史已经变了。原来这种情况被报成「重写失败」,于是忽略规则
    不写(下次同步把刚剔掉的路径原样提交回来)、结果页也不出现,而哈希全变、远端分叉
    已经发生。现在按「引用动没动」判断。
  • 重写把整条历史清空时,分支会被自动还原。 勾选的路径若覆盖了每个提交的全部内容,
    没有提交能活下来,git 会把当前分支整个删掉、仓库落到「没有提交」的状态。
    现在检测到就当场还原,并告诉你「库是好的,请少勾一些路径」。
  • 重写之后「立即同步」不再卡死。 重写后本地与远端没有任何共同提交,拉取会报
    fatal: refusing to merge unrelated histories。现在这句话有中文说明、并且直接告诉你
    该做什么
    (强制推送);拉取与 rebase 也会在动手之前就停下来(真跑起来会留下一仓库冲突)。
  • 清理相关的报错全部中文化,不再出现 git 的英文原文。

新增

  • 深度清理的四步收进一个窗口:体检 → 重写 → 强制推送 → 确认库没问题后丢弃备份。
    推完自动进入收尾页;收尾页列出三件具体要检查的事(打开几篇笔记 / 图片能不能显示 /
    别的设备重新 clone),然后才是「丢弃备份并回收」。空间要到这一步才真正释放 ——
    以前结果页的次要按钮写着「完成」,会让人以为整件事结束了。
  • 设置页「清理」一节多了「继续上次的清理」:只要还有未完成的清理(重写备份还在),
    它就可点,点进去直接到收尾那一步。中途关掉 Obsidian、甚至重启之后都能接着做。
  • 体检报告里,目录行会标出「N 篇笔记」;确认页会明确告诉你:剔掉的目录以后不再
    跟着 git 同步
    (会被写进 .gitignore),其他设备 clone 之后不会有它们。
    如果勾中的目录里有笔记,会额外警告一次 —— 这是这个功能唯一会让人丢东西的路径。

修复(进行中的可见性)

  • 重写进行中有进度可看了:弹窗里显示「已用 X,预计总共约 N 分钟」,左下角状态栏与
    「仓库同步」面板顶部也会一直显示「正在重写历史…」。窗口可以关掉,重写完成之后
    结果页会自己弹回来(关掉它不会让结果丢掉)。
  • 进度不报百分比:重写是逐提交跑的,git 不会告诉你「处理到第几个提交」,
    编一个百分比就是骗人。

0.2.3

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 09 Oct 19:35

这一版只修一个 bug,但它是必现的:在一个「刚建好、分支从没推过」的仓库里点
「立即同步」,会直接报错、什么也不做。

根因是同步链路里的一个死锁。链路是「提交 → 拉取 → 推送」,而拉取这一步
硬要求当前分支已经配置了上游;可建立上游的恰恰是推送(推送用的是
git push -u origin <分支>)。于是拉取先报错、链路中断、推送永远轮不到,
上游永远建不起来 —— 第一次同步必然卡死。

触发它的仓库形态很常见:远端分支和本地的 origin/<分支> 都在,
只是 branch.<分支>.remote / branch.<分支>.merge 还没写进配置
(这两项正是推送会替你写的)。也就是说,问题不在「仓库没配好」,
而在「只差一次推送」。

修复

  • 分支没有配置上游时,拉取不再报错。 改为:有配置的上游就用它;没有就退回
    同名的 origin/<分支>(在 fetch 之后判断,否则一个从没 fetch 过的仓库
    看不到远端分支);远端连这个分支都还没有时,没有东西可拉 —— 直接跳过,
    把建立上游交给随后的推送。这样「刚建仓库 → 点立即同步」一次就能走通。
  • 只有在压根没配置远端时才会拦下,提示改为「还没有配置远端仓库,无法拉取。
    请在设置中填写远端地址。」—— 指向真正该做的事,而不是让你去「先设置上游分支」。
  • 游离 HEAD 的提示语从「无法推送」改为「无法同步」:它现在拉取和推送都会出现,
    而「请先切换到一个分支」这条建议两边都适用。

内部

  • NoUpstreamError 的含义收窄为「没有配置远端」(原来还把「分支没配上游」算在里面,
    两者应对方式不同,混用会把用户指错方向)。
  • 新增 2 条真实仓库测试:抹掉上游配置后仍能拉回远端提交;远端还没有该分支时
    拉取返回「已是最新」、随后的推送把上游建起来。

0.2.2

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 09 Oct 19:05

[0.2.2] — 2026-10-10

这一版做两件事:别让大文件进 git(两层预防),以及已经大了怎么办(清理)。
起因是一次实测:一个 159 次提交的笔记库有 460 MB 的 .git,其中插件构建产物 319 MB、
字体 186 MB、向量库缓存 84 MB,而真正的 markdown 只有 63 MB —— 仓库体积失控几乎从来
不是笔记造成的。而 git 的历史不可逆:大文件一旦提交进去,事后清理要重写全部提交,
那是一件按提交数计时的重活。所以预防建在「它进历史之前」,清理则是一套独立的、
把代价说在前面的动作。

还有一条独立的轴:重写历史的开销只吃提交数,与每个提交改了多少字节无关 ——
20 MB 但有 10000 个「只改一行」的提交,重写要几小时;500 MB 但只有 200 个提交,
只要十几分钟。所以「本地状态文件」(光标位置缓存、工作区布局)进 git 的代价
不是体积,而是每个同步周期白多一个提交。大文件拦截防不了这一条。

新增

  • 清理:体检 / 回收 / 深度清理(设置页「仓库同步」的清理一节)。三层风险递增,
    每一层都说清代价:
    • 体检(只读)—— 按目录汇总历史里占空间最多的部分,外加最大的单个对象。
      按目录而不是按文件,是因为剔除的单位就是目录:报告里的每一行正好是一个
      可以拿去执行的动作。库根目录的文件只报账、不提供勾选(剔掉它们等于清空整个库)。
    • 回收空间 —— git gc --prune=now。安全,但常常一点也回收不到:大文件基本
      都在可达的历史里,只有重写才能清掉。这句话写在描述里,免得你把「没变小」当成功能坏了。
    • 深度清理(不可逆)—— 把选中的路径从全部历史里剔除(重写每一个提交)。
      动手前会把三件事摆出来:所有提交的哈希都会变(远端要强制推送、其他设备要重新
      clone)、已经推到远端的旧历史清不掉、以及预计耗时(按提交数算,实测约
      3.5 秒/提交 —— 一个 159 提交的库约 10 分钟,期间请不要关闭 Obsidian)。
      执行前先建一个备份引用(refs/obsync-backup/<时间戳>),失败或后悔都能退回去;
      执行后自动把那几条路径写进 .gitignore,否则它们会在下次提交时原样回来。
    • 丢弃备份并回收 —— 重写之后空间不会立刻变小(备份还拉着旧对象,这是刻意的:
      先让你确认库还能用,再丢退路)。确认无误后点它,才真正释放空间。不可逆。
  • 提交前的大文件拦截(设置页「仓库同步」的大文件阈值,默认 5 MB,填 0 关闭)。
    提交 / 立即同步时,待提交文件里超过阈值的会被拦下、弹窗问一次,整条链路停在
    那里 —— 不会出现「同步完成」而那个文件其实没提交。弹窗把两个选择各自的代价都写清楚了:
    仍然提交(它以后每次改动都会在历史里再存一份完整副本)或退出跟踪并忽略
    (不再有版本历史、本地文件保留;历史里已有的副本不会消失,仓库体积不会因此变小)。
    关掉弹窗 = 取消。自动同步不弹窗,改为发一条通知告诉你「同步已暂停、去哪处理」。
  • 「补齐推荐的忽略规则」按钮(设置页「仓库同步」的 .gitignore 一节)——
    把字体(ttf/ttc/otf/woff/woff2,大小写各一条)、Office / LibreOffice 临时文件
    (~$*、.~lock.*#)、本地状态文件(workspace.json、workspace-mobile.json、
    workspaces.json、*-position-cache.json)这几类规则并进 .gitignore。
    只追加缺的那些,你自己写的规则一行都不动,可以随手点(幂等)。
    它与那个覆盖式的「填入默认内容」是两回事。
  • 「停止跟踪本地状态文件」按钮(同一节)—— 光加忽略规则对已经跟踪的文件没用
    (.gitignore 只管未跟踪的),而已经同步了一阵子的库恰恰是最需要它的。这个按钮
    把已跟踪的那几个从索引里摘掉(本地文件不动),并补上忽略规则。会先让你看见
    要摘哪几个再确认。
  • 「忽略插件目录」开关(默认关)—— 打开后把整个插件目录也加进推荐规则。
    插件是仓库体积最大的单一来源,但忽略之后换设备 clone 时插件不会自动就位,得重新装。
    这是个取舍,所以做成开关交给你,而不是替你选。
  • 面板每一行的「放弃更改」(仓库同步面板的「更改」列表,2026-10-10)——
    一键把那个文件退回上次提交的样子。两种场景共用一个动作,因为它们在 git 眼里是同一件事:
    改坏了想退回、以及误删了想找回(被删的文件会从上次提交里重新写出来)。
    它是本插件唯一会丢用户编辑的动作,而且不可逆(放弃的编辑从来没被提交过、
    不在 git 里),所以:确认弹窗会列出具体哪几个文件、把「不可逆」写在正文里、
    确认按钮用警示色。两类行不给这个入口:未跟踪的新文件(它们没有「上次提交」
    可退,而「放弃」对它们等于删掉一个新文件 —— 丢的东西一点退路都没有)、
    冲突行(冲突区已经有「放弃本次合并」,而面板看不到文件内容,
    在这里替用户决定「用哪一边」正是不该做的事)。
  • 「文件恢复关着」的警告框(仓库同步页最上方,只在它关着时才出现)——
    Obsidian 的「文件恢复」核心插件默认每 5 分钟给每个改过的文件存一份快照、保留 7 天,
    存在 IndexedDB 里,完全不碰 git。它才是「高频防丢失」该用的机制:git 的恢复粒度是
    全库提交,用它做高频恢复会让提交数等于编辑次数。所以想靠缩短同步间隔来防丢数据时,
    这个警告框会先把你指到那里。(第一版是塞进「注意事项」的一条,太不显眼 ——
    它讲的是数据安全,现在有独立的警告配色与标题。)

变更

  • 定时同步的默认周期 10 分钟 → 30 分钟(只影响新装的库与缺这个字段的库,
    已经存过这个值的库不受影响)。理由:高频保护已经明确交给「文件恢复」,定时同步剩下的
    职责是「云端新鲜度」与「跨设备」,而灾难恢复本身要花几小时 —— 丢 30 分钟与丢 5 分钟
    没有实际差别。反过来,间隔越短提交数越线性增长,而重写历史的开销只吃提交数。
    想让云端更实时请用「立即同步」(命令 / 面板 / 功能区都有)。
  • 去掉了仓库同步面板上的逐文件暂存(「暂存此文件 / 取消暂存」与「全部暂存 /
    全部取消暂存」)—— 它们做不到看起来在做的事:SyncHub 的「提交」是 git add -A,
    手动暂存了什么对最终提交毫无影响;更要紧的是定时同步到点会把它们一起提交掉,
    也就是说这个按钮连「暂时不提交」都做不到。用户暂存 A 想只提交 A,结果 B 一起进去了。
    SyncHub 不做选择性提交 —— 它的定位是「把整个库同步上去」。按暂存状态的分组保留
    (冲突文件落在「已暂存」那一组)。
  • 自动同步被大文件拦下时会给一条通知(以前是静默停住)。只要那些文件还在,自动同步
    就一直停着 —— 这条通知是它唯一的表现,所以每次到点都会提示一次。
  • 文案口径改了:「已经写进历史的图片 / 文件不会让仓库变小」那几处,以前一律接
    「本插件不做重写历史」—— 现在指向设置页「清理」里的深度清理。

修复

  • 设置页里 .gitignore 代码框的全宽失效了。 它那条 width: 100% 被 CSS 解析器
    整条丢弃:上面那句注释里写了 `**/` 递归,而 **/ 里的 */ 提前结束了注释,
    剩下的文字被当成下一条规则的选择器,于是规则连同它一起被丢掉 —— 不报错、样式就是不生效。
    代码框因此只有 173px 宽(容器 660px)。同一段注释里 min-height、white-space、
    padding 也一起失效了。
    pnpm check 新增第 8 项CSS 注释完整性守住这类问题:现有「CSS 类覆盖」那一项拦不住它
    (被丢弃的规则在文本上仍然「有定义」)。

0.2.1

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 09 Oct 10:51

[0.2.1] — 2026-10-09

这一版把功能区头像从「一张只能看的图」变成设置页的入口:点它打开设置窗口并停靠
「通用」页(换平台、改令牌都在那一页),头像外侧常驻一圈柔灰虚影环、悬停时环加深并晕开
一团保守的模糊扩散,而光标保持默认 —— 它首先是一张头像,点击只是顺手的入口。
另给状态栏条目加了一个「贴靠最左侧」开关(默认开),并删掉了「状态栏占满整屏宽」
开关与那条拉全宽的 CSS 规则
—— 状态栏恢复 Obsidian 原生形态(右下角一簇),
条目仍排在这一簇的最左侧。

新增

  • 功能区头像可以点了(2026-10-05 加的那个头像):点它打开设置窗口并停靠
    「通用」页
    (换平台、改令牌都在那一页)。两条刻意的「不摆出按钮样子」的设计:
    头像外侧常驻一圈虚影环(2px 柔灰,紧贴头像边缘、中间没有缝),悬停时
    环加深并晕开一团模糊扩散(范围保守,不超出功能区),而光标保持默认 ——
    它首先回答「这是谁」,点击只是顺手的入口
  • 「状态栏同步条目贴靠最左侧」开关(设置页「通用」,默认开)。开着就是一直以来的
    表现:同步条目排在状态栏那一簇的最左侧(只改自己的视觉顺序,不动其他条目)。
    关掉后条目不作特殊处理,按 Obsidian 默认顺序排在其他条目后面。
    它与下面删掉的「状态栏占满整屏宽」是两回事:那个碰的是状态栏的宽度
    (为了贴屏幕最左,代价是整体观感从「右下角一簇」变成「底部一条」),已整条删除;
    这个只管条目在状态栏里的顺序,状态栏本身两种状态下都是 Obsidian 原样

变更

  • 「状态栏占满整屏宽」开关删掉了,状态栏不再拉成全屏宽。 同步条目仍然排在
    状态栏那一簇的最左侧(只改自己的视觉顺序,不动别人的条目),只是不再贴
    屏幕最左。理由:拉宽能让条目贴到屏幕最左,但代价是状态栏的整体观感
    从「右下角一簇」变成「底部一条」—— 那是用户自己的界面。设置项、那条 CSS
    规则与 main.ts 里给 body 加/摘类的代码一并删除;老 data.json 里残留的
    statusBarFullWidth 字段会被自然忽略,不需要迁移

0.2.0

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 07 Oct 18:18

[0.2.0] — 2026-10-08

这一版补上了一整块**「看得见的状态」(功能区头像、同步特效横幅、状态栏忙碌圆环、
初始化徽标),把
主题从「只能绑定 / 更新」补成「也能新装」,给图片同步加了
变动后自动同步,并修掉一个在 Obsidian 1.14 上让功能区头像
静默消失**的选择器问题。

新增

  • 功能区头像(设置页「通用」)—— 打开后在左侧功能区(ribbon)底部挂一张
    当前令牌账号的圆形头像。它回答的是「现在配的令牌是哪个账号」(镜像探测拿的
    也是这个账号名),没有点击动作。

    地址与账号名来自同一次 validateToken()(Gitee 的 GET /v5/user 一个响应里
    两个字段都有),所以不多打一次接口;那个平台没配令牌时一个请求都不发 ——
    匿名问那个接口只有 401,而 Gitee 的匿名配额实测极低。

    平台由下面新增的「使用 Gitee 头像」决定(默认开 = Gitee,关 = GitHub)。
    头像是账号资料、插件改不了,所以那一行的描述末尾直接给了换头像的个人资料页
    链接
    ,并且跟着平台走(Gitee → gitee.com/profile、GitHub →
    github.com/settings/profile)—— 点一下就到换头像的地方。

  • 主题也能新装了。 在它之前主题只有两条路:绑定库里已经装好的、更新
    已跟踪的 —— SyncHub 从来没能把一个主题装到磁盘上。现在多了「添加主题仓库」
    按钮与命令,主题写进 {configDir}/themes/{主题名}/,装完不替你切换
    (到「设置 → 外观 → 主题」里选它)。

    三处刻意与插件不同:目录名取远端 manifest 的 name(不能当目录名时回落到仓库名)、
    不做镜像发现(主题的镜像判据依赖本地已装的那一版,新装时手上还没有)、
    绝不调 setTheme。另外立了一条安全线:目标目录里已经装着另一个主题时
    拒绝写盘(同名不同主题确实存在,而被覆盖的很可能是你当前正在用的那个,
    且它不一定在跟踪列表里、没有「重新下载」这条路)。

    把主题地址填进「添加插件仓库」(或反方向)时,失败后会探一次对面的标志性文件
    (main.js / theme.css),确有就给一个「改为按主题安装」的按钮 ——
    而不是只留一句「缺少 main.js」。

  • 「正在同步」看得见(状态栏 + 侧边栏面板)。

    状态栏那一格忙碌时挂一个转动的圆环并把文字改成强调色(原来忙碌态与常态
    只差几个字,一样是 12px 灰字,在一排条目里扫过去看不出区别,而同步可能要跑几十秒);
    文案也从「正在提交…」改成「正在同步:提交中…」—— 点「立即同步」时一眼能分出
    这是三步链路里的一步,后面还有拉取与推送。

    侧边栏仓库同步面板的工具条正下方加了一条同步特效横幅(转圈 + 三个阶段 +
    一根不确定进度条 —— git 不会报「推到第几个对象」,编一个百分比就是骗人;
    三个阶段本身才是真实可得的进度)。动作进行中四个动作按钮禁用(刷新不在其中,
    它只读,随时可点)。横幅不整块重绘:一次「立即同步」三个阶段各变一次,
    走整块重绘会白跑三遍「分支 / 远端 / 体积 / 历史」(实测一次重绘 10 个 git 子进程)。

  • 图片「变动后自动同步」(设置页「图片同步」,默认开)—— 在受管文件夹里
    新增或改动图片之后,停手 30 秒(5–600 可调)自动跑一轮。一次编辑会话
    (拖进一批图、批量压缩)会被合并成一轮,也不会在你还在写文件的时候开始。
    它只管本机的改动。

    周期同步的职责因此改成「拉回其他设备上的变化」(另一台设备传的图、云端被
    手工改动的对象 —— 那些在本机不会产生任何事件),默认周期从 10 分钟改成 30 分钟
    (它默认仍是关的)。完整推导(成本模型、四个触发器的分工、明确不做的事)见
    docs/image-sync-design.md。

  • 设置页「仓库同步」能独立走完全部基本设置 —— 「初始化 git 仓库」从侧边栏
    面板搬进设置页,与远端地址、git 可执行文件路径排在同一张卡片里(这三项都是
    「连接测试能通过」的充要条件),排在「连接测试」之前。那一行带状态徽标
    (「已是 / 还不是 git 仓库」,已是时按钮置灰)。

  • 插件安装器页重排 + 标签数字徽标。 页内顺序改为:状态小字 → SyncHub 自身更新
    卡片 → 「启用 Gitee 镜像源更新 SyncHub」开关 → 「进入设置页时自动检查」→
    「启动时检查更新」→ 启动检查延迟 → 「自动发现 Gitee 镜像」。

    「进入设置页时自动检查」现在同时查跟踪列表与 SyncHub 自身 —— 一个插件都没跟踪的
    用户同样该知道自己有没有新版本。SyncHub 自身有可用更新时,「插件安装器」标签上挂
    数字徽标
    (原来只在页面里一行小字,Notice 一闪就错过)。

变更

  • 访问令牌移进「通用」页(原来在「插件安装器」页)。它和头像同处一页 —— 两者讲的
    是同一件事(当前配的是哪个平台的哪个账号)。

  • 自身更新来源从自由文本框改成开关「启用 Gitee 镜像源更新 SyncHub」(默认开 =
    走 Gitee 镜像 sofqi/SyncHub,关 = 走官方 GitHub 仓库)。两个固定地址之间切换本来
    就是二选一,而原先的自由文本框要用户先读懂一串规则(空串算默认、owner/repo 简写
    按 GitHub 解释、非法地址抛错)才敢动。

    代价是不再支持自定义来源(如自己的 fork)—— 那个场景本来也不成立:写盘前校验
    远端 manifest 的 id 必须是 ob-sync,fork 改了 id 就会被拒。

  • 删掉「启用插件安装器」总开关。 它在 src 里只有两个读取点,且都是自动检查的
    前置条件(功能区那个图标、5 条安装器命令、设置页按钮与列表从来不看它)。
    于是「关掉它」与「把两个检查开关都关掉」完全等价 —— 一个 off 的第二种说法,
    而名字让人以为「不装了」。

  • 按钮行的外观与图标:「添加主题」→「添加主题仓库」;「绑定已安装的插件与主题」
    →「绑定已有插件或主题」(并在文字前加 lucide link 图标);「检查全部更新」→
    「检查更新」(加 refresh-cw 图标)。这一排按钮的卡片(连同标题与说明)去掉,
    只留按钮 —— 页签名已经是页名,列表下方还有空状态提示,标题与说明都是重复信息。

  • 四个设置页的页首标题删掉(插件安装器 / 仓库同步 / 图片同步 / 通用)—— 标签页
    已经写着页名,再顶一行同名标题是重复。节内的小标题(「访问令牌」、R2 连接、
    连接测试…)留着。

修复

  • Obsidian 1.14 上功能区头像「静默消失」。 1.14 把功能区容器的修饰类从 mod-left
    改成了 mod-primary,而 findRibbonContainer() 的四个选择器全都写着 mod-left
    → 一个都匹配不到 → 恒返回 null → render() 静默 return,没有任何报错(所以
    它看起来像「某个改动弄坏了」)。现在补上 mod-primary(保留 mod-left),再加一条
    不依赖版本修饰类的兜底 .workspace-ribbon .side-dock-settings(只有左 / 主功能区
    才有这一组,不会误取右侧)。

    教训:选择器不要依赖版本修饰类,永远留一条不依赖它的兜底;升级 Obsidian 后要
    重抠 .probe 的 app.css 并重跑对应探针。

  • 「初始化 git 仓库」的状态徽标每切一次设置页就重问一次。 每次重绘都起一个
    git is-repo 子进程,结果回来才填徽标 —— 于是能看到徽标「弹」出来,布局还被撑高
    (.obsync-badge 的 line-height: 1.6 + padding: 0.05em 让药丸 20px,而标题那一行
    只有 17px,整行被顶高 3px、说明文字往下移)。现在问过一次就缓存(只在内存:
    这个值会变 —— 别处 rm -rf .git、从别的设备同步回一个没初始化的库 —— 写进
    data.json 就是一句没人纠正的假话),并把徽标改成 line-height: 1 +
    padding: 0.15em 0.5em(改完重量一遍:「有徽标」与「没徽标」逐项相同)。

  • 点完「初始化仓库」后按钮又亮回来 —— apply() 改成同步之后,点击处理 finally
    里的 setDisabled(false) 会把刚被置灰的按钮重新点亮;改成按已知事实恢复。

  • setButtonText 与 setIcon 连用只剩图标。 setButtonText 是「清空整个按钮再写
    文字」,而 ButtonComponent.setIcon 会先删掉第一个子节点再 append 图标 —— 两者连用,
    文字被当成「第一个子节点」删掉。按钮行那两个图标因此自己建一个容器装图标、再 prepend
    到文字前面(换文字之后还要重调一次)。

内部

  • 平台列表移进 host/types.ts,HostKind 由它推导 —— 此前「有哪些平台」有 4 份
    副本,其中 settings 那份(持久化校验)漏掉某个平台时,用户在那个平台上装的插件会在
    下次加载 data.json 时被当成非法条目无声丢弃(不报错,列表里就没了)。

  • 删掉两处死代码:InstallerService.checkForUpdate(判据用 requestedVersion,跟踪
    最新版时那个值是字符串 "latest",几乎恒报「有更新」)与 isManifestCompatible。

  • 设置迁移 v8 → v9(自身更新来源从「自由地址」折算成布尔)与 v9 → v10
    (删总开关时把两个检查开关置 false)。折算规则与当年那套解析同源,坏形状一律按当年
    同一口径处理 —— 老用户升级时行为不变。

  • 新增两个能脱离 Obsidian 单测的纯逻辑模块:ImageChangeQueue(攒批器:静默期 +
    硬上限 + 正在跑时不丢)与 features/avatar/ribbonAvatar.ts。测试增至 88 文件 /
    1871 用例
    。

  • .probe 的 app.css 随 Obsidian 1.14.4 重抠,头像探针的功能区类名改用
    mod-primary 并把两档类名都跑一遍;README 补了「升级 Obsidian 后要重抠 + 两档都要跑」。

0.1.9

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 04 Oct 19:15

[0.1.9] — 2026-10-05

这一版集中在仓库同步面板与**设置页「仓库同步」**的可用性,另有一批文案与布局修复。

新增

  • 面板顶部重排 + 「更改 / 最近提交」标签组。 状态摘要(与远端一致 / 领先落后)与
    「仓库大小 / 待提交改动」两栏搬进「更改」页顶部;列表按标签组切换,长列表不再互相挤占滚动位置。
    切换标签只换可见性,不重跑那几条 git 命令。冲突区留在标签之外(它是「现在就得处理」的状态)。
  • 更改列表的格式筛选。 全部 / Markdown / .png / …,选项由这一轮真实出现过的格式生成并带
    数量 —— 只想看笔记时一眼筛出 .md。筛选只影响列表,「待提交改动」那一栏始终是总数。
  • 「嵌套仓库」行(gitlink)识别与一键「不再跟踪」。 在库的插件目录里就地开发时,那些目录自带
    .git,库把它们记成指针(索引模式 160000):看着像文件夹、没有文件级差异、怎么点「全部暂存」
    都消不掉。面板现在给它加徽标、写明原因,并给一个「不再跟踪」(摘索引 + 写 .gitignore,
    本地文件与它自己的 .git 一个都不动)。
  • 差异视图改成主工作区标签页(原来是弹窗 —— 太小,长行读不了),并加了 双栏对照模式
    (像 VS Code:删除在左、新增在右,同一段改动按序号对齐,多出来的那一行只有一边有内容)。
    视图模式跟着标签页记住;文件差异会跟着库状态自己刷新。
  • 面板工具栏显示距离下一次同步的倒计时(与设置页那一行同一份数据),后移到「与远端一致」
    同一行展示 —— 两者都是「我现在处于什么状态」。
  • 设置页「仓库同步」重排: 远端地址(就地可改的输入框)+「打开仓库同步面板」同一行、
    git 可执行文件路径,这两项排在「连接测试」之前(它们是「测试能通过」的充要条件)。
  • 标签栏照 MDRazor 重做(只有当前那一个是贴着内容区的卡片),工具条按钮去阴影、
    间隙收紧到 4px,刷新按钮改成与前面三个同样的文字按钮。

变更

  • 「与远端一致」文案更准确:工作区还有没提交的改动时改为
    「与远端一致,但有未提交的改动」(而且不标绿)—— ahead = behind = 0 只说明已提交的部分
    对齐了,原来那句话会让人以为可以关电脑了。
  • 面板不再显示可编辑的远端地址(配置归设置页);renderRepo 与 safeRemoteUrl 一并删除,
    面板渲染少一次 getRemoteUrl()。
  • 「最近提交」页里那行与标签同名的标题删掉(多余)。
  • 远端地址的校验逻辑抽到 features/sync/remoteUrl.ts(输入框与命令面板的「编辑远端地址」弹窗共用)。

修复

  • Setting.setClass("a b") 会抛 InvalidCharacterError(它走 classList.add,一次只能一个
    类名)—— 真机上整页设置渲染不出来。测试替身现在照真机那样抛错,同样的错在单测里就会红。
  • 面板按钮的悬停效果:上一版给所有按钮换了浅底,把「立即同步」(强调色填充 + 白字)也一起改了,
    悬停时变成浅底白字、整颗糊掉;现在主按钮用自己的强调色悬停色。
  • diff 内容框的高度限制:.obsync-diff-body 上那条 max-height: 68vh 是弹窗时代留下的,
    改成标签页之后变成「框里一条滚动轴、框下空一片」;去掉之后整页滚一条轴。
  • 与远端一致 那一行与倒计时胶囊没对齐(段落自带外边距),现在两者中线一致。
  • 工具条的 padding 从 16px 收到 8px —— 侧边栏窄一点就不得不换行。

0.1.8

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 25 Sep 04:41

SyncHub 把三件事合在一起:用 git 同步笔记仓库、把图片镜像到 Cloudflare R2、
从 GitHub 或 Gitee 安装社区插件与主题 —— 并且都不只认 GitHub。界面中文优先、英文对等。

本次更新(0.1.8)

新增

  • 图片管理面板里可以单独重命名一张图了 —— 列表每行右侧一颗铅笔按钮,点开一个
    预填当前文件名的输入框。它与底部的「批量重命名」是两条路:一个管「就这一张」,
    一个管「勾选了一批」—— 改一张图的名字不该要求先勾上它。
  • 点列表里的缩略图可以放大看 —— 就地弹出预览,不离开面板。滚轮直接缩放
    (25% – 400%),放大时弹窗整体跟着变大直到窗口上限,再大就按住图片拖动看
    其余部分。100% 的含义是「图片完整装进窗口」,不是原始像素 1:1。

变更

  • 图片管理面板底部那颗按钮从「重命名…」改成「批量重命名」。

修复

  • 「仓库同步」设置页里 .gitignore 代码框的宽度 —— 它此前只靠样式表里的一条
    width: 100%,而插件样式表不保证在热重载时被重新读入,于是改了 CSS、界面却没变,
    框缩回了右侧那几百像素。现在宽度与 box-sizing 直接写在元素上,不再依赖样式表。

安装

下载 main.js / manifest.json / styles.css,放进
<你的库>/.obsidian/plugins/ob-sync/,然后在 Obsidian 的「第三方插件」里启用。

国内访问 GitHub 慢或被阻断时,用 Gitee 镜像:
https://gitee.com/sofqi/SyncHub/releases

要求

  • Obsidian ≥ 1.8.7
  • 笔记同步需要系统 git,仅桌面端;插件安装与图片同步在移动端也可用

已知限制

  • 同步只支持桌面端(移动端没有系统 git)
  • 主题:支持绑定库里已装的主题并更新,不支持从仓库新装

完整更新记录见 CHANGELOG。

0.1.7

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 24 Sep 16:34

SyncHub 把三件事合在一起:用 git 同步笔记仓库 + 把图片同步到 Cloudflare R2 + 安装社区插件与主题,三者都支持 GitHub 与 Gitee,界面中文优先、英文对等。

这一版:图片同步 · 差异视图 · 可直接编辑的 .gitignore

🖼️ 图片同步(Cloudflare R2)

库里的图片在 R2 上存一份副本 —— 笔记走 git,图片走对象存储。

  • 只复制,从不删除:每一轮只补齐缺的那一边。删除只在你删掉本地那张图、并被问过之后才发生 —— 「一边少了 = 用户删的」本质上判断不准(清单丢失、两台设备各删一边都会错),判断错的代价是删掉你没打算删的东西。
  • 删本地时问一句(默认)。也可以设成「永远同步云端」(不问,直接一起删 —— R2 没有回收站)或「永不同步云端」(云端永远不动;那一份会被下一轮同步下载回本地,因为镜像是双向补齐的)。
  • 图片管理面板:把「本地有哪些图」「云端有哪些图」「哪些图被引用着」三条轴摊平成一张可筛选的表 —— 批量同步 / 压缩 / 重命名 / 删除都在那里。「已链接」徽标悬停能看到是谁在引用它。
  • 笔记内裁剪与压缩:阅读视图里每张库内图片都有悬浮工具条;压缩保持原格式,而且只在变小时才写回。
  • Excalidraw 画布里的引用也认得出:画布数据是压缩后写进 .excalidraw.md 的,不解压就会把正在用的图当成失联删掉。
  • 另有公网外链、受管文件夹(默认整个库)、密钥进系统密钥库。

🔍 差异视图

仓库同步面板上每个文件(含冲突行)、每条提交都能点开看改了什么;命令面板里也有「SyncHub:查看当前文件的差异」。

  • 工作区改动与已暂存改动分两节显示 —— 同一个文件完全可能两边都有内容(git status 里的 MM),只给一边等于把另一半藏起来;
  • 逐行给新旧两个行号、增删分色、保留 @@ 段落头;
  • 未跟踪的新文件按「全部新增」显示内容;二进制文件、纯重命名、内容被截断、文件过大各有明确说明(一片空白会被读成「没有改动」);
  • 合并提交也能看(git 默认对它不输出差异)。

⚙️ 「仓库同步」设置页里可直接编辑 .gitignore

多行代码框 + 状态徽标(已保存 / 有未保存的修改 / 尚未创建)+ 保存 / 填入默认内容(只填进框里,不直接覆盖)/ 在编辑器中打开。改动在失焦时也会保存;文件不存在时不会自动创建(打开设置页不该往库里多出文件)。

顺带修好两处:模板里的配置目录名不再写死 .obsidian(配置目录改名后那些排除规则一条都不会匹配),以及「在编辑器中打开」打不开时会明说原因并指回这个框,而不是点了没反应。

🧹 按社区审核规范复查

按 eslint-plugin-obsidianmd 的规则本体过了一遍:18 处降到 1 处(剩的那条是「建议迁到 Obsidian 1.13 的声明式设置 API」—— 设置页整体是手写渲染的,留作独立改造)。修的都是规则明确要求的形态:不写内联样式、不静态 import Node 内置模块、console.info → console.debug、定时器走 window、不用 document.createElement、不写死配置目录路径。

环境要求

  • Obsidian ≥ 1.8.7
  • 笔记同步需要系统 git,仅桌面端;插件安装与图片同步在移动端也可用

已知限制

  • 笔记同步只支持桌面端(移动端没有系统 git)
  • 主题:支持绑定库里已装的主题并更新,不支持从仓库新装;不做版本钉选与主题 beta 通道
  • 逐文件 hunk 级暂存、树形文件视图、行作者(blame)等 obsidian-git 的增强功能仍未做
    —— 文件级 diff 查看已在 0.1.7 补上

完整变更见 CHANGELOG。

0.1.6

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 21 Sep 16:20

SyncHub 把两件事合在一起:用 git 同步笔记仓库 + 安装社区插件,两者都支持 GitHub 与 Gitee,界面中文优先、英文对等。

这一版:插件 id 回退为 ob-sync

上一版(0.1.5)把插件 id 从 ob-sync 改成了 synchub,被社区审核打回:

The plugin ID in (manifest.json) does not match the existing plugin ID

原因是审核系统在更早的提交里就把本插件登记为 ob-sync,id 与既有登记绑定,
不能自行更改。这一版把它改回去。

显示名 SyncHub 保持不变 —— 商标那条审核已经通过,本次没有再报名字问题。
所以最终形态是 显示名 SyncHub + id ob-sync,两者不一致是有意的:
审核登记决定 id,商标规则决定显示名,来源不同。

⚠️ 如果你装过 0.1.5

Obsidian 是按 id 找插件的,所以安装目录要从
.obsidian/plugins/synchub/ 回到 .obsidian/plugins/ob-sync/:

  1. 把 data.json(设置 + 跟踪列表)复制回 ob-sync/ 目录,
    否则插件会以默认设置启动;
  2. 删掉 synchub/ 目录,否则插件列表里会出现两份;
  3. 跨 id 不能用「检查更新」(自我更新会校验远端 id,对不上就拒绝写盘),
    需要手动装一次。

访问令牌始终不受影响:它们存在 obsync-token-* 这个密钥 id 下,与插件 id 无关 ——
这一来一回都没有作废过凭据。

本版其他内容(承接 0.1.5)

  • 插件改名为 SyncHub(原名 OBSync 以全大写 OBS 开头,命中商标规则)
  • 修复英文界面的 .gitignore 模板:补上排除本插件自己的 data.json
    (中文模板一直有这条),避免英文用户的设置被同步、两台设备互相覆盖
  • 修掉两处社区审核打回:SecretStorage 的 API 版本守卫、
    以及一条 eslint 指令注释缺少理由

安装

下载 main.js / manifest.json / styles.css,放进
<你的库>/.obsidian/plugins/ob-sync/,然后在 Obsidian 里启用。

要求

  • Obsidian ≥ 1.8.7
  • 笔记同步需要系统 git,仅桌面端;插件安装在移动端也可用

已知限制

  • 同步只支持桌面端(移动端没有系统 git)
  • 主题:支持绑定库里已装的主题并更新,不支持从仓库新装;不做版本钉选与主题 beta 通道
  • 逐文件暂存、diff 查看、行作者等 obsidian-git 的增强功能不在首版范围内

0.1.5

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 21 Sep 16:03

SyncHub 把两件事合在一起:用 git 同步笔记仓库 + 安装社区插件,两者都支持 GitHub 与 Gitee,界面中文优先、英文对等。

⚠️ 这一版需要手动重装

插件改名为 SyncHub,id 从 ob-sync 改为 synchub。
旧名 OBSync 被社区审核以 Plugin name must not include parts of the name "Obsidian" 打回 ——
它以全大写 OBS 开头,正是 "Obsidian" 前三字母的缩写写法。

因为 Obsidian 是按 id 找插件的:

  1. 安装目录从 .obsidian/plugins/ob-sync/ 变成 .obsidian/plugins/synchub/;
  2. data.json(设置 + 跟踪列表)不会自动跟着走 —— 请手动复制到新目录,
    否则插件会以默认设置启动;
  3. 旧的 ob-sync/ 目录请删掉,否则插件列表里会出现两份;
  4. 跨 id 这一跳不能用「检查更新」 —— 自我更新会校验远端 manifest 的 id,
    对不上就拒绝写盘(这道守卫本是为了防止覆盖别的插件),所以必须手动重装一次。

你的访问令牌不受影响:它们存在 obsync-token-* 这个密钥 id 下,与插件 id 无关,
所以不需要重新填。

这一版

  • 改名与 id 统一:显示名、仓库地址、插件 id 现在都是 SyncHub / synchub
  • 修复英文界面的 .gitignore 模板:它漏了排除本插件自己的 data.json
    (中文模板一直有这条)。英文用户初始化仓库时,插件设置会被同步,
    导致两台设备互相覆盖设置 —— 正是该模板注释里警告的那个坑
  • 修掉两处社区审核打回:SecretStorage 的 API 版本守卫、
    以及一条 eslint 指令注释缺少理由

安装

下载 main.js / manifest.json / styles.css,放进
<你的库>/.obsidian/plugins/synchub/,然后在 Obsidian 里启用。

要求

  • Obsidian ≥ 1.8.7
  • 笔记同步需要系统 git,仅桌面端;插件安装在移动端也可用

已知限制

  • 同步只支持桌面端(移动端没有系统 git)
  • 主题:支持绑定库里已装的主题并更新,不支持从仓库新装;不做版本钉选与主题 beta 通道
  • 逐文件暂存、diff 查看、行作者等 obsidian-git 的增强功能不在首版范围内