Commit graph

2813 commits

Author SHA1 Message Date
Steven
3a5d3c8ff9 feat: show inline comment preview in list view
Add a comment preview section below memo cards in list view, displaying
up to 3 comment snippets with a "View all" link. Removes the old comment
count icon from the memo header in favor of this richer inline display.
Comment preview is hidden in memo detail view.
2026-03-03 21:40:56 +08:00
Steven
3e4c052f44 chore: unify table style 2026-03-03 21:07:28 +08:00
Steven
4321887a02 chore: fix linter 2026-03-03 08:50:57 +08:00
Lincoln Nogueira
d0764fb0be
i18n: update all locale translations (#5679) 2026-03-03 08:49:08 +08:00
Steven
98859eb5e5 fix(routing): redirect unauthenticated users to /explore when public visibility is allowed 2026-03-03 08:48:54 +08:00
Steven
737acbba2f fix(markdown): support height/width attributes on img elements 2026-03-02 22:45:36 +08:00
Steven
dfab67f035 chore(seed): polish demo data with realistic multi-user content 2026-03-02 21:50:47 +08:00
Steven
6b37fcc01b fix: improve KaTeX and Mermaid error handling and overflow 2026-03-02 21:11:07 +08:00
Steven
7f753bf6d7 refactor(theme): consolidate theme system and polish dark mode colors
- Reduce themes from 6 to 4: system, light, dark, paper
  - Remove midnight (too similar to dark) and whitewall (too similar to light)
  - Drop all unused tokens: chart-*, sidebar-primary, sidebar-border,
    sidebar-ring, shadow-2xs, tracking-normal, spacing
  - Remove redundant @theme inline blocks from dynamic theme files
    (Tailwind only processes them at compile time, not at runtime)
  - Move shared tokens (fonts, radius) to default.css only

- Polish dark mode color palette
  - Consistent cool-slate hue (h265) across all surfaces
  - Proper surface layering: sidebar(0.07) → bg(0.09) → card(0.13) →
    popover(0.17) → secondary(0.19) → muted(0.21) → accent(0.22)
  - Foreground softened to 0.82 (from 0.9) — comfortable off-white
  - Accent more chromatic than muted (0.012 vs 0.008) — hover feels interactive
  - Popover elevated above card (0.17 vs 0.13) — floating elements visible
  - Destructive more vivid (0.62/c0.20) — clearly red on dark surfaces
  - Input border (0.25) more distinct than layout border (0.21)
  - Sidebar foreground (0.68) dimmer than content foreground (0.82)

- Fix inline code background invisible in dark mode (#5674)
  - Muted was same lightness as card — increased to 0.21 for clear contrast
2026-03-02 09:30:57 +08:00
Johnny
16576be111 chore: polish MemoDetailSidebar for consistent structure and styles 2026-03-01 21:22:11 +08:00
Johnny
53a8a436ba chore: fix frontend linter 2026-03-01 19:51:52 +08:00
Johnny
026ea92f7b fix(editor): show newly linked memos when editing a memo with attachments 2026-03-01 19:16:57 +08:00
mostapko
104d2ec0a6
feat(ui): allow navigating between images with arrows in preview dialog (#5669) 2026-03-01 11:30:47 +08:00
Steven
664b8c5629 fix(ui): unify metadata component styles across MemoView and MemoEditor
Align header padding, text color, background tokens, and item row styles
across CodeBlock, AttachmentList, RelationList, and LocationDisplay so all
metadata panels follow the same visual pattern.
2026-02-26 23:18:11 +08:00
milvasic
6b0736b293
fix(ui): show comment editor above the comment list (#5662) 2026-02-26 08:50:27 +08:00
Steven
f7ac6a0191 refactor: auth token refresh flow and simplify user hooks 2026-02-25 22:08:18 +08:00
Steven
333c9df233 fix(web): refresh memo detail cache after editor save 2026-02-25 20:03:09 +08:00
Steven
bbdc998646 fix(web): use BroadcastChannel to sync token refreshes across tabs
When multiple tabs are open and a token expires, each tab independently
attempts a refresh. With server-side token rotation this causes all but
the first tab to fail, logging the user out.

Add a BroadcastChannel (memos_token_sync) so that when any tab
successfully refreshes, it broadcasts the new token to all other tabs.
Receiving tabs adopt the token in-memory immediately, skipping their own
refresh request and avoiding conflicts with token rotation.

Falls back gracefully when BroadcastChannel is unavailable (e.g. some
privacy modes).
2026-02-24 23:31:59 +08:00
Steven
9ecd7b876b fix(web): fix spurious logout on page reload with expired access token
Two bugs caused users to be redirected to /auth too frequently:

1. Race condition in Promise.all([initInstance(), initAuth()]):
   initInstance() makes a gRPC request whose auth interceptor calls
   getAccessToken() synchronously. When the access token was expired,
   getAccessToken() eagerly deleted it from localStorage as a "cleanup"
   side-effect. By the time initAuth() ran and checked hasStoredToken(),
   localStorage was already empty, so it skipped the getCurrentUser()
   call and the token refresh cycle entirely — logging the user out even
   when the refresh-token cookie was still valid. Fix: remove the
   localStorage deletion from getAccessToken(); clearAccessToken()
   (called on confirmed auth failure and logout) handles proper cleanup.

2. React Query retry: 1 caused a second refresh+redirect attempt after
   auth failures. The auth interceptor already handles token refresh and
   request retry internally. If it still throws Unauthenticated, the
   redirect is already in flight — a React Query retry only fires another
   failed refresh and a redundant redirectOnAuthFailure() call. Fix: use
   a shouldRetry function that skips retries for Unauthenticated errors
   while keeping the existing once-retry behaviour for other errors.
2026-02-23 14:08:59 +08:00
Steven
03c30b8ccb fix(web): fix explore page showing private tags and improve stats hook
The explore page sidebar was showing tags from the current user's private
memos because the default ListMemos query applies a server-side OR filter
(creator_id == X || visibility in [...]), mixing private content in.

Fix by using a visibility-scoped ListMemos request in the explore context
so private memos are always excluded via the AND'd server auth filter.

Also consolidate two always-firing useMemos calls into one context-aware
query, unify activity stats computation with countBy across all branches,
and extract a toDateString helper to remove duplicated formatting logic.
2026-02-23 13:15:01 +08:00
Steven
1cea9b0a78 fix(web): make MonthNavigator month label reactive to language changes
Use useTranslation() hook instead of the static i18n import so that
the month label re-computes when the language changes.
2026-02-23 11:04:04 +08:00
Steven
17fc8383df fix(web): improve MemoEditor layout and timestamp popover styling 2026-02-23 10:20:00 +08:00
Steven
c3061002f3 fix(web): persist auth token in localStorage for cross-tab sessions
Switch from sessionStorage to localStorage so the auth token survives
across tabs and browser restarts, matching standard platform behavior.
Also guard the signup redirect in App.tsx behind profileLoaded to avoid
a false redirect when the instance profile fetch fails.
2026-02-22 13:55:46 +08:00
Steven
4aaebc507e fix(web): skip GetCurrentUser on init when no token is stored
When no token exists in sessionStorage, AuthContext.initialize() was
still calling GetCurrentUser, triggering the auth interceptor to attempt
RefreshToken and retry — producing a burst of 5+ auth API calls in under
a second that reverse proxies with rate limiting (e.g. CrowdSec) flag as
brute force.

Add hasStoredToken() to auth-state and bail out of initialize() early
when there is definitively no session to restore. The refresh flow for
expired tokens is preserved since hasStoredToken() checks for presence
regardless of expiry.

Fixes #5647
2026-02-22 13:40:34 +08:00
Steven
b8bca6bacf fix(web): scope task list item index to memo content container
The closest() selector was targeting a CSS class that never existed on
the container, causing fallback to document.body and collecting task
items across all visible memos. This caused index collisions when
multiple memos with todo lists were on the page.

Adds data-memo-content attribute to the container and updates the
selector accordingly.

Fixes #5635
2026-02-22 13:20:29 +08:00
Steven
2ab476ef2e fix(web): memoize useNavigateTo to prevent infinite view transition loop
Wrapping the returned function in useCallback prevents a new reference
on every render, which was causing an infinite startViewTransition loop
on the initial signup page (fresh install with no admin).

Fixes #5626
2026-02-22 13:16:59 +08:00
Steven
6eaab52e48 fix(web): handle delete memo errors and only run post-delete actions on success 2026-02-22 13:00:36 +08:00
milvasic
1d9d4cd797
fix: invalidate comments query on comment reaction and delete (#5641) 2026-02-22 12:58:56 +08:00
Kaki021
122ac94273
fix(web): ensure default memo visibility is correctly applied (#5623) 2026-02-14 16:58:58 +08:00
Steven
861b58cbf3 refactor(web): extract NsfwOverlay into standalone component with flexbox centering 2026-02-12 23:19:54 +08:00
Steven
aeb1e5fe40 perf(web): eliminate redundant fetch when opening inline memo editor 2026-02-12 23:02:25 +08:00
Johnny
6402618c26 feat(web): replace EditableTimestamp with inline editor timestamp popover 2026-02-11 23:45:53 +08:00
Johnny
566fdccae6 fix(web): allow calendar year picker to go back to 1970 2026-02-11 22:58:25 +08:00
Johnny
177a74e82b fix: allow ampersand in tags to support compound tags 2026-02-11 22:55:45 +08:00
Steven
47e2ace690 fix(web): redirect to auth page instead of explore on session expiry
Fixes #5617
2026-02-10 21:15:44 +08:00
MuLingQwQ
b5108b4f97
fix(web): calendar navigation should use current page path (#5605) 2026-02-09 20:40:12 +08:00
Johnny
f827296d6b chore: fix broken links 2026-02-08 19:46:03 +08:00
Johnny
c4176b4ef1 fix: videos attachment 2026-02-07 16:03:52 +08:00
Steven
81ef53b398 fix: prevent 401 errors on window focus when token expires
Fixes #5589

When the page returns from background to foreground after the JWT
token expires (~15 min), React Query's automatic refetch-on-focus
triggers multiple API calls simultaneously. These all fail with 401
Unauthorized, leaving the user with empty content.

Solution:
- Add useTokenRefreshOnFocus hook that listens to visibilitychange
- Proactively refresh token BEFORE React Query refetches
- Uses 2-minute buffer to catch expiring tokens early
- Graceful error handling - logs error but doesn't block

Changes:
- Created web/src/hooks/useTokenRefreshOnFocus.ts
- Updated isTokenExpired() to accept optional buffer parameter
- Exported refreshAccessToken() for use by the hook
- Integrated hook into AppInitializer (only when user authenticated)
2026-02-05 22:14:48 +08:00
Steven
cf65f0867b refactor: remove hide-scrollbar utility
Removed the hide-scrollbar CSS class and all its usages throughout the
codebase. Hiding scrollbars can hurt UX by making it unclear when
content is scrollable.

Changes:
- Removed hide-scrollbar CSS definition from index.css
- Removed hide-scrollbar class from Navigation component (2 instances)
- Removed hide-scrollbar class from MemoDetailSidebar (2 instances)
- Removed hide-scrollbar class from TagsSection
- Removed hide-scrollbar class from ShortcutsSection

Components now use standard browser scrollbar behavior, which provides
better visual feedback to users about scrollable content. Modern
browsers already handle scrollbar appearance elegantly.
2026-02-04 20:24:54 +08:00
Steven
74b63b278c perf: disable tooltips in year calendar to fix lag
Fixed issue #5579 where the calendar selection dialog was very laggy.

The root cause was rendering ~365 individual Tooltip components when
opening the year calendar view (one per day with activity). This created
a huge number of DOM nodes and event listeners that caused significant
performance issues.

Changes:
- Added disableTooltips prop to MonthCalendar and CalendarCell components
- Disabled tooltips in YearCalendar's small month views
- Removed unnecessary TooltipProvider wrapper in YearCalendar
- Tooltips remain enabled in the default month calendar view

Performance improvements:
- Eliminates ~365 tooltip instances when dialog opens
- Reduces initial render time significantly
- Makes dialog interactions smooth and responsive

Users can still click on dates to drill down for details if needed.
2026-02-04 20:14:55 +08:00
Steven
e7605d90da fix: shortcut edit button opens create dialog instead of edit dialog
Fixed issue #5576 where clicking the edit button on a shortcut would
incorrectly open a create dialog instead of an edit dialog.

The root cause was an incorrect useEffect that was watching the shortcut
state itself instead of the initialShortcut prop. When the dialog was
opened for editing, the state wasn't properly reinitializing with the
existing shortcut data.

Changed the useEffect to:
- Watch initialShortcut as the dependency
- Reinitialize the shortcut state when initialShortcut changes
- Properly distinguishes between create (initialShortcut undefined) and
  edit (initialShortcut has data) modes
2026-02-04 20:03:53 +08:00
memory_clear
f9bf903eea
chore: update access token deletion message description for zh-Hans (#5573)
Signed-off-by: memory_clear <83893503+MemoryClear@users.noreply.github.com>
2026-02-04 19:54:51 +08:00
Steven
6bb383a4a5 fix: prevent CTRL+Enter save while editor is loading content (#5581)
- Add validation check for loading state before allowing save
- Prevents false "Content, attachment, or file required" error
- Occurs when user presses CTRL+Enter immediately after opening edit mode
- Editor state may still be loading when keyboard shortcut fires

Closes #5581
2026-02-03 23:55:07 +08:00
Steven
b4fea8c647 fix: nested task list display and checkbox interaction (#5575)
- Fix nested task lists not showing proper indentation
- Use simple CSS cascade with [&_ul.contains-task-list]:ml-6
- Fix checkbox clicks toggling wrong tasks in nested lists
- Search from memo root container for global task indexing
- Remove complex selectors in favor of standard approach
- Match behavior of GitHub, Notion, and other platforms

Closes #5575
2026-02-03 23:45:45 +08:00
Steven
cf0a285ef1 fix(auth): make PKCE optional for OAuth sign-in (#5570)
Fixes issue where OAuth sign-in fails with 'Cannot read properties of
undefined (reading 'digest')' when accessing Memos over HTTP.

The crypto.subtle API is only available in secure contexts (HTTPS or
localhost), but PKCE (RFC 7636) is optional per OAuth 2.0 standards.

Changes:
- Make PKCE generation optional with graceful fallback
- Use PKCE when crypto.subtle available (HTTPS/localhost)
- Fall back to standard OAuth flow when unavailable (HTTP)
- Log warning to console when PKCE unavailable
- Only include code_challenge in auth URL when PKCE enabled

The backend already supports optional PKCE (empty codeVerifier), so no
backend changes needed. This fix aligns frontend behavior with backend.

Benefits:
- OAuth sign-in works on HTTP deployments (reverse proxy scenarios)
- Enhanced security (PKCE) still used when HTTPS available
- Backward compatible with OAuth providers that don't support PKCE

Fixes #5570
2026-02-02 23:28:21 +08:00
Steven
29412f4690 refactor: simplify NSFW implementation by inlining logic
- Remove unused showNsfwContent prop (was only used in MemoDetail to pre-reveal NSFW, which defeats the purpose)
- Inline useNsfwContent hook logic directly into MemoView.tsx (only 3 lines, no reusability benefit)
- Delete web/src/components/MemoView/hooks/useNsfwContent.ts
- NSFW content now consistently starts hidden across all pages
- Maintains same user experience: click to reveal, no toggle back

This removes unnecessary indirection and prop threading while preserving functionality.
2026-02-02 22:06:04 +08:00
Steven
6db58fae11 fix: prevent private memos from disappearing during token refresh (#5565)
Root cause: enabled={isInitialized && !!user} prevented displaying cached
data when user auth state transitioned during token refresh.

Changes:
- Remove !!user check from Home page enabled condition
- Add clearAccessToken() in redirectOnAuthFailure for clean logout

Fixes #5565
2026-02-02 21:45:24 +08:00
Damian Jankowski
c14843fa62
chore: view memo URL updated (#5569) 2026-02-02 20:39:33 +08:00
Steven
2db57b139a fix: handle pasted files in memo editor
Fixes #5568
2026-02-02 20:36:08 +08:00
Steven
0dbc35a2ba fix: restore access token creation flow
Fixes #5563
2026-02-02 20:31:22 +08:00
Steven
34c341c88c chore: fix update user request name in member dialog
Fixed #5564
2026-02-02 19:52:46 +08:00
Steven
b8029c70ef chore: fix OAuth callback double-run state error 2026-02-02 09:07:55 +08:00
Ganesh M
27de96d440
fix(ui): math render (#5549) 2026-01-31 21:46:19 +08:00
Johnny
8cd9c591d4 chore: deprecate remove completed tasks action
- Remove menu item and dialog from MemoActionMenu
- Remove removeCompletedTasks() and hasCompletedTasks() utilities
- Remove translation keys from all 34 locale files
- Feature was not aligned with standard note-taking UX patterns
2026-01-31 21:03:05 +08:00
Johnny
5396c126b8 chore: extract task list class names to constants
- Add TASK_LIST_CLASS and TASK_LIST_ITEM_CLASS constants
- Replace hardcoded 'contains-task-list' and 'task-list-item' strings
- Improve maintainability and prevent typos
2026-01-31 20:53:55 +08:00
Johnny
97ba15450f chore: prevent unnecessary API calls when timestamp unchanged in MemoDetailSidebar
- Add same value check before updating createTime/updateTime
- Skip request if new timestamp equals current timestamp
- Simplify callback handlers and improve code readability
- Use .some() instead of .filter().length for cleaner code
2026-01-31 15:12:27 +08:00
Johnny
f7a81296fb style: enhance ActivityCalendar components with improved styling and layout adjustments 2026-01-30 00:13:58 +08:00
Johnny
fcb9e377c1 chore: streamline memo editor insert menu 2026-01-29 23:34:40 +08:00
Steven
b0558824c4 feat: update instance profile to use admin user instead of initialized flag
- Changed InstanceProfile to include admin user field
- Updated GetInstanceProfile method to retrieve admin user
- Modified related tests to reflect changes in admin user retrieval
- Removed owner cache logic and tests, introducing new admin cache tests
2026-01-28 23:27:53 +08:00
Johnny
81022123a1 chore: simplify page loading logic 2026-01-27 23:37:32 +08:00
cui
c5d9770fd1
typo: lenght to length (#5539) 2026-01-27 22:21:55 +08:00
Johnny
6731eccded feat: add EditableTimestamp component for inline date editing in MemoDetailSidebar 2026-01-26 23:23:14 +08:00
Brent Bilis
2f7c8dcea7
fix(ui): correct calendar header month parsing (#5532)
Co-authored-by: Local Admin <root@localhost>
2026-01-26 22:01:11 +08:00
Johnny
e1888153f8 chore: polish dark styles 2026-01-26 21:59:36 +08:00
Johnny
98eaff1277 style: adjust spacing and background colors for improved UI consistency across components 2026-01-26 21:49:26 +08:00
Johnny
72c7965c8f chore: enable binary format for transport 2026-01-26 21:16:06 +08:00
itzmk21
f22b3dad25
chore(i18n): update British English spelling (#5529) 2026-01-26 08:48:43 +08:00
XIN_____
45945a1df7
chore: update Chinese translation (#5519) 2026-01-23 23:32:58 +08:00
Johnny
ad327a4a8d fix: adjust compact mode styling for MemoContent component 2026-01-23 09:11:33 +08:00
Johnny
7154ce0228 feat: implement markdown components for enhanced rendering 2026-01-23 09:04:42 +08:00
Steven
c0d6224155 chore: enable compact mode for list view 2026-01-22 22:52:14 +08:00
Steven
6c9ea31de0 chore: add translation for saving status in EditorToolbar 2026-01-22 22:31:19 +08:00
Steven
ba099b72ed feat: update InstanceProfile to include initialization status
- Removed the owner field from InstanceProfile as it is no longer needed.
- Added an initialized field to InstanceProfile to indicate if the instance has completed first-time setup.
- Updated GetInstanceProfile method to set initialized based on the existence of an admin user.
- Modified tests to reflect changes in InstanceProfile and ensure correct behavior regarding instance initialization.
- Adjusted frontend logic to redirect users based on the initialized status instead of the owner field.
2026-01-22 20:59:40 +08:00
Steven
c240b70591 feat: add enabled option to useInfiniteMemos and PagedMemoList for conditional fetching 2026-01-22 20:21:16 +08:00
Johnny
0f3c9a467d refactor: migrate HOST roles to ADMIN
- Updated the isSuperUser function to only check for ADMIN role.
- Added SQL migration scripts for MySQL, PostgreSQL, and SQLite to change user roles from HOST to ADMIN.
- Created a new SQLite migration to alter the user table structure and ensure data integrity during the migration process.
2026-01-20 23:38:30 +08:00
Johnny
47ebb04dc3 refactor: remove mode flag and introduce explicit demo flag 2026-01-20 22:58:33 +08:00
Johnny
dc7ec8a8ad feat: allow setting custom timestamps when creating memos and comments
Allow API users to set custom create_time, update_time, and display_time
when creating memos and comments. This enables importing historical data
with accurate timestamps.

Changes:
- Update proto definitions: change create_time and update_time from
  OUTPUT_ONLY to OPTIONAL to allow setting on creation
- Modify CreateMemo service to handle custom timestamps from request
- Update database drivers (SQLite, MySQL, PostgreSQL) to support
  inserting custom timestamps when provided
- Add comprehensive test coverage for custom timestamp functionality
- Maintain backward compatibility: auto-generated timestamps still
  work when custom values are not provided
- Fix golangci-lint issues in plugin/filter (godot and revive)

Fixes #5483
2026-01-17 12:56:03 +08:00
Johnny
253e79c111 style: remove unnecessary font-weight classes for cleaner UI 2026-01-13 23:19:43 +08:00
Steven
73c301072b refactor: simplify editor scroll logic
- Extract `scrollToCaret` helper to deduplicate scroll logic
- Unify precise scroll behavior for both manual triggers and auto-scroll
2026-01-13 21:23:23 +08:00
Steven
4e34ef22bf fix: improve editor auto-scroll and Safari IME handling (#5469)
- Use `textarea-caret` for precise cursor position calculation instead of line approximation
- Update `scrollToCursor` to scroll to the actual cursor position
- Fix Safari double-enter issue with IME in list completion
2026-01-13 21:19:31 +08:00
Steven
61dbca8dc2 fix: prevent browser cache from serving stale memo data (#5470)
This fixes a critical data loss issue where users editing the same memo
on multiple devices would overwrite each other's changes due to aggressive
browser caching, particularly in Chromium-based browsers and PWAs.

Changes:
- Backend: Add Cache-Control headers to all API responses to prevent
  browser HTTP caching
- Frontend: Force fresh fetch from server when opening memo editor by
  invalidating React Query cache
- Frontend: Reduce memo query staleTime from 60s to 10s for better
  collaborative editing support

Fixes #5470
2026-01-13 20:55:21 +08:00
Johnny
8f9ff5634c chore: remove redundant icon 2026-01-12 09:11:08 +08:00
Johnny
9a3451b9d1 fix(editor): filter RelationList to only show referencing memos
- Filter out COMMENT type relations, only show REFERENCE type
- When editing a memo, only show relations where current memo is the source
- Pass memoName through EditorMetadata to RelationList for filtering
2026-01-11 22:41:20 +08:00
Jongho Hong
07eac279d0
chore(i18n): add missing Korean translations (#5456)
Signed-off-by: Jongho Hong <myodan@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-08 23:13:21 +08:00
Om vataliya
013ea52519
fix: apply theme and locale changes immediately on login screen (#5440) (#5442) 2026-01-07 21:58:47 +08:00
Johnny
9ccb658768 fix: sign up redirect 2026-01-07 08:50:10 +08:00
Johnny
1f755f74a4 fix(web): make login screen theme selector reactive
This fixes an issue where the theme selector on the login screen would not update its display value after selection because the component was not re-rendering. Added local state to track the current theme. Validated that this pattern is unique to the unauthenticated context.
2026-01-06 20:51:45 +08:00
Faizaan pochi
874a4a7142
fix: KaTeX math rendering with underscores (#5438) 2026-01-06 20:16:01 +08:00
Steven
62646853eb chore: tweak comments display 2026-01-06 19:08:03 +08:00
Steven
ed66e0fec2 chore: fix linter 2026-01-06 09:08:27 +08:00
Steven
5a8e1845e2 fix: reaction button in mobile view 2026-01-06 09:06:52 +08:00
Johnny
d68ca84832 fix: delete unused attachments by using filter 2026-01-05 22:43:57 +08:00
Johnny
4b110d0d38 fix: cursor position after slash commands 2026-01-05 22:24:13 +08:00
Steven
15646a8989 chore: fix linter 2026-01-05 21:57:07 +08:00
Steven
e268a1fe9c chore: tweak memo content renderer 2026-01-05 21:50:49 +08:00
Steven
ac37738148 fix: default visibility setting 2026-01-05 21:46:35 +08:00
lif
cbbb585b2e
fix(frontend): ensure attachments are properly linked when creating memos (#5428)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 19:17:14 +08:00
Sheep-realms
b7b658358e
chore: update simplified chinese localization (#5422) 2026-01-04 19:10:24 +08:00
Roman Teitge
8cf99f5200
Update german translations (#5419)
Signed-off-by: Roman Teitge <83205200+rteitge@users.noreply.github.com>
2026-01-04 19:10:08 +08:00
Steven
06d1c60aaf chore: tweak domain format 2026-01-03 20:43:10 +08:00
Johnny
d2b421213f chore: optimize RelationList and unify RelationCard usage 2026-01-03 14:27:12 +08:00
Johnny
77e9376e03 chore: improve metadata section UI consistency and maintainability 2026-01-03 13:54:47 +08:00
Johnny
5612fb8f41 feat: add HDR image and video support
- Add HDR detection utilities for wide color gamut formats (HEIC, HEIF, WebP)
- Apply colorSpace attribute to image/video elements for HDR-capable files
- Update frontend components (AttachmentCard, PreviewImageDialog, AttachmentList)
- Expand backend thumbnail generation to support HEIC, HEIF, WebP formats
- Add Color-Gamut response headers to advertise wide gamut support
- Extend avatar MIME type validation for HDR formats

Supported formats:
- Images: HEIC, HEIF, WebP, PNG, JPEG
- Videos: MP4, QuickTime, Matroska, WebM (VP9 Profile 2)

Browser support:
- Safari 14.1+, Chrome 118+, Edge 118+
- Gracefully degrades to sRGB on unsupported browsers
2026-01-03 13:16:56 +08:00
Johnny
e761ef8684 chore: move memo-metadata components to MemoView and MemoEditor
- Remove shared memo-metadata folder
- Move metadata display components (AttachmentList, LocationDisplay, RelationList) to MemoView/components/metadata
- Move attachment types and utilities (LocalFile, AttachmentItem, toAttachmentItems) to MemoEditor/types/attachment
- Simplify AttachmentList and AttachmentCard to work directly with Attachment proto
- Update all imports across MemoEditor and MemoView components
- Better separation of concerns: MemoView handles display, MemoEditor handles local files + attachments
2026-01-03 13:07:53 +08:00
Johnny
a6e8ba7fb2
refactor: consolidate MemoEditor components (#5409) 2026-01-03 12:49:13 +08:00
Guillaume
e85a3da899
chore: add missing French locale translations (#5405)
Co-authored-by: Guillaume Reichenbach <guillaume.reichenbach@reflet-digital.com>
2026-01-03 07:46:24 +08:00
Lynchi
7b35a2672f
chore: unify the Chinese localization of ellipsis (#5404)
Signed-off-by: Lynchi <77619755+Linqi1234@users.noreply.github.com>
2026-01-03 07:45:07 +08:00
Johnny
d2acebcc53 fix: auth checks in reaction selector 2026-01-02 23:36:41 +08:00
Johnny
ef8e3cfb99 chore: remove unused keyboard shortcuts 2026-01-02 09:57:09 +08:00
Johnny
02f39c2a59 refactor: replace generic LeafletMap with dedicated LocationPicker 2026-01-02 09:36:30 +08:00
Johnny
bd02de9895
chore: add store tests (#5397) 2025-12-31 21:26:35 +08:00
Johnny
12f32acd09 chore: remove dnd-kit dependencies 2025-12-31 09:32:23 +08:00
Johnny
be1b758d30 refactor: simplify memo-metadata components 2025-12-31 09:27:37 +08:00
Johnny
d7284fe867 refactor: nest reaction resource names under memos 2025-12-30 23:29:54 +08:00
Johnny
d55af9b527 refactor: standardize loading indicators by using Spinner for route fallbacks and specializing Skeleton for memo lists 2025-12-30 21:54:22 +08:00
Johnny
61e94e8b08 refactor: replace i18n language change with loadLocale 2025-12-30 21:07:56 +08:00
Johnny
0735c11d75 feat: implement memo map in user profile 2025-12-30 20:41:44 +08:00
Johnny
f416eb00b0 refactor(web): simplify Skeleton component structure 2025-12-30 08:58:01 +08:00
Johnny
b826e90276 refactor: polish ActivityCalendar components with modern design 2025-12-29 23:40:35 +08:00
Johnny
5d677828a6 refactor: remove NSFW content settings from instance configuration 2025-12-29 20:13:54 +08:00
Johnny
96a91ebff0 chore: add week days to calendar 2025-12-29 08:59:08 +08:00
Johnny
ea3371badb chore: add ActivityCalendar components 2025-12-28 19:59:36 +08:00
Johnny
78aa41336a feat: implement attachment filtering functionality 2025-12-28 18:47:59 +08:00
Johnny
955ff0cad6 refactor: optimize user fetching in MemoCommentMessage and MemoReactionListView components 2025-12-28 17:50:43 +08:00
Johnny
115d1bacd7 refactor: replace MemoSkeleton with a new Skeleton component for improved loading states 2025-12-28 17:31:21 +08:00
Johnny
792d58b74d refactor: consolidate and update type definitions across MemoEditor components 2025-12-28 13:17:02 +08:00
Johnny
40585607f4 refactor: streamline MemoView component and related hooks, removing unused code and integrating user data 2025-12-28 12:59:55 +08:00
Johnny
64ae13839a fix: add missing @types/hast dependency 2025-12-28 12:49:41 +08:00
Johnny
85f4fc7a75 refactor: remove MemoContentContext and integrate MemoViewContext
- Deleted MemoContentContext and its associated types.
- Updated Tag and TaskListItem components to use MemoViewContext instead.
- Refactored MemoContent component to eliminate context provider and directly use derived values.
- Simplified MemoViewContext to only include essential data.
- Enhanced error handling in various components by introducing a centralized error handling utility.
- Improved type safety across components and hooks by refining TypeScript definitions.
- Updated remark plugins to enhance tag parsing and preserve node types.
2025-12-28 12:46:12 +08:00
Johnny
ab650ac86d chore: remove unused dependency react-simple-pull-to-refresh from lockfile 2025-12-27 10:26:27 +08:00
Johnny
d711d724bb chore: clean up unused imports and parameters across components 2025-12-27 10:18:38 +08:00
Johnny
0ad75b8f08 refactor: replace useResponsiveWidth with useMediaQuery across components 2025-12-26 23:44:52 +08:00
Steven
12fdf930a6 fix: invalidate React Query cache after memo reaction changes 2025-12-26 00:13:44 +08:00
Steven
6523891982 fix: react hooks order violation in MemoDetail when creating comments
Replace dynamic hook mapping with useMemoComments hook to fetch all comments
via listMemoComments API, ensuring consistent hook order across renders and
fixing page load failure after comment creation.
2025-12-25 23:40:42 +08:00
Steven
c4dfb85400 fix: ensure dispatch is used for actions in useMemoInit hook 2025-12-25 23:17:34 +08:00
Steven
28e4ade009 fix: register Catalan and Galician locales in i18n configuration
The translation files ca.json and gl.json existed but weren't registered in the locales array, preventing users from selecting these languages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:52:51 +08:00
Steven
d4e08ae2bd refactor(react-query): optimize config, add error boundary, and remove JSDoc
This commit combines multiple improvements to the React Query migration:

Performance Optimization:
- Increase default staleTime from 10s to 30s for better performance
- Reduces unnecessary network requests while maintaining data freshness

Error Handling:
- Add ErrorBoundary component with user-friendly error UI
- Integrated at app root level for comprehensive coverage
- Provides error details and reload option

Documentation:
- Add docs/auth-architecture.md explaining AuthContext design decisions
- Document why AuthContext is preferred over React Query for current user

Code Cleanup:
- Remove all JSDoc comments from hooks and components
- Keep essential inline comments for clarity
- Simplifies code readability

Files modified:
- src/lib/query-client.ts - Optimized staleTime
- src/main.tsx - Added ErrorBoundary wrapper
- src/components/ErrorBoundary.tsx - New component
- src/hooks/useMemoQueries.ts - Removed JSDoc
- src/hooks/useUserQueries.ts - Removed JSDoc
- src/components/PagedMemoList/PagedMemoList.tsx - Removed JSDoc
- docs/auth-architecture.md - New documentation

All changes verified with TypeScript compilation and production build.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:47:36 +08:00
ghose
eed935ce44
feat: contribution New Locale: Galician (gl, gl_ES) (#5376)
Signed-off-by: ghose <704948+xmgz@users.noreply.github.com>
2025-12-25 08:38:24 +08:00
dwojtas
9821d6ace4
chore: add missing keys to Polish translation, based on the en.json file (#5380) 2025-12-25 08:37:14 +08:00
Steven
b2e2b6426c perf(react-query): fix context re-renders and improve type safety
Optimizes React Query migration with performance and consistency improvements:

Performance:
- Memoize AuthContext and InstanceContext provider values to prevent unnecessary re-renders
- Convert InstanceContext getter functions to useMemo hooks
- Fix refetchSettings to avoid state dependency that caused frequent recreations

Type Safety:
- Replace 'any' types in useAttachmentQueries with proper protobuf types
- Add Attachment and ListAttachmentsRequest type imports

Query Key Consistency:
- Replace hardcoded ["users", "stats"] with userKeys.stats() factory function
- Ensures consistent cache key management across mutations

Developer Experience:
- Rename unused useCurrentUser to useCurrentUserQuery to avoid confusion
- Add documentation explaining AuthContext-based vs React Query current user hooks
- Update internal references in useNotifications and useTagCounts

All changes verified with TypeScript compilation and build tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:29:34 +08:00
Johnny
f87f728b0f
feat: react query migration (#5379) 2025-12-24 22:59:18 +08:00
Johnny
4109fe3245 chore(MemoEditor): enhance focus mode handling and improve editor layout 2025-12-23 20:11:38 +08:00
Johnny
595daaa163 style: organize imports in MemoView hooks 2025-12-23 19:33:31 +08:00
Johnny
0f9322ea11 fix(MemoEditor): dispatch toggleFocusMode action properly
- Wrap actions.toggleFocusMode() with dispatch() call
- Create toggleFocusMode helper function for callbacks
- Fix focus mode not toggling due to action not being dispatched
2025-12-23 19:30:38 +08:00
Johnny
201a0466e9 fix(MemoEditor): restore focus mode functionality
- Add useFocusMode hook to lock body scroll in focus mode
- Add 'f' key keyboard shortcut to toggle focus mode
- Add FocusModeExitButton inside editor
- Import and wire up all focus mode components and hooks
- Update useKeyboard to handle focus mode toggle
2025-12-23 19:20:21 +08:00
Johnny
ca84241b8a fix(MemoEditor): restore focus mode styles
- Import and use FOCUS_MODE_STYLES from constants
- Apply proper fixed positioning, shadow, and spacing in focus mode
- Add transition animation for smooth mode switching
- Replace empty 'focus-mode' class with actual Tailwind utilities
2025-12-23 19:18:24 +08:00
Johnny
f2bc115a1d fix(MemoEditor): restore wrapper styles removed by refactoring
- Add back Tailwind utility classes for proper layout
- Restore padding, border, background, and flex styles
- Fix missing styles on memo-editor-wrapper element
2025-12-23 19:17:00 +08:00
Johnny
735dd1fe4b style(MemoView): restore comments and formatting
- Add back descriptive comments removed by editor refactoring commit
- Restore original timestamp calculation format in MemoHeader
- Improve code readability with section comments
2025-12-23 19:05:29 +08:00
Johnny
e61d594ded refactor(MemoView): improve maintainability and code organization
Complete refactoring of MemoView components for better code quality:

- Split useMemoViewState into individual hook files (useMemoActions,
  useKeyboardShortcuts, useNsfwContent, useImagePreview, useMemoCreator)
  for single responsibility principle
- Consolidate types closer to usage - move hook-specific types to
  respective files, keep only component props in shared types.ts
- Optimize context with separate static/dynamic memoization to reduce
  unnecessary re-renders
- Simplify barrel exports to only expose public API (MemoView component
  and MemoViewProps type)
- Add comprehensive JSDoc documentation to all public APIs with usage
  examples

Benefits:
- Better maintainability: each hook file has one clear purpose
- Improved performance: context optimization prevents unnecessary re-renders
- Enhanced developer experience: clear documentation and encapsulation
- Cleaner architecture: public API is minimal, internal details hidden

All automated checks pass (TypeScript compilation, linter, production build).
2025-12-23 19:01:57 +08:00
Johnny
1b11e8c841 refactor(editor): complete state machine and services migration
BREAKING CHANGE: MemoEditor internal architecture completely refactored

## Summary

Refactored MemoEditor from hooks-based state management to a three-layer
architecture (Presentation → State → Services) using useReducer pattern.

## Changes

### Architecture
- **State Layer** (5 new files): types, actions, reducer, context, barrel export
- **Service Layer** (6 new files): error, validation, upload, cache, memo services + barrel
- **Component Layer** (3 new files): EditorToolbar, EditorContent, EditorMetadata
- **Simplified Hooks** (3 new files): useMemoInit, useAutoSave, useKeyboard

### Code Reduction
- Main component: ~380 lines → ~140 lines (-63%)
- Hooks removed: 5 old hooks (useMemoEditorState, useMemoSave, etc.)
- Total lines removed: 508 lines of old code
- Utility hooks preserved: 8 hooks still in use (useLocation, useDragAndDrop, etc.)

### Improvements
- ✅ Predictable state transitions with useReducer
- ✅ Testable business logic in pure service functions
- ✅ Cleaner component code (presentation only)
- ✅ Better separation of concerns
- ✅ Type-safe actions with discriminated unions
- ✅ Centralized error handling

## Statistics
- Files changed: 26
- Commits created: 25 (squashed into 1)
- New files: 17
- Removed files: 5
- TypeScript errors: 0
- Lint errors: 0

## Testing
Manual testing required for:
- Editor functionality (create, edit, save)
- Drag and drop
- Focus mode
- Keyboard shortcuts (Cmd/Ctrl + Enter)
- Auto-save to localStorage
2025-12-23 08:38:02 +08:00
Johnny
8a7c976758 refactor: streamline tag sorting and update coordinate handling in MemoEditor components 2025-12-22 22:54:09 +08:00
Johnny
d537591005 feat: add slash commands tooltip to InsertMenu 2025-12-22 22:42:23 +08:00
Steven
f9dd7ad853 style: improve code block styling and formatting
- Adjust CodeBlock styling for better layout and spacing
- Reorganize copy button positioning with absolute positioning
- Simplify button styling and reduce icon sizes
- Wrap MermaidBlock in pre tag for consistent structure
- Format useDropdownMenuSubHoverDelay hook call for readability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 21:27:50 +08:00
Steven
dfc0d376d1 refactor: extract submenu hover delay logic into reusable hook
- Create useDropdownMenuSubHoverDelay hook in dropdown-menu component
- Encapsulates hover delay behavior for preventing accidental submenu closure
- Eliminates code duplication at component usage sites
- Simplifies InsertMenu by removing 45 lines of timeout/state management code
- Hook provides handleTriggerEnter/Leave and handleContentEnter/Leave handlers
- Configurable closeDelay parameter (default 150ms)

This makes the hover behavior pattern reusable across any dropdown menu submenus.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 21:04:00 +08:00
Steven
332d32bd35 fix: render dates correctly in memo detail sidebar and link dialog
Convert protobuf Timestamp objects to Date before formatting
to prevent "[object Object]" from appearing in the UI.

Fixes #5368
2025-12-22 20:24:04 +08:00
Steven
be7ef74698 fix: eliminate duplicate API requests by deduplicating user fetch calls
- Add request deduplication to getOrFetchUser using RequestDeduplicator
- Consolidates multiple simultaneous calls for same user into single API request
- Prevents duplicate 401 errors and wasted network traffic
- Matches pattern already used by fetchUsers and fetchUserStats
- Remove backwards compatibility aliases (getOrFetchUserByName, getOrFetchUserByUsername)
- Update all call sites to use canonical getOrFetchUser method

Fixes issue where PagedMemoList, useMemoViewState, MainLayout, and UserProfile
were making duplicate user fetch requests when loading user data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 20:12:44 +08:00
Johnny
319a7cac94 chore: fix remark tag parse 2025-12-20 13:50:32 +08:00
Johnny
6b0f90f355 chore: prevent sensitive data caching 2025-12-20 12:33:16 +08:00
Johnny
eaef04a0a0 chore: fix linter 2025-12-20 11:55:00 +08:00
Steven
d236ef1611 feat(web): add glassmorphism map controls with Google Maps integration
- Add custom zoom controls with modern glassmorphism styling
- Add "Open in Google Maps" button for location markers
- Refactor to React component architecture with proper Leaflet integration
- Create reusable GlassButton component for maintainability
- Use React 18 createRoot for portal rendering
- Replace imperative DOM manipulation with declarative React patterns
- Add coordinate display to location metadata

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 00:18:01 +08:00
Steven
d0c3908168 refactor: remove deprecated Sessions and AccessTokens settings
- Remove ListSessions and RevokeSession RPC endpoints
- Remove Session message and SessionsSetting from UserSetting
- Remove ACCESS_TOKENS key and AccessTokensSetting
- Update references to use RefreshTokensUserSetting with its own ClientInfo
- Remove UserSessionsSection frontend component
- Clean up user store to remove session and access token settings
- Regenerate protobuf files

The system now uses:
- REFRESH_TOKENS for session management with sliding expiration
- PERSONAL_ACCESS_TOKENS for long-lived API tokens
2025-12-19 08:35:57 +08:00
Steven
b0aeb06f85 refactor(web): improve auth flow and eliminate route duplication
- Extract route paths to router/routes.ts as single source of truth
- Refactor connect.ts auth interceptor with better structure and error handling
  - Add TokenRefreshManager class to prevent race conditions
  - Implement smart redirect logic for public/private routes
  - Support unauthenticated access to explore and user profile pages
  - Add proper error handling for missing access tokens
  - Extract magic strings to named constants
- Maintain backward compatibility by aliasing Routes to ROUTES

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 22:14:30 +08:00
Johnny
50606a850e fix(auth): resolve token refresh and persistence issues
- Fix cookie expiration timezone to use GMT (RFC 6265 compliance)
- Use Connect RPC client for token refresh instead of fetch
- Fix error code checking (numeric Code.Unauthenticated instead of string)
- Prevent infinite redirect loop when already on /auth page
- Fix protobuf Timestamp conversion using timestampDate helper
- Store access token in sessionStorage to avoid unnecessary refreshes on page reload
- Add refresh token cookie fallback for attachment authentication
- Improve error handling with proper type checking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 20:56:54 +08:00
Johnny
7932f6d0d0
refactor: user auth improvements (#5360) 2025-12-18 18:15:51 +08:00
Johnny
2c2ef53737 chore: fix frontend linter 2025-12-17 09:04:05 +08:00
Johnny
642271a831 feat: add iframe support for embedded videos in markdown content 2025-12-17 08:52:59 +08:00
Steven
87b8c2b2d2 refactor(web): rename grpcweb.ts to connect.ts and enable binary format
- Rename grpcweb.ts to connect.ts to reflect ConnectRPC usage
- Enable binary protobuf format for improved performance
- Update all imports across 26 files from @/grpcweb to @/connect

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 20:15:16 +08:00
Steven
b1a52f20ed fix(web): add clipboard fallback for CodeBlock copy button in non-secure contexts
The CodeBlock component was refactored in v0.25.3 to use navigator.clipboard.writeText(),
which requires HTTPS or localhost. This caused the copy button to fail silently for users
accessing Memos over HTTP.

This fix adds a fallback to the copy-to-clipboard library (already used by all other
copy operations in the codebase) when the native clipboard API is unavailable or fails,
ensuring the copy button works reliably in all deployment scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 22:51:34 +08:00
Steven
a2ddf05933 chore: fix linter 2025-12-15 19:58:58 +08:00
Steven
1b3318f886 refactor(web): improve ActivityCalendar maintainability and add Calendar page
- Extract shared utilities and constants to eliminate code duplication
- Create dedicated Calendar page with year view and month grid
- Add date filter navigation with bidirectional URL sync
- Fix useTodayDate memoization bug causing stale date references
- Standardize naming conventions (get vs generate functions)
- Add comprehensive type exports and proper store encapsulation
- Implement size variants for compact calendar display

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 19:47:46 +08:00
Davide Truffa
8659f69da0
chore(locales): update Italian translation (#5346) 2025-12-15 10:05:32 +08:00
Steven
06a0f8d618 fix(web): convert visibility enum values to string names in filter expressions
Problem:
The Explore page filter was sending visibility filter as:
  visibility in ["3", "2"]
when it should send:
  visibility in ["PUBLIC", "PROTECTED"]

The backend CEL filter parser expects string enum names, not numeric values.
This caused the Explore page to return no memos even when public memos existed.

Solution:
- Added getVisibilityName() helper to convert Visibility enum values to string names
- Updated useMemoFilters to use getVisibilityName() when building visibility filter
- Follows same pattern as existing getInstanceSettingKeyName() and getUserSettingKeyName()
- Added validation to warn on invalid enum values

Files changed:
- web/src/store/common.ts: Add getVisibilityName() helper with validation
- web/src/hooks/useMemoFilters.ts: Use getVisibilityName() in visibility filter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 08:03:25 +08:00
Steven
8a7e00886d fix(web): convert enum values to string names in API resource paths
Frontend was incorrectly using numeric enum values (e.g., 1, 2, 3) instead
of string names (e.g., "GENERAL", "STORAGE") when constructing API resource
paths. This caused the backend to fail with "unsupported instance setting
key: INSTANCE_SETTING_KEY_UNSPECIFIED" errors during initialization.

Changes:
- Add helper functions in store/common.ts to convert enum values to names
  - getInstanceSettingKeyName() and buildInstanceSettingName()
  - getUserSettingKeyName() and buildUserSettingName()
- Update instance store to use string enum names in API calls
- Update user store to use string enum names in API calls
- Update all components to use new helper functions for setting names

Fixes enum string conversion for:
- InstanceSetting_Key (6 locations)
- UserSetting_Key (2 locations)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 20:08:11 +08:00
Johnny
edd3ced9bf
refactor: migrate to connect-rpc (#5338) 2025-12-11 19:49:07 +08:00
Steven
8af8b9d238 fix(web): use AST parsing for task detection to handle code blocks correctly
Fixes #5319. Checkboxes inside code blocks were incorrectly counted when
toggling tasks, causing the wrong checkbox to be checked. Replaced regex-based
task detection with mdast AST parsing which properly ignores code block content.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 08:26:16 +08:00
Steven
3dc740c752 refactor(web): improve locale/theme preference initialization
- Extract preference logic into dedicated hooks (useUserLocale, useUserTheme)
- Add applyLocaleEarly() for consistent early application
- Remove applyUserPreferences() from user store (now redundant)
- Simplify App.tsx by moving effects to custom hooks
- Make locale/theme handling consistent and reactive
- Clean up manual preference calls from sign-in flows

Fixes locale not overriding localStorage on user login.
Improves maintainability with better separation of concerns.
2025-12-11 07:59:52 +08:00
spaghetti-coder
7479205e21
fix(ui): change focus search bar shortcut overlapping with url shortcut (#5336) 2025-12-11 07:56:20 +08:00
XIN_____
baf33af980
chore: add 'all' translation to zh-Hans and zh-Hant (#5333) 2025-12-11 07:53:20 +08:00
Shivam Kumar
41358ed3ba
fix(theme): improve text contrast in default dark mode (#5323)
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2025-12-11 07:53:02 +08:00
Steven
48ce4ccc26 fix(web): disable setext header syntax (#5314)
Add custom remark plugin to prevent setext headers (headers using === or --- underlines) from being recognized by the markdown parser. The plugin disables the setextUnderline construct at the micromark parser level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 09:07:54 +08:00
Steven
1cf047707b refactor: migrate binary file serving from gRPC to dedicated HTTP fileserver
Migrates attachment and avatar binary serving from gRPC endpoints to a new dedicated HTTP fileserver package, fixing Safari video playback issues and improving architectural separation.

Key changes:
- Created server/router/fileserver package for all binary file serving
- Removed GetAttachmentBinary and GetUserAvatar gRPC endpoints from proto
- Implemented native HTTP handlers with full range request support
- Added authentication support (session cookies + JWT) to fileserver
- New avatar endpoint supports lookup by user ID or username
- Eliminated duplicate auth constants (imports from api/v1)

HTTP endpoints:
- Attachments: /file/attachments/:uid/:filename (unchanged URL)
- Avatars: /file/users/:identifier/avatar (new URL format)

This fixes Safari video/audio playback by using http.ServeContent() which properly handles HTTP 206 Partial Content responses and range request headers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 08:53:52 +08:00
spaghetti-coder
9ea27ee61f
fix(ui): fix todo command does nothing (#5329) 2025-12-09 08:20:57 +08:00
spaghetti-coder
618db89f4f
fix(ui): remove unsupported highlight command (#5328) 2025-12-09 07:57:28 +08:00
XIN_____
2a876436e0
chore: add 'auto-expand' translation in zh-Hans.json (#5326) 2025-12-08 21:03:57 +08:00
Steven
4668c4714b refactor(web): improve MemoContent security and maintainability
Security improvements:
- Add rehype-sanitize for XSS protection in markdown content
- Remove DOMPurify and deprecated __html code block feature
- Extract sanitize schema to constants with comprehensive documentation

Maintainability improvements:
- Extract SANITIZE_SCHEMA to constants.ts for better organization
- Create utils.ts with shared code extraction utilities
- Refactor CodeBlock and MermaidBlock to use shared utilities
- Rename PreProps to CodeBlockProps for clarity
- Reduce code duplication across components

Dependency cleanup:
- Remove explicit katex dependency (now transitive via rehype-katex)
- Remove @matejmazur/react-katex (unused)
- Remove dompurify (replaced by rehype-sanitize)
- Update vite config to remove katex-vendor chunk

Changes: 7 files changed, 84 insertions(+), 100 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:45:22 +08:00
Steven
d9f8bc80f0 feat(web): add LaTeX math rendering support to MemoContent
Integrates remark-math and rehype-katex plugins to enable LaTeX mathematical expressions in memos. Users can now write inline math ($...$) and display math ($$...$$) using standard LaTeX syntax.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:08:45 +08:00
Steven
81da20c905 refactor: simplify theme/locale to user preferences and improve initialization
Remove theme and locale from instance settings to eliminate duplication and
simplify the codebase. These are user-specific preferences and should only
exist in user settings, not instance-wide settings.

Backend changes:
- Remove theme from InstanceGeneralSetting proto
- Remove locale from InstanceCustomProfile proto
- Update instance service converters to remove theme/locale handling
- Simplify RSS feed to use static locale

Frontend changes:
- Remove theme/locale from instanceStore state
- Create unified initialization flow with clear fallback priority:
  * Theme: user setting → localStorage → system preference
  * Locale: user setting → browser language
- Add applyUserPreferences() to centralize theme/locale application
- Simplify App.tsx by removing redundant state synchronization
- Update all components to use new helper functions:
  * getThemeWithFallback() for theme resolution
  * getLocaleWithFallback() for locale resolution
- Remove theme/locale selectors from instance profile dialog

Theme utilities refactor:
- Organize code into clear sections with JSDoc comments
- Extract localStorage operations into getStoredTheme/setStoredTheme helpers
- Split DOM manipulation into focused functions
- Improve type safety with Theme and ResolvedTheme types
- Reduce code duplication and improve maintainability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 09:08:46 +08:00
Steven
8154a411a9 fix(web): allow only one active tag filter at a time
Previously, clicking multiple tags would add them all as active filters. Now clicking a new tag automatically clears any existing tag filters before applying the new one, ensuring only one tag can be filtered at a time. Clicking an already-active tag still deselects it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 08:40:43 +08:00
Steven
fae5eac31b fix(web): fix infinite loop in MemoEditor and improve React/MobX integration
- Wrap all setter functions in useMemoEditorState with useCallback to ensure stable references
  This prevents infinite loops when setters are used in useEffect dependencies (fixes "Maximum update depth exceeded" error)
- Extract MobX observable values in useMemoFilters and useMemoSorting before using them in useMemo dependencies
  This prevents React from tracking MobX observables directly, improving reliability
- Add comprehensive documentation explaining the design decisions for future maintainability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:54:40 +08:00
Johnny
1a9bd32cf1 feat(auth): add PKCE support and enhance OAuth security
Implements critical OAuth 2.0 security improvements to protect against authorization code interception attacks and improve provider compatibility:

- Add PKCE (RFC 7636) support with SHA-256 code challenge/verifier
- Fix access token extraction to use standard field instead of Extra()
- Add OAuth error parameter handling (access_denied, invalid_scope, etc.)
- Maintain backward compatibility for non-PKCE flows

This brings the OAuth implementation up to modern security standards as recommended by Auth0, Okta, and the OAuth 2.0 Security Best Current Practice (RFC 8252).

Backend changes:
- Add code_verifier parameter to ExchangeToken with PKCE support
- Use token.AccessToken for better provider compatibility
- Update proto definition with optional code_verifier field

Frontend changes:
- Generate cryptographically secure PKCE parameters
- Include code_challenge in authorization requests
- Handle and display OAuth provider errors gracefully
- Pass code_verifier during token exchange

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 00:04:26 +08:00
Johnny
a6a8997f4c chore: tweak comments 2025-11-30 13:16:02 +08:00
Johnny
07072b75a7 chore: reorganize reaction components 2025-11-30 12:48:21 +08:00
Johnny
6dcf7cc74c chore: enhance MemoView component structure 2025-11-30 12:41:24 +08:00
Johnny
7aa8262ef2 chore: streamline MemoEditor components and remove unused code 2025-11-30 12:30:00 +08:00
Johnny
2516cdf2b4 refactor: clean up MemoView and MemoEditor component architecture
This commit refactors MemoView and MemoEditor components for better
maintainability, introducing React Context, custom hooks, and improved
folder structure.

MemoView improvements:
- Introduce MemoViewContext to eliminate prop drilling
- Reduce MemoHeader props from 18 to 8
- Reduce MemoBody props from 9 to 4
- Extract custom hooks: useMemoViewDerivedState, useMemoEditor,
  useMemoHandlers for better separation of concerns
- Fix React hooks ordering bug in edit mode

MemoEditor improvements:
- Extract state management into useMemoEditorState hook
- Extract keyboard handling into useMemoEditorKeyboard hook
- Extract event handlers into useMemoEditorHandlers hook
- Extract initialization logic into useMemoEditorInit hook
- Reduce main component from 461 to 317 lines (31% reduction)

Folder structure cleanup:
- Move SortableItem to memo-metadata (correct location)
- Move ErrorBoundary to components folder
- Flatten Toolbar/InsertMenu structure (remove unnecessary nesting)
- Consolidate hooks in main hooks folder
- Consolidate types in main types folder

Benefits:
- Better separation of concerns
- Improved testability
- Easier maintenance
- Cleaner code organization
- No functionality changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 11:15:20 +08:00
Johnny
bb7e0cdb79 refactor: remove enable link preview setting
- Remove enable_link_preview field from proto definitions
- Remove setting UI from MemoRelatedSettings component
- Remove translations from all 33 locale files
- Regenerate proto files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:34:22 +08:00
Johnny
5fb6f8eccf refactor: remove legacy disable markdown shortcuts setting
- Remove disable_markdown_shortcuts field from proto definitions
- Remove setting UI from MemoRelatedSettings component
- Enable markdown shortcuts permanently in MemoEditor
- Remove translations from all 32 locale files
- Fix TypeScript error in useMemoSave hook by using typed translation function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:30:55 +08:00
Johnny
2b7b70ebfe chore: fix linter 2025-11-30 10:15:20 +08:00
Johnny
1ef11f7470 refactor: implement MemoView component with subcomponents and hooks
- Added MemoView component to display a single memo card with full functionality including creator info, memo content, attachments, reactions, and comments.
- Created MemoBody and MemoHeader subcomponents to separate concerns and improve maintainability.
- Introduced custom hooks for managing memo actions, keyboard shortcuts, NSFW content visibility, and image preview.
- Implemented reaction handling with new ReactionSelector and ReactionView components.
- Added TypeScript types for better type safety and clarity.
- Established constants for memo card styling and keyboard shortcuts.
- Removed legacy ReactionSelector and ReactionView components from the previous structure.
2025-11-29 23:21:35 +08:00
Johnny
50199fe998 feat: add LocationDialog and related hooks for location management in MemoEditor
- Implemented LocationDialog component for selecting and entering location coordinates.
- Created useLocation hook to manage location state and updates.
- Added LocationState type for managing location data.
- Introduced useLinkMemo hook for linking memos with search functionality.
- Added VisibilitySelector component for selecting memo visibility.
- Refactored MemoEditor to integrate new hooks and components for improved functionality.
- Removed obsolete handlers and streamlined memo save logic with useMemoSave hook.
- Enhanced focus mode functionality with dedicated components for overlay and exit button.
2025-11-28 09:21:53 +08:00
Chriss
c1765fc246
feat: add midnight theme (#5288) 2025-11-27 21:21:57 +08:00
Steven
05f7c9606b fix: add HTML sanitization and dynamic theme loading 2025-11-26 20:34:52 +08:00
Steven
363bc9f455 fix(web): add missing tag styles and unify primary color across themes
Tags were missing CSS styles, appearing as plain text. Added text-primary
styling to Tag component and updated default theme primary color to match
other themes (blue hue 250, chroma 0.08) for consistency.

Fixes #5282

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:25:28 +08:00
Steven
5a16f8009f fix(markdown): render single newlines as line breaks
Add remark-breaks plugin to render single newlines as <br> tags,
matching GitHub Flavored Markdown behavior.

Fixes https://github.com/usememos/memos/issues/5277

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:13:57 +08:00
김강현
ef033d21de
chore(i18n): add missing Korean translations (#5285) 2025-11-26 20:02:57 +08:00
김강현
b7c9f0e6ff
chore(i18n): improve Korean locale translations for copy and delete actions (#5280) 2025-11-26 12:34:54 +08:00
Steven
eb541d04cc fix(web): resolve tag sidebar filtering and reactivity issues
This fixes multiple issues with the tag sidebar and activity calendar:

1. Tag disappearing bug: When filtering by a tag, the sidebar now shows all tags instead of only the selected tag
2. Activity calendar filtering: Calendar now shows full activity history instead of filtered results
3. Auto-update on memo changes: Sidebar tags and calendar now update automatically when creating/editing memos without requiring manual page refresh

Technical changes:
- Modified useFilteredMemoStats to fetch unfiltered UserStats from backend API for Home/Profile pages
- Fixed key mismatch bug in userStore where stats were stored with inconsistent keys
- Added statsStateId update in fetchUserStats to trigger reactivity
- Updated MainLayout to pass appropriate userName based on page context
- Archived/Explore pages continue to compute from cached memos (correct behavior)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 22:17:01 +08:00
Steven
8ec4c9ab63 fix(web): update time locale when language is changed
Pass i18n.language to time display components to ensure locale updates
when the user switches languages in UserMenu. Changes:

- MemoView: Pass i18n.language to toLocaleString() and <relative-time> lang attribute
- MonthNavigator: Wrap with observer to make component reactive to i18n.language changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:37:04 +08:00
Steven
ef6456a4f5 refactor(web): restructure MemoEditor with custom hooks and improved error handling
Extract reusable logic into custom hooks (useLocalFileManager, useDragAndDrop, useDebounce, useAbortController), add ErrorBoundary for resilience, and centralize constants. Fix cursor positioning bugs, useEffect dependency issues, and add geocoding request cancellation. Improve performance with debounced localStorage writes and ref-based flags.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:29:54 +08:00
Johnny
1832b59190 fix(css): standardize color variable values in default-dark theme 2025-11-25 09:02:57 +08:00
Steven
5e95a77f50 chore: update color variables in default-dark theme for improved contrast 2025-11-24 21:59:24 +08:00
Steven
b5de847107 chore(web): add external link icon for memo attachments 2025-11-24 21:56:14 +08:00
Steven
424e599980 refactor(web): optimize memo statistics fetching by using cached data from memo store 2025-11-24 21:37:12 +08:00
Steven
72f93c5379 feat(web): enhance file upload handling with local file support and preview 2025-11-24 21:31:18 +08:00
Steven
1d582e0f39 chore: upgrade dependencies 2025-11-24 20:18:52 +08:00
Richard Szegh
455eef9fa3
feat(web): add ability to delete unused attachments (#5272) 2025-11-24 11:55:53 +08:00
Johnny
b78d4c2568 refactor(markdown): use Unicode categories for tag validation
Replace custom character whitelist with Unicode standards-based validation:

- Use unicode.IsLetter/IsNumber/IsSymbol instead of hardcoded lists
- Remove manual UTF-8 byte checking for CJK punctuation
- Add proper rune-based length limiting (MAX_TAG_LENGTH = 100)
- Improve international character support (CJK, Arabic, Cyrillic, etc.)
- Add emoji support via unicode.IsSymbol

Benefits:
- Cleaner, more maintainable code (~50 lines removed)
- Standards-based approach following Unicode categories
- Better UTF-8 safety with utf8.DecodeRune
- Consistent validation between Go backend and TypeScript frontend

All existing tests pass with improved Unicode handling.
2025-11-23 23:45:10 +08:00
gitkeniwo
a533ba02dc
fix: add load more button and pagination to attachments page (#5258) 2025-11-21 09:04:41 +08:00
Steven
edfbd6b073 fix(web): refresh sidebar tags when creating/updating memos
The sidebar tag list wasn't updating when users created new memos with tags
or modified existing memo tags. This was because useFilteredMemoStats hook
only refetched when filter/state/orderBy changed.

Now the hook observes memoStore.state.stateId, which changes whenever memos
are created, updated, or deleted. This triggers automatic refetch and the
sidebar updates immediately with the latest tag counts.

Fixes tag refresh issue in sidebar
2025-11-19 22:30:00 +08:00
Steven
cabd0d61c6 fix(web): resolve Leaflet DOM cleanup error causing app crashes
- Add MapCleanup component to properly remove Leaflet map instances on unmount
- Fix LocationMarker initialization with useRef to prevent re-initialization
- Remove problematic key prop in LocationDialog that caused unnecessary remounts
- Fix goimports formatting in tag parser

Fixes #5260
2025-11-19 22:21:01 +08:00
Steven
64e9d82d67 fix(parser): support Unicode characters in tags
Fixes #5264

Chinese, Japanese, Korean, and other Unicode characters are now
properly recognized in hashtags, following the standard hashtag
parsing conventions used by Twitter, Instagram, and GitHub.

Changes:
- Updated tag parser to allow Unicode letters and digits
- Tags stop at whitespace and punctuation (both ASCII and CJK)
- Allow dash, underscore, forward slash in tags
- Added comprehensive tests for CJK characters and emoji

Examples:
- #测试 → recognized as tag '测试'
- #日本語 → recognized as tag '日本語'
- #한국어 → recognized as tag '한국어'
- #测试。→ recognized as tag '测试' (stops at punctuation)
- #work/测试/项目 → hierarchical tag with Unicode
2025-11-19 22:06:11 +08:00
Neo
4de8712cb0
fix: keyboard shortcuts (#5250) 2025-11-17 08:55:57 +08:00
Johnny
357118804e feat(web): add Focus Mode UI entry in Insert Menu
Add discoverable UI entry point for Focus Mode via Insert Menu submenu:

UI Changes:
- Add "View" submenu to Insert Menu (+ button dropdown)
- Nested menu with Focus Mode option (ChatGPT-style pattern)
- Display keyboard shortcut hint (⌘⇧F) next to menu item
- Uses DropdownMenuSub components from Radix UI

User Access Methods:
1. Keyboard: Cmd/Ctrl+Shift+F (primary, power users)
2. Mouse: + menu → View → Focus Mode (discoverable)
3. Mobile: Touch-friendly menu access

Benefits:
- Improves discoverability for new users
- Doesn't clutter main editor UI
- Educates users about keyboard shortcut
- Extensible for future view options (typewriter, reading mode, etc.)
- Follows familiar UI patterns (ChatGPT, Notion)

Files Modified:
- web/src/components/MemoEditor/ActionButton/InsertMenu.tsx
  * Add DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent
  * Add View submenu with Focus Mode entry
  * Add onToggleFocusMode prop
- web/src/components/MemoEditor/index.tsx
  * Pass toggleFocusMode to InsertMenu component
- web/src/locales/en.json
  * Add "editor.view" translation key
2025-11-17 08:55:10 +08:00
Johnny
c8162ff3cc feat(web): add Focus Mode for distraction-free writing
Add keyboard-activated Focus Mode to provide an immersive writing experience:

Features:
- Toggle with Cmd/Ctrl+Shift+F (matches GitHub, Google Docs)
- Exit with Escape, toggle shortcut, button click, or backdrop click
- Expands editor to ~80-90% of viewport with centered layout
- Semi-transparent backdrop with blur effect
- Maintains all editor functionality (attachments, shortcuts, etc.)
- Smooth 300ms transitions

Responsive Design:
- Mobile (< 640px): 8px margins, 50vh min-height
- Tablet (640-768px): 16px margins
- Desktop (> 768px): 32px margins, 60vh min-height, 1024px max-width

Implementation:
- Centralized constants for easy maintenance (FOCUS_MODE_STYLES)
- Extracted keyboard shortcuts and heights to named constants
- JSDoc documentation for all new functions and interfaces
- TypeScript type safety with 'as const'
- Explicit positioning (top/left/right/bottom) to avoid width overflow

Files Modified:
- web/src/components/MemoEditor/index.tsx - Main Focus Mode logic
- web/src/components/MemoEditor/Editor/index.tsx - Height adjustments
- web/src/locales/en.json - Translation keys

Design follows industry standards (GitHub Focus Mode, Notion, Obsidian)
and maintains code quality with single source of truth pattern.
2025-11-16 23:15:36 +08:00
Steven
156908c77f chore(web): migrate from ESLint+Prettier to Biome
- Install @biomejs/biome@2.3.5 as unified linter and formatter
- Remove ESLint, Prettier and all related plugins (221 packages removed)
- Migrate linting rules from ESLint to Biome configuration
- Migrate formatting rules from Prettier to Biome configuration
- Exclude auto-generated proto files from linting (src/types/proto/**)
- Exclude CSS files from Biome (Tailwind syntax not yet supported)
- Update package.json scripts:
  - lint: tsc + biome check
  - lint:fix: biome check --write
  - format: biome format --write
- Auto-fix import organization across 60+ files
- Fix duplicate key in Russian locale (ru.json)
- Update CLAUDE.md documentation to reflect Biome usage

Benefits:
- 10-100x faster linting performance
- Simplified toolchain with single configuration file
- 221 fewer npm dependencies
- Unified linting, formatting, and import organization
2025-11-14 23:58:07 +08:00
Johnny
64111369d3
fix(web): refactor task list styles to follow GitHub standard (#5253)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-14 23:37:00 +08:00
Steven
dc398cf6a7 chore(web): unify metadata badge styling and fix event handling
- Remove MetadataBadge component and inline styles consistently
- Add pointer/mouse event handlers to prevent drag interference
- Fix LocationDisplay mode handling and popover interaction
- Clean up RelationList empty state logic
2025-11-10 21:53:56 +08:00
Simon
bb3d808e0e
feat: allow closing image preview via backdrop click (#5243) 2025-11-10 19:12:45 +08:00
Johnny
6fc0ef7cc2 chore(web): remove redundant and minimal README files
Removed 3 markdown files that provided no useful documentation:
- web/README.md: Single line "The frontend of Memos" (redundant)
- web/src/components/kit/README.md: Single line "Base components" (minimal)
- web/MARKDOWN_STYLE_GUIDE.md: Outdated styling guide (no longer applicable)

Kept comprehensive documentation files:
- web/src/components/MasonryView/README.md (implementation details)
- web/src/themes/COLOR_GUIDE.md (design system guide)
- web/src/components/ConfirmDialog/README.md (component API docs)
- web/src/store/README.md (architecture patterns)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 14:21:10 +08:00
Johnny
fa3e0fc7f9 fix(web): make MermaidBlock reactive to system theme changes and improve code quality
- Add system theme listener to detect OS theme changes in real-time
- Refactor to eliminate duplicate theme preference extraction
- Simplify getMermaidTheme function from switch statement to ternary
- Move render guard outside async function for better readability
- Update comments to be more concise and focused

The component now properly re-renders Mermaid diagrams when the OS theme changes while using "system" theme preference.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 14:19:11 +08:00
Johnny
fb736c20d3
feat(web): add Mermaid diagram support in markdown (#5242)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 14:13:10 +08:00
Johnny
5925e3cfc1 chore(web): simplify command system and improve editor UX (#5242)
Streamlines the command suggestion interface and fixes list auto-completion behavior:

- Remove command descriptions for cleaner suggestion popup UI
- Replace PaperclipIcon with FileIcon for semantic accuracy
- Fix list auto-completion to avoid extra newline when exiting list mode
- Add explanatory comments for cursor offset positions
- Improve dependency array in useListAutoCompletion hook

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 13:09:50 +08:00
Johnny
fc43f86571
chore(web): unify Location/Attachments/Relations components (#5241)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 07:23:31 +08:00
Johnny
a2ccf6b201
feat(web): improve list auto-completion and tag insertion UX (#5240)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 01:26:29 +08:00
Johnny
e8b0273473
chore(web): improve CommandSuggestions and TagSuggestions components (#5239)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 01:05:24 +08:00
Johnny
bd21338fdb
fix(web): markdown list auto-completion creates new line correctly (#5238)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 10:47:10 +08:00
Johnny
c54fcf7aa7
refactor(web): redesign Settings components (#5237)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 10:32:55 +08:00
Steven
ef9eee19d6 fix: implement tag suggestions functionality
Backend changes:
- Fix ListAllUserStats to calculate and return tag statistics
- Previously only returned name and timestamps, missing TagCount
- Now properly aggregates tags, pinned memos, and memo type stats

Frontend changes:
- Initialize user stats on app startup to populate tag data
- Show all tags when typing just '#' (fix empty Fuse.js search)
- Auto-refresh stats after creating/updating/deleting memos
- Fix Checkbox component ref warning with forwardRef

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 09:15:38 +08:00
boojack
7d4d1e8517
feat(web): standardize theme system with auto sync option (#5231)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 00:41:21 +08:00
Steven
b7215f46a6 refactor(web): use Radix Checkbox and remove memoTypeStats
- Replace native input with Radix UI Checkbox in TaskListItem for better accessibility and consistent styling
- Remove memoTypeStats tracking and display (link count, todo count, code count)
- Remove StatCard component and related type definitions
- Simplify statistics to only track activity calendar data and tags

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 08:36:15 +08:00
Elliott
bb8fa90496
feat(i18n): add missing translations for zh-Hans (closes #5209) (#5229) 2025-11-06 22:32:03 +08:00
boojack
6cff7972d5
fix(web): fix tag syntax rendering on first line (#5226)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-06 19:29:16 +08:00
Steven
8f0658e90d feat(web): enhance inbox notifications and user profile layouts
- Polish inbox notification items with improved visual hierarchy
  - Add original memo snippet with left border indicator
  - Redesign comment preview with gradient background and primary accent
  - Increase spacing and improve typography with consistent sizing
  - Add ring borders to avatars and refined icon badges
  - Enhance loading and error states with better skeleton designs
  - Improve hover states and transitions throughout

- Redesign user profile header layout
  - Create full-width centered header with avatar and user info
  - Add horizontal layout for profile actions
  - Improve responsive design with proper flex wrapping
  - Allow memo list to use full width for masonry layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:41:30 +08:00
Steven
89b0b81bdc fix(web): add required headers for Nominatim reverse geocoding API
Nominatim's usage policy requires a User-Agent header to identify the application. Added User-Agent and Accept headers to the reverse geocoding fetch request, and improved error handling to check HTTP response status.

Fixes #5222

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 23:47:44 +08:00
Steven
4c1d1c70d1 refactor: rename workspace to instance throughout codebase
Remove work-related terminology by renaming "workspace" to "instance"
across the entire application. This change better reflects that Memos
is a self-hosted tool suitable for personal and non-work use cases.

Breaking Changes:
- API endpoints: /api/v1/workspace/* → /api/v1/instance/*
- gRPC service: WorkspaceService → InstanceService
- Proto types: WorkspaceSetting → InstanceSetting
- Frontend translation keys: workspace-section → instance-section

Backend Changes:
- Renamed proto definitions and regenerated code
- Updated all store layer methods and database drivers
- Renamed service implementations and API handlers
- Updated cache from workspaceSettingCache to instanceSettingCache

Frontend Changes:
- Renamed service client: workspaceServiceClient → instanceServiceClient
- Updated all React components and state management
- Refactored stores: workspace.ts → instance.ts
- Updated all 32 locale translation files

All tests pass and both backend and frontend build successfully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 23:35:35 +08:00
boojack
d98ee36178
chore: standardize and improve API structure (#5224)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-05 22:36:51 +08:00
Steven
1d7efb1580 refactor(web): unify memo stats/filters with context-aware MainLayout
Create unified architecture for memo statistics, filters, and sorting
across all pages (Home, Explore, Archived, Profile) with proper
visibility filtering and consistent data flow.

Key changes:
- Rename HomeLayout → MainLayout to reflect broader usage
- Create useFilteredMemoStats hook for unified stats computation
- Create useMemoFilters/useMemoSorting hooks to eliminate duplication
- Refactor all pages to use unified hooks (~147 lines removed)
- Move Explore route under MainLayout (was sibling before)
- Fix masonry column calculation threshold (1024px → 688px+)

Architecture improvements:
- MainLayout computes filter/stats per route context
- Stats/tags based on same filter as memo list (consistency)
- Proper visibility filtering (PUBLIC/PROTECTED) on Explore
- MemoExplorer/StatisticsView accept stats as required props
- Eliminated optional fallbacks and redundant data fetching

Benefits:
- Single source of truth for stats computation
- Stats remain static (don't change with user filters)
- Reduced code duplication across 4 pages
- Better maintainability and type safety
- Proper security (no private memo leakage on Explore)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:46:52 +08:00
Steven
d30ff2898f fix(web): correct task checkbox toggling in multi-section memos
Fixed a bug where clicking checkboxes in task lists would toggle the wrong
checkbox when a memo contained multiple sections with separate task lists.

The issue was that TaskListItem was counting tasks only within the immediate
parent list (ul/ol), but the toggleTaskAtIndex function counts all tasks
globally across the entire memo. This caused index misalignment.

Changes:
- Add containerRef to MemoContentContext for proper task scoping
- Pass memoContentContainerRef through context in MemoContent component
- Update TaskListItem to count all tasks within the container scope

This ensures task indices are calculated consistently with the markdown
manipulation logic, fixing checkbox toggling in complex multi-section memos.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 09:25:15 +08:00
Claude
9b72963e08 feat: replace HomeSidebar with MemoExplorer and MemoExplorerDrawer components 2025-11-02 23:31:29 +08:00