Commit Graph

24565 Commits

Author SHA1 Message Date
scheinriese
1ebbf1ddf4 fix(icon): correct ordering of dedup + cap in add-used-item!
Pipeline ran (take 24) BEFORE (filter should-keep?), so an existing
duplicate at position 24+ in the recents list was truncated unfiltered
instead of caught by the dedup. Then (cons normalized) prepended the
new pick, producing 25 items — both violating the 24-item cap and
failing to actually move the dup to the front.

Reorder: filter across the whole existing list, cons the new pick,
THEN cap at 24. REPL-verified on a 27-item list with the duplicate at
index 24: old pipeline stored 25 items (cap violated), new pipeline
stored 24 (cap honored, dup correctly displaced by the cons).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:55:25 +02:00
scheinriese
3b80bce2ea refactor(icon): replace js/console.error with lambdaisland.glogi
Logseq convention is to log via lambdaisland.glogi (already used across
handler/, worker/, etc.). Four console.error sites in icon.cljs ported
to log/error with structured event keywords and context maps:

- :icon/url-asset-fetch-failed       {:url :error}
- :icon/url-asset-ipc-failed         {:url :error}
- :icon/grid-subvec-failed           {:start :end :count :error}
- :icon/clipboard-paste-failed       {:error}

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:53:24 +02:00
scheinriese
b3fcc314ba refactor(icon): rename save-image-asset! → <save-image-asset!
Logseq convention: function names prefixed with `<` return a promise.
save-image-asset! uses p/let internally and returns the entity promise;
all three external callers wrap it in p/let / p/all. Sibling
<save-url-asset! already follows the convention. Rename for consistency.

Five occurrences updated (defn, internal arity dispatch, 3 callers).
Compile clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:51:11 +02:00
scheinriese
c1b9d43dc7 refactor(cmdk): drop dead :ignore-current-icon? flag from 4 call sites
The flag was introduced upstream by Tienson Qin (4c6c3322fe, Nov 2025,
"enhance(ux): show node icon in search results") to make cmdk skip the
block's own :logseq.property/icon and fall through to the class's icon
or fallback, keeping search rows visually consistent at the class level.

During this branch's icon-picker refactor, get-node-icon was rewritten
to a new own → tag-default → type-default inheritance model and lost
the opts map entirely. The four cmdk callers kept passing
{:ignore-current-icon? true} but get-node-icon-cp silently ignores it.

