Skip to content

feat(desktop): add native file handling and Explorer improvements - #269

Merged
ThisIs-Developer merged 24 commits into
ThisIs-Developer:mainfrom
Kechos23:codex/desktop-native-runtime-demo
Oct 31, 2026
Merged

ThisIs-Developer merged 24 commits into
ThisIs-Developer:mainfrom
Kechos23:codex/desktop-native-runtime-demo

Conversation

@Kechos23

@Kechos23 Kechos23 commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Latest UI refinements

  • Multi-file selection now offers Download, exporting the selected Markdown documents together as one ZIP.
  • Omit company metadata from both packaged EXEs; retain the application name, version and other metadata.
  • Use the existing open-folder icon for Open and Open all.
  • Removed the Phosphor document-icon artwork, generator, dedicated license asset, embedding and association resource. The official Markdown Viewer icon is retained.
  • Linked-file Rename shows the base name only and retains its original .md/.markdown extension on disk.

No manual tests were run for these requested changes. Existing rename automation was updated for the new extension-free input contract; the repository's configured CI runs automatically on push.

Purpose

Add opt-in Windows native file/folder drops with real paths and forward subsequent Markdown launches to the existing window. Explorer targets distinguish independent Vault copies from links to originals, while preserving open documents, internal moves and media imports. Shared web/desktop improvements add consistent drag feedback, inline rename and web folder downloads.

The branch includes v3.10.5/main at b14a2436; the Linked Workspace and safety prerequisites from #262/#279 are merged. Native runtime/client pins in the standard release remain unchanged. Standard Windows packaging now applies application branding using pinned packaging dependencies.

Changes

  • Restore native enter/over/leave feedback, shell drag imagery, file/folder/mixed icons, precise hover targets, invalid feedback, expansion and scrolling.
  • Route Vault drops to the selected folder or file's parent. Linked drops retain original disk paths and use existing sidebar grouping, without copying/moving originals into the hovered disk directory.
  • Simplify untargeted drops to names/type and Vault Workspace, then Linked Workspace. Cancellation adds nothing. Preserve media validation/consent and internal Explorer operations.
  • Support bounded web folder imports, complete directory batches, nested/empty folders, precise destinations and staged reads. Browsers that hide drag metadata use a neutral items icon until file/folder types become available.
  • Preserve session-only Private imports, encrypted Secret persistence, failure notices, recoverable drafts and workspace-change guards.
  • Rename files/folders inline, with full-name selection, Enter, Escape/blur and F2. Preserve editor drafts, validation and targets beyond the render budget.
  • Fix the reported rename appearance: keep the Explorer font size, row height and icons, and use a thin themed border instead of the default black browser outline. Verified in light/dark themes and the actual Windows EXE.
  • Rename linked originals on disk and update links/subsequent Save paths. Protect collisions, case-only renames and POSIX backslashes; retain drafts on failures. The experimental Windows move atomically refuses destination replacement.
  • Preserve folder rename across a background organization refresh; reject actual concurrent rename/move/removal instead of overwriting it.
  • Use Open in File Explorer, Open in Finder, or Open in File Manager for the original parent directory.
  • Add web Download folder ZIPs with nested/empty folders, current drafts, safe duplicate names and Secret-lock cancellation.
  • Set Windows ProductName/FileDescription, OriginalFilename and version correctly. Both window titles read Markdown Viewer. Keep the official M application icon; remove the requested third-party document-icon integration.
  • Keep Windows registration explicit, localized and per-user; never change UserChoice/defaults. The optional helper uses the official app icon for both the Markdown ProgID and application identity. Further Open-with discovery investigation is deferred at the maintainer's request.
  • Verify the complete runtime source against the pinned commit plus reviewed patch. Record source tree and hashes in provenance. Update all 15 locale catalogs and generated desktop resources.
  • Add no demo documents to the app. Exclude native acceptance fixture files from the downloadable package.

Windows executable

Download the Windows x64 package from the successful Windows build.

  • Application commit: c092cf8dea87d52f7474416cbd427781ed889824
  • Executable: Markdown-Viewer-PR269-c092cf8d-win_x64.exe
  • EXE SHA-256: 72091fa69dc9b31c0010fb1fbb6881bf3cd0fee4cc2d6566b7bddcc57d3d8f33
  • Helper SHA-256: b854294e76d6d2a260373631713e81eeff3234e52509c1ccba6f10dc08765f08
  • Version metadata: 3.10.5.0; application/window identity: Markdown Viewer
  • Separate trial application ID: com.markdownviewer.desktop.native-demo
  • Separate trial Vault: Documents/Markdown Viewer Native Demo Vault

The separate ID/Vault protects normal-release storage; the title and application presentation have no demo suffix. The self-contained EXE requires WebView2, as the standard app does. Close older trials first because trial copies share their Vault. Saving or renaming a Linked file changes its original.

The optional registration helper must remain beside the EXE in its chosen portable location. Markdown associations now use the official application icon. Explorer controls tooltip labels, dates and size; executable metadata supplies the correct name/version.

Validation

The existing Windows CI build runs automatically after each push. No manual tests were run for this refinement at the maintainer's request. Earlier browser and native evidence remains documented in the preceding review; those browser cases were not rerun for this update.

The final Windows build completed successfully. The downloaded app/helper match their provenance hashes. Read-only inspection confirms blank CompanyName fields, the existing application icon resource and no Phosphor text in the app binary.

The current Vercel preview and Docker build pass. CodeRabbit's final review is still pending.

Acceptance boundaries

No further reproducible defect was found in the reviewed/tested paths after the fixes. This supports review of the opt-in implementation, not unconditional enterprise release certification.

  • Physical Explorer OLE drag delivery, shell imagery and hover transitions remain a hands-on acceptance item for the final EXE; bridge/browser/native filesystem tests do not prove cross-window dragging.
  • The native runtime APIs still depend on unreleased upstream work. Standard packaging retains macOS (arm64/universal/x64) and Linux (arm64/armhf/x64) targets, but this PR explicitly gates the new native drop and single-instance hooks to Windows.
  • Static platform review also found existing POSIX filename limitations: linked path identity/parent helpers treat literal backslashes as separators, and folder scans reject colon/backslash entry names. The runtime's atomic no-overwrite move patch is Windows-specific. These paths were reviewed, not rewritten or tested on macOS/Linux; identical behavior or zero issues on those systems is not claimed.
  • Windows Application Control blocked a preceding unsigned build on the reviewed machine. No policy bypass was attempted. The final binary is also unsigned; native acceptance runs on the normal Windows CI runner and does not certify execution under that enterprise policy.
  • Open-with app-list discovery work is deferred as requested. There is no automatic registration or default-app change.

Build and behavior notes · Integration and browser limits

Contributor demonstrations

Single instance:

https://github.com/user-attachments/assets/af14e78c-ccf9-4ec5-b5da-a857dac867b4

Native drop:

https://github.com/user-attachments/assets/22e4f06f-3564-4604-adb3-5302e68c9f84

@vercel

vercel Bot commented Oct 4, 2026

Copy link
Copy Markdown

@Kechos23 is attempting to deploy a commit to the Developer Labs Team on Vercel.

A member of the Team first needs to authorize it.

@ThisIs-Developer ThisIs-Developer added the ✨ enhancement New feature, improvement, or usability enhancement. label Oct 5, 2026 — with ChatGPT Codex Connector
@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
markdown-viewer Ready Ready Preview Oct 31, 2026 6:55pm UTC
markdown-viwer Ready Ready Preview Oct 31, 2026 6:55pm UTC

@Kechos23

Copy link
Copy Markdown
Contributor Author

