Skip to content

Add file library exclusion globs - #24

Merged
FernandoAbishai merged 2 commits into
mainfrom
feature/file-library-exclude-globs
Oct 12, 2026
Merged

FernandoAbishai merged 2 commits into
mainfrom
feature/file-library-exclude-globs

Conversation

@FernandoAbishai

Copy link
Copy Markdown
Member

Summary

  • add renderer-only relative exclusion globs for Files, Articles and Open Quickly
  • keep the raw host file tree and filesystem authority unchanged
  • preserve the active/revealed document and its ancestor branch even when matched
  • leave Search in Folder intentionally unfiltered over the full authorized folder

Safety boundary

  • persists pattern text only in existing renderer preferences; no folder paths or grants are persisted
  • no Electron/native IPC or filesystem-authority changes
  • filtering is presentation/library visibility, not a security boundary

Validation

  • focused: file-tree filters + preferences + navigation UI: 15/15 PASS
  • npm run verify: 27 suites / 130 tests PASS
  • clean-room, Electron syntax, TypeScript, build and native smokes PASS
  • runtime audit unchanged: 0 critical/high/moderate, 3 low
  • existing jsdom CodeMirror measurement stderr and Vite large-chunk warning remain pre-existing

Independent read-only review is running on exact head c3ff50d.

Copilot AI balanced review requested due to automatic review settings October 12, 2026 02:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T02:10:59.545995Z c3ff50d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3ff50d89f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/App.tsx
</div>
<div className="workspace">
<Sidebar visible={sidebarVisible} tab={sidebarTab} onTabChange={setSidebarTab} outline={outline} outlineDocumentKey={activeDocumentId} activeOutlineSlug={activeOutlineSlug} outlineMode={preferences.outlineMode} outlineMaxLevel={preferences.outlineMaxLevel} fileTree={fileTree} currentFilePath={filePath} revealFilePath={fileReveal?.path ?? null} revealRequest={fileReveal?.request ?? 0} onOpenFile={(path) => void loadFile(path)} onRevealEntry={(node) => void revealFolderEntryInFinder(node)} onHeadingClick={scrollToHeading} onRequestFocusEditor={() => editorRef.current?.focus()} folderPath={folderPath} onCreateEntry={beginCreateFolderEntry} onRenameEntry={beginRenameFolderEntry} onTrashEntry={(node) => void trashFolderEntry(node)} onRefreshFolder={() => { if (folderPath) void refreshFolder(folderPath) }} />
<Sidebar visible={sidebarVisible} tab={sidebarTab} onTabChange={setSidebarTab} outline={outline} outlineDocumentKey={activeDocumentId} activeOutlineSlug={activeOutlineSlug} outlineMode={preferences.outlineMode} outlineMaxLevel={preferences.outlineMaxLevel} fileTree={visibleFileTree} currentFilePath={filePath} revealFilePath={fileReveal?.path ?? null} revealRequest={fileReveal?.request ?? 0} onOpenFile={(path) => void loadFile(path)} onRevealEntry={(node) => void revealFolderEntryInFinder(node)} onHeadingClick={scrollToHeading} onRequestFocusEditor={() => editorRef.current?.focus()} folderPath={folderPath} onCreateEntry={beginCreateFolderEntry} onRenameEntry={beginRenameFolderEntry} onTrashEntry={(node) => void trashFolderEntry(node)} onRefreshFolder={() => { if (folderPath) void refreshFolder(folderPath) }} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear selections hidden by an exclusion change

When a user selects a directory or image and then adds a glob that excludes it, visibleFileTree removes the row but Sidebar retains the node in its local selectedNode state. The toolbar therefore remains enabled with no visible selection, and Create, Rename, Reveal, or Move to Trash still operates on that hidden stale path; in particular, clicking the trash action can remove an item the user can no longer see. Clear the selection whenever its path is absent from the newly filtered tree.

Useful? React with 👍 / 👎.

Comment on lines +48 to +51
.split(/\r?\n/)
.slice(0, 100)
.map((line) => normalizePattern(line).slice(0, 256))
.filter(Boolean)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count only nonempty patterns toward the glob limit

When the preference contains blank separator lines, the 100-line limit is applied before normalization and empty-line removal, so those blanks consume pattern slots and valid globs later in the textarea are silently ignored. For example, 50 patterns separated by blank lines already exhaust the limit before any subsequent entries are compiled, causing entries the user explicitly excluded to remain visible. Filter empty normalized lines before taking the first 100 patterns.

Useful? React with 👍 / 👎.

Comment on lines +52 to +55
.map((pattern) => ({
basenameOnly: !pattern.includes('/'),
expression: new RegExp(`^${globSource(pattern)}$`)
}))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Compile single-character globs as Unicode-aware

For filenames containing a non-BMP character such as an emoji, ? does not behave as a single-character wildcard because the generated regex is compiled without the Unicode flag and [^/] consumes only one UTF-16 surrogate. Consequently, a documented pattern such as ?.md fails to exclude 😀.md even though it contains one user-visible character. Compile the expression in Unicode mode so the wildcard consumes one code point.

Useful? React with 👍 / 👎.

@FernandoAbishai
FernandoAbishai merged commit ef491f8 into main Oct 12, 2026
2 checks passed
@FernandoAbishai
FernandoAbishai deleted the feature/file-library-exclude-globs branch October 12, 2026 02:11
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.

2 participants