The new behavior (show the block's effective icon with full inheritance)
is preferable for the new picker model — pages with meaningful per-
instance icons like photos show their photos in cmdk, instead of a
generic class glyph. Drop the dead flags to reflect actual behavior and
remove the misleading vestige. If "always show class default in cmdk"
is wanted later, it's a deliberate new feature, not a regression to
restore.

Verified live: cmdk renders page rows with their inherited/own avatars,
asset rows with asset glyphs, block rows with dot fallbacks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:49:16 +02:00
scheinriese
e393a7edee refactor(block): drop dead block-title-with-icon helper
block-title-with-icon had zero callers — the editor.cljs and
property/value.cljs sites that used to compose via this helper were
migrated to the explicit 20×20 icon-slot pattern (single icon per row,
sourced from get-node-icon-cp), and CMD-K never composed through it.
The only remaining references were explanatory comments documenting
*why* the new pattern doesn't reuse it.

Delete the function and rewrite the four comments to describe the
de-dup rule directly (instance rows that diverge from a class default
would otherwise render the same icon twice) rather than referencing a
dead symbol that would rot future readers.

Compile clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:42:07 +02:00
scheinriese
abdfa0ca67 refactor(theme): single helper owns theme-DOM stamping
state.cljs and theme.cljs both stamped data-theme + body classes onto
the DOM (in apply-theme-to-dom! and the container's mount effect
respectively). The duplicate setAttribute work is idempotent in
practice but the two code paths drift on edge cases (plugin hook
order, custom-theme application) and obscure who owns the stamp.

Promote state/apply-theme-to-dom! to public and have theme.cljs's
effect call it instead of inlining its own copy. Now: set-theme-mode!
calls it synchronously before set-state! (so subscribers see fresh
DOM on next render); the container effect calls it on mount and on
every theme prop change (so the initial render and any external
:ui/theme writes also stamp the DOM). Effect retains its
custom-theme + plugin-hook + re-render-root! responsibilities.

re-render-root! kept on toggle: bg-var cache invalidation (commit
6b4e5fb910) makes recomputed values correct, but components that
don't subscribe to :ui/theme but DO render avatar/contrast colors
would keep stale inline styles without a forced reconciliation.

Verified live: set-theme-mode! "dark" → data-theme stamped to "dark",
`dark` class added to <html>, body classes updated, end state
consistent.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:38:06 +02:00
scheinriese
6b4e5fb910 perf(colors): memoize read-bg-var across renders, invalidate on theme flip
read-bg-var was called on every render of every colored icon via three
call sites in icon.cljs (avatar-fallback-style, icon color? wrapper,
get-node-icon-cp). On a graph with many tagged pages — page list, cmdk
results, sidebar — that meant hundreds of synchronous getComputedStyle
calls per frame, each forcing a style recalc / layout flush.

Cache values per CSS var name in a defonce atom; a MutationObserver on
documentElement watching data-theme + class invalidates the cache on
theme flips (apply-theme-to-dom! writes both). Observer callbacks fire
at the microtask boundary — before React commits the render scheduled
by the same set-state! that triggered the flip — so subscribers always
see fresh values on the next paint without an explicit invalidation
call from state.cljs.

Cache also holds nil so unset vars don't repeatedly hit getComputedStyle.

Verified live:
- 1001 read-bg-var calls after initial fill: 0 getComputedStyle calls.
- Flip documentElement data-theme attribute: exactly 1 fresh
  getComputedStyle call on the next lookup (observer fired, cache
  cleared, value recomputed).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:25:03 +02:00
scheinriese
69f0ef55b2 fix(lightbox): clean up on PhotoSwipe init failure
attach! sets every Radix popper to inert=true and installs 5 window-
capture listeners (pointerdown/mousedown/click/contextmenu/keydown).
Cleanup was wired only to PhotoSwipe's "destroy" event, but if .init
or .loadAndOpen threw, that event never fired — leaving the listeners
attached and every popper permanently inert (soft-bricked app).

Wrap init+loadAndOpen in try/catch: on failure synchronously call
detach! to roll back inert + remove listeners, clear the window-global
so mobile/navigation's later .destroy call doesn't act on a broken
instance, and rethrow so the underlying error surfaces.

Verified by stubbing PhotoSwipeLightbox to throw inside .init and
calling preview-images!: caught exception bubbles up, inert restored
to false on a probe popper, and window.photoLightbox is null.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:20:49 +02:00
scheinriese
b1685ea6bc i18n: drop 89 orphan en.edn keys with no callers
Cleanup pass following the icon-picker i18n migration. Removes 84 keys
in :settings-page/*, :content/*, :linked-references/*, :text/* that
were imported from a sibling branch but have no (t ...) call sites in
the current codebase, plus 5 stale bare-form shortcut keys
(:editor/copy, :dev/show-{block-data,block-ast,page-data},
:asset/confirm-delete) whose dynamic shortcut-desc lookup goes through
the decorated form :command.<ns>/<leaf> instead.

Verified via:
- ripgrep across src/ and deps/ for each key (no static call sites)
- inspection of shortcut-desc-by-id + decorate-namespace path
- bb lang:validate-translations: down from 94 unused → 5 unused
- 5 remaining unused are master-owned :icon/icons-count,
  :icon/matched-count, :icon/search-{all,emojis,icons}; left in place
- bb lang:lint-hardcoded -w: still 0 hardcoded strings
- shadow/compile :app: 0 warnings

Keys existed only in en.edn — no other locale files affected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:17:20 +02:00
scheinriese
0274af211d i18n(icon-picker): replace 129 hardcoded UI strings with translation keys
Move icon picker + property default-icon-row + selection action-bar text
through frontend.context.i18n/t per .agents/skills/logseq-i18n. Adds
~93 new keys across :icon/*, :icon.{asset,asset-mode,asset-search,
avatar-band,avatar-fallback,avatar-scope,avatar-tab,clipboard,color,
fallback,mode,section-header,shape,text-picker,text-tab,upload,
web-images}/*, :class.default-icon/* namespaces. Each new key is
defined in both en.edn (source) and zh-cn.edn (required second locale
per skill Rule 3).

Compound sentences kept whole via interpolate-rich-text-node (Rule 4);
dynamic-count messages use Tongue function values (Rule 6); existing
generic keys reused where semantics matched (:ui/cancel, :ui/reset,
:ui/empty, :ui/untitled, :property.status/done, :context-menu/set-icon).

Verified:
- bb lang:lint-hardcoded -w → 0 hardcoded strings
- bb lang:validate-translations → all referenced keys defined
- shadow/compile :app → 0 warnings

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:12:05 +02:00
scheinriese
5329e52402 Merge origin/master into feat/unified-icon-picker
Brings 99 new master commits forward. 5 file-level conflicts resolved:

- deps/db/src/logseq/db/frontend/schema.cljs — bumped version to "65.32"
  to accommodate both sides' migration chains
- src/main/frontend/worker/db/migrate.cljs — both branches defined a
  65.26 migration; renumbered master's :logseq.property.repeat/repeat-type
  to 65.32 after my 65.26..65.31 chain
- src/main/frontend/components/content.cljs — dropped master's debug
  prn (commit "remove debug print"); kept HEAD's indentation
- src/main/frontend/components/icon.cljs — kept HEAD's refactor of
  emoji-cp into type-dispatched emoji/icon/text/avatar components
  + render-item dispatcher; master's simpler emoji-cp would break
  the item-render call site
- .agents/skills/logseq-task-on-lambda/SKILL.md — took master's
  updated skill doc verbatim (not my work area)

Re-added /.claude/plans/ to .gitignore after auto-merge picked
master's rewrite of /.claude → /.claude/settings.local.json and
dropped my prior ignore rule.

Compile verified clean against shadow-cljs :app and :test builds
(0 new warnings). App loads in browser without runtime errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:28:05 +02:00
scheinriese
a55bd0be04 enhance(cmdk): drop icons from search-result breadcrumbs
Breadcrumb segments in CMD-K rendered the page's full 20px avatar above
12px breadcrumb text, breaking the line box, competing with the row's
own 20px icon for attention, and producing a "double face" effect when
the same entity appeared as a row icon and a breadcrumb icon nearby.
Hide the segment icon behind the existing .breadcrumb--search-result
modifier so all other surfaces (app header, right sidebar, FSRS, etc.)
keep their breadcrumb icons unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:16:07 +02:00
Tienson Qin
7efb9aa0a7 enhance(mobile): improve flashcards tab 2026-05-19 08:42:43 +08:00
Tienson Qin
519bdf39e0 fix: port 2026-05-19 06:54:41 +08:00
Tienson Qin
df6a83d079 fix: address ios native review issues 2026-05-19 06:54:41 +08:00
Tienson Qin
05ea21e8f1 fix: remove unused navigation binding 2026-05-19 06:54:41 +08:00
Tienson Qin
0f352a8e07 enhance: pull to refresh graphs 2026-05-19 06:54:41 +08:00
Tienson Qin
32f3fd5a64 fix: prevent calendar double redirect 2026-05-19 06:54:41 +08:00
Tienson Qin
3852d18822 fix: mask native tab transition briefly 2026-05-19 06:54:41 +08:00
Tienson Qin
4803a30327 fix: avoid web graphs flash on ios 2026-05-19 06:54:41 +08:00
Tienson Qin
7259ce4669 fix: native ios graphs view 2026-05-19 06:54:41 +08:00
Tienson Qin
2b950bad69 fix: show graph download progress from switcher 2026-05-19 06:54:41 +08:00
Tienson Qin
92c2b09c79 fix: wrap native notifications 2026-05-19 06:54:41 +08:00
Tienson Qin
c879671817 fix: smooth bottom sheet 2026-05-19 06:54:41 +08:00
Tienson Qin
0d79279c4f fix: avoid search exit on app background 2026-05-19 06:54:41 +08:00
Tienson Qin
326eebefdc fix: speed up ios search focus 2026-05-19 06:54:41 +08:00
Tienson Qin
96fbf5b4c0 fix: focus mobile search immediately 2026-05-19 06:54:41 +08:00
Tienson Qin
ae0a675dc4 fix: smooth mobile search transitions 2026-05-19 06:54:41 +08:00
Tienson Qin
66711b471e fix: smooth ios search exit 2026-05-19 06:54:41 +08:00
Tienson Qin
4885e9a922 fix: keep search result navigation in search stack 2026-05-19 06:54:41 +08:00
Tienson Qin
b28cd247ce fix: route mobile search results through home stack 2026-05-19 06:54:41 +08:00
Tienson Qin
e6c3011ead fix: navigation stack 2026-05-19 06:54:41 +08:00
Tienson Qin
5038cd0c7c fix: use https for ios mobile dev server 2026-05-19 06:54:41 +08:00
Tienson Qin
6dd00b0d6c fix: stabilize mobile navigation stacks 2026-05-19 06:54:41 +08:00
Tienson Qin
efd9380f22 fix: path bookkeeping 2026-05-19 06:54:41 +08:00
Tienson Qin
466647ef3d [codex] improve sync onboarding (#12676)
* enhance: improve sync onboarding

* chore: update sync onboarding local changes

* fix: show sync upload in native header

* fix: route native local sync taps

* fix: use upload icon for native local sync

* chore: remove debug log

* fix: compile cljs tests

* test: remove header compile dependency

* test: remove mobile header compile dependency
2026-05-18 23:27:44 +08:00
scheinriese
708ba0d915 fix(page-title): icon centering + tag proximity in narrow viewports
When the page-title row wrapped to a column (narrow containers), the
icon stretched to the full column height and centered between title
and wrapped tag, and the #tag landed with a disconnected 17px gap.
Constrain the icon box to one title line via align-self + height, and
collapse the tag's margin-top once the row has wrapped. Nudge the
centered icon 4px down for optical alignment.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:51:45 +02:00
scheinriese
afc0ecafef fix(icon-picker): lightbox failed on Wikimedia PDF/DJVU web images
The maximize button on Web image hover previews showed "The image
cannot be loaded" for any Wikimedia PDF or DJVU result. Two causes:
the upscale regex `#"/\d+px-"` didn't match the `/pageN-NNNpx-` size
token PDFs use, so `src` fell back to the raw `.pdf` URL PhotoSwipe
can't render; and Wikimedia's PdfHandler caps PDF/DJVU thumbs at
1280px wide, so even a corrected upscale to 1600 returned 400.

Drop the leading `/` anchor so the regex matches both regular and
PDF/DJVU thumbs, clamp the upscale target to 1280 when we detect
the `/pageN-` prefix, and fall the probe back to the original
thumb URL on error — beats showing the placeholder when a
particular size isn't cached.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:26:28 +02:00
Tienson Qin
4cdb14ef8f fix(cli): normalize block content tree 2026-05-18 20:20:45 +08:00
scheinriese
6173879fe4 enhance(icon-picker): universal hover preview + working lightbox integration
Two related improvements to the asset picker:

1. Hover preview parity across all asset lanes. Previously the rich
   preview card (image + From + license badge) only fired for web-image
   search results. Now Recently used and Available assets show the same
   card too, gracefully degrading to image + title when source/license
   are missing (e.g. locally-uploaded assets that haven't been touched
   by migration 65.29 yet).

   - `asset->preview-data` normalizes an asset block + blob URL into
     the shape `web-image-card-content` consumes. Derives `:source`
     from `:source-name` (Wikipedia / Wikimedia Commons regex) so the
     existing branches still route.
   - `image-asset-item` wraps its button in the same shui/tooltip
     pattern web-image-item uses.
   - `web-image-card-content` source row now omits when neither
     `:source` nor `:source-name` is set (was always rendering a
     misleading "From: Web" fallback for non-web items). Title
     fallback changed to "Untitled image".
   - `license->description` made public so the asset path can derive
     the human-readable badge same as Commons results.
   - Both asset queries (sync + async) extended to pull
     `:logseq.property.asset/source-name` and `:logseq.property.asset/license`.

2. Maximize button now opens the same PhotoSwipe lightbox the #Asset
   tag page row-click and inline asset blocks use, replacing the
   half-baked positioned-popover that was sized via the deleted
   `full-image-view` component and `.full-image-view-popup` CSS.

   The lightbox-over-popup scenario surfaced three layering bugs that
   the new wrapper handles:

   - Body's `pointer-events: none` from Radix `modal: true` cascades
     into PhotoSwipe and kills backdrop click — fixed via a one-line
     `.pswp { pointer-events: auto !important }` rule in
     `lightbox.css` (auto-imported via tailwind.all.css's glob).
   - Hover states behind the lightbox activate because the swallow
     listener can't suppress CSS `:hover` — fixed by marking Radix
     popper wrappers `inert` for the lightbox lifetime (browser spec
     suppresses mouseover/pointerover targeting the inert subtree).
   - Escape closes both lightbox and picker because both attach
     keydown handlers at document level — fixed by a window-capture
     keydown handler that intercepts Escape before Radix sees it and
     manually calls `pswp.close()`.

   For Wikimedia results where `:url` is sometimes a PDF/DJVU source
   file (not an image), the maximize handler upscales the
   `/NNNpx-FILENAME` segment in `:thumb-url` to `/1600px-` so we
   always feed PhotoSwipe a server-rendered JPG. Image dimensions
   come from an async `new Image()` probe.

   Callers outside the picker (block.cljs, pdf/assets.cljs,
   handbooks/core.cljs) are unaffected — `roots` is empty, the
   pointer-events override is harmless, the swallow has nothing to
   swallow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 13:58:10 +02:00
Tienson Qin
e9d66de128 fix(electron): install CLI launcher in local bin (#12664)
* fix(electron): install CLI launcher in local bin

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-18 10:28:29 +08:00
Mega Yu
e3e548f0f0 emove debug print 2026-05-18 09:18:27 +08:00
Gabriel Horner
efea55bace fix: emoji doesn't show name on hover
in the emoji picker most of the time
2026-05-17 19:18:35 -04:00
rcmerci
8cfe7b232b Merge pull request #12670 from logseq/codex/bounded-pr-str
fix(cli): bound truncate-preview printing
2026-05-17 18:19:52 +08:00
rcmerci
c673ff428c fix(cli): preserve deep preview values 2026-05-17 17:56:23 +08:00
rcmerci
d3823805e7 fix: bound preview printing 2026-05-17 17:28:22 +08:00
Gabriel Horner
6af3934dd3 enhance: export-edn exports ::sqlite-export/graph-files
in an idempotent/roundtrippable way
2026-05-17 01:55:56 -04:00
Gabriel Horner
c89c7eaacc fix: build-edn fails to export :build/class-properties that roundtrip
When running `bb dev:cli export-edn --roundtrip` on a graph with
included test, :build/class-properties sort order kept changing
because built-in properties order is lost on export
2026-05-17 01:26:45 -04:00
Gabriel Horner
9ac459cc76 fix(cli): task --priority completion regression 2026-05-16 17:52:16 -04:00
Gabriel Horner
ef2c35874e enhance(dev): enable claude to read project skills 2026-05-16 17:32:49 -04:00