Hello @ThisIs-Developer, if you would like to evaluate these features together, I can point you to the custom Windows release used for our manual testing. It demonstrates single-instance file opening and native drag-and-drop with the choice between linking the original and creating a Workspace copy.

If you are comfortable maintaining a custom Neutralino build, this could also serve as an interim option while the upstream runtime changes are pending. However, it is not a maintenance-free alternative to updating Neutralino: security fixes and future runtime updates would still need to be incorporated and retested.

There is no expectation to adopt or distribute that runtime. Keeping this PR as a draft/demo until official support becomes available is equally reasonable.

@ThisIs-Developer

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

ThisIs-Developer

This comment was marked as outdated.

@ThisIs-Developer ThisIs-Developer changed the title feat(desktop): demo single instance and native Linked/Vault drops feat(desktop): add native file handling and Explorer improvements Oct 30, 2026
coderabbitai[bot]

This comment was marked as outdated.

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Hi @Kechos23! 👋

I've made quite a few updates to this PR, and I wanted to share the full list with you.

Most of the changes are related to your original vision for this PR. I've mainly focused on fixing issues, improving the existing functionality, and polishing the overall experience.

I've also included some additional Explorer and UI/UX improvements that I felt were needed. Rather than creating separate PRs for these smaller changes, I thought it would be better to address them together.

I'd really appreciate it if you could review all these changes, including the new features I've added.

Since this PR started with your vision, I genuinely value your feedback and suggestions. I want to make sure the changes align with what you originally intended and that the additional improvements make sense to you.

Please take your time reviewing everything. There's absolutely no rush. Feel free to point out anything you think should be changed, improved, or reconsidered. I'm happy to make further adjustments based on your feedback.

Once you've reviewed everything and we're both happy with the result, I'd like to merge this PR and move forward with the next improvements.

Thanks again for your time! 🙌

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Here's a summary of everything I've updated:

1. Main Changes (Related to Your PR Vision)

  • Fixed native drag-and-drop issues with files, folders, images, GIFs, and videos.
  • Restored drag-and-drop animations, visual feedback, and file/folder icons.
  • Restored precise drop targets inside Explorer, including folder highlighting, expansion, and scrolling.
  • Fixed incorrect drop destinations between Vault and Linked Workspace.
  • Added folder drag-and-drop support to the web version, including nested and empty folders.
  • Improved Private and Secret Workspace data safety.
  • Improved Windows integration, application branding, and file associations.

2. Additional Changes (Explorer & UI/UX)

  • Added inline file and folder renaming with improved input styling to match Explorer.
  • Improved linked-file renaming while preserving original file extensions.
  • Added downloading multiple selected Markdown files together as a ZIP.
  • Added downloading entire folders as ZIP files, including nested and empty folders.
  • Updated Open, Open all, and New file icons for consistency.
  • Fixed disabled Sync button styling.

@Kechos23 Kechos23 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hi @ThisIs-Developer,

Thanks for the updates! I reviewed the latest changes with assistance from Codex, focusing on data safety and recovery. Two points came up:

  1. Secret Workspace — saving while locking: an import can queue another save while locking is still in progress. That queued save may run after the unlocked documents have been removed from memory and interpret the empty workspace as deletions. The underlying save/lock behavior already exists in main; the new import flows provide another way to encounter it.

  2. Linked-file rename — interrupted operation: the original is renamed before the updated link is persisted. A crash or lost native response between those steps can leave the workspace pointing to the old path. The file itself remains intact, so I consider this a lower-priority recovery improvement.

These findings were reproduced in controlled simulations using the relevant application functions, rather than through the packaged EXE. In particular, the Secret Workspace scenario deserves confirmation in the full application.

The proposed fixes are in the inline suggested-change comments, together with the reasoning and validation cases. Please review and adapt them as appropriate.

