Commit Graph
663 Commits
Author SHA1 Message Date
tianma-if 7d2e54966b feat(poster): guide AI template selection with shared descriptions 2026-10-19 17:33:04 +08:00
tianma-if 3519fc9ec3 feat: support SVG image uploads and previews 2026-10-19 16:43:11 +08:00
tianma-if 0bebd4e542 fix: unify font loading and fallback messages 2026-10-19 11:34:31 +08:00
tianma-if 83fac43d4e fix: show template font fallback and restore fonts after retry 2026-10-19 11:31:51 +08:00
tianma-if 5eecc8df13 perf: reduce bundled fonts and defer startup dependencies
Keep shared offline defaults and download optional fonts into a validated cache with reliable export fallbacks. Prune stale Android DOM assets and refresh the smaller iOS editor bundles.

Preserve lazy startup boundaries through direct shared exports and dependency-aware splitting. Add ESM graph and Chrome startup checks to prevent eager editor and font loading.
2026-10-19 11:10:25 +08:00
tianma-if 8a06c8ca55 test: provide paper texture in book theme font fixture 2026-10-18 22:19:50 +08:00
tianma-if 89000466ad fix: hide note titles in shared images by default 2026-10-18 22:15:21 +08:00
tianma-if f4f307d2a2 fix: show theme font names in image sharing 2026-10-18 21:27:55 +08:00
tianma-if 2d48d02af9 style: give book excerpt images a warm paper background 2026-10-18 21:19:00 +08:00
tianma-if 4c00dbb1df fix: use glass as the default note image theme 2026-10-18 21:16:29 +08:00
tianma-if f4732e3df7 fix: remove generated avatar from note image signatures 2026-10-18 21:12:24 +08:00
tianma-if d885161b3e fix: restore template typography when switching note image themes 2026-10-18 21:09:50 +08:00
tianma-if b58011f76f fix: improve note share image hierarchy and rich content exports 2026-10-18 21:05:16 +08:00
tianma-if 51973cf16e fix: match note image template fonts to their visual styles 2026-10-18 20:07:03 +08:00
Dariusz Korytoandtianma-if df22f55d1c feat(docker): report image build metadata in System information (#602)
Docker instances reported most deployment fields as unknown. Report how
and when the container image was built, separately from how the
instance was deployed:

- Dockerfile: optional EDGE_EVER_BUILD_CREATED_AT, EDGE_EVER_BUILD_TRIGGER
  and EDGE_EVER_BUILD_METHOD build args, empty by default.
- /api/health (self-hosted-bun only): optional buildCreatedAt and
  buildProvenance. deploymentVersionCreatedAt and deployment keep their
  meaning and stay runtime-supplied; Cloudflare responses are unchanged.
- docker-image.yml: official images record the build time and their
  provenance. Draft-release builds dispatched with release_tag are
  github_release, main pushes main_push, other dispatches manual.
  The container test checks the health response for a metadata build
  with runtime overrides and for a default self-build; the post-publish
  audit checks the published image.
- Add an explicit `docker` deployment method. It is never inferred from
  the runtime, and the registry source still comes only from
  EDGE_EVER_CONTAINER_IMAGE.
- Web/desktop show "Image built at" and "Image build source" for Docker;
  Android shows "Image built at". Older clients ignore the new fields.
- Document the build args and runtime variables in both Docker guides.

Co-authored-by: tianma-if <yingwaizhiying@gmail.com>
2026-10-18 11:43:41 +08:00
Dariusz Korytoandtianma-if 5ac19b542b feat(web): show a QR code for note and notebook share links (#610)
Opening a shared note on a phone meant copying the link to another
device. Add a collapsible "QR code" section to the note and notebook
share dialogs that renders the public link as a scannable code.

- Rendered with qrcode.react 4.2.0 (SVG, no dependencies), loaded with
  the share dialogs only.
- Dark modules on a white panel in every theme so phone cameras can
  read it; labelled for screen readers, no native title tooltip.
- Hidden for password-protected links, so the code never replaces the
  password the recipient still has to receive separately.
- Copy in all four catalogs.

Co-authored-by: tianma-if <yingwaizhiying@gmail.com>
2026-10-18 11:39:00 +08:00
Dariusz Korytoandtianma-if d0f441dafa fix(web): localize untitled notes and diagrams on public share pages (#605)
* fix(web): show the localized label for untitled notes everywhere

Untitled notes are stored with the zh-CN default title, and several views
only replaced an empty title, so they showed 无标题笔记 in every locale.
The visible cases were the public share page (heading and browser tab),
the public notebook site, AI companion cards and mentions, the note link
picker, link text inserted for a note, and the title of a duplicated
note.

Add getMemoDisplayTitle() next to DEFAULT_MEMO_TITLE and use it in those
views, matching what MemoCard already does with isDefaultMemoTitle.

* fix(web): localize diagrams and content label on the public share page

The public share page passed zh-CN to read-only diagrams for every
language other than English, so Japanese and Polish visitors saw Chinese
diagram labels. Resolve the locale with resolveSupportedLocale(), which
the diagram renderer already supports for all four languages.

Also translate the note content aria-label, which was hard-coded in
English.

---------

Co-authored-by: tianma-if <yingwaizhiying@gmail.com>
2026-10-18 11:26:50 +08:00
Dariusz Korytoandtianma-if 82dac9b5cb fix: keep share and form links out of search indexes and caches (#608)
Public share and form pages only added a robots meta tag from JavaScript,
so the HTML for /share/* and /form/* was served without any indexing or
caching directive, and the form page had none at all. Error responses
from /api/public/* also lacked X-Robots-Tag.

Send one policy everywhere a token-bearing link is served:

  X-Robots-Tag: noindex, nofollow, noarchive, nosnippet, noimageindex
  Cache-Control: private, no-store
  Referrer-Policy: no-referrer

- /api/public/*: shared middleware in the application, so it applies on
  Cloudflare and Docker, including 404/403 responses. Routes that already
  set Cache-Control keep it.
- /share/* and /form/* HTML: _headers rules for Cloudflare static assets
  and the self-hosted static server.
- Referrer-Policy keeps the share token out of Referer headers sent to
  linked sites.

robots.txt is deliberately not used to block these paths: a disallowed
URL can still be indexed from external links, because crawlers never see
the noindex header.

Co-authored-by: tianma-if <yingwaizhiying@gmail.com>
2026-10-18 11:23:42 +08:00
tianma-if 67f627cc3c feat(fonts): share all 23 poster fonts across typography pickers 2026-10-17 11:10:22 +08:00
Dariusz Koryto ccc5ed3f29 refactor: remove unused code and enforce no-unused-vars (#598)
* refactor: remove unused imports, variables and parameters

Remove the 110 bindings reported by no-unused-vars:

- 78 unused imports. Nine whole value-import statements disappear:
  shadcn/ui input, tooltip, button and switch, MobileWebClipCapture,
  AccountSecurityModal and @/lib/api in plugin-host. None of these
  modules has top-level side effects beyond displayName assignments,
  and @/lib/api is still imported by 60 other web modules. The other
  removals are type-only imports or bindings from modules that stay
  imported, so module evaluation is unchanged.
- Dead helpers: appendResourceMarkdown, handleTogglePin (mobile),
  CheckCircleCheck, moveTargetTitle, moveTargetSelectRef,
  handleMoveTargetSelectKeyDown (memo list), copiedLabel (share
  dialog), and an unused palette and flowchart in the diagram editor.
- Component props that are passed but never read are dropped from the
  destructuring only. Their prop types and call sites are unchanged,
  so no caller changes behaviour.
- Tests: iterate Object.values() where keys were unused, and drop
  unused fixture bindings and callback parameters.

* ci: enforce no-unused-vars in oxlint

Turn the rule on with the conventional escapes: names starting with an
underscore and rest siblings used to omit a property
(`({ id, ...item }) => item`) are allowed.
2026-10-17 01:11:05 +08:00
tianma-if 8726df7542 feat(fonts): show loading status and retry failed font loads 2026-10-17 01:03:25 +08:00
tianma-if 9dc05c2480 feat(fonts): unify catalog for body and poster editors 2026-10-16 22:59:19 +08:00
tianma-if a2a0f37377 Merge remote-tracking branch 'origin/main' 2026-10-16 22:41:16 +08:00
tianma-if 20a3851958 feat(share): add cached fonts and font picker previews 2026-10-16 22:40:12 +08:00
Dariusz Koryto 50e4a1a7f2 fix(i18n): localize the suspicious overwrite save rejection (#593)
The API rejects a save that changes the title while most of the note
content disappears with an English message, and clients showed it
verbatim in every locale.

- shared: add editor.saveState.errorReason.suspiciousOverwrite in all
  four catalogs and getMemoSaveErrorReasonKey(), matching the error code
  or the server message; the API reuses the exported code and message.
- desktop sync details: translate the item by lastErrorCode.
- Android: map the stored message to its zh-CN source text so the
  localized components translate it.
- web editor: show the reason in the save status tooltip and label
  instead of the bare "Could not save".
2026-10-16 22:09:26 +08:00
tianma-if 29ff4d14e0 Merge remote-tracking branch 'origin/main' 2026-10-16 21:58:11 +08:00
tianma-if 776fc3b566 feat(share): refine image themes and persist settings across clients 2026-10-16 21:57:49 +08:00
Dariusz Koryto bec688b91a ci: add oxlint correctness check and resolve its findings (#592)
* refactor: resolve oxlint correctness findings without behavior changes

- Snapshot iterations that mutate their collection with Array.from()
  instead of a spread (live childNodes, self-removing disposers, a Set
  extended inside its own loop).
- Drop empty spread fallbacks, redundant regex escapes, Boolean() casts
  inside negations, a rethrow-only try/catch and statement ternaries.
- Use startsWith/endsWith for anchored literal checks in the extension.
- List U+FE0F explicitly in the mobile attachment emoji class; the
  matched set is unchanged.
- Fix the WeChat copy fixture, where \oint in a template literal lost its
  backslash and the block formula never exercised \oint.
- Document the intentional control-character regexes (filename
  sanitizing and input validation), the throwing provider stream test,
  Astro's generated type reference and the mobile auto-sync finally
  block with narrow inline exceptions.

* ci: run oxlint correctness rules on pull requests

Pin oxlint 1.88.0 and enable only its correctness category across apps/
and packages/, excluding build output, vendored code and the iOS app.
Findings are errors and the script passes --deny-warnings, so CI fails
on any finding. no-unused-vars stays off until unused code is removed
in a dedicated pass.
2026-10-16 21:57:36 +08:00
Dariusz Koryto d96b8f6e69 feat(diagram): start new diagrams with labels in the interface language (#594)
New mind maps, flowcharts and architecture diagrams always started with
Chinese labels, whatever language the interface used.

- createDefaultDiagramDocument takes optional starter labels. Without
  them it returns the existing Chinese starter unchanged, so the other
  callers (tests, desktop sidecar checks) keep their output.
- The web client passes translated labels from new diagram.seed keys in
  en-US, zh-CN, ja and pl.
- fitDefaultDiagramLabels sizes the nodes and lays the starter out again
  only when a translated label needs more room than the default label it
  replaces, so the Chinese starter keeps its tuned geometry. The helper is
  loaded with the lazily loaded diagram editor, which keeps dagre out of
  the workspace chunk; if that import fails the note is still created
  with the starter geometry.
2026-10-16 21:53:03 +08:00
Thorsten Ruf 640f973997 fix(web): open internal note links in the target notebook (#581)
* fix(web): open linked notes in their target notebook

* fix(web): release pending note selection on manual scope changes
2026-10-16 21:52:57 +08:00
tianma-if 2c1b713ffa docs: modernize product positioning and decouple evernote coupling across locales 2026-10-16 13:09:13 +08:00
tianma-if 0d1682e48d fix(web): show local agent connection failure reasons 2026-10-16 12:06:36 +08:00
tianma-if 80038dd2d1 feat(editor): refine note image share themes with typography affinity and curated layout 2026-10-16 00:10:18 +08:00
LuoQianhong 1bb9580007 feat(extension): expand vertical and article platform clipping (#578) 2026-10-15 21:39:41 +08:00
tianma-if 7493f3cf8f fix(editor): exclude adjacent CJK prose from pasted links 2026-10-15 21:11:51 +08:00
Dariusz Koryto 72ab4816a1 feat(memos): duplicate a note with its files (#566)
* feat(memos): duplicate a note with its files

Add "Duplicate note" to the note list's context menu and the text editor's
"More note actions" menu. The copy keeps the note's content and tags, is
titled "<title> (copy)" in the UI language, and opens in the editor.

POST /api/v1/memos/:id/duplicate (write:memos) copies every image and
attachment of the note to a new resource with its own stored object and
rewrites the content to reference the copies, so editing or deleting either
note never affects the other. Shares, revisions, the pinned state, public
form links and unsubmitted form uploads are not copied. A note with more
than 20 files or more than 64 MiB of files is refused, and files written for
a copy that fails are removed.

The Web and desktop clients synchronize the note's queued changes before
duplicating and refuse while any remain, including unresolved conflicts;
the editor item stays disabled until the current edit is saved.

* fix(memos): keep committed duplicate files and check the whole desktop outbox

- Copied objects are removed only when the write batch fails. A failure
  after the commit, such as a transient error while reading the new memo,
  no longer deletes files that committed resource rows reference. When the
  memo row is missing after the commit (its notebook was removed meanwhile),
  the rows are removed before their objects.
- The sidecar lists at most 200 outbox items, so a conflict of the note
  further down the queue was invisible and the stale server version could be
  copied. The desktop client now compares the listed items with the
  sidecar's status counts and refuses to duplicate unless the whole
  outstanding queue was listed, nothing is being synchronized, and no item
  belongs to the note.
- Regression tests cover a read failure after the commit and a target
  conflict at position 201 behind 200 other conflicts.
2026-10-15 16:54:04 +08:00
tianma-if 7b03c8dbff fix: use neutral colors for white note image theme 2026-10-15 13:48:30 +08:00
tianma-if f4b36fc64f fix(desktop): repair ACP updates and add manual retry 2026-10-15 11:10:39 +08:00
Dariusz Koryto 9bb3218c03 feat(templates): show unedited default templates in the current UI language (#563)
* feat(templates): show unedited default templates in the current UI language

Default templates are stored in the language of the workspace's first
sign-in, so switching the UI language left them in that language. While a
default template still equals one of its seeded translations, the web
template center and the Android template picker now show it in the current
UI language, and using it creates the note in that language. Templates the
user created or edited are shown and used exactly as stored.

POST /api/v1/templates/:id/use accepts an optional `locale`; without it the
stored template is used as before, so MCP, agents and older clients are
unaffected.

* fix(templates): edit the stored template and stop localizing retagged defaults

- The template center now keeps each card's stored template next to its
  display translation. Editing starts from the stored fields, so saving a
  name-only change in another UI language no longer writes the translated
  title, description and Markdown.
- A default template whose tags differ from its seeded tags is treated as
  edited and is no longer localized.
- Add regression tests for the name-only edit and changed tags.
2026-10-15 09:10:38 +08:00
Dariusz Koryto b3f4dfda2b feat(workspace): localize default notebooks and welcome note at first sign-in (#562)
* feat(workspace): localize default notebooks and welcome note at first sign-in

A new installation always created its five default notebooks, welcome
note and note templates in Chinese, whatever the interface language.
Members added by the owner got notebooks and templates in the owner's
language instead of their own.

The seed data is now localized once, at the first sign-in of the
workspace's user, using the UI locale the client sends with the login
request (Web and Android send it; other clients fall back to
Accept-Language, and unsupported languages to English).

Migration 0070 marks the default workspace as waiting for this only on
an installation nobody has used yet: no users, no notes beyond the
welcome note, no edits to it, no extra notebooks, revisions or
resources. Existing installations keep their data unchanged. Member
workspaces created by the owner are marked when created.

The sign-in localizes notebook names, templates, the welcome note and
its search document in one transaction that also clears the mark, and
replaces only values that still equal a seeded translation. A failed
attempt leaves the mark for the next sign-in to retry, and a second
sign-in changes nothing. The demo clears the mark so its bilingual seed
stays as it is.

Refs #483

* fix(workspace): guard seed inserts and title-only welcome edits during localization

- Default template and AI prompt inserts in the first-sign-in batch now
  require the pending marker, so a delayed concurrent sign-in cannot
  recreate seeds removed after the faster sign-in finished.
- The welcome note is treated as untouched only while it keeps the seeded
  title, the system actor, the seed content hash, and revision 0, so a
  title-only edit is no longer overwritten.
- Add regression tests for both cases.

Refs #483
2026-10-14 20:45:42 +08:00
tianma-if 590150d3ea fix(web): clarify sharing states and close dialogs on navigation 2026-10-14 10:02:58 +08:00
tianma-if 29bb511259 feat(sharing): recover encrypted passwords across devices 2026-10-14 09:27:13 +08:00
tianma-if a78586b716 feat(sharing): add password protection for notebook shares 2026-10-13 23:24:17 +08:00
tianma-if a7f05b439c fix(web): clarify share management layout and notebook icon 2026-10-13 21:56:08 +08:00
tianma-if 62390b218f feat(web): turn shared notebooks into a navigable website 2026-10-13 21:45:58 +08:00
tianma-if 13f8b3f407 feat: share notebooks recursively with live public reading
Add notebook-level share management, directory navigation, and live subtree checks for notes and attachments. Include migration and access-boundary regression tests.

Refs #551
2026-10-13 19:27:16 +08:00
tianma-if a8d845e9cb fix(i18n): shorten inbox deletion hint 2026-10-13 19:23:25 +08:00
tianma-if 91f1887c33 fix(ai): surface safe companion failure diagnostics
Preserve HTTP status and fixed failure categories for direct and proxied agent requests, display diagnostics beside failed turns, and prevent AI SDK error logging from exposing request data.

Refs #555
2026-10-13 17:35:33 +08:00
tianma-if 1c234a463c fix: clarify used storage labels and simplify member descriptions
Refs #553
2026-10-13 17:17:23 +08:00
tianma-if 7bbde189f8 feat: show instance and per-account attachment storage usage
Add owner-only attachment summaries and a compact member management table. Keep personal attachment statistics unchanged and exclude Trash from usage totals.

Refs #553
2026-10-13 17:12:04 +08:00