Skip to content

FolderDock 发版记录 ​

把文件夹拼成可嵌套的「组合」、一次铺成多面板的 Windows 文件管理器

当前版本0.2.5
最近更新2026-10-21
Git 标签v0.2.5(另有 v0.2.4、v0.2.3、v0.2.2、v0.2.1、v0.2.0、v0.1.0)
状态可用(0.2.5,本站不分发安装包)
平台Windows 10/11(原生 shell 集成);Linux 有 XDG .desktop 安装实现,macOS 打包未实现

v0.2.5 — 2026-10-21 ​

安装目录里的 uninstall.exe 双击即卸载

  • 它原本是安装器副本,无参数双击会打开安装界面。现在按文件名识别:双击直接弹卸载确认(默认保留用户数据),完成后退出;带 --uninstall / --silent / --help 时仍走原来的命令行
  • 修 GUI 卸载停在结果对话框时临时清理副本提前放弃、留下 uninstall.exe 的问题:副本带 --wait-pid 等原进程退出再清理,并把子进程 stdio 设为 null(GUI 卸载器 FreeConsole 后无效句柄会让 CreateProcess 报 error 50)

v0.2.4 — 2026-10-21 ​

双击启动不再多出一个空控制台

  • 主程序改为 Windows GUI 子系统:console 子系统的进程会被系统分配控制台,关掉控制台等于结束进程;日志本来就走文件,不需要控制台
  • 安装器无参数打开图形安装界面时主动 FreeConsole;--silent / --uninstall / --help 仍保留控制台,脚本可继续同步读取 stdout 与退出码

v0.2.3 — 2026-10-21 ​

修项目 / 组合改名,文件夹不再提供改名

  • 项目根同时出现在项目列表和组合树根,两处都画了同一个 id 的输入框(egui ID clash),一次按键被两个 TextEdit 同时处理,改名因此改不对。现在记录改名的来源栏,只画一处,两栏共用同一个缓冲区
  • 修非当前项目改名静默失败(rename_node 只认 active_project);项目 / 组合名统一 trim、拒绝空名
  • 文件夹节点不再提供改名:它只是真实路径,改显示名不会动文件系统,容易让人误以为文件夹被重命名(旧的 label 字段随配置忽略)

v0.2.2 — 2026-10-13 ​

修组合树内部的行拖拽:落点原来只按被拖行自己算

现象 0.1.0 起就有、0.2.1 复核一致:在组合树里把一行拖到别的行上,松手什么也不发生;文件级拖放不受影响。

  • 根因:每行的 interactions 只在 st.drag == Some(id)(被拖的那一行)时才算落点,parent / index 也取自它自己——拖到别的行上时落点仍是它自己,MoveNode 要么原位、要么原地 +1。另外它读的是 resp.hover_pos(),而拖动中的控件不算 hover,拿到的是旧位置
  • 改法:落点由指针所在的那一行自己认领,规则抽成纯函数 claim_drop——被拖行绝不认领;组合行中带(0.3..0.7)= 放进这个组合,行的上半 = 插到它前面、下半 = 插到它后面;指针位置改用 pointer.latest_pos();draw_tree 每帧开头清一次 st.drop,拖着行滑出树外松手不再按旧落点改结构
  • 保留「越过 egui 拖动阈值才算数」的闸门(单击不会误当重排),新增 4 条单测钉住规则(含「被拖行绝不认领」这条回归)
  • 真鼠标实测(发行版):移动节点 4 → 组合 2 第 0 位,树里 B 插到 A 之前、面板顺序随之变化;组合行中带那档也实测到 into
  • 顺带核查「搜索浮层左边界贴窗口左边」是否回归:v0.1.0 → HEAD 的调用链与放置式完全一致,不是回归,本次未改动

v0.2.1 — 2026-10-13 ​

修拖拽:窗口从没被注册成 OLE 放置目标,而且拖出缺协议