Another idea I've been considering is an explicit “Open in new window” option for opening a file in a second window when desired, while keeping the current single-instance behavior by default. Handling shared workspace state, drafts and concurrent edits safely could make this a substantial addition, so it would probably be better explored later in a separate PR. I'd be interested in your feedback on whether this would be useful and how you would approach it.

Comment thread script.js
let linkedSourceMonitoringChain = Promise.resolve();
const linkedSourceSavePaths = new Set();
let linkedReadEpoch = 0;
let explorerRename = null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Secret Workspace: coordinate locking with queued saves and imports

This is pre-existing shared save/lock behavior, exposed by the new asynchronous import flows, rather than a regression introduced solely by this PR.

Controlled sequence with the current application functions and an in-memory storage double:

  1. Start locking; hold encryption of an existing secret document.
  2. Complete another import and queue its encrypted flush.
  3. Release the first save. Lock removes the unlocked tabs.
  4. The queued save then reads an empty payload, deletes the existing record, and commits documentCount: 0.

Proposed coordinated fix — do not apply the declaration below on its own. The shared functions below are outside this PR's changed hunks, so I am including their required edits explicitly rather than pretending this one suggestion fixes everything.

Suggested change
let explorerRename = null;
let explorerRename = null;
let secretWorkspaceLockInProgress = false;

Required companion changes in script.js:

  • In enqueueSecretWorkspaceSave, revalidate the captured key inside the queued callback, at each conflict retry, and again after asynchronous encryption immediately before applySecretRecordChanges:
if (!isSecretWorkspaceUnlocked() || secretWorkspaceKey !== key) return false;
  • In lockSecretWorkspace, synchronously set the lock-in-progress flag before awaiting the flush. Preserve/restore the app container's previous inert state in finally; aborting a flush must keep the workspace unlocked and its documents intact. The existing lock body belongs inside the try:
if (!isSecretWorkspaceUnlocked() || secretWorkspaceLockInProgress) return;
secretWorkspaceLockInProgress = true;
const container = document.querySelector('.app-container');
const previousInert = Boolean(container && container.inert);
if (container) container.inert = true;
try {
  // Existing save/flush/remove-tabs/clear-key lock body.
} finally {
  secretWorkspaceLockInProgress = false;
  if (container) container.inert = previousInert;
}
  • In createImportedDocument, refuse Secret imports while locking:
if (targetLocation.workspaceId === SECRET_WORKSPACE_ID &&
    (secretWorkspaceLockInProgress || !isSecretWorkspaceUnlocked())) return null;
  • Apply the same lock-in-progress check to the Secret target checks in both browser handleDrop.canApply and native processNativeDrop.canApply, so an in-progress folder import cancels before adding more items. Retain the existing encrypted flush on successful completion.

The core guard/lock draft passed four isolated regression checks: lock + concurrent import + queued save retains existing records; failed encryption retains documents and restores controls; an old queued save cannot enter a new unlock session; a session change during encryption cancels before storage mutation. These used the actual extracted functions with controlled storage/crypto doubles, not the EXE. Please also verify actual browser/native imports, Private mode, lock failure, and lock/unlock before accepting the coordinated changes, and regenerate the desktop resources from the root source.

Comment thread script.js Outdated
await workspaceStorage._desktopCheckMovePaths(source, destination);
if (!tabs.includes(tab) || tab.sourcePath !== source) throw new Error('Link changed');
captureLiveLinkedDraft(tab);
await Neutralino.filesystem.move(source, destination);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Linked rename: preserve durable intent before the external filesystem mutation

With a simulated native response loss after a successful disk rename, move rejects and the metadata update below never runs: the file is at the new path, while both the live and persisted link still point to the old path. A process interruption at the same boundary leaves the same recovery gap. This does not delete the original content.

