Commit graph

2828 commits

Author SHA1 Message Date
boojack
9e84f61029 fix(web): delay loading skeleton to avoid flash on fast loads
Render the memo list skeleton only after loading exceeds a short delay
(SKELETON_LOADING_DELAY_MS). Fast/self-hosted loads now finish before the
threshold and never flash the skeleton, while slow loads still show it.

Close #6047
2026-06-25 22:02:39 +08:00
boojack
e3e4ae1051 feat(web): add link preview view setting
Add a persisted "Link preview" toggle (default on) to the memo
display-settings popover, mirroring the compact-mode setting. When turned
off, link-preview cards are hidden across all memo views and the metadata
request is skipped (the gate sits at the paragraph renderer and reads the
preference from ViewContext). Resolves the request in #6045.
2026-06-25 20:45:51 +08:00
greymoth
a5c10a7221
i18n(ja): complete Japanese translations — fill 24 missing keys (#6048) 2026-06-25 18:11:23 +08:00
boojack
5f7e038aa7 fix(editor): support backslash-escaping literal #tags
Memos layers #tag syntax on top of CommonMark, but there was no way to
write a literal "#NAS" — it always became a clickable tag (issue #6035).

Handle escapes lexically, the way TipTap/prosemirror-markdown do, with no
"escaped tag" node in the document model:

- Parse: marked's built-in backslash escape already turns "\#NAS" into
  plain text; the read-only renderer (remark-tag) now honors the same
  escape by lexing from the original source slice and falling back to the
  prior value-based parse when it can't faithfully reconstruct the text.
- Serialize: a tag-aware Markdown extension (tagMarkdown.ts) backslash-
  escapes a "#" that would re-parse into a tag, skipping links and code
  where tags never form.
- The editor's #tag lexing moves to the canonical @tiptap/markdown
  markdownTokenizer; tag-in-link skipping moves to a tree pass so the
  editor and renderer agree.

The capped tag-run grammar is consolidated into utils/tag-grammar.ts
(TAG_RUN), shared by the tokenizer, the serialize-escape, and the
renderer so they can't drift. README documents why the markdown manager
is worked around in three places.
2026-06-23 23:00:54 +08:00
boojack
20c19ef82d feat(storage): add insecure_skip_tls_verify option for S3
Adds an opt-in toggle to skip TLS certificate verification when connecting
to the S3 endpoint, for self-hosted S3-compatible backends (e.g. rustfs,
MinIO) that use self-signed certificates. Exposed in both the store/API
protos and the storage settings UI, mirroring the existing use_path_style
toggle. When enabled, the AWS client uses an HTTP transport with
InsecureSkipVerify; default behavior is unchanged.

This governs backend-initiated S3 calls (uploads, deletes, thumbnails, and
image/document streaming). Video/audio playback redirects the browser to a
presigned URL, so that path still requires the browser to trust the cert.

Closes #6039
2026-06-23 00:04:54 +08:00
boojack
1e3ec38fa1 refactor(editor): modularize formatting and simplify editor state
Behavior-preserving restructure of the MemoEditor subsystem for simplicity
and extensibility:

- Add a data-driven command catalog (editorCommands.ts) as the single source
  for formatting verbs; the toolbar, active-state hook, and WYSIWYG handle all
  derive from it, so adding a verb is a one-file change.
- Add a createSuggestionExtension factory; TagSuggestion consumes it, so new
  `/` or `@` triggers reuse the shared popup in ~10 lines.
- Collapse FormattingController into a single EditorController with an optional
  `formatting` capability; PlainEditor is an honest textarea fallback (no faked
  formatting); replace stringly-typed isActive with typed getActiveFormats.
- Move audio-recorder state out of the reducer into useAudioRecorder, keeping a
  single recorderBusy flag in the store.
- Convert the editor context to an external store (useSyncExternalStore) with
  per-slice subscriptions, so typing no longer re-renders the toolbar, insert
  menu, or metadata.
- Extract the shared #tag lexing grammar (tag-grammar.ts) used by both the
  editor tokenizer and the remark renderer.
- Remove dead reducer actions/cases and fix a preview blob-URL leak on the
  upload path.

Add tests for the command catalog, suggestion factory, and autosave.
2026-06-22 23:51:59 +08:00
boojack
26f4b73cb9 feat(filter): standard CEL now variable, time accessors, set ops
Replace the custom now() function with an idiomatic `now` timestamp variable (host-injected, frozen once per compile) and retype created_ts/updated_ts/create_time to CEL timestamp. Filters now use standard timestamp/duration arithmetic, e.g. `created_ts >= now - duration("24h")` and `timestamp("2025-01-01T00:00:00Z")`.

Add standard CEL surface that compiles to SQL across SQLite/MySQL/Postgres: timestamp accessors (getFullYear/getMonth/getDate/getDayOfWeek/..., with 0-based month and weekday normalized), ext.Sets() (sets.contains/intersects/equivalent over tags), tags.exists_one(), size() on string fields, and division/modulo folding. A frozen clock is injectable for deterministic tests.

BREAKING CHANGE: now() is removed (use the `now` variable) and time fields are timestamps, so bare-epoch comparisons need timestamp(<epoch>). Existing saved shortcuts using the old syntax must be updated.
2026-06-22 22:42:44 +08:00
johnnyjoygh
cafa56f1a8 chore: make compact mode an opt-in view setting
Memo list views hard-coded compact rendering, truncating long memos by
default. Make full content the default and add a persisted 'Compact mode'
toggle (default off) in the display-settings popover, backed by the
localStorage ViewContext. Wire Home/Explore/Archived/UserProfile to read
it; add the compact-mode label across all locales.
2026-06-21 22:55:56 +08:00
johnnyjoygh
96cb65320b fix(instance): add needs_setup so admin-less instances aren't treated as fresh
The frontend keyed first-run setup off a null InstanceProfile.admin, but a
null admin only means "no admin-role user exists" — which also happens on a
populated instance that has lost all its admins. Such an instance was wrongly
redirected to signup, where the new account is created as a normal user (the
first-user promotion only triggers when there are zero users), leaving the
instance permanently admin-less.

Add an explicit InstanceProfile.needs_setup derived from user count == 0, and
switch the signup redirect and host tip to use it. admin stays for display only.
2026-06-21 22:14:15 +08:00
johnnyjoygh
6eb17864df feat: surface newly created memo above pinned list 2026-06-21 14:11:46 +08:00
johnnyjoygh
deddf71d7b feat(editor): add focus-mode formatting toolbar
Add a rich-text formatting toolbar as the focus-mode header when the
WYSIWYG editor is active: heading dropdown, bold/italic/code, lists, and
link, with a priority+overflow responsive layout and live active-state
highlighting. The toolbar is a self-contained component driven through a
new FormattingController surface routed via EditorContent.

Remove the now-redundant slash-command feature (/todo, /code, /link,
/table) and its "Type / for commands" hint, since the toolbar covers
those actions; the shared suggestion renderer stays for #tag.
2026-06-21 11:57:45 +08:00
johnnyjoygh
f727ad217c fix(comments): list all memo comments via pagination
Memo detail only showed the first 10 comments: the frontend requested
pageSize=0, which the backend normalizes to DefaultPageSize (10), and the
returned nextPageToken was never followed.

Add useInfiniteMemoComments (mirrors useInfiniteMemos) so the detail page
paginates through every comment, with a "Load more" control in
MemoCommentSection. Page size defaults to DEFAULT_LIST_MEMOS_PAGE_SIZE to
match the memo list convention.
2026-06-21 09:55:37 +08:00
johnnyjoygh
f5a60263b2 chore(ui): align frontend on shadcn kit
Design system:
- add semantic --success/--warning OKLCH tokens across themes; replace
  hardcoded green/amber feedback colors and their manual dark: overrides
- drop the unused @emotion dependency

Kit usage:
- migrate raw <button>/<input> to ui-kit components (actions) or
  <div>/<span> (non-action surfaces); keep genuinely custom looks as
  raw HTML with their own styles
- make kit usage prop-only (no className overrides): add Button
  size="icon-sm", Badge "warning" variant + "pill" shape
- extract a shared Tabs primitive (segmented/underline) and migrate
  Inboxes + UserProfile onto it
- tokenize z-index tiers as z-overlay/z-dropdown/z-tooltip
- export variant types (ButtonVariant/Size, BadgeVariant/Shape, TabsVariant)
- document the kit and its policy in components/ui/README.md
2026-06-21 09:17:04 +08:00
boojack
f0e4a5624f feat(filter): expand CEL filter surface with startsWith/endsWith, matches(), and all()
Let users write three more CEL constructs in the filter field, each compiled to
SQL across SQLite/MySQL/Postgres:

- Scalar startsWith()/endsWith() on content/filename/mime_type (case-insensitive)
- matches() regex: PG ~, MySQL/SQLite REGEXP (Go-backed SQLite fn), validated at
  compile time via cel.ValidateRegexLiterals()
- all() comprehension over tags via per-element subqueries, non-empty required

Also: contains() now escapes LIKE metacharacters (%, _, \); cross-dialect render
tests plus behavioral tests; cel-go bumped to v0.28.1; new operators surfaced in
the frontend shortcut guide.
2026-06-15 23:22:28 +08:00
boojack
817561df8f fix(editor): collapse lingering select-all selection after delete
Ctrl+A creates a whole-document AllSelection; deleting it (Backspace, Delete, or Cut) maps the AllSelection onto the now-empty paragraph instead of collapsing to a caret, so the view paints a "selected" empty block. A ProseMirror appendTransaction now collapses a leftover AllSelection to a caret after any doc-changing edit.
2026-06-15 09:33:16 +08:00
ManJieqi
46685b1906
chore: update Chinese translations in zh-Hans.json (#6033)
Signed-off-by: ManJieqi <40858189+manjieqi@users.noreply.github.com>
2026-06-14 23:23:18 +08:00
boojack
00225db922 refactor(web): share markdown element styles between viewer and editor
Extract the Tailwind classes for common markdown elements (paragraph,
blockquote, lists, inline code, link, hr, headings) into a single
markdownStyles.ts consumed by both the read-only MemoContent components
and the WYSIWYG editor, replacing the duplicated per-element strings and
the .memo-wysiwyg CSS block. Heading classes are precomputed per level so
the hot renderHTML path is a lookup, not a cn() merge.

Also require at least one character after `#` before opening the tag
suggestion menu so a bare `#` (or `# ` heading) no longer conflicts with
markdown headings.
2026-06-13 22:17:00 +08:00
boojack
2c0efeba7c refactor(web): rename editor dirs and simplify raw mode to a plain textarea 2026-06-13 01:08:38 +08:00
boojack
797f1ff15d
feat(web): markdown WYSIWYG editor with raw-mode toggle (#6030)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:34:51 +08:00
Yiges.M.x.
063a44498d
feat: add optional webhook signing secret (Standard Webhooks HMAC-SHA256) (#6013) 2026-06-09 22:45:01 +08:00
boojack
1052c04d33 fix(web): improve mobile control spacing 2026-06-09 21:04:47 +08:00
boojack
418398587c feat(i18n): add searchable locale picker 2026-06-09 09:33:17 +08:00
boojack
a47d04954e feat(i18n): expand European locale coverage 2026-06-09 09:07:28 +08:00
boojack
ecbe2ab797 fix(memo): preserve expanded todo list state 2026-06-08 19:11:29 +08:00
ay5399
8f1377324f
fix(editor): wire Ctrl+B and Ctrl+I markdown shortcuts to textarea (#6016)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2026-06-08 00:24:05 +08:00
boojack
9eabb554d5
feat(settings): move tag metadata to user settings (#6017) 2026-06-07 23:58:00 +08:00
boojack
a50ce09e81 fix(markdown): ignore tags inside links 2026-06-06 00:01:28 +08:00
boojack
0e2a9a9c0c fix(web): render video attachment posters on mobile 2026-06-02 23:08:16 +08:00
boojack
0d31e3c2fb chore(media): add zoom controls to preview dialog 2026-06-02 22:46:07 +08:00
boojack
53abb8020e refactor(frontend): remove react-use dependency 2026-05-31 18:32:17 +08:00
boojack
7c3bff4e98 fix(markdown): keep task item content in one grid column 2026-05-27 23:57:23 +08:00
boojack
e0bb3a2e68 fix(editor): wrap selected text when pasting URL 2026-05-27 20:36:27 +08:00
boojack
648b3bd812
feat(memo): add task list quick actions (#5983) 2026-05-27 09:13:55 +08:00
boojack
e564c1a993 chore: update about page 2026-05-26 21:14:59 +08:00
boojack
439ddaebf5 refactor(placeholder): extract tile sprite strip 2026-05-14 20:38:00 +08:00
boojack
411ba7b34c feat(about): add about page with bird sprites 2026-05-14 20:30:37 +08:00
boojack
638e4f398e feat(placeholder): add woodpecker tilemap 2026-05-14 09:35:11 +08:00
boojack
cf55f11072 feat(frontend): add pixel bird tilemaps 2026-05-14 00:03:21 +08:00
boojack
ca2bc4eb84 chore: render placeholder ascii pieces as components 2026-05-13 09:06:23 +08:00
boojack
aa5cb455e9 refactor(web): use / as the home route instead of /home
Home now lives at `/` directly. Unauthenticated visitors are sent to
`/explore` by the landing gate; old `/home` URLs redirect to `/` for
bookmark compatibility.
2026-05-12 23:17:46 +08:00
boojack
8c16ffa1f1
feat: add <Placeholder> component with ASCII bird states (#5949)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 22:48:37 +08:00
boojack
a6024eebf1
perf: lazy load heavy first-screen dependencies (#5947) 2026-05-12 20:11:39 +08:00
boojack
f3f059b2f7 chore: add batch get settings API 2026-05-09 09:30:28 +08:00
boojack
21303e879d fix(sse): stream initial response and refresh tokens 2026-05-09 09:15:50 +08:00
boojack
88ac3ec31e feat(stats): support filtered all-user stats
- Add state and filter inputs to ListAllUserStats and reuse it for explore/archive sidebar stats.
- Reduce duplicate home initialization requests by sharing stats/settings data paths.
- Include memo paragraph regression coverage from the current working tree.
2026-05-09 09:11:04 +08:00
boojack
1df6479443
feat: add dedicated shortcuts page (#5942) 2026-05-08 23:06:12 +08:00
boojack
b6f42cbe6b
chore: upgrade frontend to React 19 (#5940) 2026-05-08 22:10:48 +08:00
hchengting
bcbcb03894
chore: update zh-Hant translation (#5930) 2026-05-04 20:18:00 +08:00
boojack
5ccba98adc
refactor: split STT and Audio-LLM into separate interfaces (#5928) 2026-05-03 00:21:58 +08:00
boojack
238f27dea1
feat(transcription): explicit STT settings with provider, model, prompt (#5926) 2026-05-02 19:35:18 +08:00
boojack
ef55013418
feat(memo): create memos on the selected calendar date (#5925) 2026-05-02 11:53:50 +08:00
Steven
d349fe4409 chore(theme): rebalance dark palette for readability 2026-05-02 09:11:46 +08:00
Steven
8daef1dc89 feat(activity-calendar): aggregate by ViewContext.timeBasis
Fixes the inconsistency where switching the memo list to update_time
left the activity heatmap aggregating by created_time. The heatmap
now follows the same time basis as the list it sits next to.

Backend
- UserStats gains memo_updated_timestamps (additive proto field, tag 8).
- GetUserStats and ListAllUserStats populate it alongside the existing
  memo_created_timestamps. No DB migration; memo.updated_ts already
  exists on every row.

Frontend
- useFilteredMemoStats reads timeBasis from ViewContext and selects
  the matching timestamp source.
- StatisticsView and MonthNavigator forward timeBasis through to
  MonthCalendar / YearCalendar so tooltip text matches the basis
  ("X memos in DATE" vs "X memos updated on DATE").
- Falls back to memoCreatedTimestamps when an old server returns an
  empty memoUpdatedTimestamps array (detected by length divergence,
  since protobuf-es deserializes missing repeated fields as []).

Tests
- Backend: TestGetUserStats_MemoUpdatedTimestamps verifies the field
  is populated and reflects post-creation updates.
- Frontend: filtered-memo-stats covers create/update source switching
  and the old-server fallback path; activity-calendar-tooltip covers
  basis-aware label selection.

Spec and implementation plan committed under docs/superpowers/.
2026-05-02 00:26:53 +08:00
Steven
ea0625da45 feat(stats): admin instance resource statistics 2026-05-01 23:15:56 +08:00
Steven
cd4f28ae10 feat(notification): add smtp email settings
- Add admin notification email settings UI and test-email RPC
- Dispatch privacy-first comment and mention emails through server notification layer
- Keep SMTP secrets write-only and require passwords when SMTP identity changes
2026-05-01 18:48:21 +08:00
Steven
a0b6417689 chore: bump pnpm to 11.0.1 and align list test assertions 2026-04-30 20:05:39 +08:00
boojack
e008b1a23c fix(markdown): align list items with checkboxes 2026-04-30 08:49:49 +08:00
boojack
0bc56694b0 feat: render link metadata cards 2026-04-29 23:23:52 +08:00
boojack
9c5c604944 feat: add link metadata endpoints 2026-04-29 22:38:08 +08:00
memoclaw
267f90a3ff
chore: refactor Settings UI structure (#5912)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-29 09:30:58 +08:00
boojack
14480bfc46 chore(settings): improve storage tags and memo panels 2026-04-28 23:28:01 +08:00
boojack
ee65e90a39
chore: upgrade pnpm to 11 (#5911) 2026-04-28 22:16:22 +08:00
Chyna
328396a97f
fix(web): sync avatar changes immediately after profile update (#5903)
Signed-off-by: Chyna <68607983+chyna-gvng@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-28 21:57:58 +08:00
Mostafa Attia
9353848603
chore: increased muted text contrast in dark theme (#5902) 2026-04-28 20:03:24 +08:00
boojack
616487fa37
chore: update backend and frontend dependencies (#5900)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-28 08:25:26 +08:00
boojack
18e729fe00 chore(memo): simplify markdown task list rendering 2026-04-27 23:22:29 +08:00
boojack
9e310bf93c chore(memo): clarify displayed update time 2026-04-27 21:50:41 +08:00
boojack
94ce1e5347 chore(settings): show build commit in version info 2026-04-27 08:51:11 +08:00
boojack
e2c60845ea fix(markdown): split mixed task and bullet lists 2026-04-26 23:25:29 +08:00
boojack
c268551a16
feat(memos): choose created or updated time for memos (#5894) 2026-04-26 11:50:26 +08:00
boojack
3949a252db style(web): refine scrollbar styling 2026-04-26 00:24:45 +08:00
boojack
34c90dd5e1 chore: remove duplicate tags from share image preview 2026-04-25 22:22:49 +08:00
boojack
ee1799851e
feat: redesign account and SSO management (#5886) 2026-04-24 09:08:58 +08:00
boojack
30c0611a82
fix: fix legacy username auth flows (#5885) 2026-04-23 22:35:38 +08:00
boojack
d688914b28
feat(auth): add SSO user identity linkage (#5883) 2026-04-23 08:51:45 +08:00
boojack
50638040f6
fix: reduce list memo query overhead (#5880) 2026-04-22 09:31:48 +08:00
boojack
b5863d76be
fix(web): preserve task checkbox state (#5867) 2026-04-20 23:27:00 +08:00
wndnjs0
d98f665919
fix: disable modal prop on DropdownMenu to prevent scroll disappearing (#5861) 2026-04-20 21:38:28 +08:00
boojack
88cb58ab64
refactor(web/routing): guard-based auth flow, migrate tests to Vitest (#5848) 2026-04-18 01:06:54 +08:00
Mattia Borda
5be530dbac
chore: update Italian translation for 'cancel' key (#5841)
Signed-off-by: Mattia Borda <mattiagiovanni.borda@icloud.com>
2026-04-15 21:01:57 +08:00
boojack
411d8335e7
chore: set native color scheme for dark themes (#5840) 2026-04-15 20:55:41 +08:00
boojack
a3a5b52d60 chore: tweak location picker 2026-04-15 20:07:36 +08:00
boojack
ab5332901f fix: hide transcribe button without AI provider 2026-04-14 21:47:59 +08:00
boojack
35504cc8bd
feat(web): add demo mode banner (#5836) 2026-04-14 09:08:17 +08:00
boojack
101704c8ea
feat(ai): add BYOK audio transcription (#5832) 2026-04-13 22:09:24 +08:00
boojack
0ad0fec8d4 feat(ai): add Anthropic provider option 2026-04-12 21:42:17 +08:00
memoclaw
d87539a1e1
feat: add Gemini transcription provider (#5830)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 21:12:03 +08:00
memoclaw
83ed32f119
feat(ai): add instance AI providers and transcription (#5829)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 19:23:34 +08:00
boojack
efeb28c872 fix: remove duplicate Japanese locale keys 2026-04-12 10:34:20 +08:00
Takuro Onoue
0f7c7eb75e
i18n: refine and normalize Japanese locale strings (#5826)
Signed-off-by: Takuro Onoue <kusanaginoturugi@gmail.com>
2026-04-11 22:15:26 +08:00
boojack
2523d966f4 chore(web): improve navigation accessibility 2026-04-10 22:27:29 +08:00
boojack
8cdcd7b284 refactor(attachments): extract visual gallery layout and tile style tokens 2026-04-10 08:55:20 +08:00
boojack
9ca71229a6 fix: preserve draft content when tab is suspended or editor remounts
Gate auto-save on initialization to prevent empty content from overwriting
cached drafts on remount. Flush drafts synchronously on visibilitychange/
pagehide so Chromium tab suspension cannot drop pending debounced saves.
Restore cached draft over saved memo content when they differ (inline editing).
2026-04-10 08:48:50 +08:00
boojack
938c405b0f refactor: move embedded content styles from global CSS to Tailwind 2026-04-08 23:34:49 +08:00
boojack
124708f164 chore: refactor attachment media layout and insert menu organization 2026-04-08 23:28:49 +08:00
boojack
7e21b728b3 fix: harden memo content iframe and HTML sanitization 2026-04-08 21:10:35 +08:00
boojack
2d682ae176 refactor(attachments): compact audio item layout and playback logic
Made-with: Cursor
2026-04-07 21:47:06 +08:00
boojack
5b78023fd5 Polish share-as-image UI and sidebar sharing actions
Made-with: Cursor
2026-04-07 21:07:40 +08:00
boojack
e51985a29f
feat(memo-editor): add compact live waveform recorder panel (#5817) 2026-04-07 20:40:34 +08:00
boojack
61c963841b chore(web): polish dark theme and calendar UI
- simplify ActivityCalendar state handling and shared max-count utilities
- remove calendar ring styling and darken the default dark theme primary colors
- tighten the audio recorder panel layout and action sizing
2026-04-06 22:44:11 +08:00