用户反馈「拖拽我试了,不行」——根因分两层,第一层是致命的:

  • 落点整体失效:winit 只在窗口属性 drag_and_drop 为真时才 RegisterDragDrop,而 viewport 没开这个开关,窗口上压根没有 OleDropTargetInterface 属性。于是拖到面板 / 组合树、从资源管理器拖进来全都收不到落点,DoDragDrop 一律返回 DROPEFFECT_NONE(先前注释里「winit 已经注册过、再注册会拿 DRAGDROP_E_ALREADYREGISTERED」是误判)。打开后用 GetProp(hwnd,"OleDropTargetInterface") 实测确认已注册
  • 落点位置是旧值:拖拽期间鼠标被 OLE 抓走,winit 收不到 WM_MOUSEMOVE,egui 手里的指针位置还停在按下那一刻,按原样取会让落点偏回源面板。改成现问系统要光标(GetCursorPos + ScreenToClient,再按 pixels_per_point 折成 egui 点)
  • 拖出补齐协议:IDataObject::EnumFormatEtc 原来返回 E_NOTIMPL,而资源管理器在落下前后会枚举格式(实测被连调 8 次),拿不到枚举就判定数据不能用;现在返回只列 CF_HDROP + CFSTR_PREFERREDDROPEFFECT 的 IEnumFORMATETC,并补上 CFSTR_PREFERREDDROPEFFECT(声明允许的效果)与 SetData(CFSTR_PERFORMEDDROPEFFECT)(接受落点回报的实际效果)
  • 保留两条诊断日志:[drag] 收到落点 N 项 @(x,y)、[drag] 悬停开始/结束,外加落点回报的效果——现场排查「拖进来没反应」时能一眼分清是系统没把拖拽送到窗口,还是送到了但没命中目标
  • 验证:72 单测 + clippy 零警告;分发物实跑(装 / 卸 exit=0、数据目录保留、安装目录已清空);四条路径端到端跑通——面板↔面板、面板→组合树、从资源管理器拖进来、拖出到资源管理器(拖出那次的日志:落点回报所做的效果 = 2 → 拖放结束:Move,说明新加的 SetData(CFSTR_PERFORMEDDROPEFFECT) 生效了)

v0.2.0 — 2026-10-13 ​

拖拽(拖出 / 拖入)+ 面板布局可选;卸载不再留空壳

  • 拖拽走系统级 OLE:面板里选中的文件 / 文件夹能拖到资源管理器或别的程序;文件夹拖到组合树上 = 加进这个组合(只做结构、不动文件系统——落点若回报 MOVE,资源管理器会把源文件删掉而这边什么都没复制,等于丢文件,所以组合树上只回报 COPY);拖到面板上 = 复制 / 移动进该目录(同卷默认移动、跨卷自动复制,Ctrl 强制复制、Shift 强制移动,同名冲突自动改成 name (2))。内外部拖拽走同一条 OLE 路径,本窗口也注册成放置目标
  • 右侧面板布局可选:顶栏「▦ 布局」里选「一排(可拖宽)」或任意「X 行 × Y 列」网格;列数 / 行数各留 0 = 自动(给了行数就按 ⌈文件夹数 / 行数⌉ 算列数),面板多于格子时行数自动增长,绝不隐藏面板;网格每格等宽,一排布局下可拖分栏调宽;另加面板最小宽度与装不下时的横向滚动条
  • 卸载不再留空壳:删完安装目录里的文件后从来没试过删那个目录、也不报告——实测 --uninstall --silent 之后 %LOCALAPPDATA%\Programs\FolderDock 会剩一个空壳,用户看到的就是「卸载没卸干净」。根因是刚删掉的文件在 Windows 上会短暂处于「删除挂起」,目录要等句柄真正关闭才删得掉;现在空目录重试 20 次(每次 50 ms),仍不行就复用已有的临时副本收尾
  • 加 .verify/dist-run.ps1:把「静默装到临时目录 → 查落盘 / 数据目录指针 → 静默卸载 → 查有没有留残渣」固化成一条命令,指针文件走 FOLDERDOCK_POINTER_FILE 隔离,不碰真实工作区
  • 验证:72 单测 + clippy 零警告;dist.ps1 -Release 出 dist/FolderDock-0.2.0.zip;实跑分发物安装 exit=0(2 个文件 + 2 个快捷方式 + 登记到「应用和功能」)、卸载 exit=0(removed=2、registered=false、数据目录保留、安装目录已清空)

v0.1.0 — 2026-10-13 ​

首个发布版:可嵌套的组合树 + 多面板 Dock + 系统原生右键

  • 组合是一棵可嵌套的树:项目(顶层组合)→ 任意子组合 → 任意文件夹,深度不限;选中任意节点,主区域就把它子树里的全部文件夹按深度优先并排成面板(选项目根 = 看整个项目,选一个文件夹 = 只看那一个)。早先那版把组合当成「一层装几个文件夹」的扁平列表,这次按树重做,并带 v1 配置迁移——解析时必须先看顶层键(groups / projects)判断版本:新结构字段都带 serde(default),拿新结构去试解析 v1 文本会把未知键静默忽略,老配置会被读成空工作区再覆盖回去
  • 修「点文件夹不展示内容」:folder_leaves(node) 对文件夹节点必须返回它自己,早先只认组合,于是点文件夹等于点了一个空组合
  • 多面板 Dock:一个文件夹一个面板,可并排、拖分隔条调宽度、各自返回 / 上级 / 刷新 / 关闭;面板标题第二行是所属组合的面包屑
  • 系统原生右键菜单:文件与多选走 Windows 的 IContextMenu——不是自绘替代品,所以「打开方式」「发送到」「属性」以及 7-Zip、Git Bash 这类第三方扩展项都在;面板空白处是文件夹背景菜单(新建、粘贴、在此打开终端、属性)。原生菜单是阻塞模态的,弹菜单时挡住 UI 线程属预期行为
  • 搜索:后台增量索引(可取消)+ 模糊匹配 + 过滤语法,45k 条索引下单次查询约 6–7 ms
  • 设置页(顶栏 ⚙ 或 Ctrl+,):语言、主题(深 / 浅 / 跟随系统)、强调色、展示字体(枚举系统字体,217 个可选)、字号、界面密度、隐藏文件与 .gitignore 开关、数据保存位置——全部即时生效并落盘
  • 数据位置可配置:解析顺序 FOLDERDOCK_CONFIG_DIR → 指针文件(FOLDERDOCK_POINTER_FILE 可整体替换)→ 平台默认;在设置页改路径会当场把工作区搬过去
  • 安装器(folderdock-setup.exe,同一个二进制也是卸载器):可分别指定安装路径与数据路径、可建开始菜单与桌面快捷方式、登记到「应用和功能」,支持 --silent / --uninstall / --finish;卸载默认保留用户数据,只有 --purge-data 才连数据一起删
  • 三个卸载相关的坑都是实测踩过才定下来的:删安装目录要重试几秒(临时副本刚起来时原卸载器还没退,第一遍必然「拒绝访问」)、临时副本的工作目录必须挪出安装目录(Windows 不允许删任何进程的当前工作目录,否则安装目录剩一个空壳)、running_from 两边都要 canonicalize(Windows 会给路径加 \\?\ 前缀,只规范化一边则永远不相等)
  • i18n:所有展示文本走文案表(简体中文 / English),切语言连窗口标题一起变;英文槽里混 CJK 有测试钉住

获取方式 ​

本站不分发安装包;构建与打包方式见项目仓库的 README—— powershell -ExecutionPolicy Bypass -File scripts/dist.ps1 -Release 出 dist/FolderDock/(主程序 + 安装器 + README + LICENSE)与 dist/FolderDock-<版本>.zip,或邮件联系我。