Suggested recovery change: treat this as a coordinated write-ahead/recovery feature, rather than adding a catch that guesses success:

  1. Before filesystem.move, commit and verify the current draft plus a rename-intent record containing the document ID, old/new paths and a source identity/content fingerprint. Abort before touching the original if that durable commit fails or persistence is unavailable (including Private mode).
  2. Recheck the source/link and destination after that asynchronous commit; then perform the existing no-overwrite move.
  3. Persist the new linked metadata before clearing the intent.
  4. On startup or an uncertain native response, inspect the saved intent without replaying the move. Repair the link only when the outcome can be established safely. Both paths present, neither path present, unreadable/changed content, case aliases or a destination already linked elsewhere must remain an explicit recovery decision. Never automatically overwrite, delete or roll back an external file.

Do not reuse the current Vault move-recovery branch unchanged: it is deliberately scoped to paths inside the managed Vault, whereas these originals are external. Recovery records also need validation and must not cause restored/imported backups to silently reconnect external paths.

Validation cases: crash before move, crash after move/before metadata commit, lost response after a successful move, metadata-save failure, occupied destination, case-only rename, and newer local/external edits. Preserve draft bytes and both originals in every ambiguous case.

This is a proposed recovery protocol, not a tested drop-in implementation; I have not fabricated a one-click code patch for the startup/storage work. The failure sequence was reproduced in a controlled simulation, while the full recovery feature still needs implementation and EXE validation.

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Hi @Kechos23,

I saw the inline suggestions and clicked Apply changes, but I don't think anything actually changed.

Could you please check whether the suggestions were applied successfully? If not, could you please implement the fixes for both issues you identified and submit them?

Regarding Open in new window, could you elaborate a little more on how you envision it working? For example, would the new window display only the selected document, or would other documents and workspaces also be accessible? How would synchronization between windows work?

I think we need to consider these aspects carefully. It sounds like a useful feature, but I believe it would be better to explore it separately in a future PR.

Thank you!

Copy link
Copy Markdown
Contributor Author

Hi @ThisIs-Developer,

Thank you for all the time you've put into reviewing my PRs and for the fixes, additions and polish you've contributed. I really appreciate the care you're giving this work.

You were right: the earlier one-click suggestion only added the guard variable; the accompanying instructions required additional implementation. Sorry for the confusion.

I've now implemented both fixes and pushed them to this PR as separate commits:

  • 04a3fc8 — Prevent stale queued Secret Workspace saves from treating locked documents as deletions. Imports are cancelled when locking begins, and a failed flush leaves the documents open.
  • 5d263c1 — Persist and verify the draft and rename intent before changing an original. Recovery repairs a verified link without replaying the move; ambiguous cases retain the evidence and offer Resolve interrupted rename…. The draft can also be retained as a Vault copy. Original renames are blocked in Private mode because durable recovery is paused.

Validation passed: 249 unit tests and 234 Chromium tests, including simulated interruption/restart, lost replies, storage failures and actual temporary Windows filesystem checks. This does not replace hands-on acceptance of the packaged EXE. The existing CI build has been triggered.

Regarding Open in new window, my initial thought is an explicit action on a selected document, while normal launches continue using the existing window. I haven't settled whether the second window should expose the full workspace or just that document. Shared workspace state, separate drafts and concurrent saves need careful design. The idea came to mind for dual-monitor setups, where users might want several documents open and editable at the same time across both screens. I'll think through the behavior more carefully and come back to it in the future.

On a separate note, I've also done some initial exploration related to #280, which I can share there whenever you're ready to revisit it—no rush.

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Hi @Kechos23,

Thank you for looking into the issues and implementing the fixes! I believe everything is now resolved, so I'll go ahead and merge the PR.

Thanks again for your time and valuable contribution! The changes will be available in the desktop version soon. 🚀

@ThisIs-Developer
ThisIs-Developer merged commit 6c00002 into ThisIs-Developer:main Oct 31, 2026
5 checks passed

This branch was successfully deployed

1 active deployment
Preview — 5d263c13 Deployed Oct 31, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ enhancement New feature, improvement, or usability enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants