Commit Graph

2676 Commits

Author SHA1 Message Date
milvasic aa7e74d1e6
Merge 355fd9e7be into 63a17d897d 2026-03-31 23:49:49 +02:00
memoclaw 63a17d897d refactor: split audio attachment view into reusable components 2026-03-31 23:03:38 +08:00
memoclaw 1921b57662
fix(tags): allow blur-only tag metadata (#5800)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-31 21:38:55 +08:00
memoclaw e520b637fd fix: prevent stale comment drafts from being restored 2026-03-30 22:37:07 +08:00
memoclaw c53677fcba fix(api): improve SSE hub design and fix double-broadcast on comments
- Fix duplicate SSE event on comment creation: CreateMemoComment now
  suppresses the redundant memo.created broadcast from the inner
  CreateMemo call, emitting only memo.comment.created
- Extract reaction event-building IIFEs into buildMemoReactionSSEEvent
  helper, removing duplicated inline DB-fetch logic
- Promote resolveSSEAudienceCreatorID from method to free function
  (resolveSSECreatorID) since it never used the receiver
- Add userID to SSE connect/disconnect log lines for traceability
- Change canReceive default from permissive (return true) to
  deny-with-warning for unknown visibility types
- Add comprehensive tests covering all new helpers, visibility edge
  cases, slow-client drop behavior, and the double-broadcast fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 07:33:40 +08:00
milvasic 355fd9e7be
Merge branch 'usememos:main' into feat/table-editor 2026-03-28 17:21:07 +02:00
memoclaw acddef1f3d
fix(api): switch user resource names to usernames (#5779)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-25 09:11:17 +08:00
milvasic 324c644071 fix: close table dialog and restore editor focus after confirm 2026-03-24 18:50:32 +01:00
milvasic 0ad53f9dd3 refactor(table): rename resolveTableIndex, fix escapeCell backslash handling, remove redundant cast
- Rename `resolveTableIndex` useMemo value to `currentTableIndex` in Table.tsx
  so the name reflects a computed value rather than an action; update all
  references (callbacks, dependency arrays, JSDoc comment)

- Fix `escapeCell` in markdown-table.ts: replace the single-char lookbehind
  regex `(?<!\\)|` with a character loop that counts consecutive backslashes
  before each pipe and only inserts an escape when the count is even, mirroring
  the parser logic and correctly handling sequences like `\\|`

- Remove redundant `as ColumnAlignment` type assertion in `createEmptyTable`;
  TypeScript infers `\"none\"` correctly via contextual typing from the return type

- Add regression test for the `\\|` round-trip case in markdown-table.test.ts
2026-03-24 18:42:47 +01:00
milvasic 26dec86b70 fix(markdown-table): handle escaped backslashes before pipe separators; use @/ alias in test import
- Rewrite parseRow to count consecutive backslashes before each pipe so
  that `\\|` (escaped backslash + unescaped pipe) is correctly treated as
  a column separator. The previous lookbehind regex (?<!\\)| only checked
  the single character immediately before the pipe, causing it to fail for
  an even number of preceding backslashes.
- Update test file import from relative `./markdown-table` to the project
  alias `@/utils/markdown-table` for consistency with frontend conventions.
2026-03-24 18:33:16 +01:00
milvasic aa0f072c42 perf(Table): memoize findAllTables result to avoid redundant AST parses
Hoist `findAllTables(memo.content)` into a shared `useMemo` so the
markdown AST is parsed exactly once per `memo.content` change.
Both `resolveTableIndex` and `handleEditClick` now reference the same
cached `tables` array, keeping the lookup and edit paths in sync and
eliminating the duplicate parse that previously occurred on every edit
click.
2026-03-24 18:33:16 +01:00
milvasic 004e667b7a fix(table): escape pipe chars in cells on serialize, unescape on parse
- escapeCell() replaces unescaped | with \| before writing each cell,
  applied in both width calculation and formatRow so padding is accurate
- parseRow unescapes \| back to | after splitting on unescaped pipes
- Adds round-trip regression test for cells containing pipe characters

Addresses coderabbitai review comment on PR #5680.
2026-03-24 18:33:16 +01:00
milvasic 314ab03715 fix(table): use GFM AST parser for findAllTables; fix lints
- Replace regex-based TABLE_LINE scan in findAllTables with a proper
  GFM markdown AST lookup using mdast-util-from-markdown + mdast-util-gfm
  + micromark-extension-gfm + unist-util-visit (all already in deps).
  Tables without leading/trailing pipes (e.g. 'A | B\n--- | ---\n1 | 2')
  are now correctly detected via node.position.start/end.offset.
- Add regression test asserting pipe-less GFM table is found with correct
  start/end offsets.
- Fix parseMarkdownTable to split on unescaped pipes only (lookbehind).
- Fix import order in Table.tsx (Biome organizeImports).
- Fix useless escape \- → - in TableEditorDialog.tsx sort regex.
- Reformat long normalize/compareFn lines to satisfy Biome formatter.
2026-03-24 18:33:16 +01:00
milvasic 651c4085bf pnpm format 2026-03-24 18:33:16 +01:00
milvasic 9cbf5ebac4 fix: forward node prop to Table component for AST-based index resolution\n\nThe table component mapping in MemoContent discarded the `node` prop\nfrom react-markdown, so `node.position.start.offset` was always\nundefined and the edit button never opened the table editor." 2026-03-24 18:32:49 +01:00
milvasic a759acc6a7 fix: address PR review comments for table editor
Bugs:
- Fix replaceNthTable off-by-one: findAllTables now uses truly exclusive
  end index (start + text.length) so content.slice(start, end) === text
- Replace fragile DOM-based table index resolution with AST-based approach
  using node.position.start.offset from hast ReactMarkdownProps

Architecture:
- Unify TableEditorDialog instances: InsertMenu no longer manages its own
  dialog, instead calls onOpenTableEditor from parent MemoEditor which
  owns the single shared dialog instance
- Remove onInsertText prop chain (InsertMenu → EditorToolbar → MemoEditor)
  replaced by onOpenTableEditor

Other improvements:
- Add i18n: all hardcoded English strings now use useTranslate()/t() with
  new editor.table.* keys in en.json
- Fix useCallback [props] dependency that defeated memoization (removed
  with dialog unification)
- Use stable row IDs (monotonic counter) as React keys instead of array
  indices in TableEditorDialog
- Replace hardcoded MONO_FONT constant with Tailwind font-mono class
  (maps to project's --font-mono CSS variable)
- Add 28 vitest tests for markdown-table.ts covering parse, serialize,
  findAllTables, replaceNthTable, createEmptyTable with edge cases
- Add vitest dev dependency with test/test:watch scripts
2026-03-24 18:32:49 +01:00
Milan Vasić 0aada4230c Lint run 2026-03-24 18:27:17 +01:00
Milan Vasić b4c2c180b8 feat: table editor dialog for visual markdown table editing
Add a dialog-based table editor to create and edit markdown tables via a
visual grid instead of raw pipe-delimited text.

Features:
- Visual grid with inputs for headers and cells; add/remove rows and columns
- Sort columns (asc/desc, text and numeric); tab navigation (new row at end)
- Insert column/row between columns/rows via hover zones and + buttons with
  blue highlight lines clipped to table bounds
- Sticky header with solid background; square headers; monospace cell font
- Row numbers with insert zones; delete row at row end; delete column with
  spacing from insert button; Add row/Add column in footer and below table
- Delete table button on rendered tables (with confirm); edit pencil opens
  dialog with parsed data; always-visible sort/delete at 40% opacity
- Fixed-size dialog (56rem x 44rem); /table slash command and Table in
  InsertMenu open dialog; Command.action support for dialog-based commands

New: TableEditorDialog.tsx, utils/markdown-table.ts. Integration in
SlashCommands, EditorContent, InsertMenu, MemoContent Table.

Made-with: Cursor
2026-03-24 18:27:17 +01:00
memoclaw 4f6730a12e chore: show compact attachment count instead of thumbnails in comment previews
When truncate mode is active (comment list), display an inline file icon
with attachment count instead of rendering full image thumbnails.
2026-03-24 19:30:39 +08:00
memoclaw 6a03917f6e chore: upgrade TypeScript to 6.0.2 2026-03-24 08:45:56 +08:00
memoclaw bb7f4978e5
refactor(web): consolidate SharedMemo into MemoDetail (#5773)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-24 08:40:49 +08:00
memoclaw 6b30579903
feat: add outline navigation to memo detail sidebar (#5771)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-24 00:20:40 +08:00
memoclaw 2aaca27bd5
refactor(web): improve MemoDetail and sidebar maintainability (#5769)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-23 22:51:24 +08:00
memoclaw e176b28c80
feat(memo-preview): support comment metadata in previews (#5768)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-23 21:51:30 +08:00
memoclaw 22519b57a0 fix(web): prevent MemoContent prop leaks 2026-03-23 20:34:14 +08:00
memoclaw 45b21530d9
feat: add blur_content attribute to tag metadata settings (#5767)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-23 19:42:27 +08:00
memoclaw 9e04049632
feat: treat tag setting keys as anchored regex patterns (#5759)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 08:07:45 +08:00
memoclaw 9ded59a1aa
refactor(web): improve Settings page maintainability and consistency (#5757)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-21 15:05:48 +08:00
memoclaw d5de325ff4
refactor(web): simplify main layout sidebar structure (#5756)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-21 12:54:18 +08:00
memoclaw 4177898054
refactor(web): consolidate memo metadata components into MemoMetadata (#5755)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-21 09:04:15 +08:00
memoclaw ac077ac3d3
refactor(web): improve MemoView and MemoEditor maintainability (#5754)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-21 07:20:18 +08:00
memoclaw 7b4f3a9fa5 refactor(memo): simplify MemoDetail error handling, drop memo.failed-to-load i18n key
The failed-to-load key was only used for non-ConnectError exceptions, which
are unreachable in practice since the Connect RPC client always wraps errors
as ConnectError. Use (error as Error).message as a plain fallback instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 20:19:44 +08:00
memoclaw 5f6f624635 i18n: add missing auth.protected-memo-notice and memo.failed-to-load fallbacks to all locales
30 locale files were missing the two keys added in the auth redirect PR.
Added English fallback strings so all locales render properly until
community translations are contributed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 19:41:12 +08:00
xun zhao 7601708ae4
Redirect unauthenticated protected memo access to sign in (#5738) 2026-03-20 19:40:19 +08:00
fiatcode 551ee1d81f
fix(auth): recover session via refresh cookie when localStorage is empty (#5748) 2026-03-20 19:21:11 +08:00
memoclaw be00abe852
fix: sync html lang attribute with active locale (#5753)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 19:17:30 +08:00
google-labs-jules[bot] 23a7e99a21
chore: optimize unreact network requests (#5747)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2026-03-20 18:08:28 +08:00
memoclaw a7cabb7ce6
refactor(web): remove masonry memo layout (#5746)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-20 09:01:43 +08:00
memoclaw 05810e7882
fix(memo-editor): scope Cmd+Enter save to the active editor (#5745)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-20 08:43:01 +08:00
memoclaw e0334cf0a8
refactor: restructure i18n locale keys for better maintainability (#5744)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 05:56:56 +08:00
memoclaw 6f1f3d81c5
chore: remove disallow_public_visibility setting (#5743)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 00:00:51 +08:00
memoclaw 3f3133d6e2
feat(memo): add share links for private memos (#5742)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 23:47:22 +08:00
memoclaw a249d06e2e
feat(instance): add notification transport setting (#5737)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 09:18:28 +08:00
boojack 65d14fbb63
feat(instance): add canonical tag metadata setting (#5736) 2026-03-19 08:54:43 +08:00
boojack 330291d4d9
feat(user): add per-user tag metadata settings (#5735) 2026-03-18 23:15:14 +08:00
boojack 04f239a2fc
fix(api): remove public activity service (#5734) 2026-03-18 22:42:57 +08:00
Nix 89c6902895
feat(i18n): update sse connect label in Chinese (#5732) 2026-03-18 18:53:09 +08:00
memoclaw 6f5f0d94e8
chore(web): update frontend dependencies and Node runtime (#5729) 2026-03-16 20:37:16 +08:00
memoclaw 1e688b2a5d
feat: extract title from first H1 heading into memo property (#5726)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:05:03 +08:00
memoclaw 8f43e8075b
fix: correct typos in comments, error messages, and identifiers (#5704)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:40:17 +08:00