Skip to content

chore: sync Acode main changes (ef7f3265..6962af1e) - #29

Open
bajrangCoder wants to merge 14 commits into
Acode-Foundation:mainfrom
bajrangCoder:chore/sync-acode-main-b08fd0bf
Open

bajrangCoder wants to merge 14 commits into
Acode-Foundation:mainfrom
bajrangCoder:chore/sync-acode-main-b08fd0bf

Conversation

@bajrangCoder

@bajrangCoder bajrangCoder commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Syncs the commits that landed on Acode-Foundation/Acode main from ef7f3265 up to 6962af1e. Each one was cherry-picked with -x, so the original SHA is recorded in the commit message.

Upstream Commit
d755c315 fix: prevent crash when opening file:// links from LSP tooltips (Acode-Foundation/Acode#2977)
579af33f update: es-sv (Acode-Foundation/Acode#2974)
5323b587 feat(modes): let plugin modes reuse another mode's formatter (Acode-Foundation/Acode#2976)
88ddc274 chore(deps): bump @lezer/common to 1.5.4
b08fd0bf feat(markdown): render mermaid diagrams with pele (Acode-Foundation/Acode#2987)
98446ef1 feat(editor): add experimental canvas renderer (Acode-Foundation/Acode#2988)
a16e2d3b chore(deps): bump @acode.app/canvas-view to 0.0.2
2f6e4c55 Translation: Update hu-hu.json (Acode-Foundation/Acode#2989)
f4b75304 chore(deps): bump @acode.app/canvas-view to 0.0.3
dd649703 feat(sidebar): add multi-select & drag-drop to file tree (Acode-Foundation/Acode#2999)
9960e6e2 fix(sidebar): don't render a folder twice when toggled while loading (Acode-Foundation/Acode#3002)
06db4929 fix(scrollbar): place thumb correctly when it reappears (Acode-Foundation/Acode#3003)
6962af1e feat(ui): polish dialogs, sidebar, search and file actions (Acode-Foundation/Acode#3004)

Skipped for now

Conflict resolutions

  • System.java (d755c315): applied upstream's guarded openInBrowser to platforms/android/.../acode/system/System.java, using this repo's Callback instead of CallbackContext.
  • src/lib/editorManager.js (98446ef1): kept this repo's setLspOptions and passed upstream's new canvas option to lspDiagnosticsUiExtension.
  • src/lib/openFolder.js (dd649703): kept both imports (fileOperationExclusions from upstream, haptic from this repo). Upstream's new copyText helper uses Bridge.clipboard instead of cordova.plugins.clipboard, which also replaces this repo's inline clipboard fallback.
  • src/sidebarApps/files/{selection,dragMove}.js (dd649703): new files; I swapped navigator.vibrate for this repo's haptic() so iOS gets haptic feedback too.
  • src/utils/helpers.js (6962af1e): kept this repo's isCancelled next to upstream's new friendlyErrorMessage.
  • bun.lock: this repo doesn't track it, so I dropped it in every commit.
  • package-lock.json: regenerated from the merged package.json with npm install --package-lock-only. This covers mermaid → pele, @lezer/common, @acode.app/canvas-view and the @codemirror/* bumps.

Extra commit

  • test: queue happy-dom selectionchange in quick tools navigation tests: with @codemirror/view 6.43.14+ (required by the canvas renderer), happy-dom's synchronous selectionchange re-entered EditorView.update in two of this repo's iOS quick-tools tests. They pass on 6.43.13. The fix is a small tests/helpers/queueSelectionChange.ts that queues the event like a browser does, the same workaround upstream already uses in editorReadOnly.test.ts.

Verification

  • bun run check passes
  • bun run typecheck passes
  • bun run test: all 134 files / 1062 tests pass
  • The rspack web bundle compiles
  • Not run: the Android Gradle build (no JDK 26 toolchain on the machine)

🤖 Generated with Claude Code

bajrangCoder and others added 10 commits October 28, 2026 22:57
Open file:// links in LSP hover/signature docs in the editor, and guard
the native openInBrowser against file URIs and launch failures.

(cherry picked from commit d755c315cb760a964a89b136f4ae244ef89db0f8)
* update: es-sv

* Fix errors detected by greptile

* fix: fmt

---------

Co-authored-by: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com>
(cherry picked from commit 579af33f9ee584c5f4ad9e60c0f4a90346aa3b5b)
* feat(modes): let plugin modes reuse another mode's formatter

Add a formatAs option to editorLanguages.register so a plugin mode
(e.g. json-bedrock) formats with the formatter and Prettier parser of an
existing mode (e.g. json) when the user hasn't picked one for it.

editorLanguages.register now forwards its options to addMode, and Mode
ignores malformed options instead of throwing.

* fix(modes): resolve formatAs aliases and label the inherited choice

Resolve formatAs through the mode list so an alias (e.g. json5) finds
the base mode's saved formatter and Prettier parser.

For modes with formatAs, the picker's unset option now names the
inherited formatter (e.g. "Prettier (JSON)") instead of "None".

* fix(settings): refresh inherited formatter label when the picker opens

(cherry picked from commit 5323b5879f60605195b259fe38f35e2b7c273c6e)
@lezer/common 1.5.4 fixes the look-ahead of the anonymous nodes that
balance long repeats (lezer/common!11). Before it, incremental parses
never reused them and re-tokenized everything before an edit, so a
keystroke's reparse grew with its position in the file: CodeMirror's
language field hit its 20ms budget on every key deep in large files
(369ms vs 0.5ms for an edit at line 100k of a 4MB file in plain Lezer).
Bumped in dependencies and overrides, so every package uses this copy.

(cherry picked from commit 88ddc2740ac307acb2410ef26094d7ff163b5caa)
* feat(markdown): render mermaid diagrams with pele

Replace the mermaid package with pele, a small synchronous renderer that loads each diagram type on demand and themes via CSS variables.

* fix(markdown): map pele colors to defined theme variables

(cherry picked from commit b08fd0bfc27abd6c58c576d959c607a7b6b69c31)
* build: link @acode/canvas-view from a local checkout

Resolve canvas-view's imports (and their types) from Acode's own
node_modules, so CodeMirror's state and view stay single instances.

* feat(settings): add editor renderer setting

Renderer: DOM (default) or Canvas (experimental), applied on reload.

* feat(editor): add experimental canvas renderer

With editorRenderer set to canvas, editors are @acode/canvas-view
CanvasViews. Settings that the DOM editor applies through extensions
(line numbers, folding, guides, rainbow brackets, whitespace, wrapping,
scroll past end, RTL) become canvas options, kept in sync on changes.
Themes map to a CanvasThemeSpec (config colors + the theme's
HighlightStyle). The selection menu is driven by the view's touch
selection hooks, reusing the existing menu UI.

* perf(editor): leave out CodeMirror's fold gutter with the canvas renderer

The canvas renderer draws its own fold markers, but foldGutter() was
still in the state, and its markers plugin rebuilt (unused) markers for
the viewport on every update and tab switch. Canvas views now get only
the folding state (codeFolding) with indentation folding.

* fix(editor): open the color picker on canvas views

isViewEditable read contentDOM's contenteditable and aria-readonly
attributes. A canvas view's contentDOM is its hidden input element,
which has neither, so taps on color chips (regex and LSP document
colors) were swallowed as if the editor were read-only. Read the
state's editable and readOnly facets instead, which is what the DOM
editor's attributes reflect.


* feat(editor): leave read-only handling to canvas views

Acode's read-only setup works around the DOM editor on mobile: it makes
the content non-editable, blurs on every focus so no keyboard opens,
and shows CodeMirror's cursor layer with CSS. A canvas view handles
read-only documents itself: it ignores typing, cut, paste and drops,
takes focus with inputmode="none" (so its cursor blinks and hardware
shortcuts work, without a keyboard), and drops focus when it becomes
read-only. For canvas views the extension is now only
EditorState.readOnly plus the filter for Acode's own editing commands,
and blurEditorIfReadOnly / focusEditorIfEditable leave them focused.


* feat(editor): selection matches and active indent guide on canvas

With the canvas renderer:
- highlightSelectionMatches is on (it's off by default for the DOM
  editor), drawn with the theme's selectionMatch color, or its
  selection color, as the themes' CSS does;
- indent guides highlight the block around the cursor (one rect per
  frame on the canvas);
- the base extensions leave out drawSelection, dropCursor,
  highlightActiveLine (and its gutter) and highlightSpecialChars,
  which the canvas draws itself. The canvas view only skipped their
  plugins; the active line gutter still rebuilt its markers on every
  selection change.


* feat(editor): show lint underlines on canvas views on touch devices

On touch devices the LSP linter drops every in-text mark (markerFilter),
so only the lint gutter showed an error. Canvas views draw the wavy
underlines and lint points natively, without the DOM editor's layout
cost, so they keep them; hover tooltips stay filtered on touch.


* perf(editor): draw color chips on canvas views without DOM

ColorChipWidget gets toCanvas(): the same box toDOM styles (0.9em,
2px margins, rounded, a faint border), in cells of the view's font.
Canvas views then make no element per chip; they call toDOM only when
a chip is tapped, so the color picker still opens.


* fix(editor): apply the line height setting to the editor's lines

The font theme set `lineHeight` on the editor element, but CodeMirror's
base theme sets `line-height: 1.4` on `.cm-scroller`, so the setting
never reached the lines or gutters: the DOM editor was always 1.4 while
canvas views used the setting, and the two renderers didn't match.

Set it on `.cm-scroller`, so both renderers use it (canvas-view measures
it like CodeMirror, to the DOM's exact value). The default becomes 1.4,
what the editor always showed, and stored values of the old default (2),
which nobody ever saw, are migrated once so editors don't change size.

* feat(editor): canvas backend and sticky scroll settings

Two settings for the canvas renderer, next to "Renderer":
- "Canvas backend": Auto (WebGL2), WebGL2 or WebGPU (falls back to
  WebGL2 where unavailable). Views are created with it, so a change asks
  to reload when the canvas renderer is on.
- "Sticky scroll": keeps the header lines of the scopes around the top
  line pinned while scrolling. Applies live to canvas views.

* build: use @acode.app/canvas-view from npm

canvas-view is now published as @acode.app/canvas-view, so depend on it
instead of a local `bun link` checkout and drop the rspack and tsconfig
workarounds that kept the linked copy on Acode's CodeMirror packages.

Raise @codemirror/view, state, language and @lezer/common to the
versions canvas-view requires, in dependencies and overrides, so a
single copy of each is installed.

The newer view flushes on every selectionchange, and happy-dom fires
that event synchronously from Selection methods, which re-entered
EditorView.update in the read-only cursor test. Queue it there like a
browser does.


* fix(editor): keep edits and DOM extensions across renderer changes

- Flush pending cache writes and save the session before the reload that
  applies a renderer or canvas backend change, as the pause handler does,
  so recent edits aren't lost.
- Include the renderer in the editor state signature, and give the DOM
  fallback pane a fresh empty state, so states built for canvas views
  (without fold controls and the active line) aren't reused by DOM ones.
- Declare the canvas backend and sticky scroll strings in LangStrings.


* feat(settings): more canvas renderer settings, shown only with canvas

- Cursor blink rate, sticky scroll max lines and gutter marker layout
  (shared column, column per gutter, over line numbers), mapped to the
  matching canvas-view options and applied live.
- Bring back the scroll speed setting, which canvas views use.
- Canvas-only settings (backend, sticky scroll, its max lines, gutter
  markers, cursor blink rate, scroll speed) are listed only while the
  canvas renderer is selected, and follow renderer changes.


---------

(cherry picked from commit 98446ef10ea8f2866416d18e753ccc8bfccd8b44)
The canvas renderer now draws font ligatures (Fira Code's =>, !==...)
like the DOM editor, and its fold markers no longer flash when the
mouse quickly enters and leaves the gutter.

(cherry picked from commit a16e2d3b2c95f5f670121075584617c2c838df54)
* Translation: Update hu-hu.json

Translate new strings

* Translation: Update hu-hu.json

Fix translation

(cherry picked from commit 2f6e4c55e82333545ba987054aafc62929225e21)
The canvas renderer's repeated flicks now add up like Android's list
views, a magnifier shows the text under the finger while dragging a
selection (like sora-editor), and touch selections no longer draw a
blinking cursor at their end.

(cherry picked from commit f4b75304f5af12c7891d137517350fce6967d536)
@codemirror/view 6.43.14+ re-enters EditorView.update when happy-dom
fires selectionchange synchronously while the view syncs its selection.
* feat(sidebar): add multi-select to file tree

Select files and folders in the sidebar and act on them together:
copy, cut, delete, copy relative paths, open and rename. The clipboard
is now shared across open folders and pastes multiple entries.

* feat(sidebar): drag to move, folder header actions, review fixes

- Long-press and drag entries (or the whole selection) onto a folder to
  move them; closed folders open on hover and the list scrolls at edges.
- Open folder headers get New file, New folder, Refresh and Collapse all:
  shown on hover with a mouse, behind a single "+" on touch.
- Paste keeps skipped or failed entries in the clipboard and continues
  past failures.
- Pasting across servers or storage transfers through both providers.
- Open and copy path keep entries selected inside a selected folder.
- Folder-into-itself warnings no longer block the paste.
- Closing an open folder drops its entries from the selection.
- Mock the new sidebar modules in the file icon sidebar test.

* feat(sidebar): slide folder header actions out inline on touch

Tapping "+" now reveals the actions as an inline strip in the header
instead of a popup menu; it closes after an action or a tap elsewhere.

* fix(sidebar): header menu, tree scrolling, long-press and review fixes

- Header button opens the folder's select menu, which now also has
  Refresh and Collapse all.
- Size open folders on every expand and measure real header heights, so
  the tree can scroll to its last entry.
- Holding still after a long press opens the menu without lifting; a
  drag needs a deliberate move.
- Release touch listeners after a drag ends.
- Replacing an existing entry works when pasting across connections.

* fix(sidebar): keep drags working across open folders

Opening another folder mid-drag collapsed the source folder, which then
collapsed the new one back, and detached the touched row so the drag
stopped receiving touch events. Size folders only when they expand,
listen for touch events on the touched row too, and cancel a drag on any
stray touch.

* fix(sidebar): check exclusions before replacing, recheck folder before sizing

- Cross-connection copies skip excluded entries before deleting an
  existing destination.
- Size a folder only if it's still open once the files app has loaded.

(cherry picked from commit dd6497033c62ee0c21b29945cf59c5976169a72e)
…(#3002)

* fix(sidebar): don't render a folder twice when toggled while loading

Collapsing and re-expanding a folder before its listing finished let the
old load render alongside the new one. Stale loads now skip rendering,
and a new expand or collapse cancels a tree that is still loading.

* test(sidebar): cover root folders toggled while loading

Drive a real root folder through expand, collapse and expand with the
directory reads still pending, resolving them in both orders and failing
the stale one, and check that only the latest tree renders, a stale error
doesn't collapse the folder and the loading bar follows the latest read.
openFolder's single JSX expression becomes a tag() call so the module can
load in tests.

* test(sidebar): stub global tag in root folder tests

(cherry picked from commit 9960e6e227c79c6ed03b2de4231aca2506aeec30)
* fix(scrollbar): place thumb correctly when it reappears

The value was set while the scrollbar was detached, so it was measured
against an empty rect and painted at 0 for a frame. Only check the track
along the scroll axis, and measure again after appending.

* fix(scrollbar): measure the track on every update while attached

The parent can change size without a window resize (e.g. the sidebar
opening), so a cached track length can go stale.

(cherry picked from commit 06db49298f8e4e1cf3c80f436f1b50c7dca17276)
* feat(ui): polish dialogs, sidebar, search and file actions

- Rename selects the file name without its extension
- Hide the search summary until there is a query
- Show an unread dot on the notifications icon; clear-all icon
- Pin the sponsor icon above the profile, out of the app list
- Make the sidebar icon rail scrollable on touch
- Show Delete in red in menus; distinct Save as icon
- Map common native errors to readable messages
- Theme-aware toast; sentence-case dialog buttons and titles
- Title-case settings page names; fix inconsistent labels

* style: format files command

* fix(prompt): select whole file name when it has no extension

(cherry picked from commit 6962af1e805b8996e743df97cad4df3ecef687e5)
@bajrangCoder bajrangCoder changed the title chore: sync Acode main changes (ef7f3265..f4b75304) chore: sync Acode main changes (ef7f3265..6962af1e) Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants