1. 04 Mar, 2026 3 commits
  2. 03 Mar, 2026 8 commits
  3. 02 Mar, 2026 5 commits
    • Steven's avatar
      737acbba
    • boojack's avatar
      chore: tweak sponsor assets · ec3ab350
      boojack authored
      Signed-off-by: 's avatarboojack <stevenlgtm@gmail.com>
      ec3ab350
    • Steven's avatar
      dfab67f0
    • Steven's avatar
      6b37fcc0
    • Steven's avatar
      refactor(theme): consolidate theme system and polish dark mode colors · 7f753bf6
      Steven authored
      - 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
      7f753bf6
  4. 01 Mar, 2026 10 commits
  5. 26 Feb, 2026 4 commits
  6. 25 Feb, 2026 2 commits
  7. 24 Feb, 2026 3 commits
    • Steven's avatar
      fix(web): use BroadcastChannel to sync token refreshes across tabs · bbdc9986
      Steven authored
      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).
      bbdc9986
    • Steven's avatar
      refactor: consolidate duplicated auth logic into auth package · 26d10212
      Steven authored
      Add ApplyToContext and AuthenticateToUser helpers to the auth package,
      then remove the duplicated auth code spread across the MCP middleware,
      file server, Connect interceptor, and gRPC-Gateway middleware.
      
      - auth.ApplyToContext: single place to set claims/user into context after Authenticate()
      - auth.AuthenticateToUser: resolves any credential (bearer token or refresh cookie) to a *store.User
      - MCP middleware: replaced manual PAT DB lookup + expiry check with Authenticator.AuthenticateByPAT
      - File server: replaced authenticateByBearerToken/authenticateByRefreshToken with AuthenticateToUser
      - Connect interceptor + Gateway middleware: replaced duplicated context-setting block with ApplyToContext
      - MCPService now accepts secret to construct its own Authenticator
      26d10212
    • Steven's avatar
      feat: add MCP server with PAT authentication · 47d94147
      Steven authored
      Embeds a Model Context Protocol (MCP) server into the Memos HTTP
      process, exposing memo operations as MCP tools at POST/GET /mcp using
      Streamable HTTP transport.
      
      Authentication is PAT-only — requests without a valid personal access
      token receive HTTP 401. Six tools are exposed: list_memos, get_memo,
      create_memo, update_memo, delete_memo, and search_memos, all scoped to the authenticated user.
      47d94147
  8. 23 Feb, 2026 5 commits
    • Steven's avatar
      chore: fix codeowners · 71263736
      Steven authored
      71263736
    • Mudkip's avatar
      ff3e4c5c
    • Steven's avatar
      fix(web): fix spurious logout on page reload with expired access token · 9ecd7b87
      Steven authored
      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.
      9ecd7b87
    • Steven's avatar
      fix(web): fix explore page showing private tags and improve stats hook · 03c30b8c
      Steven authored
      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.
      03c30b8c
    • Steven's avatar
      fix(web): make MonthNavigator month label reactive to language changes · 1cea9b0a
      Steven authored
      Use useTranslation() hook instead of the static i18n import so that
      the month label re-computes when the language changes.
      1cea9b0a