Skip to content

feat: add import directory button to sidebar header#5

Open
Roganic wants to merge 138 commits into
huanghao:mainfrom
Roganic:feat/import-dir-button-v2
Open

feat: add import directory button to sidebar header#5
Roganic wants to merge 138 commits into
huanghao:mainfrom
Roganic:feat/import-dir-button-v2

Conversation

@Roganic
Copy link
Copy Markdown

@Roganic Roganic commented Apr 10, 2026

Summary

Adds a folder icon button in the top-left sidebar header (next to the MD Viewer logo) that opens the existing "Add Workspace" dialog.

Before: the only way to import a directory was to switch to the workspace view (焦点/全量 tab) and find the + button there — not obvious for new users.

After: a small folder icon sits in the header, always visible regardless of which sidebar tab is active.

Changes

  • src/client/html.ts: add .import-dir-btn button inside <h1>, calls showAddWorkspaceDialog() which is already exposed on window by sidebar-workspace.ts
  • src/client/css.ts: style the button — 26×26px, transparent background, hover state consistent with existing toolbar icon buttons; margin-left: auto pushes it to the far right of the header row

No new logic or API changes — the dialog, path autocomplete, and workspace scan flow are fully reused.

Test plan

  • Click the folder icon in the sidebar header → "添加工作区" dialog opens
  • Works in all three sidebar tabs (焦点 / 全量 / 列表)
  • Enter a directory path, confirm → workspace is added and sidebar switches to workspace view
  • Button hover state looks consistent with other icon buttons

🤖 Generated with Claude Code

huanghao and others added 30 commits March 3, 2026 19:06
feat(annotation): 添加圈点批注功能
## 问题
1. iTerm2 环境中 PATH 不包含 ~/.bun/bin,导致找不到 mdv 命令
2. mdv 脚本依赖 `#!/usr/bin/env bun`,在受限环境中无法执行
3. dispatcher 脚本退出码处理不明确
4. 调试日志污染 /tmp/my.log

## 修复
1. **dispatcher 脚本** (scripts/mdv-iterm2-dispatcher.sh)
   - 移除硬编码路径和调试日志
   - 添加结构化的调试日志(时间戳格式)
   - 直接查找 bun 和 mdv 的完整路径(支持多个可能位置)
   - 使用 `bun run script.ts` 方式调用,不依赖 PATH
   - 显式 `exit 0` 确保退出码正确

2. **CLI 退出码** (src/cli.ts)
   - 成功时显式调用 `process.exit(0)`

3. **检查脚本** (scripts/check-iterm2-setup.sh)
   - 更新为检查 ~/.bun/bin 而不是 ~/bin
   - 使用 `command -v` 动态查找命令

4. **简化安装** (package.json)
   - 移除不需要的 postinstall 脚本
   - 通过 bin 字段自动安装所有命令

5. **文档**
   - 更新设计文档,反映实际安装方式
   - 添加修复报告和退出码问题详解
   - 创建快速配置指南

## 测试
✅ 在受限 PATH 环境下测试通过(模拟 iTerm2)
✅ 所有路径格式正确解析(绝对、相对、basename)
✅ 退出码始终为 0
✅ 用户实际 iTerm2 环境验证通过

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
调试日志已注释,需要时可以取消注释启用。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 在 tabs 按钮上显示当前打开的文件总数
- 提取 tab 批量操作逻辑到独立的 tab-batch.ts 工具模块
- 优化 tabs 渲染性能,避免不必要的 DOM 重建
- 修复 tabs 滚动位置保持问题

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 方案概述
通过 Bun 编译为自包含二进制,使用 Homebrew 分发

## 核心特性
- ✅ 完全自包含(不需要 bun/node 运行时)
- ✅ 跨平台支持(macOS Intel/ARM, Linux x64/ARM64)
- ✅ 一键安装(brew install md-viewer)
- ✅ 自动更新(brew upgrade md-viewer)
- ✅ 只依赖系统自带库

## 文件大小
- CLI 工具: ~58MB
- 包含完整 Bun 运行时和所有依赖

## 实施计划
- Week 1: 基础架构(静态资源、路径处理)
- Week 2: 打包与分发(构建脚本、Formula)
- Week 3: 自动化(CI/CD、GitHub Actions)
- Week 4: 测试与发布

## 工具
- 添加 scripts/test-compile.sh 用于测试编译功能

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## 问题
为什么 Bun 编译的二进制这么大(58MB),而 Go 只有 2MB?

## 对比测试
- C: 16KB (优化后)
- Rust: 300KB
- Go: 1.6MB
- Bun: 58MB

## 根本原因
Bun 58MB = 完整的 JavaScript 运行时
├── JavaScriptCore 引擎 (40MB) - 4层JIT编译器
├── Node.js API 兼容层 (10MB) - 40+个模块
├── 内置工具 (5MB) - 包管理/打包/测试
└── 原生依赖 (3MB) - SQLite/压缩/加密

## 对比分析
- Go: 简单GC + 静态类型 = 2MB
- Rust: 零运行时 + 编译时检查 = 300KB
- Bun: 完整JS引擎 + JIT + 兼容层 = 58MB

## 结论
对于 md-viewer:
✅ 58MB 是合理的代价
✅ 用户体验优先(一键安装、快速启动)
✅ 开发效率高(TypeScript + JS生态)
⚠️ 在文档中说明大小原因

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
核心方案:
- 单一二进制 mdv(TypeScript 编译,60MB)
- 统一 CLI:mdv server/open/config/stats
- 前端资源嵌入
- 5 个实施 Phase

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Homebrew distribution support
- Create unified CLI (mdv command)
- Embed frontend resources (client.js, CSS, favicon)
- Add server management (foreground/daemon mode)
- Add operational commands (stats, cleanup, logs)
- Add comments management commands
- Create build and packaging scripts
- Setup GitHub Actions for multi-platform builds
- Add comprehensive documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move Formula to dedicated tap repo (huanghao/homebrew-tap)
- Update installation instructions (brew tap huanghao/tap)
- Add sync-formula-to-tap.sh script for automation
- Update all documentation references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change macos-13 to macos-13-xlarge for x64 builds
- Add fail-fast: false to continue building other platforms on failure
- Add BUN_TARGET environment variable for cross-compilation
- Update build-all.sh to support --target flag
- Update package.sh to accept platform parameter
- Add --frozen-lockfile to bun install for reproducible builds
- Improve server detection in cli.ts with HTTP reachability check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove --frozen-lockfile flag to allow lockfile updates
- Change macos-13-xlarge to macos-13 (standard Intel runner)
- Use bun-darwin-x64-baseline target for better compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add retry logic for bun install to handle transient network errors
- Use macos-latest for darwin-x64 with cross-compilation instead of macos-13
- This avoids the 'macos-13-us-default' configuration error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Disable errexit during retry loop
- Re-enable errexit after successful install
- This allows retries to work properly in GitHub Actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Increase retry attempts from 3 to 5
- Verify critical packages (esbuild, typescript) are actually installed
- Clean node_modules between retries
- Increase sleep time to 10 seconds
- Add final verification check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Node.js setup with npm cache
- Try bun install first, fall back to npm if it fails
- Use npm (more reliable in CI) as fallback
- Simplify retry logic with explicit fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace bun install with npm ci (more reliable in CI)
- npm ci uses package-lock.json for reproducible builds
- Avoid network issues with bun's registry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
npm ci requires package-lock.json to be in sync, use npm install for flexibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
package-lock.json contains internal registry URLs (sankuai.com)
that are not accessible from GitHub Actions. Force official registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove internal registry URLs (sankuai.com) from package-lock.json
to make CI builds work on GitHub Actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Artifacts are downloaded flat, not in subdirectories.
Fix SHA256 calculation to handle both structures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Avoid shell glob expansion issues by checking file type directly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add packages/*.tar.gz to handle flat artifact downloads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
huanghao03 and others added 26 commits April 6, 2026 20:44
Update renderWorkspaceSidebar to reference state.config.sidebarTab ('focus' | 'full' | 'list')
instead of the deprecated state.config.sidebarView.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s with tree-item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…m styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… tags

- Add markdownTheme and codeTheme fields to AppConfig interface
- Add corresponding defaults (both set to 'github')
- Add id attributes (theme-md-css, theme-hl-css) to style tags for dynamic theme switching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a folder icon button in the top-left sidebar header (next to the
MD Viewer logo) that opens the existing "Add Workspace" dialog.

Previously the only way to import a directory was to switch to the
workspace view (focus/full tab) and find the "+" button there. This
change makes directory import accessible from any sidebar mode without
requiring a tab switch.

Implementation:
- html.ts: add .import-dir-btn button inside <h1>, calls
  showAddWorkspaceDialog() which is already wired to window by
  sidebar-workspace.ts
- css.ts: style the button — transparent background, 26×26px,
  hover state matches existing icon button patterns; margin-left:auto
  pushes it to the far right of the h1 row

No new logic or API changes needed; the dialog and workspace scan
flow are fully reused.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an "Import Directory" button to the MD Viewer header, including its HTML structure and CSS styling. The review feedback focuses on improving the button's visual consistency with existing UI elements by adjusting the border radius and transitions, as well as enhancing accessibility for screen readers by adding an aria-label.

Comment thread src/client/css.ts
Comment on lines +64 to +83
.import-dir-btn {
margin-left: auto;
display: flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
padding: 0;
border: none;
border-radius: 5px;
background: transparent;
color: #57606a;
cursor: pointer;
flex-shrink: 0;
transition: background 0.15s, color 0.15s;
}
.import-dir-btn:hover {
background: #e8eaed;
color: #24292e;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with other interactive elements in this repository, the border-radius should be 6px and the transition should explicitly use background-color with the ease timing function. Additionally, adding an :active state with a slight scale effect would match the behavior of other buttons in the UI (like the copy buttons).

    .import-dir-btn {
      margin-left: auto;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 26px;
      height: 26px;
      padding: 0;
      border: none;
      border-radius: 6px;
      background: transparent;
      color: #57606a;
      cursor: pointer;
      flex-shrink: 0;
      transition: background-color 0.15s ease, color 0.15s ease;
    }
    .import-dir-btn:hover {
      background: #e8eaed;
      color: #24292e;
    }
    .import-dir-btn:active {
      transform: scale(0.95);
    }

Comment thread src/client/html.ts
Comment on lines +73 to +77
<button
class="import-dir-btn"
onclick="showAddWorkspaceDialog()"
title="导入目录"
>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To ensure accessibility for screen readers and maintain consistency with other icon-only buttons in the sidebar (such as the annotation density and filter toggles), please add an aria-label attribute to this button.

Suggested change
<button
class="import-dir-btn"
onclick="showAddWorkspaceDialog()"
title="导入目录"
>
<button
class="import-dir-btn"
onclick="showAddWorkspaceDialog()"
title="导入目录"
aria-label="导入目录"
>

zhaoyang79 and others added 2 commits April 10, 2026 20:15
On macOS, clicking the import button now opens a native Finder folder
picker (via osascript) instead of a text input dialog.

- handlers.ts: add handlePickDirectory — spawns osascript to show the
  system folder chooser, returns { path } on confirm or { cancelled }
  on dismiss
- server.ts: register POST /api/pick-directory
- sidebar-workspace.ts: showAddWorkspaceDialog now calls the API first;
  on success it adds the workspace directly; on cancel it does nothing;
  on error (non-macOS or API failure) it falls back to the text dialog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…all)

Right-clicking any tab now shows a native-style context menu with three
actions:

- 关闭当前 — closes the tab that was right-clicked
- 关闭其他 — closes every tab except the one right-clicked (uses that
  tab as the pivot, not necessarily the active tab)
- 关闭所有 — closes all open tabs

Implementation:
- sidebar.ts: showTabContextMenu() builds and positions a fixed-overlay
  menu element, wires click handlers, and auto-dismisses on any outside
  click/contextmenu; applyTabBatchAction gains an optional pivotPath
  param so "close-others" works correctly from the context menu
- css.ts: .tab-context-menu / .tab-context-item styles, matching the
  app's existing GitHub-inspired design language

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants