cherry-studio icon indicating copy to clipboard operation
cherry-studio copied to clipboard

feat: Support relative paths for notes working directory with backup support

Open Copilot opened this issue 3 months ago • 4 comments

What this PR does

Before this PR:

  • Notes working directory required absolute paths
  • Users syncing via WebDav needed to reconfigure paths on each device due to different absolute paths across systems
  • Default notes path was stored as absolute path
  • Notes in custom locations outside the Data folder were not included in backups

After this PR:

  • Supports relative paths: ~/Notes, ./Notes, ../Notes
  • Default notes path returns relative path ./Data/Notes for better portability
  • Paths are expanded to absolute on-demand during file operations
  • Original path format preserved in storage for portability
  • Externally selected paths (via folder picker) remain absolute
  • Backup and restore now handles notes in custom locations - Notes are always backed up regardless of configured path

Fixes #11221

Why we need it and why it was done in this way

Problem: WebDav sync users have different absolute paths per device (C:\Users\Alice\Notes vs /home/alice/Notes), requiring manual reconfiguration. Additionally, notes configured outside the default Data folder were not being backed up, risking data loss.

Solution: Store paths in original format, expand to absolute when needed, and intelligently backup/restore notes:

// New utility handles expansion
export function expandNotesPath(pathString: string, basePath?: string): string {
  let expandedPath = untildify(pathString)  // ~/Notes -> /home/user/Notes
  if (path.isAbsolute(expandedPath)) return path.normalize(expandedPath)
  
  const base = basePath || app.getPath('userData')
  return path.normalize(path.resolve(base, expandedPath))
}

// Default path now returns relative
export function getNotesDir() {
  const notesDir = path.join(app.getPath('userData'), 'Data', 'Notes')
  if (!fs.existsSync(notesDir)) {
    fs.mkdirSync(notesDir, { recursive: true })
  }
  return './Data/Notes'  // Relative for portability
}

// Absolute version for internal use
export function getNotesDirAbsolute() {
  return path.join(app.getPath('userData'), 'Data', 'Notes')
}

// Applied in file operations
const expandedPath = expandNotesPath(dirPath)
const stats = fs.statSync(expandedPath)

// Backup logic intelligently handles notes location
const expandedNotesPath = expandNotesPath(notesPath)
if (isOutsideDataFolder(expandedNotesPath)) {
  // Backup notes separately to Notes folder
  await backupNotesDirectory(expandedNotesPath)
}

The following tradeoffs were made:

  • Relative paths resolve against userData directory by default (predictable, consistent across devices)
  • Path expansion happens on every file operation (simple, stateless, no caching needed)
  • Default path is relative while folder picker selections remain absolute (best of both worlds)
  • Backup parses configuration data to determine notes location (ensures complete backups)

The following alternatives were considered:

  • Store both original and expanded paths: rejected for data duplication and sync complexity
  • Global path resolver service: rejected for unnecessary abstraction
  • Always convert to absolute: rejected as it breaks multi-device sync portability
  • Only backup Data folder: rejected as it would lose notes in custom locations

Breaking changes

None. Absolute paths continue to work unchanged. Existing configurations with absolute paths will continue to function normally and will now be properly backed up and restored.

Special notes for your reviewer

  • expandNotesPath tested with 8 test cases covering tilde, relative, absolute, edge cases
  • getNotesDir and getNotesDirAbsolute tested to ensure correct behavior
  • UI change: removed readOnly from path input to allow manual entry
  • Localization updated across en-us, zh-cn, zh-tw with examples
  • FileStorage updated to use getNotesDirAbsolute() for internal operations requiring absolute paths
  • BackupManager enhanced: Parses notes path from backup data, creates separate Notes folder in backup for external notes, restores notes to configured location

Checklist

  • [x] PR: The PR description is expressive enough and will help future contributors
  • [x] Code: Write code that humans can understand and Keep it simple
  • [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule)
  • [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required
  • [x] Documentation: A user-guide update was considered and is present (link) or not required. You want a user-guide update if it's a user facing feature.

Release note

Notes working directory now supports relative paths like `~/Notes` or `./Data/Notes` for easier multi-device synchronization. Default notes path is now stored as relative path for better portability across devices. Backup and restore functionality now correctly handles notes in custom locations, ensuring notes are never lost regardless of configured path.
Original prompt

This section details on the original issue you should resolve

<issue_title>[Feature]: The working directory of notes supports relative directories</issue_title> <issue_description>> [!NOTE]

This issue/comment/review was translated by Claude.

Issue Checklist

  • [x] I understand that issues are for reporting problems and requesting features, not for off-topic comments, and I will provide as much detail as possible to help resolve the issue.
  • [x] I have checked the pinned issues and searched through the existing open issues, closed issues, and discussions and did not find a similar suggestion.
  • [x] I have provided a short and descriptive title so that developers can quickly understand the issue when browsing the issue list, rather than vague titles like "A suggestion" or "Stuck."
  • [x] The latest version of Cherry Studio does not include the feature I am suggesting.

Platform

Windows

Version

v1.6.5

Is your feature request related to an existing issue?

When I use WebDav for multi-device data synchronization, the working directory of the note-taking function will also be synchronized. However, the working paths of the note-taking feature are inconsistent between my different devices, causing me to need to modify the working directory every time I sync.

Desired Solution

The working directory of notes can be compatible with relative directories to solve the problem of path inconsistency when using multiple devices simultaneously.

Alternative Solutions

No response

Additional Information

No response


Original Content

当我使用 WebDav 进行多设备数据同步时,笔记功能的工作目录也会一并同步。然而,我的不同设备之间笔记功能的工作路径不一致,导致我每次同步时都需要修改工作目录。

笔记的工作目录可以兼容相对目录,以解决多设备同步使用时的路径不一致问题

Comments on the Issue (you are @copilot in this section)

  • Fixes CherryHQ/cherry-studio#10995

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot avatar Nov 12 '25 08:11 Copilot

[!NOTE] This issue/comment/review was translated by Claude.

The default notepath supports relative paths. If the notepath is selected from external sources, it still uses absolute paths for backup @copilot


Original Content 默认的notepath支持相对路径,如果从外部选择的notepath最后还是用绝对路径来备份 @copilot

DeJeune avatar Nov 12 '25 09:11 DeJeune

[!NOTE] This issue/comment/review was translated by Claude.

Implemented. Now:

  1. Default path: getNotesDir() returns relative path ./Data/Notes for easy multi-device synchronization
  2. External selection: Paths selected through folder picker remain as absolute paths (default behavior of OS dialog)
  3. Internal use: Added getNotesDirAbsolute() for file operations that require absolute paths

This way when users sync settings via WebDav, the default path can be correctly resolved to each device's respective userData directory.

Commit: 6493f18


Original Content

[!NOTE] This issue/comment/review was translated by Claude. ...

已实现。现在:

  1. 默认路径getNotesDir() 返回相对路径 ./Data/Notes,便于多设备同步
  2. 外部选择:通过文件夹选择器选择的路径保持为绝对路径(操作系统对话框的默认行为)
  3. 内部使用:添加了 getNotesDirAbsolute() 用于需要绝对路径的文件操作

这样用户通过 WebDav 同步设置时,默认路径在所有设备上都能正确解析到各自的 userData 目录。

Commit: 6493f18

Copilot avatar Nov 12 '25 09:11 Copilot

[!NOTE] This issue/comment/review was translated by Claude.

@copilot The backup didn't include notes


Original Content

@copilot 备份的时候没有带上notes

DeJeune avatar Nov 12 '25 10:11 DeJeune

[!NOTE] This issue/comment/review was translated by Claude.

Fixed. Now the backup logic will:

  1. Detect notes path configuration: Parse notes path from backup data
  2. Smart backup:
    • If notes are in default location (./Data/Notes or {userData}/Data/Notes), backup with Data directory ✓
    • If notes are in external location (like ~/MyNotes), backup separately to Notes folder ✓
  3. Correct restore: When restoring, notes will be restored to the configured path location

This ensures complete backup and restore regardless of where notes are configured.

Commit: 4269a32


Original Content

[!NOTE] This issue/comment/review was translated by Claude. ...

已修复。现在备份逻辑会:

  1. 检测notes路径配置:从备份数据中解析notes路径
  2. 智能备份
    • 如果notes在默认位置(./Data/Notes{userData}/Data/Notes),随Data目录一起备份 ✓
    • 如果notes在外部位置(如~/MyNotes),单独备份到Notes文件夹 ✓
  3. 正确恢复:恢复时会将notes恢复到配置的路径位置

这样无论notes配置在哪里,都能确保完整备份和恢复。

Commit: 4269a32

Copilot avatar Nov 12 '25 10:11 Copilot