Compare commits

...

3392 Commits

Author SHA1 Message Date
boojack 5f194da7d3 chore(main): release 0.29.1 (#5985) 2026-06-05 08:06:30 +08:00
boojack bb76949fc0 chore(server): centralize CORS policy 2026-06-04 22:37:41 +08:00
boojack d69f1aab27 chore: tweak demo data 2026-06-03 00:21:45 +08:00
boojack 0e2a9a9c0c fix(web): render video attachment posters on mobile 2026-06-02 23:08:16 +08:00
goingforstudying-ctrl e8d32e87d1 fix: support <meta name=description> in link previews (#6000)
Co-authored-by: goingforstudying-ctrl <goingforstudying-ctrl@users.noreply.github.com>
2026-06-02 23:02:21 +08:00
boojack 0d31e3c2fb chore(media): add zoom controls to preview dialog 2026-06-02 22:46:07 +08:00
boojack fadc974364 docs: consolidate agent guidance 2026-05-31 18:53:37 +08:00
boojack 53abb8020e refactor(frontend): remove react-use dependency 2026-05-31 18:32:17 +08:00
boojack 7c3bff4e98 fix(markdown): keep task item content in one grid column 2026-05-27 23:57:23 +08:00
boojack f22c4bd5c2 chore(main): release 0.29.0 (#5909) 2026-05-27 20:48:29 +08:00
boojack e0bb3a2e68 fix(editor): wrap selected text when pasting URL 2026-05-27 20:36:27 +08:00
boojack 648b3bd812 feat(memo): add task list quick actions (#5983) 2026-05-27 09:13:55 +08:00
boojack e564c1a993 chore: update about page 2026-05-26 21:14:59 +08:00
boojack e53b7d96e7 fix: delete user cleanup (#5981) 2026-05-25 22:10:29 +08:00
boojack d1208a68e9 chore: update sponsors 2026-05-25 20:39:25 +09:00
boojack 3c3382a3c6 fix: avoid update event on memo create attachments (#5961) 2026-05-16 21:18:44 +08:00
boojack 858f7419b4 chore(seed): tweak seed data 2026-05-15 09:04:28 +08:00
boojack 63d6431d3e chore: update images in README for dark mode
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-05-15 08:33:19 +08:00
Santosh Yadav ddcaf5f25c chore: fix coderabbit logo for light and dark theme (#5954) 2026-05-15 07:10:27 +08:00
boojack ab2b08a21e chore(seed): refresh demo memos and sponsor showcase 2026-05-15 00:23:11 +08:00
boojack 727480d49d chore: revamp sponsors section in README
Updated the featured sponsors section to include a table layout and added new sponsor information.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-05-14 23:56:57 +08:00
boojack 439ddaebf5 refactor(placeholder): extract tile sprite strip 2026-05-14 20:38:00 +08:00
boojack 411ba7b34c feat(about): add about page with bird sprites 2026-05-14 20:30:37 +08:00
boojack 638e4f398e feat(placeholder): add woodpecker tilemap 2026-05-14 09:35:11 +08:00
boojack cf55f11072 feat(frontend): add pixel bird tilemaps 2026-05-14 00:03:21 +08:00
boojack ca2bc4eb84 chore: render placeholder ascii pieces as components 2026-05-13 09:06:23 +08:00
boojack aa5cb455e9 refactor(web): use / as the home route instead of /home
Home now lives at `/` directly. Unauthenticated visitors are sent to
`/explore` by the landing gate; old `/home` URLs redirect to `/` for
bookmark compatibility.
2026-05-12 23:17:46 +08:00
boojack 8c16ffa1f1 feat: add <Placeholder> component with ASCII bird states (#5949)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 22:48:37 +08:00
Mayank Saini f1e2a06b46 feat: add configurable --log-level flag (#5934)
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2026-05-12 21:10:05 +08:00
boojack a6024eebf1 perf: lazy load heavy first-screen dependencies (#5947) 2026-05-12 20:11:39 +08:00
boojack 7f1f53ffc4 fix(s3presign): preserve motion media payload 2026-05-09 22:51:56 +08:00
boojack 511c04bca2 chore: fix linter 2026-05-09 19:08:21 +08:00
boojack f3f059b2f7 chore: add batch get settings API 2026-05-09 09:30:28 +08:00
boojack 21303e879d fix(sse): stream initial response and refresh tokens 2026-05-09 09:15:50 +08:00
boojack 88ac3ec31e feat(stats): support filtered all-user stats
- Add state and filter inputs to ListAllUserStats and reuse it for explore/archive sidebar stats.
- Reduce duplicate home initialization requests by sharing stats/settings data paths.
- Include memo paragraph regression coverage from the current working tree.
2026-05-09 09:11:04 +08:00
boojack c49e75f91f chore: avoid copying memo protobuf locks 2026-05-09 08:32:00 +08:00
boojack 078488ca81 fix(httpgetter): prevent DNS rebinding in link metadata fetch 2026-05-08 23:24:16 +08:00
boojack 4a1e401bd9 fix(memo): enforce parent visibility for comments 2026-05-08 23:22:56 +08:00
boojack 1df6479443 feat: add dedicated shortcuts page (#5942) 2026-05-08 23:06:12 +08:00
boojack 02096836c3 test: stabilize backend tests in CI
- Avoid requiring built frontend assets in cache header tests.
- Skip Testcontainers-backed store tests when Docker is unavailable.
2026-05-08 22:24:54 +08:00
boojack b6f42cbe6b chore: upgrade frontend to React 19 (#5940) 2026-05-08 22:10:48 +08:00
boojack 084f40bc9e fix(frontend): correct static cache headers 2026-05-08 21:25:05 +08:00
boojack 4f0556e23f chore: update sponsors
Added sponsorship information for InstaPods.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-05-08 19:48:30 +08:00
hchengting bcbcb03894 chore: update zh-Hant translation (#5930) 2026-05-04 20:18:00 +08:00
boojack 5ccba98adc refactor: split STT and Audio-LLM into separate interfaces (#5928) 2026-05-03 00:21:58 +08:00
boojack 238f27dea1 feat(transcription): explicit STT settings with provider, model, prompt (#5926) 2026-05-02 19:35:18 +08:00
boojack ef55013418 feat(memo): create memos on the selected calendar date (#5925) 2026-05-02 11:53:50 +08:00
Steven d349fe4409 chore(theme): rebalance dark palette for readability 2026-05-02 09:11:46 +08:00
Steven 8daef1dc89 feat(activity-calendar): aggregate by ViewContext.timeBasis
Fixes the inconsistency where switching the memo list to update_time
left the activity heatmap aggregating by created_time. The heatmap
now follows the same time basis as the list it sits next to.

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

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

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

Spec and implementation plan committed under docs/superpowers/.
2026-05-02 00:26:53 +08:00
Steven ea0625da45 feat(stats): admin instance resource statistics 2026-05-01 23:15:56 +08:00
Steven cd4f28ae10 feat(notification): add smtp email settings
- Add admin notification email settings UI and test-email RPC
- Dispatch privacy-first comment and mention emails through server notification layer
- Keep SMTP secrets write-only and require passwords when SMTP identity changes
2026-05-01 18:48:21 +08:00
Steven 35bf761b8c fix(security): enforce attachment ownership on memo updates 2026-05-01 18:23:53 +08:00
Tokenicrat 词元 603781f792 fix(frontend): use correct url path for memos in sitemap.xml (#5921) 2026-05-01 16:08:31 +08:00
Steven a0b6417689 chore: bump pnpm to 11.0.1 and align list test assertions 2026-04-30 20:05:39 +08:00
boojack e008b1a23c fix(markdown): align list items with checkboxes 2026-04-30 08:49:49 +08:00
boojack 1df3fe7955 fix(user): omit internal settings from list responses (#5917) 2026-04-30 08:49:03 +08:00
boojack 0bc56694b0 feat: render link metadata cards 2026-04-29 23:23:52 +08:00
boojack 9c5c604944 feat: add link metadata endpoints 2026-04-29 22:38:08 +08:00
memoclaw c7242324a1 fix(fileserver): preserve HDR image metadata in thumbnails 2026-04-29 21:32:10 +08:00
memoclaw 267f90a3ff chore: refactor Settings UI structure (#5912)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-29 09:30:58 +08:00
boojack 14480bfc46 chore(settings): improve storage tags and memo panels 2026-04-28 23:28:01 +08:00
boojack ee65e90a39 chore: upgrade pnpm to 11 (#5911) 2026-04-28 22:16:22 +08:00
Chyna 328396a97f fix(web): sync avatar changes immediately after profile update (#5903)
Signed-off-by: Chyna <68607983+chyna-gvng@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-28 21:57:58 +08:00
Mostafa Attia 9353848603 chore: increased muted text contrast in dark theme (#5902) 2026-04-28 20:03:24 +08:00
boojack 616487fa37 chore: update backend and frontend dependencies (#5900)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-28 08:25:26 +08:00
boojack 18e729fe00 chore(memo): simplify markdown task list rendering 2026-04-27 23:22:29 +08:00
boojack 9e310bf93c chore(memo): clarify displayed update time 2026-04-27 21:50:41 +08:00
boojack 9bf648ac91 chore(main): release 0.28.0 (#5866) 2026-04-27 08:56:00 +08:00
boojack 94ce1e5347 chore(settings): show build commit in version info 2026-04-27 08:51:11 +08:00
boojack e2c60845ea fix(markdown): split mixed task and bullet lists 2026-04-26 23:25:29 +08:00
boojack c268551a16 feat(memos): choose created or updated time for memos (#5894) 2026-04-26 11:50:26 +08:00
boojack 3949a252db style(web): refine scrollbar styling 2026-04-26 00:24:45 +08:00
boojack 34c90dd5e1 chore: remove duplicate tags from share image preview 2026-04-25 22:22:49 +08:00
boojack 0fb83a745d fix(auth): harden authorization and username validation (#5890) 2026-04-25 21:24:16 +08:00
boojack ee1799851e feat: redesign account and SSO management (#5886) 2026-04-24 09:08:58 +08:00
boojack 30c0611a82 fix: fix legacy username auth flows (#5885) 2026-04-23 22:35:38 +08:00
boojack d688914b28 feat(auth): add SSO user identity linkage (#5883) 2026-04-23 08:51:45 +08:00
boojack 50638040f6 fix: reduce list memo query overhead (#5880) 2026-04-22 09:31:48 +08:00
boojack ebc0e10f07 docs: refine SSO identity linkage design (#5879) 2026-04-22 09:09:15 +08:00
boojack b5863d76be fix(web): preserve task checkbox state (#5867) 2026-04-20 23:27:00 +08:00
wndnjs0 d98f665919 fix: disable modal prop on DropdownMenu to prevent scroll disappearing (#5861) 2026-04-20 21:38:28 +08:00
boojack 765a8c6e28 chore(main): release 0.27.1 (#5855) 2026-04-19 13:17:09 +08:00
George Wu bbded584ce fix: user resource names can be uuidv4 from idp sub claim (#5856) 2026-04-19 13:05:08 +08:00
boojack f8a304bae3 fix(release): inject build version into artifacts 2026-04-19 12:02:32 +08:00
boojack cfe2cf4cf5 chore(main): release 0.27.1 (#5854) 2026-04-19 10:55:16 +08:00
boojack 01be01f4b7 fix: mixed-case user resource names (#5853) 2026-04-19 10:44:25 +08:00
boojack 1fd6a2a385 chore(main): release 0.27.0 (#5843)
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-04-19 04:02:50 +08:00
boojack 583c3d24f4 feat(mcp): harden tool exposure and side effects (#5850) 2026-04-18 22:28:35 +08:00
wndnjs0 0fc1dab28b fix: add unix socket file permission setting (755 -> 660) (#5849) 2026-04-18 13:21:03 +08:00
boojack 88cb58ab64 refactor(web/routing): guard-based auth flow, migrate tests to Vitest (#5848) 2026-04-18 01:06:54 +08:00
boojack 587f5b1b6c chore(github): simplify issue templates 2026-04-17 23:54:17 +08:00
boojack ff6389a5ef fix(api): appease image size lint 2026-04-16 23:21:07 +08:00
boojack c45663761d fix(api): reduce memory pressure in backend paths 2026-04-16 23:08:48 +08:00
boojack 8479e1d5a3 test: close SSE response body explicitly 2026-04-16 22:57:31 +08:00
boojack a5ddd5adaf fix(server): close SSE clients during shutdown
Close long-lived SSE streams before HTTP shutdown so graceful shutdown is not held until the deadline. Also wait for background runners before closing the store to make shutdown ordering explicit.
2026-04-16 22:49:10 +08:00
boojack a7fd1dacc9 refactor(ai): use official provider SDKs (#5845) 2026-04-16 22:27:57 +08:00
boojack f394e9469a chore: add release-please automation (#5842) 2026-04-15 23:04:10 +08:00
Mattia Borda 5be530dbac chore: update Italian translation for 'cancel' key (#5841)
Signed-off-by: Mattia Borda <mattiagiovanni.borda@icloud.com>
2026-04-15 21:01:57 +08:00
boojack 411d8335e7 chore: set native color scheme for dark themes (#5840) 2026-04-15 20:55:41 +08:00
boojack a3a5b52d60 chore: tweak location picker 2026-04-15 20:07:36 +08:00
boojack ab5332901f fix: hide transcribe button without AI provider 2026-04-14 21:47:59 +08:00
boojack 35504cc8bd feat(web): add demo mode banner (#5836) 2026-04-14 09:08:17 +08:00
boojack 101704c8ea feat(ai): add BYOK audio transcription (#5832) 2026-04-13 22:09:24 +08:00
boojack 0ad0fec8d4 feat(ai): add Anthropic provider option 2026-04-12 21:42:17 +08:00
memoclaw d87539a1e1 feat: add Gemini transcription provider (#5830)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 21:12:03 +08:00
memoclaw 83ed32f119 feat(ai): add instance AI providers and transcription (#5829)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-12 19:23:34 +08:00
boojack 40fd700fb8 fix(fileserver): render SVG attachment previews 2026-04-12 10:41:38 +08:00
boojack efeb28c872 fix: remove duplicate Japanese locale keys 2026-04-12 10:34:20 +08:00
Takuro Onoue 0f7c7eb75e i18n: refine and normalize Japanese locale strings (#5826)
Signed-off-by: Takuro Onoue <kusanaginoturugi@gmail.com>
2026-04-11 22:15:26 +08:00
boojack 2523d966f4 chore(web): improve navigation accessibility 2026-04-10 22:27:29 +08:00
boojack fee7fcd660 fix(frontend): restore sitemap and robots routes 2026-04-10 22:23:00 +08:00
boojack 8cdcd7b284 refactor(attachments): extract visual gallery layout and tile style tokens 2026-04-10 08:55:20 +08:00
boojack 9ca71229a6 fix: preserve draft content when tab is suspended or editor remounts
Gate auto-save on initialization to prevent empty content from overwriting
cached drafts on remount. Flush drafts synchronously on visibilitychange/
pagehide so Chromium tab suspension cannot drop pending debounced saves.
Restore cached draft over saved memo content when they differ (inline editing).
2026-04-10 08:48:50 +08:00
boojack 938c405b0f refactor: move embedded content styles from global CSS to Tailwind 2026-04-08 23:34:49 +08:00
boojack 124708f164 chore: refactor attachment media layout and insert menu organization 2026-04-08 23:28:49 +08:00
boojack 7e21b728b3 fix: harden memo content iframe and HTML sanitization 2026-04-08 21:10:35 +08:00
boojack 2d682ae176 refactor(attachments): compact audio item layout and playback logic
Made-with: Cursor
2026-04-07 21:47:06 +08:00
boojack 5b78023fd5 Polish share-as-image UI and sidebar sharing actions
Made-with: Cursor
2026-04-07 21:07:40 +08:00
boojack e51985a29f feat(memo-editor): add compact live waveform recorder panel (#5817) 2026-04-07 20:40:34 +08:00
boojack 61c963841b chore(web): polish dark theme and calendar UI
- simplify ActivityCalendar state handling and shared max-count utilities
- remove calendar ring styling and darken the default dark theme primary colors
- tighten the audio recorder panel layout and action sizing
2026-04-06 22:44:11 +08:00
memoclaw 24fc8ab8ca feat(mentions): add memo mention parsing, notifications, and rendering (#5811)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-06 22:16:53 +08:00
boojack 38fc22b754 feat(memo): add image sharing in detail view
Keep the unpublished image-sharing flow scoped to memo detail pages.

- add a dedicated share-image preview and export pipeline
- measure the rendered memo card so preview and exported image stay aligned
- move the entry point into the detail sidebar and drawer only
2026-04-06 18:30:01 +08:00
boojack 2cbc70762b refactor(attachments): simplify the attachment library
- split attachment page states and primitives into focused components
- unify card and list item presentation across media, audio, documents, and unused uploads
- move attachment paging and cleanup flows onto shared query and view-model hooks
2026-04-06 17:39:58 +08:00
boojack 7ac9989d43 fix(map): align dark mode map styling 2026-04-06 17:38:56 +08:00
boojack 15d8ec10d5 chore: update locale translations for new i18n entries 2026-04-06 16:11:21 +08:00
boojack 067d7ff0ce chore: refactor memo editor audio recording flow 2026-04-06 15:46:38 +08:00
boojack c3e7e2c316 fix: normalize attachment MIME types before validation 2026-04-06 14:05:24 +08:00
boojack aafcc21ae6 fix: improve image preview dialog and live photo trigger 2026-04-06 13:41:27 +08:00
boojack 6b0487dcd8 fix: unify live photo previews around LIVE badge playback 2026-04-06 11:56:58 +08:00
boojack 065e817470 fix: backend tests action 2026-04-06 11:19:31 +08:00
boojack 10a955fd62 refactor: move plugin packages under internal 2026-04-06 11:10:32 +08:00
boojack 4b4e719470 feat(attachments): add Live Photo and Motion Photo support (#5810) 2026-04-06 10:47:01 +08:00
boojack 894b3eb045 fix(map): refine Leaflet controls and memo map styling 2026-04-06 08:45:54 +08:00
boojack 25feef3aad fix(api): tolerate missing related users in memo conversions (#5809) 2026-04-06 08:23:18 +08:00
boojack 87d411bc70 docs(agents): align contributor guidance with current CI workflows (#5808) 2026-04-06 08:02:21 +08:00
memoclaw f403f8c03c refactor: simplify memo metadata components 2026-04-02 22:30:21 +08:00
memoclaw 0e4d2d25ca refactor: simplify audio attachment playback component 2026-04-02 21:56:01 +08:00
Serhat 9676e72533 i18n: complete Turkish (tr) translations to 100% coverage (#5802)
Signed-off-by: Serhat <49079271+onwp@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-01 19:25:18 +08:00
memoclaw c0d5854f67 feat(editor): add voice note recording to the memo composer (#5801)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-04-01 09:36:33 +08:00
memoclaw a0d83e1a9e fix(web): refine attachment media layout 2026-04-01 08:40:36 +08:00
memoclaw cdbe40a390 chore: update security.md 2026-04-01 08:39:49 +08: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
boojack 201c8a8ea9 chore: add rc release handling 2026-03-31 08:34:36 +08:00
boojack 0e89407ee9 fix(filter): enforce CEL syntax semantics
Reject non-standard truthy numeric expressions in filters and document the parser as a supported subset of standard CEL syntax.

- remove legacy filter rewrites
- support standard equality in tag exists predicates
- add regression coverage for accepted and rejected expressions
2026-03-31 08:10:49 +08:00
boojack d3f6e8ee31 chore: harden MCP access control and origin validation 2026-03-31 00:12:28 +08:00
boojack 7c708ee27e chore: add migration upgrade coverage (#5796) 2026-03-30 23:51:57 +08:00
memoclaw e520b637fd fix: prevent stale comment drafts from being restored 2026-03-30 22:37:07 +08:00
memoclaw acbc914dea fix(webhooks): trigger memo updates for attachment and relation changes (#5795)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-30 20:01:16 +08:00
memoclaw 9610ed8fc8 fix(lint): correct goimports struct literal alignment after removing write-only credential fields (#5794)
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-29 20:31:09 +08:00
memoclaw 9d3a74bccc fix(api): make credentials write-only and restrict sensitive settings to admins
Security fixes for credential leakage across three resources:

- NOTIFICATION setting: restrict GetInstanceSetting to admin-only
  (was publicly accessible, exposing SMTP credentials)
- SMTP password: never return SmtpPassword in API responses (write-only)
- S3 secret: never return AccessKeySecret in API responses (write-only)
- OAuth2 ClientSecret: never return in API responses for any role
  (was previously returned to admins); remove redactIdentityProviderResponse
  in favor of omitting the field at the conversion layer
- Preserve-on-empty: when updating settings with an empty credential
  field, preserve the existing stored value instead of overwriting
  (applies to SmtpPassword, AccessKeySecret, and ClientSecret)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 07:34:00 +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
boojack d720efb6e6 chore: tweak featured sponsors
Removed the old sponsors table and replaced it with individual sponsor links and descriptions.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-29 02:17:29 +08:00
memoclaw 4add9b04ad fix: prevent local attachment uploads from overwriting files 2026-03-26 21:46:51 +08:00
memoclaw a24d420922 fix(api): restrict user email exposure to self and admins (#5784)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-25 22:02:08 +08: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
boojack 2327f4e3a6 chore: revamp featured sponsors in README
Updated featured sponsors section with new layout and content.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-25 00:02:26 +08:00
boojack 60a7d49874 chore: add InstaPods promotion to README
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-24 23:46:37 +08:00
memoclaw 4818bf3559 refactor(store): remove synthetic system bot user lookup (#5778)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-24 22:16:30 +08: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] ff32869d2f chore: improve access to default fields in cron parser (#5750)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-20 18:50:07 +08:00
google-labs-jules[bot] e0cc247823 chore: optimize multi-user RSS feed generation by fixing N+1 query (#5749)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-03-20 18:09:24 +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 e164517773 test: remove raw SQL migration backfill test setup 2026-03-19 19:54:39 +08:00
memoclaw f759b416af refactor(inbox): store memo comment payloads without activity records (#5741)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
2026-03-19 19:33:25 +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
Johnny 0ba4c0f397 feat(cli): add version subcommand (#5731) 2026-03-18 08:41:34 +08:00
johnnyjoygh f90d9a49a7 fix: improve installer compatibility and docs 2026-03-17 20:46:18 +08:00
johnnyjoygh 1ed542c21d feat: add GitHub release installer and release workflow 2026-03-17 20:16:16 +08:00
memoclaw 12e2205cb6 chore(backend): update Go toolchain and dependencies (#5730) 2026-03-16 21:07:52 +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 b8e9ee2b26 feat(mcp): enhance MCP server with full capabilities and new tools (#5720)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:15:52 +08:00
boojack d0b0652a7c chore: tweak README (#5717)
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-12 23:16:59 +08:00
memoclaw f4154d090b fix: restrict archived memo access to creator only (#5707)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:15:08 +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
memoclaw bdd3554b89 fix: handle chunk load errors after redeployment with auto-reload (#5703)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:45:16 +08:00
memoclaw e5b9392fcd chore: use issue types instead of labels for bug/feature templates
Replace `labels: [bug]` and `labels: [enhancement]` with `type: Bug`
and `type: Feature` to leverage GitHub's native issue types already
configured on this repo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:49:27 +08:00
memoclaw 1bfd121d7d chore: improve GitHub issue templates (#5700)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:25:10 +08:00
memoclaw 2ccb98a6cb fix: render audio attachments as inline players (#5699)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:57:48 +08:00
memoclaw 4503679155 enhance: improve link memo dialog with rich previews (#5697)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:54:13 +08:00
memoclaw e70149af5f enhance: polish PWA manifest and meta tags (#5695)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:02:13 +08:00
memoclaw cd5816c428 feat: add --allow-private-webhooks flag to bypass SSRF protection (#5694)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:46:03 +08:00
memoclaw 851e090ff9 chore: align branding with brand guidelines (#5693)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:32:36 +08:00
memoclaw 1e82714a52 perf: batch load memo relations when listing memos (#5692)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:19:19 +08:00
memoclaw 3d4f793f97 fix: include plain URLs and tags in memo snippet generation (#5688)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 22:03:45 +08:00
memoclaw 92d937b1aa feat: replace auto-increment ID with UID for identity provider resource names (#5687)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:01:22 +08:00
memoclaw f0c4489468 chore: move storage setting migration to v0.27.0 (#5686)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 19:44:36 +08:00
Peter Etelej 3010f10eaf fix: access token refresh on web app (#5681) 2026-03-05 19:29:21 +08:00
memoclaw 334dfef714 docs: streamline AGENTS.md and simplify CLAUDE.md (#5685)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 19:28:09 +08:00
boojack 5a17614a6e chore: tweak CODEOWNERS
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-05 19:14:16 +08:00
memoclaw b44d9c4629 docs: add CLAUDE.md for Claude Code quick reference (#5683)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:42:48 +08:00
longhe.li 0729779e04 fix: toggle focus mode do not reset editor height (#5504)
Signed-off-by: longhe.li <lilonghe@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-04 22:13:58 +08:00
thefatcode 2c3f9e3bfb fix: clear content search filter when selecting shortcut (#5499) 2026-03-04 22:12:41 +08:00
Ashour Badine 3ea6ea3108 fix: tag parsing truncates emojis with variation selectors (#5496) 2026-03-04 22:10:40 +08:00
Steven ce441644af fix: ensure comment divs span full width in MemoDetail 2026-03-04 19:13:58 +08:00
Biplav Barua def123232a feat: implement ListActivities pagination (#5468) 2026-03-04 19:08:47 +08:00
Steven c36934f348 chore: add featured sponsor section for Warp 2026-03-04 08:51:29 +08:00
Steven 0cf8805184 refactor(sse): move status indicator to avatar badge
Replace the standalone SSE dot above UserMenu with a small badge
overlaid on the bottom-right of the user avatar. Only visible when
status is connecting (yellow) or disconnected (red) — invisible in the
normal connected state, removing constant visual noise.
2026-03-03 23:25:01 +08:00
milvasic ea0892a8b2 feat: add live refresh via Server-Sent Events (SSE) with visual indicator (#5638)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-03-03 22:56:12 +08:00
Steven a69e405c95 refactor: remove dead code and deduplicate comment amount logic 2026-03-03 22:30:25 +08:00
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
boojack ec3ab350d9 chore: tweak sponsor assets
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-03-02 22:31:20 +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 803d488a5f feat(mcp): refactor MCP server to standard protocol structure
- Replace PAT-only auth with optional auth supporting both PAT and JWT
  via auth.Authenticator.Authenticate(); unauthenticated requests see
  only public memos, matching REST API visibility semantics
- Inline auth middleware into mcp.go following fileserver pattern;
  remove auth_middleware.go
- Introduce memoJSON response type that correctly serialises store.Memo
  (including Payload.Tags and Payload.Property) without proto marshalling
- Add tools: list_memo_comments, create_memo_comment, list_tags
- Extend list_memos with state (NORMAL/ARCHIVED), order_by_pinned, and
  page parameters
- Extend update_memo with pinned and state parameters
- Extract #tags from content on create/update via regex to pre-populate
  Payload.Tags without requiring a full markdown service rebuild
- Add MCP Resources: memo://memos/{uid} template returns memo as
  Markdown with YAML frontmatter, allowing clients to read memos by URI
- Add MCP Prompts: capture (save a thought) and review (search + summarise)
2026-03-01 23:10:23 +08:00
Johnny 16576be111 chore: polish MemoDetailSidebar for consistent structure and styles 2026-03-01 21:22:11 +08:00
Johnny 9628d3de21 fix: detect legacy installations with empty schema version 2026-03-01 20:59:39 +08:00
Johnny 7c1defba01 feat(webhook): dispatch webhook on memo comment creation 2026-03-01 20:11:23 +08:00
Johnny 53a8a436ba chore: fix frontend linter 2026-03-01 19:51:52 +08:00
Johnny 78efa6802e feat(store): change default storage type to local filesystem
Add migration scripts for existing instances without a storage setting
to explicitly preserve DATABASE as their storage type, ensuring backward
compatibility. Change the default for new installations to LOCAL to
improve out-of-the-box performance.
2026-03-01 19:42:01 +08:00
Johnny 026ea92f7b fix(editor): show newly linked memos when editing a memo with attachments 2026-03-01 19:16:57 +08:00
Johnny 252b3eff90 test(store): add tests for CreateMemo with custom timestamps 2026-03-01 19:08:27 +08:00
Mudkip 09d73e8b6e fix(mysql): handle CreateMemo custom timestamps with FROM_UNIXTIME (#5673) 2026-03-01 19:01:54 +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
Steven 2be4a52e1a ci: extend stale workflow to cover PRs and improve clarity
- Add PR stale/close handling alongside issues
- Reduce close grace period from 7 to 3 days
- Add inline comments explaining the two-phase stale behavior
- Rename workflow and job names for clarity
2026-02-26 22:44:47 +08:00
Kevin Zhang 54d6d8c644 chore: update documentation link in README (#5663)
Signed-off-by: Kevin Zhang <ztm0929@icloud.com>
2026-02-26 18:18:06 +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 26d10212c6 refactor: consolidate duplicated auth logic into auth package
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
2026-02-24 23:08:16 +08:00
Steven 47d9414702 feat: add MCP server with PAT authentication
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.
2026-02-24 22:54:51 +08:00
Steven 71263736b0 chore: fix codeowners 2026-02-23 20:10:18 +08:00
Mudkip ff3e4c5cfe fix: avoid truncating memo batch attachments (#5654) 2026-02-23 20:09:39 +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 704503e556 fix(store): allow memo/attachment deletion when local file is missing
Fixes two bugs reported in #5603:

1. store/attachment.go: ignore os.ErrNotExist when removing a local
   attachment file so that a missing file on disk (broken state from
   failed uploads) no longer blocks deletion of the DB record, allowing
   memos referencing corrupt attachments to be deleted normally.

2. memo_attachment_service.go: add nil guard on GetAttachment result
   before dereferencing it in SetMemoAttachments, preventing a nil
   pointer panic when an attachment UID no longer exists in the DB.
2026-02-23 10:26:40 +08:00
Steven 17fc8383df fix(web): improve MemoEditor layout and timestamp popover styling 2026-02-23 10:20:00 +08:00
Steven 150371d211 fix(webhook): remediate SSRF vulnerability in webhook dispatcher
- Add plugin/webhook/validate.go as single source of truth for SSRF
  protection: reserved CIDR list parsed once at init(), isReservedIP(),
  and exported ValidateURL() used at registration/update time
- Replace unguarded http.Client in webhook.go with safeClient whose
  Transport uses a custom DialContext that re-resolves hostnames at
  dial time, defeating DNS rebinding attacks
- Call webhook.ValidateURL() in CreateUserWebhook and both
  UpdateUserWebhook paths to reject non-http/https schemes and
  reserved/private IP targets before persisting
- Strip internal service response body from non-2xx error log messages
  to prevent data leakage via application logs
2026-02-23 10:14:24 +08:00
Steven f43965de00 chore: bump version 2026-02-22 18:06:58 +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
Steven 69485eecb3 chore: tweak readme 2026-02-12 22:35:58 +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
boojack f7d370dba1 chore: tweak readme
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-02-10 23:04:35 +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
Steven 27063d4850 chore(ci): auto-upload binaries to GitHub Release on publish 2026-02-10 20:51:05 +08:00
Steven 71e8a06463 chore: upgrade Echo v4 to v5.0.3 2026-02-10 09:15:27 +08:00
boojack cdadead6c9 chore: add SSD Nodes sponsorship
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-02-10 08:27:18 +08:00
Steven 2b19d8a969 fix(tests): update PAT tests to accept both custom and SQL errors
The PostgreSQL implementation returns 'PAT not found' when no rows match,
while SQLite/MySQL return 'sql: no rows in result set' from QueryRowContext.

Both behaviors are correct - the key fix is that PostgreSQL no longer
throws JSONB errors on missing/malformed data.

Changes:
- Update test assertions to accept either error type
- Fix comment punctuation for godot linter
- Maintain backward compatibility across all database drivers
2026-02-09 21:09:19 +08:00
Steven d9e8387d63 fix(postgres): handle missing PAT data gracefully and add comprehensive tests
Fixes #5612, #5611

Root cause: PostgreSQL's jsonb_array_elements() throws errors when the
'tokens' key is missing or malformed, while SQLite/MySQL return NULL
gracefully. This caused:
- 502 errors when creating admin after v0.25.3 → v0.26.0 upgrade
- Settings not persisting and users unable to stay logged in

Changes to store/db/postgres/user_setting.go:
- Remove strict JSONB operations from GetUserByPATHash query
- Fetch all PERSONAL_ACCESS_TOKENS rows and filter in Go
- Skip malformed/invalid JSON rows with continue (error recovery)
- Match SQLite/MySQL's forgiving error handling

New integration tests (store/test/user_setting_test.go):
- TestUserSettingGetUserByPATHashNoTokensKey
- TestUserSettingGetUserByPATHashEmptyTokensArray
- TestUserSettingGetUserByPATHashWithOtherUsers

New PostgreSQL-specific tests (store/db/postgres/user_setting_test.go):
- TestGetUserByPATHashWithMissingData (comprehensive edge cases)
- TestGetUserByPATHashPerformance (100+ users)
- TestUpsertUserSetting (basic upsert)

Test coverage:
 Missing PERSONAL_ACCESS_TOKENS key
 Empty/malformed JSON data
 Multiple users with mixed valid/invalid data
 Performance with 100+ users
 Error recovery without crashes

Benefits:
- No database migration required (TEXT column works fine)
- Backward compatible with v0.25.3 upgrades
- Handles missing/corrupt data gracefully
- Consistent behavior across all database drivers
2026-02-09 21:02:09 +08:00
MuLingQwQ b5108b4f97 fix(web): calendar navigation should use current page path (#5605) 2026-02-09 20:40:12 +08:00
Johnny b623162d37 chore: fix static check linter warnings 2026-02-08 21:37:02 +08:00
Johnny ba615172b0 chore: bump version 2026-02-08 21:28:11 +08:00
Johnny 984d9b461b fix: gracefully handle deleted memos in activity service to prevent inbox crashes 2026-02-08 21:26:18 +08:00
Johnny a69056a1c2 fix: handle underscores in environment variables correctly 2026-02-08 20:38:43 +08:00
Johnny f827296d6b chore: fix broken links 2026-02-08 19:46:03 +08:00
Johnny d9dc5be200 fix: replace echo.NewHTTPError with status.Errorf 2026-02-08 19:23:34 +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 86f780d1a4 chore: tweak security report email 2026-02-05 19:43:19 +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 7465fbb4cc refactor: improve GitHub Actions workflows structure and maintainability
- Add build-binaries workflow for multi-platform binary releases
- Rename workflows for conciseness:
  - demo-render-deploy.yml → demo-deploy.yml
  - build-and-push-canary-image.yml → build-canary-image.yml
  - build-and-push-stable-image.yml → build-stable-image.yml
- Centralize version config with env variables (GO_VERSION, NODE_VERSION, PNPM_VERSION)
- Standardize step names across all workflows
- Add concurrency controls to prevent redundant runs
- Update Node.js (20→22) and pnpm (9→10) versions to match build-binaries
- Improve job names with descriptive labels
- Add consistent comments and formatting
- Set artifact retention to 60 days for binary builds
2026-02-02 23:15:15 +08:00
Steven 4033f64b9a feat: add build binaries workflow for multi-platform releases
- Add workflow_dispatch trigger for manual binary builds
- Build for linux (amd64, arm64, arm/v7), darwin (amd64, arm64), windows (amd64)
- Package as tar.gz (Unix) and zip (Windows)
- Generate build summary with artifact sizes
2026-02-02 22:54:30 +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
Steven 8770b186e4 fix: add Unicode case-insensitive search for SQLite (#5559)
Add custom memos_unicode_lower() SQLite function to enable proper
case-insensitive text search for non-English languages (Cyrillic,
Greek, CJK, etc.).

Previously, SQLite's LOWER() only worked for ASCII characters due to
modernc.org/sqlite lacking ICU extension. This caused searches for
non-English text to be case-sensitive (e.g., searching 'блины' wouldn't
find 'Блины').

Changes:
- Add store/db/sqlite/functions.go with Unicode case folding function
- Register custom function using golang.org/x/text/cases.Fold()
- Update filter renderer to use custom function for SQLite dialect
- Add test for Unicode case-insensitive search
- Make golang.org/x/text a direct dependency

Fixes #5559
2026-02-02 21:10:07 +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 e1c8101d29 fix: preserve tag case when extracting markdown tags
Fixes #5566
2026-02-02 20:07:06 +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
Johnny d14cfa1c4f fix: auto-fix permission issues when upgrading from 0.25.3 to 0.26.0
Fixes #5551

The Docker image now runs as non-root (UID 10001) for security, but this
breaks upgrades from 0.25.3 where data files were owned by root.

Changes:
- Dockerfile: Keep USER as root, install su-exec
- entrypoint.sh: Fix ownership of /var/opt/memos, then drop to non-root
- Supports custom MEMOS_UID/MEMOS_GID env vars for flexibility

This allows seamless upgrades without manual chown on the host.
2026-02-01 08:37:06 +08:00
Johnny 1696c6c414 fix: add nil check for currentUser in DeleteUser
Defense-in-depth fix: Add missing nil check before accessing
currentUser.ID and currentUser.Role in DeleteUser function.

While the auth interceptor should block unauthenticated requests,
this check prevents potential nil pointer panic if fetchCurrentUser
returns (nil, nil).
2026-01-31 23:08:09 +08:00
Johnny c7b48b800f fix: add access control checks for attachments, comments, and reactions
Security fixes for multiple authorization bypass vulnerabilities:

- GetAttachment: Add visibility check via checkAttachmentAccess helper
- UpdateAttachment: Add ownership check (creator or admin only)
- Fileserver: Require creator/admin auth for unlinked attachments
- ListMemoAttachments: Add memo visibility check
- CreateMemoComment: Add memo visibility check for target memo
- ListMemoReactions: Add memo visibility check
- UpsertMemoReaction: Add memo visibility check

All checks follow the existing pattern used in GetMemo for consistency.
2026-01-31 23:02:30 +08:00
Johnny 86fab0cf4c fix(fileserver): use streaming for video/audio to prevent memory exhaustion
- Add serveMediaStream() to stream video/audio without loading into memory
- Use http.ServeFile for local files (zero-copy, handles range requests)
- Redirect to S3 presigned URLs for S3-stored media files
- Refactor for better maintainability:
  - Extract constants and pre-compile lookup maps
  - Consolidate duplicated S3 client creation logic
  - Split authentication into focused helper methods
  - Group code by responsibility with section comments
  - Add setSecurityHeaders() and setMediaHeaders() helpers
2026-01-31 22:01:28 +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 b32cba35c6 fix: add nil check for AnyResponse in WrapUnary method to prevent caching issues 2026-01-29 21:32:54 +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
Johnny a7b0d71f6e feat: implement EXIF metadata stripping for image uploads 2026-01-26 22:18:44 +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
Salman Chishti a8dbc1fd5e chore: upgrade GitHub Actions for Node 24 compatibility (#5527)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-01-26 09:02:57 +08:00
itzmk21 f22b3dad25 chore(i18n): update British English spelling (#5529) 2026-01-26 08:48:43 +08:00
Salman Chishti 1e82723e88 chore: upgrade GitHub Actions to latest versions (#5528)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-01-26 08:48:07 +08:00
XIN_____ 45945a1df7 chore: update Chinese translation (#5519) 2026-01-23 23:32:58 +08:00
Pádraic Slattery 7fbf3bed85 chore: update outdated GitHub Actions versions (#5522) 2026-01-23 23:22:14 +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 501e8f1eae chore: implement read-write lock for owner cache 2026-01-22 22:11:47 +08:00
Steven edcddf3c95 chore: fix tests 2026-01-22 21:59:23 +08:00
Steven fd29a98c90 chore: fix linter 2026-01-22 21:03:05 +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
Steven 956ae0ebc5 fix: prevent browser caching of API responses in MetadataInterceptor 2026-01-21 08:12:23 +08:00
Steven 9cc970a3ea chore: fix data directory handling 2026-01-21 08:02:25 +08:00
Steven 4180613fc0 fix: update demo mode handling 2026-01-21 07:36:30 +08:00
Johnny 324f795965 fix: improve default data directory handling 2026-01-20 23:55:46 +08:00
Johnny d3ed069ddb refactor: remove environment variable binding for instance URL 2026-01-20 23:45:59 +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 05f31e457e fix: add mmap size setting to database connection to prevent OOM errors 2026-01-20 21:53:31 +08:00
Johnny 552318209b fix: resolve flaky migration tests and add stable upgrade test (#5514) 2026-01-20 19:25:00 +08:00
Steven 00f21b86e2 chore: remove redundant tests 2026-01-20 09:12:36 +08:00
Steven d8b5bd61ab chore: tweak sponsor assets 2026-01-20 08:58:25 +08:00
Johnny 7089db06c2 test: enhance memo filter tests with COALESCE for JSON extraction and add migration data persistence tests 2026-01-19 23:09:17 +08:00
Johnny af2a2588bf chore(test): add edge case tests for user settings shortcuts and JSON fields 2026-01-19 22:50:14 +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 cbf46a2988 feat(filter): add CEL list comprehension support for tag filtering
Add support for CEL exists() comprehension with startsWith, endsWith, and
contains predicates to enable powerful tag filtering patterns.

Features:
- tags.exists(t, t.startsWith("prefix")) - Match tags by prefix
- tags.exists(t, t.endsWith("suffix")) - Match tags by suffix
- tags.exists(t, t.contains("substring")) - Match tags by substring
- Negation: !tags.exists(...) to exclude matching tags
- Works with all operators (AND, OR, NOT) and other filters

Implementation:
- Added ListComprehensionCondition IR type for comprehension expressions
- Parser detects exists() macro and extracts predicates
- Renderer generates optimized SQL for SQLite, MySQL, PostgreSQL
- Proper NULL/empty array handling across all database dialects
- Helper functions reduce code duplication

Design decisions:
- Only exists() supported (all() rejected at parse time with clear error)
- Only simple predicates (matches() excluded to avoid regex complexity)
- Fail-fast validation with helpful error messages

Tests:
- Comprehensive test suite covering all predicates and edge cases
- Tests for NULL/empty arrays, combined filters, negation
- Real-world use case test for Issue #5480 (archive workflow)
- All tests pass on SQLite, MySQL, PostgreSQL

Closes #5480
2026-01-17 12:36:39 +08:00
zz4zz f600fffe93 fix: use stable memos image tag (#5482) 2026-01-14 23:56:27 +08:00
Johnny 4bd0f29ee5 fix: resolve linter warning and cache race condition
- Suppress revive redundant-test-main-exit warning with //nolint
- Fix data race in cache.Clear() by using Delete() instead of map replacement
- Both changes maintain correct behavior while fixing CI failures
2026-01-14 23:50:37 +08:00
Johnny db57f4456a fix: resolve data races in store tests with atomic operations
Fix all data races detected by -race flag in parallel store tests.

Problems fixed:
1. TestMain not propagating exit code
   - Was: m.Run(); return
   - Now: os.Exit(m.Run())

2. Data races on global DSN variables
   - mysqlBaseDSN and postgresBaseDSN written in sync.Once
   - Read outside Once without synchronization
   - Race detector: write/read without happens-before relationship

3. Data races on container pointers
   - mysqlContainer, postgresContainer, testDockerNetwork
   - Same pattern: write in Once, read in cleanup

Solution: Use atomic operations
- atomic.Value for DSN strings (Store/Load)
- atomic.Pointer for container pointers (Store/Load)
- Provides proper memory synchronization
- Race-free reads and writes

Why sync.Once alone wasn't enough:
- sync.Once guarantees function runs once
- Does NOT provide memory barrier for variables written inside
- Reads outside Once have no synchronization with writes
- Race detector correctly flags this as violation

Technical details:
- atomic.Value.Store() provides release semantics
- atomic.Value.Load() provides acquire semantics
- Guarantees happens-before relationship per Go memory model
- All 159 parallel tests can safely access globals

Impact:
- Tests now pass with -race flag
- No performance degradation (atomic ops are fast)
- Maintains parallel execution benefits (8-10x speedup)
- Proper Go memory model compliance

Related: Issues #2, #3 from race analysis
2026-01-14 23:37:12 +08:00
Johnny e082adf7b6 fix: set DRIVER=sqlite in CI to prevent TestMain from spawning child processes
Problem:
- store/test/TestMain checks if DRIVER env var is set
- If not set, it runs tests for all 3 drivers (sqlite, mysql, postgres)
  by spawning child 'go test' processes
- This conflicts with t.Parallel() in individual tests
- CI workflow didn't set DRIVER, triggering multi-driver execution

Solution:
- Set DRIVER=sqlite in GitHub Actions workflow
- TestMain will run tests once with SQLite driver
- Tests run in parallel with t.Parallel() as intended
- Avoids spawning child processes and race conditions

Why SQLite:
- Fastest test execution (no container startup)
- Sufficient for CI validation
- MySQL/Postgres can be tested locally when needed

This fixes the 'table already exists' errors and test flakiness
in CI while maintaining parallel execution benefits.
2026-01-14 22:50:30 +08:00
Johnny 411e8fc5b0 perf: enable parallel execution for all store tests
Add t.Parallel() to all 159 test functions in store/test/

Benefits:
- Tests run in parallel (8-16 concurrent on typical CI)
- Each test already has isolated database (safe to parallelize)
- No shared state between tests
- Go test runner handles synchronization

Expected performance:
- SQLite tests: 4-6min → 30-45sec (87% faster)
- MySQL tests: 6-8min → 45-60sec (88% faster)
- Better CPU utilization (10-15% → 80-95%)

Why it's safe:
- NewTestingStore() creates isolated DB per test
- No global state mutations
- Each test uses t.TempDir() for file isolation
- Container-based tests use unique database names

Impact on CI workflow:
- Backend tests workflow: 4-6min → 1-2min total
- Store test group: 3-4min → 20-30sec
- 8-10x speedup from parallelization alone
2026-01-14 22:44:19 +08:00
Johnny 07b837b6f6 perf: optimize backend tests with parallel execution
Major improvements:
- Split tests into 4 parallel groups (store, server, plugin, other)
  * 3-4x faster test execution (4-6min → 1-2min)

- Enable golangci-lint cache (was disabled)
  * Saves 20-30s on lint checks

- Remove unnecessary flags
  * check-latest: API call overhead
  * --verbose: unnecessary output
  * skip-cache: disabled caching

- Add race detector (-race)
  * Better concurrency bug detection
  * Only 10-20% overhead

- Add coverage tracking
  * Per-group coverage upload to Codecov
  * Better visibility into test quality

- Add concurrency control
  * Cancel outdated PR runs
  * Saves runner minutes

- Clean up output processing
  * Remove test.log and complex awk/sed parsing
  * GitHub Actions shows output by default

Performance impact:
- Setup: 30s → 10s (2-3x faster)
- Tests: Sequential → 4 parallel jobs (3-4x faster)
- Total: 4-6min → 1-2min (~70% faster)
2026-01-14 22:34:46 +08:00
Johnny d7c5641246 fix: correct manifest merge step in workflows
- Re-run docker/metadata-action in merge job to generate proper JSON
- Use steps.meta.outputs.json instead of needs.prepare.outputs.tags
- Remove unused prepare job outputs (tags, labels)
- Simplify workflow dependency chain

This fixes the jq parse error when creating multi-arch manifests.
2026-01-14 22:28:26 +08:00
Johnny d1d2d86900 perf: optimize CI/CD workflows and Docker builds
- Implement parallel matrix builds for multi-platform images (~50% faster)
- Add pnpm store caching for 20-40s savings on cache hits
- Use --frozen-lockfile for faster, deterministic installs
- Optimize Dockerfile: CGO_ENABLED=0, -trimpath, static linking
- Reduce Docker layers and improve caching strategy
- Enhance .dockerignore to exclude unnecessary files (~1MB saved)

Build time improvements:
- Canary: 12-18min → 6-10min
- Stable: 17-27min → 8-12min
2026-01-14 22:12:28 +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 c45a59549a fix: replace os.Exit with panic for clearer error handling 2026-01-12 23:36:48 +08:00
Johnny 69b62cccdb test: optimize store tests performance by reusing docker image and reducing build context 2026-01-12 23:30:56 +08:00
Johnny f58533003b fix: clean up memo_relation and attachments when deleting memo
Fixes #5472

Move cleanup logic to store.DeleteMemo to ensure data consistency:
- Delete memo_relation records where memo is source (MemoID) or target (RelatedMemoID)
- Delete attachments linked to the memo (including S3/local files)

This prevents stale COMMENT records in memo_relation after deleting
a memo that has comments.
2026-01-12 23:18:04 +08:00
Johnny 6899c2f66a chore: fix golangci-lint 2026-01-12 22:32:38 +08:00
Johnny 31f634b71a chore: add more tests 2026-01-12 22:28:42 +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
Johnny 7053edae27 fix: allow guests to view public memo comments
Add ListMemoComments to public endpoints whitelist so unauthenticated
users can see public comments. The service layer already filters
comments by visibility (only PUBLIC for guests).

Fixes #5471
2026-01-11 22:35:12 +08:00
Faizaan pochi da2dd80e2f fix: return Unauthenticated instead of PermissionDenied on token expiration (#5454) 2026-01-08 23:21:33 +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
Johnny 1e8505bfeb chore: fix tests 2026-01-08 23:06:28 +08:00
Johnny af6a0726d8 chore: drop redundant indexes in sqlite migration 2026-01-08 22:53:46 +08:00
Johnny 1985205dc2 chore: remove memo_organizer table 2026-01-08 22:28:13 +08:00
Johnny f4cf2e9559 test: improve migration tests stability and maintainability
- Fix linting issues and address testcontainers deprecation in store/test/containers.go
- Extract MemosStartupWaitStrategy for consistent container health checks
- Refactor migrator_test.go to use a consolidated testMigration helper, reducing duplication
- Add store/test/Dockerfile for optimized local test image builds
2026-01-07 23:04:12 +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
Faizaan pochi 7c3fcc297d fix: allow public memo API access without authentication (#5451) 2026-01-07 20:52:04 +08:00
Johnny 14fb38f375 fix: attachment table name 2026-01-07 20:44:21 +08:00
Johnny c29c1d3e1f fix: seed data 2026-01-07 20:41:16 +08:00
Johnny cc9a214be8 revert: revert system_setting to instance_setting rename changes
Reverts only the system_setting → instance_setting rename related changes from commit d326c71.
Keeps the resource → attachment rename changes intact.

- Reverts table name back to system_setting in all database drivers (MySQL, PostgreSQL, SQLite)
- Removes migration files for the system_setting rename
- Reverts LATEST.sql files to use system_setting table
2026-01-07 20:38:02 +08:00
Johnny e75862de31 chore: fix tests 2026-01-07 09:17:34 +08:00
Johnny 79f1edc9ba chore: bump version 2026-01-07 09:08:20 +08:00
Johnny 9ccb658768 fix: sign up redirect 2026-01-07 08:50:10 +08:00
Johnny 64b487d4af chore: fix seed data 2026-01-07 08:34:42 +08:00
Johnny d326c71078 refactor(db): rename tables for clarity - resource→attachment, system_setting→instance_setting 2026-01-06 23:36:42 +08:00
Johnny 01669685b4 fix(ci): remove invalid revive rule 'use-waitgroup-go' from golangci-lint config 2026-01-06 21:12:40 +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
Steven fb4f3e70dc fix: resolve golangci-lint issues 2026-01-06 20:41:24 +08:00
Steven e1941e7843 fix: attachment type checks 2026-01-06 20:37:04 +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 86013d6c2a fix(scripts): add file existence check in file_env (#5424)
Signed-off-by: majiayu000 <1835304752@qq.com>
2026-01-04 19:18:48 +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
Johnny a630b70ba9 chore: add .worktrees to gitignore 2026-01-03 12:44:37 +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 f66c750075 chore: simplify attachment file writing 2025-12-31 21:54:37 +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 c2aea5a4b7 feat: implement refresh token rotation with sliding window sessions in the auth service 2025-12-30 23:00:15 +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 d7478b8003 perf: optimize memory usage for statistics and image processing 2025-12-30 00:06:23 +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
boojack d21610cce1 chore: add @johnnyjoygh as a code owner
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-12-26 23:04:16 +08:00
Steven 12fdf930a6 fix: invalidate React Query cache after memo reaction changes 2025-12-26 00:13:44 +08:00
Steven 9f5a7bb889 docs: create AGENTS.md for AI agents and remove outdated CLAUDE.md
- Remove outdated CLAUDE.md with obsolete architecture references
- Create comprehensive AGENTS.md covering:
  - Backend: Go, gRPC, Connect RPC, store layer, migrations
  - Frontend: React, React Query, Context API, state management
  - Development commands, workflows, and testing patterns
  - Code conventions, configuration, CI/CD, and security notes
2025-12-25 23:48:16 +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 5828f34aae feat: implement scheduler plugin
- Added `scheduler` package with core functionalities for job scheduling.
- Implemented job registration, execution, and graceful shutdown mechanisms.
- Introduced middleware support for logging, recovery from panics, and timeout handling.
- Developed cron expression parser to support both 5-field and 6-field formats.
- Created comprehensive integration and unit tests for scheduler, job definitions, middleware, and parser functionalities.
- Enhanced logging capabilities to track job execution and errors.
2025-12-20 15:43:25 +08:00
Johnny b55a0314f8 feat: add Email Plugin with SMTP functionality
- Implemented the Email Plugin for self-hosted Memos instances, providing SMTP email sending capabilities.
- Created configuration structure for SMTP settings with validation.
- Developed message structure for email content with validation and formatting.
- Added synchronous and asynchronous email sending methods.
- Implemented error handling and logging for email sending processes.
- Included tests for client, configuration, and message functionalities to ensure reliability.
- Updated documentation to reflect new features and usage instructions.
2025-12-20 14:23:15 +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 a6c32908a0 refactor(auth): remove legacy session cookie authentication
- Remove SessionCookieName and SessionSlidingDuration constants
- Remove ExtractSessionCookieFromHeader() function
- Remove SessionIDContextKey and GetSessionID() function
- Remove sessionID parameter from SetUserInContext()
- Remove SessionID field from AuthResult struct
- Remove session cookie extraction from middleware
- Update documentation to reflect JWT + PAT only auth

Session cookies were never being set since migration to refresh token
authentication. This change removes ~50 lines of dead code and clarifies
that the system uses JWT access tokens, refresh tokens, and PATs only.
2025-12-19 00:09:08 +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 ea14280cb3 feat: enhance attachment handling with MIME type validation 2025-12-17 08:58:43 +08:00
Johnny 642271a831 feat: add iframe support for embedded videos in markdown content 2025-12-17 08:52:59 +08:00
Johnny 310590b278 chore: fix golang checks 2025-12-16 22:53:36 +08:00
Johnny 40e129b8af refactor(auth): streamline session authentication and cookie handling 2025-12-16 22:23: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 6926764b91 fix: allow unauthenticated CreateUser for first user registration
Add CreateUser to PublicMethods ACL whitelist to fix "authentication required"
error during first-time setup. The CreateUser method already has proper security
logic that automatically assigns HOST role to the first user and enforces
DisallowUserRegistration setting for subsequent users.

Fixes #5352

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 23:18:30 +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
Johnny d14e66daf5 fix: openapi generation (#5349) 2025-12-15 10:55:04 +08:00
Davide Truffa 8659f69da0 chore(locales): update Italian translation (#5346) 2025-12-15 10:05:32 +08:00
Johnny 09afa579e4 chore: implement session sliding expiration and JWT authentication
- Added UpdateSessionLastAccessed method to update session access time.
- Enhanced Authenticate method to support both session cookie and JWT token authentication.
- Introduced AuthResult struct to encapsulate authentication results.
- Added SetUserInContext function to simplify context management for authenticated users.

refactor(auth): streamline gRPC and HTTP authentication

- Removed gRPC authentication interceptor and replaced it with a unified approach using GatewayAuthMiddleware for HTTP requests.
- Updated Connect interceptors to utilize the new authentication logic.
- Consolidated public and admin-only method checks into service layer for better maintainability.

chore(api): clean up unused code and improve documentation

- Removed deprecated logger interceptor and unused gRPC server code.
- Updated ACL configuration documentation for clarity on public and admin-only methods.
- Enhanced metadata handling in Connect RPC to ensure consistent header access.

fix(server): simplify server startup and shutdown process

- Eliminated cmux dependency for handling HTTP and gRPC traffic.
- Streamlined server initialization and shutdown logic for better performance and readability.
2025-12-15 10:04:11 +08:00
Steven 65a19df4be fix(backend): correct generic type parameter in withHeaderCarrier helper
Problem:
The withHeaderCarrier generic function had a type mismatch that caused compilation
errors in CI. The function used `T proto.Message` constraint, but Connect's Response
type expects the non-pointer message type while protobuf methods return pointers.

Error from CI:
  type T of resp does not match *T (cannot infer T)

This occurred because:
- Connect methods expect: *connect.Response[v1pb.CreateSessionResponse]
- Service methods return: (*v1pb.CreateSessionResponse, error)
- Old signature: fn func(context.Context) (T, error) with T proto.Message
- This caused T to be inferred as *v1pb.CreateSessionResponse
- Leading to return type: *connect.Response[*v1pb.CreateSessionResponse] (wrong!)

Solution:
Changed generic signature to explicitly handle the pointer/non-pointer distinction:
- New signature: fn func(context.Context) (*T, error) with T any
- T is now the non-pointer type (e.g., v1pb.CreateSessionResponse)
- fn returns *T (e.g., *v1pb.CreateSessionResponse)
- Return type is correctly: *connect.Response[T] (e.g., *connect.Response[v1pb.CreateSessionResponse])

Also removed unused "google.golang.org/protobuf/proto" import and improved documentation
to clarify the T vs *T distinction.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 08:06:13 +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 3d893a7394 fix(backend): implement protocol-agnostic header setting for dual gRPC/Connect-RPC support
Problem:
The codebase supports both native gRPC and Connect-RPC protocols, but auth
service was using grpc.SetHeader() which only works for native gRPC. This
caused "failed to set grpc header" errors when using Connect-RPC clients
(browsers using nice-grpc-web).

Solution:
- Created HeaderCarrier pattern for protocol-agnostic header setting
- HeaderCarrier stores headers in context for Connect-RPC requests
- Falls back to grpc.SetHeader for native gRPC requests
- Updated auth service to use SetResponseHeader() instead of grpc.SetHeader()
- Refactored Connect wrappers to use withHeaderCarrier() helper to eliminate
  code duplication

Additional fixes:
- Allow public methods when gRPC metadata is missing in ACL interceptor
- Properly handle ParseSessionCookieValue errors instead of ignoring them
- Fix buildSessionCookie to gracefully handle missing metadata

Files changed:
- server/router/api/v1/header_carrier.go: New protocol-agnostic header carrier
- server/router/api/v1/auth_service.go: Use SetResponseHeader, handle missing metadata
- server/router/api/v1/connect_services.go: Use withHeaderCarrier helper
- server/router/api/v1/acl.go: Allow public methods without metadata
- server/router/api/v1/connect_interceptors.go: Handle ParseSessionCookieValue errors

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 07:46:28 +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
xiaolinny 6beb3fcde0 chore: fix some typos in comments (#5332)
Signed-off-by: xiaolinny <xiaolincode@outlook.com>
2025-12-11 07:50:16 +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
Johnny a863154224 docs: update Memos Codebase Guide for clarity and structure 2025-12-02 08:19:20 +08:00
Steven 0610257562 refactor(store): remove deprecated migration_history table and backward compatibility code
Complete removal of migration_history system in favor of instance_setting based schema versioning.

Changes:
- Remove migration_history table creation from all LATEST.sql files
- Delete all migration_history model and implementation files (~300 lines)
- Remove FindMigrationHistoryList and UpsertMigrationHistory from Driver interface
- Replace complex backward compatibility functions with simple version check
- Update health check to use instance_setting instead of migration_history
- Simplify checkMinimumUpgradeVersion to detect pre-v0.22 installations

Breaking change:
Users on versions < v0.22.0 (May 2024) must upgrade to v0.25.x first before upgrading to this version.
Clear error message with upgrade instructions will be shown for old installations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 22:54:30 +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
Steven d1492007ab fix(store): filter inbox notifications by message type at database level
Add MessageType filter to FindInbox to exclude legacy VERSION_UPDATE
notifications from inbox queries. This resolves the issue where users
saw notification counts but no items displayed, as VERSION_UPDATE
entries cannot be rendered in the new UserNotification API.

Changes:
- Add MessageType field to FindInbox struct for database-level filtering
- Implement JSON extraction filters in SQLite, MySQL, and PostgreSQL drivers
- Update ListUserNotifications to filter MEMO_COMMENT type at store level

This approach improves performance by filtering at the database rather
than in application code, reducing unnecessary data transfer for users
with many legacy inbox entries.

Fixes #5278

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:43:05 +08:00
Steven 17e116b977 chore: fix linter 2025-12-01 08:27:23 +08:00
Johnny 545323d12c refactor(rss): comprehensive RSS service improvements
Major performance and standards compliance improvements to RSS feed generation:

Performance optimizations:
- Fix N+1 query problem by batch loading attachments (101 queries → 2-3)
- Add in-memory caching with 1-hour TTL and LRU eviction
- Implement ETag-based conditional requests (304 Not Modified)
- Add database-level pagination with LIMIT clause
- Clean up expired cache entries to prevent memory leaks

RSS 2.0 compliance:
- Add item titles extracted from memo content
- Include both description and content:encoded fields
- Add author information (name and email)
- Set proper Last-Modified headers
- Use specific application/rss+xml content type

Code quality:
- Fix potential index out of bounds panic in title generation
- Improve markdown heading stripping with regex (handles # to ######)
- Add proper HTTP caching headers (Cache-Control, ETag, Last-Modified)
- Thread-safe cache implementation with RWMutex
- Better error handling and edge case coverage

The RSS backend now follows industry best practices with optimal
performance, full standards compliance, and production-ready reliability.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 00:28:23 +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
Huang Youchuan 26cb357685 fix: update user session retrieval to use user.ID instead of userID (#5294)
Co-authored-by: huangyouchuan <huangyouchuan@letu.com>
2025-11-30 11:45:16 +08:00
Johnny ee9d9603ee chore: remove goreleaser 2025-11-30 11:42:46 +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 07a030ddfd fix(postgres): update tag filtering SQL to ensure proper type casting for LIKE comparisons 2025-11-26 23:04:07 +08:00
Steven 50f49fc00d chore: update demo data 2025-11-26 21:58:56 +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 424f11f227 fix(store): fix PostgreSQL tag filtering type inference error
Resolves issue where tag filtering in PostgreSQL databases failed with "operator does not exist: jsonb ~~ unknown" error. The hierarchical tag filtering feature introduced in commit 5e47f25b generated SQL with implicit type placeholders that PostgreSQL couldn't infer.

The fix explicitly casts the LIKE comparison placeholder to text (::text) in the PostgreSQL dialect, ensuring proper type resolution for the query parameter.

Fixes #5275

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 07:40:39 +08:00
Steven 68c17469a3 fix(markdown): fix UTF-8 truncation for CJK characters in snippet generation
The truncateAtWord function was slicing strings by byte position instead of
character position. When truncating text with multi-byte UTF-8 characters
(like CJK), this could cut in the middle of a character, creating invalid
UTF-8 and causing gRPC marshaling errors.

Fixed by converting to runes before truncation to ensure we always cut at
proper character boundaries. Added test cases for CJK characters.

Fixes #5276

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 07:34:28 +08:00
Steven e17cd163c6 chore: bump version 2025-11-25 22:17:45 +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 60d977c0bf fix: add period to comment for golangci-lint compliance 2025-11-23 23:47:17 +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
Steven d69435c97c chore(docs): update security policy to prevent public vulnerability disclosure
- Direct security reports to email only instead of public GitHub issues
- Set clear expectations: no CVEs during beta (v0.x) phase
- Add security best practices for self-hosted deployments
- Plan formal vulnerability disclosure program for v1.0+

Addresses #5255
2025-11-21 09:13:40 +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 3989100a27 fix(parser): handle additional Unicode punctuation in tag parsing 2025-11-19 22:19:56 +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 d1b2c0308b chore: add demo user access token for testing purposes 2025-11-11 08:31:05 +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
boojack 659c63165b chore: add Vercel OSS Program badge
Added Vercel OSS Program badge to README.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-11-10 20:18:41 +08:00
Johnny 9a100d55be chore(server): remove profiler code and endpoints (#5244)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-10 20:17:21 +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 805bb4e741 chore(github): streamline issue templates with validation and better structure
Improve bug report and feature request templates to reduce duplicate submissions and gather better information:

Bug Report Template:
- Add pre-submission checklist requiring users to search existing issues and test on latest version/demo
- Add dropdown for issue location (stable, dev, demo site, older version)
- Restructure fields with clearer labels and better placeholders
- Add "Expected Behavior" section for clarity
- Combine screenshots and context with helpful prompts

Feature Request Template:
- Add pre-submission checklist to confirm issue search
- Expand feature type categories (API/Backend, Integrations/Plugins, Security/Privacy, Performance)
- Add "Problem or Use Case" field to understand the underlying need
- Add "Alternatives Considered" section
- Improve placeholders with specific examples

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 10:28:51 +08:00
boojack 906412013f refactor(api): remove test_auth.go and inline test helpers (#5235)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 09:53:29 +08:00
boojack 13fea64d15 fix(api): implement custom memo ID support in CreateMemo (#5234)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 09:43:10 +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 8f29db2f49 fix(server): prevent memory exhaustion in thumbnail generation
Address high memory usage when opening resource tab (fixes #5183) by implementing:

1. Concurrency control: Limit thumbnail generation to 3 concurrent operations using semaphore to prevent memory exhaustion when many images are requested simultaneously

2. S3 optimization: Skip server-side thumbnail generation for S3-stored images by default. S3 images now use presigned URLs directly, avoiding:
   - Downloading large images from S3 into server memory
   - Decoding and resizing images on the server
   - High memory consumption during batch requests

3. Memory management improvements:
   - Explicitly clear blob and decoded image from memory after use
   - Restructure thumbnail cache check to avoid unnecessary semaphore acquisition
   - Double-check pattern to prevent duplicate generation while waiting

This restores the original S3 behavior before commit e4f6345 while maintaining thumbnail support for local/database storage.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 09:04: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
Steven 8f136ffa75 fix(api): correct user registration logic and first-user detection
- Changed first-user detection to check for any users instead of only HOST users
- Moved registration setting check before role assignment to properly block unauthorized registrations
- Fixed role assignment logic to ensure unauthenticated users always get USER role
- Updated test cases to create host user first when not testing first-user scenario

This ensures the first user is always created as HOST and registration settings are properly enforced for subsequent user creation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 23:41:47 +08:00
boojack 21d31e3609 fix(security): implement security review recommendations (#5228)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-06 23:32:27 +08:00
Elliott bb8fa90496 feat(i18n): add missing translations for zh-Hans (closes #5209) (#5229) 2025-11-06 22:32:03 +08:00
Steven 32d47abef2 fix(api): use correct instance setting method in user registration
Replace non-existent GetWorkspaceGeneralSetting with GetInstanceGeneralSetting
to properly check if user registration is allowed. This fixes a compilation
error that was preventing tests from running.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 20:00:35 +08:00
Florian Dewald 769dcd0cf9 fix(security): add missing authorization checks to various services (#5217) 2025-11-06 19:42:44 +08:00
boojack df93120f60 chore: add Claude Code GitHub workflow (#5227) 2025-11-06 19:40:01 +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 71d0dbaf41 chore: fix linter 2025-11-05 23:59:24 +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
Florian Dewald 5f57f48673 fix(security): validate attachment filenames (#5218) 2025-11-05 08:48:55 +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
Claude dc9470f71c feat: implement OAuth state management with CSRF protection and cleanup functionality 2025-11-02 23:23:44 +08:00
Claude fb01b49ecf feat: add VisuallyHidden component and enhance LocationDialog accessibility 2025-11-02 23:02:08 +08:00
Claude 638b22a20d chore: implement InsertMenu with file upload and memo linking functionality 2025-11-02 22:53:07 +08:00
Steven 93964827ad refactor: redesign memo editor action bar UI
- Replace multiple action buttons with unified InsertMenu dropdown
- Consolidate upload, link memo, and location into single + button
- Redesign VisibilitySelector with text-based dropdown UI
- Unify badge styling for location, attachments, and links
  - Consistent height (h-7), padding, gaps, and border styles
  - Secondary foreground text color with hover states
  - Max width with truncation for long content
- Add image thumbnails in attachment badges
- Simplify button hierarchy with ghost variant for save/cancel
- Remove obsolete components (TagSelector, MarkdownMenu, etc.)
- Extract LocationView to separate component for better organization

Fixes #5196
2025-10-31 21:29:58 +08:00
Steven 1ced0bcdbd chore: fix linter 2025-10-31 08:36:12 +08:00
Steven bc1550e926 refactor(api): migrate inbox functionality to user notifications
- Remove standalone InboxService and move functionality to UserService
- Rename inbox to user notifications for better API consistency
- Add ListUserNotifications, UpdateUserNotification, DeleteUserNotification methods
- Update frontend components to use new notification endpoints
- Update store layer to support new notification model

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 08:33:09 +08:00
Steven e915e3a46b refactor(web): refactor MemoFilters component and add comprehensive filter support
- Refactored MemoFilters.tsx for better maintainability:
  * Centralized filter configuration with FILTER_CONFIGS object
  * Added TypeScript interfaces for type safety
  * Removed separate FactorIcon component
  * Extracted handleRemoveFilter function
  * Improved imports organization

- Polished MemoFilters UI styles:
  * Changed to modern pill/badge design with rounded-full
  * Enhanced spacing and color schemes
  * Added smooth transitions and hover effects
  * Improved interactive remove button with destructive color hints
  * Better text readability with font-medium

- Added comprehensive filter support to all pages:
  * Explore page: Added full filter support (was missing)
  * Archived page: Enhanced from basic to full filter support
  * UserProfile page: Enhanced from basic to full filter support
  * All pages now support: content search, tag search, pinned, hasLink, hasTaskList, hasCode, and displayTime filters

- Consistency improvements:
  * All pages using PagedMemoList now have identical filter logic
  * Respects workspace settings for display time (created/updated)
  * Unified filter behavior across Home, Explore, Archived, and UserProfile pages
2025-10-30 22:52:58 +08:00
Steven 1e954070b9 refactor(web): improve memo component skeleton and loading states 2025-10-30 22:25:19 +08:00
Steven 5e47f25bf5 feat(store): add hierarchical tag filtering support
Tag filters now support hierarchical matching where searching for a tag (e.g., "book") will match both the exact tag and any tags with that prefix (e.g., "book/fiction", "book/non-fiction"). This applies across all database backends (SQLite, MySQL, PostgreSQL) with corresponding test updates.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 00:21:53 +08:00
boojack a2bfba6928 chore: update readme
Added LambdaTest to sponsorship section

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-30 00:16:40 +08:00
Steven f65633e8a9 chore: fix linter issues in backend and frontend
- Remove extra blank line in memo_service.go (goimports)
- Remove invalid fields from CreateMemoRequest call (validateOnly, requestId)
- Clean up unnecessary comments

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:41:20 +08:00
Steven 243ecf14b0 refactor(api): remove DeleteMemoTag and RenameMemoTag endpoints
BREAKING CHANGE: Removed DeleteMemoTag and RenameMemoTag API endpoints
for better API consistency. Tags should now be managed by updating memo
content directly via UpdateMemo endpoint.

Backend changes:
- Remove RenameMemoTag and DeleteMemoTag RPC methods from proto
- Remove backend implementations in memo_service.go
- Regenerate protocol buffers (Go, TypeScript, OpenAPI)

Frontend changes:
- Remove RenameTagDialog component
- Simplify TagsSection to remove rename/delete functionality
- Improve tag styling with active state highlighting
- Add smooth transitions and better hover interactions
- Polish TagTree component for consistency
- Tags now only support click-to-filter (no inline editing)

Style improvements:
- Active tags highlighted with primary color and font-medium
- Consistent hover states across flat and tree views
- Better spacing and visual hierarchy
- Improved empty state styling

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:32:47 +08:00
Steven d794c0bf8b feat(web): improve loading performance with skeleton screens and parallel fetches
- Add MemoSkeleton component for smooth initial page load experience
- Integrate skeleton loader into PagedMemoList during initial fetch
- Parallelize user settings and shortcuts API calls (~50% faster session init)
- Batch-fetch memo creators in parallel to eliminate individual loading spinners
- Pass showCreator prop to Explore page for proper skeleton rendering

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 23:53:35 +08:00
Steven 2371bbb1b7 feat(web): add quick language and theme switchers to user menu
- Add language and theme selector submenus to UserMenu component for quick access
- Refactor shared utilities: extract THEME_OPTIONS constant and getLocaleDisplayName() function
- Update LocaleSelect and ThemeSelect to use shared utilities, eliminating code duplication
- Make UserMenu reactive with MobX observer for real-time setting updates
- Fix language switching reactivity by immediately updating workspaceStore.state.locale
- Add scrollable menu support for language selector (max-h-[90vh])
- Apply same instant locale update to PreferencesSection for consistency

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 22:32:25 +08:00
Steven d693142dd4 feat(web): enhance code blocks with copy button and fix link navigation
Add custom code block renderer with language display and copy functionality. Links now open in new windows, and clicking image links no longer triggers both link navigation and image preview.

- Add CodeBlock component with copy-to-clipboard button and language label
- Configure all markdown links to open in new windows with target="_blank"
- Fix image link behavior to prevent duplicate actions when clicked

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 22:06:07 +08:00
Steven b00df8a9d1 fix(web): remove error notifications for location geocoding failures
Remove disruptive error toasts when reverse geocoding or geolocation fails.
Instead, silently fall back to using coordinates as the location placeholder.
This improves UX for users in regions where OpenStreetMap is restricted
(e.g., China) or when CSP blocks external API calls.

Fixes #5198, #5197

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 21:28:29 +08:00
Steven 5f7c758f38 fix(web): make layout and direction settings reactive in UI
Fixed issue #5194 where changing the layout (List/Masonry) or sort direction
didn't update the UI until page refresh. The root cause was that ViewState
fields weren't marked as MobX observables, so the UI didn't react to changes
even though values were being persisted to localStorage.

Solution: Added constructor to ViewState that marks orderByTimeAsc and layout
fields as observable, following the same pattern used in other stores like
MemoFilterState.

Fixes #5194

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 07:58:15 +08:00
Steven 91a7e927a5 fix(server): reduce static asset cache to prevent stale files after redeploy
Changed Cache-Control max-age from 7 days to 1 hour with immutable directive.
This prevents users from experiencing blank pages or JS errors when accessing
frequently redeployed instances (e.g., demo environments) where old cached
assets may reference files that no longer exist after redeployment.

Since Vite generates content-hashed filenames, the immutable directive prevents
unnecessary revalidation while the shorter cache duration ensures fresh assets
are served within an hour of redeployment.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 07:55:02 +08:00
Steven 2197178dd7 chore: update README for clarity and consistency 2025-10-28 07:46:45 +08:00
boojack d516f9aab2 chore: tweak readme
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-27 23:41:24 +08:00
Steven f635d85bcf chore: fix reactions seed data
- Add comprehensive inline documentation for auth services
- Document session-based and token-based authentication flows
- Clarify authentication priority and validation logic
- Add detailed comments for JWT token structure and claims
- Fix reactions seed data to use memo UIDs instead of numeric IDs

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 20:27:27 +08:00
Claude f241b590a2 chore: update demo data 2025-10-27 09:20:26 +08:00
Claude 596b894ca0 chore: remove unused syntax
- Removed the wikilink extension from markdown services in test and API service.
- Deleted the DefaultLink and WikiLink components, simplifying link handling.
- Updated ConditionalComponent to remove wikilink checks.
- Adjusted MemoContent to exclude wikilink handling in markdown rendering.
- Refined markdown styles for compact rendering, enhancing readability.
- Added a Markdown Styling Guide to document the new compact styling approach.
2025-10-27 08:31:57 +08:00
Claude 7eec424274 chore: remove references handling from markdown extraction 2025-10-27 00:12:24 +08:00
Claude 6cb96ef65e chore: add missing punctuation in comments 2025-10-26 11:58:34 +08:00
Claude 739fd2cde6 refactor: update markdown parser
- Removed the `nodes` field from the `Memo` interface in `memo_service.ts`.
- Updated the `createBaseMemo` function and the `Memo` message functions to reflect the removal of `nodes`.
- Cleaned up the serialization and deserialization logic accordingly.

chore: remove code-inspector-plugin from Vite configuration

- Deleted the `codeInspectorPlugin` from the Vite configuration in `vite.config.mts`.
- Simplified the plugins array to include only `react` and `tailwindcss`.
2025-10-26 11:28:40 +08:00
Steven bfad0708e2 fix(web): make memoFilterStore reactive by marking fields as observable
Fixes the root cause of non-reactive filtering. The MemoFilterState class
was not marking its fields as observable in MobX, so changes to the filters
array were not being tracked.

Added makeObservable configuration to mark:
- filters and shortcut as observable
- addFilter, removeFilter, removeFiltersByFactor, clearAllFilters, setShortcut as actions

This ensures that when tags are clicked and filters are added/removed,
MobX observer components will re-render and fetch new data.

Related to #5189

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 07:01:27 +08:00
Steven e0b1153269 fix(web): resolve MobX observable reactivity issue in filter computation
Fixes filtering functionality that was broken due to improper use of
useMemo with MobX observables. The issue occurred because useMemo's
dependency array uses reference equality, but MobX observable arrays
are mutated in place (reference doesn't change when items are added/removed).

Changes:
- Remove useMemo from filter computation in Home, UserProfile, and Archived pages
- Calculate filters directly in render since components are already MobX observers
- Fix typo: memoFitler -> memoFilter in Archived.tsx

This ensures filters are recalculated whenever memoFilterStore.filters changes,
making tag clicks and other filter interactions work correctly.

Fixes #5189

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 06:59:13 +08:00
Steven 46ce0bc62e fix(store): correct PostgreSQL placeholder generation in IN clauses
Fixes a regression introduced in v0.25.2 where PostgreSQL IN clause
placeholders were not properly incremented, causing all parameters to
use the same placeholder index (e.g., $1, $1, $1 instead of $1, $2, $3).

This bug affected:
- ListReactions (ContentIDList) - caused "failed to list reactions" errors
- ListAttachments (MemoIDList)
- ListMemos (IDList and UIDList)

The fix combines placeholder generation and argument appending into a
single loop to ensure proper incrementing.

Fixes #5188

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 06:47:06 +08:00
Steven 0c0d2a6294 chore: bump version 2025-10-24 08:15:32 +08:00
Claude 455665a16b docs: enhance README with improved feature descriptions and formatting 2025-10-23 22:25:54 +08:00
boojack f2f2a5159c chore: tweak README to enhance sponsorship and clarity
Updated README to include sponsorship details and enhance clarity on features and benefits.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-23 21:49:15 +08:00
Florian Dewald e4f6345342 feat: generate thumbnails for images stored in S3 and generate thumbnails with a maximum size (#5179) 2025-10-23 21:29:22 +08:00
Claude 16425ed650 feat(web): improve ReactionSelector UX with hover visibility
- Add hover-based visibility for reaction selector in memo cards
- Show reaction selector only on card hover or when popover is open
- Add onOpenChange callback to ReactionSelector for state management
- Reorder action buttons for better visual hierarchy
- Simplify conditional rendering of comment link
2025-10-23 21:20:15 +08:00
Claude 16e0049490 chore: improve layout and spacing in LocationSelector 2025-10-23 20:21:00 +08:00
Claude 7079790d4f feat: add copy content functionality to MemoActionMenu 2025-10-23 20:05:31 +08:00
Claude 686d31b357 feat: enhance attachment store with MobX observables and actions 2025-10-23 19:55:44 +08:00
Claude e35f16306e feat: add id as final tie-breaker in ListMemos 2025-10-23 19:44:41 +08:00
Steven c177871ab4 chore: remove outdated dependabot configuration and agents documentation 2025-10-23 19:16:21 +08:00
Steven f5624fa682 refactor: standardize MobX store architecture with base classes and utilities
Refactored all stores to follow consistent patterns and best practices while keeping MobX:

New Infrastructure:
- Created base-store.ts with StandardState base class and factory functions
- Added store-utils.ts with RequestDeduplicator, StoreError, and OptimisticUpdate helpers
- Added config.ts for MobX configuration and strict mode
- Created comprehensive README.md with architecture guide and examples

Server State Stores (API data):
- attachment.ts: Added request deduplication, error handling, computed properties, delete/clear methods
- workspace.ts: Added Theme type validation, computed memoization, improved initialization
- memo.ts: Enhanced with optimistic updates, request deduplication, structured errors
- user.ts: Fixed temporal coupling, added computed memoization, request deduplication

Client State Stores (UI state):
- view.ts: Added helper methods (toggleSortOrder, setLayout, resetToDefaults), input validation
- memoFilter.ts: Added utility methods (hasFilter, clearAllFilters, removeFiltersByFactor)

Improvements:
- Request deduplication prevents duplicate API calls (all server stores)
- Computed property memoization improves performance
- Structured error handling with error codes
- Optimistic updates for better UX (memo updates)
- Comprehensive JSDoc documentation
- Type-safe APIs with proper exports
- Clear separation between server and client state

All stores now follow consistent patterns for better maintainability and easier onboarding.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 19:13:42 +08:00
dependabot[bot] cce52585c4 chore: bump actions/setup-node from 4 to 5 (#5134)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 22:41:45 +08:00
Steven c09ea5a8ab chore: remove basic filter support from ListAttachments method 2025-10-22 22:41:24 +08:00
Steven 2e31bee1de fix: add missing period to comment per golangci-lint 2025-10-22 22:32:24 +08:00
Steven 9121ddbad9 feat(api): support username lookup in GetUser endpoint
- Update GetUser to accept both numeric IDs and username strings (users/{id} or users/{username})
- Implement CEL filter parsing for username-based lookups
- Update proto documentation to reflect dual lookup capability
- Simplify frontend user store to use GetUser instead of ListUsers filter
- Update ListUsers filter documentation to show current capabilities
2025-10-22 21:48:34 +08:00
Steven 4d4325eba5 chore: update component styles for consistency 2025-10-22 20:21:58 +08:00
Steven b4341dd123 fix(web): make reaction selector responsive with scrolling
- Replace fixed width (max-w-56) with responsive viewport-based width
- Use 90vw on mobile and max-w-md on desktop for better adaptability
- Add vertical scrolling with max-h-64 overflow-y-auto
- Increase grid columns to 8 on medium+ screens for better space utilization
- Ensures all reactions are accessible regardless of quantity

Fixes #5117

Co-authored-by: GitHub Copilot <noreply@github.com>
2025-10-22 19:31:58 +08:00
dependabot[bot] 07b523e4b2 chore: bump actions/setup-go from 5 to 6 (#5135)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 19:23:39 +08:00
dependabot[bot] 7a58250195 chore: bump actions/stale from 9.1.0 to 10.0.0 (#5136)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 19:23:25 +08:00
Simon 290cdf5d4f chore: use input type datetime-local instead of text (#5174) 2025-10-22 09:04:37 +08:00
Steven 2d4361d5fe chore: update memo content formatting and enhance link styling 2025-10-22 08:50:09 +08:00
Steven d8f7a4e739 chore: tweak demo data 2025-10-21 23:41:46 +08:00
Steven 81e852e3b5 chore: update gomark dependency 2025-10-21 23:09:27 +08:00
Steven b19e736f10 chore: tweak demo data 2025-10-20 23:58:49 +08:00
Steven b4ea7d843f feat: enhance memo sorting functionality to support multiple fields 2025-10-20 23:41:58 +08:00
Steven 95de5cc700 refactor: update migration history methods 2025-10-20 23:05:50 +08:00
Johnny bc7decf642 refactor: remove unused constants 2025-10-16 20:40:46 +08:00
Copilot b685ffacdf refactor: memo filter
- Updated memo and reaction filtering logic to use a unified engine for compiling filter expressions into SQL statements.
- Removed redundant filter parsing and conversion code from ListMemoRelations, ListReactions, and ListAttachments methods.
- Introduced IDList and UIDList fields in FindMemo and FindReaction structs to support filtering by multiple IDs.
- Removed old filter test files for reactions and attachments, as the filtering logic has been centralized.
- Updated tests for memo filtering to reflect the new SQL statement compilation approach.
- Ensured that unsupported user filters return an error in ListUsers method.
2025-10-16 09:22:52 +08:00
Steven 228cc6105d chore: update StatCard component for improved icon and count rendering in StatisticsView 2025-10-14 23:15:16 +08:00
Steven 56758f107c chore: refactor ActivityCalendar to use a calendar matrix and improve cell rendering 2025-10-14 21:12:43 +08:00
Steven 5011eb5d70 feat: enhance LocationSelector with improved geolocation handling 2025-10-14 20:23:14 +08:00
Ben Mitchinson 12c4aeeccc feat: lat/long input fields (#5152)
Signed-off-by: Ben Mitchinson <mitchinson.dev@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-14 20:07:01 +08:00
Steven 435cc7b177 feat: implement masonry layout with responsive columns and memo height tracking 2025-10-14 19:46:09 +08:00
Copilot 3245613a88 chore: cleanup components naming 2025-10-12 18:58:37 +08:00
asttool 54e3c13435 refactor: use WaitGroup.Go to simplify code (#5162)
Signed-off-by: asttool <asttool@outlook.com>
2025-10-10 22:28:35 +08:00
Huang Cheng Ting d7e751997d chore: update zh-Hant translation (#5159) 2025-10-09 21:30:55 +08:00
Nic Luckie 20233c7051 feat(web): add accessible ConfirmDialog and migrate confirmations; and Markdown-safe descriptions (#5111)
Signed-off-by: Nic Luckie <nicolasluckie@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-09 00:40:08 +08:00
Johnny 4056a1bada chore: update sponsors 2025-10-08 20:42:15 +08:00
Johnny efe6013c36 fix: add user authentication checks 2025-10-08 20:30:05 +08:00
Claude f6e025d583 feat: implement theme management with system preference detection and early application 2025-10-08 09:51:49 +08:00
dependabot[bot] 3514180721 chore: bump golang.org/x/crypto from 0.41.0 to 0.42.0 (#5141)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:30:37 +08:00
dependabot[bot] 184e975664 chore: bump mobx-react-lite from 4.1.0 to 4.1.1 in /web (#5137)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:40 +08:00
dependabot[bot] 1db86bcd30 chore: bump typescript-eslint from 8.44.0 to 8.45.0 in /web (#5138)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:31 +08:00
dependabot[bot] 0f19713fce chore: bump github.com/aws/aws-sdk-go-v2/config from 1.31.6 to 1.31.12 (#5139)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:25 +08:00
dependabot[bot] ca62b8cd0c chore: bump google.golang.org/protobuf from 1.36.8 to 1.36.9 (#5140)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:17 +08:00
dependabot[bot] cca33af8fd chore: bump google.golang.org/grpc from 1.75.0 to 1.75.1 (#5142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:06 +08:00
dependabot[bot] 763a0d0dea chore: bump golang.org/x/mod from 0.27.0 to 0.28.0 (#5143)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:58 +08:00
dependabot[bot] 498facdfbe chore: bump lucide-react from 0.486.0 to 0.544.0 in /web (#5144)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:48 +08:00
dependabot[bot] 698b08ae8d chore: bump tw-animate-css from 1.3.8 to 1.4.0 in /web (#5145)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:39 +08:00
dependabot[bot] e3890ca9be chore: bump typescript from 5.9.2 to 5.9.3 in /web (#5146)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-07 00:14:11 +08:00
boojack bcfcb1b554 docs: add sponsor section for Warp in README (#5127) 2025-10-01 05:25:42 +08:00
Claude c3a961229e fix: update cell opacity colors to use primary theme instead of destructive 2025-09-29 15:01:46 +08:00
github-actions[bot] 074c580214 chore: bump gomark
- Bump protoc-gen-go version from v1.36.8 to v1.36.9 in multiple generated files.
- Enhance OpenAPI descriptions for various endpoints to improve clarity and readability.
- Fix typo in the description list handling in the markdown service.
- Update HTMLElement component to handle children and self-closing tags correctly.
- Modify types in the markdown service to include children and self-closing properties for HTML elements.
2025-09-28 16:15:55 +08:00
Steven 8d8cc83fd8 chore: tweak assets link 2025-09-26 20:47:54 +08:00
Steven 7ab57f8ed2 chore: upgrade frontend dependencies 2025-09-17 21:51:58 +08:00
Steven 6d1485d168 fix: reset state on dialog close and improve dialog open handling 2025-09-17 21:51:46 +08:00
Steven 5ad2038b1a feat: update gomark dependency and refactor markdown parsing logic 2025-09-17 21:09:30 +08:00
Steven b7f792cbf7 chore: tweak development instructions 2025-09-17 08:48:27 +08:00
Steven f44b0850f4 feat: enhance CodeBlock component with theme-aware syntax highlighting 2025-09-16 19:08:28 +08:00
Steven c3d4f8e9d1 feat: implement user-specific SQL converter for filtering in user service 2025-09-10 21:05:26 +08:00
Steven 383553d3c8 feat: add DOMPurify for sanitizing HTML content in CodeBlock component 2025-09-10 20:52:51 +08:00
Giacomo Cerquone f4e23727bb fix: avoid hiding reaction selector and keep it always shown for mobile (#5079) 2025-09-09 11:35:21 +08:00
Giacomo Cerquone 60123de318 fix: update useEffect dependency to location.key so drawer is closed also when re-navigating to current route (#5077) 2025-09-08 16:26:18 +08:00
dependabot[bot] 3be1b3a1e3 chore: bump @radix-ui/react-checkbox from 1.3.2 to 1.3.3 in /web (#5062)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 22:57:34 +08:00
dependabot[bot] fb8a997248 chore: bump @radix-ui/react-dropdown-menu from 2.1.15 to 2.1.16 in /web (#5063)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 22:57:11 +08:00
dependabot[bot] b2a259d0ff chore: bump react-router-dom from 7.7.1 to 7.8.2 in /web (#5061)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 21:01:44 +08:00
dependabot[bot] b8fe953833 chore: bump @radix-ui/react-select from 2.2.5 to 2.2.6 in /web (#5065)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 21:01:34 +08:00
Steven 5a1af7b240 fix: adjust badge height 2025-09-02 23:18:11 +08:00
dependabot[bot] 0c516c83bd chore: bump nice-grpc-web from 3.3.7 to 3.3.8 in /web (#5056)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:34 +08:00
dependabot[bot] 9c67bbbbba chore: bump tw-animate-css from 1.3.6 to 1.3.7 in /web (#5053)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:23 +08:00
dependabot[bot] 74a44ac3e2 chore: bump actions/checkout from 4 to 5 (#5052)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:08 +08:00
dependabot[bot] fdbcd20ad1 chore: bump react-hot-toast from 2.5.2 to 2.6.0 in /web (#5051)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:55:57 +08:00
dependabot[bot] 56fd9fd7d5 chore: bump @bufbuild/protobuf from 2.6.2 to 2.7.0 in /web (#5057)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:47 +08:00
dependabot[bot] 9c456c3b72 chore: bump i18next from 25.3.2 to 25.4.2 in /web (#5058)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:34 +08:00
dependabot[bot] 1954eeb37b chore: bump github.com/spf13/cobra from 0.0.3 to 1.10.1 (#5059)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:21 +08:00
Johnny ebff15149b fix: use Fprint instead of Fprintf for development mode message 2025-08-31 20:38:07 +08:00
Johnny 3a7538f787 chore: fix linter 2025-08-31 20:29:40 +08:00
Johnny a373673087 chore: go mod tidy 2025-08-31 20:24:18 +08:00
Johnny 7cc2df9254 chore: fix linter 2025-08-31 20:22:32 +08:00
Johnny 3d1c197764 chore: upgrade golangci-lint version to v2.4.0 2025-08-31 19:50:55 +08:00
Johnny 9557150a87 chore: upgrade go version to 1.25 2025-08-31 19:45:41 +08:00
Johnny e427344e82 chore: upgrade dependencies 2025-08-31 13:14:10 +08:00
Johnny 12ab7e9dde chore: tweak docs 2025-08-27 21:35:04 +08:00
Johnny 3ba3f610c9 chore: upgrade typescript-eslint 2025-08-27 19:54:17 +08:00
Johnny 0b4252d1a3 chore: fix linter 2025-08-25 19:52:53 +08:00
Johnny cf29684882 chore: tweak links 2025-08-25 19:51:01 +08:00
Johnny 01c6aca788 chore: update readme with star history section 2025-08-24 22:43:49 +08:00
Xiang Jaywhen 016efe50a2 fix: update the link of Installation Guide (#5024)
Signed-off-by: Xiang Jaywhen <jaywhenx@gmail.com>
2025-08-24 20:24:46 +08:00
varsnotwars e2454a8ae4 chore: add test for ListMemos (#5015) 2025-08-19 21:57:38 +08:00
boojack c5a61ba89e chore: tweak README.md
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-08-18 22:13:58 +08:00
Steven 0d658088dc chore: bump version to 0.25.1 2025-08-18 20:21:30 +08:00
Steven e07e9f2e9f fix: theme selector 2025-08-18 20:08:53 +08:00
varsnotwars fbcdf0fba7 fix update theme not saving (#5012) 2025-08-18 01:39:48 +00:00
Johnny 01d3f2f86c chore: tweak dark theme 2025-08-17 21:11:54 +08:00
Johnny e93f3cbb8b refactor: unify theme and apperance 2025-08-17 11:27:59 +08:00
varsnotwars 4eb5b67baf feat: attachments by id (#5008) 2025-08-15 22:02:29 +08:00
Amazingca a3add85c95 fix: Update SSO login flow to encode redirect_uri (#5006)
Signed-off-by: Amazingca <autumn@amazingca.dev>
2025-08-15 08:45:19 +08:00
varsnotwars a9508b2546 chore: simplify convert reaction (#5001) 2025-08-14 00:06:23 +08:00
Sara Vieira 51d643c780 chore: default type to text/plain (#4993)
Signed-off-by: Sara Vieira <hey@iamsaravieira.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2025-08-13 20:09:02 +08:00
Liu Chao ba7dfb7d98 fix: OpenAPI Parameter Conflict in DeleteMemoTag Endpoint (#4985)
Signed-off-by: ChaoLiu <chaoliu719@gmail.com>
2025-08-13 07:14:18 +08:00
Huang Cheng Ting 5ba81d629c fix: prevent default focus behavior on open and close events in sheet (#4998) 2025-08-13 07:13:45 +08:00
Johnny 76ca258f23 chore: simplify update user settings 2025-08-11 23:19:56 +08:00
Huang Cheng Ting d86756f104 feat: add an option to auto expand subtags in tree mode (#4994) 2025-08-11 23:05:36 +08:00
varsnotwars 3fd305dce7 fix: preferences being overwritten (#4990) 2025-08-11 22:57:52 +08:00
Neo c76ffb0fe4 chore: adds a check to only query reactions when there are actual memos (#4984) 2025-08-10 14:25:35 +08:00
Jason Shawn D' Souza 1dd25634fd fix: Midi files show up as playable (#4991) 2025-08-10 14:23:41 +08:00
Neo 6b507ff600 fix: pinned shortcut comparison operators (#4987) 2025-08-10 14:22:54 +08:00
varsnotwars 9f8921d3b9 fix: preference not being saved (#4980)
Signed-off-by: varsnotwars <varsnotwars@protonmail.com>
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-08-08 22:50:46 +08:00
Sara Vieira 1f1add1a48 fix: add mime type check for file types (#4981) 2025-08-08 20:39:16 +08:00
Tobias Waslowski 15c146cfc5 feat(editor): create text-based autocompleting commands (#4971) 2025-08-08 18:55:59 +08:00
varsnotwars f4bdfa28a0 feat: filter/method for reactions by content_id (#4969) 2025-08-08 00:00:51 +08:00
Brandon Sprague 931ddb7c1c chore: add a new LOG_STACKTRACES option (#4973) 2025-08-07 23:56:21 +08:00
Johnny 8576001c83 fix: nl.json
Signed-off-by: Johnny <yourselfhosted@gmail.com>
2025-08-07 14:43:35 +08:00
Stephan Paternotte 1043fc8fba chore: update nl.json (#4974)
Signed-off-by: Stephan Paternotte <Stephan-P@users.noreply.github.com>
2025-08-07 14:40:53 +08:00
Colin Holzman 8319516d1a fix: boolean filters (#4966) 2025-08-06 21:06:15 +08:00
johnnyjoy 66b4f583a5 fix: linter 2025-08-06 20:22:20 +08:00
aarohee-he 0f2390a0b7 feat: add tooltips to editor buttons (#4934)
Co-authored-by: Anthony Cooper <antcoop096@gmail.com>
Co-authored-by: aarohee-he <aarohee-he@users.noreply.github.com>
Co-authored-by: Mishti Gala <mishtigala19@gmail.com>
2025-08-06 10:15:06 +08:00
boojack 13957472eb chore: merge visibility selector into save button
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-08-06 00:03:59 +08:00
johnnyjoy a5e441b622 chore: tweak dark mdoe styles 2025-08-05 21:07:59 +08:00
Liu Chao 3427ae75ba fix: resolve gRPC Gateway connection issue when server address is empty (#4968)
Signed-off-by: ChaoLiu <chaoliu719@gmail.com>
2025-08-05 19:42:20 +08:00
johnnyjoy 506b477d50 fix: get user by username 2025-08-04 19:56:12 +08:00
varsnotwars fa2fa8a5d7 refactor: remove call to db for parent memo name (#4947) 2025-08-04 19:39:52 +08:00
Huang Cheng Ting 896a3dccf2 chore: update zh-Hant translation (#4962) 2025-08-04 19:38:58 +08:00
johnnyjoy 34fb3f1514 chore: fix linter 2025-08-03 19:55:04 +08:00
Colin Holzman aae7ec8d1f fix: calendar filter (#4942) 2025-08-03 19:11:09 +08:00
Maximilian Krauß 4d6042e35f fix(tags): ensure JSON array elements are properly formatted in SQL queries (#4944) 2025-08-03 19:10:59 +08:00
XIN_____ 9c60165ba1 chore: update zh-Hans.json (#4940) 2025-08-03 19:10:49 +08:00
Andrea Marchetta 71464779dd fix: change itemCount into an Int64 (#4945) 2025-08-03 19:07:17 +08:00
dependabot[bot] 07e270564a chore: bump golang.org/x/net from 0.40.0 to 0.42.0 (#4948)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:49 +08:00
dependabot[bot] 94b58f0691 chore: bump google.golang.org/grpc from 1.72.2 to 1.74.2 (#4949)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:40 +08:00
dependabot[bot] 5a7693c90a chore: bump github.com/google/cel-go from 0.25.0 to 0.26.0 (#4951)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:30 +08:00
dependabot[bot] 11685c1f4d chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.82 to 1.18.2 (#4952)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:22 +08:00
dependabot[bot] a5711e893a chore: bump code-inspector-plugin from 0.18.3 to 1.0.4 in /web (#4954)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:17 +08:00
johnnyjoy b2a2151eaf chore: bump frontend dependencies 2025-08-03 18:17:21 +08:00
dependabot[bot] 9b06275f4c chore: bump vite from 7.0.1 to 7.0.6 in /web (#4957)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 12:46:05 +08:00
Colin Holzman 671f4bf88b fix: shortcuts list (#4936) 2025-07-31 19:52:13 +08:00
XIN_____ 79c7fcc8b6 chore: update zh-Hans.json (#4933) 2025-07-31 19:50:29 +08:00
Colin Holzman 6005d0f3f7 chore: use MEMOS_INSTANCE_URL for "Copy Link" (#4930) 2025-07-30 18:57:39 +08:00
Steven 1fcafd807e chore: enable memo comments by default 2025-07-29 22:31:18 +08:00
Johnny 5074268f4f fix: action styles in memo editor 2025-07-29 22:10:31 +08:00
Maximilian Krauß e724a7ef72 fix: disable profiler in production mode (#4925) 2025-07-29 19:22:41 +08:00
johnnyjoy 9971cbeed4 chore: fix linter 2025-07-29 19:20:59 +08:00
Johnny 8f51791da8 chore: update user setting definition 2025-07-29 09:21:51 +08:00
Johnny 3b8bfe72ea fix: linter 2025-07-27 23:35:01 +08:00
johnnyjoy c5d497a1f0 chore: update user settings 2025-07-27 23:12:42 +08:00
johnnyjoy 3f56ce47d2 chore: update definition of workspace setting 2025-07-27 15:50:09 +08:00
Anthony Cooper 53d3978507 chore: add hyperlink for 'releases page' (#4914) 2025-07-24 12:51:02 +08:00
Steven c5d2d15278 chore: fix eslint 2025-07-23 23:41:59 +08:00
Steven f78b277462 chore: simplify add memo relation 2025-07-23 23:34:30 +08:00
johnnyjoy 9b5b7b1ea2 Merge branch 'main' of https://github.com/usememos/memos 2025-07-23 22:22:15 +08:00
johnnyjoy c5767bf9d6 fix: eslint 2025-07-23 22:22:12 +08:00
Maximilian Krauß 2c7eb23343 feat(inbox): handles errors while fetching and adds possibility to delete items (#4908) 2025-07-23 14:21:26 +00:00
johnnyjoy db63b1949a chore: fix creator id format 2025-07-23 22:18:47 +08:00
johnnyjoy 9ea2f9f686 fix: linter 2025-07-23 22:13:48 +08:00
johnnyjoy ed23cbc011 refactor: memo filter 2025-07-23 22:10:16 +08:00
Steven 1a75d19a89 fix: memo filter for sqlite 2025-07-22 23:39:52 +08:00
Steven ac386c218d fix: workspace setting keys 2025-07-22 22:59:54 +08:00
Steven c133f5528a fix: workspace setting keys in frontend 2025-07-22 22:45:47 +08:00
johnnyjoy 6e45e9f8b6 refactor: deprecate old filter 2025-07-22 21:25:57 +08:00
johnnyjoy 7098721617 chore: fix linter 2025-07-22 21:15:23 +08:00
johnnyjoy e24f92b719 fix: tests 2025-07-22 21:13:24 +08:00
johnnyjoy b55904a428 feat: support more filter factors 2025-07-22 19:18:08 +08:00
Johnny 1a3fc4d874 fix: media width 2025-07-21 23:55:28 +08:00
johnnyjoy 6d9770b9c8 chore: move filter to filters 2025-07-21 21:52:00 +08:00
johnnyjoy 7481fe10bf chore: remove order by pinned 2025-07-21 21:45:10 +08:00
Johnny 71181b1640 chore: update openapi version 2025-07-20 12:02:16 +08:00
Huang Cheng Ting f675324994 chore: update zh-Hant translation (#4895) 2025-07-18 19:27:03 +08:00
Steven d7ced7b738 fix: code block style in dark mode 2025-07-18 19:25:29 +08:00
Johnny 74769b3332 fix: user state 2025-07-17 22:36:28 +08:00
Johnny e3735d2de3 fix: storage setting 2025-07-17 22:02:40 +08:00
Johnny f09897e4b6 fix: dialog state 2025-07-17 21:58:00 +08:00
Huang Cheng Ting 6119a4b965 chore: update zh-Hant translation (#4889) 2025-07-17 21:24:29 +08:00
Maximilian Krauß c4baba8527 fix(syntax-highlighting): adds missing CSS imports to CodeBlock.tsx (#4890) 2025-07-17 21:23:42 +08:00
Anthony Cooper 1f88e3e2d2 chore: Docker hyperlink in README (#4887) 2025-07-17 12:12:48 +08:00
Johnny 40130350c5 fix: args offset for postgres 2025-07-17 00:05:07 +08:00
Steven 834f92f67c chore: fix linter 2025-07-16 22:24:50 +08:00
Steven 0398df1d21 chore: update migrator comments 2025-07-16 21:59:37 +08:00
Jovane Castro a8db132110 chore(i18n): update hindi translation (#4858) 2025-07-16 21:46:18 +08:00
XIN_____ 84eacebfbb chore: update zh text i18n (#4844) 2025-07-16 21:46:09 +08:00
Jovane Castro 72b5186a56 chore(i18n): update croatian translation (#4859) 2025-07-16 21:45:58 +08:00
Steven 54e6ca37a2 chore: tweak props definition 2025-07-15 23:51:28 +08:00
Steven 8df0dea304 chore: remove fixed theme color 2025-07-15 23:26:07 +08:00
Jovane Castro 7683b26658 chore(i18n): update farsi translation (#4855) 2025-07-15 23:21:16 +08:00
Jovane Castro 4066af989c chore(i18n): update spanish translation (#4854) 2025-07-15 23:20:52 +08:00
Jovane Castro 8ef13468c7 chore(i18n): update hungarian translation (#4860) 2025-07-15 23:20:15 +08:00
Jovane Castro 2d4b5a1044 chore(i18n): update german translation (#4853) 2025-07-15 19:25:33 +08:00
Jovane Castro a21112427b chore(i18n): update french translation (#4856) 2025-07-15 19:25:21 +08:00
Jovane Castro 5a53f7178c chore(i18n): update italian translation (#4861) 2025-07-15 19:25:10 +08:00
Jovane Castro 74d35f7e33 chore(i18n): update japanese translation (#4862) 2025-07-15 19:24:59 +08:00
Jovane Castro 163038d5e0 chore(i18n): update georgian translation (#4863) 2025-07-15 19:24:49 +08:00
Jovane Castro af60f81f96 chore(i18n): update korean translation (#4864) 2025-07-15 18:15:25 +08:00
Jovane Castro c79b114972 chore(i18n): update marathi translation (#4865) 2025-07-15 18:14:41 +08:00
Jovane Castro a95104a0d4 chore(i18n): update norwegian translation (#4866) 2025-07-15 18:14:30 +08:00
Jovane Castro ff38347272 chore(i18n): update dutch translation (#4867) 2025-07-15 18:14:19 +08:00
Jovane Castro 4659b932d0 chore(i18n): update polish translation (#4868) 2025-07-15 18:14:09 +08:00
Jovane Castro d9e13baa37 chore(i18n): update portuguese-Brazil translation (#4869) 2025-07-15 18:13:58 +08:00
Jovane Castro 4551a0c52d chore(i18n): update portuguese translation (#4870) 2025-07-15 18:13:40 +08:00
Jovane Castro bd1f675051 chore(i18n): update slovenian translation (#4871) 2025-07-15 18:13:19 +08:00
Jovane Castro b4046f339e chore(i18n): update swedish translation (#4872) 2025-07-15 18:12:56 +08:00
Jovane Castro d9d63bf174 chore(i18n): update thai translation (#4873) 2025-07-14 23:26:17 +08:00
Jovane Castro d2dcf26104 chore(i18n): update turkish translation (#4874) 2025-07-14 23:26:06 +08:00
Johnny 1c408ff5a9 chore: remove unused main file 2025-07-14 23:18:24 +08:00
Jovane Castro 78387bec83 chore(i18n): update ukrainian translation (#4875) 2025-07-14 23:14:06 +08:00
Dedy F. Setyawan def61a8877 fix(i18n): Improve Indonesian translation (#4849) 2025-07-12 21:29:51 +08:00
Anthony Cooper 02641ef10a chore: hyperlinks in README Prerequisites (#4848) 2025-07-12 21:29:34 +08:00
unuunn 08883b58a7 updated Russian translation (#4840) 2025-07-10 07:38:56 +08:00
unuunn 9eafb9bc26 feat: highlight pinned memos (#4843) 2025-07-10 07:38:33 +08:00
unuunn 452f47c4b9 set HasCode only for CodeBlock (#4842) 2025-07-10 07:37:33 +08:00
Steven 29b683d5db fix: dialog styles 2025-07-09 21:48:02 +08:00
Steven e8862e3ca9 chore: update claude.md 2025-07-09 21:13:54 +08:00
Amar Singh Rathour b779dd2e54 fix: correct avatar URL generation to resolve 404 errors (#4839) 2025-07-09 21:05:52 +08:00
Dedy F. Setyawan e803d7bc0f feat(i18n): update Indonesian (id) translations (#4838) 2025-07-09 18:08:36 +08:00
unuunn 8732575ea4 fix: dayjs - ISO 8601 compatible DATE_TIME_FORMAT (#4829) 2025-07-09 00:16:10 +08:00
XIN_____ 0b1b471ee4 chore: update zh-Hant.json (#4833) 2025-07-08 23:03:35 +08:00
Steven 3ac4a03229 chore: update i18n 2025-07-08 20:33:44 +08:00
Steven c1708df7a2 chore: use select/dropdown instead of popover 2025-07-08 20:25:56 +08:00
Jovane Castro d32924ec48 chore: update i18n for Arabic locale (#4825) 2025-07-08 19:57:50 +08:00
Jovane Castro 1e582baf1c chore: update i18n for Catalan locale (#4826) 2025-07-08 19:57:14 +08:00
Jovane Castro eeb18e5deb chore: update i18n for Czech locale (#4827) 2025-07-08 19:57:08 +08:00
Kevin b074aefc34 chore: enhance site.webmanifest in firefox (#4828)
Signed-off-by: Kevin <16837578+KevinStaude@users.noreply.github.com>
2025-07-08 19:56:46 +08:00
Steven 533591af2b chore: theme in user setting 2025-07-08 19:50:04 +08:00
Johnny f907619752 chore: move frontend store 2025-07-07 22:44:08 +08:00
Johnny 12fdf5292d chore: tweak form style 2025-07-07 22:33:49 +08:00
johnnyjoy 239671eb87 chore: tweak tag style 2025-07-07 22:20:17 +08:00
Johnny e55ed8a9c7 chore: new theme whitewall 2025-07-07 20:13:55 +08:00
Johnny 1b3083b216 feat: themes (#4824) 2025-07-07 20:13:22 +08:00
Johnny 3426a791b6 chore: update tag styles 2025-07-07 08:58:09 +08:00
Johnny fb13d2e63d chore: tweak colors 2025-07-07 08:46:53 +08:00
Johnny d8d88c2505 fix: creator view 2025-07-06 22:51:28 +08:00
Johnny f2e27c16a1 chore: tweak colors 2025-07-06 22:26:54 +08:00
Johnny 240d89fbca feat: migrate dialogs 2025-07-06 22:01:55 +08:00
Jovane Castro f70138535c chore: update i18n for pt-BR text (#4819) 2025-07-06 13:59:50 +08:00
Johnny 35928ce5ba chore: unify colors 2025-07-06 13:55:08 +08:00
Jovane Castro 2e474d37fd chore: update i18n for pt-BR locale (#4817) 2025-07-05 19:32:57 +08:00
dependabot[bot] d60aee7823 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.80.0 to 1.82.0 (#4806)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-05 19:32:25 +08:00
Johnny 41fdc7a484 chore: fix frontend linter 2025-07-05 11:44:01 +08:00
Johnny a3de61a141 chore: fix dark mode 2025-07-05 11:40:49 +08:00
XIN_____ cf16795a98 chore: update zh text (#4797) 2025-07-05 11:28:30 +08:00
dependabot[bot] 3c512939a8 chore: bump github.com/go-sql-driver/mysql from 1.9.2 to 1.9.3 (#4807)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-05 11:27:57 +08:00
Johnny db4b1f5fde chore: tweak styles 2025-07-05 11:26:59 +08:00
Johnny 91be2f68d1 feat: variant colors (#4816) 2025-07-04 23:03:13 +08:00
dependabot[bot] b164c15976 chore: bump @types/node from 22.15.34 to 24.0.8 in /web (#4802)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:55:35 +08:00
dependabot[bot] f8fa0985fb chore: bump tailwind-merge from 2.6.0 to 3.3.1 in /web (#4801)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:39:25 +08:00
dependabot[bot] 1e09bf9a4f chore: bump vite from 6.3.5 to 7.0.0 in /web (#4805)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:39:10 +08:00
dependabot[bot] 17cd19588d chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.77 to 1.17.82 (#4808)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:34:19 +08:00
dependabot[bot] 49004f230f chore: bump golang.org/x/mod from 0.24.0 to 0.25.0 (#4809)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:34:11 +08:00
Steven fda19c2d73 chore: update 2025-07-03 22:33:31 +08:00
Steven 046c6c83e1 chore: fix linter formats 2025-07-03 22:28:45 +08:00
Copilot e3a2dadb4b fix: tag count regression - remove double increment causing off-by-one error (#4800)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2025-07-02 20:17:19 +08:00
Steven 0df3171b64 chore: remove command 2025-07-01 20:14:42 +08:00
boojack 0cabdbe020 chore: rename Popover.tsx to popover.tsx
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-07-01 19:43:46 +08:00
Steven 49766ed920 chore: update frontend instructions 2025-07-01 19:42:25 +08:00
Johnny 493832aeb4 refactor: unify components 2025-07-01 19:29:48 +08:00
Steven 50a41a39a6 chore: tweak instructions 2025-06-30 19:49:18 +08:00
XIN_____ 98d1238674 chore: update i18n text for zh-hans (#4790) 2025-06-28 16:06:32 +08:00
Steven c18d6927ba chore: update user session table 2025-06-27 00:00:06 +08:00
johnnyjoy 1fffc41f79 feat: sliding expiration for user sessions 2025-06-26 23:03:28 +08:00
XIN_____ e93d695aa8 chore: update i18n for zh text (#4785)
* Update zh-Hans.json

* Update zh-Hant.json

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>
2025-06-26 08:44:32 +08:00
Johnny 3e24f8cf62 fix: seed data 2025-06-25 10:07:24 +08:00
Steven 42d1650c6d chore: tweak auth service 2025-06-24 23:31:37 +08:00
Steven 6e1b01cb68 chore: bump version 2025-06-24 23:06:57 +08:00
XIN_____ 3a7995c733 chore: update i18n text for zh-hans and zh-hant (#4784)
chore: update i18n text for zh-hant
2025-06-24 21:59:03 +08:00
johnnyjoy 976bd332fe chore: fix linter 2025-06-24 21:55:27 +08:00
johnnyjoy d6a75bba4c refactor: webhook service 2025-06-24 21:28:21 +08:00
jinjingroad 03399a6007 refactor: use the built-in max/min to simplify the code (#4781)
Signed-off-by: jinjingroad <jinjingroad@sina.com>
2025-06-24 07:12:02 +08:00
Johnny e6e460493c refactor: general user setting 2025-06-23 23:23:57 +08:00
Johnny 9b15936873 refactor: clean unused fields 2025-06-23 22:55:14 +08:00
Johnny 778a5eb184 refactor: memo filter 2025-06-23 22:38:44 +08:00
Johnny 52a5ca2ef4 chore: update get attachment binary 2025-06-23 21:20:59 +08:00
Steven 697e54758d fix: frontend linter 2025-06-23 21:20:37 +08:00
Steven 83febf9928 chore: clean resource definition 2025-06-23 21:08:25 +08:00
Steven 5821bb7a65 chore: update auth service 2025-06-23 20:31:18 +08:00
Steven 59eae4465a chore: update user session section 2025-06-23 20:12:29 +08:00
Johnny b8a37c7229 chore: fix linter 2025-06-23 09:27:06 +08:00
XIN_____ bbd984a754 chore: update i18n for zh (#4780)
* feat: add i18n text for zh

* feat: add i18n text for zh-hant
2025-06-23 09:14:49 +08:00
Johnny 4e3a4e36f6 feat: implement user sessions 2025-06-23 09:13:51 +08:00
Johnny 6e4d1d9100 fix: auth context 2025-06-22 22:58:00 +08:00
johnnyjoy 45df653f37 fix: navigation overflow style 2025-06-22 18:49:12 +08:00
Johnny a2bfa82a88 fix: linter 2025-06-22 14:13:27 +08:00
Johnny 77b7fc4441 feat: implement user session 2025-06-22 12:46:13 +08:00
Johnny 741fe35c2a refactor: rename session methods in auth service 2025-06-21 00:00:58 +08:00
Johnny cb96d4e76d fix: embedded attachment 2025-06-18 23:10:41 +08:00
Steven df52bf5e63 fix: tag count 2025-06-18 22:49:03 +08:00
Steven 35df62a96c chore: remove duplicated prefix from enums 2025-06-18 22:40:54 +08:00
XIN_____ d27639f147 chore: update i18n zh-Hans and zh-Hant (#4778)
* Update zh-Hans.json

* Update zh-Hant.json

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>
2025-06-18 20:46:37 +08:00
Steven d71fd2f84a refactor: auth service 2025-06-18 20:25:46 +08:00
Steven 9972a77d9e refactor: memo service 2025-06-18 19:58:38 +08:00
Steven 91c2a4cef9 refactor: inbox service 2025-06-18 19:06:09 +08:00
Steven a4920d464b refactor: attachment service part2 2025-06-18 00:09:19 +08:00
Steven bb5809cae4 refactor: attachment service 2025-06-17 22:15:19 +08:00
Steven 174b1a0361 chore: fix linter 2025-06-17 21:04:28 +08:00
Steven 760c164328 chore: add server tests 2025-06-17 20:56:10 +08:00
Steven f6e5da4499 refator: activity service 2025-06-17 09:00:03 +08:00
Steven 4a20b529df chore: add CLAUDE.md 2025-06-17 08:51:43 +08:00
Steven 8e8e246ab2 chore: add server tests 2025-06-17 00:29:42 +08:00
Steven dac059a7f7 refactor: identity provider service 2025-06-16 23:56:28 +08:00
Steven 8d8e9b3b30 refactor: shortcut service 2025-06-16 23:10:50 +08:00
Steven 1ea4cc453c refactor: workspace setting service 2025-06-16 22:51:26 +08:00
Steven da906c665c chore: tweak workspace service 2025-06-16 22:20:10 +08:00
Steven 3b0c87591f refactor: webhook service 2025-06-16 22:10:43 +08:00
Steven c9ab03e1a0 refactor: user service 2025-06-16 21:49:38 +08:00
Steven 330282d8b2 chore: tweak styles 2025-06-16 20:48:08 +08:00
Johnny f467264e7d chore: remove memopayload runonce 2025-06-16 20:24:57 +08:00
Johnny 38b6c3afb9 chore: fix linter 2025-06-15 10:27:24 +08:00
Johnny 3fd29f6493 refactor: schema migrator 2025-06-15 10:23:18 +08:00
XIN_____ d386b83b7b chore: update i18n text for zh (#4771)
* feat: add i18n text

* feat: add i18n text for zh
2025-06-12 23:09:04 +08:00
Steven c9c07a599c chore: unify action names 2025-06-11 23:39:29 +08:00
Steven efc0dc9aea chore: update trim in Autocomplete 2025-06-11 23:21:48 +08:00
Johnny acb71dfb69 chore: tweak button styles 2025-06-10 22:51:42 +08:00
KidLoveToPlay df8d1d4f3d fix: trim queryText and split by regex (#4766) 2025-06-09 22:13:39 +08:00
Johnny f2a01d9ccb chore: use popover instead of dropdown/menu 2025-06-08 23:21:23 +08:00
Johnny 522da2a114 fix: border color 2025-06-08 00:39:51 +08:00
Johnny f5c64849d2 chore: upgrade tailwindcss to v4 2025-06-07 10:15:12 +08:00
Ezmana a50253d311 chore: add missing lines and French translations (#4761)
Adding missing lines and translations
2025-06-06 19:18:48 +08:00
Steven add099b89d chore: update rollup options 2025-06-05 23:09:15 +08:00
Steven 786c6f672e chore: remove prevent default for enter keydown 2025-06-05 23:08:55 +08:00
boojack cc36422e43 chore: tweak README.md 2025-06-05 09:43:41 +08:00
Steven fe71b01f2d chore: polish readme 2025-06-04 23:10:31 +08:00
johnnyjoy c84dcddbf6 chore: always show visibility label 2025-06-04 22:05:51 +08:00
johnnyjoy 8d9396247b fix: external newline 2025-06-04 21:28:58 +08:00
Maya Doshi efb8e7ab0c fix: broken resource urls in RSS feed (#4753)
fix: resource url generation in rss feed
2025-06-04 09:06:34 +08:00
johnnyjoy 94d1e20570 chore: update date time format 2025-06-03 21:22:14 +08:00
Steven 6d319900d6 fix: date format 2025-06-03 09:24:38 +08:00
Johnny b942643785 chore: tweak seed data 2025-06-02 20:06:45 +08:00
Lincoln Nogueira 44e710ce4a fix: downgrade modernc.org/libc to v1.65.7 (#4745)
`modernc.org/libc` version on go.mod must match whatever is on `modernc.org/sqlite`'s [go.mod](https://gitlab.com/cznic/sqlite/-/blob/v1.37.1/go.mod#L9) file to prevent sqlite-related issues.

See:
  - <https://pkg.go.dev/modernc.org/sqlite#hdr-Fragile_modernc_org_libc_dependency>
  - <https://gitlab.com/cznic/sqlite/-/issues/177>
2025-06-02 18:19:57 +08:00
Johnny d20362e722 chore: tweak stat card 2025-06-02 10:20:11 +08:00
Johnny 1594c1ce3e chore: bump version 2025-06-02 09:39:57 +08:00
Johnny 3343dc73f7 chore: update navigator 2025-06-02 09:39:50 +08:00
Johnny 663e56747f chore: replace switch kit 2025-06-02 01:01:29 +08:00
Johnny ff0f275431 chore: fix golangci-lint version 2025-06-02 00:34:45 +08:00
dependabot[bot] 136c1d7aa6 chore: bump golangci/golangci-lint-action from 7 to 8 (#4744)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 7 to 8.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v7...v8)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 00:32:53 +08:00
dependabot[bot] 7c9215b513 chore: bump i18next from 24.2.3 to 25.2.1 in /web (#4742)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.3 to 25.2.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.3...v25.2.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 25.2.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 00:32:27 +08:00
Johnny d4425a6aa1 chore: upgrade dependencies 2025-06-02 00:27:35 +08:00
Johnny e6fe088ac0 chore: fix missing observer 2025-06-01 09:22:33 +08:00
Johnny fd99e10962 chore: tweak sidebar 2025-06-01 09:13:44 +08:00
Johnny 2595e32f83 chore: simplify date editor 2025-05-31 11:14:47 +08:00
Johnny 673026ffa1 chore: update statistics view 2025-05-31 09:43:24 +08:00
Johnny 376b25a69c chore: fix visibility selector style (#4733) 2025-05-31 09:15:28 +08:00
Steven f1b365f928 refactor: clean packages 2025-05-29 21:44:43 +08:00
Johnny 2bde296217 chore: add demo deployment to Render action 2025-05-29 08:38:01 +08:00
Johnny ea4e7a1606 refactor: memo editor (#4730) 2025-05-29 07:46:40 +08:00
Maximilian Krauß 77d3853f73 fix: inherits memo visibility for default comment visibility (#4728) 2025-05-28 22:18:41 +08:00
Steven a317f9e653 fix: linter 2025-05-28 21:21:27 +08:00
Steven de3e55c2e6 feat: support now() time functions 2025-05-28 21:18:49 +08:00
Steven f5ecb66fb8 feat: implement height-based masonry view 2025-05-28 08:27:15 +08:00
Steven 8520e30721 fix: handle type assertion safely 2025-05-27 23:44:39 +08:00
Steven ef6f80d925 chore: fix linter 2025-05-27 23:22:32 +08:00
Steven 81ae42518e chore: fix linter 2025-05-27 22:49:56 +08:00
Maximilian Krauß eca91d5c0c feat(rss): use server title and description for RSS feed, if configured (#4717) 2025-05-27 22:10:23 +08:00
Steven ad2c5f0d05 refactor: store cache 2025-05-27 22:06:41 +08:00
Steven c23aebd648 refactor: memo filter store 2025-05-27 21:14:18 +08:00
Steven f12d7ae8bc chore: add asynchronous webhook dispatch 2025-05-27 20:01:04 +08:00
Jonathan Fok kan 7c05a9b997 fix(editor): prevent race condition and ensure correct list continuation on Enter (#4716)
* fix(editor): Prevent race condition and ensure correct list continuation on Enter

_

* fix: always insert newline after preventing default Enter key behavior
2025-05-27 19:57:33 +08:00
Johnny d76f988bb5 fix: edit for comment 2025-05-27 08:38:14 +08:00
Steven 785c250f3c refactor: migrate memo store 2025-05-27 08:26:13 +08:00
Steven dcd68bc5f4 refactor: migrate resource store to v2 2025-05-27 07:55:00 +08:00
Steven 46900f9807 refactor: move store prefixes to common module 2025-05-27 07:49:46 +08:00
Steven 46be6b0ff6 fix: missing service handler 2025-05-26 23:22:10 +08:00
Steven b89d8f5342 feat: implement hasTaskList filter 2025-05-26 22:37:59 +08:00
Steven cbf5687dd9 chore: remove unused action 2025-05-26 21:50:36 +08:00
eya46 4924b23884 fix: state mismatch in Storage and System pages (#4719)
* fix: sync storage setting state

* fix: sync customProfile state
2025-05-26 21:50:10 +08:00
Steven 64b27d5a4e refactor: shortcut service 2025-05-26 21:45:14 +08:00
dabeeduu 6964c1df05 fix: make the save button disabled after a successful update (#4721)
* fix: make the save button disabled after a successful update

* fix: fixing formatting error

---------

Co-authored-by: didi <didi@localhost.localdomain>
2025-05-26 14:50:13 +08:00
Brian c6e6b7b93b feat: add infinite scrolling for memos (#4715)
* feat(WIP): add prop-driven infinite scroll

* feat(WIP): add global toggle for infinite scrolling under settings

* feat: integrate newly added scroll-mode selection state with backend for persists across refreshes

* fix: default to infinite scrolling over load more button & remove redundant setting option

* fix: rectify linting issues

* Update web/src/components/PagedMemoList/PagedMemoList.tsx

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-05-25 23:12:47 +08:00
Steven 46d5307d7f fix: prevent XSS for specific content types 2025-05-22 00:05:33 +08:00
Dimitris Zervas c2528c57f0 feat: automatically add a new table row in the editor when pressing enter (#4706)
Automatically add a new table row in the editor when pressing enter
2025-05-21 20:11:53 +08:00
Steven 72babbb393 fix: dark mode of highlight.js 2025-05-20 23:58:22 +08:00
johnnyjoy f9c0621c15 refactor: root layout 2025-05-19 22:15:11 +08:00
johnnyjoy ee99afd7a4 chore: enable location by default 2025-05-19 21:25:51 +08:00
Johnny d4ebf293f3 chore: fix format 2025-05-19 10:03:05 +08:00
Jake Howard 0440888571 chore: hide "or" when password auth disabled (#4699)
This makes the UI cleaner, instead only showing the "Sign in with ..." buttons.
2025-05-19 09:59:52 +08:00
Steven 606924b4c9 chore: unify form styles 2025-05-15 22:15:01 +08:00
johnnyjoy f9e07a2245 feat: support update user's role 2025-05-15 19:36:15 +08:00
Simon ead2d70082 fix: remove duplicated “Enable” in settings label (#4692)
remove duplicated “Enable” in settings label
2025-05-15 15:08:50 +08:00
Steven 1f79ee575b fix: create user with avatar url for sqlite 2025-05-14 23:45:02 +08:00
johnnyjoy 21935abe3f chore: update canary build action 2025-05-14 22:24:54 +08:00
johnnyjoy ca79990679 refactor: merge sign in requests 2025-05-14 22:13:52 +08:00
johnnyjoy a0f68895ab chore: add more logs for oauth2 2025-05-14 20:38:14 +08:00
johnnyjoy 733f16816b chore: bump mui 2025-05-13 23:28:15 +08:00
johnnyjoy 43d176f272 fix: idp config convert 2025-05-13 20:40:54 +08:00
johnnyjoy 966a108d52 chore: check signin with sso 2025-05-13 20:36:00 +08:00
Steven fa1ad7dc72 chore: update list padding 2025-05-12 22:39:25 +08:00
啥也不会的帆 f6054b6138 fix: preview image window proportion error (#4689) 2025-05-12 21:32:01 +08:00
Johnny 87798801fc fix: list styles 2025-05-12 09:09:09 +08:00
johnnyjoy 446447a20c chore: update stable build action 2025-05-11 18:04:15 +08:00
Pavel Stržínek 070b392942 chore: Czech locale update (#4685)
* cs locale updated

* cs locale update
2025-05-11 17:45:32 +08:00
Johnny 9c7899781f chore: update alt text of deepwiki badge 2025-05-09 14:58:58 +08:00
johnnyjoy cd5abd9e60 chore: update nsfw description 2025-05-08 21:18:46 +08:00
johnnyjoy ccfa9983e9 fix: user avatar url 2025-05-08 20:28:00 +08:00
mousemin 30f37f6a05 feat: enhance site.webmanifest in chrome (#4676)
Update site.webmanifest
2025-05-07 22:47:55 +08:00
Sergey Gorbunov e23ade1f8b feat: support listening on a UNIX socket (#4654) 2025-05-07 22:12:05 +08:00
johnnyjoy 2a92baf52c fix: filter args of postgres 2025-05-06 21:19:13 +08:00
Johnny 1328e0b861 chore: remove issue-translator 2025-05-03 16:16:01 +08:00
dependabot[bot] c3273f8f97 chore: bump @vitejs/plugin-legacy from 6.0.2 to 6.1.1 in /web (#4661)
Bumps [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/HEAD/packages/plugin-legacy) from 6.0.2 to 6.1.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/plugin-legacy/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.1.1/packages/plugin-legacy)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-legacy"
  dependency-version: 6.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:15:21 +08:00
dependabot[bot] 24650140b2 chore: bump @types/node from 22.13.10 to 22.15.3 in /web (#4660)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.10 to 22.15.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:10:17 +08:00
dependabot[bot] f6b5b26cda chore: bump eslint from 9.23.0 to 9.25.1 in /web (#4663)
Bumps [eslint](https://github.com/eslint/eslint) from 9.23.0 to 9.25.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.23.0...v9.25.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.25.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:10:08 +08:00
dependabot[bot] 0ab7082c7c chore: bump mobx from 6.13.6 to 6.13.7 in /web (#4662)
Bumps [mobx](https://github.com/mobxjs/mobx) from 6.13.6 to 6.13.7.
- [Release notes](https://github.com/mobxjs/mobx/releases)
- [Commits](https://github.com/mobxjs/mobx/compare/mobx@6.13.6...mobx@6.13.7)

---
updated-dependencies:
- dependency-name: mobx
  dependency-version: 6.13.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:27:06 +08:00
dependabot[bot] 8550176cfa chore: bump golang.org/x/crypto from 0.35.0 to 0.37.0 (#4665)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.35.0 to 0.37.0.
- [Commits](https://github.com/golang/crypto/compare/v0.35.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:26:28 +08:00
dependabot[bot] fdcef4d3a7 chore: bump golang.org/x/net from 0.35.0 to 0.39.0 (#4666)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.35.0 to 0.39.0.
- [Commits](https://github.com/golang/net/compare/v0.35.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:26:19 +08:00
dependabot[bot] a266c4c6a5 chore: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 (#4667)
Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.1 to 5.2.2.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.1...v5.2.2)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-version: 5.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:17:07 +08:00
dependabot[bot] 0c692c48af chore: bump modernc.org/sqlite from 1.36.0 to 1.37.0 (#4668)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.36.0 to 1.37.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.36.0...v1.37.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:16:59 +08:00
dependabot[bot] b5f68576ff chore: bump golang.org/x/mod from 0.23.0 to 0.24.0 (#4669)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/mod/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:16:51 +08:00
boojack 75f5c4c0b2 chore: add deepwiki badge 2025-04-28 13:51:41 +08:00
João Tiago a46301fa77 feat: support child tags in NSFW blur feature (#4640)
* fix: add support for child nsfw tags

* fix: correctly detect child tags of custom NSFW tags

* Update web/src/components/MemoView.tsx

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-04-26 16:23:15 +08:00
johnnyjoy 411a91122b fix: linter error 2025-04-24 10:11:35 +08:00
johnnyjoy eb33a604b2 feat: support mapping avatar url from oauth2 2025-04-24 10:07:24 +08:00
Steven e41916408a chore: update dockerfile 2025-04-21 22:26:18 +08:00
Johnny 0f965c6fe0 chore: add action cache 2025-04-21 21:39:09 +08:00
Johnny 33907539cd chore: merge release action 2025-04-21 21:26:46 +08:00
johnnyjoy dc5f37ebba chore: remove unused demo dockfile 2025-04-21 21:16:38 +08:00
Johnny 7e1368028b chore: add dockerfile.demo 2025-04-21 09:02:38 +08:00
Johnny fdc0553cfb chore: move frontend build to action 2025-04-19 23:10:32 +08:00
Simon bb892be5b3 feat: improve visual feedback in MemoEditor for drag/drop file uploads (#4634)
* improve drag/drop file upload UI

* fix eslint errors

* use tailwind for cursor styles

* fix eslint issues
2025-04-18 23:49:59 +08:00
Johnny d38f4699c2 chore: try build arm/v7 2025-04-17 23:28:33 +08:00
Steven 1a121e350b chore: update gitignore 2025-04-17 23:11:36 +08:00
RichardYe 76ed1b5cc5 feat: set locale based on browser language when user is not logged in (#4635)
* feat: set locale based on browser language when user is not logged in

* docs: comments for locale fallback logic
2025-04-17 20:02:41 +08:00
Steven f6e4e504fe chore: remove armv7 2025-04-16 23:05:27 +08:00
Steven aa272670ce chore: upgrade buf 2025-04-16 23:00:11 +08:00
Steven 7475a30fe9 chore: update docker platforms 2025-04-16 22:50:31 +08:00
Steven e2f5c61e30 fix: docker username in actions 2025-04-16 22:39:58 +08:00
Steven 02f8e0da41 chore: update actions 2025-04-16 22:39:15 +08:00
RichardYe ebccef6033 fix: shutdown gRPC server gracefully (#4626)
fix: add graceful shutdown for gRPC server
2025-04-15 22:58:25 +00:00
Steven 789a9cc5a2 fix: padding left of list 2025-04-14 23:00:36 +08:00
Steven a6be658f42 fix: list memo comments 2025-04-14 22:51:11 +08:00
Johnny b94682dc4f chore: fix linter 2025-04-12 22:16:32 +08:00
Johnny 18b9b9d18f chore: implement memo filter in list memo relations 2025-04-12 22:13:18 +08:00
Johnny 08f9b18ced fix: list memo relations 2025-04-12 22:02:13 +08:00
Johnny 2f6dc2b51f fix: padding of list 2025-04-10 23:06:14 +08:00
Johnny 7632c52c0c chore: bump version 2025-04-10 22:52:03 +08:00
Johnny 97b23f46e6 chore: remove resource title 2025-04-09 22:58:53 +08:00
倒霉狐狸 ebf13c4dff chore: caching resource files accelerates second requests (#4614)
* cache assets files

* Apply suggestions from code review

* Update server/router/frontend/frontend.go

* Update server/router/frontend/frontend.go

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-04-09 22:22:03 +08:00
Johnny 3cc0e255ce fix: memo filter for postgres 2025-04-08 23:46:08 +08:00
Johnny f5d5ebea6f chore: hide actions for comment 2025-04-06 22:58:43 +08:00
Johnny aa8cf44c41 chore: fix entrypoint.sh 2025-04-06 22:44:19 +08:00
Johnny 9dde9f332f chore: move dockerfile 2025-04-06 22:40:26 +08:00
dependabot[bot] 052d5d41fe chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.26.1 to 2.26.3 (#4586)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.26.1 to 2.26.3.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.26.1...v2.26.3)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:08:48 +08:00
dependabot[bot] bec0acc66a chore: bump golang.org/x/oauth2 from 0.27.0 to 0.28.0 (#4587)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.27.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 22:56:28 +08:00
Steven 3d610a78f2 chore: update golangci config 2025-04-02 22:53:17 +08:00
Steven ec17c4b015 chore: update linter ci 2025-04-02 22:51:22 +08:00
Steven 2cf2126d64 fix: golangci config 2025-04-02 22:47:34 +08:00
Steven 2aca8180d1 chore: update golangci config 2025-04-02 22:16:05 +08:00
Steven 0430de8713 chore: fix golangci version 2025-04-02 22:10:19 +08:00
dependabot[bot] 76737b5542 chore: bump golangci/golangci-lint-action from 6 to 7 (#4584)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6 to 7.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:17:02 +08:00
dependabot[bot] 39f85e9d68 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.64 to 1.17.70 (#4585)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.64 to 1.17.70.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.64...feature/s3/manager/v1.17.70)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:49 +08:00
dependabot[bot] ebc2cc2970 chore: bump google.golang.org/grpc from 1.70.0 to 1.71.1 (#4588)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.70.0 to 1.71.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:27 +08:00
dependabot[bot] d1fb602988 chore: bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#4589)
Bumps google.golang.org/protobuf from 1.36.5 to 1.36.6.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:11 +08:00
dependabot[bot] c43762a9b6 chore: bump lucide-react from 0.453.0 to 0.486.0 in /web (#4590)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.453.0 to 0.486.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.486.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:58 +08:00
dependabot[bot] 28074c1404 chore: bump nice-grpc-web from 3.3.6 to 3.3.7 in /web (#4591)
Bumps [nice-grpc-web](https://github.com/deeplay-io/nice-grpc) from 3.3.6 to 3.3.7.
- [Release notes](https://github.com/deeplay-io/nice-grpc/releases)
- [Commits](https://github.com/deeplay-io/nice-grpc/compare/nice-grpc-web@3.3.6...nice-grpc-web@3.3.7)

---
updated-dependencies:
- dependency-name: nice-grpc-web
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:46 +08:00
dependabot[bot] 2458bc98f2 chore: bump i18next from 24.2.2 to 24.2.3 in /web (#4592)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.2 to 24.2.3.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.2...v24.2.3)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:03 +08:00
dependabot[bot] d98520acba chore: bump @trivago/prettier-plugin-sort-imports from 4.3.0 to 5.2.2 in /web (#4593)
chore: bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.3.0 to 5.2.2.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.3.0...v5.2.2)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:14:46 +08:00
dependabot[bot] 3dac75f48c chore: bump react-datepicker from 7.6.0 to 8.2.1 in /web (#4594)
Bumps [react-datepicker](https://github.com/Hacker0x01/react-datepicker) from 7.6.0 to 8.2.1.
- [Release notes](https://github.com/Hacker0x01/react-datepicker/releases)
- [Commits](https://github.com/Hacker0x01/react-datepicker/compare/v7.6.0...v8.2.1)

---
updated-dependencies:
- dependency-name: react-datepicker
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 09:44:20 +08:00
Steven 4f39e00868 chore: fix lint 2025-04-01 20:06:54 +08:00
Johnny b770042a8a refactor: migrate eslint 2025-04-01 00:04:43 +08:00
cmuangs d649d326ef fix: remove errors.Wrap(nil) (#4576)
* Fix errors.Wrap(nil)

* fix resource_test failure where resource does not exist
2025-03-31 12:56:51 +08:00
Shawn 88b38ff2c0 fix: aws-chunked encoding is not supported with the specified x-amz-content-sha256 value for some s3 providers (#4575)
Co-authored-by: Shawn L. <shawn@sola.sh>
2025-03-31 08:49:48 +08:00
Johnny 09c50a8419 fix: codeblock highlight 2025-03-30 23:49:51 +08:00
johnnyjoy 8e6d9b4943 chore: buf generate 2025-03-30 13:16:42 +08:00
Anubhav Singh a63d9b471b feat: update ItalicNode to use repeated children instead of content (#4566)
* feat: update ItalicNode to use repeated children instead of content

* chore: update gomark dependency to latest version

---------

Co-authored-by: Anubhav Singh <anubhav@mail.techindika.com>
2025-03-28 16:15:03 +08:00
olavlan 8bdd1ec009 feat: add norwegian bokmål (nb) translation (#4561)
* add locale file for norwegian (nb)

* correct spelling
2025-03-27 13:14:12 +08:00
Anubhav Singh 194a49367c fix: incorrect checkbox state after removing checked items #4549 (#4552)
Co-authored-by: Anubhav Singh <anubhav@mail.techindika.com>
2025-03-25 21:59:30 +08:00
johnny 44df17aecc chore: bump version 2025-03-23 11:32:09 +08:00
Austin Pearce c4f094d22b fix: BrandBanner to use NavLink (#4536)
* Fix BrandBanner to use NavLink

* Apply suggestions from code review

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-03-18 21:18:22 +08:00
XIN_____ 3d0f7285f9 feat: add i18n for Pinned (#4535)
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-03-18 21:17:09 +08:00
Johnny d63ef81c9d chore: update common locale 2025-03-18 09:04:47 +08:00
Amir Ehsandar 7b23bdcfcf fix: allow admins to uncheck disallow password if applicable (#4532)
- closes #4469
2025-03-18 09:00:50 +08:00
Steven 9b957edd1f chore: fix linter 2025-03-17 21:52:35 +08:00
Steven 8164986fcc chore: move store test 2025-03-17 21:51:02 +08:00
Steven fdf9d9f506 chore: move resource name test 2025-03-17 21:41:21 +08:00
XIN_____ b79755dd09 feat: update zh-hans i18n (#4531)
* feat: update zh-hans i18n

* Update zh-Hans.json

Co-authored-by: taosin <xinxintao@foxmail.com>

---------

Co-authored-by: KissFire <53330905+kiss-fire@users.noreply.github.com>
2025-03-17 18:22:13 +08:00
Amir Ehsandar 2e9b9368db fix: prevent double effect on image modal wheel event (#4522)
- escape key closes the modal
- zooming is a bit smoother
2025-03-16 10:28:59 +08:00
Amir Ehsandar c0643ff6fa fix: use valid query parameters for postgres (#4515) 2025-03-15 12:59:00 +08:00
Steven 6b042fe16e chore: always show full content when pinned 2025-03-14 20:13:54 +08:00
Steven ea3a534ce5 chore: fix typo 2025-03-14 20:01:10 +08:00
Steven f1f0253e8d fix: typo 2025-03-14 19:55:25 +08:00
George Wu fae7b5d3e8 fix: typo s/contnet/content (#4507) 2025-03-14 14:54:55 +08:00
XIN_____ be18a7b77b chore: update i18n for resource page (#4505)
* chore: update i18n for resources

* Update Resources.tsx

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>
2025-03-14 13:04:07 +08:00
Amir Ehsandar 32c69bbb52 fix: user stats changes based on selected tab (#4504)
- set partial only the relevant user stats instead of only adding up stats
2025-03-14 13:02:47 +08:00
Amir Ehsandar e75ef0964d feat: implement grpc health service checking database connection (#4499) 2025-03-14 08:43:01 +08:00
Johnny fc7dc58720 chore: move archived route 2025-03-13 20:38:14 +08:00
Lincoln Nogueira e8e393a9cb chore(i18n): tidy (#4497)
- sort all keys alphabetically for easier side-by-side translation

- remove keys from other locales that don't exist anymore in `en.json`

- remove keys from other locales that have missing {{interpolations}}

- add missing entries to pt-BR
2025-03-13 20:37:50 +08:00
XIN_____ 1762496e79 chore: update zh-hans text for rename-tag (#4496)
* Update RenameTagDialog.tsx

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

* Update zh-Hans.json

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>
2025-03-13 20:00:22 +08:00
Johnny 34ab88348e chore: sort by pinned 2025-03-13 19:57:12 +08:00
Johnny d794e6db76 chore: remove internal frontend cache 2025-03-13 11:23:27 +08:00
XIN_____ 81e40d9b18 chore: update i18n for tag reame (#4493)
* feat: update i18n for zh-hans

* Update zh-Hans.json

---------

Co-authored-by: KissFire <53330905+kiss-fire@users.noreply.github.com>
2025-03-13 09:20:46 +08:00
Johnny fc5962f6a4 feat: show pinned count 2025-03-12 23:33:51 +08:00
Johnny fb3c17d0e9 chore: update mobile header 2025-03-12 22:21:22 +08:00
Johnny 0dfcb1a7c8 feat: total memo count 2025-03-12 22:15:46 +08:00
Johnny 3349311b51 chore: update frontend dependencies 2025-03-12 21:05:32 +08:00
Heiko 775673d17f fix: update README.md (#4492)
Fixed link for contribution
2025-03-12 20:35:10 +08:00
XIN_____ 1edb9e6774 feat: update i18n for zh-hans (#4488)
* chore:memo filter support i18n for zh-hans

* feat: restore addFilter method value field in StatisticsView.tsx

* chore: change getFilterDisplayText for i18n

* chore: add string type in utils/i18n

* feat: using switch to avoid change TranslationType

* feat: eslint check

* feat: eslint fix
2025-03-12 16:54:04 +08:00
Simon 690f28bed8 feat: add loading spinner during file upload process (#4491)
* show LoaderIcon while uploading file

* fix spacing for eslint
2025-03-12 09:56:22 +08:00
Johnny 7a438be08d chore: update user stats 2025-03-12 09:14:43 +08:00
Johnny e3a4f49c5c feat: implement creator_id factor 2025-03-11 22:00:57 +08:00
Johnny ba52a786f9 chore: update canary image 2025-03-11 10:23:38 +08:00
wrrrzr b0392954f4 Add executable permission to scripts/build.sh (#4486) 2025-03-11 09:00:42 +08:00
Johnny 7123a2cf51 chore: remove sort by pinned 2025-03-10 21:32:17 +08:00
Johnny ff13e0f353 chore: add legacy plugin 2025-03-10 18:57:48 +08:00
Johnny 925e97882e feat: support pinned factor 2025-03-10 18:52:12 +08:00
Johnny 90119c1af8 refactor: move memo property 2025-03-07 22:53:35 +08:00
Johnny 3401def442 chore: simplify memo filters 2025-03-06 23:10:20 +08:00
Johnny 16a0872972 chore: enable auto compact by default 2025-03-06 23:02:12 +08:00
Johnny 56ad8ab3bd refactor: view store 2025-03-06 21:38:54 +08:00
Johnny 2e0467e3d1 fix: mobile header 2025-03-06 20:46:16 +08:00
Lincoln Nogueira d7d3568ba4 chore(i18n): update pt-BR (#4471) 2025-03-06 09:21:44 +08:00
Johnny c668073cf3 chore: update resource view 2025-03-05 23:08:44 +08:00
Johnny 92a44e26b9 chore: remove emoji regex 2025-03-04 22:56:46 +08:00
XIN_____ 6ed6b86a75 chore: update i18n zh-hans (#4467)
* Update MemoDisplaySettingMenu.tsx

Masonry View

* Update en.json

* Update zh-Hans.json
2025-03-04 22:43:48 +08:00
Johnny 36d458fe88 chore: update masonry scale 2025-03-03 22:41:18 +08:00
Johnny 7592e5fe76 fix: masonry state 2025-03-03 09:23:40 +08:00
Johnny d6be20b917 feat: implement masonry view 2025-03-02 23:27:12 +08:00
Johnny a8713ec639 chore: update backend dependencies 2025-03-02 21:58:46 +08:00
Johnny 32da704be6 chore: update frontend dependencies 2025-03-02 21:55:55 +08:00
dependabot[bot] 858053e3b1 chore: bump @dnd-kit/sortable from 8.0.0 to 10.0.0 in /web (#4454)
Bumps [@dnd-kit/sortable](https://github.com/clauderic/dnd-kit/tree/HEAD/packages/sortable) from 8.0.0 to 10.0.0.
- [Release notes](https://github.com/clauderic/dnd-kit/releases)
- [Changelog](https://github.com/clauderic/dnd-kit/blob/master/packages/sortable/CHANGELOG.md)
- [Commits](https://github.com/clauderic/dnd-kit/commits/@dnd-kit/sortable@10.0.0/packages/sortable)

---
updated-dependencies:
- dependency-name: "@dnd-kit/sortable"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:47:19 +08:00
dependabot[bot] b36e2b630a chore: bump @bufbuild/buf from 1.48.0 to 1.50.0 in /web (#4452)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.48.0 to 1.50.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.48.0...v1.50.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:47:09 +08:00
dependabot[bot] c24ad79b36 chore: bump vite from 6.0.6 to 6.2.0 in /web (#4451)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.6 to 6.2.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.2.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:59 +08:00
dependabot[bot] 9a0a1f0baf chore: bump i18next from 24.2.0 to 24.2.2 in /web (#4453)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.0 to 24.2.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.0...v24.2.2)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:50 +08:00
dependabot[bot] 8ab77442f5 chore: bump fuse.js from 7.0.0 to 7.1.0 in /web (#4455)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v7.0.0...v7.1.0)

---
updated-dependencies:
- dependency-name: fuse.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:25 +08:00
dependabot[bot] ea9db2ff56 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.48 to 1.17.61 (#4460)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.48 to 1.17.61.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.48...credentials/v1.17.61)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:12 +08:00
Johnny 8acded1f23 chore: fix linter 2025-03-02 15:40:16 +08:00
Johnny 372fc3655a refactor: retire less 2025-03-02 15:34:21 +08:00
dependabot[bot] 4ed6862423 chore: bump pnpm/action-setup from 4.0.0 to 4.1.0 (#4456)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:42 +08:00
dependabot[bot] 69ea9eac94 chore: bump google.golang.org/protobuf from 1.35.2 to 1.36.5 (#4458)
Bumps google.golang.org/protobuf from 1.35.2 to 1.36.5.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:30 +08:00
dependabot[bot] 459e8e9589 chore: bump modernc.org/sqlite from 1.34.2 to 1.36.0 (#4457)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.34.2 to 1.36.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.34.2...v1.36.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:17 +08:00
dependabot[bot] d107373ae9 chore: bump github.com/google/cel-go from 0.23.2 to 0.24.1 (#4459)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.23.2 to 0.24.1.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.23.2...v0.24.1)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:06 +08:00
dependabot[bot] 4e5b9d39b3 chore: bump github.com/spf13/cobra from 1.8.1 to 1.9.1 (#4461)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.9.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.1...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:20:50 +08:00
xt 7651c454fd chore: chinese localization enhancements (#4450)
* Chinese localization enhancements

* Fix for eslint

* Chinese localization fixed
2025-02-28 17:45:50 +08:00
Johnny 5562282822 chore: update demo site 2025-02-27 23:05:43 +08:00
Johnny 47b41bce85 refactor: move memo relation definition 2025-02-27 15:28:36 +08:00
Johnny ba98fddbaf chore: go mod tidy 2025-02-27 15:12:25 +08:00
Johnny 5bb4a300db chore: bump gomark 2025-02-27 15:10:39 +08:00
Johnny 012405f7fd refactor: user stats state 2025-02-26 22:58:22 +08:00
Johnny 81502d9092 fix: stats requests 2025-02-26 22:32:26 +08:00
Johnny b897b243e5 feat: dynamic fetch user stats 2025-02-26 22:29:59 +08:00
Johnny 5d1075a647 refactor: update home layout 2025-02-26 22:14:07 +08:00
Johnny 0da3859878 chore: bump version to 0.24.1 2025-02-26 21:41:57 +08:00
Johnny b56aa397b2 chore: update assets routes 2025-02-26 21:40:28 +08:00
Johnny f60906ce33 chore: tweak vite config 2025-02-26 21:21:46 +08:00
nbb 5962c6d04b feat: optimize initial load performance by implementing lazy loading and code splitting (#4445) 2025-02-26 13:16:05 +08:00
Johnny bef67638c1 chore: fix home route 2025-02-25 23:34:55 +08:00
Johnny 8e4e745ba9 chore: update navigation 2025-02-25 23:13:48 +08:00
XIN_____ 3a7b24bd01 chore: add cursor-pointer to memo's display time (#4441)
feat: memo title add cursor-pointer when mouse hover
2025-02-25 10:13:04 +08:00
Johnny 271a8c8c28 refactor: home layout 2025-02-24 23:42:35 +08:00
Johnny 9107a941ca chore: update linter config 2025-02-24 22:21:07 +08:00
Johnny f98c519834 fix: linter 2025-02-24 22:04:25 +08:00
Johnny 66a4b04454 chore: update readme 2025-02-24 22:01:36 +08:00
Johnny 0200ce7681 chore: upgrade golangci-lint 2025-02-24 21:50:39 +08:00
Johnny bbca130d62 chore: bump golang version 2025-02-24 21:47:57 +08:00
XIN_____ a0fabaf012 chore: update cn-zh i18n (#4435) 2025-02-24 10:43:24 +08:00
Michael Baumgarten 9f01b451df feat: match sublist indentation when adding a new item (#4433)
* match sublist indentation

* recursively get last node

* fix linting issues
2025-02-22 20:48:39 +08:00
MHZ 964ae16851 feat: support YouTube video thumbnail in link preview (#4427) 2025-02-22 20:46:58 +08:00
MHZ f17774cb3b feat: prevent attackers from exploiting redirect attack GetLinkMetadata API (#4428)
fix: Prevent attackers from exploiting redirect attack GetLinkMetadata API.
2025-02-21 17:29:17 +08:00
Johnny bc97b66f36 fix: serial updates 2025-02-20 21:38:36 +08:00
johnnyjoy f15fd42ed5 fix: inboxes state 2025-02-20 20:51:08 +08:00
johnnyjoy 7a685d6435 fix: fetch user by username 2025-02-20 20:43:28 +08:00
XIN_____ 1ebe2e9aae chore: update chinese i18n for settings section (#4424) 2025-02-20 20:21:59 +08:00
Johnny ea165db751 chore: update README.md 2025-02-20 17:43:47 +08:00
Johnny c088c5b26a feat: render emoji from shortcut title 2025-02-19 22:13:32 +08:00
Johnny 37eceabc94 chore: fix memo view gap 2025-02-19 22:02:41 +08:00
Johnny cdbaf805b7 chore: pnpm install 2025-02-19 22:00:12 +08:00
Johnny e528203cde chore: remove unused deps 2025-02-19 21:59:45 +08:00
MHZ f8c973c938 fix: prevent previewing internal network web pages. (#4421) 2025-02-19 21:55:24 +08:00
Johnny 2aaaef79f7 chore: fix tests 2025-02-18 22:32:30 +08:00
Johnny 2dc7766fd0 fix: content contains for postgres 2025-02-18 22:28:25 +08:00
taosin 00932d18f5 feat: update i18n zh-hans (#4416) 2025-02-18 10:47:01 +08:00
taosin 6fdfe6b118 chore: update chinese i18n (#4414) 2025-02-17 17:52:18 +08:00
ProjectOrangeJuice 9f25bb2034 feat: trim space on webhook url (#4411) 2025-02-17 10:16:01 +08:00
MHZ 174b8b048a feat: support blur processing for NSFW content with customizable NSFW tags (#4407) 2025-02-16 23:35:31 +08:00
Johnny 47a9b434e6 fix: translate in members section 2025-02-16 22:34:35 +08:00
Johnny 5686fdfb0a chore: handle redirect 2025-02-16 22:17:48 +08:00
Johnny f5394a3e32 chore: update golangci config 2025-02-16 21:42:33 +08:00
Johnny 9299c216e2 chore: move migration to 0.24.0 2025-02-16 21:02:18 +08:00
taosin a7fef80384 chore: update chinese i18n at member setting section (#4405) 2025-02-16 21:00:37 +08:00
Chris Dzombak d25f355392 chore: allow storing resource references >256 chars long in mysql (#4408)
fix: allow storing resource references >256 chars long in mysql
2025-02-16 18:20:51 +08:00
boojack 04d7ba48e5 chore: remove default gzip middleware 2025-02-13 22:00:55 +08:00
Johnny 920b0f64f2 chore: extract auth footer 2025-02-12 22:05:58 +08:00
taosin 3c71ee9d7b chore: update i18n chinese (#4400) 2025-02-12 16:43:44 +08:00
xt 4cd2aa6f32 chore: chinese localization enhancements (#4397)
* Chinese localization enhancements

* Fix for eslint
2025-02-12 10:13:09 +08:00
Johnny 7a57b5c6e7 refactor: user store 2025-02-11 21:29:16 +08:00
Johnny 11b9c240e9 refactor: workspace setting store 2025-02-11 21:23:46 +08:00
Kevin Clark e27f6f0c52 chore: update LICENSE (#4394)
This PR updates the Copyright information for memos.
Related to usememos/memos#4393
2025-02-11 15:45:20 +08:00
Johnny 9027430646 fix: store reactive 2025-02-10 22:20:07 +08:00
CyberSlinger 01a9bb2d49 feat: add zh hans text (#4384)
* feat: test dev push

* feat: add zh Hans text

* feat: restore readme

* feat: update zh hans text

* feat: add tag for properties label

* feat: updarte zh hans translation

* feat: add tab
2025-02-10 10:19:19 +08:00
Simon c9edac9d5a chore: update i18n Ukrainian (#4385)
* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json
2025-02-10 10:18:55 +08:00
Martin Hartl ae85dff5e4 chore: add id to RSS feed items (#4383) 2025-02-09 22:24:23 +08:00
Johnny 6abd51fe5a chore: update resource storage type comment 2025-02-09 12:56:30 +08:00
Johnny 49332851d4 chore: go mod tidy 2025-02-09 11:50:16 +08:00
Johnny 0a429a899f chore: remove version update activity 2025-02-09 11:48:53 +08:00
Johnny 983323ceef chore: remove debug code 2025-02-09 11:44:15 +08:00
Johnny 5a2f18da69 refactor(frontend): retire redux 2025-02-09 11:43:55 +08:00
johnnyjoy 13f6fa7b37 refactor: remove default visibility in workspace setting 2025-02-08 11:40:31 +08:00
Steven 9957f8e290 chore: move dsn output to dev mode 2025-02-07 20:59:14 +08:00
Steven 4dfe078f3e chore: tweak memo link is rss 2025-02-07 20:55:38 +08:00
Steven f6ad49754a chore: update url of memo detail page 2025-02-07 20:51:04 +08:00
shungiku 8be0ddfb35 chore: add datepicker to calendar month (#4379)
Co-authored-by: shungiku <79780196+shungikuk@users.noreply.github.com>
2025-02-07 12:53:02 +08:00
Steven e09819da53 chore: add MemoFilters to explore sidebar 2025-02-06 23:35:25 +08:00
Steven 2ed3e34636 refactor: update root layout 2025-02-06 23:20:37 +08:00
johnnyjoy 505fee1abb chore: add noreferrer to external links 2025-02-06 20:19:58 +08:00
johnnyjoy 3a3ffe633d chore: remove latest tag 2025-02-06 19:48:51 +08:00
johnnyjoy 0e303181a9 chore: update action's title 2025-02-06 19:45:05 +08:00
johnnyjoy 849bf66612 fix: remove outdated factor 2025-02-06 19:38:53 +08:00
𝗦𝗵𝗟𝗲𝗿𝗣 48988a8814 fea: improve Turkish Locales (#4375) 2025-02-06 19:11:02 +08:00
Steven dfacb33abe chore: update release action by branch 2025-02-06 09:15:12 +08:00
Steven 84ef3558ab chore: update release action by branch 2025-02-06 09:12:42 +08:00
wzc90 3f33ccd906 fix: update 01__memo_pinned.sql (#4370) 2025-02-06 09:08:31 +08:00
Steven 7996586488 chore: fix migration script for sqlite 2025-02-05 20:56:46 +08:00
johnnyjoy 54a48b58d7 chore: remove random field 2025-02-05 20:48:27 +08:00
johnnyjoy 2a8c4cb750 chore: update styles 2025-02-05 20:30:22 +08:00
johnnyjoy 07336f0392 chore: update condition concat check 2025-02-05 20:07:38 +08:00
johnnyjoy 64dfadb538 chore: update readme 2025-02-05 19:51:09 +08:00
johnnyjoy 732a7d0bbf chore: add fa locale 2025-02-05 19:26:34 +08:00
spidtzz d8b3a69c31 feat: add Farsi(Persian) localazation (#4364)
Add files via upload
2025-02-05 19:19:29 +08:00
shungiku c2210b65ee fix: calendar coloring issue (#4352)
* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* chore: adjust calendar color for dark theme
2025-02-05 11:13:25 +08:00
RoccoSmit 03267d6d37 feat: search for multiple words (#4362) 2025-02-04 21:04:36 +08:00
johnnyjoy 6c088e09d9 chore: fix import order 2025-02-03 18:35:16 +08:00
johnnyjoy a7ca63434b feat: validate shortcut's filter 2025-02-03 18:34:31 +08:00
johnnyjoy 8f35086da7 chore: update docs link 2025-02-03 18:23:50 +08:00
johnnyjoy ff04fdc459 feat: support more operators in filter 2025-02-03 18:23:09 +08:00
johnnyjoy 03189ee3b2 chore: remove corepack in dockerfile 2025-02-03 17:50:33 +08:00
johnnyjoy f25acfe8e2 chore: fix linter 2025-02-03 17:34:46 +08:00
johnnyjoy e0e735d14d feat: support memo filter for mysql and postgres 2025-02-03 17:14:53 +08:00
hchengting 0f8b7b7fe6 fix: show loader icon while refreshing (#4358) 2025-02-03 15:59:46 +08:00
johnnyjoy 503c892abf chore: buf generate 2025-02-03 15:09:37 +08:00
johnnyjoy b734d429ec chore: fix linter warning 2025-02-03 13:08:13 +08:00
johnnyjoy 364f005ee5 fix: filter 2025-02-03 12:44:01 +08:00
johnnyjoy 2db86f6644 feat: implement shortcut components 2025-02-03 12:26:44 +08:00
johnnyjoy 3a085f3639 chore: fix filter tests 2025-02-03 12:01:34 +08:00
johnnyjoy 8e586d348e chore: fix tag filter 2025-02-03 11:45:26 +08:00
johnnyjoy bf5a29524a chore: remove drop index 2025-02-03 11:45:15 +08:00
johnnyjoy 6682917931 chore: add validate only to create shortcut 2025-02-03 11:45:05 +08:00
johnnyjoy 81e8aed6ab chore: move part of memo filter 2025-02-02 20:28:24 +08:00
johnnyjoy fafd6d81c7 chore: fix linter warning 2025-02-02 18:50:51 +08:00
johnnyjoy be5e24c0eb refactor: renovate list memos endpoint 2025-02-02 18:43:26 +08:00
johnnyjoy 14c72fa7df feat: implement shortcuts 2025-02-02 17:11:52 +08:00
johnnyjoy b9a0c56163 feat: support more factors in filter 2025-02-02 16:12:44 +08:00
johnnyjoy 2a392b8f8d chore: fix import order 2025-02-02 13:52:45 +08:00
johnnyjoy f31800456e chore: fix import order 2025-02-02 13:52:29 +08:00
johnnyjoy 58a867e4da fix: linter warning 2025-02-02 13:50:36 +08:00
johnnyjoy 2d731c5cc5 feat: memo filter for sqlite 2025-02-02 13:35:57 +08:00
johnnyjoy 0af08d9c06 chore: add if exists to postgres 2025-02-02 13:19:56 +08:00
johnnyjoy e6cd761787 chore: remove cgo 2025-02-02 13:07:11 +08:00
dependabot[bot] 66db662e33 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.66.3 to 1.75.2 (#4346)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.66.3 to 1.75.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.66.3...service/s3/v1.75.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:41:26 +08:00
dependabot[bot] 9f99a7de35 chore: bump @types/leaflet from 1.9.15 to 1.9.16 in /web (#4340)
Bumps [@types/leaflet](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/leaflet) from 1.9.15 to 1.9.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/leaflet)

---
updated-dependencies:
- dependency-name: "@types/leaflet"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:43 +08:00
dependabot[bot] ed3923e1ba chore: bump typescript from 5.7.2 to 5.7.3 in /web (#4341)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:30 +08:00
dependabot[bot] 0eed9d5839 chore: bump less from 4.2.1 to 4.2.2 in /web (#4342)
Bumps [less](https://github.com/less/less.js) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/less/less.js/releases)
- [Changelog](https://github.com/less/less.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/less/less.js/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: less
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:21 +08:00
dependabot[bot] a80e407dc5 chore: bump @radix-ui/react-popover from 1.1.4 to 1.1.5 in /web (#4343)
Bumps [@radix-ui/react-popover](https://github.com/radix-ui/primitives) from 1.1.4 to 1.1.5.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-popover"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:13 +08:00
dependabot[bot] 2322f989ea chore: bump actions/stale from 9.0.0 to 9.1.0 (#4344)
Bumps [actions/stale](https://github.com/actions/stale) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:04 +08:00
dependabot[bot] 00dd54bae4 chore: bump github.com/lithammer/shortuuid/v4 from 4.0.0 to 4.2.0 (#4345)
Bumps [github.com/lithammer/shortuuid/v4](https://github.com/lithammer/shortuuid) from 4.0.0 to 4.2.0.
- [Release notes](https://github.com/lithammer/shortuuid/releases)
- [Commits](https://github.com/lithammer/shortuuid/compare/v4.0.0...v4.2.0)

---
updated-dependencies:
- dependency-name: github.com/lithammer/shortuuid/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:55 +08:00
dependabot[bot] e034254807 chore: bump github.com/google/cel-go from 0.22.1 to 0.23.2 (#4347)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.22.1 to 0.23.2.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.22.1...v0.23.2)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:42 +08:00
dependabot[bot] 1e9d8f7460 chore: bump golang.org/x/net from 0.33.0 to 0.34.0 (#4348)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.34.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:33 +08:00
dependabot[bot] cda5a5baa4 chore: bump github.com/aws/aws-sdk-go-v2 from 1.32.7 to 1.36.0 (#4349)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.32.7 to 1.36.0.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.32.7...v1.36.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:21 +08:00
dependabot[bot] 7a21391446 chore: bump @github/relative-time-element from 4.4.4 to 4.4.5 in /web (#4339)
Bumps [@github/relative-time-element](https://github.com/github/relative-time-element) from 4.4.4 to 4.4.5.
- [Release notes](https://github.com/github/relative-time-element/releases)
- [Commits](https://github.com/github/relative-time-element/compare/v4.4.4...v4.4.5)

---
updated-dependencies:
- dependency-name: "@github/relative-time-element"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:36:29 +08:00
Xiao Wei 37a81f9d28 fix: migrate sql error (#4338)
* fix: migrate sql error

sqlite not support postgres sql

* Apply suggestions from code review

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-02-01 22:11:17 +08:00
johnnyjoy 0b85cb567e chore(frontend): fix clsx 2025-02-01 22:04:29 +08:00
johnnyjoy 57014e392f feat: get user by username 2025-02-01 18:00:22 +08:00
johnnyjoy 45c16f9d52 chore: fix linter 2025-02-01 12:53:48 +08:00
johnnyjoy 0dcd0904e8 refactor: remove resource uid 2025-02-01 12:50:15 +08:00
johnnyjoy 97d12db3d5 refactor: renovate create memo 2025-02-01 11:48:22 +08:00
johnnyjoy 98aa0b73c5 refactor: retire memo uid 2025-02-01 11:28:07 +08:00
johnnyjoy b0119f320a chore: tweak migration scripts 2025-02-01 11:19:36 +08:00
johnnyjoy 5e770dda52 refactor: memo name 2025-02-01 11:17:36 +08:00
RoccoSmit 2f4c5d7bc2 fix: cancel out of no changes save (#4335)
Cancel out of trying to save
2025-02-01 08:30:04 +08:00
johnnyjoy 9bd6d17864 chore: add migration script 2025-01-31 22:00:05 +08:00
johnnyjoy 39d4d4f4f3 chore: update migrate scripts 2025-01-31 21:05:20 +08:00
johnnyjoy d605faeffa refactor: move pinned to memo 2025-01-31 20:58:18 +08:00
johnnyjoy 2058a8ab7b chore: move references to memo property 2025-01-31 14:18:07 +08:00
thehijacker 3fa690964e chore: update Slovenian translation (#4329)
Co-authored-by: Andrej Kralj <andrej.kralj@gmail.com>
2025-01-31 13:39:07 +08:00
Viacheslav Potoropin 7ed3a12a64 fix: internal error on pin/unpin (#4332) 2025-01-31 13:38:43 +08:00
Zero King 5ec3150e0e fix: use correct separator in migration file name (#4327)
Fixes: e913271f15 ("refactor: move tags from property to payload (#4229)")
2025-01-30 12:26:14 +08:00
johnnyjoy 75fd4223bf chore: bump version 2025-01-29 23:41:50 +08:00
changchiakai 9172e47c33 chore: update zh-Hant (#4324)
Update zh-Hant

Co-authored-by: changchiakai <changeric1031@gmail.com>
2025-01-29 09:56:20 +08:00
Philipp Mundhenk 63bbeb9ca3 chore: link to SSO Documentation (#4319)
* Update SSOSection.tsx

linked to SSO (links to Authentik, Authelia, Keycloak), instead of Keycloak only

* Update id.json

* Update uk.json

* Update fr.json

* Update pt-PT.json

* Update vi.json

* Update uk.json

* Update de.json

* Update en.json
2025-01-26 23:03:56 +08:00
Pavel Stržínek 0435a67aa7 feat: czech locale support (#4316) 2025-01-26 23:03:11 +08:00
johnnyjoy 0334a4845f chore: tweak calendar styles 2025-01-21 22:55:57 +08:00
johnnyjoy ef3b7ac6ae chore: update tag icon 2025-01-21 22:55:35 +08:00
johnnyjoy f9b1df5d13 fix: tags container 2025-01-21 22:46:09 +08:00
Comix d9a92b2ef8 feat: support path style of s3 url (#4304)
Signed-off-by: ComixHe <ComixHe1895@outlook.com>
2025-01-21 18:02:21 +08:00
johnnyjoy 702c092289 chore: update auth message 2025-01-20 19:38:50 +08:00
johnnyjoy 409d64b839 chore: update memo comment in activity 2025-01-20 19:34:23 +08:00
johnnyjoy f1308ddd27 refactor: update part of resource identifier 2025-01-19 23:03:22 +08:00
johnnyjoy cda18a37c0 chore: remove docs 2025-01-19 10:50:49 +08:00
johnnyjoy 3c0d011085 chore(dev): update build guides 2025-01-19 10:46:35 +08:00
johnnyjoy f1eacfefb0 chore(dev): update build directory 2025-01-19 10:33:04 +08:00
Steven edc3f1d9d9 chore: retire unused memo view 2025-01-16 09:20:01 +08:00
Steven 147458347b chore: tweak user stats in frontend 2025-01-16 09:12:47 +08:00
johnnyjoy 6904dc16af chore: fix linter 2025-01-15 22:33:18 +08:00
johnnyjoy c76ab87a0a refactor: update list user stats 2025-01-15 19:25:36 +08:00
Steven 8b65d248b1 fix: memo filter 2025-01-14 00:05:33 +08:00
johnnyjoy ee96465be0 feat: list user stats 2025-01-13 23:14:44 +08:00
johnnyjoy cde058c72a chore: tweak theme code 2025-01-13 19:46:06 +08:00
Query&mut NinjaStyle, &Ryder 94517490f5 fix: mermaid diagrams in dark mode (#4289)
* fix #4257 fixed ui for mermaid diagrams in dark mode

* fixed linting issues

* added dynamic color theme for mermaid diagrams

* now mermaid block uses theme according to the system as well when 'follow system' is selected

* refactored code for mermaid theme logic

* refactored mermaid code to use const instead of function call

---------

Co-authored-by: root <root@DESKTOP-G3MCU14>
2025-01-13 19:44:53 +08:00
johnnyjoy d050a6fd46 chore: update user stats 2025-01-11 20:12:02 +08:00
johnnyjoy 34c26a394a feat: implement user stats endpoint 2025-01-11 16:59:22 +08:00
Steven 5ff8ab9a61 chore: polish creator definition 2025-01-10 23:39:50 +08:00
Steven 8b7e9f5443 chore: remove unused user id 2025-01-10 23:35:00 +08:00
RoccoSmit 3081015692 feat: date picker navigation (#4286)
Added month and year dropdowns
2025-01-10 22:46:08 +08:00
johnnyjoy 2cd524e4fa chore: fix buf format 2025-01-10 22:29:57 +08:00
johnnyjoy a1be73cce3 chore: buf format 2025-01-10 22:26:19 +08:00
johnnyjoy c1498a1844 chore: retire webhook state 2025-01-10 22:24:12 +08:00
johnnyjoy 2a861ea430 refactor: tweak resource state in api 2025-01-10 22:20:23 +08:00
johnnyjoy 1caaef1c5b chore: fix memo compact mode 2025-01-10 21:47:00 +08:00
Query&mut NinjaStyle, &Ryder 972ebbae2f fix: compact mode storage (#4279)
fix #4274 now when checkbox is toggled the memo remembers the compact state

Co-authored-by: root <root@DESKTOP-G3MCU14>
2025-01-10 20:43:46 +08:00
johnnyjoy ac7121c21a chore: update archived page 2025-01-10 20:24:05 +08:00
johnnyjoy 5d40f38956 chore: fix name comments 2025-01-09 21:35:02 +08:00
Steven 840b16f041 chore: tweak back to top button 2025-01-08 22:59:08 +08:00
Steven 012ca1d780 fix: tag stats 2025-01-08 22:35:34 +08:00
johnnyjoy d9d6f73330 chore: fix memo converter 2025-01-08 20:57:34 +08:00
johnnyjoy 65da94521d chore: buf generate 2025-01-08 20:29:20 +08:00
Pierre Quillery cdadf133d0 chore: adding missing translations (#4273)
* Added missing translations strings (filters, about page, ...)

* Forgot one translation string.

* Fixed PR issues and added Access Token related missing translation strings.

* Fixed eslint issues.

* Fixed eslint issues #2.

* Fixed access token dialog translations, added missing webhook dialog translations.
2025-01-08 10:24:41 +08:00
Chris Curry 7b909fb772 feat: scroll to top (#4244) 2025-01-04 23:44:37 +08:00
Chris Curry d81174ad7c feat: optimize filters sync (#4260)
* refactor: add bi-directional filters sync between filterStore and searchParams

* fix: tag redirection from memos detail page, https://github.com/usememos/memos/issues/4232
2025-01-04 23:42:49 +08:00
tungerno e3d1967db8 chore: add missing german translations (#4268) 2025-01-04 23:42:29 +08:00
Pierre Quillery 50d09bb91e chore: added missing French translations (#4270)
Added missing French translations.
2025-01-04 23:42:09 +08:00
dependabot[bot] 828461d430 chore: bump golang.org/x/net from 0.30.0 to 0.33.0 (#4251)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.30.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.30.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 10:23:29 +08:00
Chris Curry e3b378b03b feat: persist memo filters with url query (#4239)
* feat: persist memo filters with url query

- Implemented synchronization of memo filters with URL search parameters.
- Enhanced memo store to manage current request state for fetching memos, allowing for request cancellation, avoiding the race conditions.

* refactor: update import
2025-01-02 10:23:15 +08:00
dependabot[bot] 0e1ac30462 chore: bump react-router-dom from 6.28.1 to 7.1.1 in /web (#4246)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.28.1 to 7.1.1.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.1.1/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:25 +08:00
dependabot[bot] 94c47cc520 chore: bump i18next from 23.16.8 to 24.2.0 in /web (#4247)
Bumps [i18next](https://github.com/i18next/i18next) from 23.16.8 to 24.2.0.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.16.8...v24.2.0)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:15 +08:00
dependabot[bot] 93f01f02e1 chore: bump @types/node from 22.10.2 to 22.10.3 in /web (#4248)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.10.2 to 22.10.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:05 +08:00
dependabot[bot] fd257ba900 chore: bump @mui/joy from 5.0.0-beta.48 to 5.0.0-beta.51 in /web (#4249)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.48 to 5.0.0-beta.51.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:55 +08:00
dependabot[bot] 00df48e594 chore: bump google.golang.org/grpc from 1.67.1 to 1.69.2 (#4250)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.69.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.69.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:44 +08:00
dependabot[bot] 00c7ea229c chore: bump github.com/aws/aws-sdk-go-v2/config from 1.28.2 to 1.28.7 (#4252)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.28.2 to 1.28.7.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.2...config/v1.28.7)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:27 +08:00
dependabot[bot] 3b57b03e57 chore: bump golang.org/x/crypto from 0.29.0 to 0.31.0 (#4253)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:18 +08:00
dependabot[bot] 2b681bf594 chore: bump golang.org/x/mod from 0.21.0 to 0.22.0 (#4254)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/mod/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:08 +08:00
Steven aff6b8707d chore: upgrade frontend dependencies 2025-01-01 07:59:56 +08:00
Chris Curry bc0bac94ed refactor: enhance hyperlink handling in markdown shortcuts (#4238) 2024-12-30 17:46:24 +08:00
Hadley Rich 82b5c8ab07 feat: add sh entrypoint to allow MEMOS_DSN_FILE to load variable from secret (#4236)
Add sh entrypoint to allow MEMOS_DSN_FILE to load variable from secret
2024-12-30 17:46:02 +08:00
johnnyjoy 7817ad07f7 chore: fix linter 2024-12-30 09:18:11 +08:00
johnnyjoy 3220adbff9 refactor: split memo service 2024-12-26 20:13:05 +08:00
johnnyjoy a78bfffb17 chore: add output only flag 2024-12-26 20:06:42 +08:00
johnnyjoy 541e07af8c chroe: rebuild memo references 2024-12-26 20:04:36 +08:00
johnnyjoy 3b0be442de chore: update memo payload runner schedule 2024-12-26 20:01:15 +08:00
johnnyjoy 41d9c9d76e fix: order list starts 2024-12-25 22:43:26 +08:00
Johnny e913271f15 refactor: move tags from property to payload (#4229)
* refactor: move tags from property to payload

* chore: fix tests

* chore: drop memo tags

* chore: update

---------

Co-authored-by: Steven <stevenlgtm@gmail.com>
2024-12-24 15:23:15 +00:00
zjy4fun f15346e615 fix: optimize memoMap generation logic to ensure memoMap count matche… (#4214)
fix: optimize memoMap generation logic to ensure memoMap count matches memos
2024-12-20 13:22:48 +08:00
zjy4fun 7a77b4ba38 chore: fix css location compatibility issues on Safari (#4215)
chore: fix location compatibility issues on Safari

closes https://github.com/usememos/memos/issues/4190
2024-12-20 13:21:59 +08:00
RoccoSmit ce6ad4035d fix: limit the size of the resource list viewer (#4210)
Limit the size of the file upload box
2024-12-19 10:32:05 +08:00
Lincoln Nogueira 1c255d4e1f fix: panic on arm v5-v6-v7 builds (#4204)
- upgrade modernc.org/libc to v1.34.2

libc version on go.mod must match upstream's sqlite go.mod file to prevent similar issues.

https://pkg.go.dev/modernc.org/sqlite#hdr-Fragile_modernc_org_libc_dependency

```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGBUS: bus error code=0x2 addr=0x0 pc=0xdd8568]
```
2024-12-16 14:31:58 +08:00
Nikolay ea394d89b2 fix: add server name change in mobile header (#4195)
* [fix] add server name change in  mobile header

* Update web/src/components/MobileHeader.tsx

* Update web/src/components/MobileHeader.tsx

* Apply suggestions from code review

---------

Co-authored-by: Николай Витальевич Никоноров <nnv@bitt.moe>
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2024-12-13 13:23:16 +08:00
johnnyjoy cb569c99fd chore: remove useCallback in fetching memo list 2024-12-07 12:26:21 +08:00
johnnyjoy 5a83f0c4fa chore: update frontend dependencies 2024-12-07 12:22:54 +08:00
johnnyjoy f1d6a6766e chore: revert bump react version 2024-12-07 12:19:55 +08:00
johnnyjoy 0a5111e4b0 chore: update i18n types definition 2024-12-07 12:16:38 +08:00
Johnny 67f8811f3f chore: tweak bug report template 2024-12-07 11:48:02 +08:00
Steven a97154e72d chore: bump react version 2024-12-06 22:16:18 +08:00
dependabot[bot] dd15012661 chore: bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#4164)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:44 +08:00
dependabot[bot] 6e88b4203b chore: bump github.com/google/cel-go from 0.22.0 to 0.22.1 (#4165)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.22.0 to 0.22.1.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.22.0...v0.22.1)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:34 +08:00
dependabot[bot] 6cdc90bc97 chore: bump google.golang.org/protobuf from 1.35.1 to 1.35.2 (#4166)
Bumps google.golang.org/protobuf from 1.35.1 to 1.35.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:24 +08:00
dependabot[bot] d06e67f57c chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.43 to 1.17.46 (#4167)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.43 to 1.17.46.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.43...credentials/v1.17.46)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:10 +08:00
dependabot[bot] 4e99de2692 chore: bump @bufbuild/buf from 1.46.0 to 1.47.2 in /web (#4169)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.46.0 to 1.47.2.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.46.0...v1.47.2)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:59 +08:00
dependabot[bot] edb8db9914 chore: bump @reduxjs/toolkit from 2.3.0 to 2.4.0 in /web (#4170)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:48 +08:00
dependabot[bot] 1e28f7abb5 chore: bump tailwind-merge from 2.5.4 to 2.5.5 in /web (#4171)
Bumps [tailwind-merge](https://github.com/dcastil/tailwind-merge) from 2.5.4 to 2.5.5.
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/compare/v2.5.4...v2.5.5)

---
updated-dependencies:
- dependency-name: tailwind-merge
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:38 +08:00
dependabot[bot] 56c9e94ac4 chore: bump class-variance-authority from 0.7.0 to 0.7.1 in /web (#4172)
Bumps [class-variance-authority](https://github.com/joe-bell/cva) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/joe-bell/cva/releases)
- [Commits](https://github.com/joe-bell/cva/compare/v0.7.0...v0.7.1)

---
updated-dependencies:
- dependency-name: class-variance-authority
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:27 +08:00
dependabot[bot] 790004463b chore: bump less from 4.2.0 to 4.2.1 in /web (#4173)
Bumps [less](https://github.com/less/less.js) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/less/less.js/releases)
- [Changelog](https://github.com/less/less.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/less/less.js/commits)

---
updated-dependencies:
- dependency-name: less
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:16 +08:00
dependabot[bot] 77e4d6f6f1 chore: bump golang.org/x/crypto from 0.28.0 to 0.29.0 (#4168)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:49:13 +08:00
Cheng 2aa3795e50 fix: search conditions affected by pull-to-refresh (#4159) 2024-11-29 22:13:41 +08:00
Query&mut NinjaStyle, &Ryder 009f4956ac fix: check IdP for disallow password auth
* fix #4144 now when there is no sso then the Disallow password auth is disabled

* fixed the import issue

* attempt fixing linting issues

---------

Co-authored-by: pransh62390 <63577123+pransh62390@users.noreply.github.com>
2024-11-29 12:23:17 +08:00
KidLoveToPlay 73d13cb97b chore: style fix to #4151 (#4153)
* chore: apply styles to the correct month

* chore: style fix
2024-11-28 10:23:28 +08:00
KidLoveToPlay 97ef5a8871 chore: apply styles to the correct month (#4151) 2024-11-27 14:00:50 +08:00
Madhur Jodhwani a51e363c7c chore: fix truncation of webhook url to avoid disappearance of Trash Icon (#4145)
* Fixed truncation of webhook url to avoid disappearance of Trash Icon

* fixing webhook truncation issue #4078

* Removing overflow-hidden

* resolving pipeline issues

* supporting on hover url display

---------

Co-authored-by: Madhur <madhur.jodhwani@accelya.com>
2024-11-25 14:19:04 +08:00
RoccoSmit 54ee2bf3ab feat: show less when memo expanded (#4143)
* Added show less action and language files

* Renaming type as suggested in pr review
2024-11-24 22:24:58 +08:00
johnnyjoy 2a1c0bba6c chore: remove unused reaction.proto 2024-11-21 23:08:03 +08:00
JP Hastings-Edrei fcc4abf5b8 feat: remove RSS titles (#4140)
This removes the content of the <title> element in the RSS feeds that Memo produces.

Why remove? Every RSS client I can find shows the <title> next to the <description> when viewing an item. This creates a duplicate (but often trimmed, so less useful) version of <description> right above the actual text the user wants to read (often in a much larger font). It similarly makes lists of items in some clients extremely tall, as 128 characters is a lot of hard-to-read text — especially when Memos renders links as their URL in titles.

Why an empty tag? The RSS 1.0 and 2.0 specs require that a <title> element is present.

Examples from elsewhere:
- micro.blog uses an empty <title /> element: https://www.manton.org/feed.xml
- Bluesky omits the <title> element: https://bsky.app/profile/did%3Aplc%3Aqvzn322kmcvd7xtnips5xaun/rss
- Mastodon omits the <title> element: https://mastodon.social/@scalzi.rss
2024-11-20 22:31:32 +08:00
Steven 51c80c37d1 revert: tweak reaction_type column type for mysql 2024-11-20 20:37:35 +08:00
Steven 9f2c1b2556 chore: tweak reaction_type column type for mysql 2024-11-20 20:35:03 +08:00
Steven 104948ae40 chore: set pull to refresh with screen size 2024-11-20 20:28:49 +08:00
Steven 7b70c203cc chore: buf generate 2024-11-20 20:22:21 +08:00
nlfox 3cbccde67e feat: add pull to refresh for PagedMemoList (#4128) 2024-11-19 23:34:47 +08:00
johnnyjoy 1424036ccd chore: use for...of 2024-11-17 22:04:49 +08:00
Andy An f6af564d4e feat: enhancement on UI/UX on user statistic view part. (#4122)
Enhancement on UI/UX on user statistic view part.
2024-11-17 09:47:41 +08:00
lcdgit f00751a6e0 feat: allow to remove done items (#4126)
* add remove done items

* i18n en add

* bug fix

* add i18n

* Modify the description

* Modify the description

* Modify the description

* remove remove_done_check_items setting

* fix the static checks

* fix the static checks

---------

Co-authored-by: mozhu <lcl_em@163.com>
2024-11-17 09:33:39 +08:00
johnnyjoy 80785de900 chore: remove unused script 2024-11-14 22:12:00 +08:00
Steven 378b6a51c1 chore: tweak default reactions 2024-11-13 08:33:12 +08:00
Steven f007185b8f chore: tweak form styles 2024-11-12 23:23:14 +08:00
RoccoSmit 142e97ab5a feat: navigate image view with keyboard keys (#4116)
* Navigate images with keyboard left and right keys

* Fix linting

* Adding missing "

* Added change to incorrect branch
2024-11-11 08:16:09 +08:00
RoccoSmit bcd8856732 fix: added missing " (#4119)
Added missing "
2024-11-11 08:14:17 +08:00
johnnyjoy 45d4d391d8 fix: air script in windows 2024-11-07 23:34:39 +08:00
johnnyjoy 2f8d347310 Merge branch 'main' of https://github.com/usememos/memos 2024-11-07 23:32:49 +08:00
johnnyjoy b4f9c09d85 chore: upgrade backend dependencies 2024-11-07 23:32:44 +08:00
Steven 5601daef40 chore: add semantic action 2024-11-06 21:15:53 +08:00
Steven ad50aec2db chore: update activity calendar 2024-11-06 21:14:36 +08:00
RoccoSmit 3b25a6bbec fix: handle missing reaction (#4094)
* migration version

* Updated test to match with current version set in version.go file

* updated logic to check if migration should run for fresh install

* Update test to test for version number set in version.go

* fixed test

* Revert "fixed test"

This reverts commit 4004d0e92b.

* Revert "Update test to test for version number set in version.go"

This reverts commit d304add5d6.

* Revert "updated logic to check if migration should run for fresh install"

This reverts commit b44dca2194.

* Revert "Updated test to match with current version set in version.go file"

This reverts commit 3ad0d889b6.

* Revert "migration version"

This reverts commit b13cfc346a.

* Added default reaction if no reation found

* Fixed static check issue

* Use emoji
2024-11-06 21:11:26 +08:00
johnnyjoy 3786fb8db2 chore(dev): add code inspector plugin 2024-11-06 19:28:18 +08:00
Steven 67c1a46346 chore: remove html renderer sanitizes 2024-11-05 22:44:37 +08:00
Steven 57c00734e2 fix: frontend build 2024-11-05 21:15:13 +08:00
Ngô Quốc Đạt e25792be9c chore: update vi translations (#4099) 2024-11-05 15:29:43 +08:00
Steven f5a0827a3f chore: update explore translate of zh-hans 2024-11-04 21:38:34 +08:00
Steven 04c6e262c3 chore: align colors 2024-11-04 21:30:50 +08:00
Simon f310207b9a chore: update i18n Ukrainian (#4096)
* Update uk.json

* Update uk.json
2024-11-04 20:04:20 +08:00
Steven 7b79c49414 chore: remove version tests 2024-11-03 22:55:09 +08:00
Steven b547720aa8 chore: add id to i18n locales 2024-11-03 22:48:39 +08:00
kiraware 3542a79420 feat: add Bahasa Indonesia (id) translation (#4092) 2024-11-03 22:45:49 +08:00
johnnyjoy 227cc26cb9 chore: align table styles for access token section 2024-11-03 20:28:42 +08:00
Steven f59daf839b chore: fix action 2024-11-02 20:00:00 +08:00
Steven ae957439ec chore: update build action 2024-11-02 19:56:07 +08:00
Steven 4b28dfddb6 fix: visibility selector overflow 2024-11-02 13:39:08 +08:00
dependabot[bot] 648db7e82a chore: bump uuid from 10.0.0 to 11.0.2 in /web (#4086)
Bumps [uuid](https://github.com/uuidjs/uuid) from 10.0.0 to 11.0.2.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v10.0.0...v11.0.2)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 11:58:31 +08:00
dependabot[bot] bd4e4b632a chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.25 to 1.17.35 (#4084)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.25 to 1.17.35.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.25...credentials/v1.17.35)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 11:58:17 +08:00
dependabot[bot] a449988a7e chore: bump golang.org/x/crypto from 0.27.0 to 0.28.0 (#4085)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/crypto/compare/v0.27.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:40 +08:00
dependabot[bot] 6be36d268a chore: bump @types/node from 22.8.0 to 22.8.6 in /web (#4087)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.0 to 22.8.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:25 +08:00
dependabot[bot] c1a13be778 chore: bump golang.org/x/net from 0.29.0 to 0.30.0 (#4082)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:08 +08:00
dependabot[bot] d2c4a9e7b6 chore: bump github.com/aws/aws-sdk-go-v2 from 1.31.0 to 1.32.3 (#4083)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.31.0 to 1.32.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.31.0...v1.32.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:58 +08:00
dependabot[bot] bb9b6be19e chore: bump zustand from 4.5.5 to 5.0.1 in /web (#4090)
Bumps [zustand](https://github.com/pmndrs/zustand) from 4.5.5 to 5.0.1.
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v4.5.5...v5.0.1)

---
updated-dependencies:
- dependency-name: zustand
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:39 +08:00
dependabot[bot] 183a22a928 chore: bump @bufbuild/buf from 1.45.0 to 1.46.0 in /web (#4088)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.45.0 to 1.46.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.45.0...v1.46.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:04 +08:00
dependabot[bot] aea814de83 chore: bump @bufbuild/protobuf from 2.2.0 to 2.2.2 in /web (#4089)
Bumps [@bufbuild/protobuf](https://github.com/bufbuild/protobuf-es/tree/HEAD/packages/protobuf) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/bufbuild/protobuf-es/releases)
- [Commits](https://github.com/bufbuild/protobuf-es/commits/v2.2.2/packages/protobuf)

---
updated-dependencies:
- dependency-name: "@bufbuild/protobuf"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:36:27 +08:00
Daniel Pinto f44583e87d chore: allow some hardcoded strings to be translated (#4076)
Allow some hardcoded strings to be translated

Also add pt-PT translation for them
2024-11-02 10:36:11 +08:00
johnnyjoy 9a4fc2e015 chore: buf generate 2024-10-30 21:52:27 +08:00
Steven 67e474d4dd fix: linter warning 2024-10-30 20:19:08 +08:00
Steven c12425329b chore: fix action buttons 2024-10-29 00:18:02 +08:00
Steven db2b34a850 chore: update input source 2024-10-28 22:04:52 +08:00
Daniel Pinto 12bcf65f7d locale: Add pt-PT translations (#4064)
* locale: Add pt-PT translations

* fix str
2024-10-28 09:14:00 +08:00
Steven f373d8e88c chore: update checkbox source 2024-10-27 10:19:06 +08:00
Steven 963706aebd refactor: update button source 2024-10-26 21:36:05 +08:00
Steven 8635aed138 chore: update dependencies 2024-10-25 21:55:00 +08:00
new-aspect aa9649adf0 fix: automatic indentation follows previous lines in lists (#4048) (#4050)
* fix: automatic indentation follows previous lines in lists (#4048)

* fix: automatic indentation follows previous lines in lists (#4048)
change the position of this logic and recommit it
2024-10-25 19:16:59 +08:00
RoccoSmit 2851f11302 fix: use UTC date for calendar filter (#4046) 2024-10-23 22:52:20 +08:00
johnnyjoy 7e48d13834 fix: workspace setting state 2024-10-23 13:46:07 +08:00
Steven 4fcc682a15 chore: add beta badge to relation graph 2024-10-21 20:23:34 +08:00
Steven f9fec56560 chore: fix date picker position 2024-10-20 17:08:01 +08:00
johnnyjoy 2ebf3f2615 chore: fix math styles 2024-10-19 21:40:24 +08:00
johnnyjoy cf1be81de2 feat: use date-picker instead of raw datetime input 2024-10-19 21:30:02 +08:00
johnnyjoy 199d5680e6 chore: update inbox messages style 2024-10-19 21:01:02 +08:00
johnnyjoy 435bd5c44f fix: update relation graph checks 2024-10-19 20:53:53 +08:00
johnnyjoy 04d6329d0f feat: use hash router to sub-setting pages 2024-10-19 20:46:57 +08:00
johnnyjoy 085995ec3d chore: update setting title 2024-10-19 20:32:55 +08:00
johnnyjoy c3cb3770cc chore: tweak function names 2024-10-19 16:13:33 +08:00
johnnyjoy c2e820400e chore: regenerate api docs 2024-10-19 16:13:27 +08:00
d0zingcat 67dc9a3f0a chore: allow quick unpin (#4031)
Signed-off-by: d0zingcat <leewtang@gmail.com>
2024-10-19 16:05:14 +08:00
Matteo Vollero 19098940f7 chore: check currentUser and redirect to index if logged (#4021)
* If to check currentUser and redirect to index if logged

* Moved check into useEffect
2024-10-19 16:04:34 +08:00
d0zingcat e5cb2037e4 feat: allow to disable markdown shortcuts (#4025)
* add settting to disable markdown keymap

Signed-off-by: d0zingcat <leewtang@gmail.com>

* rename disable markdown shortcuts

Signed-off-by: d0zingcat <leewtang@gmail.com>

* fix lint

Signed-off-by: d0zingcat <leewtang@gmail.com>

---------

Signed-off-by: d0zingcat <leewtang@gmail.com>
2024-10-16 23:27:54 +08:00
Steven 009534f1cf chore: fix linter warning 2024-10-16 23:11:34 +08:00
Steven 68c2bd3837 chore: update memo relations 2024-10-16 23:09:20 +08:00
Steven 82da20e1c3 feat: implement graph of relations 2024-10-15 23:31:44 +08:00
Steven 952428c15d chore: update default max height 2024-10-15 20:38:17 +08:00
Steven cfe1765067 chore: tweak user statistics view 2024-10-15 20:30:24 +08:00
Steven c4b52c68b5 fix: max height of memo content compact mode 2024-10-15 20:07:55 +08:00
Steven 317cf06579 chore: tweak demo data 2024-10-14 23:35:19 +08:00
Steven 14712b42fa chore: add pagination to list inboxes 2024-10-14 23:32:39 +08:00
Steven b4d72e3349 fix: memo visibilities with filter 2024-10-14 21:31:44 +08:00
Steven 60a0ead0fa chore: add ka-GE locale 2024-10-14 20:31:45 +08:00
Aleksandre 69e93c1ab4 feat: support Georgian Language (#4016)
Create ge.json

Georgian language
2024-10-14 09:46:48 +08:00
Steven b2f60758bc chore: update workspace setting in demo mode 2024-10-12 09:21:00 +08:00
Steven 74498a726e chore: update package 2024-10-11 21:35:25 +08:00
Steven cab981c393 chore: fix linter errors 2024-10-11 21:27:08 +08:00
Steven 3370ecd4fc chore: ignore lint for tests 2024-10-11 21:22:04 +08:00
Steven 0a871b8960 chore: fix tests 2024-10-11 21:13:36 +08:00
RoccoSmit 35cf975e76 fix: apply system theme dynamically (#4010)
Remove appearance comparison
2024-10-11 21:05:52 +08:00
Steven 43d13a3edc chore: tweak linter 2024-10-11 21:05:07 +08:00
Steven f467f1d9f6 chore: update cron package 2024-10-11 19:59:14 +08:00
Steven 0b6f24a21a chore: update task complete 2024-10-10 23:22:18 +08:00
Steven d066d46f6e chore: tweak schema version 2024-10-10 22:30:46 +08:00
Steven d54c8065b5 chore: update demo data 2024-10-10 22:04:41 +08:00
Steven 2acad978d1 chore(frontend): add reactions setting 2024-10-10 22:04:35 +08:00
Steven e527b6a878 feat: move reaction type to setting 2024-10-10 21:06:32 +08:00
wjsoj 1f9d657065 feat: support set global Default memo visibility (#3989)
* feat: support set global Default memo visibility

* feat: Move to WorkspaceMemoRelatedSetting

* fix: goimports check failure

* chore: change item name to default_visibility

* fix: goimports check failure
2024-10-08 22:45:18 +08:00
Steven dc15e8f30f chore: implement memo metadata store 2024-10-08 22:22:45 +08:00
johnnyjoy 831c254d64 fix: update user fields 2024-10-08 19:52:49 +08:00
Roman 310f147911 feat: allow single letter user id (#3991)
* Allow single letter user id.

They do work - I use one and login using Authelia, but then I am not able to update the profile to update avatar or add comment because "Invalid username: r" errors

* Add test for the util with uid matcher

* Move the test to separate directory

* Use goimports on the test file

* Rename the test for a mroe matching name, add failing test

* Update the regexp so that two letter work

---------

Co-authored-by: Roman Kamyk <roman@kamyk.me>
2024-10-08 13:47:24 +08:00
Steven 0b2f08ad15 fix: memo view 2024-10-07 01:57:37 +08:00
Steven d11e7a3a9a chore: remove duplicated requests 2024-10-07 01:40:15 +08:00
Steven c401a07933 chore: update dependencies 2024-10-02 22:22:21 +08:00
RoccoSmit f0d43c9577 feat: add tag count to tree view (#3970)
* Add tag count to tree view

* Only display tag amounts > 1

* Updated tag amount var name to be more descriptive

* - Moved display logic to html in return
- Updated var names to closer match var passed in by TagSection component
2024-10-02 18:31:50 +08:00
dependabot[bot] 4ab06f5f11 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.22 to 1.17.25 (#3978)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.22 to 1.17.25.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.22...credentials/v1.17.25)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:42 +08:00
dependabot[bot] dab0f1907d chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.36 to 1.27.39 (#3976)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.36 to 1.27.39.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.36...config/v1.27.39)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:33 +08:00
dependabot[bot] e7949d0748 chore: bump vite from 5.4.7 to 5.4.8 in /web (#3981)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.7 to 5.4.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.8/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:16 +08:00
Xavier Hocquet 32123e0c21 feat: add month toggle on hover (#3972)
* Add month toggle on hover

* Lint
2024-10-02 11:37:05 +08:00
dependabot[bot] 4c0c7431c8 chore: bump google.golang.org/grpc from 1.67.0 to 1.67.1 (#3977)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.0 to 1.67.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.0...v1.67.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:36:12 +08:00
dependabot[bot] 25367bc000 chore: bump nice-grpc-web from 3.3.4 to 3.3.5 in /web (#3979)
Bumps [nice-grpc-web](https://github.com/deeplay-io/nice-grpc) from 3.3.4 to 3.3.5.
- [Release notes](https://github.com/deeplay-io/nice-grpc/releases)
- [Commits](https://github.com/deeplay-io/nice-grpc/compare/nice-grpc-web@3.3.4...nice-grpc-web@3.3.5)

---
updated-dependencies:
- dependency-name: nice-grpc-web
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:36:00 +08:00
dependabot[bot] 6cd86c0de1 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.34 to 1.17.37 (#3975)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.34 to 1.17.37.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.34...credentials/v1.17.37)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:35:40 +08:00
dependabot[bot] 508146b052 chore: bump mermaid from 10.9.1 to 11.2.1 in /web (#3980)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 11.2.1.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...mermaid@11.2.1)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:35:28 +08:00
dependabot[bot] 143167386e chore: bump dompurify from 3.1.6 to 3.1.7 in /web (#3982)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.6...3.1.7)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 07:43:34 +08:00
dependabot[bot] 938cfb4a69 chore: bump @types/node from 22.5.5 to 22.7.4 in /web (#3983)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.5 to 22.7.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 07:43:26 +08:00
dependabot[bot] 6965f0b89d chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.63.0 to 1.63.3 (#3974)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.63.0 to 1.63.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.63.0...service/s3/v1.63.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 05:14:26 +08:00
ElTopo 0ba36ed7e0 chore: updated zh-Hans.json from current version of en.json (#3966) 2024-09-30 10:48:36 +08:00
Steven 771a977c9f chore: tweak words 2024-09-29 22:49:29 +08:00
Steven 69ad5178b3 chore: update MaxCallRecvMsgSize 2024-09-29 22:00:15 +08:00
Steven 2b86069f3b chore: update MaxRecvMsgSize 2024-09-29 21:58:06 +08:00
johnnyjoy d5d37c1d59 chore: bump gomark version 2024-09-28 21:55:58 +08:00
Steven cf4e660f41 chore: add memo location setting 2024-09-26 22:11:37 +08:00
Steven 95a50b6596 chore: tweak leaflet map 2024-09-26 22:04:05 +08:00
Steven 9c41c8d5c9 chore: fix marker icon 2024-09-26 09:20:33 +08:00
Steven 2837816ff7 chore: fix component state 2024-09-26 00:27:39 +08:00
Steven b144faf43a feat: add location selector 2024-09-26 00:03:17 +08:00
Steven 63989ab365 feat: add location to memo payload 2024-09-25 21:48:54 +08:00
Steven 92c41458a9 chore: fix release action 2024-09-25 20:03:27 +08:00
Steven a55afbd3ed chore: tweak build actions 2024-09-25 19:57:14 +08:00
boojack 9c4d25cc4d chore: update README.md 2024-09-25 19:47:12 +08:00
Steven 8b444be6ca chore: update tag search 2024-09-23 21:41:23 +08:00
Steven 171a89564e chore: tweak gen apidocs 2024-09-23 08:43:16 +08:00
RoccoSmit 6cbe957db2 fix: show future relative dates (#3946)
Show future relative dates
2024-09-22 22:24:46 +08:00
auphone 0711ac4ecb feat: allow mobile user zooming in image preview (#3880)
* Set viewport scalable in image preview dialog for mobile zooming and reset it on destroy

* Format with prettier

* move setViewportScalable() into useEffect

* use const instead of function
2024-09-22 21:48:01 +08:00
Steven ea881338a9 chore: add gradient block to compact mode 2024-09-22 21:15:46 +08:00
johnnyjoy 7817947f66 fix: clean duplicated requests 2024-09-22 19:51:55 +08:00
johnnyjoy 1f7a90cec4 chore: add spinner to paged memo list 2024-09-22 19:41:27 +08:00
johnnyjoy 339c38750f refactor: paged memo list container 2024-09-22 19:30:39 +08:00
johnnyjoy 41976cb894 feat: update memo endpoints 2024-09-22 15:43:46 +08:00
johnnyjoy c28516b35f chore: buf generate 2024-09-22 13:57:47 +08:00
Steven ca213437e9 feat: implement nesting lists 2024-09-21 20:02:47 +08:00
johnnyjoy 7a4d54bb3c chore: update error messages 2024-09-21 18:23:30 +08:00
johnnyjoy f102aeb9b9 chore: tweak golangci version 2024-09-21 18:10:05 +08:00
johnnyjoy a6de047b64 chore: fix actions 2024-09-21 17:54:51 +08:00
johnnyjoy 9130d981fa chore: fix actions 2024-09-21 17:37:57 +08:00
johnnyjoy b915eaa620 chore: bump dependencies 2024-09-21 17:36:53 +08:00
Johnny a81d7b3260 chore: revert "perf: reduce image size by 21.3MB" (#3942)
Revert "perf: reduce image size by 21.3MB (#3849)"

This reverts commit 0156c7e11f.
2024-09-21 17:33:01 +08:00
johnnyjoy 8cdc956e59 chore: update ts proto 2024-09-21 17:25:57 +08:00
John Regan 46830e31ec buf: specify version of stephenh-ts-proto plugin (#3941) 2024-09-21 07:36:37 +08:00
Sriniwas 2db67118fc fix: case insensetive memo search for postgres (#3938)
fix:case insensetive memo search for postgres #3892
2024-09-19 23:14:51 +08:00
thehijacker f6ebfdf7f9 feat: update Slovenian translation (#3935)
Updated Slovenian translation

Co-authored-by: Andrej Kralj <andrej.kralj@t-2.com>
2024-09-18 16:52:43 +08:00
Steven ec2b59bff5 chore: bump gomark 2024-09-17 20:41:13 +08:00
Steven d663313ca2 chore: fix frontend linter 2024-09-17 19:09:05 +08:00
Steven fbe0251eed feat: impl list renderer 2024-09-17 19:03:10 +08:00
johnnyjoy 759f7c6171 chore: fix workspace setting tests 2024-09-14 08:27:37 +08:00
johnnyjoy 1da0752922 chore: add schema version to workspace setting 2024-09-14 08:23:39 +08:00
Zisu Zhang b787d1c7b6 feat: support disable change username and nickname (#3911)
* feat: support disable change username and nickname

* chore: update UX
2024-09-12 13:45:04 +08:00
ti777777 6f3d5762ca fix: iframe rendering (#3916)
* fix iframe rendering

* fix eslint check
2024-09-12 08:54:33 +08:00
RoccoSmit 42bc769d5d fix: load server name and icon from settings (#3908) 2024-09-10 23:02:48 +08:00
Steven 4790e84b98 chore: use ratio instead of max width 2024-09-09 21:43:47 +08:00
Steven 76a9a343a5 chore: fix linter 2024-09-09 20:36:35 +08:00
RoccoSmit f695e93f20 fix: update first day logic for months starting on Sunday (#3896)
* Update calendar logic to accomodate for months starting on Sunday

* Apply suggestions from code review

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-09-09 09:19:12 +08:00
RoccoSmit 05d5fb4b04 chore: use translations for calendar days (#3895)
Use translations for calendar days
2024-09-08 20:24:59 +08:00
Haohan Yang 044d46c36d chore: replace unmatchedEmailAndPasswordError with unmatchedUsernameAndPasswordError` (#3889)
replace unmatchedEmailAndPasswordError with unmatchedUsernameAndPasswordError
2024-09-07 23:17:20 +08:00
Steven 88db037204 chore: fix linter warnings 2024-09-04 23:31:28 +08:00
Steven 4209575244 chore: tweak folder naming style 2024-09-04 23:29:18 +08:00
onee-only b664653306 test: add test for searching memos by tags (#3876) 2024-09-04 12:14:17 +08:00
Leo 95939ebcf1 fix: v0.22.5: start fail caused by incorrect migration file naming (#3873)
fix incorrect naming of migration file
2024-09-04 06:28:55 +08:00
Steven 9612c302c4 chore: bump version to v0.22.5 2024-09-03 22:17:46 +08:00
Steven 773ab96bd0 chore: update thumbnail generator 2024-09-03 22:09:02 +08:00
johnnyjoy 09586d032c chore: fix user checks 2024-09-03 20:48:23 +08:00
Steven fe01d68d2a fix: user role checks 2024-09-03 08:07:31 +08:00
johnnyjoy 5bbf57ece4 chore: update comments of find memo 2024-09-02 21:27:55 +08:00
johnnyjoy c5ef5b9040 chore: update readme 2024-09-02 21:25:42 +08:00
Johnny 971128af05 revert: chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3870)
Revert "chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3862)"

This reverts commit d13bb7648b.
2024-09-02 21:10:54 +08:00
johnnyjoy 40d59fc47a chore: fix user role checks 2024-09-02 21:04:25 +08:00
johnnyjoy 7a9f61967d feat: allow admin users to update other memos 2024-09-02 20:59:22 +08:00
johnnyjoy 8c6682bd77 chore: regenerate apidocs 2024-09-02 20:50:59 +08:00
dependabot[bot] d13bb7648b chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3862)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 11.0.2.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...mermaid@11.0.2)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 20:46:36 +08:00
dependabot[bot] 0b1ca218ce chore: bump lucide-react from 0.419.0 to 0.437.0 in /web (#3860)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.419.0 to 0.437.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.437.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:54 +08:00
dependabot[bot] 7bce4f5d7b chore: bump @types/react from 18.3.4 to 18.3.5 in /web (#3859)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.4 to 18.3.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:45 +08:00
dependabot[bot] c018af6249 chore: bump @types/node from 22.5.0 to 22.5.2 in /web (#3858)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.0 to 22.5.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:34 +08:00
dependabot[bot] 45d45d0936 chore: bump @bufbuild/buf from 1.38.0 to 1.39.0 in /web (#3861)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.38.0 to 1.39.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.38.0...v1.39.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:18 +08:00
dependabot[bot] 04fad85afe chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.21.0 to 2.22.0 (#3863)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.21.0 to 2.22.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.21.0...v2.22.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:06:52 +08:00
dependabot[bot] a654b12670 chore: bump golang.org/x/mod from 0.19.0 to 0.20.0 (#3864)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.19.0 to 0.20.0.
- [Commits](https://github.com/golang/mod/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:03:01 +08:00
dependabot[bot] 2fac11936b chore: bump golang.org/x/oauth2 from 0.21.0 to 0.22.0 (#3866)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:02:53 +08:00
dependabot[bot] acc6c29d01 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.9 to 1.17.16 (#3867)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.9 to 1.17.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.17.9...credentials/v1.17.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 09:20:36 +08:00
Steven be25fbe185 chore: tweak readme 2024-09-02 09:20:14 +08:00
Steven 4322bfa506 chore: tweak seed data 2024-09-01 22:51:02 +08:00
Steven fa2b01cfb1 chore: tweak latest schema file name 2024-09-01 22:11:15 +08:00
aqyuki 35b0bd82f4 chore: migrate of Docker compose v2 (#3857)
chore: rename docker-compose.yaml and remove deprecated field
2024-09-01 22:08:57 +08:00
RoccoSmit bfe57b9202 chore: set max thumbnail width to home/explore image max width (#3852)
* Set max thumbnail width to timeline img max width

* Prevent images less than thumbnail size from being scaled up

* Apply suggestions from code review

---------

Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2024-08-31 03:37:07 +08:00
aqyuki 0156c7e11f perf: reduce image size by 21.3MB (#3849)
- Change base image to distroless (static-debian12)
- Remove unnecessary RUN instructions
- Add build options
  - add options to delete debug information
  - add options to remobe embedded paths
2024-08-30 19:36:34 +08:00
Steven 960af444fa chore: fix linter 2024-08-30 08:25:06 +08:00
Steven 20570fc771 refactor: resource thumbnail 2024-08-30 08:09:07 +08:00
RoccoSmit 9b1adfbbe9 feat: reintroducing thumbnails (#3821)
* Reintroducing thumbnails

* Aligned with linting rules

* making recomended code review change
- changed method names to start with lower case as they are not used outside of their package
- made receiver types for struct funcs to be pointers to not need to create copies

Trying to cover all linting issues
- converted slog warning to use attributes when logging warnings
- seperated imports to have package files in their own section

* Update go.mod

---------

Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2024-08-29 21:01:57 +08:00
Steven 615aa94793 fix: base path of migrator 2024-08-29 20:40:50 +08:00
Steven 710961d336 chore: fix text color in dark mode 2024-08-29 20:39:24 +08:00
Steven bb86482b71 chore: tweak setting name 2024-08-29 08:28:11 +08:00
Steven f0abd792c7 chore: update auth service 2024-08-29 00:06:15 +08:00
Steven 1167df29d8 feat: add security related settings 2024-08-28 23:46:06 +08:00
Steven 4e5810e205 chore: update workspace setting section 2024-08-28 23:29:30 +08:00
Steven a8ea28066e chore: retire export memos 2024-08-28 23:20:32 +08:00
Steven 9bea6e1eea chore: go mod tidy 2024-08-28 22:56:17 +08:00
Michel Heusschen 2dbf92f7f1 perf: reduce bundle size by 21% with direct icon imports (#3844) 2024-08-28 22:55:28 +08:00
Steven d11bd30ec6 chore: tweak logger 2024-08-28 22:53:57 +08:00
Steven de980fb7d7 chore: update setting display name 2024-08-28 22:44:13 +08:00
Steven cce92f513c chore: tweak readme 2024-08-27 23:44:03 +08:00
Steven 7134ad4883 chore: fix migration history 2024-08-27 09:20:23 +08:00
Steven fbdfaf85d9 chore: update migrator 2024-08-26 22:50:46 +08:00
Steven ccd3fdcd38 chore: fix tests 2024-08-26 08:59:35 +08:00
Steven 70837f88cb chore: fix linter 2024-08-26 08:47:29 +08:00
Steven 525223c261 chore: add tests for migrator 2024-08-26 08:41:26 +08:00
Steven 96b9269cd3 chore: fix golangci linter 2024-08-24 22:38:22 +08:00
Steven 80f9b5b861 chore: fix golangci linter 2024-08-24 22:30:41 +08:00
Steven fb23f43431 chore: update golangci config 2024-08-24 20:39:46 +08:00
RoccoSmit eca9649be3 fix: cancel removes memo cache (#3826)
Clear local storage record of memo changes if chanes to a memo are cancelled
2024-08-24 06:48:16 +08:00
Steven 5f35ac5ca0 chore: update frontend dependencies 2024-08-22 23:38:11 +08:00
Steven b376a20fb4 chore: tweak linter warnings 2024-08-20 08:25:34 +08:00
Steven 2999f472dd chore: fix typo 2024-08-20 08:17:27 +08:00
Steven 45ddd05c42 chore: tweak linter warning 2024-08-20 08:13:52 +08:00
Steven d1280bc04f chore: implement memo property runner 2024-08-20 08:07:48 +08:00
Steven f4d6675363 chore: add enable memo comment setting 2024-08-19 09:13:44 +08:00
Steven 3c5aa41a78 feat: implement week start day setting 2024-08-18 23:18:45 +08:00
Steven 06c460b476 chore: tweak linter warning 2024-08-16 08:15:59 +08:00
Steven 07012e3f60 chore: remove unused files 2024-08-16 08:14:02 +08:00
Steven 1b6685d7cf chore: tweak linter warning 2024-08-16 08:12:09 +08:00
Steven 710d1b304e chore: update dev mode 2024-08-16 08:08:26 +08:00
Steven 6e901fc940 refactor: store migrator 2024-08-16 08:07:30 +08:00
Steven 1ae3afc0ba chore: tweak memo relation popover 2024-08-14 23:15:04 +08:00
Jakub Wołynko 18db78172c feat: add translation for collapse/expand button and update polish locale (#3811)
add: collapse, expand, polish locale
2024-08-14 18:02:02 +08:00
Steven aae3e8ae64 chore: update memo property checks 2024-08-13 23:29:40 +08:00
Steven 506d2ed8ca chore: tweak menu style 2024-08-13 23:28:02 +08:00
Steven c3f381c8c5 chore: add instance url to profile 2024-08-13 22:16:43 +08:00
Steven 9a27fdf855 chore: tweak load more button 2024-08-12 23:52:23 +08:00
Steven fc2cd43dc2 chore: tweak util tests 2024-08-12 23:44:04 +08:00
Mykal Machon c0826c43b0 fix: explicitly disabling autocapitalize and spellcheck (#3797)
fix #3747: removing autocapitalize and spellcheck
2024-08-12 12:24:37 +08:00
Steven 724db203f7 chore: tweak seed data 2024-08-08 23:45:26 +08:00
Steven 04b4fa1d02 chore: tweak icon button container 2024-08-07 22:56:47 +08:00
Steven 61b8cee31d chore: retire preview markdown dialog 2024-08-07 22:48:16 +08:00
Steven 4ad6028681 refactor: use popover instead of dialog for memo relations 2024-08-07 22:44:39 +08:00
tiltshiftfocus a5978e7657 fix: tag query for mysql (#3785) 2024-08-06 13:56:44 +08:00
Steven 158745704e feat: add memo display setting menu 2024-08-03 01:22:40 +08:00
dependabot[bot] 01819610c7 chore: bump modernc.org/sqlite from 1.30.2 to 1.31.1 (#3769)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.2 to 1.31.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.2...v1.31.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:14:15 +08:00
dependabot[bot] bc5e0b5daf chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.8 to 1.17.9 (#3770)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.8 to 1.17.9.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.8...config/v1.17.9)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:14:05 +08:00
dependabot[bot] 4924af5235 chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.20.0 to 2.21.0 (#3771)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.20.0 to 2.21.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.20.0...v2.21.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:55 +08:00
dependabot[bot] 12a9165852 chore: bump react-router-dom from 6.25.1 to 6.26.0 in /web (#3772)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.26.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:44 +08:00
dependabot[bot] 1fcb867e0f chore: bump react-i18next from 14.1.3 to 15.0.0 in /web (#3774)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 14.1.3 to 15.0.0.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v14.1.3...v15.0.0)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:35 +08:00
dependabot[bot] 222e9dfe58 chore: bump @types/node from 20.14.13 to 22.0.2 in /web (#3775)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.13 to 22.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:26 +08:00
dependabot[bot] 55a2e791aa chore: bump lucide-react from 0.399.0 to 0.419.0 in /web (#3773)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.399.0 to 0.419.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.419.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:01:36 +08:00
Steven 21f18f7c56 chore: tweak activity service definition 2024-08-01 23:40:16 +08:00
Steven cc91b1e512 chore: buf generate 2024-08-01 22:03:07 +08:00
Steven 26fa172641 chore(frontend): add order by time asc 2024-07-31 23:51:20 +08:00
Steven 6184375cbb chore: upgrade frontend dependencies 2024-07-31 23:51:00 +08:00
Steven 07667257d5 feat: support order by time asc 2024-07-31 23:34:00 +08:00
Steven ea70dd85bf chore: remove color in manifest 2024-07-31 23:09:13 +08:00
Steven 14194504ee chore: remove unused classnames 2024-07-29 23:12:27 +08:00
Steven 444ccc03ed chore: tweak default title 2024-07-29 23:09:46 +08:00
Noah Alderton 117077ac8f fix: dead link in README.md (#3750) 2024-07-28 17:41:47 +08:00
Steven 342b6ad696 chore: tweak seed data 2024-07-27 22:12:43 -04:00
Steven a948555166 fix: release action 2024-07-27 21:21:09 -04:00
Steven 4870433289 chore: tweak release action 2024-07-27 21:07:15 -04:00
Steven a1083e648f chore: fix resource display time 2024-07-27 20:54:42 -04:00
Steven 4b415e519e chore: tweak demo data 2024-07-28 00:24:16 +08:00
Steven 7564c40c8d chore: fix env init 2024-07-27 23:08:22 +08:00
Steven 8fd5365ac1 chore: tweak linter error 2024-07-27 22:19:53 +08:00
Steven a50f3b9382 chore: fix memos sorting 2024-07-27 22:15:47 +08:00
Steven 5ad00c3a50 chore: fix env binding 2024-07-27 21:57:13 +08:00
Steven 8bf7cdfd31 feat: add password auth flag 2024-07-27 19:24:37 +08:00
Steven b9006f8ce0 chore: tweak date utils 2024-07-27 17:21:22 +08:00
Steven 3d63d9d5fb chore: fix activity stats 2024-07-27 10:11:41 +08:00
Steven 139090fb8f chore: fix calendar timestamps 2024-07-27 09:47:12 +08:00
Steven bdc257d837 chore: tweak release actions 2024-07-26 23:30:16 +08:00
Andrew Williams c9c40bc876 chore: build release containers from tags rather than branches (#3739)
Fixes #3645, currently the release containers are build from the release branches, which are created in preparation for a release. This causes some users with automated CI/CD to either deploy a pre-release version or be notified of a release version before it has actually been released. 

This change switches the workflow to be triggered by tags, which are created on the release version.
2024-07-26 10:36:34 +08:00
Steven edc3b578d6 feat: implement search multi tags 2024-07-26 08:40:40 +08:00
Steven c6a09d9353 chore: update memo filter styles 2024-07-26 08:30:59 +08:00
Steven cd38ec93ed feat: implement memo filters 2024-07-26 00:46:48 +08:00
Steven b3b4aa9ddb chore: remove unused code 2024-07-24 23:53:07 +08:00
Steven c5900b355e chore: tweak signup checks 2024-07-24 23:38:51 +08:00
Steven 553e8d09dd chore: update public default value to false 2024-07-24 23:34:19 +08:00
Steven 22ec0cf2e3 chore: bump version 2024-07-23 22:11:53 +08:00
Steven 44e56844f5 chore: tweak search resources 2024-07-22 15:33:02 +08:00
dependabot[bot] 95fa145665 chore: bump @types/node from 20.14.9 to 20.14.11 in /web (#3726)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.9 to 20.14.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 15:32:35 +08:00
dependabot[bot] 84e2d40481 chore: bump @typescript-eslint/parser from 7.16.0 to 7.16.1 in /web (#3727)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.16.0 to 7.16.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:36 +08:00
dependabot[bot] 582c360787 chore: bump dayjs from 1.11.11 to 1.11.12 in /web (#3728)
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.11 to 1.11.12.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.11...v1.11.12)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:26 +08:00
dependabot[bot] 756470099f chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.7 to 1.17.8 (#3729)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.7 to 1.17.8.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.8/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.7...v1.17.8)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:15 +08:00
dependabot[bot] 0a6d7387d1 chore: bump vite from 5.3.1 to 5.3.4 in /web (#3730)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.1 to 5.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:01 +08:00
dependabot[bot] 511178389b chore: bump eslint-plugin-prettier from 5.1.3 to 5.2.1 in /web (#3731)
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.3 to 5.2.1.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.3...v5.2.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:49 +08:00
dependabot[bot] e5c214ba5c chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.26 to 1.27.27 (#3732)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.26 to 1.27.27.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.26...config/v1.27.27)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:23 +08:00
dependabot[bot] 7e7786077f chore: bump google.golang.org/grpc from 1.64.0 to 1.65.0 (#3733)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.65.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.65.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:11 +08:00
dependabot[bot] 5f58bb368b chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.26 to 1.17.27 (#3734)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.26 to 1.17.27.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.26...credentials/v1.17.27)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 09:57:59 +08:00
Steven c313596144 feat: update memo editor 2024-07-22 09:57:40 +08:00
Johnny d2727e6825 chore: update dependabot schedule interval (#3725) 2024-07-21 20:49:42 +08:00
Steven 10c9bb081b chore: retire timeline page 2024-07-20 00:28:49 +08:00
Steven 17ecfb5cf5 fix: acl config 2024-07-19 20:54:51 +08:00
Steven c4a24bead6 chore(frontend): tweak memo relations 2024-07-19 20:52:52 +08:00
andrigamerita d264f45979 fix: code blocks of unknown languages cause HTML injection (#3711)
* fix: code blocks of unknown languages cause HTML injection

A code block of unknown language (that is, a language not treated as special by Memos and not handled by highlight.js) should fall back on rendering its plaintext content. However, the content is never properly escaped before it is appended to the DOM, and thus any string that happens to contain HTML is unsafely rendered. This commit fixes the issue by ensuring that, when none of the previous cases handle the text, any HTML entities are escaped first.

* Update CodeBlock.tsx to conform to eslint
2024-07-19 08:32:58 +08:00
andrigamerita af952807c7 feat: write memo UID in file names when exporting to Markdown (#3712)
When using the "export to Markdown" feature in Memos, the files included in the ZIP folder don't feature any kind of reference to their alphanumeric UID from the server's database, which completely breaks the point of links inside the files made with the `[[memos/<uid>]]` format, since it's impossible to know which Markdown file this kind of string inside other files refers to.

This pull request modifies the ExportMemos server function, to add the UID of every memo immediately after the date in the filename. For example, an exported memo would now be called: `YYYY-MM-DDThh:mm:ss+hh:mm-AbcDefGhiJklMnoPqrStu1-PUBLIC.md`.
2024-07-19 07:14:31 +08:00
Steven fefe2b0655 chore: fix build artifacts action 2024-07-17 23:16:09 +08:00
Steven 5704aaad08 chore: tweak embeded memo style 2024-07-17 22:48:22 +08:00
Steven ef7e2151dc chore: update memo relation list 2024-07-17 21:40:43 +08:00
Steven e2fd79200e feat: implement inline memo editor 2024-07-17 21:07:36 +08:00
Steven 956f21838d chore: fix popover z-index 2024-07-17 20:28:31 +08:00
Steven 878fea5f13 chore: use popover for update tag view setting 2024-07-17 08:46:52 +08:00
Steven 5a26b76511 chore: add memo content snippet 2024-07-17 08:18:37 +08:00
dependabot[bot] 0053977b14 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.24 to 1.27.26 (#3691)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.24 to 1.27.26.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.24...config/v1.27.26)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:26:20 +08:00
dependabot[bot] e5c7571eb5 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.4 to 1.17.7 (#3690)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.4 to 1.17.7.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.7/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.4...v1.17.7)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:26:06 +08:00
dependabot[bot] daca7193b5 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.24 to 1.17.26 (#3693)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.24 to 1.17.26.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.24...credentials/v1.17.26)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:24:48 +08:00
dependabot[bot] ca1d3b6eb1 chore: bump modernc.org/sqlite from 1.30.1 to 1.30.2 (#3692)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.1 to 1.30.2.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.1...v1.30.2)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:24:34 +08:00
dependabot[bot] fcdca5b270 chore: bump github.com/aws/aws-sdk-go-v2 from 1.30.1 to 1.30.3 (#3694)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.30.1 to 1.30.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.30.1...v1.30.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:46 +08:00
dependabot[bot] 07f79b9f7a chore: bump @mui/joy from 5.0.0-beta.36 to 5.0.0-beta.48 in /web (#3695)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.36 to 5.0.0-beta.48.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:26 +08:00
dependabot[bot] 41d9d3bc21 chore: bump prettier from 3.3.2 to 3.3.3 in /web (#3696)
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.2...3.3.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:01 +08:00
dependabot[bot] fae951ae2b chore: bump @typescript-eslint/eslint-plugin from 7.15.0 to 7.16.0 in /web (#3697)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.15.0 to 7.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:22:44 +08:00
Steven 446e38f15b fix: memo content snippet 2024-07-16 22:19:48 +08:00
dependabot[bot] 7c9f967a07 chore: bump dompurify from 3.1.5 to 3.1.6 in /web (#3698)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.5...3.1.6)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 09:43:40 +08:00
dependabot[bot] a5d36655e9 chore: bump tailwindcss from 3.4.4 to 3.4.5 in /web (#3699)
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.4 to 3.4.5.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.5/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.5)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 09:43:29 +08:00
Steven f2cfc528a6 chore: introduce tag view option 2024-07-15 22:55:59 +08:00
Steven 260a4f89fc chore: buf generate 2024-07-15 22:32:59 +08:00
Johnny 9909fd8a6f feat: add snippet field to memo message (#3689) 2024-07-15 08:08:08 +08:00
Johnny bcb8843245 chore: implement stringify markdown nodes endpoint (#3688) 2024-07-14 20:46:57 +08:00
Johnny 7c9e54afbd chore: update disallow public visibility setting name (#3687) 2024-07-14 20:23:19 +08:00
Steven 6825c1def4 fix: delete access token when sign out 2024-07-13 11:18:29 +08:00
Steven f374169a2b feat: implement html element renderer 2024-07-13 11:06:51 +08:00
Johnny 4ff3b89a8e chore: update i18n from Weblate (#3680)
* Added translation using Weblate (Catalan)

* Translated using Weblate (Catalan)

Currently translated at 25.0% (65 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ca/

* Translated using Weblate (French)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

---------

Co-authored-by: Carles Mateu <carlesm@carlesm.com>
Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-07-12 22:22:59 +08:00
Johnny 5a196e2f1a feat: update gomark version (#3679) 2024-07-12 22:17:03 +08:00
Steven 9449886d60 chore: fix linter 2024-07-12 08:36:55 +08:00
Steven 457cf92cc1 feat(api): implement get resource by uid 2024-07-11 23:43:44 +08:00
Steven 1ab2c89408 feat(api): implement get memo by uid 2024-07-11 23:31:50 +08:00
dependabot[bot] 34e938a1e3 chore: bump typescript from 5.5.2 to 5.5.3 in /web (#3664)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.5.2 to 5.5.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.5.2...v5.5.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 23:00:45 +08:00
dependabot[bot] b265445068 chore: bump golang.org/x/net from 0.26.0 to 0.27.0 (#3669)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:52 +08:00
dependabot[bot] 37d13b5cbc chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.23 to 1.27.24 (#3667)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.23 to 1.27.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.23...config/v1.27.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:45 +08:00
dependabot[bot] fb4fdb326a chore: bump golang.org/x/crypto from 0.24.0 to 0.25.0 (#3668)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/crypto/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:26 +08:00
dependabot[bot] 5623a0f065 chore: bump @typescript-eslint/parser from 7.14.1 to 7.16.0 in /web (#3672)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.14.1 to 7.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:12 +08:00
dependabot[bot] b220f14bec chore: bump katex from 0.16.10 to 0.16.11 in /web (#3663)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.10 to 0.16.11.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.10...v0.16.11)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:03 +08:00
dependabot[bot] 3e4b33fb28 chore: bump highlight.js from 11.9.0 to 11.10.0 in /web (#3665)
Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 11.9.0 to 11.10.0.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/main/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/11.9.0...11.10.0)

---
updated-dependencies:
- dependency-name: highlight.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:13:36 +08:00
dependabot[bot] 08a43d0faa chore: bump @typescript-eslint/eslint-plugin from 7.14.1 to 7.15.0 in /web (#3666)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.14.1 to 7.15.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.15.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:13:24 +08:00
dependabot[bot] 36795abacc chore: bump golang.org/x/mod from 0.18.0 to 0.19.0 (#3670)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/mod/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:12:49 +08:00
dependabot[bot] 9f7295a4ee chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.23 to 1.17.24 (#3671)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.23 to 1.17.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.23...credentials/v1.17.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:12:39 +08:00
Steven 626c972d9c chore: add properties to memo detail sidebar 2024-07-08 23:14:00 +08:00
Johnny 5e3ed201b4 fix: update mask of update memo (#3659) 2024-07-08 08:50:38 +08:00
Johnny eccddb1154 chore: add create time to memo detail sidebar (#3657) 2024-07-07 23:09:48 +08:00
dependabot[bot] a681b8e205 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.21 to 1.27.23 (#3640)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.21 to 1.27.23.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.21...config/v1.27.23)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-06 16:48:24 +08:00
dependabot[bot] 881809926e chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.1 to 1.17.4 (#3649)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.1 to 1.17.4.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.4/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.1...v1.17.4)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-06 16:48:15 +08:00
Johnny a98d16bcaa chore: update bug report template fields (#3656) 2024-07-06 14:16:44 +08:00
dependabot[bot] 46ca5bb8e7 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.21 to 1.17.23 (#3637)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.21 to 1.17.23.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.21...credentials/v1.17.23)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-03 11:44:04 +08:00
dependabot[bot] b1f12d54a0 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.56.1 to 1.57.1 (#3644)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.56.1 to 1.57.1.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.56.1...service/s3/v1.57.1)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 23:15:39 +08:00
Johnny 4d2b953e23 chore: add enable link preview setting to memo related settings (#3647) 2024-07-02 22:00:38 +08:00
dependabot[bot] b57b6bae34 chore: bump postcss from 8.4.38 to 8.4.39 in /web (#3642)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.38 to 8.4.39.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.38...8.4.39)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:51 +08:00
dependabot[bot] 90c67d5592 chore: bump @typescript-eslint/eslint-plugin from 7.13.1 to 7.14.1 in /web (#3641)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.13.1 to 7.14.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.14.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:38 +08:00
dependabot[bot] 4655c99c4e chore: bump @bufbuild/buf from 1.33.0 to 1.34.0 in /web (#3639)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.33.0 to 1.34.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.33.0...v1.34.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:24 +08:00
dependabot[bot] 68e924e48c chore: bump @types/node from 20.14.2 to 20.14.9 in /web (#3638)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.2 to 20.14.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:13 +08:00
dependabot[bot] ee61bc7861 chore: bump react-router-dom from 6.23.1 to 6.24.0 in /web (#3636)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.23.1 to 6.24.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.24.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:02 +08:00
Steven 3782d412f5 chore: upgrade gomark 2024-07-01 23:28:36 +08:00
dependabot[bot] de754079cc chore: bump zustand from 4.5.2 to 4.5.4 in /web (#3632)
Bumps [zustand](https://github.com/pmndrs/zustand) from 4.5.2 to 4.5.4.
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v4.5.2...v4.5.4)

---
updated-dependencies:
- dependency-name: zustand
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:41 +08:00
dependabot[bot] df0dcb553b chore: bump typescript from 5.4.5 to 5.5.2 in /web (#3633)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.5 to 5.5.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.5...v5.5.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:33 +08:00
dependabot[bot] 584d73659e chore: bump @reduxjs/toolkit from 2.2.5 to 2.2.6 in /web (#3634)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.5 to 2.2.6.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.5...v2.2.6)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:22 +08:00
dependabot[bot] 122710801a chore: bump protobufjs from 7.3.0 to 7.3.2 in /web (#3631)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.3.0 to 7.3.2.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.0...protobufjs-v7.3.2)

---
updated-dependencies:
- dependency-name: protobufjs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:24:33 +08:00
Steven 1ad5d9bf0a chore: update confirm dialog 2024-07-01 23:22:39 +08:00
dependabot[bot] 4a3afffeef chore: bump lucide-react from 0.396.0 to 0.399.0 in /web (#3630)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.396.0 to 0.399.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.399.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:13:52 +08:00
Steven 291b815653 feat: implement memo detail sidebar 2024-07-01 23:06:10 +08:00
Steven 05c6edfe2f chore: tweak auth pages 2024-06-26 22:11:18 +08:00
dependabot[bot] 6325b3eef9 chore: bump @types/uuid from 9.0.8 to 10.0.0 in /web (#3616)
Bumps [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid) from 9.0.8 to 10.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/uuid)

---
updated-dependencies:
- dependency-name: "@types/uuid"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:39 +08:00
dependabot[bot] 80c57692e9 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.24 to 1.17.1 (#3617)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.24 to 1.17.1.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.1/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.24...v1.17.1)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:29 +08:00
dependabot[bot] 5828632613 chore: bump @typescript-eslint/parser from 7.13.0 to 7.14.1 in /web (#3620)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.13.0 to 7.14.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.14.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:18 +08:00
Roman Lomonosov b923988fd6 fix: can't change memo UID (#3621) 2024-06-26 07:18:00 +08:00
dependabot[bot] 9b090d909e chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.18 to 1.27.21 (#3612)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.18 to 1.27.21.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.18...config/v1.27.21)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:31:27 +08:00
dependabot[bot] 6abc272709 chore: bump lucide-react from 0.395.0 to 0.396.0 in /web (#3614)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.395.0 to 0.396.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.396.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:31:12 +08:00
dependabot[bot] 3752e7b638 chore: bump eslint-plugin-react from 7.34.2 to 7.34.3 in /web (#3618)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.34.2 to 7.34.3.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.2...v7.34.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:30:56 +08:00
dependabot[bot] 9ba2adb4c4 chore: bump @typescript-eslint/eslint-plugin from 7.13.0 to 7.13.1 in /web (#3619)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.13.0 to 7.13.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:30:39 +08:00
Zeng1998 4f4fe9b26b fix: add charset=utf-8 for text content resources (#3608)
Co-authored-by: = <=>
2024-06-24 23:01:19 +08:00
Johnny ca463891f2 chore: fix linter warning for slog (#3604) 2024-06-22 16:39:40 +08:00
Mudkip e33244e64b fix: PATCH requests on /api/v1 not working (#3600)
* fix: PATCH requests on /api/v1

* Update server/server.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-06-21 18:16:55 +08:00
steven 33cd3ed8e3 chore: bump version 2024-06-21 18:16:35 +08:00
Ryo a09c669865 fix: allow cors for grpc gateway handler (#3574) 2024-06-21 18:13:59 +08:00
dependabot[bot] 759337996f chore: bump lucide-react from 0.383.0 to 0.395.0 in /web (#3584)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.383.0 to 0.395.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.395.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:11:05 +08:00
dependabot[bot] cee1d4b1ed chore: bump @typescript-eslint/eslint-plugin from 7.12.0 to 7.13.0 in /web (#3585)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.12.0 to 7.13.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:51 +08:00
dependabot[bot] 77b92f675a chore: bump @bufbuild/buf from 1.32.2 to 1.33.0 in /web (#3586)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.32.2 to 1.33.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.32.2...v1.33.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:38 +08:00
dependabot[bot] 795700b161 chore: bump vite from 5.2.13 to 5.3.1 in /web (#3587)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.13 to 5.3.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:28 +08:00
dependabot[bot] 513ff9d2b0 chore: bump prettier from 3.3.1 to 3.3.2 in /web (#3588)
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:10 +08:00
dependabot[bot] 84692404e1 chore: bump golang.org/x/oauth2 from 0.20.0 to 0.21.0 (#3583)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.20.0 to 0.21.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:09:34 +08:00
dependabot[bot] d5d0d14728 chore: bump github.com/gorilla/feeds from 1.1.2 to 1.2.0 (#3582)
Bumps [github.com/gorilla/feeds](https://github.com/gorilla/feeds) from 1.1.2 to 1.2.0.
- [Release notes](https://github.com/gorilla/feeds/releases)
- [Commits](https://github.com/gorilla/feeds/compare/v1.1.2...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/gorilla/feeds
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:09:02 +08:00
dependabot[bot] 9bec88eedc chore: bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#3581)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:53 +08:00
dependabot[bot] 1bf6db8154 chore: bump google.golang.org/protobuf from 1.34.1 to 1.34.2 (#3580)
Bumps google.golang.org/protobuf from 1.34.1 to 1.34.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:42 +08:00
dependabot[bot] 5fb649c3c3 chore: bump modernc.org/sqlite from 1.30.0 to 1.30.1 (#3579)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.0 to 1.30.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.0...v1.30.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:30 +08:00
dependabot[bot] b911e98e37 chore: bump docker/build-push-action from 5 to 6 (#3578)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:20 +08:00
Steven 0501f5198a chore: buf format 2024-06-19 22:07:51 +08:00
Johnny 736637a362 feat: add public flag instead of system setting to enable signup (#3589) 2024-06-19 22:03:12 +08:00
Steven 387bf48fc8 chore: update s3 config 2024-06-11 22:05:28 +08:00
dependabot[bot] e9d027ca3e chore: bump @typescript-eslint/parser from 7.12.0 to 7.13.0 in /web (#3558)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.12.0 to 7.13.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 10:48:03 +08:00
dependabot[bot] 0c378ec291 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.21 to 1.16.24 (#3547)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.21 to 1.16.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.21...service/ram/v1.16.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 09:01:47 +08:00
dependabot[bot] 5836bf5a72 chore: bump golang.org/x/net from 0.25.0 to 0.26.0 (#3549)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0.
- [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:43 +08:00
dependabot[bot] 7aba6bef21 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.16 to 1.27.18 (#3550)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.16 to 1.27.18.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.16...config/v1.27.18)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:32 +08:00
dependabot[bot] f31a53caa7 chore: bump uuid from 9.0.1 to 10.0.0 in /web (#3556)
Bumps [uuid](https://github.com/uuidjs/uuid) from 9.0.1 to 10.0.0.
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.1...v10.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:08 +08:00
dependabot[bot] 28624514d1 chore: bump goreleaser/goreleaser-action from 5 to 6 (#3551)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 5 to 6.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:35:09 +08:00
dependabot[bot] b42979edcc chore: bump golang.org/x/mod from 0.17.0 to 0.18.0 (#3548)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/mod/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:34:45 +08:00
dependabot[bot] bc1b095812 chore: bump github.com/aws/aws-sdk-go-v2 from 1.27.0 to 1.27.2 (#3546)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.27.0 to 1.27.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.27.0...v1.27.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:34:24 +08:00
Ryo 2c819ace4e feat: return not found error instead internal error for local file not exist (#3543)
* chore: add `/.vscode` to `.gitignore`

* feat: return not found instead of internal for resource

* feat: check file not exist only if error not nil
2024-06-10 14:11:28 +08:00
andrigamerita e4a09c407c feat: write memo visibility in file names when exporting (#3538)
When using the dedicated feature in Memos' user settings to export all memos to Markdown files inside a ZIP folder, the output doesn't feature any kind of distinction for memos by their set visibility.
While this is not a big issue for personal backups, it can reveal itself problematic if exporting the data to share it with other people, or maybe deploy to a static site generator, because there is nothing in the files that distinguishes public memos from private or workspace-restricted ones.

This pull request simply modifies the ExportMemos server function, to add the Visibility status to the end of every exported file name inside the ZIP, right after the date (which is left intact). For example, the file for a public memo would now be called: `YYYY-MM-DDThh:mm:ss+hh:mm-PUBLIC.md`.

An alternative solution would have been to write this information in a YAML header at the beginning of every Markdown file, but, since those are not used anywhere else in the software, I decided to stick with what is already used for export metadata, the filename.
2024-06-09 19:22:13 +08:00
Steven da603053f2 chore: add th locale 2024-06-09 07:46:03 +08:00
boojack edda6ea4bd chore: update i18n with Weblate (#3540)
* Added translation using Weblate (Thai)

* Translated using Weblate (Thai)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/th/

---------

Co-authored-by: NeneNeko <lennon.rin@gmail.com>
2024-06-09 07:43:59 +08:00
boojack 7b7ecc2daa chore: update i18n with Weblate (#3533)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Yuri <isyuricunha@duck.com>
2024-06-07 05:10:12 +08:00
Steven fa4521e0c5 chore: update gomark source 2024-06-06 23:09:13 +08:00
Steven 076aa2f8aa chore: remove memo filter 2024-06-05 23:18:14 +08:00
Steven f33571fec6 feat: update webhook request payload 2024-06-05 20:53:20 +08:00
Steven d159975994 chore: update statistics view 2024-06-05 20:46:35 +08:00
Martin MacDonald aec5927d31 feat: add hook for generating different date times (#3524)
* Added hook for generating different date times

* Fixed up logic to destructure the datetime params

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 19:52:07 +08:00
Steven 7375b87967 chore: tweak tooltips 2024-06-05 08:51:04 +08:00
Steven 54539aa047 chore: tweak seed data 2024-06-05 08:48:46 +08:00
Steven d0ac866eb1 chore: update statistics view 2024-06-05 08:48:40 +08:00
Steven 797f5a123c feat: add HasIncompleteTasks to memo property 2024-06-05 08:39:56 +08:00
Martin MacDonald f0817f2762 chore: update fetch tags args (#3515)
* Centralised the logic for filters to apply to tagging and updated components to pass in those params needed

* Fixed linting issue

* Split out params from options

* Fixed linting errors

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:06:01 +08:00
Martin MacDonald 2ebd5c64bd fix: copy by reference (#3517)
* Fixed issue with copy by reference

* Fixed linting issues

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:04:50 +08:00
Martin MacDonald 0977acbc7f fix: update uniqby key (#3518)
* Used correct uniqby key

* Put back filter

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:03:56 +08:00
Steven e8ed437ca3 fix: purify html before render 2024-06-04 23:10:54 +08:00
Steven 2b49025f4a chore: update memo filters 2024-06-04 23:03:51 +08:00
Steven bddfe00b5c chore: bump version 2024-06-04 20:51:53 +08:00
dependabot[bot] aafddac65f chore: bump modernc.org/sqlite from 1.29.10 to 1.30.0 (#3510)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.10 to 1.30.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.10...v1.30.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-04 07:18:07 +08:00
dependabot[bot] b4113581b3 chore: bump github.com/spf13/viper from 1.18.2 to 1.19.0 (#3511)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.2 to 1.19.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.2...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-04 07:17:40 +08:00
Steven e40b39033f chore: fix compact default value 2024-06-04 07:17:16 +08:00
Michael 616f306efe chore: update i18n with Weblate (#3509)
* Translated using Weblate (French)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: ti777777 <ti12272198686@yahoo.com.tw>
2024-06-03 23:57:59 +08:00
Steven 370ac32344 chore: regenerate pnpm-local.yaml 2024-06-03 23:51:29 +08:00
Steven 20b8a97a88 chore: retire outdate scripts 2024-06-03 23:50:59 +08:00
dependabot[bot] be6fc1ca4d chore: bump lucide-react from 0.378.0 to 0.383.0 in /web (#3507)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.378.0 to 0.383.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.383.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 23:40:00 +08:00
dependabot[bot] c41d53b4b6 chore: bump @types/node from 20.12.12 to 20.14.0 in /web (#3504)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.12 to 20.14.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 23:38:03 +08:00
Martin MacDonald 760dee4159 feat: delete memo comments when memo is deleted (#3491)
* Added logic to delete memo relation and memo comments recursively when a memo is deleted

* Fixed logic to only target comment types and added removing of broken references

* Fixed linting errors

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-03 19:50:13 +08:00
Steven 08d37acffa chore: tweak readme 2024-06-02 14:31:54 +08:00
Michael c484b09c4c chore: update i18n with Weblate (#3499)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-06-02 14:06:05 +08:00
Steven 2e0d5412b4 chore: tweak webhook payload 2024-06-01 23:46:00 +08:00
Steven 8c0bee3840 chore: tweak refresh button 2024-06-01 23:27:35 +08:00
Steven 78f6064530 chore: tweak goreleaser action 2024-06-01 10:04:39 +08:00
Steven d7be24a0e1 chore: tweak goreleaser 2024-06-01 09:59:52 +08:00
Steven 5493f5f14e chore: regenerate dependencies 2024-06-01 09:58:47 +08:00
Steven 1dc686fa6c chore: update build artifacts 2024-06-01 09:49:47 +08:00
Steven 4e54ec38ff chore: update memo related settings 2024-06-01 09:05:09 +08:00
Steven 0657a1ef5b chore: fix memo editor cache 2024-06-01 08:48:54 +08:00
Michael 48546f05b3 chore: update i18n with Weblate (#3492)
* Translated using Weblate (Turkish)

Currently translated at 100.0% (259 of 259 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (259 of 259 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Apply suggestions from code review

---------

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-06-01 08:42:01 +08:00
Steven 08a9291964 chore: update timeline filters 2024-05-31 09:06:03 +08:00
Steven 98f2cf6397 chore: tweak linter 2024-05-30 07:23:16 +08:00
Steven b1cc1255bb chore: tweak seed data 2024-05-30 07:21:10 +08:00
Steven b215426623 chore: update general setting 2024-05-30 07:19:38 +08:00
Steven 423861d48c fix: create idp in postgres 2024-05-29 23:22:20 +08:00
Michael f2b708c1b8 chore: update i18n with Weblate (#3483)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (257 of 257 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (257 of 257 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Ramazan SANCAR <ramazansancar4545@gmail.com>
2024-05-29 23:20:11 +08:00
Steven 0f4b7c5f4a feat: add more memo settings 2024-05-29 23:17:53 +08:00
Steven 1894ef161f chore: fix content search 2024-05-29 22:04:37 +08:00
Michael 98eb57b370 chore: update translation files (#3481)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-29 08:05:14 +08:00
Steven cf70867470 chore: update tag section 2024-05-29 08:03:01 +08:00
Steven 719c22fef8 chore: update i18n 2024-05-29 07:39:16 +08:00
Steven 6010139291 chore: remove unused 2024-05-29 07:36:51 +08:00
Steven cbf556fee5 chore: fix memo cache key 2024-05-28 23:23:23 +08:00
Steven 93e848d170 chore: tweak root redirector 2024-05-28 19:59:29 +08:00
Steven 60b5b4815d chore: fix imports 2024-05-28 09:10:08 +08:00
dependabot[bot] 98bd4568e7 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.20 to 1.16.21 (#3469)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.20 to 1.16.21.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.20...service/ram/v1.16.21)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:07:42 +08:00
dependabot[bot] c24225fd89 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.54.2 to 1.54.3 (#3471)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.54.2 to 1.54.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.54.2...service/s3/v1.54.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:06:53 +08:00
dependabot[bot] 5ea04ca596 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.15 to 1.27.16 (#3472)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.15 to 1.27.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.15...config/v1.27.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:06:45 +08:00
Steven 0275a65781 chore: add last visited page 2024-05-28 09:05:59 +08:00
dependabot[bot] 239f28c1e0 chore: bump @vitejs/plugin-react from 4.2.1 to 4.3.0 in /web (#3467)
Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/v4.3.0/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 06:07:43 +08:00
dependabot[bot] f78114da43 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.15 to 1.17.16 (#3468)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.15 to 1.17.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.15...credentials/v1.17.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:37:05 +08:00
dependabot[bot] 75e76e1331 chore: bump @types/react from 18.3.2 to 18.3.3 in /web (#3466)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.2 to 18.3.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:53 +08:00
dependabot[bot] 9f83be1d48 chore: bump @typescript-eslint/parser from 7.9.0 to 7.10.0 in /web (#3465)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.9.0 to 7.10.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.10.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:43 +08:00
dependabot[bot] 250bdff4c5 chore: bump @bufbuild/buf from 1.32.0 to 1.32.1 in /web (#3464)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.32.0 to 1.32.1.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.32.0...v1.32.1)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:33 +08:00
dependabot[bot] b8d4720e5e chore: bump i18next from 23.11.4 to 23.11.5 in /web (#3463)
Bumps [i18next](https://github.com/i18next/i18next) from 23.11.4 to 23.11.5.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.11.4...v23.11.5)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:24 +08:00
dependabot[bot] 3e11adc15b chore: bump modernc.org/sqlite from 1.29.9 to 1.29.10 (#3470)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.9 to 1.29.10.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.9...v1.29.10)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:09 +08:00
Steven e475f00ba1 chore: tweak seed data 2024-05-27 23:32:08 +08:00
Steven f0e5a72271 feat: update search memo filter 2024-05-27 23:25:25 +08:00
Steven ba0876a563 feat: update statistics view 2024-05-27 20:04:07 +08:00
Steven a423dac12c chore: tweak memo property 2024-05-27 19:43:57 +08:00
Steven 2b4c2b23b2 chore: tweak linter 2024-05-26 21:39:34 +08:00
Ryo 784fcbb698 feat: add panic recovery middleware for grpc and echo server (#3459) 2024-05-26 21:38:59 +08:00
Steven 1ccfa81cf3 chore: tweak common function 2024-05-26 11:02:23 +08:00
Steven a177800e83 chore: tweak error message 2024-05-25 11:05:35 +08:00
Steven d39cacf1f9 chore: tweak readme 2024-05-25 11:01:54 +08:00
Michael 8233a6ba1c chore: translated using Weblate (Marathi) (#3451)
Translated using Weblate (Marathi)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/mr/

Co-authored-by: quaintdev <accounts@rohanrd.xyz>
2024-05-25 05:44:20 +08:00
quaintdev af71ac49bb feat(i18n): added marathi(mr) translations (#3449) 2024-05-25 05:43:37 +08:00
Steven 7d6dbb9487 fix: link hover handler 2024-05-22 23:25:04 +08:00
Steven 4070998f9f chore: fix linter 2024-05-22 21:55:13 +08:00
Steven d3235f75f3 chore: tweak memo definition 2024-05-22 21:52:41 +08:00
Steven e0600388b2 chore: implement memo property endpoint 2024-05-22 09:21:12 +08:00
Steven 16d3de63c2 chore: update resource binary endpoint 2024-05-21 21:25:21 +08:00
Michael 2c50d3469e chore: update i18n with weblate (#3435)
* Translated using Weblate (Ukrainian)

Currently translated at 58.0% (148 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 58.0% (148 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/uk/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: Gregory Malets <gregory.malets@gmail.com>
2024-05-21 20:36:28 +08:00
Steven b5d2ff6e28 chore: fix linter 2024-05-21 00:08:57 +08:00
dependabot[bot] 3616194d03 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.17 to 1.16.20 (#3415)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.17 to 1.16.20.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.17...service/ram/v1.16.20)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:04:02 +08:00
Steven 811c0757c4 chore: fix linter 2024-05-21 00:03:30 +08:00
dependabot[bot] 464b00ea0b chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.53.2 to 1.54.2 (#3416)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.53.2 to 1.54.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.53.2...service/s3/v1.54.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:02:17 +08:00
dependabot[bot] a1e610fd8e chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.19.1 to 2.20.0 (#3417)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.19.1 to 2.20.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.19.1...v2.20.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:02:08 +08:00
dependabot[bot] e813853624 chore: bump google.golang.org/grpc from 1.63.2 to 1.64.0 (#3418)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.63.2 to 1.64.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.63.2...v1.64.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:52 +08:00
dependabot[bot] b2f9496c96 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.13 to 1.27.15 (#3414)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.13 to 1.27.15.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.13...config/v1.27.15)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:27 +08:00
dependabot[bot] f1392e220e chore: bump @typescript-eslint/parser from 7.8.0 to 7.9.0 in /web (#3423)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.8.0 to 7.9.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.9.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:06 +08:00
Steven f37b34544b chore: update user access token checks 2024-05-20 22:32:42 +08:00
Steven f54b05a521 chore: tweak comments 2024-05-20 22:15:51 +08:00
Steven 613c9e9416 chore: tweak version 2024-05-20 21:10:04 +08:00
Steven fb15386db2 chore: remove access token after sign out 2024-05-20 08:53:29 +08:00
Steven 21838d0aae chore: fix editor autocomplete 2024-05-20 08:49:55 +08:00
Timothy 52ebfd703c fix: update resource with id (#3405)
* chore: update presign expires

* fix: update resource with id

---------

Co-authored-by: timothy <timothy123890511@gmail.com>
2024-05-19 23:18:03 +08:00
Michael 8f6d38719f chore: update i18n from Weblate (#3399)
* Added translation using Weblate (Marathi)

* Translated using Weblate (Marathi)

Currently translated at 22.7% (58 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/mr/

---------

Co-authored-by: quaintdev <accounts@rohanrd.xyz>
2024-05-19 09:16:13 +08:00
Steven 93d06bc0f0 chore: tweak readme 2024-05-19 09:15:46 +08:00
Steven c25c57ab61 feat: support updating display time 2024-05-18 07:52:35 +08:00
Steven b0aad6f694 chore: tweak resource payload 2024-05-17 08:50:02 +08:00
Steven 0c251f9ab8 chore: fix resource delete handler 2024-05-16 21:53:12 +08:00
wzc90 0a9212f815 fix: memo find for mysql(#3387)
* Update memo.go

* Update store/db/mysql/memo.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-05-16 07:37:42 +08:00
Steven 537ae622d2 chore: filter inbox type 2024-05-15 23:22:23 +08:00
Steven 3e5e5b1f80 chore: fix search memos 2024-05-15 22:42:31 +08:00
wzc90 3ecbbf31a9 fix: migration scripts for mysql (#3384) 2024-05-15 17:34:59 +08:00
wzc90 deb1deb14c fix: resource create time format for mysql (#3381) 2024-05-15 15:51:43 +08:00
Steven c8ff3fa2ee chore: fix uploading flag 2024-05-15 09:08:34 +08:00
dependabot[bot] f67676ac43 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.15 to 1.16.17 (#3367)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.15 to 1.16.17.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.16.15...service/ram/v1.16.17)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:48:46 +08:00
dependabot[bot] 38c6c50681 chore: bump golangci/golangci-lint-action from 5 to 6 (#3365)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5 to 6.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:44 +08:00
dependabot[bot] 74e0f5429a chore: bump pnpm/action-setup from 3.0.0 to 4.0.0 (#3366)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v3.0.0...v4.0.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:35 +08:00
dependabot[bot] 3add70714f chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.53.1 to 1.53.2 (#3369)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.53.1 to 1.53.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.53.1...service/s3/v1.53.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:28 +08:00
dependabot[bot] 78f0ae649a chore: bump golang.org/x/net from 0.24.0 to 0.25.0 (#3370)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/net/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 08:12:52 +08:00
Steven 9265b8e2bd chore: update tags filter 2024-05-14 08:12:25 +08:00
Steven 2317204c50 fix: list idp 2024-05-14 07:04:17 +08:00
dependabot[bot] 32abc50af4 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.11 to 1.27.13 (#3371) 2024-05-14 06:45:14 +08:00
Steven 0c673d49ef chore: retire memo tags 2024-05-13 22:12:56 +08:00
Steven d3744ccfa3 chore: tweak seed data 2024-05-13 22:07:44 +08:00
Steven c561362d62 feat: implement memo property 2024-05-13 22:04:37 +08:00
Steven 555b4fbe32 chore: update seed data 2024-05-13 20:27:24 +08:00
Steven 8948edf654 chore: impl memo payload definition 2024-05-13 20:24:11 +08:00
Steven 31e07c083d chore: fix types 2024-05-13 20:07:56 +08:00
Steven b8763905ba chore: tweak naming 2024-05-13 20:03:04 +08:00
Michael 62705fed39 chore: translated using Weblate (French) (#3358)
Translated using Weblate (French)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-05-13 10:18:33 +08:00
Michael 6df3cf808e chore: update seed data 2024-05-13 10:15:30 +08:00
Michael 6c481743de chore: translated using Weblate (Turkish) (#3356)
Translated using Weblate (Turkish)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-05-13 08:10:15 +08:00
Steven 83b9ea45b9 chore: tweak dark mode styles 2024-05-13 08:09:32 +08:00
Steven f79554371d chore: retire share dialog 2024-05-13 07:57:58 +08:00
Steven eda1983964 chore: return workspace setting with default value 2024-05-12 13:32:26 +08:00
Steven cf423026a5 chore: update store cache 2024-05-12 13:19:31 +08:00
Leo LI 93e8fa4912 fix: upgrade scripts for mysql
* Fix mysql db migration

* Update store/db/mysql/migration/prod/0.22/01__memo_tags.sql

* Update store/db/mysql/migration/prod/0.22/02__memo_payload.sql

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-05-12 12:34:21 +08:00
Steven bb076ce486 chore: update list workspace settings 2024-05-12 08:09:14 +08:00
Steven cf7718f8dc chore: update presign expires 2024-05-12 08:03:56 +08:00
Steven 29a22914cf fix: postgres upgrade script 2024-05-11 22:35:26 +08:00
Steven 087f60ba7b chore: fix user setting key checks 2024-05-11 21:14:21 +08:00
wzc90 d4157bcffa fix: upgrade scripts (#3347) 2024-05-11 17:43:13 +08:00
Michael ee984a8872 chore: translated using Weblate (Chinese (Simplified)) (#3345)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Coisini-H <2972186196@qq.com>
2024-05-11 16:00:33 +08:00
wzc90 80df8f8aed fix: upgrade scripts (#3344) 2024-05-11 15:38:14 +08:00
Michael a15025303b chore: update i18n with Weblate (#3339)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 99.6% (254 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-05-11 08:15:40 +08:00
Lincoln Nogueira f45f673aec chore: respect supplied listening address (#3338) 2024-05-11 06:50:22 +08:00
Steven f30599fbd2 chore: fix scripts 2024-05-10 23:23:15 +08:00
Steven 041f9b1beb chore: bump version 2024-05-10 23:02:57 +08:00
boojack 3fbc4d8539 feat: implement drag and drop for resource order in editor (#3337)
* Implement drag and drop for resource order in editor

* chore: update

* chore: update

* chore: update
2024-05-10 20:34:35 +08:00
Steven 5f207c8f0c fix: math overflow 2024-05-10 06:21:47 +08:00
Michael fe5a0fe98a chore: update i18n with Weblate (#3335)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-09 22:40:27 +08:00
Steven 584c669068 chore: tweak max width 2024-05-09 22:10:27 +08:00
Steven 46a085f8df chore: add datepicker to timeline 2024-05-09 20:31:37 +08:00
Steven e7a788fa71 chore: tweak memo detail page 2024-05-09 20:10:13 +08:00
Steven 942052b1ea chore: update grpc options 2024-05-09 20:08:18 +08:00
Steven deae53c1f1 chore: add dayjs to fix datetime format in safari 2024-05-09 08:52:34 +08:00
Steven 1d99dad435 feat: update timeline page 2024-05-09 07:56:00 +08:00
Steven 33133ea1a3 chore: tweak searchbar styles 2024-05-08 22:50:13 +08:00
Steven a4235bb4bf chore: tweak tags style 2024-05-08 22:31:22 +08:00
Steven e0977e53f7 chore: remove unused route 2024-05-08 22:15:29 +08:00
Michael 4e12744811 chore: update translation files (#3332)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-08 21:35:19 +08:00
Steven 40a5503d45 chore: tweak i18n locales 2024-05-08 21:33:49 +08:00
Steven 16670b6b8d chore: tweak seed data 2024-05-08 20:08:53 +08:00
Michael d57e7d5a0b chore: update translation files (#3331)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-08 20:06:05 +08:00
Steven f7f4206fa1 chore: fix linter 2024-05-08 20:05:16 +08:00
Steven 292861be16 chore: retire tag store 2024-05-08 20:03:18 +08:00
Steven d0655ece53 refactor: update memo tags 2024-05-08 20:03:01 +08:00
Steven 2c270438ec chore: update default service config 2024-05-08 06:57:53 +08:00
Jerwin Arnado a9caecf479 fix: Set max height to 50vh for better viewing for larger screens. (#3330)
Feature: Set max height to 50vh for better viewing for larger screens.
2024-05-07 23:19:20 +08:00
Steven d355e2c631 chore: tweak tags section 2024-05-07 22:11:46 +08:00
Steven 4950ea1c74 fix: grpc max message size 2024-05-07 22:10:27 +08:00
Steven f9258e41a0 chore: tweak max width 2024-05-07 22:10:08 +08:00
steven e16546f80a chore: handle legacy workspace setting 2024-05-07 22:07:44 +08:00
dependabot[bot] a73f979f96 chore: bump lucide-react from 0.368.0 to 0.378.0 in /web (#3313)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.368.0 to 0.378.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.378.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:35 +08:00
dependabot[bot] 41549a6951 chore: bump @types/node from 20.12.9 to 20.12.10 in /web (#3323)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.9 to 20.12.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:18 +08:00
dependabot[bot] 1e8346290c chore: bump @mui/joy from 5.0.0-beta.32 to 5.0.0-beta.36 in /web (#3317)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.32 to 5.0.0-beta.36.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:06 +08:00
dependabot[bot] 6a2701ee83 chore: bump react-redux from 9.1.1 to 9.1.2 in /web (#3316) 2024-05-07 05:11:26 +08:00
dependabot[bot] 68fcf250a0 chore: bump google.golang.org/protobuf from 1.33.0 to 1.34.1 (#3318) 2024-05-07 05:11:15 +08:00
dependabot[bot] 5aaf0b88fd chore: bump golang.org/x/oauth2 from 0.19.0 to 0.20.0 (#3319) 2024-05-07 05:11:04 +08:00
dependabot[bot] f9b0a2b693 chore: bump golang.org/x/crypto from 0.22.0 to 0.23.0 (#3320) 2024-05-07 05:10:52 +08:00
dependabot[bot] bf07a2cfe6 chore: bump modernc.org/sqlite from 1.29.8 to 1.29.9 (#3321) 2024-05-07 05:10:40 +08:00
Steven 776664105a chore: tweak content length limit 2024-05-06 19:12:30 +08:00
Michael b0ecb72eaa chore: translated using Weblate (Hungarian) (#3312)
Translated using Weblate (Hungarian)

Currently translated at 98.6% (299 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

Co-authored-by: Vermunds <33235701+Vermunds@users.noreply.github.com>
2024-05-06 08:03:52 +08:00
Steven af1ad2f2db chore: add memo content length limit setting 2024-05-06 08:02:39 +08:00
Nabiel Omar Syarif 56ceba2dec fix: fix deleting tag from tag lists (#3311) 2024-05-06 07:38:15 +08:00
Steven e32a585bbf chore: update resource dashboard 2024-05-06 07:37:48 +08:00
Steven dfc0889a4f chore: tweak package name 2024-05-06 07:18:54 +08:00
Michael da535c8dc6 chore: translated using Weblate (Chinese (Simplified)) (#3307)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Sung Kim <1740603900@qq.com>
2024-05-04 11:52:26 +08:00
Steven 10c57167cc chore: remove unused flags 2024-05-03 07:16:07 +08:00
Steven 5742f9ca13 fix: seed data 2024-05-03 07:02:08 +08:00
Steven e9831caca1 chore: remove unused field 2024-05-02 22:21:49 +08:00
Steven b23b6302de chore: tweak linter 2024-05-02 22:10:50 +08:00
Steven 74145157a0 chore: add presign background service 2024-05-02 22:08:45 +08:00
Steven 05f73a2236 chore: tweak linter 2024-05-02 21:46:47 +08:00
Steven 775b79338d chore: update object in s3 2024-05-02 21:44:17 +08:00
Steven 26545c855c refactor: implement s3 storage 2024-05-02 21:28:06 +08:00
Michael 355ea352aa chore: translated using Weblate (Chinese (Traditional)) (#3304)
Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (303 of 303 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (303 of 303 strings)


Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/
Translation: memos-i18n/i18n

Co-authored-by: Yuri <isyuricunha@duck.com>
2024-05-02 20:23:12 +08:00
Steven 144269fbbc chore: fix router 2024-05-01 12:44:18 +08:00
Steven 590b626052 chore: update upload resources button 2024-05-01 10:43:09 +08:00
Steven 832ad92bac chore: update gitignore 2024-05-01 10:31:26 +08:00
Steven 20dd3e17f7 chore: rename router package 2024-05-01 10:28:32 +08:00
Steven 8ae4bc95dc chore: migrate auth package 2024-05-01 10:26:46 +08:00
Steven ff175bbb7e refactor: update resource binary request handler 2024-05-01 10:23:56 +08:00
Steven 6d3d71df30 chore: update frontend dependencies 2024-04-30 22:27:20 +08:00
Steven d668794c7c chore: update build docker image actions 2024-04-30 22:21:46 +08:00
Steven 33f52320f7 fix: remove lazy import components 2024-04-30 22:06:47 +08:00
Steven 6295979592 chore: add user avatar route 2024-04-30 22:06:34 +08:00
Michael cac6f42770 fix: server matchs 2024-04-30 10:18:04 +08:00
dependabot[bot] 00f1773495 chore: bump golangci/golangci-lint-action from 4 to 5 (#3298)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-29 23:28:15 +08:00
Steven 8a3845ff54 chore: remove external resource dialog 2024-04-29 22:57:47 +08:00
Steven 155c5baf2c refactor: add markdown service 2024-04-29 08:00:37 +08:00
Steven 4338234641 chore: retire storage related functions 2024-04-28 21:50:09 +08:00
Steven 320963098f refactor: update storage setting 2024-04-28 21:36:22 +08:00
Steven f25c7d9b24 fix: serve frontend assets 2024-04-28 08:36:33 +08:00
Steven d8aeec993c chore: replace classnames with clsx 2024-04-28 00:58:40 +08:00
Steven 1b291422e7 refactor: api version 2024-04-28 00:44:29 +08:00
Steven 8bba7f706e chore: update IME mode checks 2024-04-28 00:12:44 +08:00
Steven f9942002f9 chore: fix linter 2024-04-27 23:36:57 +08:00
Steven 92872118b9 refactor: tweak api definition 2024-04-27 23:14:58 +08:00
Steven 9b66ef5e26 chore: tweak api definition 2024-04-27 22:02:15 +08:00
Steven 04c78e180c chore: update buf dependencies 2024-04-27 00:37:45 +08:00
Michael cc2370e01e chore: update i18n with Weblate (#3287)
* Translated using Weblate (Japanese)

Currently translated at 91.0% (276 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: mirukupc <mirukupc.jp@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-27 00:32:58 +08:00
Steven 7217605831 chore: update gitignore 2024-04-27 00:26:04 +08:00
Steven a6a62eb79c chore: update gitignore 2024-04-27 00:25:47 +08:00
Steven 5f26c52b49 feat: add goreleaser 2024-04-27 00:22:27 +08:00
Steven 647602beac chore: update link preview 2024-04-25 21:01:13 +08:00
Steven 81d24f32a7 fix: memo comment keys 2024-04-25 09:10:11 +08:00
SkyWT 9bcd4f59a2 fix: editor IME composing event behavior (#3267)
* fix: editor IME composing event behavior

* fix: editor IME composing event behavior

* Update web/src/components/MemoEditor/hooks/useAutoComplete.ts

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-04-25 08:59:26 +08:00
Steven 205bf7ed0e chore: update link target 2024-04-24 22:02:11 +08:00
Steven cdcb61da17 chore: fix update storage 2024-04-24 09:18:33 +08:00
Michael 7f9af9b12c chore: translated using Weblate (French) (#3272)
Translated using Weblate (French)

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Alexis <alexisl61@outlook.fr>
2024-04-24 06:22:57 +08:00
dependabot[bot] 6b253247cb chore: bump modernc.org/sqlite from 1.29.7 to 1.29.8 (#3266)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.7 to 1.29.8.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.7...v1.29.8)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 10:04:10 +08:00
Michael 761b4e115b chore: translated using Weblate (English) (#3259)
Translated using Weblate (English)

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

Co-authored-by: noxonad <noxonad@proton.me>
2024-04-22 10:11:30 +08:00
Nabiel Omar Syarif 16f209eada fix: specify go toolchain in go.mod (fix #3252) (#3253) 2024-04-22 10:06:33 +08:00
刘明野 06a79a2e37 fix: tag dependencies (#3251)
fix: 修改tag名称后重新请求数据
2024-04-20 21:16:17 +08:00
Michael 330cc3dc89 chore: translated using Weblate (French) (#3249)
Translated using Weblate (French)

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Alexis <alexisl61@outlook.fr>
2024-04-19 08:58:39 +08:00
Steven e8dfd579c3 chore: update background services 2024-04-18 23:34:35 +08:00
Steven 2a93b8d720 chore: tweak linter 2024-04-18 21:44:46 +08:00
Steven 5d967f41d9 chore: update server 2024-04-18 21:41:00 +08:00
Steven 339fecbfff chore: allow search comments 2024-04-18 21:04:10 +08:00
Steven 2cdcd17ba3 chore: tweak linter 2024-04-17 09:00:16 +08:00
Steven 14d4cfd5a4 chore: tweak store methods name 2024-04-17 08:56:52 +08:00
Michael 00d25b12c1 chore: translated using Weblate (Russian) (#3245)
Translated using Weblate (Russian)

Currently translated at 90.4% (274 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

Co-authored-by: sergeybutakov <pushkagun@gmail.com>
2024-04-16 22:38:20 +08:00
Steven 95df647265 chore: tweak comments 2024-04-16 22:33:25 +08:00
Steven f52e0e005a chore: update dependencies 2024-04-16 21:28:40 +08:00
Steven 70f3d131f6 chore: update pnpm version 2024-04-16 21:22:40 +08:00
Steven f7f139d65a chore: tweak typo 2024-04-16 21:15:17 +08:00
coderwander 162521885c chore: fix some typos in comments (#3243)
Signed-off-by: coderwander <770732124@qq.com>
2024-04-16 21:14:38 +08:00
dependabot[bot] b0b9513de7 chore: bump @types/react from 18.2.75 to 18.2.79 in /web (#3240)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.75 to 18.2.79.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:36:03 +08:00
dependabot[bot] f221f9bfe9 chore: bump i18next from 23.11.1 to 23.11.2 in /web (#3235)
Bumps [i18next](https://github.com/i18next/i18next) from 23.11.1 to 23.11.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.11.1...v23.11.2)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:40 +08:00
dependabot[bot] e831fa8190 chore: bump react-redux from 9.1.0 to 9.1.1 in /web (#3234)
Bumps [react-redux](https://github.com/reduxjs/react-redux) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/reduxjs/react-redux/releases)
- [Changelog](https://github.com/reduxjs/react-redux/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reduxjs/react-redux/compare/v9.1.0...v9.1.1)

---
updated-dependencies:
- dependency-name: react-redux
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:23 +08:00
dependabot[bot] eae0b7115b chore: bump @types/react-dom from 18.2.24 to 18.2.25 in /web (#3233)
Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 18.2.24 to 18.2.25.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:01 +08:00
dependabot[bot] 1f0fffda95 chore: bump lucide-react from 0.367.0 to 0.368.0 in /web (#3232)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.367.0 to 0.368.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.368.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:07:49 +08:00
Michael 404751f378 chore: update i18n with Weblate (#3230)
* Translated using Weblate (Turkish)

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-15 11:19:52 +08:00
Steven f9dd29ae07 chore: tweak tag store 2024-04-14 22:20:09 +08:00
Steven 1f0bfd2169 chore: update tag store 2024-04-14 22:03:56 +08:00
Michael 4aa72306ff chore: update i18n with Weblate (#3227)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (308 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (307 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-04-14 21:27:55 +08:00
Eng Zer Jun 3b550a8ab8 chore: replace util.Min helper with built-in min (#3224) 2024-04-13 20:16:22 +08:00
Steven cb7886dc49 chore: retire telegram integration in frontend 2024-04-13 12:42:34 +08:00
Steven d00e4fdf17 chore: retire telegram plugin 2024-04-13 12:39:41 +08:00
Steven 9a2c423435 chore: update var-naming 2024-04-13 12:11:59 +08:00
Steven 49f8cfd5d1 chore: update jwt middleware 2024-04-13 12:10:57 +08:00
Steven b27004daae chore: retire unused plugin 2024-04-13 12:09:32 +08:00
Steven 75359854cc chore: fix resource routes 2024-04-13 12:07:53 +08:00
Steven cebc46adc7 chore: tweak store definition 2024-04-13 11:54:37 +08:00
Steven 6ee3b0f704 chore: go mod tidy 2024-04-13 11:02:29 +08:00
Steven bbd206e893 chore: retire legacy api 2024-04-13 11:01:16 +08:00
Steven cf4db17080 chore: fix linter 2024-04-13 10:53:39 +08:00
Steven c373131b89 chore: migrate idp service 2024-04-13 10:50:25 +08:00
Steven a77703260f chore: fix linter 2024-04-13 02:57:32 +08:00
Steven 8f51529c78 chore: implement storage service 2024-04-13 02:55:40 +08:00
Steven 707e5caf89 chore: update workspace setting store 2024-04-13 02:08:35 +08:00
Michael 17e8fc5408 chore: update i18n with Weblate (#3220)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 98.0% (302 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 98.0% (302 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
2024-04-12 22:45:12 +08:00
Steven 074e7cf71a chore: fix resource path 2024-04-12 08:57:34 +08:00
Steven f5461264c5 chore: fix dialog background color 2024-04-12 08:44:19 +08:00
Michael e2ae32063e chore: translated using Weblate (Turkish) (#3215)
Translated using Weblate (Turkish)

Currently translated at 100.0% (300 of 300 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-04-12 08:36:38 +08:00
Steven 133951328b chore: fix linter 2024-04-12 08:36:02 +08:00
imikod 257b8add8c chore: localization improvements (#3213)
* localization improvements

* typo fix

* fix linting error
2024-04-12 08:35:14 +08:00
Steven 755d5b83c6 chore: retire legacy setting api 2024-04-12 08:32:54 +08:00
Steven 3088cabe10 chore: tweak linter 2024-04-11 17:58:49 +08:00
Steven 3e6e56b008 refactor: update workspace store definition 2024-04-11 17:53:00 +08:00
Steven 6d842711e2 chore: fix dependencies 2024-04-10 23:34:29 +08:00
dependabot[bot] b84a0592bb chore: bump react-i18next from 11.18.6 to 14.1.0 in /web (#3210)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 11.18.6 to 14.1.0.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v11.18.6...v14.1.0)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:28:11 +08:00
dependabot[bot] 581a64d5c1 chore: bump lucide-react from 0.309.0 to 0.367.0 in /web (#3208)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.309.0 to 0.367.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.367.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:27:34 +08:00
dependabot[bot] 4537411109 chore: bump @typescript-eslint/eslint-plugin from 6.21.0 to 7.0.0 in /web (#3207)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.21.0 to 7.0.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.0.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:53 +08:00
dependabot[bot] d6b1326a2d chore: bump eslint-config-prettier from 8.10.0 to 9.1.0 in /web (#3206)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.10.0 to 9.1.0.
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.10.0...v9.1.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:36 +08:00
dependabot[bot] 9490e890c7 chore: bump i18next from 21.10.0 to 23.11.1 in /web (#3205)
Bumps [i18next](https://github.com/i18next/i18next) from 21.10.0 to 23.11.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v21.10.0...v23.11.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:22 +08:00
dependabot[bot] aed76165ea chore: bump @reduxjs/toolkit from 1.9.7 to 2.2.3 in /web (#3204)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 1.9.7 to 2.2.3.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v1.9.7...v2.2.3)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:11 +08:00
dependabot[bot] 51a90b0013 chore: bump golangci/golangci-lint-action from 3 to 4 (#3203)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3 to 4.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:25:53 +08:00
dependabot[bot] 7b1fe9fcfc chore: bump pnpm/action-setup from 2.4.0 to 3.0.0 (#3202)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2.4.0 to 3.0.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2.4.0...v3.0.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:25:42 +08:00
Steven ec67f1b3c9 chore: add dependabot 2024-04-10 23:24:17 +08:00
Steven 97cfab1758 chore: upgrade dependencies 2024-04-10 23:19:59 +08:00
Steven eb251a097e chore: update workspace setting service 2024-04-10 23:01:01 +08:00
Steven 4c47e93fce chore: tweak workspace setting store 2024-04-10 22:31:55 +08:00
Michael af954db473 chore: update i18n with Weblate (#3201)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
2024-04-10 22:05:31 +08:00
Steven a376dc4dd6 chore: fix linter 2024-04-10 22:04:02 +08:00
Dubzer 8ee56bd29f feat: add code wrapping option on mobile devices (#3196)
* feat: add code wrapping option on mobile devices

* Minor changes

* oopsie
2024-04-10 22:03:47 +08:00
Steven 71c39ed554 chore: update workspace setting definition 2024-04-10 21:15:55 +08:00
Steven c93b1efbae chore: update workspace setting store 2024-04-10 20:05:17 +08:00
Steven 58ae3217ff chore: update auth callback messages 2024-04-09 21:23:17 +08:00
Steven 6028838f03 chore: update component name 2024-04-09 20:51:09 +08:00
Michael 000b3a7a2c chore: update i18n with weblate (#3195)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-04-09 20:29:26 +08:00
Steven bbdd40b2b0 chore: add placeholder to comment editor 2024-04-09 20:01:19 +08:00
imikod 8356ebc46b chore: improve localization (#3190)
* improve localization

* follow suggestion
2024-04-09 16:11:32 +08:00
Steven fc95876617 chore: update memo creator display 2024-04-09 09:05:34 +08:00
Steven b1e196bb4f fix: delete memo reaction 2024-04-08 20:52:46 +08:00
Steven 6d10251cbd feat: impl list syntax auto complete to editor 2024-04-08 20:42:53 +08:00
Steven 436a6cb084 chore: fix text truncate 2024-04-08 19:20:16 +08:00
imikod 90ed908d2e fix: set navigation icons to not shrink (#3186) 2024-04-08 10:16:52 +08:00
Steven 756ab71302 chore: tweak truncate styles 2024-04-07 23:30:28 +08:00
Steven a6b09aa5b1 chore: add confirm dialog for disable password login setting 2024-04-07 23:22:59 +08:00
Steven ff81ea602d chore: tweak error message 2024-04-07 22:35:02 +08:00
Steven 8101a5e0b1 chore: add origin flag to config cors 2024-04-07 22:15:15 +08:00
Michael b5893aa60b chore: update i18n with Weblate (#3183)
* Translated using Weblate (French)

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-04-07 10:13:12 +08:00
Steven bedf3b3025 chore: tweak embedded memo styles 2024-04-02 23:32:43 +08:00
The Anh Nguyen 09ffa7b818 chore: fix memo link (#3173) 2024-04-02 07:13:58 +08:00
Steven ba7dbc1fca chore: fix task node click handler 2024-04-01 21:38:18 +08:00
Steven 15ef57589e chore: go mod tidy 2024-04-01 21:35:58 +08:00
stayweek 5aa633948e chore: use the built-in slices library (#3172)
Signed-off-by: stayweek <jiangtengtao@outlook.com>
2024-04-01 17:16:29 +08:00
Steven b1297f5d01 chore: tweak linter 2024-04-01 00:41:25 +08:00
Steven 33e9b13665 chore: tweak linter 2024-04-01 00:34:51 +08:00
Steven b79f626a74 chore: fix memo comment inbox 2024-04-01 00:26:46 +08:00
Michael ec35a42fb5 chore: update i18n with Weblate (#3168)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (290 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-01 00:07:03 +08:00
Michael 98c9ab70e2 chore: update translation files (#3166)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-30 22:54:38 +08:00
Steven edc7645086 chore: fix linter 2024-03-30 15:01:19 +08:00
Steven cbebbca7d6 chore: add idp definition 2024-03-30 14:58:47 +08:00
Steven 4d62ed46cc chore: tweak words 2024-03-30 14:14:42 +08:00
Steven bb10bb200c chore: implement search random memos 2024-03-30 13:50:18 +08:00
Steven 03c93785f4 chore: implement list random users 2024-03-30 13:29:48 +08:00
The Anh Nguyen 2fe6d606ec feat: handle restore memo when is in archived memo detail page (#3165) 2024-03-30 13:06:08 +08:00
Steven c8baeb86ec chore: fix memo links 2024-03-30 13:04:40 +08:00
The Anh Nguyen 9a88e00df0 fix: link embedded content to uid instead of name (#3164) 2024-03-30 12:30:09 +08:00
Steven 54a3c25ebd chore: update memo resource name definition 2024-03-30 08:26:28 +08:00
Steven d84a88e805 chore: fix linter 2024-03-30 00:05:19 +08:00
Steven 5ab845d92e chore: fix linter 2024-03-30 00:02:34 +08:00
Steven 4f7a6cd6cc chore: fix default logo url 2024-03-29 23:12:30 +08:00
Steven c7aaf791e6 chore: tweak props naming 2024-03-29 22:49:19 +08:00
Michael 239348c403 chore: update i18n with Weblate (#3162)
* Translated using Weblate (Russian)

Currently translated at 85.1% (252 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

* Translated using Weblate (Vietnamese)

Currently translated at 91.8% (272 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/vi/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: The Anh Nguyen <anhntdev0@gmail.com>
2024-03-29 21:32:55 +08:00
Michael 9f803aa9bb chore: translated using Weblate (Russian) (#3161)
Translated using Weblate (Russian)

Currently translated at 85.1% (252 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

Co-authored-by: xyznetsov <invisiblesun2016@yandex.ru>
2024-03-29 21:29:49 +08:00
Steven 200a0d3e2b fix: memo relations 2024-03-29 21:27:38 +08:00
Steven ea6628066d chore: update sidebar components 2024-03-29 09:16:55 +08:00
Steven 526f46807e chore: tweak user list display 2024-03-29 08:37:07 +08:00
Michael bfaf06582c chore: translated using Weblate (Portuguese (Brazil)) (#3157)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (296 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-29 08:20:56 +08:00
Steven 7331c598df fix: edit account dialog fields 2024-03-29 08:19:32 +08:00
The Anh Nguyen f7a445ac8b chore: update Vietnamese translation (#3155) 2024-03-29 08:07:02 +08:00
Steven 90679cc33a chore: add explore sidebar 2024-03-29 00:01:45 +08:00
Steven 192ee7acc0 chore: fix memo link 2024-03-28 22:53:22 +08:00
Michael 7d94256a2a chore: update i18n with Weblate (#3152)
* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-03-28 22:51:50 +08:00
Michael aed4c1392d chore: update i18n with Weblate (#3151)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (296 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
2024-03-28 22:48:32 +08:00
Paul 3605efc4d1 chore: removed sanitization logic (#3147)
* removed sanitization logic

* to avoid lint err
2024-03-28 22:44:44 +08:00
Dubzer a0846c2818 feat: add shortcut to edit the previous memo (#3122)
* Add shortcut to edit the previous memo

* Fix compilation

* Update web/src/components/MemoEditor/index.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-03-27 21:46:29 +08:00
Steven 2ebea4dba9 chore: fix workspace profile api 2024-03-27 18:51:11 +08:00
Steven 16cfef32d6 chore: tweak statistics translation 2024-03-26 23:49:37 +08:00
Steven f637deacfc chore: tweak tag list 2024-03-26 23:43:31 +08:00
Steven a07805907b chore: fix action run 2024-03-26 22:46:17 +08:00
Steven 2e87da4927 chore: update frontend dependencies 2024-03-26 22:35:11 +08:00
Steven d460e6bf41 fix: link node 2024-03-25 23:59:19 +08:00
Steven e703b4f70d fix: resource v1 definition 2024-03-24 22:35:10 +08:00
Steven be525fa3df chore: fix migration script 2024-03-23 01:03:11 +08:00
Steven d1e8af48c0 chore: tweak memo view styles 2024-03-23 00:58:15 +08:00
Steven 005305cd9a chore: update relative time display 2024-03-22 08:12:08 +08:00
Steven 8fd1dff484 chore: update migration scripts 2024-03-21 22:24:39 +08:00
Steven c5fa4fe304 chore: tweak imports order 2024-03-21 21:44:43 +08:00
Steven 8f37d7490c chore: fix linter 2024-03-21 21:42:44 +08:00
Steven 18d16abdb5 chore: update workspace service 2024-03-21 21:39:34 +08:00
Steven 1d83c68cb5 chore: update type definitions 2024-03-21 08:12:38 +08:00
Michael 861a1e4c9b chore: update i18n with Weblate (#3115)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
2024-03-20 21:42:08 +08:00
Steven 26e5b70483 chore: upgrade frontend dependencies 2024-03-20 21:32:06 +08:00
Steven 7c5261b5d2 chore: tweak resource definition 2024-03-20 21:17:04 +08:00
Steven 7cc8b951a3 refactor: update resource id naming 2024-03-20 20:39:16 +08:00
Steven a3a4e37cb0 chore: update memo content styles 2024-03-20 09:07:54 +08:00
Steven 76c936357b chore: fix resource link 2024-03-20 08:51:32 +08:00
Steven 6db427e396 chore: update acl list 2024-03-20 08:18:43 +08:00
Steven 0a0ccbf6e1 chore: update acl list 2024-03-20 08:12:46 +08:00
Steven 96a7d0eb25 chore: tweak line height 2024-03-20 00:40:46 +08:00
Steven ed89cb8310 chore: update memo relation definition 2024-03-19 21:53:44 +08:00
Steven 722e356044 chore: update memo store 2024-03-19 20:55:33 +08:00
Steven efb15a0453 chore: tweak naming 2024-03-18 23:41:57 +08:00
Steven 5f2d6b22be chore: tweak memo structure 2024-03-18 23:23:53 +08:00
Steven 2dc8ed773c chore: tweak linter 2024-03-18 19:57:53 +08:00
Steven 86db6d0254 chore: tweak user api definition 2024-03-18 12:56:52 +08:00
Steven f3fb5e0c60 chore: tweak route enum 2024-03-18 12:07:44 +08:00
Steven 1e43c8d84b chore: disallow update workspace setting in demo mode 2024-03-17 19:18:45 +08:00
Steven cf207df672 chore: tweak link styles 2024-03-17 18:28:37 +08:00
Michael 5dd1251d1e chore: update i18n with Weblate (#3109)
* Translated using Weblate (Japanese)

Currently translated at 95.2% (279 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-17 18:22:22 +08:00
sunxunle ea104a5e54 chore: fix typo (#3106) 2024-03-17 09:52:04 +08:00
Steven 335a0312f2 chore: tweak link styles 2024-03-16 23:35:36 +08:00
Mehad Nadeem 9c1e2f8137 feat: implemented link previews (frontend files) (#3074)
* feat: implmented link previews (frontend files)

* chore: updated frontend side for Link Previews

* chore: updated frontend gen types with the renamed (server) service file

* fix: passing errors

* chore: switched to using generated type instead of separate fields

* fix: passing linter error

* chore: updated Link.tsx

* chore: using `useResponsiveWidth` to render for different devices

* chore: refactored Link.tsx
2024-03-16 22:51:16 +08:00
Steven 14479347d8 chore: remove demo checks 2024-03-15 09:05:02 +08:00
Steven 0f48cfbb4e chore: tweak padding styles 2024-03-15 08:52:11 +08:00
Steven 606a30640d fix: check username in signup 2024-03-15 08:37:58 +08:00
Steven ab136e3310 chore: tweak styles 2024-03-15 00:12:22 +08:00
Michael 21af2a004d chore: translated using Weblate (French) (#3099)
Translated using Weblate (French)

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-03-14 17:09:29 +08:00
Steven 115b5551b3 chore: tweak default avatar 2024-03-14 09:11:57 +08:00
Steven 15be18fa85 chore: update compace mode handler 2024-03-14 09:07:18 +08:00
Steven 9ce381abb9 chore: tweak user profile 2024-03-14 00:13:56 +08:00
Steven 2516431b20 chore: tweak memo content styles 2024-03-14 00:01:33 +08:00
Steven ded4da07a3 feat: use @github/relative-time-element to display time 2024-03-13 23:47:34 +08:00
Steven e795149186 chore: tweak memo view display 2024-03-13 22:30:59 +08:00
Steven 8fe6874b1b chore: add description field to user 2024-03-13 21:24:16 +08:00
boojack 7c1510e7a9 chore: update i18n with Weblate (#3090)
* Translated using Weblate (Spanish)

Currently translated at 95.4% (293 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/es/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Hisiste <aditooliva@gmail.com>
Co-authored-by: keocheung <keocheung@outlook.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-13 20:55:04 +08:00
Steven e5fc107920 chore: tweak i18n locales 2024-03-13 20:51:19 +08:00
Steven 5d740c3813 chore: update link service 2024-03-13 20:25:27 +08:00
Mehad Nadeem 0abe20df72 feat: implemented link previews (server files) (#3073)
* feat: implmented link previews (server files)

* chore: updated variable name

* chore: renamed service file from `metadata_service.go` to `link_service.go`

* fix: passing errors

* fix: fixed linter warnong about `ctx`
2024-03-13 17:31:53 +08:00
Mehad Nadeem 4d41b68d4c feat: implemented link previews (proto files) (#3072)
* feat: implmented link previews (proto files)

* fix: passing proto linter errors

* chore: renamed MetadataService service in proto file.

* fix: removed unused files

* chore: removed meaningless comments from proto file
2024-03-13 16:52:59 +08:00
Lincoln Nogueira 7c87c1ff74 chore: update build scripts (#3085) 2024-03-13 08:50:56 +08:00
Steven 963c630428 chore: update readme with weblate 2024-03-13 08:25:38 +08:00
Steven 6b6edc3791 chore: update tg message handler 2024-03-12 22:48:53 +08:00
Mario Gómez 425e85f0f9 chore: fix spanish typos (#3083) 2024-03-12 21:48:02 +08:00
huajin tong 8e7f826ae6 chore: fix typo (#3080)
Signed-off-by: thirdkeyword <fliterdashen@gmail.com>
2024-03-12 17:05:49 +08:00
Michael 9ffc1515f4 chore: update i18n with Weblate (#3079)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Matsuri <matsuri@vmoe.info>
Co-authored-by: keocheung <keocheung@outlook.com>
2024-03-12 13:14:56 +08:00
steven 8cdc0c7ffa chore: add delete tag action 2024-03-09 17:26:58 +08:00
zty 999a05307e fix: body overflow styles #3056
Co-authored-by: zty <zty.dev@outlook.com>
2024-03-09 14:09:31 +08:00
steven ed1954c58c chore: fix check setting value 2024-03-09 12:56:44 +08:00
steven 77bafba682 chore: update gomark.wasm 2024-03-09 12:47:20 +08:00
Michael 1540de2f44 chore: translated using Weblate (Korean) (#3060)
Translated using Weblate (Korean)

Currently translated at 95.1% (292 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

Co-authored-by: WonSeok <wonseok@duck.com>
2024-03-09 12:40:42 +08:00
Steven ed4b48c54f chore: update gomark.wasm 2024-03-08 00:34:34 +08:00
Michael 706e749275 chore: translated using Weblate (Portuguese (Brazil)) (#3050)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-07 11:38:24 +08:00
Steven 845999292a chore: update frontend dependencies 2024-03-06 23:33:00 +08:00
Michael 240da335c1 chore(i18n): update translation files (#3042)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-05 11:44:51 +08:00
Steven f9f277695d chore: fix comment amount 2024-03-04 23:37:38 +08:00
Dubzer 6cbfbe9c07 chore: settings page improvements (#3034)
* Don't allow to select text on buttons in settings + refactoring

* Remove redundant useMemo

* Update web/src/pages/Setting.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Rename other constants too

* Rename AdminSection to ADMIN_SECTIONS

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-03-04 23:33:43 +08:00
Steven ec206104e5 chore: tweak i18n locale 2024-03-04 23:23:14 +08:00
Steven 342f341b3d chore: ignore import locale error 2024-03-04 13:16:55 +08:00
WonSeok f46b64a17d fix: check disallow public memo in Telegram(#3036) (#3037) 2024-03-04 11:24:09 +08:00
Steven 7d5f603482 chore: update compact view 2024-03-04 11:21:48 +08:00
Dubzer f0a521f5b8 feat: improve theming (#3032)
Add color-scheme and dark scrollbar styles
2024-03-04 09:35:40 +08:00
Steven 59314cdf80 chore: add compact mode to memo view 2024-03-04 01:11:34 +08:00
Steven ac0315334d chore: update i18n locales imports 2024-03-04 00:05:27 +08:00
Steven ac8a374ebd chore: bump version 2024-03-03 23:45:52 +08:00
Steven 95b02341eb chore: tweak logger 2024-03-03 23:45:32 +08:00
Steven d34273b186 chore: update memo icons style 2024-03-03 16:41:03 +08:00
Steven dcfb2b7de2 chore: tweak docs generate path 2024-03-03 15:05:42 +08:00
Steven ebcf43c997 chore: update gomark.wasm 2024-03-03 14:56:40 +08:00
Steven cfb50f19aa chore: tweak linter 2024-03-03 14:23:21 +08:00
Steven e441e3882b chore: update error logger 2024-03-03 14:20:59 +08:00
Steven c1da87a819 chore: update get request origin 2024-03-03 14:10:48 +08:00
jjaychen 3b089eeae3 fix: ignore "Tab" key down event when is composing in editor(#3026) (#3027) 2024-03-03 13:04:00 +08:00
Steven 9a8a1d017e chore: add comments icon 2024-03-02 11:29:21 +08:00
Steven 7e23ceb242 chore: fix frontend linter 2024-03-01 19:39:24 +08:00
Steven 898b3c3779 chore: update gomark.wasm 2024-03-01 19:31:00 +08:00
Steven 8eb01adb6f chore: go mod tidy 2024-02-29 23:56:20 +08:00
jg0312 621a8d4e20 chore: fix typo in build script's if statement (#3017)
missing 'i' in 'if' statement
2024-02-29 23:55:25 +08:00
Steven dfa78cac49 chore: update logger 2024-02-29 23:54:43 +08:00
Steven 12f4d3a10d chore: tweak default page size 2024-02-29 23:42:06 +08:00
Steven 00788bd8f8 chore: update actions 2024-02-29 09:21:55 +08:00
Steven 5f2a624c0c chore: tweak imports order 2024-02-29 01:32:59 +08:00
Steven 3e50bee7da chore: move api directory 2024-02-29 01:16:43 +08:00
Steven 1aa75847d6 chore: upgrade gomark 2024-02-29 01:07:53 +08:00
Steven 89a270cede chore: add username to cache key 2024-02-28 00:34:55 +08:00
Xylit 5526355621 fix: dark mode tag selection and suggestion (#3004)
* fix: use correct higlight color on selecting a tag in darkmode

* fix: take scrolling into account in tab suggestion

Issue: When editing a long memo and editing a tag somewhere where the user has
to scroll down to, the tag suggestions would be out of place (too far down)
because the scrolling wouldn't be taken into account.

Fix: Substract the suggestions div by the scroll amount.

* fix: don't show tag suggestion when on '#'

Fixes this issue like this:
1. Text #tag text
        ^ backspace here
2. Text#tag text
       ^ space
3. Text #tag text
        ^ tag suggestion opens
2024-02-27 09:16:56 +08:00
ercd 1ae9bf23a0 fix: telegram callback query handler dereferencing nil pointer if memo not found (#3003)
* fix: telegram callback query handler dereferencing nil pointer if memo not found

* chore: add an answer to callback query if memo not found
2024-02-27 00:03:08 +08:00
Zhiyuan Zheng 51a7934616 fix: firefox/safari to redirect to /explore in HomeLayout (#3001) 2024-02-26 13:38:24 +08:00
Mr. Lin 8d08cfe1c9 fix: incorrectly checking whether registration is allowed in the login v1 api (#2998)
fix: Incorrectly checking whether registration is allowed in the login interface, resulting in the inability to log in through apiv1
2024-02-26 13:36:17 +08:00
Steven b0f52ade7a chore: remove metric service 2024-02-24 23:32:39 +08:00
Steven 222d04fb22 chore: add fuse to get tag suggestions 2024-02-24 11:02:46 +08:00
Steven 68468927dd chore: tweak setting styles 2024-02-24 11:01:57 +08:00
Steven dfe29ec766 chore: tweak route layout 2024-02-24 10:18:53 +08:00
Steven db56e1b575 chore: fix user banner dropdown 2024-02-23 23:47:26 +08:00
Steven 5b92ac1775 chore: fix setting migrator 2024-02-23 09:16:34 +08:00
Steven f2eb9f1b8f chore: fix get workspace setting 2024-02-23 09:11:39 +08:00
Steven e602aeecc1 fix: update workspace general setting 2024-02-23 09:08:49 +08:00
Steven ce133ad69b chore: retire unused workspace settings 2024-02-23 08:40:33 +08:00
Steven e585578553 chore: tweak readme 2024-02-23 08:25:54 +08:00
Steven 4d9c929c32 chore: upgrade gomark 2024-02-23 08:22:39 +08:00
Steven 39bf850591 fix: embed memos callback 2024-02-22 23:17:15 +08:00
Steven 9cd835b979 chore: upgrade gomark wasm 2024-02-22 23:11:32 +08:00
Steven 0afdbe3332 chore: remove animation of spoiler 2024-02-22 19:25:24 +08:00
Steven 6b14d87521 chore: fix linter 2024-02-21 23:45:12 +08:00
Steven 51d58d3982 chore: add workspace setting migrator 2024-02-21 23:43:18 +08:00
Steven 4378816e44 chore: tweak i18n 2024-02-21 23:02:18 +08:00
Steven e7bbd850b2 chore: tweak spoiler animation 2024-02-21 21:31:34 +08:00
Steven c6162d3f38 chore: update dependencies 2024-02-21 21:24:31 +08:00
Steven ce32206677 chore: remove unused system setting 2024-02-21 21:15:28 +08:00
Steven 50a3af3b29 chore: fix get general setting 2024-02-21 20:44:35 +08:00
Steven 80b64c02fd chore: tweak workspace setting seeds 2024-02-21 20:25:25 +08:00
Steven 13b911ebf0 chore: add spoiler node 2024-02-20 23:55:54 +08:00
Steven 4a6da91719 chore: fix serve frontend flag 2024-02-20 23:24:13 +08:00
Steven fa62e8b59a chore: tweak linter errors 2024-02-20 23:07:42 +08:00
Steven 8e11826db1 chore: update workspace setting service 2024-02-20 23:02:01 +08:00
David Nguyen e6d0c00cf6 chore: update vi.json (#2980) 2024-02-20 17:57:06 +08:00
Kristián 03d67d5a00 feat: add mermaid support in codeblock (#2971) 2024-02-19 15:10:58 +08:00
Kazuki H a86117f613 feat: add new line if the cursor is on a character when adding a tag (#2960) 2024-02-19 08:54:47 +08:00
Søm fc1a2cf2fc chore: update ja.json (#2966) 2024-02-17 09:31:52 +08:00
Steven d22b772232 chore: add memo actions to memo detail page 2024-02-15 11:16:51 +08:00
Steven f1ec5775a7 chore: update inbox props 2024-02-14 09:44:35 +08:00
Bryan 4aa4417d91 chore: allow all 20x response status code in webhook (#2947) 2024-02-13 09:30:48 +08:00
Steven 606e574e19 chore: update enum type 2024-02-13 09:30:28 +08:00
Brilliant Hanabi ebe3678288 feat: add visibility select in ShareMemoDialog (#2941)
In ShareMemoDialog, user can change the visibility
of the memo, so that the memo can be set to public
to be viewed by anyone with the link.
2024-02-13 09:28:16 +08:00
Steven b3ca9969c4 chore: tweak linter 2024-02-09 22:18:55 +08:00
Steven 3dddd3ec4c chore: tweak reaction store 2024-02-09 21:59:45 +08:00
Brilliant Hanabi 81aa9b107f feat: add notice when sharing private links in MemoDetail (#2942) 2024-02-09 09:30:01 +08:00
Steven 60efd3ac32 chore: tweak memo view 2024-02-08 22:52:49 +08:00
Steven 4081a6f5ad chore: add more reactions 2024-02-08 21:20:51 +08:00
Lincoln Nogueira 334e489867 chore: improve docker-compose.dev (#2938) 2024-02-08 16:28:43 +08:00
Steven c7822515a1 chore: tweak view checks 2024-02-08 13:37:38 +08:00
Steven d86f0bac8c chore: implement reaction frontend 2024-02-08 13:25:15 +08:00
Steven e5f244cb50 chore: fix tests 2024-02-08 11:58:23 +08:00
Steven 3a5bc82d39 chore: implement reaction service 2024-02-08 11:54:59 +08:00
Steven a4fa67cd18 chore: update dependencies 2024-02-08 08:13:42 +08:00
Steven 43a2d6ce09 chore: tweak user setting 2024-02-08 08:06:55 +08:00
Mehad Nadeem d2434111b4 chore: impl compact mode setting (#2935)
* chore: backend/DB related files for compact view setting.

* fix: passing lint errors

* fix2: passing linter errors
2024-02-08 08:05:56 +08:00
Steven 559e427c50 chore: implement reaction store 2024-02-07 23:40:23 +08:00
Steven 99568236a3 chore: run buf generate 2024-02-07 21:51:30 +08:00
Mehad Nadeem 06fb2174c3 feat: add compact mode setting (Proto) (#2934)
* chore: proto related files for compact view setting.

* fix: pasing lint errors
2024-02-07 21:45:11 +08:00
Kazuki H 5ac17fc012 fix: displaying archived memos (#2933)
* fix: web: Archived: Show displayTime instead of updateTime

Archiving a memo is considered "updating" it, so the time it was
archived will be displayed, instead of the time it was created.

* fix: web: Archived: Add an option to fetch more memos

Just like on other pages, add a button to fetch more memos. Otherwise,
the user would only be able to load the latest 10 memos, as defined in
DEFAULT_MEMO_LIMIT.
2024-02-07 17:53:23 +08:00
Steven a76b86f18a chore: fix highlight code 2024-02-06 20:59:17 +08:00
Steven ded8001735 chore: fix v2 routes 2024-02-06 20:55:27 +08:00
Steven 185ec2ad2a chore: update inbox service 2024-02-06 19:46:25 +08:00
Steven 6b59c7670c chore: fix linter warning 2024-02-05 23:32:01 +08:00
Steven 434ef44f8c chore: add cookie builder 2024-02-05 23:28:29 +08:00
Steven 46ea16ef7e chore: fix cookie attrs 2024-02-05 22:14:58 +08:00
Steven 8f15e8773a chore: update cookie attrs 2024-02-05 21:42:23 +08:00
Steven 25efc33b24 chore: tweak timeline styles 2024-02-05 21:37:43 +08:00
Steven ba460382b0 chore: remove type-gen script 2024-02-05 20:42:01 +08:00
Steven e35225ff24 chore: fix resource url 2024-02-05 19:35:23 +08:00
Steven 397a7f00ef chore: add postinstall script 2024-02-05 19:29:47 +08:00
Steven 06eff151e7 chore: tweak memo find builder 2024-02-05 06:40:55 +08:00
Steven c30d7ab8f3 chore: update cors middleware 2024-02-05 06:10:10 +08:00
Steven ab4a670bec chore: add env example 2024-02-05 00:33:07 +08:00
Steven ce663efc14 chore: update cookie attrs 2024-02-05 00:11:36 +08:00
Steven 9e72432f19 chore: tweak cookie attrs 2024-02-05 00:10:54 +08:00
Steven b056c59dea chore: add vercel.json 2024-02-05 00:01:31 +08:00
Steven 15c90871d9 chore: update request base url 2024-02-04 23:48:26 +08:00
Steven be899cd027 chore: update eslint config 2024-02-04 22:52:47 +08:00
Steven 8773a3d2c1 chore: tweak assets folder 2024-02-04 22:45:51 +08:00
Steven d2603ee67b chore: upgrade frontend dependencies 2024-02-04 21:36:11 +08:00
Steven c92507728a chore: tweak filter checks 2024-02-04 21:07:14 +08:00
Steven eb4f7b47b7 chore: update memo find builder 2024-02-04 20:54:17 +08:00
Steven 1e07b70d23 chore: fix export memos 2024-02-04 20:20:14 +08:00
Athurg Gooth b8a9783db5 fix: signin error notification is not shown (#2908)
fix signin error notification is not shown
2024-02-04 14:25:51 +08:00
Ikko Eltociear Ashimine 82e72813f9 chore: fix typo in About.tsx (#2899) 2024-02-04 08:33:13 +08:00
Steven 57510ddee5 chore: update readme with used resources 2024-02-03 23:42:24 +08:00
Steven 00c47a0673 chore: fix menu z-index 2024-02-03 23:17:03 +08:00
Steven 374f3f7d96 chore: fix filter initial state 2024-02-03 22:03:56 +08:00
Steven 8340e6b247 chore: upgrade gomark 2024-02-03 21:52:54 +08:00
Steven 7f5148d490 chore: clean dropdown 2024-02-01 21:56:08 +08:00
Steven c522e1450a chore: update codeblock style 2024-02-01 21:38:28 +08:00
Steven c342c464a2 chore: update services comment 2024-02-01 21:26:09 +08:00
Steven f6f193af2d chore: format proto 2024-02-01 21:15:56 +08:00
Steven dd06278692 feat: add batch upsert tags 2024-02-01 21:13:42 +08:00
Steven fdd17ce849 chore: update memo content key 2024-02-01 20:40:43 +08:00
Elliot Chen 7cd3fcbc61 fix: wrong order of the timeline in the resource page & add webhook when create memos using Telegram bot (#2886)
* fix: wrong order in resource page timeline

* feat: add webhook when create memos using Telegram bot

* rename variables and fix typos for static checks
2024-02-01 20:24:58 +08:00
Steven e78311b3af fix: initial gomark wasm 2024-02-01 19:39:41 +08:00
Steven e3afad74ce fix: update initial wasm 2024-02-01 19:27:54 +08:00
Steven 554f93eccc fix: move initial wasm into app 2024-02-01 19:06:44 +08:00
Steven 79227021f5 chore: bump version 2024-01-31 23:08:33 +08:00
Steven b4f2a3bd14 chore: remove migrator 2024-01-31 22:58:43 +08:00
Steven 0b4914d880 chore: update generated node types 2024-01-31 22:42:51 +08:00
Steven 2f0b0e0071 chore: remove node definition 2024-01-31 22:32:09 +08:00
Steven 8ce6a32aac feat: use gomark wasm in frontend 2024-01-31 22:25:24 +08:00
Wen Sun 3158c4b8b5 fix: role error in api/v2 when the first user registers (#2875)
Fix role error in api/v2 when the first user registers
2024-01-31 19:55:52 +08:00
Steven 30ae4140f3 chore: update gomark source 2024-01-31 19:01:08 +08:00
Lincoln Nogueira 279cba0e6b chore: greatly speed up migrator and lower memory usage (#2874)
* chore: add en-GB language

* chore: remove en-GB contents

* chore: prevent visitors from breaking demo
- prevent disabling password login
- prevent updating `memos-demo` user
- prevent setting additional style
- prevent setting additional script
- add some error feedback to system settings UI

* Revert "chore: add en-GB language"

This reverts commit 2716377b04.

* chore: speed-up migrator and lower memory usage
- remove all Store indirections
- query database directly with prepared statements

* chore: fix golangci-lint warnings
2024-01-31 16:45:21 +08:00
Lincoln Nogueira 52539fc130 chore: prevent visitors from breaking demo (#2869)
* chore: add en-GB language

* chore: remove en-GB contents

* chore: prevent visitors from breaking demo
- prevent disabling password login
- prevent updating `memos-demo` user
- prevent setting additional style
- prevent setting additional script
- add some error feedback to system settings UI

* Revert "chore: add en-GB language"

This reverts commit 2716377b04.
2024-01-31 13:16:31 +08:00
Steven 49e3eb107c chore: update gomark wasm 2024-01-31 00:25:01 +08:00
Lincoln Nogueira e7d5dfe515 chore: add en-GB language (#2865)
* chore: add en-GB language

* chore: remove en-GB contents
2024-01-30 23:39:13 +08:00
Steven 28c7a75ea2 chore: fix import nodes 2024-01-30 22:15:05 +08:00
Steven 59d69a05fa feat: initial gomark wasm importer 2024-01-30 22:12:44 +08:00
Steven ad2d492dec chore: move preview memo content 2024-01-30 22:10:17 +08:00
Elliot Chen bee6f278ba fix: the same-storage check in the new pre-sign feature (#2860)
* fix: error check for the same oss-storage

* fix: conflict error2 variable in code refactor in s3.go

* chore: rename endpointUrl to endpointURL
2024-01-30 19:07:16 +08:00
Brilliant Hanabi 1bad0543d0 feat: add notice when sharing private links (#2809)
Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-01-30 19:06:30 +08:00
Noah Alderton 73337331cb feat: export all user Memos as a .zip of Markdown files (#2854)
* Add gRPC Memos Export

* Update code style

* Add URL.revokeObjectURL

* Rename protobuf and ESLint fix

* Change MemosExport to ExportMemos
2024-01-30 16:42:54 +08:00
Wen Sun 50f7f131ea fix: month grouping error in timeline page (#2861) 2024-01-30 07:56:03 +08:00
Steven a16bde23f7 chore: tweak variable name 2024-01-29 23:15:47 +08:00
Steven c5a5f67fdb refactor: migrate auth service 2024-01-29 23:12:02 +08:00
Steven de8db63811 chore: rename workspace setting service 2024-01-29 22:43:40 +08:00
Steven dd9ee44a1f docs: regenerate swagger 2024-01-29 22:05:33 +08:00
Aleksandr Baryshnikov fa17dce046 feat: pre-signed URL for S3 storage (#2855)
Adds automatically background refresh of all external links if they are belongs to the current blob (S3) storage. The feature is disabled by default in order to keep backward compatibility.

The background go-routine spawns once during startup and periodically signs and updates external links if that links belongs to current S3 storage.

The original idea was to sign external links on-demand, however, with current architecture it will require duplicated code in plenty of places. If do it, the changes will be quite invasive and in the end pointless: I believe, the architecture will be eventually updated to give more scalable way for pluggable storage. For example - Upload/Download interface without hard dependency on external link. There are stubs already, but I don't feel confident enough to change significant part of the application architecture.
2024-01-29 21:12:29 +08:00
Steven cbcec80c5d chore: fix import order 2024-01-29 21:08:30 +08:00
Steven 2b7bd47b44 fix: rss routes 2024-01-29 21:04:35 +08:00
Steven 54c5039db3 chore: fix golang linter 2024-01-29 19:17:25 +08:00
Steven af646ce2de refactor: move gomark 2024-01-29 19:14:46 +08:00
Steven f4ac7ff529 chore: update memo resource url 2024-01-28 23:02:38 +08:00
Steven 55ecdae509 chore: fix auto link matcher 2024-01-28 22:13:19 +08:00
Steven ef73299340 chore: update resource name migrator 2024-01-28 21:40:24 +08:00
Steven 8c6292925e chore: update code block styles 2024-01-28 15:41:11 +08:00
Steven f05a89315c chore: fix list memos 2024-01-28 08:38:29 +08:00
Steven a4452d8a2f chore: update linter rules 2024-01-28 08:17:11 +08:00
Steven 5e74394643 chore: add resource name migrator 2024-01-28 07:58:53 +08:00
Steven f4e722c516 chore: remove latest tag 2024-01-28 07:46:08 +08:00
Steven 12275c6a34 chore: fix linter warning 2024-01-28 07:38:01 +08:00
Steven 21ef5a9bc0 chore: tweak workspace service 2024-01-28 07:35:42 +08:00
Steven 87b23940a6 chore: upgrade backend dependencies 2024-01-28 07:13:11 +08:00
Steven 11dd23f59b chore: tweak link checks 2024-01-28 07:04:35 +08:00
Lincoln Nogueira 887903b66b feat: add buf plugin to generate openapiv2 spec (#2843) 2024-01-28 06:16:37 +08:00
Steven 309fab222e chore: implement nested blockquote 2024-01-27 21:38:07 +08:00
Steven 1dc4f02b64 chore: update memo requests 2024-01-27 20:35:48 +08:00
Steven 8db90a040c chore: remove unused dependencies 2024-01-27 20:20:36 +08:00
Steven 932f636d84 chore: update codeblock renderer 2024-01-27 19:09:10 +08:00
Steven ed32b20c9e chore: update frontend dependencies 2024-01-27 17:28:06 +08:00
Steven 10d709c167 chore: fix highlight cursor 2024-01-27 12:35:01 +08:00
Steven 8455114eef chore: fix list memos request 2024-01-27 11:17:59 +08:00
Steven c26109cd36 chore: update list memos request 2024-01-27 11:14:17 +08:00
Steven 4b223c1e4c chore: update collapse sidebar 2024-01-27 05:27:42 +08:00
Steven b9cbe6626f chore: update tag rename 2024-01-27 05:26:32 +08:00
Steven 566171783d chore: tweak embedded memo style 2024-01-26 23:33:40 +08:00
Steven 7edb3598ea chore: update default request limit 2024-01-26 23:03:10 +08:00
Steven bc2d2d0cde feat: support set embedded content in UI 2024-01-26 22:51:57 +08:00
Steven e1977df14b chore: remove check underscores 2024-01-26 21:23:36 +08:00
Wei Zhang ddc89029b7 fix: use mysql to parse dsn (#2838)
Signed-off-by: Zhang Wei <kweizh@gmail.com>
2024-01-26 13:43:48 +08:00
Steven f8b9a83d4a chore: tweak default value 2024-01-26 09:22:47 +08:00
Steven 2f16b7065a chore: tweak scripts 2024-01-26 09:15:27 +08:00
Steven e5ff1829a5 chore: add Hungarian locale 2024-01-26 08:44:12 +08:00
Steven d7889d9903 chore: tweak url filters 2024-01-26 08:39:53 +08:00
Steven db3457e081 chore: bump version 2024-01-26 08:30:22 +08:00
Steven 4f2b00b4f3 chore: add migration scripts 2024-01-26 08:29:11 +08:00
Steven 79558028c0 feat: implement rename tag 2024-01-25 23:09:35 +08:00
Steven 70d1301dc3 chore: use filter in url params 2024-01-25 20:05:47 +08:00
Steven 6d5e1def76 chore: update member section 2024-01-25 19:49:39 +08:00
boojack a5bc2d0ed6 chore: update i18n from Weblate (#2832)
* Added translation using Weblate (Hungarian)

* Translated using Weblate (Hungarian)

Currently translated at 0.3% (1 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

* Translated using Weblate (Hungarian)

Currently translated at 71.2% (226 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Vermunds <com.github@weylus.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: ti777777 <ti12272198686@yahoo.com.tw>
2024-01-25 19:36:02 +08:00
Steven 08ac60cc70 chore: update memo relation dialog 2024-01-25 08:59:10 +08:00
Mudkip f654d3c90e fix: encode filename when using url prefix for resources (#2829)
* fix: encode filename when using url prefix for resources

* fix: only encode the last parts of filename

* fix: encode all parts in filepath
2024-01-24 11:28:26 +08:00
Steven 1b69b73eb9 chore: update calendar styles 2024-01-23 23:15:54 +08:00
Steven 3dbb254aeb chore: update referenced memo title from params 2024-01-23 21:54:15 +08:00
Steven fdb1779a59 chore: implement referenced content renderer 2024-01-23 21:47:17 +08:00
Steven a316e239ce chore: implement referenced content node 2024-01-23 21:40:59 +08:00
Steven d7f02b94e5 chore: fix linter 2024-01-23 21:27:05 +08:00
Steven d165d87288 refactor: markdown parser matchers 2024-01-23 21:23:40 +08:00
Steven bf905bba86 chore: remove unused date picker 2024-01-22 22:50:27 +08:00
Brilliant Hanabi 3a129d5cfb fix: avoid making memos public when disabled (#2816)
* fix: avoid making memos public when disabled in v2

* fix: avoid making memos public when disabled in v1
2024-01-22 20:51:33 +08:00
ti777777 024a818e91 chore: update zh-Hant (#2815) 2024-01-21 23:50:44 +08:00
Steven 54a24833a7 chore: fix resource seeds 2024-01-21 21:36:31 +08:00
Steven a620d140c5 chore: update embedded content renderers 2024-01-21 21:27:04 +08:00
Steven 370054e040 chore: implement collapsed navigation 2024-01-21 21:02:55 +08:00
Steven fae0b4e900 chore: update memo relation style 2024-01-21 11:22:25 +08:00
Steven c38404b5d5 chore: tweak get memo by name 2024-01-21 10:57:53 +08:00
Steven 4d48f50815 chore: use resource name in frontend 2024-01-21 10:55:49 +08:00
Steven 582cc6609c feat: add user-defined id to resource 2024-01-21 10:49:30 +08:00
Steven 40bd75c725 fix: create memo with resource name 2024-01-21 10:33:31 +08:00
Steven b2fc3076f6 chore: update memo store 2024-01-21 01:23:55 +08:00
Steven 288527914b chore: migrate memo route 2024-01-21 01:23:44 +08:00
Steven a2aea3747c chore: remove server tests 2024-01-20 23:51:24 +08:00
Steven 8382354ef7 feat: add user-defined name to memo 2024-01-20 23:48:35 +08:00
Steven 264e6e6e9c chore: tweak file name 2024-01-20 23:47:04 +08:00
Steven eb72609ea3 chore: update memo editor cache key 2024-01-20 20:52:11 +08:00
Brilliant Hanabi 776785ac90 chore: update zh-Hans & zh-Hant translations (#2804) 2024-01-20 20:27:20 +08:00
Steven d5f874e185 chore: handle resource not found 2024-01-20 12:47:43 +08:00
Steven 89d940d9b7 feat: implement params field for embedded content node 2024-01-20 12:41:08 +08:00
Mark Zhao bd1cf62761 feat: enable iframe rendering in markdown code block (#2799)
* enable iframe rendering in code block

* fix eslint issue
2024-01-20 11:36:45 +08:00
Steven 196facfacd feat: implement embedded resource renderer 2024-01-20 09:17:31 +08:00
Steven afe75fd9f2 chore: fix tokens split tests 2024-01-20 02:09:33 +08:00
Steven 8a34013558 feat: implement embedded memo renderer 2024-01-20 01:56:10 +08:00
Steven 67f5ac3657 feat: implement subscript and superscript renderer 2024-01-19 23:10:16 +08:00
Steven 7236552b6c feat: implement subscript and superscript parsers 2024-01-19 23:06:22 +08:00
Steven 1f5899d238 chore: update dependencies 2024-01-19 19:20:59 +08:00
Wen Sun ec4884ea04 fix: incorrect timeline month display (#2792)
Fix incorrect timeline month display
2024-01-19 18:07:08 +08:00
Elliot Chen 2e0619b4dc feat: add a webhook action for deleted memos (#2791) 2024-01-19 09:56:00 +08:00
Steven c9146bc749 chore: update code style 2024-01-19 07:06:28 +08:00
Steven f5b5bd64bc chore: tweak datetime.ts 2024-01-18 22:18:56 +08:00
Steven d31d9eb71c chore: remove unused nil checks 2024-01-18 19:23:45 +08:00
Steven f28b654057 chore: fix setting nil checks 2024-01-18 19:20:48 +08:00
Steven 8738b68a44 chore: tweak readme 2024-01-18 19:06:49 +08:00
Steven 42381fa154 chore: add stable build action 2024-01-18 18:49:06 +08:00
Steven 22427101f8 chore: add stale issue action 2024-01-18 16:18:18 +08:00
Steven 2a4ebf5774 chore: add search bar in archived page 2024-01-18 15:28:37 +08:00
Steven 5172e4df7c chore: create memo visibility when creating 2024-01-18 15:20:22 +08:00
Steven 893dd2c85e chore: add disable filter to renderer context 2024-01-18 14:52:57 +08:00
Steven d426f89cf0 chore: add time filter to timeline 2024-01-18 14:30:20 +08:00
Steven 7de3de5610 chore: fix go test warning 2024-01-18 11:45:59 +08:00
Steven 2856e66609 chore: fix go test 2024-01-18 11:42:57 +08:00
Steven 354011f994 chore: handle filter in user profile page 2024-01-18 11:38:45 +08:00
Steven 8ed827cd2d chore: update table node delimiter 2024-01-18 11:36:13 +08:00
Steven 05c0aeb789 feat: implement table renderer 2024-01-18 10:49:28 +08:00
Steven aecffe3402 feat: implement table parser 2024-01-18 10:21:08 +08:00
Mehad Nadeem 70e6b2bb82 chore: added tooltip for vacuum button (#2778)
* chore: added tooltip for vacuum button

- At the moment only has text for English language therefore other JSON files need to be updated accordingly

* Update en.json
2024-01-18 08:09:49 +08:00
Steven 54296f0437 chore: update filter in timeline 2024-01-18 08:06:59 +08:00
Steven 8fcd9332f7 chore: tweak timeline styles 2024-01-17 22:32:58 +08:00
Steven 1857362d03 fix: locale and appearance setting 2024-01-17 22:16:12 +08:00
Steven 6d7186fc81 feat: rebuild timeline page 2024-01-17 21:59:49 +08:00
Wen Sun e4488da96e fix: signup is not allowed if password login is disabled (#2776)
Signup is not allowed if password login is disabled

If password login is disabled in the system configuration, the "signup" in the "/auth" page disappears, but the user can manually enter "/auth/signup" to access the system by creating a new user.
2024-01-17 10:49:22 +08:00
Steven cc43d06d33 chore: update memo stats response 2024-01-17 09:17:33 +08:00
Steven 9ffd827028 fix: appearance and locale initial value 2024-01-16 22:53:45 +08:00
Hanqin Guan 15e6542f0d fix: server overrides user's locale/appearance (#2771) 2024-01-16 18:21:08 +08:00
Noah Alderton 24bb3e096a fix: DatePicker by passing in Timezone to API (#2770)
* Fix DatePicker by passing in Timezone to API

* Add some clarity
2024-01-16 18:02:09 +08:00
Lincoln Nogueira 5bcbbd4c52 chore: fix store tests on Windows (#2769)
It's just a matter of explicitly closing the database, so that TempDir.removeAll doesn't fail.
2024-01-16 13:51:26 +08:00
Noah Alderton ff13d977e9 feat: add URL paste handler (#2768)
* feat: Add URL paste handler

* Check if text highlighted for URL pasting
2024-01-16 10:06:16 +08:00
Wen Sun 1fdb8b7b01 fix: apply customized profile name in mobile header (#2723)
Fix mobile header title, apply customized profile name
2024-01-16 09:04:03 +08:00
Wen Sun f1ee88c4e1 fix: display system logo in user banner if user not logged in (#2747)
Display system logo in user banner if user not logged in
2024-01-16 09:03:27 +08:00
Noah Alderton b578afbc6a fix: DatePicker Local Date (#2766)
Fix DatePicker Local Date
2024-01-16 08:35:48 +08:00
Steven ad94e8e3c6 feat: implement highlight renderer 2024-01-15 22:54:18 +08:00
Steven 3f4b361fad feat: implement highlight parser 2024-01-15 22:30:06 +08:00
Steven 46bd470640 chore: update favicon 2024-01-15 21:10:41 +08:00
Steven fdbf2d8af2 chore: fix blockquote renderer 2024-01-15 20:41:37 +08:00
Steven 5a723f00fa chore: split editor keydown handler 2024-01-15 20:33:42 +08:00
Noah Alderton 728a9705ea feat: Markdown Editor Keyboard Shortcuts (#2763)
* Add bold and italic keyboard shortcut

* Add hyperlink keyboard shortcut support
2024-01-15 20:19:59 +08:00
THELOSTSOUL cd3a98c095 fix: change use-set priority (#2760)
The user settings(locale, appearance) are not in use when restart broswer
2024-01-15 20:08:14 +08:00
Wen Sun a22ad90174 fix: set memo resources error in mysql (#2761)
Fix error updating memo resources in mysql
2024-01-15 20:05:07 +08:00
Steven 5ebbed9115 chore: handle tag click 2024-01-15 08:15:34 +08:00
Steven 7ae4299df2 chore: implement create resource 2024-01-15 08:13:06 +08:00
Noah Alderton 3d23c01e26 feat: add additional favicon formats (#2752)
Add additional favicons
2024-01-15 07:54:33 +08:00
Lincoln Nogueira 089e04bcfd chore: use webp compression on logo (#2756)
- Logo size reduced from 310 KB to 36 KB.
- Point metadata image URL to local logo instead of remote
2024-01-14 22:21:03 +08:00
Steven 98762be1e5 feat: implement indent for list nodes 2024-01-14 22:19:03 +08:00
Steven d44e74bd1e chore: update editor actions 2024-01-14 21:47:03 +08:00
Steven 8e0ce4d678 fix: list memos with pinned 2024-01-14 20:51:52 +08:00
Steven 45cf158508 chore: fix max width of home section 2024-01-14 20:25:45 +08:00
Anish Kelkar 7340ae15f7 chore: delete .vscode directory (#2693)
* Delete .vscode directory

* web/.vscode deleted
2024-01-14 20:12:57 +08:00
Steven 6db7ad76da chore: update tag selector 2024-01-13 16:26:42 +08:00
Steven 4a407668bc chore: tweak dialog close button 2024-01-13 15:33:23 +08:00
Steven ab1fa44f00 feat: implement markdown buttons 2024-01-13 15:09:06 +08:00
Steven cd0004cf88 chore: update icon version 2024-01-13 15:08:58 +08:00
Steven 667aaf06a0 chore: update dependencies 2024-01-13 14:33:50 +08:00
Steven a8074d94e8 chore: update image attrs 2024-01-13 14:08:36 +08:00
Hanqin Guan 16e68fbfff fix: duplicated/reflexive relation in v2 api. (#2750) 2024-01-13 07:21:19 +08:00
Wen Sun 81942b3b98 chore: updating the default scopes of GitHub SSO (#2746)
Updating the default scopes of GitHub SSO

The scope of "user" in GitHub OAuth includes permissions to update a user's profile.
2024-01-12 14:02:11 +08:00
Athurg Gooth a7cda28fc7 fix: filename with space (#2745) 2024-01-12 14:01:19 +08:00
Steven 0c52f1ee6a chore: tweak home style 2024-01-12 08:08:24 +08:00
Steven 1994c20c54 chore: tweak setting page 2024-01-11 22:25:05 +08:00
Steven a1dda913c3 chore: fix tag selector position 2024-01-11 21:36:22 +08:00
Athurg Gooth d626de1875 fix: pnpm install failed in docker (#2732)
fix pnpm install failed in docker
2024-01-11 21:29:55 +08:00
Wen Sun 6cfd94cc69 fix: deleting inbox records that senders have been deleted (#2743)
Deleting inbox records that senders have been deleted
2024-01-11 21:29:22 +08:00
Athurg Gooth 79b68222ff chore: set image loading to lazy (#2733)
set image loading to lazy to avoid concurrent problem
2024-01-11 10:27:18 +08:00
Steven aaec46a39c chore: update find memo with updated time 2024-01-10 00:10:59 +08:00
Steven 9c663b1ba2 fix: merge mysql dsn with params 2024-01-10 00:03:47 +08:00
Steven 777ed899a3 chore: add memo uid 2024-01-08 21:48:26 +08:00
Steven ddcf1d669d chore: add max content length 2024-01-08 21:17:21 +08:00
Steven 32d02ba022 chore: fix horizontal rule matcher 2024-01-08 21:00:45 +08:00
Steven 5449342016 fix: auto link converters 2024-01-08 20:57:44 +08:00
Noah Alderton 43e42079a4 feat: export Memos as Markdown FIles (#2716) 2024-01-08 11:40:50 +08:00
Steven cafa7c5adc chore: update backend dependencies 2024-01-06 19:46:35 +08:00
Steven 1258c5a5b0 chore: update workspace setting proto 2024-01-06 19:46:21 +08:00
Steven 83141f9be2 chore: tweak navigation styles 2024-01-06 19:12:26 +08:00
Steven 4c59035757 chore: update about page 2024-01-06 19:01:11 +08:00
Steven 9459ae8265 chore: update postgres stmt builder 2024-01-06 17:12:10 +08:00
Steven 8893a302e2 chore: update logs 2024-01-06 16:58:58 +08:00
Steven d67eaaaee2 chore: update database migrator 2024-01-06 16:55:13 +08:00
Steven fd8333eeda chore: fix memo parent_id 2024-01-06 13:22:02 +08:00
Steven f5a1739472 chore: update memo detail checks 2024-01-06 10:03:36 +08:00
Steven a297cc3140 chore: exclude comments in memo list response 2024-01-06 09:48:11 +08:00
Steven 79c13c6f83 chore: fix edit memo params 2024-01-06 09:25:17 +08:00
Steven 8b9455d784 chore: fix memo resources position 2024-01-06 09:23:20 +08:00
Steven 501f8898f6 chore: fix postgres stmts 2024-01-05 21:27:16 +08:00
Steven ee13927607 chore: fix restore tag node 2024-01-05 18:50:28 +08:00
Steven d2a9aaa9d4 chore: update line break renderer 2024-01-05 09:18:37 +08:00
Steven f563b58a85 chore: fix renderer props 2024-01-05 08:47:43 +08:00
Steven ce2d37b90c chore: fix find sibling node 2024-01-05 08:43:30 +08:00
Steven 454cd4e24f feat: implement switchable task list node 2024-01-05 08:40:16 +08:00
Steven 6320d042c8 chore: update home padding styles 2024-01-04 22:50:46 +08:00
Steven d7ed59581c chore: fix math block matcher 2024-01-04 21:50:13 +08:00
Steven 9593b0b091 chore: fix link rel field 2024-01-04 21:26:56 +08:00
Steven ca53630410 chore: update drawer background 2024-01-04 21:11:22 +08:00
Steven f484c38745 chore: fix dependencies 2024-01-04 20:07:53 +08:00
Steven d12a2b0c38 feat: implement math expression parser 2024-01-04 20:05:29 +08:00
Steven c842b921bc chore: update backend dependencies 2024-01-04 19:15:25 +08:00
Wen Sun 6b2eec86c2 fix: image upload failed with cloudflare R2 (#2704)
Fix image upload failed with cloudflare R2
2024-01-04 19:08:54 +08:00
Steven 2eba4e2cd4 chore: update version 2024-01-04 08:36:45 +08:00
Steven 73baeaa0ad chore: tweak dark mode styles 2024-01-04 08:32:14 +08:00
Steven c58851bc97 chore: tweak accent color 2024-01-03 23:30:28 +08:00
Steven 96140f3875 chore: tweak dark mode styles 2024-01-03 23:12:50 +08:00
Lincoln Nogueira 369b8af109 chore: improve resource internal_path migrator (#2698)
* chore: improve internal path migrator
- handle mixed path styles
- handle Windows paths
- add tests

* chore: fix goimports error
2024-01-03 08:31:59 +08:00
Steven 914c0620c4 chore: add statistics view 2024-01-03 08:22:32 +08:00
Steven 138b69e36e chore: fix memo comment 2024-01-03 08:19:38 +08:00
Elliot Chen 3181c076b2 feat: add {uuid} in path template when using local storage or S3 (#2696)
Add {uuid} in path template when using local storage or S3

Add an addition tag `{uuid}` to the `replacePathTemplate`.

It is a workaround to leak the public links of a resource when using S3-based object storage. Currently, all resource blobs stored in S3 (R2, OSS) are set to be public. It is insecure as the resources for the private memos are also accessible on the Internet. Using an additional {uuid} might reduce this risk.

Meanwhile, it is also possible to avoid filename conflict
2024-01-02 20:57:55 +08:00
Noah Alderton 673809e07d fix: docker-compose.dev.yaml (#2695)
* Fix docker-compose.dev.yaml

* Add newline to .gitignore
2024-01-02 18:33:19 +08:00
Steven f74fa97b4a chore: traverse nodes to upsert tags 2024-01-02 08:56:30 +08:00
Steven c797099950 chore: update resource internal path migrator 2024-01-02 08:29:18 +08:00
Steven 0f8bfb6328 chore: update index.html 2023-12-29 08:28:17 +08:00
Steven 4cd01ece30 chore: update frontend metadata 2023-12-29 08:19:32 +08:00
Lincoln Nogueira 14b34edca3 chore: fix misuse of package path instead of filepath.path (#2684)
As stated by https://pkg.go.dev/path, "path" is mainly for URLs, "path.filepath" for file systems
2023-12-29 07:50:15 +08:00
Lincoln Nogueira 411e807dcc chore: use consistent relative paths for resources (#2683)
- always store resources with a relative path with forward slashes, which will be transformed as needed when the file is accessed

- fix an issue with thumbnail generation on Windows

- add several validations for local storage setting

- improve front-end error feedback when changing local storage

- add migrations to make existing resource paths relative (not needed, but improves database consistency)
2023-12-29 07:49:55 +08:00
Steven ea87a1dc0c chore: update memo content props 2023-12-28 22:57:51 +08:00
Steven 46f7cffc7b feat: implement restore nodes 2023-12-28 22:35:39 +08:00
Steven 2a6f054876 chore: update auto link parser 2023-12-28 21:32:44 +08:00
Steven 30dca18b79 chore: fix suspense wrapper 2023-12-28 08:34:06 +08:00
Steven 09c195c752 chore: update backend dependencies 2023-12-28 08:28:50 +08:00
Steven 2ae6d94e2c chore: update frontend dependencies 2023-12-28 08:27:06 +08:00
Steven 9ee4b75bbd chore: tweak memo detail styles 2023-12-27 23:25:02 +08:00
Steven cc40803b06 chore: update feature request template 2023-12-27 09:00:16 +08:00
Steven a0a03b0389 chore: tweak list memos request 2023-12-27 08:54:00 +08:00
Steven 0dfc367e56 chore: start grpc server 2023-12-27 08:50:02 +08:00
Steven c8d7f93dca feat: implement auto link parser 2023-12-27 08:44:51 +08:00
Steven 6fac116d8c chore: update user store 2023-12-26 23:05:33 +08:00
subks f48ff102c9 fix: eslint check failure after fixing #2672 (#2673) 2023-12-26 21:46:26 +08:00
subks bd5a0679ee fix: date format in share memo dialog (#2672)
fix: Date format in shareable Memo Images (#2668)
2023-12-26 17:50:09 +08:00
Steven fcfb76a103 chore: remove user urlsets in sitemap 2023-12-23 19:35:46 +08:00
Steven 8e325f9986 chore: return username in user response 2023-12-23 19:23:39 +08:00
Steven b8eaf1d57e chore: deprecate memo creation stats legacy api 2023-12-23 18:35:47 +08:00
Steven 42608cdd8f chore: fix server context 2023-12-23 17:59:15 +08:00
Steven 2cfa4c3b76 chore: tweak frontend routes register 2023-12-23 17:58:49 +08:00
Steven aa136a2776 chore: remove vite pwa plugin 2023-12-23 17:42:13 +08:00
Steven 68413a5371 chore: update frontend service 2023-12-23 17:04:52 +08:00
Steven 638f17a02c chore: update scripts 2023-12-23 15:12:25 +08:00
Steven 273d6a6986 chore: update dockerfile 2023-12-23 14:13:40 +08:00
Steven 953141813c chore: regenerate pnpm lock file 2023-12-23 12:01:26 +08:00
Leyang be2db3f170 feat: use vite plugin pwa for generate right sw.js (#2658)
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-12-23 12:00:03 +08:00
Steven eefce6ade3 chore: implement webhook dispatch in v2 api 2023-12-23 11:17:35 +08:00
Steven c6ebb5552e chore: add 403 page 2023-12-23 10:08:23 +08:00
Steven 4d64d4bf25 chore: upgrade frontend dependencies 2023-12-23 09:47:43 +08:00
Steven 2ee4d7d745 chore: add startTransition to links 2023-12-23 08:55:43 +08:00
Steven 1b81999329 chore: skip invalida setting checks 2023-12-23 08:55:23 +08:00
Steven df5aeb6d88 chore: remove v1 prefix in store name 2023-12-23 08:48:11 +08:00
Steven df3303dcd3 chore: update list users 2023-12-23 08:35:54 +08:00
Steven c267074851 chore: prevent archive/delete current user 2023-12-23 08:05:05 +08:00
Steven 21874d0509 chore: fix navigation errors 2023-12-23 08:01:16 +08:00
Steven 7898df2876 chore: update issue templates 2023-12-23 08:00:59 +08:00
Steven b2ec0d1217 chore: add skip cache requesting 2023-12-22 20:30:28 +08:00
Steven 5673e29e51 chore: compose memo in backend 2023-12-22 20:18:31 +08:00
Steven feefaabce9 chore: update heatmap click handler 2023-12-22 20:07:17 +08:00
Steven 29b540ade3 chore: fix fetch memos 2023-12-22 19:47:46 +08:00
Steven 919f75af1a chore: update suspense loading 2023-12-22 19:27:09 +08:00
Steven 17e905085f chore: update acl config 2023-12-22 09:11:55 +08:00
Steven 34af969785 chore: fix list memos order by pinned 2023-12-22 09:09:03 +08:00
Steven fd9c3ccbae chore: implement useMemoList store 2023-12-22 09:01:30 +08:00
Steven a3feeceace chore: remove component v1 suffix 2023-12-22 08:29:02 +08:00
Steven 02265a6e1a chore: fix memo search 2023-12-22 00:31:29 +08:00
Steven 81524c38e9 chore: refactor memo module 2023-12-21 23:40:43 +08:00
Steven 671551bdc1 chore: update memo detail page 2023-12-21 22:42:06 +08:00
Steven 10c81ccba3 chore: fix type definition 2023-12-21 21:43:28 +08:00
Steven 9361613f23 chore: update timeline page 2023-12-21 21:24:08 +08:00
Athurg Gooth b14334220f fix: trim the dirname of attachment send by telegram bot (#2651) 2023-12-21 09:47:57 +08:00
Athurg Gooth f184d65267 fix: attachments send from telegram lost (#2650) 2023-12-21 09:47:25 +08:00
Steven b64e2ff6ff chore: implement list memo resources api 2023-12-20 23:46:04 +08:00
Steven cbdae24314 chore: update archived page 2023-12-20 23:23:26 +08:00
Steven 762cb25227 chore: update memo service 2023-12-20 23:14:15 +08:00
Steven fc01a796f8 chore: fix demo seed data 2023-12-20 08:18:56 +08:00
Steven feb700f325 chore: clear access token when user not found 2023-12-20 07:42:02 +08:00
Steven 5334fdf1b2 chore: use api v2 in archived page 2023-12-19 23:49:24 +08:00
Steven abc14217f6 chore: tweak padding styles 2023-12-19 23:09:57 +08:00
Steven af68cae6ea chore: regenerate swagger docs 2023-12-19 22:37:07 +08:00
Steven e0cacfc6d6 chore: retire auto backup for sqlite 2023-12-19 22:34:06 +08:00
Steven b575064d47 chore: tweak padding 2023-12-19 21:44:40 +08:00
Steven 6290234ad1 chore: fix button styles 2023-12-19 21:29:07 +08:00
Steven aeed25648a chore: tweak drawer background 2023-12-19 08:55:21 +08:00
Steven 43e7506ed5 chore: fix react-uses import 2023-12-19 08:45:47 +08:00
Steven a3a1bbe8de chore: tweak responsible styles 2023-12-19 08:41:41 +08:00
Steven fe4ec0b156 chore: rename navigator 2023-12-19 00:13:22 +08:00
Steven 7c5fdd1b06 chore: remove demo banner 2023-12-18 23:46:48 +08:00
Steven 4d54463aeb chore: add mobile header 2023-12-18 23:33:09 +08:00
Steven 40bc8df63d chore: fix container height 2023-12-18 23:01:39 +08:00
Steven 61de7c8a32 chore: fix demo banner 2023-12-18 22:29:29 +08:00
Steven d6656db20d feat: implement part of full-screen layout 2023-12-18 22:10:36 +08:00
Steven 15a091fe4c chore: fix offset params in explore page 2023-12-18 20:54:51 +08:00
Steven d8a0528135 chore: tweak variable names 2023-12-18 20:47:29 +08:00
Steven 16fb5faebd chore: revert go mod update 2023-12-18 19:40:39 +08:00
Steven 2c4b5d75b3 chore: fix html escaping 2023-12-17 23:37:00 +08:00
Steven 770607f93f fix: add markdown service to acl 2023-12-17 11:37:38 +08:00
Steven db0eff4743 chore: clean frontend dependencies 2023-12-17 11:25:10 +08:00
Steven 0793f96578 chore: update heading styles 2023-12-17 11:08:13 +08:00
Steven 8095d94c97 chore: deprecate marked 2023-12-17 11:02:16 +08:00
Steven bcfcd59642 chore: deprecate old MemoContent 2023-12-17 10:58:22 +08:00
Steven 5d677c3c57 chore: implement node renderer components 2023-12-17 10:49:49 +08:00
Steven 28c0549705 feat: add markdown service 2023-12-17 09:53:22 +08:00
Steven bb42042db4 chore: implement task list parser 2023-12-16 12:48:52 +08:00
Steven 1c7fb77e05 chore: update user setting names 2023-12-16 12:18:53 +08:00
Steven e8ca2ea5a0 chore: rename renderer package 2023-12-16 11:57:36 +08:00
Steven e43a445c34 chore: implement escaping character node 2023-12-16 11:47:29 +08:00
Steven 1237643028 chore: update parser tests 2023-12-16 11:34:55 +08:00
Steven aee0e31b0a chore: update parser functions 2023-12-16 10:38:05 +08:00
Steven 47af632c79 chore: update inline parser 2023-12-16 10:09:20 +08:00
Steven 7b0ceee57b chore: update memo metadata description 2023-12-16 09:23:45 +08:00
Steven bdc867d153 fix: heading render 2023-12-16 09:12:55 +08:00
Steven 6421fbc68a chore: implement list html render 2023-12-16 09:01:19 +08:00
Steven b00443c222 chore: implement list nodes 2023-12-16 08:51:29 +08:00
Steven a10b3d3821 chore: tweak custom profile 2023-12-15 22:57:53 +08:00
Steven 7735cfac31 chore: update seed data 2023-12-15 22:34:19 +08:00
Steven 749187e1e9 chore: update dockerfile 2023-12-15 21:46:11 +08:00
Steven a9812592fe chore: tweak editor border styles 2023-12-15 21:35:31 +08:00
Steven e4070f7753 chore: bump version 2023-12-15 21:11:04 +08:00
Steven ff53187eae chore: add sitemap and robots routes 2023-12-15 20:18:01 +08:00
Steven 89ef9b8531 chore: add instance url system setting 2023-12-15 19:39:37 +08:00
Steven 56b55ad941 chore: update memo metadata 2023-12-15 19:13:56 +08:00
Steven 24672e0c5e chore: update memo metadata 2023-12-15 08:12:10 +08:00
Steven 52743017a3 chore: implement memo route 2023-12-15 07:32:49 +08:00
Steven 6cf7192d6a chore: add ssr placeholder in index.html 2023-12-14 23:29:42 +08:00
Steven 6763dab4e5 chore: handle newline in block parsers 2023-12-14 22:55:46 +08:00
Steven e0290b94b4 chore: use gomark in rss api 2023-12-14 22:33:20 +08:00
Steven 242f64fa8e chore: implement html render 2023-12-14 22:21:23 +08:00
Steven 3edce174d6 chore: remove unused methods 2023-12-14 00:24:41 +08:00
Steven 5266a62685 chore: implement html renderer 2023-12-14 00:04:20 +08:00
Steven 43ef9eaced chore: implement part of html renderer 2023-12-13 23:50:05 +08:00
Steven 453707d18c feat: implement gomark parsers 2023-12-13 21:00:13 +08:00
Steven 2d9c5d16e1 chore: fix user string 2023-12-13 19:08:06 +08:00
Steven b20e0097cf chore: implement part of nodes 2023-12-13 09:06:47 +08:00
Steven dd83782522 chore: add line break node 2023-12-12 23:38:43 +08:00
Steven aa3632e2ac chore: implement gomark skeleton 2023-12-12 23:24:02 +08:00
boojack 7f1f6f77a0 chore: update i18n with weblate (#2614)
* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-12-12 21:06:13 +08:00
Steven 7eb5be0a4e chore: fix update user 2023-12-12 20:01:31 +08:00
Steven 603a6a4971 chore: fix vacuum memo 2023-12-12 19:56:15 +08:00
Cologler 6bda64064e fix: delete one memo will delete all memos on pgsql (#2611)
fix: delete single memo will all memos on pgsql

Close #2605
2023-12-12 19:52:39 +08:00
Steven ec7992553f chore: go mod update 2023-12-11 22:21:05 +08:00
Steven e5de8c08f5 chore: clean debug code 2023-12-11 22:20:57 +08:00
Steven c608877c3e chore: clean binary entries 2023-12-11 22:16:39 +08:00
Steven 52f399a154 chore: remove unused functions 2023-12-11 21:53:16 +08:00
Gabe Cook 88728906a8 fix(copydb): fix migration to Postgres (#2601)
* chore(copydb): Use query builder during setup

* fix(copydb): Fix migration to Postgres
2023-12-11 18:05:15 +08:00
boojack 0916ec35da chore: update i18n with Weblate (#2594)
* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
2023-12-10 15:49:29 +08:00
Steven 9f4f2e8e27 chore: fix user setting values 2023-12-10 11:57:31 +08:00
Steven 82009d3147 chore: tweak webhook section 2023-12-10 10:21:36 +08:00
Steven 0127e08a28 fix: data conflict handler 2023-12-10 10:07:26 +08:00
Steven d275713aff chore: fix timestamp type in postgres 2023-12-09 23:19:57 +08:00
Steven c50f4f4cb4 chore: update migration scripts 2023-12-09 22:18:05 +08:00
Steven fa34a7af4b chore: tweak memo parent styles 2023-12-09 19:32:16 +08:00
Steven 77b75aa6c4 chore: tweak memo display 2023-12-09 18:57:59 +08:00
Steven 9faee68dab chore: code clean 2023-12-09 18:57:18 +08:00
Steven 4f05c972d5 chore: fix jwt acl 2023-12-09 16:17:11 +08:00
Steven abda6ad041 chore: update latest schema 2023-12-09 12:05:45 +08:00
Steven 7fc7b19d64 chore: deprecate user setting legacy api 2023-12-08 22:41:47 +08:00
Steven b2d898dc15 chore: fix import order 2023-12-08 22:06:42 +08:00
Steven 15425093af chore: skip user setting key checks 2023-12-08 22:05:43 +08:00
K.B.Dharun Krishna b02aa2d5e5 chore: bump actions in workflows (#2588)
Signed-off-by: K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
2023-12-08 09:55:18 +08:00
steven c68bfcc3b9 chore: fix user setting store 2023-12-08 09:54:32 +08:00
Athurg Gooth 2964cf93ab fix: visibility of user preference is empty (#2581)
Fix visibility of user preference is empty
2023-12-07 22:50:03 +08:00
Arnaud Brochard 787cf2a9fe feat: tables support (#2573)
* Tables support

* Linter fixes

* Regex Redos fix

* Fix empty row and variables proper naming

* Default cell style

* Now unncessary

* Support rows without a starting pipe char

* Striped rows

* Fix parsing issues

* Support tabs in separators
2023-12-07 22:49:49 +08:00
Athurg Gooth ed190cd41e fix: visibility of memo editor is empty (#2580)
Fix visibility of memo editor is empty
2023-12-06 23:17:26 +08:00
Steven 33dda9bf87 chore: fix auth status checks 2023-12-06 23:03:24 +08:00
Steven fa6693a7ae chore: update list memos 2023-12-06 22:44:49 +08:00
t.yang 055a327b5e fix: detail page user-avatar size have unexpected height (#2576)
Co-authored-by: tyangs.yang <tyangs.yang@hstong.com>
2023-12-06 10:58:33 +08:00
Athurg Gooth aff1b47072 chore: remove debug log (#2582)
Remove debug log
2023-12-06 10:57:55 +08:00
Athurg Gooth 5f86769255 fix: field type of row_status for table webhook (#2579)
Fix field type of row_status for table webhook
2023-12-06 10:57:03 +08:00
Irving Ou 9c18960f47 feat: support Postgres (#2569)
* skeleton of postgres

skeleton

* Adding Postgres specific db schema sql

* user test passed

* memo store test passed

* tag is working

* update user setting test done

* activity test done

* idp test passed

* inbox test done

* memo_organizer, UNTESTED

* memo relation test passed

* webhook test passed

* system setting test passed

* passed storage test

* pass resource test

* migration_history done

* fix memo_relation_test

* fixing server memo_relation test

* passes memo relation server test

* paess memo test

* final manual testing done

* final fixes

* final fixes cleanup

* sync schema

* lint

* lint

* lint

* lint

* lint
2023-12-03 13:31:29 +08:00
Webysther Sperandio 484efbbfe2 chore: update manifest.json (#2568) 2023-12-01 16:43:48 +08:00
Steven e83d483454 refactor(frontend): use auth service 2023-12-01 09:15:02 +08:00
Steven b944418257 fix: register auth service 2023-12-01 09:13:32 +08:00
Steven 4ddd3caec7 chore: update user setting api 2023-12-01 09:03:30 +08:00
Steven c1f55abaeb chore: update user setting api 2023-11-30 23:08:54 +08:00
Steven fff42ebc0d fix: check auth status 2023-11-30 21:52:02 +08:00
Steven 2437419b7f fix: add auth status checks 2023-11-30 20:58:36 +08:00
boojack e53cedaf14 chore: update i18n with weblate (#2562)
* Translated using Weblate (Polish)

Currently translated at 46.3% (147 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pl/

* Translated using Weblate (Polish)

Currently translated at 56.1% (178 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pl/

---------

Co-authored-by: igormakarowicz <igormakarowicz@gmail.com>
2023-11-30 19:34:50 +08:00
Steven 6d469fd997 chore: fix image size 2023-11-30 19:36:12 +08:00
boojack 9552cddc93 chore: update graph format 2023-11-29 09:00:29 +08:00
boojack 34181243e5 chore: update graph route 2023-11-28 23:06:19 +08:00
boojack a0eb891132 chore: update contributor graph source 2023-11-28 22:31:34 +08:00
Steven e136355408 chore: tweak setting button style 2023-11-28 21:15:24 +08:00
Steven 5069476dcc chore: add webhook metric 2023-11-28 21:15:10 +08:00
Steven f950750d56 chore: tweak storage list title 2023-11-28 21:03:21 +08:00
Steven 0026f9e54f chore(frontend): add webhooks section 2023-11-28 20:52:48 +08:00
Steven f8f73d117b chore: update healthz message 2023-11-26 23:33:34 +08:00
Steven 8586ebf098 chore: add /healthz endpoint 2023-11-26 23:06:50 +08:00
Steven 472afce98f chore: fix current user store 2023-11-25 22:58:17 +08:00
Steven a12844f5db chore: tweak seed data 2023-11-25 10:34:54 +08:00
Steven bc965f6afa chore: implement webhook dispatch in api v1 2023-11-25 10:31:58 +08:00
Steven db95b94c9a chore: implement webhook service 2023-11-24 23:04:36 +08:00
Steven 1a5bce49c2 chore: implement webhook store 2023-11-24 22:45:38 +08:00
Steven 436eb0e591 chore: tweak s3 comments 2023-11-24 21:55:09 +08:00
Hou Xiaoxuan e016244aba fix: remove ACL when set URLPrefix (#2532) 2023-11-23 23:20:11 +08:00
Steven d317b03832 feat: add search box in resources dashboard 2023-11-23 22:12:15 +08:00
Athurg Gooth 3e138405b3 chore: remove the max height limit for single media (#2545)
Remove the max-height limit for single media
2023-11-23 09:59:33 +08:00
Steven 0dd0714ad0 chore: update security 2023-11-23 08:55:57 +08:00
Steven 45d7d0d5f6 chore: migrate get current user 2023-11-23 08:50:33 +08:00
boojack c3db4ee236 chore: translated using Weblate (Portuguese (Brazil)) (#2543)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-11-22 23:22:10 +08:00
Athurg Gooth 91296257fc chore: remove invalid access token from db (#2539)
Remove invalid access token from db
2023-11-22 23:20:45 +08:00
Steven e5f660a006 chore: migrate update user 2023-11-22 23:11:29 +08:00
Steven c0628ef95b chore: migrate create user 2023-11-22 22:58:04 +08:00
Steven c0b5070e46 chore: migrate delete user 2023-11-22 22:52:19 +08:00
Steven b1128fc786 chore: fix inline latext renderer 2023-11-22 22:38:03 +08:00
Steven bcd8a5a7a9 chore: migrate get tag suggestions 2023-11-22 22:33:02 +08:00
boojack 0cf280fa9a chore: translated using Weblate (Croatian) (#2541)
Translated using Weblate (Croatian)

Currently translated at 92.7% (293 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
2023-11-22 19:22:12 +08:00
Steven b11653658d chore: update readme 2023-11-21 20:39:48 +08:00
Cheng Jiang adf96a47bb fix: correct some Chinese translation inaccuracy (#2536)
Signed-off-by: Cheng Jiang <gabriel.chengj@gmail.com>
2023-11-21 10:58:19 +08:00
Steven 6529375a8b chore: update seed data 2023-11-19 23:58:35 +08:00
Steven e7e83874cd chore: upgrade version 2023-11-19 11:01:21 +08:00
Steven 7ef125e3af chore: update fetch tags 2023-11-19 11:01:04 +08:00
Steven dfa14689e4 chore: add click away event to date picker 2023-11-19 10:41:08 +08:00
Steven ec2995d64a chore: fix order by pinned 2023-11-19 09:42:59 +08:00
Steven 94c71cb834 chore: fix loading status 2023-11-19 09:38:04 +08:00
Steven 7f7ddf77b8 chore: update allow sign up default value 2023-11-18 12:51:07 +08:00
Steven 089cd3de87 chore: fix linter 2023-11-18 12:44:49 +08:00
zty 2d34615eac fix: parse inline latex as a inline element (#2525)
* fix:  parse inline latex as a inline element

* Update web/src/labs/marked/parser/InlineLatex.tsx

---------

Co-authored-by: zty <zty.dev@outlook.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-11-18 12:41:33 +08:00
Steven 4da3c1d5e5 chore: fix update user 2023-11-18 12:37:24 +08:00
zty 4f222bca5c fix: keep content and query param on save when access token is invalid (#2524)
fix:
keep content on save when access token is invalid

Co-authored-by: zty <zty.dev@outlook.com>
2023-11-17 10:01:14 +08:00
Steven 0bb0407f46 chore: add overflow tips to tag 2023-11-17 08:22:47 +08:00
Zexi 8bc117bce9 feat: optimize media resource display (#2518)
* feat: optimize media resource display

* fix: type error

* Update web/src/components/MemoResourceListView.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update MemoResourceListView.tsx

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-11-17 08:03:26 +08:00
Athurg Gooth afd0e72e37 chore: skip timeout for blob upload (#2516)
Skip timeout for blob upload
2023-11-15 17:23:56 +08:00
Vespa314 d758ba2702 fix: allow host role update user info (#2515) 2023-11-15 11:43:49 +08:00
Leyang 0f126ec217 docs: add obsidian plugin (#2512) 2023-11-14 23:22:54 +08:00
Steven c1a6dc9bac chore: fix home sidebar max width 2023-11-14 23:23:05 +08:00
Athurg Gooth 6ee95a2c0c fix: clear localStorage while draft is empty (#2510)
* Clear localStorage while draft is empty

* change == into ===
2023-11-14 10:02:16 +08:00
Athurg Gooth 6814915c88 feat: backup file rotate (#2511)
Add support for rotate backup files
2023-11-13 22:12:25 +08:00
Athurg Gooth 52fdf8bccd fix: persist jwt expires by cookie (#2509)
fix pesist jwt expires by cookie
2023-11-13 13:52:04 +08:00
Mahoo Huang f67757f606 feat: add editor auto focus preference (#2498)
* feat: add editor auto focus perference

* feat: set editor auto focus
2023-11-13 13:51:52 +08:00
ti777777 38f05fd6f2 chore: fix tag in http_getter.go (#2500)
Update http_getter.go

fix tag in  http_getter.go
2023-11-11 23:21:15 +08:00
Vespa314 65022beb0d fix: duplicate memo filter in user profile page (#2502) 2023-11-11 23:20:53 +08:00
swebdev 5d81338aca fix: demo banner link for self-hosting guide (#2499) 2023-11-11 19:15:24 +08:00
Steven c288d49138 chore: fix decouple user name 2023-11-10 23:08:11 +08:00
Steven 0ea0645258 chore: add use reponsive width 2023-11-10 11:22:32 +08:00
steven 9227ca5b5b chore: update debounce ms 2023-11-09 08:52:02 +08:00
steven eb6b0ddead chore: update navigation 2023-11-09 08:46:26 +08:00
Steven dca90fb5d2 chore: update header 2023-11-09 08:27:46 +08:00
steven 172e27016b chore: upgrade frontend deps 2023-11-09 08:26:00 +08:00
steven 6da2ff7ffb chore: clean logs 2023-11-09 08:25:28 +08:00
Steven 6c433b452f chore: update user checks 2023-11-08 22:58:35 +08:00
Steven 65a34ee41a chore: update home sidebar 2023-11-08 22:18:12 +08:00
Steven 5ff0234c71 chore: update response styles 2023-11-08 22:10:15 +08:00
Steven e76509a577 chore: update header menu style in mobile view 2023-11-08 22:00:49 +08:00
Steven 4499f45b67 chore: deprecate daily review offset local setting 2023-11-08 21:49:03 +08:00
boojack 504d1768f2 chore: update i18n with Weblate (#2492)
* Translated using Weblate (Chinese (Traditional))

Currently translated at 91.7% (290 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: dwong33 <dwong@posteo.ch>
2023-11-08 13:02:24 +08:00
zty caea065594 feat: add share btn in more-action (#2491)
Co-authored-by: zty <zty.dev@outlook.com>
2023-11-08 10:34:07 +08:00
Athurg Gooth 2ee426386a fix: skip system_setting check while copydb (#2490)
Skip system_setting check while copydb
2023-11-08 10:06:27 +08:00
boojack 9df05fe0fa chore: update i18n from Weblate (#2489)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-11-07 22:39:27 +08:00
zty 184f79ef8e feat: support code in headings (#2488)
Co-authored-by: zty <zty.dev@outlook.com>
2023-11-07 22:38:38 +08:00
Athurg Gooth 35f0861d6e fix: prevent copydb to create a fresh memos (#2486)
Prevent copydb to create a fresh memos
2023-11-07 13:53:53 +08:00
Steven c4d27e7a78 chore: update backend dependencies 2023-11-07 07:36:16 +08:00
Steven 7e545533cf chore: update resource cache control 2023-11-07 07:24:41 +08:00
Steven 32cafbff9b chore: add OverflowTip kit component 2023-11-07 07:20:17 +08:00
Steven 9c4f72c96e chore: update tooltips 2023-11-07 07:06:38 +08:00
Steven 5e4493b227 chore: remove debug codes 2023-11-06 23:20:26 +08:00
Steven 834b58fbbd feat: add version update inbox message 2023-11-06 22:53:55 +08:00
Steven 342d1aeefb fix: version checker 2023-11-06 22:33:12 +08:00
Steven 363c107359 chore: update frontend deps 2023-11-06 21:08:09 +08:00
boojack 0458269e15 revert: "chore: add frontend type definitions" (#2483)
Revert "chore: add frontend type definitions (#2482)"

This reverts commit 64d4db81ca.
2023-11-06 21:01:17 +08:00
boojack 64d4db81ca chore: add frontend type definitions (#2482)
chore: update
2023-11-06 21:00:42 +08:00
Steven 865cc997a4 chore: remove upgrade version banner 2023-11-06 20:51:59 +08:00
Steven 981bfe0464 feat: add version checker 2023-11-06 20:49:02 +08:00
Steven 695fb1e0ca chore: update migration history store 2023-11-06 08:33:31 +08:00
Steven 21ad6cc871 chore: update tag service creator 2023-11-06 08:05:07 +08:00
Steven c24181b2be chore: fix jwt checks 2023-11-05 23:39:30 +08:00
Steven 39a0e69b04 chore: update function name 2023-11-05 23:28:09 +08:00
Steven e60e47f76f chore: update user definition 2023-11-05 23:03:43 +08:00
Steven e67820cabe chore: update list user api permission 2023-11-05 22:35:09 +08:00
Steven 3266c3a58a chore: update link styles 2023-11-05 22:26:09 +08:00
Steven ef820a1138 chore: fix memo editor padding in daily review 2023-11-05 21:42:02 +08:00
Steven 137e64b0dd chore: update metrics 2023-11-05 21:41:47 +08:00
Steven 982b0285c9 chore: fix date picker 2023-11-05 16:02:51 +08:00
Steven 405fc2b4d2 chore: simplify find migration history 2023-11-05 15:49:57 +08:00
Steven eacd3e1c17 chore: fix mysql latest schema 2023-11-05 15:38:45 +08:00
Christopher a62f1e15a6 fix: private memos being public (#2480)
* fix(web/memo): filter out public option

Filter out the public option if we have disabled public memos

* feat(api/memo): sanity check for disabled public memos

In case something goes wrong, we check the system setting on the backend in order to valdiate if we can create a public memo

* refactor(web/memo): disable public option

Seems like a better option than removing it, as it looks werid if you are looking at a memo that is previously public

* fix(web/memo): use translation keys

* chore(web/editor): remove unsused tooltip

* revert(api/memo): sanity check

* fix(web/memo): allow admins to create public memos

* chore(web/memo): remove unused import

* fix(web/memo): check for both host and admin

* fix(web/memo): remove warning text from MemoDetail
2023-11-05 01:19:54 +08:00
Zexi 8b0083ffc5 fix: auto fetch more (#2472)
* fix: auto fetch more

* feat: use union type
2023-11-03 05:16:55 +08:00
Athurg Gooth 5d69d89627 feat: week from monday in heatmap for zh-Hans and ko (#2457)
* week from monday in heatmap for zh-Hans and ko

* optimize code
2023-10-31 12:06:14 +08:00
Athurg Gooth b966c16dd5 fix: data too large for mysql (#2470)
* Extend some TEXT field to LONGTEXT in mysql

* move db migration version

* fix error in migrate SQL
2023-10-31 10:23:15 +08:00
Steven 97190645cc chore: update memo editor styles 2023-10-29 23:59:23 +08:00
Steven c26417de70 chore: update docs links 2023-10-29 18:36:09 +08:00
Steven f5c1e79195 chore: update about dialog 2023-10-28 15:17:33 +08:00
Steven d02105ca30 chore: update i18n 2023-10-28 15:10:20 +08:00
Steven 44e50797ca chore: update go mods 2023-10-28 14:57:39 +08:00
Steven 7058f0c8c2 chore: add docs link in settings 2023-10-28 14:56:08 +08:00
Steven f532ccdf94 chore: upgrade frontend deps 2023-10-28 14:55:57 +08:00
Steven a6fcdfce05 chore: update memo comment i18n 2023-10-28 11:39:10 +08:00
Steven dca712d273 chore: fix resource tests 2023-10-28 10:51:03 +08:00
Steven ac81d856f6 chore: delete resource file sync 2023-10-28 10:42:39 +08:00
Steven 88fb79e458 chore: impl inbox store for mysql 2023-10-28 09:44:52 +08:00
Steven 480c53d7a2 chore: fix id converter 2023-10-28 09:04:32 +08:00
Steven 2b7d7c95a5 chore: update inbox detect 2023-10-28 09:02:02 +08:00
Steven 0ee938c38b chore: remove unused inbox status 2023-10-28 02:49:35 +08:00
Steven 3c36cc2953 feat: add inbox ui 2023-10-28 02:43:46 +08:00
Steven 79bb3253b6 chore: add activity service 2023-10-28 00:21:53 +08:00
Steven 18107248aa chore: rename list inbox 2023-10-28 00:08:42 +08:00
Athurg Gooth 4f1bb55e55 fix: metric env not affect (#2450)
fix metric env not affect
2023-10-27 23:26:23 +08:00
Athurg Gooth 20d3abb99a chore: downgrade log level for auto backup disable (#2454)
downgrade log level for auto backup disable
2023-10-27 23:25:51 +08:00
Steven 1b34119e60 chore: update activity store definition 2023-10-27 23:24:56 +08:00
Steven 9d2b785be6 chore: fix inbox test 2023-10-27 23:17:17 +08:00
Steven 36b4ba33fa chore: remove outdated activity definition 2023-10-27 23:11:56 +08:00
Steven 625ebbea1a chore: update proto linter action 2023-10-27 21:49:07 +08:00
Athurg Gooth 0f4e5857f0 chore: remove gRPC listener (#2456)
Disable gRPC listener
2023-10-27 21:38:17 +08:00
Athurg Gooth 76d955a69a chore: docker compose dev (#2458)
* add golang build cache volume to speedup build

* replace `lint` with `npm` to run more scripts

* wrap golangci-lint as entrypoint instead of command
2023-10-27 21:21:52 +08:00
Athurg Gooth e41ea445c9 fix: missing relation after post comment (#2452)
fix missing relation after post comment
2023-10-27 10:12:25 +08:00
boojack c952651dc1 chore: update i18n from Weblate (#2455)
* Translated using Weblate (Croatian)

Currently translated at 92.3% (290 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

* Translated using Weblate (Korean)

Currently translated at 100.0% (314 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

---------

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
Co-authored-by: nulta <un5450@naver.com>
2023-10-27 10:12:02 +08:00
Steven 58e771a1d7 chore: combine v2 services 2023-10-27 09:07:35 +08:00
Steven e876ed3717 feat: impl part of inbox service 2023-10-27 09:01:17 +08:00
Steven 67d2e4ebcb chore: update method name 2023-10-27 08:36:43 +08:00
Steven 4ea78fa1a2 chore: impl inbox store methods 2023-10-27 08:17:58 +08:00
Steven 93b8e2211c chore: update dev latest schema 2023-10-27 01:18:00 +08:00
Steven 052216c471 chore: fix list activities typo 2023-10-27 01:11:41 +08:00
Steven e5978a70f5 chore: initial inbox store model 2023-10-27 01:10:19 +08:00
Steven 59f0ee862d chore: fix viper default value 2023-10-27 00:49:58 +08:00
Athurg Gooth 215981dfde chore: remote context.Context pointer (#2448)
remote context.Context pointer
2023-10-26 20:21:44 +08:00
Athurg Gooth bfdb33f26b chore: add a flag to change metric switch (#2447)
* add a flag to change metric switch

* change the default value of metric
2023-10-26 20:21:18 +08:00
Steven 5b3af827e1 chore: move common packages to internal 2023-10-26 09:02:50 +08:00
Steven 9859d77cba chore: update links 2023-10-26 09:00:36 +08:00
Athurg Gooth 064c930aed fix: validate username before create token (#2439)
Validate username before create token
2023-10-25 12:05:44 +08:00
Athurg Gooth 043357d7dc fix: list token for others failed (#2440)
Fix list token for others failed
2023-10-25 12:05:30 +08:00
Athurg Gooth 3a5deefe11 chore: disable NPM update notice while running lint (#2438)
Disable NPM update notice while running lint
2023-10-25 10:00:45 +08:00
Athurg Gooth 2c71371b29 chore: update @typescript-eslint to avoid WARNING (#2437)
Update @typescript-eslint to avoid WARNING
2023-10-25 10:00:30 +08:00
Steven 222e6b28b7 chore: update website links in readme 2023-10-25 07:43:52 +08:00
Athurg Gooth 496cde87b2 feat: list access tokens by admin (#2434)
* Allow admin user list access_tokens of anyone

* fix undefined variable

* Update api/v2/user_service.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-10-24 18:51:01 +08:00
Athurg Gooth 79bbe4b82a feat: support filter creator in /api/v2/memos (#2432)
* Add creator_id param in /api/v2/memos

* make creator_id optional
2023-10-23 21:32:58 +08:00
Zexi 035d71e07c fix: visibility translation (#2429)
* fix: visibility translation

* refactor: remove useless file

* feat: add visibility icon
2023-10-23 08:06:59 +08:00
Christopher 82effea070 tweak(web): use iconbutton for editor helpers (#2426) 2023-10-22 22:10:27 +08:00
Lincoln Nogueira 331f4dcc1b chore: update dev scripts (#2427)
- add type-gen
- remove some unused air settings
- restrict air monitoring to changed go files
2023-10-22 22:09:25 +08:00
Lincoln Nogueira 055b246857 chore: update ci (#2428)
- restrict codeql and backend tests from running on pull requests with unrelated files
- upgrade codeql: current version is generating a deprecation warning in logs
2023-10-22 22:08:38 +08:00
boojack 8fc9a318a4 chore: translated using Weblate (Portuguese (Brazil)) (#2422)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (314 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-10-22 12:27:29 +08:00
MotH 9aed80a4fd feat: better tag suggestion (#2421)
Better Tag Suggestion
2023-10-22 09:15:25 +08:00
MotH c31f306b5b fix: smaller logo file (#2418) 2023-10-22 05:51:37 +08:00
Steven bfd2dbfee2 chore: fix update resource api 2023-10-21 12:41:55 +08:00
Steven c42af95dd3 chore: fix update user 2023-10-21 12:22:23 +08:00
Steven 89a073adc0 chore: implement create user api v2 2023-10-21 12:19:06 +08:00
Steven 1c2d82a62f chore: remove major label 2023-10-21 09:36:50 +08:00
Steven 02f7a36fa4 chore: remove unsupported linux/arm/v7 2023-10-21 08:29:21 +08:00
Steven a76f762196 chore: update memo share dialog 2023-10-21 08:19:25 +08:00
Steven 2c2955a229 chore: add back linux/arm/v7 2023-10-21 08:15:25 +08:00
Steven d06d01cef2 chore: release mysql driver 2023-10-21 01:25:07 +08:00
boojack 4b91738f21 chore: translated using Weblate (Croatian) (#2413)
Translated using Weblate (Croatian)

Currently translated at 87.5% (274 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
2023-10-21 01:23:12 +08:00
Steven 12fd8f34be chore: fix styles 2023-10-21 01:23:21 +08:00
Steven c2ab05d422 chore: fix member section style 2023-10-21 01:09:52 +08:00
Steven 7b25b8c1e1 feat: update daily review 2023-10-21 00:57:44 +08:00
Athurg Gooth af7c0a76d0 fix: fail to update user's update_ts (#2410) 2023-10-20 19:10:38 +08:00
Athurg Gooth 664c9c4a7c chore: extend height of setting page (#2407)
Extend height of setting page
2023-10-20 17:41:37 +08:00
Athurg Gooth fd5d51ee54 fix: some fields of profile leaked without auth (#2408)
* fix some fields of profile leaked without auth

* protect driver and dsn of profile
2023-10-20 17:41:21 +08:00
Steven 1b105db958 chore: fix field syntax 2023-10-20 08:52:16 +08:00
Steven a541e8d3e3 chore: upgrade version 2023-10-20 08:49:58 +08:00
Steven 6f2ca6c87a chore: update find memo api 2023-10-20 08:48:52 +08:00
Steven 952539f817 chore: update memo editor dialog 2023-10-20 08:19:08 +08:00
Steven c87b679f41 chore: add memo relation list 2023-10-19 21:26:38 +08:00
Baksi e6b20c5246 chore: update Shortcuts link (#2405)
* Update Shortcuts

* Update README.md

* Update README.md
2023-10-19 04:56:59 -05:00
Athurg Gooth 0bfcff676c feat: add support for remember sign in (#2402) 2023-10-18 20:38:49 -05:00
Athurg Gooth 37601e5d03 chore: change the timeout value of golangci-lint (#2403) 2023-10-18 20:37:35 -05:00
Steven 21c70e7993 feat: update memo relations dialog 2023-10-19 00:18:07 +08:00
Athurg Gooth 22d331d6c4 chore: switch storage of selected date in DailyReview (#2399)
Switch storage of selected date in DailyReview
2023-10-18 09:06:34 -05:00
Steven 9bfb2d60b9 chore: tweak wording 2023-10-18 06:05:19 +08:00
Steven 203b2d9181 chore: fix container styles 2023-10-18 06:02:39 +08:00
boojack ddc4566dcb chore: translated using Weblate (German) (#2396)
Translated using Weblate (German)

Currently translated at 99.6% (312 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

Co-authored-by: Frank Emmerlich <femmdi2012@gmail.com>
2023-10-17 10:49:36 -05:00
Steven 1755c9dc79 chore: update button style 2023-10-17 23:49:26 +08:00
Steven a5df36eff2 chore: update metrics 2023-10-17 23:44:16 +08:00
Athurg Gooth e30d0c2dd0 fix: image width error while loading (#2394)
fix image width error while loading
2023-10-17 09:00:45 -05:00
boojack 213c2ea71b chore: translated with Weblate (German) (#2390)
Translated using Weblate (German)

Currently translated at 99.6% (312 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

Co-authored-by: Frank Emmerlich <femmdi2012@gmail.com>
2023-10-16 11:21:11 -05:00
guopeng 73f59eaf09 fix: storage setting changed don't take effect (#2385)
* fix: Storage setting changed don't take effect

* fix: Storage setting changed don't take effect

* fix: Storage setting changed don't take effect
2023-10-16 08:07:21 -05:00
TianLun Song c999d71455 chore: update iOS shortcut link (#2387)
* Update README.md

New shortcut for memos version 0.15.0 and above on IOS

* Update README.md

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-10-16 08:06:36 -05:00
Steven 5359d5a66d chore: add container-queries tailwind plugin 2023-10-14 14:13:55 +08:00
Steven c58820fa64 chore: update username regexp 2023-10-14 13:42:27 +08:00
Steven cfc5599334 chore: cleanup less files 2023-10-14 12:06:24 +08:00
Steven c02f3c0a7d chore: remove less files in editor 2023-10-14 11:55:37 +08:00
Steven dd83358850 chore: update some styles 2023-10-14 01:12:41 +08:00
Steven d95a6ce898 chore: add ar locale item 2023-10-14 00:25:01 +08:00
boojack 7e80e14f16 chore: add Arabic from weblate (#2382)
* Added translation using Weblate (Arabic)

* Translated using Weblate (Arabic)

Currently translated at 46.6% (146 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ar/

---------

Co-authored-by: Ali AlShaikh <Mi3LiX9@outlook.sa>
2023-10-13 11:11:56 -05:00
Steven 219304e38d chore: update frontend deps 2023-10-13 23:29:55 +08:00
Steven 20e5597104 chore: fix memo container max width 2023-10-13 23:26:56 +08:00
Athurg Gooth ed2e299797 fix: invalid type convert in apiv2 (#2380)
fix invalid type convert in apiv2
2023-10-13 09:53:58 -05:00
boojack bacc529391 chore: fix linter errors (#2381)
* chore: fix linter errors

* chore: update

* chore: update
2023-10-13 09:53:02 -05:00
Steven ed1ff11e80 chore: update 2023-10-13 00:13:13 +08:00
Steven a0f8e6987c chore: update go deps 2023-10-13 00:08:52 +08:00
Athurg Gooth d3e32f0d5a chore: add latency in log (#2374)
* Print profile.Data in boot log

* Add latency in request log
2023-10-10 06:03:32 -05:00
Athurg Gooth 95bfcb8055 chore: print profile.Data in boot log (#2373)
Print profile.Data in boot log
2023-10-10 05:59:19 -05:00
Athurg Gooth 096c489eb3 feat: copy data between drivers (#2370)
* Add copydb command to copy data between drivers

* Check if table is empty before copy
2023-10-09 22:45:17 -05:00
boojack b6425f9004 chore: update i18n with weblate (#2369)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Qing Long <longyinx@duck.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2023-10-09 10:54:54 -05:00
Steven ab2c86640b chore: move rate limiter to apiv1 2023-10-09 23:10:41 +08:00
Steven 1489feb054 chore: update common dialog default color 2023-10-09 23:08:52 +08:00
Steven acdeabb861 chore: add issue template config.yml 2023-10-09 22:10:28 +08:00
Athurg Gooth 6bb6c043e5 feat: add support for ListMemoOrganizer (#2367)
* Add support for ListMemoOrganizer

* fix rows not close
2023-10-09 08:18:47 -05:00
Athurg Gooth fa2bba51c1 feat: add support for ListActivity (#2365)
Add support for ListActivity
2023-10-09 08:18:33 -05:00
Steven 3822c26e32 chore: update memo props 2023-10-09 21:09:17 +08:00
Athurg Gooth 425b43b3bb fix: ListTag not support omit params (#2366)
fix ListTag not support omit params
2023-10-09 01:40:54 -05:00
Athurg Gooth c00dac1bbf fix: index page failed with 429 (#2363) 2023-10-08 20:54:12 -05:00
Steven 3ff4d19782 chore: update initial global loader 2023-10-08 20:31:38 +08:00
Steven 31997936d6 chore: move resource public api 2023-10-08 19:40:30 +08:00
Athurg Gooth 287f1beb90 fix: create storage without some attributes (#2358) 2023-10-08 05:30:24 -05:00
Athurg Gooth 7680be1a2f fix: create user without some attributes (#2357) 2023-10-08 05:29:32 -05:00
Athurg Gooth 55e0fbf24e fix: create activity without some attributes (#2356) 2023-10-08 05:29:22 -05:00
Athurg Gooth eaac17a236 fix: create memo without some attributes (#2355) 2023-10-08 05:29:12 -05:00
Athurg Gooth 1fbd568dfe fix: create resource without some attributes (#2354) 2023-10-08 05:29:03 -05:00
Athurg Gooth c0619ef4a4 fix: CreateIdentityProvider without id (#2352) 2023-10-08 05:28:22 -05:00
Athurg Gooth b2aa66b4fd fix: migration always in mysql (#2353) 2023-10-08 05:28:11 -05:00
boojack dfaf2ee29c chore: update pnpm scripts (#2350)
* chore: update pnpm scripts

* chore: update development guide
2023-10-07 12:06:18 -05:00
Steven b938c8d7b6 chore: only show comments in memo detail page 2023-10-08 00:42:02 +08:00
Steven 553de3cc7e fix: mysql syntax 2023-10-07 22:56:12 +08:00
Steven 73980e9644 chore: fix video element syntax 2023-10-07 22:01:07 +08:00
Athurg Gooth 087e631dd8 chore: optmize docker-compose.dev.yml (#2347)
Optmize docker-compose.dev.yml
2023-10-07 08:24:53 -05:00
boojack 76fb280720 chore: translated with Weblate (#2348)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Qing Long <longyinx@duck.com>
2023-10-07 08:23:06 -05:00
Steven 6ffc09d86a chore: remove unused httpmeta getter api 2023-10-06 23:03:36 +08:00
白宦成 125c9c92eb chore: compress image and reduce 500kb in network (#2339)
feat: compress image and reduce 500kb in network
2023-10-06 07:45:17 -05:00
Steven 15eb95f964 chore: delete resource file synchronously 2023-10-06 19:02:40 +08:00
boojack ed96d65645 chore: update i18n with weblate (#2338)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Qing Long <longyinx@duck.com>
2023-10-06 05:29:50 -05:00
boojack 9c2f87ec2e chore: update i18n with weblate (#2337)
* Translated using Weblate (English)

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 98.4% (310 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@gmail.com>
2023-10-05 22:49:38 -05:00
Steven 19f6ed5530 chore: remove pr preview actions 2023-10-06 11:00:17 +08:00
Steven 57c5a92427 chore: update archived memo styles 2023-10-06 00:34:40 +08:00
Steven 9410570195 chore: update version 2023-10-06 00:34:38 +08:00
Steven c0422dea5b chore: fix sqlite migrator 2023-10-06 00:34:06 +08:00
Steven 7791fb10d8 chore: update new db driver 2023-10-05 23:19:52 +08:00
Steven a6ee61e96d chore: update package name 2023-10-05 23:11:29 +08:00
boojack 99d9bd2d75 chore: update i18n with weblate (#2333)
* Translated using Weblate (Dutch)

Currently translated at 85.7% (271 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 85.4% (270 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (German)

Currently translated at 88.9% (281 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

* Translated using Weblate (Russian)

Currently translated at 86.7% (274 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

* Translated using Weblate (Japanese)

Currently translated at 90.8% (287 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Croatian)

Currently translated at 86.3% (273 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

* Translated using Weblate (Hindi)

Currently translated at 68.0% (215 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hi/

* Translated using Weblate (Italian)

Currently translated at 89.2% (282 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/it/

* Translated using Weblate (Korean)

Currently translated at 89.2% (282 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 90.8% (287 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 89.8% (284 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (English)

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

---------

Co-authored-by: Jasper Platenburg <jasperdgp@outlook.com>
Co-authored-by: memos <usememos@gmail.com>
2023-10-05 08:36:23 -05:00
boojack e7aeca736b chore: update i18n with weblate (#2332)
* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Translated using Weblate (Dutch)

Currently translated at 77.8% (246 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 78.4% (248 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 78.7% (249 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 79.1% (250 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 79.7% (252 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 81.6% (258 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

---------

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Jasper Platenburg <jasperdgp@outlook.com>
2023-10-05 04:36:00 -05:00
Steven e85f325eb2 chore: add tranlated status badge 2023-10-05 17:32:23 +08:00
Steven 7dcc5cbaf1 chore: fix mysql migrator 2023-10-05 17:11:28 +08:00
Steven 1cdd70e008 chore: update dark mode styles 2023-10-05 16:16:02 +08:00
Steven 6a11fc571d chore: update empty icon 2023-10-05 15:52:16 +08:00
Steven 771fe394fd chore: fix initial guide 2023-10-05 15:50:16 +08:00
Steven d474d1abd0 chore: update store cache 2023-10-05 15:17:40 +08:00
Steven 576111741b chore: downgrade zustand 2023-10-05 15:13:02 +08:00
Steven 9ac44dfbd9 chore: update mui/joy version 2023-10-05 15:08:55 +08:00
Steven 110b53b899 chore: update frontend deps 2023-10-05 15:07:10 +08:00
Steven 42e8d51550 chore: update i18n 2023-10-05 15:07:03 +08:00
Steven fd7043ea40 chore: fix editor cache 2023-10-05 14:20:35 +08:00
Steven 34ae9b0687 chore: update default storage back to database 2023-10-05 13:36:33 +08:00
Steven 077bf95425 chore: add pinned icon in status bar 2023-10-05 13:12:03 +08:00
Steven e465b2f0e8 chore: update i18n for auth pages 2023-10-05 12:48:40 +08:00
Steven 01ff3f73f8 chore: update auth pages 2023-10-05 12:38:46 +08:00
Steven 8aae0d00cd chore: fix fetch comments 2023-10-05 08:58:44 +08:00
Steven 16dad8b00d chore: update logo 2023-10-05 08:40:25 +08:00
Steven 7dc4bc5714 chore: update resource service 2023-10-03 23:44:14 +08:00
K.B.Dharun Krishna 2e82ba50f2 chore: bump actions/checkout; actions/setup-go to v4 (#2325)
* chore: bump actions/checkout to v4

Signed-off-by: GitHub <noreply@github.com>

* chore: bump actions/setup-go to v4

Signed-off-by: GitHub <noreply@github.com>

---------

Signed-off-by: GitHub <noreply@github.com>
2023-10-03 16:58:47 +08:00
Steven 1542f3172a chore: update tag service 2023-10-03 09:39:39 +08:00
serverless83 69d575fd5b chore: update it.json translation (#2323)
Changed translation of "private" to "Privato" instead of "Privao" (missing the letter "t")

Signed-off-by: serverless83 <35410475+serverless83@users.noreply.github.com>
2023-10-02 20:01:16 -05:00
Steven 607fecf437 chore: update store tests 2023-10-03 00:47:34 +08:00
Steven 91f7839b31 chore: update memo detail styles 2023-10-03 00:25:22 +08:00
Steven 078bc164d5 chore: update memo relations view 2023-10-02 08:26:15 +08:00
Steven 70f464e6f2 chore: update frontend deps 2023-10-01 22:14:33 +08:00
Steven e40621eb0f chore: implement memo content views 2023-10-01 22:14:25 +08:00
Steven fd395e5661 chore: update list memo relations 2023-10-01 21:35:17 +08:00
Steven be046cae8e chore: add parent field to memo 2023-10-01 16:27:40 +08:00
Steven 922de07751 feat: impl memo comment api 2023-10-01 14:44:10 +08:00
Steven 7549c807ac chore: update memo view activity 2023-10-01 14:14:33 +08:00
Steven de5eccf9d6 chore: update icon styles 2023-09-30 02:06:30 +08:00
Steven 952225d1da chore: add back to top button 2023-09-30 02:04:13 +08:00
steven a928c4f845 chore: update error format 2023-09-29 13:04:54 +08:00
Johan 73e189ea61 chore: update fr.json (#2304)
* Update fr.json

Updated some translations

Signed-off-by: Johan <45337552+LittleJ@users.noreply.github.com>

* Apply suggestions from code review

Signed-off-by: boojack <stevenlgtm@gmail.com>

---------

Signed-off-by: Johan <45337552+LittleJ@users.noreply.github.com>
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-29 04:51:14 +00:00
steven 8168fb71a8 chore: update migrator 2023-09-29 12:47:49 +08:00
Steven 87ddeb2c79 chore: adjust store test for mysql 2023-09-29 09:15:54 +08:00
Athurg Gooth 255254eb69 feat: add some dev tools in the docker compose (#2309)
* Add some dev tools in the docker compose

* Merge tsc and lint
2023-09-28 14:54:11 +00:00
Athurg Gooth c72f221fc0 feat: support mysql as backend storage driver (#2300)
* Rename checkDSN to checkDataDir

* Add option to set DSN and db driver

* Add mysql driver skeleton

* Add mysql container in compose for debug

* Add basic function for mysql driver

* Cleanup go mod with tidy

* Cleanup go.sum with tidy

* Add DeleteUser support for mysql driver

* Fix UpdateUser of mysql driver

* Add DeleteTag support for mysql driver

* Add DeleteResource support for mysql driver

* Add UpdateMemo and DeleteMemo support for mysql driver

* Add MemoRelation support for mysql driver

* Add MemoOrganizer support for mysql driver

* Add Idp support for mysql driver

* Add Storage support for mysql driver

* Add FindMemosVisibilityList support for mysql driver

* Add Vacuum support for mysql driver

* Add Migration support for mysql driver

* Add Migration support for mysql driver

* Fix ListMemo failed with referece

* Change Activity.CreateTs type in MySQL

* Change User.CreateTs type in MySQL

* Fix by golangci-lint

* Change Resource.CreateTs type in MySQL

* Change MigrationHistory.CreateTs type in MySQL

* Change Memo.CreateTs type in MySQL
2023-09-28 09:09:52 -05:00
CorrectRoadH 4ca2b551f5 chore: update seed data (#2311) 2023-09-28 09:03:32 -05:00
Athurg Gooth 5b6b2f0528 fix: apiv2 failed in container (#2307) 2023-09-28 05:45:45 -05:00
Steven fbbfb11916 chore: adjust memo elements 2023-09-28 08:59:55 +08:00
Steven c54febd024 chore: fix reset script 2023-09-27 18:55:26 +08:00
Athurg Gooth 5ebf920a61 chore: stop process on build error (#2295)
* Move migration and seed code into driver

* Stop process on build error
2023-09-27 11:56:39 +08:00
Athurg Gooth 5121e9f954 chore: move migration and seed code into driver (#2294)
Move migration and seed code into driver
2023-09-27 11:56:20 +08:00
Athurg Gooth ca98367a0a chore: store vacuum and clean (#2293)
* Move all vacuum code into driver

* Remove db from Store
2023-09-26 20:27:31 -05:00
Steven 9abf294eed chore: update seed data 2023-09-27 09:13:56 +08:00
Athurg Gooth 9ce22e849c chore: move SQL code of Memo into Driver (#2292) 2023-09-27 00:57:12 +00:00
Athurg Gooth 58b84f83d1 chore: move SQL code of MemoOrganizer into Driver (#2291) 2023-09-26 19:54:50 -05:00
Athurg Gooth acbde4fb2d chore: move SQL code of MemoRelation into Driver (#2290) 2023-09-26 19:43:46 -05:00
Steven 53090a7273 chore: show unused resources in dashboard 2023-09-27 08:09:30 +08:00
Steven 71ee299de7 chore: drop shortcut 2023-09-27 07:28:17 +08:00
Steven 9d1c9fc505 chore: regenerate swagger docs 2023-09-27 00:52:42 +08:00
Steven 03a0972712 chore: rename sqlite entry file name 2023-09-27 00:51:16 +08:00
Steven 0bddbba00e chore: fix frontend linter 2023-09-27 00:45:15 +08:00
Steven 6007f48b7d chore: retire memo resource relation table 2023-09-27 00:40:16 +08:00
Steven 4f10198ec0 chore: add tooltip to icon buttons 2023-09-26 23:48:34 +08:00
Steven 7722c41680 chore: add edit button to memo detail page 2023-09-26 23:46:58 +08:00
Steven 7cdc5c711c chore: update key of daily memo 2023-09-26 23:34:35 +08:00
Steven 4180cc3a3d refactor: migrate storage to driver 2023-09-26 19:43:55 +08:00
Steven d6789550a0 refactor: migrate tag to driver 2023-09-26 19:37:22 +08:00
Steven d68da34eec refactor: migrate idp to driver 2023-09-26 19:17:17 +08:00
Steven 63b55c4f65 chore: fix tests 2023-09-26 19:15:18 +08:00
Steven 96395b6d75 chore: rename package sqlite3 to sqlite 2023-09-26 19:07:14 +08:00
Athurg Gooth d3a6fa50d6 chore: move sql code of Resource into driver (#2286)
Move sql code of Resource into driver
2023-09-26 19:04:07 +08:00
May Kittens Devour Your Soul 47f22a20ba chore: update Croatian (#2283)
* Add files via upload

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Update hr.json

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Update hr.json

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Delete web/src/css/prism.css

Signed-off-by: boojack <stevenlgtm@gmail.com>

---------

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-26 19:03:50 +08:00
Athurg Gooth 14ec524805 chore: move sql code of UserSetting into Driver (#2282)
* Move SQL code of UserSetting into Driver

* Fix golang import issue
2023-09-26 19:02:48 +08:00
Athurg Gooth fcba3ffa26 chore: move sql code of User into driver (#2281)
Move SQL code of User into Driver
2023-09-26 18:23:45 +08:00
Athurg Gooth 41eba71f0f chore: split sql to driver (#2279)
* Add new database interface for SQL operations

* Move SQL code of Activity into Database

* Rename `Database` into `Driver`

* Move SQL code of SystemSetting into Driver

* Fix store.New in text code

* Change database into driver in the variables

* Change sqlite3.New into sqlite3.NewDriver
2023-09-26 17:16:58 +08:00
Steven 85ed0202d8 chore: fix user request cache 2023-09-25 20:52:29 +08:00
Steven 745902e8b1 chore: update access token order 2023-09-25 20:14:01 +08:00
Steven ad3487a9ac chore: update username matcher 2023-09-25 20:03:58 +08:00
Steven 8c2f89edc5 chore: update demo username 2023-09-25 09:10:39 +08:00
Steven 6cff920f0c chore: update user demo data 2023-09-23 20:41:47 +08:00
Steven 27f3f6fbf0 chore: upgrade version 2023-09-23 20:41:42 +08:00
Steven 89c24415a6 chore: update not found page 2023-09-23 20:39:01 +08:00
Steven 0d803bf45f chore: update dark mode styles 2023-09-23 20:30:47 +08:00
Steven d4e54f343d feat: update memo detail page 2023-09-23 20:14:07 +08:00
Steven 08a81e79dd chore: update frontend deps 2023-09-23 17:55:26 +08:00
Steven cad789e948 chore: update frontend deps 2023-09-21 23:41:05 +08:00
Steven 4de18cfab1 chore: remove unused deps 2023-09-20 21:24:46 +08:00
Steven 5cec1a71da chore: update access token generator 2023-09-20 20:48:34 +08:00
Steven ae1e22931f chore: auto remove current access token when sign out 2023-09-20 19:24:26 +08:00
Steven a60d4dee41 chore: remove lazy loading image 2023-09-19 23:06:30 +08:00
Steven 7da10cd367 chore: update telegram integration folder 2023-09-19 22:35:20 +08:00
Steven 6d45616dbe chore: add cors middleware 2023-09-19 20:34:25 +08:00
Fabian Wünderich ad326147f1 chore: fix typo in german localization (#2256)
Fix typo in german localization

Signed-off-by: Fabian Wünderich <fabian@wuenderich.de>
2023-09-19 20:21:32 +08:00
Steven 465b173b36 chore: fix resource int type 2023-09-19 09:05:34 +08:00
Steven 9bf1979fa8 fix: list resources 2023-09-19 08:24:24 +08:00
Steven 0a811e19ba chore: remove arm/v7 form platforms 2023-09-19 00:34:27 +08:00
Steven e119acb0e9 chore: remove unused platform of test image 2023-09-19 00:08:58 +08:00
Steven 0f1e87bd93 chore: update test image platforms 2023-09-18 23:28:28 +08:00
Steven f9f2f549af chore: update dockerfile 2023-09-18 23:23:13 +08:00
Steven d665adf78b chore: remove outdate build artifacts action 2023-09-18 22:56:39 +08:00
Steven 1c27824e58 chore: upgrade version 2023-09-18 22:54:44 +08:00
Steven 14adcb56da chore: update resource description 2023-09-18 22:46:24 +08:00
Steven b452d63fa6 chore: skip compose memo error 2023-09-18 22:41:49 +08:00
Steven e2b82929ab chore: fix daily review params 2023-09-18 22:38:52 +08:00
Steven 8fbd33be09 chore: update username matcher 2023-09-18 22:37:13 +08:00
Steven bff41a8957 fix: invalid username checks 2023-09-18 22:34:31 +08:00
Steven 2375001453 chore: fix acl interceptor 2023-09-18 21:50:59 +08:00
Zeng1998 462f10ab60 feat: optimize the logic of the checkbox button. (#2227) 2023-09-18 20:37:28 +08:00
Vespa314 58026c52ea fix: heatmap show on wrong date (#2243)
fix: heatmap show wrong date
2023-09-18 13:53:16 +08:00
victorsch 97b434722c fix: content sanitization in getimage endpoint (#2241) 2023-09-18 12:45:26 +08:00
Steven b22d236b19 chore: update golangci-lint version 2023-09-17 23:21:03 +08:00
Steven cc809a5c06 chore: update github action trigger 2023-09-17 23:18:18 +08:00
Steven cd0ea6558d chore: update golangci-lint config 2023-09-17 22:55:13 +08:00
Steven 9eb077c4af chore: update service clients 2023-09-17 21:12:23 +08:00
Steven 6eeee6b704 docs: add buf to development guide 2023-09-17 20:56:03 +08:00
boojack b13042d644 chore: move buf generated code to gitignore (#2236) 2023-09-17 20:55:05 +08:00
Steven d09e3c3658 chore: remove buf es generator 2023-09-17 20:14:45 +08:00
Steven 72ca4e74ee refactor: impl part of grpcweb 2023-09-17 19:20:03 +08:00
Steven d5c1706e9c chore: update api middlewares 2023-09-17 18:11:13 +08:00
Steven 3a1f82effa fix: migration script 2023-09-16 14:10:51 +08:00
Steven a3d7cc9392 fix: migration script 2023-09-16 14:01:05 +08:00
Steven 178a5c0130 chore: upgrade version to 0.15.0 2023-09-16 12:46:26 +08:00
Steven b233eaea97 chore: update docs link 2023-09-16 12:25:57 +08:00
Steven 51137e01ef chore: update resource description 2023-09-16 11:53:16 +08:00
Steven fb1490c183 feat: impl resources list page 2023-09-16 11:48:53 +08:00
Steven 4424c8a231 chore: add resource service definition 2023-09-16 00:11:07 +08:00
Steven 723e6bcdae refactor: update resources page 2023-09-15 22:25:07 +08:00
Steven d1156aa755 chore: update account setting styles 2023-09-15 22:09:51 +08:00
Steven 4e49d3cb22 chore: update frontend deps 2023-09-15 21:50:50 +08:00
Athurg Gooth 13c7871d20 chore: update vite dev server proxy setting (#2222)
fix vite proxy setting to keep the request headers
2023-09-15 21:49:34 +08:00
Athurg Gooth 137c8f8a07 chore: better date picker (#2220)
* Add buttons to increase year in DatePicker

* Show month with padding 0 to keep DatePicker size
2023-09-15 21:48:52 +08:00
Athurg Gooth 0c0c72c3ca chore: optimize layout of image resources (#2221)
Optimize layout of image resource
2023-09-15 17:58:17 +08:00
steven e6a90a8be8 chore: register reflection grpc server 2023-09-15 17:57:45 +08:00
Steven e65282dcc5 chore: fix user state loader 2023-09-15 09:10:16 +08:00
Steven 28a1888163 chore: fix user seed data 2023-09-15 08:55:18 +08:00
Steven 8824ee9b9d chore: fix user state loader 2023-09-15 08:43:52 +08:00
Steven 936fe5ac9d chore: update state initial loader 2023-09-15 08:31:19 +08:00
Steven f5802a7d82 chore: update access token ui 2023-09-15 08:18:30 +08:00
Steven 33d9c13b7e chore: remove openid field from user 2023-09-14 22:57:27 +08:00
Steven 42bd9b194b feat: impl user access token api 2023-09-14 20:16:17 +08:00
Athurg Gooth 41e26f56e9 chore: persist selected date of DailyReview page (#2219)
* Persist selected date of DailyReview page

* Use hook useLocalStorage instead of useState

* Update web/src/pages/DailyReview.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>
Signed-off-by: Athurg Gooth <athurg@gooth.org>

---------

Signed-off-by: Athurg Gooth <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-14 19:57:44 +08:00
Steven 14aa3224ce chore: add readme about protobuf 2023-09-14 19:21:21 +08:00
Steven 8a796d12b4 chore: add user access token setting definition 2023-09-14 19:18:54 +08:00
Athurg Gooth c87df8791b chore: optimize performance of /memo/stats (#2218)
Optimize performance of /memo/stats
2023-09-14 14:18:29 +08:00
Steven f0f42aea9f chore: fix react use imports 2023-09-13 22:56:02 +08:00
Athurg Gooth 626ff5e3a7 feat: notify by telegram while new memo create by HTTP (#2215)
* Inject telegram bot into API service

* Add support for send telegram message

* Send notification by telegram while new memo post
2023-09-13 21:36:43 +08:00
Steven 36209eaef1 feat: add content cache for memo editor 2023-09-13 21:32:21 +08:00
Steven d63715d4d9 feat: implement list memos filter 2023-09-13 20:42:44 +08:00
Kada Liao 9600fbb609 fix: multiple inline latex parsing (#2214) 2023-09-13 17:58:52 +08:00
Steven 04595a5fb1 chore: update resource icons 2023-09-13 09:12:51 +08:00
Kada Liao 9a0ada6756 feat: support LaTeX with react-katex (#2209)
feat: support latex

Co-authored-by: liaoxingyi <liaoxingyi@douban.com>
2023-09-12 23:53:46 +08:00
Steven 416e07cb1f fix: inject additional style and scripts 2023-09-12 23:43:32 +08:00
Steven 58429f88a0 fix: memo filter in daily review 2023-09-12 23:38:13 +08:00
Steven 439d88f06b chore: fix user avatar style 2023-09-12 23:35:10 +08:00
Steven d165ad187c chore: pnpm update 2023-09-12 08:25:57 +08:00
Steven 319f679e30 chore: fix timestamp type 2023-09-10 23:52:35 +08:00
Steven b6d1ded668 chore: adjust initial states 2023-09-10 23:44:06 +08:00
Steven 3ad0832516 chore: use user v2 api in frontend 2023-09-10 22:03:12 +08:00
Steven 93f062d0b9 chore: update user v2 api 2023-09-10 18:56:24 +08:00
Steven 866937787c chore: clean duplicated requests 2023-09-10 11:43:38 +08:00
Steven ca336af4fa chore: update locale checks 2023-09-10 10:53:37 +08:00
Steven 7ec5d07cb8 chore: remove fullscreen button 2023-09-10 10:48:08 +08:00
Steven 2e79fe12e2 chore: remove helm folder 2023-09-10 10:39:46 +08:00
Steven 3df550927d chore: update user profile page 2023-09-10 10:33:22 +08:00
Willian Ricardo Da Silva 44be7201c0 chore: update pt-BR.json (#2196)
* chore: update pt-BR.json

* update import order
2023-09-07 09:23:12 +08:00
boojack 0d50f5bd08 chore: update comments (#2195) 2023-09-06 21:59:20 +08:00
boojack 8b1f7c52aa choer: add system setting api (#2194) 2023-09-06 21:54:12 +08:00
Athurg Gooth 9987337eca fix: all ID from int to int64 to avoid 32bits machine break (#2191)
Fix all ID from int to int64 to avoid 32bits machine break
2023-09-06 21:14:07 +08:00
Takuro Onoue 87a1d4633e chore: update ja.json (#2192)
* Update ja.json

I added the missing lines and translated.

* Update ja.json

I forgot to remove the comma at the end of the column.
I translated the untranslated portions.
2023-09-06 21:10:42 +08:00
boojack c2aeec20b7 chore: upgrade deps version (#2181) 2023-08-27 16:08:39 +08:00
boojack a5b3fb2a6a chore: move cron package to internal (#2180) 2023-08-26 23:13:03 +08:00
boojack c67a69629e chore: update user menu items (#2179) 2023-08-26 23:11:45 +08:00
boojack 18fb02a1ec chore: update swag docs (#2178)
* chore: update swag docs

* chore: update
2023-08-26 08:07:43 +08:00
boojack ad1822d308 chore: update db utils (#2177) 2023-08-26 07:33:45 +08:00
boojack 4af0d03e93 chore: add user profile page (#2175)
chore: some enhancements
2023-08-25 23:10:51 +08:00
boojack 8c312e647d chore: remove auto collapse setting (#2169) 2023-08-24 22:00:48 +08:00
boojack d3bd3ddab0 chore: update some detail styles (#2168)
* chore: update some detail styls

* chore: update
2023-08-24 21:52:16 +08:00
Sandu Liviu Catalin 6c01e84099 feat: add configuration option to bind server to specific address (#2165) 2023-08-24 09:59:23 +08:00
boojack b9b795bf0e chore: add react use (#2157)
* chore: add react use

* chore: update
2023-08-21 02:35:53 +08:00
boojack 19e7731abb chore: generate ts definition (#2156)
* chore: generate ts definition

* chore: update
2023-08-21 02:09:41 +08:00
ti777777 609b24f2ba chore: update zh-Hant.json (#2155)
Update zh-Hant.json

* removed unused entries
* updated the Traditional Chinese translation
2023-08-20 09:18:38 +08:00
Maciej Kasprzyk 735cfda768 fix: tag suggestions positioning (#2151) 2023-08-18 08:41:24 +08:00
Lincoln Nogueira 3f82729e9f chore: update build scripts (#2150)
update developer build scripts, bringing
feature parity between platforms.
2023-08-17 05:40:40 +08:00
Maciej Kasprzyk 077cfeb831 feat: improve tag suggestions (#2126)
* feat: make filtering case insensitive

* fix: wrong letter case when accepting suggestion

* refactor: wrap textarea in TagSuggestions

* fix: less styles not matching common-editor-inputer

* refactor: use explanatory const names for tested value in conditional checks

* feat: style highlighted option

* feat: handle down/up arrow keys

* feat: handle enter or tab to trigger autocomplete

* fix: wrong import

* fix: tab key adding whitespace after auto-completion

* fix: starting a note with a tag

* fix: close on escape

* refactor: early version of removed wrapping and children prop

* refactor: remove unnecessary return false

* refactor: finished rewriting to not wrap editor
2023-08-16 08:54:30 +08:00
boojack 95588542f9 chore: upgrade version to 0.14.4 (#2132) 2023-08-13 23:34:17 +08:00
boojack dd529f845a fix: fetch tags in memo editor (#2131)
fix: fetch tag
2023-08-13 23:27:01 +08:00
boojack 9f8a0a8dd3 fix: lazy rendering checks (#2130) 2023-08-13 23:19:29 +08:00
boojack e266d88edd chore: add acl config (#2128) 2023-08-13 00:06:03 +08:00
YuzeTT 0bb5f7f972 chore: update zh-Hans.json (#2127) 2023-08-12 21:34:01 +08:00
OKIAAAAA 012a5f4907 feat: add helm chart (#2095)
* add helm chart

* fix: remove unnecessary documents
2023-08-12 21:33:13 +08:00
YuNing Chen 409d686f7d chore: minor cleanup (#2124) 2023-08-11 22:34:08 +08:00
Jianwei Zhang c835231d32 feat: add header into resource response (#2120)
Update - add header for get resource
2023-08-10 23:45:30 +08:00
boojack 723c444910 chore: update server tests (#2118) 2023-08-10 09:01:38 +08:00
boojack 35f2d399e2 chore: update api v1 docs (#2117)
* chore: update apiv1 docs

* chore: update
2023-08-09 22:30:27 +08:00
Lincoln Nogueira 4491c75135 feat: add SwaggerUI and v1 API docs (#2115)
* - Refactor several API routes from anonymous functions to regular definitions. Required to add parseable documentation comments.

- Add API documentation comments using Swag Declarative Comments Format

- Add echo-swagger to serve Swagger-UI at /api/index.html

- Fix error response from extraneous parameter resourceId to relatedMemoId in DELETE("/memo/:memoId/relation/:relatedMemoId/type/:relationType")

- Add an auto-generated ./docs/api/v1.md for quick reference on repo (generated by swagger-markdown)

- Add auxiliary scripts to generate docs.go and swagger.yaml

* fix: golangci-lint errors

* fix: go fmt flag in swag scripts
2023-08-09 21:53:06 +08:00
Chris Akring 513002ff60 chore: update zh-Hans translations for "Tag suggestions" (#2110) 2023-08-08 19:12:04 +08:00
boojack 9693940010 chore: update en locale (#2109) 2023-08-08 07:29:29 +08:00
Moris 8747c58c7d feat: fixed heat map colors, updated it.json (#2106)
* Update it.json

* Add files via upload

* Add files via upload
2023-08-08 07:13:35 +08:00
nulta 0fd791c02d feat: update Korean localization (#2105)
Update korean localization
2023-08-08 07:12:57 +08:00
Jasper Platenburg 3a804ce012 feat: update Dutch translation (#2107) 2023-08-08 07:12:43 +08:00
Ghost108 f864ec3730 chore: update de.json (#2101)
* Update de.json

I used the en.json as a template and translated it (german language)

* Update de.json

* Update de.json

* Update de.json

* Update de.json

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-08-07 20:09:48 +08:00
Chris Akring 9503f73115 feat: use user avatar in ShareMemoDialog (#2102)
fix: ShareMemoDialog use user avata
2023-08-07 19:40:43 +08:00
Derek Reiff f9d1080a7d fix: minor spelling and wording changes for en and de (#2096)
Minor spelling and wording changes

I went through some of english and german localizations to correct or add minor things.

Added `invalid-tag-name` to json. Which also means it should be translated elsewhere.
2023-08-07 11:26:57 +08:00
boojack 4d3e4358e8 chore: update docs (#2094) 2023-08-06 11:25:35 +08:00
boojack 843850675f chore: update image displays (#2093) 2023-08-06 10:42:30 +08:00
boojack 726300394b chore: update image checks (#2092) 2023-08-06 10:38:39 +08:00
boojack 5d5d8de9fe fix: get all memo api (#2091) 2023-08-06 10:14:30 +08:00
boojack e097e8331e chore: upgrade version 0.14.3 (#2086) 2023-08-05 22:47:29 +08:00
boojack 7189ba40d3 feat: add lazy rendering in home page (#2085) 2023-08-05 22:14:17 +08:00
boojack 218159bf83 chore: remove openai setting section (#2084) 2023-08-05 21:39:12 +08:00
boojack 238f896907 feat: add system service (#2083)
* feat: add system service

* chore: update
2023-08-05 21:30:23 +08:00
boojack 270a529948 chore: update resource type checks (#2081) 2023-08-05 20:17:33 +08:00
boojack cc400da44e fix: remove translate hook in code block (#2080) 2023-08-05 20:01:32 +08:00
boojack 3df9da91b4 chore: update get memo api (#2079) 2023-08-05 19:51:32 +08:00
boojack 57dd1fc49f chore: initial memo service definition (#2077)
* chore: initial memo service definition

* chore: update

* chore: update

* chore: update
2023-08-05 09:32:52 +08:00
boojack 7c5296cf35 chore: update id type to int32 (#2076) 2023-08-04 21:55:07 +08:00
boojack cbe27923b3 chore: update commands (#2074) 2023-08-03 23:48:21 +08:00
boojack aa26cc30d7 chore: remove memo chat components (#2073) 2023-08-03 23:37:46 +08:00
boojack 1ce82ba0d6 chore: remove shortcut related api (#2072) 2023-08-03 23:33:45 +08:00
boojack d1b0b0da10 chore: remove shortcuts in frontend (#2071) 2023-08-03 23:28:38 +08:00
Athurg Gooth 11abc45440 feat: add command to move blob from local to db (#2026)
* Add `mvrss` command to move blob from local to db

* Add comment for mvrss command
2023-08-03 19:08:39 +08:00
boojack b5a6f1f997 chore: regenerate pnpm lock file (#2056)
* chore: regenerate pnpm lock file

* chore: update

* chore: update
2023-08-02 20:20:34 +08:00
boojack d114b630d2 feat: add prettier sort import plugin (#2058) 2023-07-31 22:26:45 +08:00
boojack 5f819fc86f chore: update auth middleware (#2057)
* chore: update auth middleware

* chore: update

* chore: update
2023-07-31 20:55:40 +08:00
boojack cc3a47fc65 feat: impl auth interceptor (#2055)
* feat: impl auth interceptor

* chore: update

* chore: update

* chore: update
2023-07-30 23:49:10 +08:00
Maciej Kasprzyk 5d3ea57d82 feat: tag suggestions (#2036)
* feat: figure out how to read caret position

* feat: figure out how to read caret position

* feat: create and style Editor/TagSuggestions.txs

* feat: progress on detect when to show and hide

* feat: progress on when to show and hide and setting position

* feat: toggling and exact placement done

* fix: pnpm lock problems

* feat: filter suggestions by partially typed tag name

* style: prettier

* chore: add types package for textarea-caret

* feat: handle option click

* style: prettier

* style: reorder imports

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-30 22:55:45 +08:00
Lilith c1cbfd5766 feat: add system setting to disable password-based login (#2039)
* system setting to disable password login

* fix linter warning

* fix indentation warning

* Prohibit disable-password-login if no identity providers are configured

* Warnings and explicit confirmation when en-/disabling password-login

- Disabling password login now gives a warning and requires a second
  confirmation which needs to be explicitly typed.
- (Re)Enabling password login now also gives a simple warning.
- Removing an identity provider while password-login is disabled now
  also warns about possible problems.

* Fix formatting

* Fix code-style

---------

Co-authored-by: traumweh <5042134-traumweh@users.noreply.gitlab.com>
2023-07-30 21:22:02 +08:00
boojack 9ef0f8a901 feat: add user setting field (#2054) 2023-07-30 09:53:24 +08:00
boojack 470fe1df49 feat: implement part of user service (#2053)
* feat: implement part of user service

* chore: update

* chore: update
2023-07-30 01:35:00 +08:00
boojack 2107ac08d7 chore: add docs generator (#2052) 2023-07-30 00:12:16 +08:00
boojack 89ba2a6540 feat: implement part of tag service (#2051)
* feat: add grpc gateway tempalte

* chore: update

* chore: move directory

* chore: update
2023-07-30 00:00:49 +08:00
boojack 9cedb3cc6c chore: update github actions (#2050) 2023-07-29 20:59:22 +08:00
boojack d0cfb62f35 chore: add tag service proto definition (#2049)
* chore: add tag proto definition

* chore: rename
2023-07-29 20:52:45 +08:00
boojack 9abf0eca1b feat: add buf configuration files and example proto (#2048)
* feat: add proto and buf configuration files

* chore: buf generate

* chore: update comments

* chore: go mod tidy
2023-07-29 19:44:09 +08:00
boojack a6a1898c41 refactor: user v1 store (#2047) 2023-07-29 18:57:09 +08:00
boojack f5793c142c revert: chore: update build docker image actions (#2046)
Revert "chore: update build docker image actions (#2045)"

This reverts commit 8f37c77dff.
2023-07-29 16:09:00 +08:00
boojack 8f37c77dff chore: update build docker image actions (#2045) 2023-07-29 15:59:23 +08:00
Gerald 28aecd86d3 fix: avoid content flash on auto collapse (#2042) 2023-07-29 09:04:34 +08:00
Gerald 95675cdf07 fix: show full content in detail page (#2041)
fix #1373 again
2023-07-28 15:52:50 +00:00
boojack 8328b5dd4a chore: upgrade version to 0.14.2 (#2035)
* chore: upgrade version to `0.14.2`

* chore: remove TestConcurrentReadWrite test
2023-07-26 22:42:38 +08:00
boojack d8d6de9fca fix: get user by username api (#2034) 2023-07-26 22:41:21 +08:00
boojack 56c321aeaa revert: fix: exclude all punctuation chars except underscore in tags (#2033)
Revert "fix: exclude all punctuation chars except underscore in tags (#1974)"

This reverts commit 8c61531671.
2023-07-26 21:11:13 +08:00
Takuro Onoue 756e6a150c chore: update ja.json (#2032)
I think free means freedom, not freemiam.

Fixed some strange expressions in the heatmap section.

Added spaces before and after English words that are in Japanese sentences.
2023-07-26 20:53:14 +08:00
Takuro Onoue 828984c8ec chore: update ja.json (#2030)
Update ja.json

translated one part.
2023-07-26 08:57:53 +08:00
Harry Tran 9da0ca5cb3 feat: add search bar in archived and explore pages (#2025)
* feat: add search bar in archived and explore pages

* Update web/src/pages/Archived.tsx

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-24 11:09:30 +00:00
iMaeGoo dc5f82ac9c feat: update chinese translate (#2023) 2023-07-24 19:08:46 +08:00
Ajay Kumbhare d000083b41 fix: hashtag filter for Unicode characters (#2017) 2023-07-23 19:17:18 +08:00
Mason Sun a9eb605b0f fix: auth api json format (#2021)
Update auth.go

api/v1/auth/相关接口未应用convertUserFromStore方法,会导致User对象获得类型存在问题,导致User定义的`json:`相关的字段转化失效。
导致输出json未被正确格式化
2023-07-23 19:11:29 +08:00
Ajay Kumbhare 5604129105 fix: empty state display issue with resourceList style Grid (#2018) 2023-07-23 19:10:33 +08:00
boojack 04b7a26c03 chore: fix request path (#2014) 2023-07-23 10:12:13 +08:00
boojack 28203bbaf9 chore: fix rss route (#2010) 2023-07-22 21:51:05 +08:00
boojack 9138ab8095 fix: rss route (#2008)
* fix: rss route

* chore: update
2023-07-22 12:58:17 +08:00
boojack 4231ec5a1a chore: upgrade version to 0.14.1 (#2004) 2023-07-22 09:58:03 +08:00
Ajay Kumbhare 55975a46d8 feat: add hindi language translation for i18n support (#2001) 2023-07-22 09:38:54 +08:00
Alexandr Tumaykin 1182545448 fix: add resource.clear to translate (#1999)
Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-21 17:07:05 +08:00
Takuro Onoue 9f3c3ae094 chore: update ja.json (#1996)
It is strange to translate "about" as "Notes について". However, if we define "について" as "about", the sentence becomes "について Memos". It is better not to translate here.
2023-07-21 10:38:06 +08:00
boojack 4c33d8d762 chore: remove unused transaction in store (#1995)
* chore: remove unused transaction in store

* chore: update
2023-07-20 23:15:56 +08:00
Lincoln Nogueira c8961ad489 fix: database is locked (#1992)
* fix: database is locked

The option "_journal_mode=WAL" is currently *not* being applied when
provided in the DSN.

This issue affects only new memos installations, not older ones where
the database journal was properly set to WAL mode by the previous sqlite
library go-sqlite3.

modernc.org/sqlite DSN parsing is different from go-sqlite3. It requires
the `_pragma=` prefix and even some options order matter.

https://gitlab.com/cznic/sqlite/-/issues/115

Closes #1985

* chore: upgraded notes on sqlite DSN
2023-07-20 20:51:25 +08:00
Alexandr Tumaykin f91f09adea feat: use username instead of uid (#1977)
* #1916 replace userId to username

* resolve

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-20 19:48:39 +08:00
Athurg Gooth 336b32004d feat: add AutoBackupInterval in SystemSetting (#1989)
Add AutoBackupInterval in SystemSetting page
2023-07-19 21:39:21 +08:00
Jerry Wang 7b5c13b712 fix: delete multiple resources
* fix: delete multiple resources, close #1986

* chore: remove useless comment
2023-07-19 21:36:02 +08:00
Jianwei Zhang 8bcc2bd715 fix: access token will expired after 24h (#1988) 2023-07-19 08:45:30 +08:00
Ajay Kumbhare 83b771d5cd fix: disable selection of future dates in daily review section (#1983)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error

* chore: Disallow destructuring 't' from useTranslation

This commit adds a linting rule to disallow the destructuring of the 't' property from the result of the useTranslation function call. The no-restricted-syntax rule in the ESLint configuration has been updated to enforce this restriction. The intention is to promote alternative approaches like using the useTranslate hook for localization.

* fix: typo fixed for memoChat

* fix: copy code button toast message

Refactored the code for the "Copy Code" button to utilize i18 strings for displaying the success message. Replaced the hard-coded value with the appropriate i18 string "Code copied successfully."

* fix: #1980 disable selection of future dates in daily review section
2023-07-18 22:21:08 +08:00
EINDEX 8dbc63ed56 docs: add rowStatus parameter for memo api document (#1984)
add missing parameters for memo api
2023-07-18 22:20:22 +08:00
Felipe Martínez 8c61531671 fix: exclude all punctuation chars except underscore in tags (#1974)
* Change tag regex

* Update tests

* Add more tag tests
2023-07-18 01:53:07 +08:00
Ajay Kumbhare b5d4b8eae8 fix: copy code button toast message (#1979)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error

* chore: Disallow destructuring 't' from useTranslation

This commit adds a linting rule to disallow the destructuring of the 't' property from the result of the useTranslation function call. The no-restricted-syntax rule in the ESLint configuration has been updated to enforce this restriction. The intention is to promote alternative approaches like using the useTranslate hook for localization.

* fix: typo fixed for memoChat

* fix: copy code button toast message

Refactored the code for the "Copy Code" button to utilize i18 strings for displaying the success message. Replaced the hard-coded value with the appropriate i18 string "Code copied successfully."
2023-07-18 00:16:55 +08:00
Alexandr Tumaykin e36e5823cd feat(security): disable access for anonymous users, when disablePublicMemos is true (#1966) 2023-07-17 09:12:53 +08:00
Ajay Kumbhare 4ac63ba1f0 chore: disallow destructuring 't' from useTranslation (#1973) 2023-07-16 21:26:26 +08:00
boojack 589b104671 chore: upgrade version to v0.14.0 (#1970)
* chore: upgrade version

* chore: update

* chore: update
2023-07-16 13:48:10 +08:00
boojack 220cba84ae chore: add dev guard for memo chat (#1968) 2023-07-16 13:02:52 +08:00
CorrectRoadH 032509ddba feat: save message to memo (#1940)
* feat: implment backend function

* feat: implment frontend component

* stash

* eslint

* eslint

* eslint

* delete node

* stash

* refactor the style

* eslint

* eslint

* eslint

* fix build error

* stash

* add dep

* feat: save message as memos

* eslint

* eslint

* Update web/src/components/MemosChat/MemosChatMessage.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* stash

* eslint

* eslint

* chore: change translate

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-16 11:51:30 +08:00
5idereal 054ef3dc8d chore: update Traditional Chinese translation (#1967) 2023-07-16 10:19:08 +08:00
boojack 2effacd0a6 chore: add api docs (#1965) 2023-07-15 23:30:20 +08:00
boojack 01f4780655 chore: update detail styles (#1964) 2023-07-15 22:57:57 +08:00
Alexandr Tumaykin 49dd90578b fix: add resource.clear to en.json (#1963) 2023-07-15 20:03:49 +08:00
Ajay Kumbhare 1780225da5 feat: add typeScript support to enforce valid translation keys (#1954)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error
2023-07-15 10:27:37 +08:00
boojack 5e20094386 chore: add indexes (#1959) 2023-07-15 10:26:31 +08:00
boojack 40a30d46af chore: update db connection params (#1960) 2023-07-15 10:26:19 +08:00
Alexandr Tumaykin 6b17a27a13 feat: update russian translate and new translate message (#1958)
* feat: add russian translate and new translate message

* fix

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-15 10:01:40 +08:00
Felipe Martínez 2a7104e564 fix: exclude commas in tags (#1957) 2023-07-15 10:00:35 +08:00
Ajay Kumbhare 8ca2dac184 fix: incorrect localization key for sign-up failure message (#1953) 2023-07-14 21:43:46 +08:00
Athurg Gooth d9b3501fae feat: add support for auto backup db file (#1950)
Add support for auto backup db file
2023-07-14 20:05:07 +08:00
CorrectRoadH 39351970d0 feat: implement memo chat frontend (#1938)
* feat: implment backend function

* feat: implment frontend component

* stash

* eslint

* eslint

* eslint

* delete node

* stash

* refactor the style

* eslint

* eslint

* eslint

* fix build error

* add dep

* Update web/src/components/MemosChat/ConversationTab.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update web/src/components/MemosChat/ConversationTab.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* feat: change the name

* disable for vistor

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-14 13:09:21 +08:00
Athurg Gooth 06dbd87311 chore: split save resource asset (#1939)
* Move resource blob save into a independent function

* Support save resouce blob from Telegram like HTTP API

* Support save resouce blob download from URL to LocalStorage or S3

* fix typo
2023-07-14 11:14:10 +08:00
Alexandr Tumaykin c5a1f4c839 feat: format message from telegram and upload attachments (#1924)
* feat: format message from telegram and download documents

* fix: remove bool in expression

* refactor: convert to markdown

* refactor: resolve remarks and add support new message types

* refactor: resolve remarks

* feat: add test for mime type

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-14 00:18:44 +08:00
Ikko Eltociear Ashimine f074bb1be2 docs: fix typo in deploy-with-render.md (#1946)
reliablity -> reliability
2023-07-14 00:00:23 +08:00
boojack 90e7d02e35 chore: update readme (#1947) 2023-07-14 00:00:08 +08:00
boojack 437e05bd2f chore: update header style (#1945) 2023-07-13 23:15:11 +08:00
Sergei Vassiljev 934f57c92f chore: update MemoRelationListView.tsx (#1933) 2023-07-13 19:42:50 +08:00
Athurg Gooth 3093f80d68 fix: visibility param override the user auth state (#1942)
fix visibility param override the user auth state
2023-07-13 15:20:15 +08:00
Athurg Gooth 11aa01ee2e fix: visibility param override the user auth state (#1941)
fix visibility param override the user auth state
2023-07-13 14:56:43 +08:00
CorrectRoadH d8b6e92813 feat: implement memos chat backend function (#1934)
* feat: implment backend function

* eslint

* eslint

* eslint
2023-07-13 11:25:59 +08:00
Athurg Gooth 6adbb7419c chore: split Go binary and src for dev (#1932)
Split Go binary and src for dev
2023-07-12 15:39:56 +08:00
boojack d4b88c6c86 chore: remove auto signout in auth page (#1927) 2023-07-12 00:16:32 +08:00
boojack 698380f940 chore: update seed data (#1928) 2023-07-12 00:16:19 +08:00
Cyang39 dcac442ebf chore: change dropdown's background color in dark mode (#1925)
#1919
2023-07-11 22:37:04 +08:00
boojack da70917b08 chore: update auth page (#1920)
* chore: update auth page

* chore: update
2023-07-09 21:13:26 +08:00
boojack 0292f472e0 chore: add data empty placeholder (#1913) 2023-07-08 13:04:12 +08:00
boojack 7e391bd53d chore: remove resource public id (#1912)
* chore: remove resource public id

* chore: update
2023-07-08 11:29:50 +08:00
Peng Ding 2157651d17 update zh-Hans & zh-Hant translations (#1909) 2023-07-07 08:40:35 +08:00
boojack 0e05c62a3b chore: update common utils (#1908) 2023-07-06 22:53:38 +08:00
boojack a7573d5705 refactor: migrate memo to apiv1 (#1907)
* refactor: migrate memo to apiv1

* chore: update

* chore: update

* chore: update

* chore: upate

* chore: update

* chore: update
2023-07-06 21:56:42 +08:00
boojack 1fa9f162a5 refactor: migrate resource to apiv1 (#1901) 2023-07-06 00:01:40 +08:00
Athurg Gooth 5ea561af3d feat: add support for purged resource link (#1897)
Add support for purged resource link
2023-07-05 21:56:13 +08:00
Athurg Gooth 2033b0c8fa fix: skip auth on /api/v1/status to avoid sign up while token invalid (#1895)
Skip auth on /api/v1/status to avoid sign up while token invalid
2023-07-05 13:55:04 +08:00
Athurg Gooth 1c07ae2650 fix: escape on resource filename (#1892)
add escape on resource filename
2023-07-04 10:06:11 +08:00
boojack 5b6c98582e refactor: migrate storage to apiv1 (#1890)
* refactor: migrate storage to apiv1

* chore: update

* chore: update

* chore: update
2023-07-04 10:05:57 +08:00
Athurg Gooth 0af14fc81a fix: invalid orientation of image thumbnail in Apple devices (#1891) 2023-07-04 09:05:56 +08:00
Athurg Gooth 833fd23820 fix: OpenID was disappear sometimes (#1886)
Fix openid was disapear sometimes
2023-07-03 19:10:24 +08:00
Jiraiya8 d46126c5c3 fix: header archived id (#1888)
Co-authored-by: qingbo <qingbo@jingling.group>
2023-07-03 19:09:59 +08:00
Athurg Gooth 811c3e8844 fix: auto expand height of setting page (#1885) 2023-07-03 13:35:55 +08:00
boojack 223404a240 chore: update memo seed data (#1884) 2023-07-02 23:58:02 +08:00
boojack 31373be172 chore: remove unused packages (#1880) 2023-07-02 19:41:56 +08:00
boojack 66e65e4dc1 refactor: migrate definition to api v1 (#1879)
* refactor: user api v1

* refactor: system setting to apiv1

* chore: remove unused definition

* chore: update

* chore: refactor: system setting

* chore: update

* refactor: migrate tag

* feat: migrate activity store

* refactor: migrate shortcut apiv1

* chore: update
2023-07-02 18:56:25 +08:00
Phong H b84ecc4574 chore: update vi.json locale (#1878)
Co-authored-by: phong.bnh <phong.bnh@globalfactories.com>
2023-07-02 16:41:03 +08:00
boojack 9a8d43bf88 chore: update user store names (#1877)
* chore: update user store names

* chore: update
2023-07-02 14:27:23 +08:00
boojack ca770c87d6 chore: upgrade version to v0.13.2 (#1873) 2023-07-01 18:01:51 +08:00
boojack c83fd1de38 chore: update dialog overflow style (#1872) 2023-07-01 17:37:43 +08:00
boojack db8b8f0d58 chore: remove unused kit components (#1871) 2023-07-01 12:34:37 +08:00
CorrectRoadH 30fae208c2 fix: pin memos of other people (#1870) 2023-07-01 12:04:49 +08:00
boojack 5fe644a3b6 chore: add jwt middleware in apiv1 (#1869) 2023-07-01 00:03:28 +08:00
CorrectRoadH a108f5e212 fix: ignore internalpath field when creating resource (#1868)
* fix/to_valid_token

* eslint

* revert

* fix/invalid_internalpath_file_upload
2023-06-30 23:50:55 +08:00
CorrectRoadH c9aa2eeb98 fix: validate access token (#1867)
* fix/to_valid_token

* eslint

* revert

* Update server/jwt.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-30 14:59:52 +00:00
Vespa314 63d6b6f9f9 chore: listMemos sort by id for memos post/update at the same time (#1866) 2023-06-30 22:56:31 +08:00
boojack 847b4605f4 chore: update dark mode style (#1864) 2023-06-30 08:40:13 +08:00
boojack 6b3748e2a3 chore: update setting page styles (#1863)
* chore: update setting page styles

* chore: update
2023-06-29 23:17:01 +08:00
boojack 6a78887f1d chore: update store types name (#1862) 2023-06-29 22:55:03 +08:00
boojack 7226a9ad47 chore: update idp store (#1856) 2023-06-26 23:46:01 +08:00
boojack b44f2b5ffb chore: migrate user setting to api v1 package (#1855)
* chore: migrate to api v1 package

* chore: update
2023-06-26 23:06:53 +08:00
boojack 07e82c3f4a fix: schema migrate (#1846)
* fix: schema migrate

* chore: update
2023-06-20 12:18:04 +08:00
boojack b34aded376 refactor: migration idp api (#1842)
* refactor: migration idp api

* chore: update
2023-06-17 22:35:17 +08:00
boojack 4ed9a3a0ea refactor: migrate auth routes to v1 package (#1841)
* feat: add api v1 packages

* chore: migrate auth to v1

* chore: update test
2023-06-17 21:25:46 +08:00
boojack f1d85eeaec chore: upgrade pnpm version (#1833)
* chore: upgrade pnpm version

* chore: update
2023-06-15 22:35:41 +08:00
SedationH 1b0efc5548 fix: use ?? in className use (#1829) 2023-06-15 20:05:19 +08:00
May Kittens Devour Your Soul 6dca551164 chore: update hr.json (#1832)
Update hr.json

Updated Croatan [some fixes]
2023-06-15 19:27:13 +08:00
Athurg Gooth 7694597728 feat: Add suppport for tap to reload on PWA (#1827)
* Add suppport for tap to reload on PWA

* Clean empty className

* Move click event to site title

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-14 22:33:46 +08:00
Athurg Gooth 4d59689126 feat: set memo visibility in telegram (#1824)
* Add telegram.Bot in MessageHandler

* Change single message handler like group messages

* Move message notify wrapper from plugin to server

* Add keyboard buttons on Telegram reply message

* Add support to telegram CallbackQuery update

* Set visibility in callbackQuery

* Change original reply message after callbackQuery

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-14 22:10:01 +08:00
May Kittens Devour Your Soul 8f7001cd9f feat: add croatian locale (#1822)
* Create hr.json

Croatian Language

* Update user_setting.go

* Update i18n.ts

* Update hr.json

* Update web/src/i18n.ts

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-14 22:09:19 +08:00
David Angel 781b1f7b3a chore: add classnames for easy logo/server name customizations via CSS. (#1828)
Update MemoDetail.tsx
2023-06-14 21:03:38 +08:00
Athurg Gooth e6c9f2a00e feat: add support for download resource from link (#1800)
* Add support for download resource from link

* Parse external link and add file ext name from mime info

* Add zh-Hans locale for `download-link`

* fix typo on code and comments

* Update server/resource.go

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-08 14:35:33 +00:00
Athurg Gooth 5d06c8093c fix: systemSetting in UI changed unexpectedly (#1812)
Fix systemSetting in UI changed unexpectedly

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-08 22:32:57 +08:00
kakik0u c396cc9649 feat: add japanese locale (#1802)
* Add japanese

* Add japanese setting files

---------

Co-authored-by: barappe <121844712+barappe@users.noreply.github.com>
2023-06-08 13:50:48 +08:00
zhangpeng ac5d8b47ca chore: modify the error message when registering a Host user (#1804)
* Modify the error message

* modify the error message
2023-06-07 12:12:23 +08:00
Athurg Gooth 77e8e9ebbd revert: fix: add public base path (#1748) (#1775) (#1806)
This reverts commit d205a7683a.
2023-06-07 10:07:30 +08:00
c14c6b3786 fix: user default 'Basic Setting' should follow server's setting (#1795)
fix: user default 'Basic Setting' should follow system setting
2023-06-07 00:38:50 +08:00
Athurg Gooth c27c6cea13 fix: failed to upload OSS with S3 SDK (#1792)
Fix failed to upload OSS with S3 SDK

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-03 14:38:28 +08:00
boojack 11a385cda6 chore: update upgrade version view (#1791) 2023-06-03 14:32:04 +08:00
boojack 32e2f1d339 chore: update page routes (#1790)
chore: update routers
2023-06-03 13:03:22 +08:00
Athurg Gooth 69225b507b chore: clean Dockerfile to exclude musl-dev (#1787)
Clean Dockerfile to exclude musl-dev install

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-01 20:16:13 +08:00
-Shiken- 2f905eed0d chore: update zh-Hant.json (#1781)
* Update zh-Hant.json

follow these commits to complete zhTW translation:
96021e518a
8628d1e4b2
93d608f050
ce64894abe
845297ec03

* Update web/src/locales/zh-Hant.json

Co-authored-by: Zeng1998 <acan.coder@gmail.com>

* Fix json format error

---------

Co-authored-by: Zeng1998 <acan.coder@gmail.com>
Co-authored-by: Athurg Gooth <github@gooth.org>
2023-06-01 09:03:44 +08:00
Athurg Gooth 55cf19aa2e fix: copy-to-clipboard not works well in Safari (#1779)
* Fix copy-to-clipboard not works well in Safari

* Fix typescript type check failure

* Remove global copy inject in home page

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-01 08:53:40 +08:00
boojack dd8c10743d feat: memo editor dialog (#1772)
* feat: memo editor dialog

* chore: update mark

* chore: update
2023-05-30 20:23:26 +08:00
Athurg Gooth 25ce36e495 feat: resource visibility (#1777)
* Add method to query visibility list by memoIDs

* Add function to get visibility by resourceID

* Check resource visibility in /r/:resourceId/:publicId/:filename

* Check resource visibility in /r/:resourceId/:publicId

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-30 19:00:54 +08:00
Gener d205a7683a fix: add public base path (#1748) (#1775) 2023-05-30 18:55:23 +08:00
Athurg Gooth 7e4d71cf58 fix: infinite loop in home page (#1773)
Fix infinite loop in home page

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-30 18:54:58 +08:00
Athurg Gooth 97df1a82c7 feat: add docker compose file for development (#1769)
* Add support to fetch devProxyServer from environment

* Add docker compose file for developer

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 19:49:47 +08:00
Athurg Gooth 845297ec03 refactor: change all Robot to Bot (#1767)
* Change all `Robot` to `Bot`

* Change all `r` of `Bot` to `b`

* Change `Robot` to `bot` in comments

* Fix typo

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 19:49:05 +08:00
Athurg Gooth ddf4cae537 feat: disable CGO_ENABLED (#1766)
* Replace mattn/go-sqlite3 with modernc.org/sqlite

* Disable CGO to make binary work without special c lib

* Replace mattn/go-sqlite3 with modernc.org/sqlite in testing code

* Tidy go module

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 13:29:42 +08:00
Athurg Gooth ce64894abe feat: add telegram proxy support (#1764)
* Add support for reverse proxy of telegram API

* Add Telegram API proxy hint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 13:29:21 +08:00
boojack beb4d8ccb9 chore: order by updated ts in memo store (#1761) 2023-05-28 02:04:05 +08:00
boojack e0e59c5831 feat: display memo with updated ts (#1760) 2023-05-28 01:50:09 +08:00
_Jellen 826541a714 feat: update korean localization (#1758) 2023-05-27 22:03:06 +08:00
boojack c40aeb91e6 fix: patch memo row status (#1755) 2023-05-27 11:14:23 +08:00
boojack 2e34ce90a1 chore: upgrade version 0.13.1 (#1754) 2023-05-27 09:09:41 +08:00
GodMeowIceSun 93d608f050 feat(#1568): add "ask ai" section session splitting function (#1711)
* feat(#1568): Added "ask ai" section session splitting function

Added "ask ai" section session splitting function
Optimize the "ask ai" dialogue style

* fix(#1568): Fix wrong attribute "appearance"

* fix(#1568): Add ts type define

* fix(#1568): Add ts type define

* fix(#1568): Resolve the issue of components not being stretched when only user input is available

* feat(#1568): New session automatic switching function

* refactor(#1729): remove unused code

* feat(#1568): New Remove Session Function

New Remove Session Function
Rename some methods
2023-05-27 02:29:54 +08:00
boojack ec26a9702d fix: sso templates (#1753) 2023-05-26 22:25:30 +08:00
boojack dbe8aa1d3a chore: update telegram bot related section (#1750)
* chore: update telegram bot related section

* chore: update
2023-05-26 21:32:44 +08:00
Athurg Gooth 8628d1e4b2 feat: add Telegram bot config UI (#1747)
* Add retry wait for telegram.GetUpdates

* Add support to set telegram robot token from UI

* Change validator of UserSettingTelegramUserID

* Add support to set telegram user id from UI

* Fix typescript check

* Add validator for SystemSettingTelegramRobotTokenName

* Optimize error notice while config telegram params

* Change for review

* Fix telegram user id could not be empty

* Fix telegram robot could not be empty

* Fix for eslint (again)

* Update web/src/components/Settings/SystemSection.tsx

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-05-26 19:16:51 +08:00
Athurg Gooth 4ea5426e18 feat: add support for content search (#1728)
* Change MemoFind.ContentSearch to slice

* Add support for content search

* Change for go-simple sugguest

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-26 18:51:18 +08:00
Athurg Gooth 1282fe732e feat: implement telegram bot plugin (#1740) 2023-05-26 09:43:51 +08:00
boojack a07d11e820 feat: tag parser (#1745) 2023-05-26 09:05:17 +08:00
boojack dbc85fe7e4 feat: image and link parser (#1744)
* feat: image and link parser

* chore: update
2023-05-26 08:43:37 +08:00
boojack 523ef2bba5 chore: update demo banner style (#1743) 2023-05-26 00:47:53 +08:00
boojack de8014dfe8 feat: resource store cache (#1742) 2023-05-26 00:38:27 +08:00
deeshu b42e5c3213 chore: update vscode setting enforcement for go111module="on" (#1738)
vscode setting enforcement for go111module to set on and availability of schema for go extension
2023-05-25 22:00:32 +08:00
boojack ea728d232d refactor: memo store (#1741) 2023-05-25 21:50:37 +08:00
boojack 43819b021e chore: add demo banner (#1739) 2023-05-25 19:29:30 +08:00
boojack e69f7c735b chore(revert): retire demo site (#1733)
Revert "chore: retire demo site (#1659)"

This reverts commit cd2bdab683.
2023-05-24 20:34:07 +08:00
Athurg Gooth 5e792236af fix: infinite loop while daily memos more than DEFAULT_MEMO_LIMIT (#1730)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-24 20:22:16 +08:00
boojack 45c119627b chore: move flags into env variables (#1732) 2023-05-24 20:08:47 +08:00
boojack 65890bc257 feat: implement code block parser (#1727) 2023-05-24 00:31:37 +08:00
boojack 42c653e1a4 feat: implement paragraph and italic parsers (#1725) 2023-05-23 21:11:01 +08:00
boojack 8c34be92a6 feat(gomark): add bold parser (#1724) 2023-05-23 20:49:32 +08:00
boojack fa53a2550a feat: add heading tokenizer (#1723) 2023-05-23 19:52:31 +08:00
Athurg Gooth 616b8b0ee6 feat: introduce publicid to filename template (#1713)
* Add support for `publicid` in PathTemplate

* Use `publicid` by default instead of `filename` in filesystem

* Fix blank string of `systemSettingLocalStoragePath` affect incorrectly

* Add ext name to compatible with OS's preview

* Optimize code for systemSettingLocalStoragePath empty

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-23 19:15:30 +08:00
Athurg Gooth d24632682f chore: add volume define in Dockerfile to avoid data lose (#1718)
Add volume define in Dockerfile to protect data

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-23 18:50:17 +08:00
Athurg Gooth 3b1bab651a fix: system memo visibility was replace by user's setting (#1707)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-22 12:15:00 +08:00
Athurg Gooth 0cea5ebaeb fix: concurrent counter operates (#1706)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-22 11:08:49 +08:00
Zeng1998 1e4a867a9a fix: add thumbnail param only for internal link (#1701)
* fix: add thumbnail param using `URLSearchParams`

* update: add thumnail param only for internal link
2023-05-21 16:41:04 +08:00
CorrectRoadH 6bb0b4cd47 fix: pop search when touch textarea in Android Chrome (#1700)
* fix: pop search when touch textarea

* eslint
2023-05-21 16:31:50 +08:00
CorrectRoadH 56c6f603aa fix: md without search icon (#1699) 2023-05-21 16:28:30 +08:00
boojack 98b3a371f4 fix: patch memo visibility (#1695) 2023-05-21 11:51:13 +08:00
boojack ba8e1e5dc2 chore: add available generator amount flag (#1696) 2023-05-21 11:50:57 +08:00
boojack 467f9080a1 feat: get or generate thumbnail image (#1691) 2023-05-20 22:08:07 +08:00
Athurg Gooth 0894bf13d2 fix: fail to open file while generate thumbnail (#1687)
* Fix fail to open file while generate thumbnail

* Fix for Uncontrolled data used in path expression check

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-20 14:33:59 +08:00
boojack 1d7627dd72 chore: upgrade version 0.13.0 (#1685)
* chore: upgrade version `0.13.0`

* chore: update
2023-05-20 10:16:19 +08:00
boojack d80aa67c97 feat: parse markdown to html format in rss (#1683) 2023-05-20 10:00:21 +08:00
boojack ae1d9adf65 fix: initial system locale (#1684) 2023-05-20 09:39:20 +08:00
boojack b40571095d feat: update memo detail page (#1682)
* feat: update memo detail page

* chore: update
2023-05-20 08:39:39 +08:00
Athurg Gooth 04124a2ace feat: generate thumbnail while get and improve thumbnail quality (#1680)
* Use disintegration/imaging to optimize thumbnail quality

* Generate thumbnail if not exists while GET it

* Changes for `go mod tidy`

* Changes for golang comments lint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 20:07:39 +08:00
Athurg Gooth 2730b90512 feat: highlight the DatePicker's date (#1669)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 08:36:08 +08:00
Athurg Gooth 34913cfc83 feat: show thumbnail in resource dashboard (#1666)
* Add image thumbnail instead of an icon

* Change thumbnail size of dashboard to fixed

* Fix for eslint-checks

* Fix for eslint-checks

* Replace css with tailwind

* Remove the parent div used for style

* Show preview while click on the resource

* Change for review Suggested by @Zeng1998

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 08:31:32 +08:00
boojack 88799d469c chore: initial gomark plugin (#1678)
chore: initial gomark folder
2023-05-18 21:33:18 +08:00
boojack a07d5d38d6 feat: memo relation part1 (#1677)
* feat: memo relation part1

* chore: update
2023-05-18 21:29:28 +08:00
Stephen Zhou ca5859296a fix: resource url in rss (#1672) 2023-05-18 06:53:20 +08:00
boojack 1a8310f027 chore: update system setting default value (#1665) 2023-05-15 22:59:26 +08:00
Athurg Gooth 041be46732 Add support for image thumbnail (#1641)
* Add a common function for resize image blob

* Auto generate thumbnail for image resources

* Auto thumbnail support for fetch image resources

* Add support for image thumbnail in view

* Fix missing error check

* Fix es-lint check

* Fix uncontrolled data used in path expression

* Remove thumbnail while origin resource been deleted

* Change the thumbnail's storage path

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-15 22:42:12 +08:00
Zeng1998 9eafb6bfb5 chore: add the default value of MaxUploadSizeMiB (#1663) 2023-05-15 21:54:45 +08:00
Lincoln Nogueira 668a9e88c6 fix: File size exceeds allowed limit of 0 MiB (#1664)
fix: File size exceeds allowed limit of 0 MiB

This could happen in databases without "max-upload-size-mib" setting.

Now, both the front-end and the back-end will start with a default
limit of 32 MiB, even if the key is absent.

It is still possible to disable uploads by setting the value to 0.
2023-05-15 21:54:13 +08:00
boojack cd2bdab683 chore: retire demo site (#1659) 2023-05-14 23:35:31 +08:00
CorrectRoadH d72b4e9a98 feat: filter support plain link (#1657)
* fix: unexpected empty lines when copying-pasting

* add ref

* feat: support to filter plain link

* eslint

* fix the typo

* fix the typo

* unified the import path
2023-05-14 23:17:18 +08:00
boojack 2cc5691efd chore: update memo relation types (#1658) 2023-05-14 23:17:05 +08:00
guanzi008 7726ed4245 feat: add build-artifacts.yml (#1583)
* Create main.yml

构建的单文件运行版本几个平台的Windows amd64 ,Linux amd64,Linux arm64

* Rename main.yml to build-artifacts.yml

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-05-13 14:52:50 +00:00
boojack 921d4b996d chore: update help button style (#1656) 2023-05-13 22:52:06 +08:00
Lincoln Nogueira 96021e518a feat: add max upload size setting to UI & UI improvements (#1646)
* Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)

* feat: improve Windows support

- Fix local file storage path handling on Windows

- Improve Windows dev script

* feat: add max upload size setting to UI & more

- feat: add max upload size setting to UI

- feat: max upload size setting is checked on UI during upload,
but also enforced by the server

- fix: overflowing mobile layout for Create SSO, Create Storage
and other Settings dialogs

- feat: add HelpButton component with some links to docs were appropriate

- remove LearnMore component in favor of HelpButton

- refactor: change some if/else to switch statements

- refactor: inline some err == nil checks

! Existing databases without the new setting 'max-upload-size-mib'
will show an upload error, but this can be user-fixed by simply
setting the value on system settings UI.

* improvements requested by @boojack
2023-05-13 22:27:28 +08:00
boojack 5c5199920e chore: seed data for new user (#1655) 2023-05-13 22:25:15 +08:00
CorrectRoadH e1c809d6f1 fix: unexpected empty lines when copying-pasting (#1654) 2023-05-13 22:08:54 +08:00
Athurg Gooth 218009a5ec fix: wrong position of UsageStatItem's popup (#1647)
* fix: wrong position of UsageStatItem's popup

* Replace TAB into Space for eslint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-12 22:07:53 +08:00
Lincoln Nogueira 5340008ad7 feat: improve Windows support (#1645)
* Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)

* feat: improve Windows support

- Fix local file storage path handling on Windows

- Improve Windows dev script
2023-05-10 08:03:55 +08:00
CorrectRoadH 700fe6b0e4 fix: return pinned status after edit (#1629)
* stash

* query pinned status after patch

* eslint

* refactor query

* eslint

* process specify case

* add test

* Update memo.go
2023-05-09 09:03:09 +08:00
boojack 9b8d69b2dd chore: add vacuum memo relation to dev guard (#1644)
* chore: add vacuum memo relation to dev guard

* chore: update
2023-05-09 09:02:59 +08:00
Zeng1998 84546ff11c chore: show server name instead of "MEMOS" (#1639) 2023-05-09 08:24:13 +08:00
Zeng1998 885a0ddad0 chore: add size for s3 resource (#1638) 2023-05-09 08:17:26 +08:00
Lincoln Nogueira 3b76c6792c feat: add preliminar Windows support (#1636)
Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)
2023-05-09 08:16:38 +08:00
jonny 4605349bdc chore: update Chinese name translation (#1630) 2023-05-06 07:36:22 +08:00
Stephen Zhou ff447ad22b feat: support file sorting when uploading (#1627) 2023-05-03 19:18:29 +08:00
Stephen Zhou c081030d61 chore: lock pnpm version (#1628) 2023-05-03 19:14:21 +08:00
boojack e3496ac1a2 refactor: memo editor components (#1625) 2023-05-03 19:13:37 +08:00
boojack 8911ea1619 chore: update related time format (#1621)
chore: update related time
2023-05-02 08:54:51 +08:00
boojack 34700a4c52 chore: check allow sign up setting in sso (#1620) 2023-05-02 08:45:03 +08:00
boojack b6564bcd77 feat: implement memo relation server (#1618) 2023-05-01 16:09:41 +08:00
Peng Ding 6e6aae6649 feat: update zh-Hans translations and minor fixes in locale_updater.py (#1615)
* update zh-Hans translations

* minor update

* update instruction part

* print json_value for debugging purpose

* update post requests related

* machine translate with chunks to get around {{field}}
2023-05-01 13:27:08 +08:00
João Nuno Mota b98f85d8a7 feat: add infinite scroll for memos (#1614)
Add infinite scroll for memos on home
2023-05-01 13:26:15 +08:00
João Nuno Mota 3314fe8b0e fix: failed eslint checks (#1616) 2023-05-01 08:38:35 +08:00
powersee f12163bc94 feat: add linux/arm/v7 to docker build action (#1610) 2023-04-29 00:40:15 +08:00
CorrectRoadH f7a1680f72 fix: only delete last file when select multiple files #1576 (#1578)
* fix the bug can't delete multiple files #1576

* using useEvent instead of useRef

* delete unused code

* delete unused code

* change hook file name

* refactor the useEvent

* delete unnecessary export

* fix import

* Apply suggestions from code review

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-04-28 16:17:08 +00:00
boojack 4603f414db chore: add system setting cache (#1609) 2023-04-28 00:02:54 +08:00
deeshu 884dca20b3 fix: reappearing of dialog should add body scrolling class (#1602)
When dialog is reappeared after being in a hidden state. Then reappeaning should block further body scrolling for consistent UX.
2023-04-27 07:16:15 +08:00
Max Malm dbb544dc92 feat: read content from search params (#1607) 2023-04-27 07:15:40 +08:00
deeshu 3fad718807 fix: memo content availability for visitor mode (#1605) 2023-04-26 21:57:01 +08:00
boojack fab8a71fd2 feat: implement memo relation store (#1598)
* feat: implement memo relation store

* chore: update
2023-04-25 23:27:38 +08:00
Barry 7776a6b7c6 docs: update readme with MemosGallery (#1590)
- add: https://github.com/BarryYangi/MemosGallery

A simple gallery static page based on the memos api, I think it might be useful for some people, so I just post it up. Close this if not necessary.
2023-04-25 22:27:02 +08:00
boojack cd6ab61c2d chore: add memo_relation (#1585) 2023-04-25 22:26:45 +08:00
_Jellen 00f69d683a feat: update Korean translation (#1592)
Update Korean translation

- add missing keys
- polish some translations
- remove trailing whitespaces
2023-04-23 20:13:34 +08:00
boojack 0e70de4003 chore: split memo resource api (#1587) 2023-04-22 10:42:24 +08:00
boojack 35efa927b6 chore: update readme with docs (#1586) 2023-04-22 10:25:32 +08:00
Antzed 1ff03e87c2 docs: upgrade on fly.io (#1582) 2023-04-22 09:34:36 +08:00
boojack edf934efbb chore: update memo style (#1581) 2023-04-21 14:46:41 +08:00
-Shiken- d0815f586e feat: update zh-tw translation to latest file format (#1569)
* update zh-tw translation to latest file format

* Update zh-Hant.json

* Update web/src/locales/zh-Hant.json

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-04-19 20:22:23 +08:00
Yang 685a23bce8 feat: add auto collapse feature for all memos issue #1463 (#1550)
* add auto collapse feature

* fix some styles

* pass eslint

---------

Co-authored-by: liyang <liyangg@umich.edu>
2023-04-18 10:05:36 +08:00
boojack 0aa7085303 chore: add enclosure to rss (#1559) 2023-04-17 23:26:56 +08:00
boojack 994d5dd891 feat: server tests (#1556)
* feat: server tests

* chore: update
2023-04-17 21:34:59 +08:00
deeshu e62a94c05a feat: hiding dialog using X button should remove class "overflow-hidden" (#1555)
Hiding dialogs result in the body to stay frozen due to mounting behaviour of the dialog, but using 'X' button hides the dialog and won't let user scroll any further. Removing overflow behaviour during hiding procedure will improve User Experience.
2023-04-17 20:13:33 +08:00
Manu 2b83572641 fix: the broken install docs link (#1554) 2023-04-17 19:00:13 +08:00
boojack 5f8aae69e4 chore: update save button style (#1542) 2023-04-16 15:47:01 +08:00
1227 changed files with 172733 additions and 32969 deletions
+12
View File
@@ -1 +1,13 @@
web/node_modules
web/dist
.git
.github
build/
tmp/
memos
*.md
.gitignore
.golangci.yaml
.dockerignore
docs/
.DS_Store
+73 -16
View File
@@ -1,31 +1,88 @@
name: Bug Report
description: Create a report to help us improve
labels: [bug]
description: Something isn't working as expected
type: Bug
body:
- type: markdown
attributes:
value: |
If you are reporting a new issue, make sure that we do not have any duplicates already open. You can ensure this by searching the issue list for this repository. If there is a duplicate, please close your issue and add a comment to the existing issue instead.
- type: textarea
Thanks for reporting a bug. Please provide enough detail for maintainers to reproduce the issue.
**Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues) to avoid duplicates.
- type: checkboxes
id: pre-check
attributes:
label: Describe the bug
description: |
Briefly describe the problem you are having in a few paragraphs.
label: Pre-submission Checklist
options:
- label: I have searched existing issues and confirmed this has not already been reported
required: true
- label: This is a bug report, not a question or configuration request
required: true
- type: input
id: version
attributes:
label: Memos Version
description: Use the version shown in **Settings > System**, the container image tag, the release binary version, or `memos --version`. Please do not write `latest` only.
placeholder: "v0.25.x, ghcr.io/usememos/memos:v0.25.x, main@abcdef, or demo site"
validations:
required: true
- type: textarea
id: environment
attributes:
label: Steps to reproduce
description: |
Provide the steps to reproduce the issue.
label: Environment Details
description: Include anything relevant to where Memos is running.
placeholder: |
1. Go to '...'
2. Click on '....'
3. See error
- Deployment: Docker / binary / source / demo site
- Database: SQLite / PostgreSQL / MySQL
- Browser: Chrome 120 on macOS 15
- Server OS: Ubuntu 24.04
- Reverse proxy: nginx / Caddy / Traefik / none
- type: textarea
id: reproduction-steps
attributes:
label: Steps to Reproduce
description: Minimal steps to reliably reproduce the issue
placeholder: |
1. Go to ...
2. Click ...
3. Enter ...
4. See ...
validations:
required: true
- type: textarea
id: current-behavior
attributes:
label: Screenshots or additional context
description: |
Add screenshots or any other context about the problem.
label: Current Behavior
description: What happened? Include exact error messages if available.
placeholder: The application ...
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: What did you expect to happen instead?
placeholder: I expected...
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs
description: Paste relevant server logs, browser console output, or network errors. Remove secrets before submitting.
render: shell
placeholder: |
Paste logs here.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Attach screenshots, screen recordings, sample data, or links to related issues.
placeholder: Drag and drop files here or add any extra context.
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions & Support
url: https://github.com/usememos/memos/discussions
about: Ask questions or get help in GitHub Discussions — please don't open issues for questions
- name: Documentation
url: https://www.usememos.com/docs
about: Check the documentation before opening an issue
+42 -13
View File
@@ -1,28 +1,57 @@
name: Feature Request
description: Suggest an idea for this project
labels: [enhancement]
description: Suggest a new feature or improvement
type: Feature
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to suggest an idea for Memos!
- type: textarea
Thanks for suggesting an improvement. Please describe the problem first so maintainers can evaluate the request.
**Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues?q=label%3Aenhancement) to avoid duplicates.
- type: checkboxes
id: pre-check
attributes:
label: Is your feature request related to a problem?
description: |
A clear and concise description of what the problem is.
label: Pre-submission Checklist
options:
- label: I have searched existing issues and confirmed this has not already been requested
required: true
- label: This is a feature request, not a bug report or support question
required: true
- type: textarea
id: problem
attributes:
label: Problem or Use Case
description: What problem does this solve? Describe the user need, not just the proposed UI or API.
placeholder: |
I'm always frustrated when [...]
I often need to ...
Today, this is difficult because ...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: |
A clear and concise description of what you want to happen.
label: Proposed Solution
description: Describe the behavior you would like Memos to support.
placeholder: |
Memos should ...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request.
label: Alternatives Considered
description: Existing workarounds, related tools, or simpler alternatives you considered.
placeholder: |
I tried ...
It does not work well because ...
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Mockups, screenshots, examples from other apps, API sketches, or any other context.
placeholder: Drag and drop files here or add links/examples.
+76 -27
View File
@@ -1,42 +1,91 @@
name: Backend Test
name: Backend Tests
on:
push:
branches: [main]
pull_request:
branches:
- main
- "release/*.*.*"
branches: [main]
paths:
- "go.mod"
- "go.sum"
- "**.go"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
GO_VERSION: "1.26.2"
jobs:
go-static-checks:
static-checks:
name: Static Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: 1.19
check-latest: true
go-version: ${{ env.GO_VERSION }}
cache: true
cache-dependency-path: go.sum
- name: Verify go.mod is tidy
run: |
go mod tidy -go=1.19
go mod tidy -go=${{ env.GO_VERSION }}
git diff --exit-code
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52.0
args: -v --timeout=3m
skip-cache: true
go-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
go-version: 1.19
check-latest: true
version: v2.11.3
args: --timeout=3m
tests:
name: Tests (${{ matrix.test-group }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test-group: [store, server, internal, other]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Run all tests
run: go test -v ./... | tee test.log; exit ${PIPESTATUS[0]}
- name: Pretty print tests running time
run: grep --color=never -e '--- PASS:' -e '--- FAIL:' test.log | sed 's/[:()]//g' | awk '{print $2,$3,$4}' | sort -t' ' -nk3 -r | awk '{sum += $3; print $1,$2,$3,sum"s"}'
cache-dependency-path: go.sum
- name: Run tests
run: |
case "${{ matrix.test-group }}" in
store)
# Run store tests for all drivers (sqlite, mysql, postgres)
go test -v -coverprofile=coverage.out -covermode=atomic ./store/...
;;
server)
go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/...
;;
internal)
go test -v -race -coverprofile=coverage.out -covermode=atomic ./internal/...
;;
other)
go test -v -race -coverprofile=coverage.out -covermode=atomic \
./cmd/... ./internal/... ./proto/...
;;
esac
env:
DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }}
- name: Upload coverage
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: codecov/codecov-action@v5
with:
files: ./coverage.out
flags: ${{ matrix.test-group }}
fail_ci_if_error: false
@@ -1,69 +0,0 @@
name: build-and-push-release-image
on:
push:
branches:
# Run on pushing branches like `release/1.0.0`
- "release/*.*.*"
jobs:
build-and-push-release-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Extract build args
# Extract version from branch name
# Example: branch name `release/1.0.0` sets up env.VERSION=1.0.0
run: |
echo "VERSION=${GITHUB_REF_NAME#release/}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: neosmemo
password: ${{ secrets.DOCKER_NEOSMEMO_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
install: true
version: v0.9.1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
tags: |
type=raw,value=latest
type=semver,pattern={{version}},value=${{ env.VERSION }}
type=semver,pattern={{major}}.{{minor}},value=${{ env.VERSION }}
type=semver,pattern={{major}},value=${{ env.VERSION }}
- name: Build and Push
id: docker_build
uses: docker/build-push-action@v3
with:
context: ./
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
@@ -1,60 +0,0 @@
name: build-and-push-test-image
on:
push:
branches: [main]
jobs:
build-and-push-test-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: neosmemo
password: ${{ secrets.DOCKER_NEOSMEMO_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
install: true
version: v0.9.1
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
flavor: |
latest=false
tags: |
type=raw,value=test
- name: Build and Push
id: docker_build
uses: docker/build-push-action@v3
with:
context: ./
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+172
View File
@@ -0,0 +1,172 @@
name: Build Canary Image
on:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.repository }}
cancel-in-progress: true
permissions:
contents: read
jobs:
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4.2.0
with:
version: 11.0.1
- uses: actions/setup-node@v6
with:
node-version: "24"
cache: pnpm
cache-dependency-path: "web/pnpm-lock.yaml"
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- run: pnpm install --frozen-lockfile
working-directory: web
- name: Run frontend build
run: pnpm release
working-directory: web
- name: Upload frontend artifacts
uses: actions/upload-artifact@v6
with:
name: frontend-dist
path: server/router/frontend/dist
retention-days: 1
build-push:
needs: build-frontend
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
steps:
- uses: actions/checkout@v6
- name: Download frontend artifacts
uses: actions/download-artifact@v7
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
build-args: |
VERSION=canary
COMMIT=${{ github.sha }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v6
with:
name: digests-${{ strategy.job-index }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
needs: build-push
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v7
with:
pattern: digests-*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
flavor: |
latest=false
tags: |
type=raw,value=canary
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
- name: Inspect images
run: |
docker buildx imagetools inspect neosmemo/memos:canary
docker buildx imagetools inspect ghcr.io/usememos/memos:canary
-68
View File
@@ -1,68 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["go", "javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+17
View File
@@ -0,0 +1,17 @@
name: Demo Deploy
on:
workflow_dispatch:
jobs:
deploy-demo:
runs-on: ubuntu-latest
steps:
- name: Trigger Render Deploy
run: |
curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \
-H "Content-Type: application/json" \
-d '{"trigger": "github_action"}'
- name: Deployment Status
run: echo "Demo deployment triggered successfully on Render"
-66
View File
@@ -1,66 +0,0 @@
name: "E2E Test"
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
name: Build and Run Memos With E2E Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build Docker image
id: docker_build
uses: docker/build-push-action@v3
with:
context: ./
file: ./Dockerfile
platforms: linux/amd64
push: false
tags: neosmemo/memos:e2e
labels: neosmemo/memos:e2e
- name: Run Docker container
run: docker run -d -p 5230:5230 neosmemo/memos:e2e
- uses: pnpm/action-setup@v2.2.4
with:
version: 8.0.0
- uses: actions/setup-node@v3
with:
node-version: 18
cache: "pnpm"
cache-dependency-path: ./web/pnpm-lock.yaml
- name: Install dependencies
working-directory: web
run: pnpm install
- name: Install Playwright Browsers
working-directory: web
run: npx playwright install --with-deps
- name: Run Playwright tests
working-directory: web
run: npx playwright test
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: web/playwright-report/
retention-days: 30
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-screenshot
path: web/playwright-screenshot/
retention-days: 30
- name: Stop Docker container
run: docker stop $(docker ps -q)
+61 -29
View File
@@ -1,44 +1,76 @@
name: Frontend Test
name: Frontend Tests
on:
push:
branches: [main]
pull_request:
branches:
- main
- "release/*.*.*"
branches: [main]
paths:
- "web/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "24"
PNPM_VERSION: "11.0.1"
jobs:
eslint-checks:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
with:
version: 8.0.0
- uses: actions/setup-node@v3
with:
node-version: "18"
cache: pnpm
cache-dependency-path: "web/pnpm-lock.yaml"
- run: pnpm install
working-directory: web
- name: Run eslint check
run: pnpm lint
working-directory: web
- name: Checkout code
uses: actions/checkout@v6
frontend-build:
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Run lint
working-directory: web
run: pnpm lint
- name: Run unit tests
working-directory: web
run: pnpm test
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- name: Checkout code
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: 8.0.0
- uses: actions/setup-node@v3
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "18"
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: "web/pnpm-lock.yaml"
- run: pnpm install
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Build frontend
working-directory: web
- name: Run frontend build
run: pnpm build
working-directory: web
-18
View File
@@ -1,18 +0,0 @@
name: 'issue-translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: usthe/issues-translate-action@v2.7
with:
IS_MODIFY_TITLE: false
# not require, default false, . Decide whether to modify the issue title
# if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot.
CUSTOM_BOT_NOTE: Issue is not in English. It has been translated automatically.
# not require. Customize the translation robot prefix message.
+40
View File
@@ -0,0 +1,40 @@
name: Proto Linter
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "proto/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint Protos
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup buf
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ github.token }}
- name: Run buf lint
uses: bufbuild/buf-lint-action@v1
with:
input: proto
- name: Check buf format
run: |
if [[ $(buf format -d) ]]; then
echo "❌ Proto files are not formatted. Run 'buf format -w' to fix."
exit 1
fi
+37
View File
@@ -0,0 +1,37 @@
name: Release Please
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
issues: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- name: Check release token
env:
RELEASE_PLEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
run: |
if [ -z "$RELEASE_PLEASE_TOKEN" ]; then
echo "RELEASE_PLEASE_TOKEN must be set to a fine-grained PAT so release-please tags can trigger release.yml." >&2
exit 1
fi
- name: Run release-please
uses: googleapis/release-please-action@v4
with:
# Use a fine-grained PAT so generated tags trigger release.yml.
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
+384
View File
@@ -0,0 +1,384 @@
name: Release
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
GO_VERSION: "1.26.2"
NODE_VERSION: "24"
PNPM_VERSION: "11.0.1"
ARTIFACT_RETENTION_DAYS: 60
ARTIFACT_PREFIX: memos
jobs:
prepare:
name: Extract Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
major_minor: ${{ steps.version.outputs.major_minor }}
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
steps:
- name: Extract version
id: version
env:
REF_NAME: ${{ github.ref_name }}
EVENT_NAME: ${{ github.event_name }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
echo "tag=" >> "$GITHUB_OUTPUT"
echo "version=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
echo "major_minor=" >> "$GITHUB_OUTPUT"
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ ! "$REF_NAME" =~ ^v([0-9]+\.[0-9]+\.[0-9]+)(-rc\.[0-9]+)?$ ]]; then
echo "Unsupported release tag format: $REF_NAME" >&2
exit 1
fi
version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
major_minor="${BASH_REMATCH[1]%.*}"
is_prerelease=false
if [ -n "${BASH_REMATCH[2]}" ]; then
is_prerelease=true
fi
echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT"
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "major_minor=${major_minor}" >> "$GITHUB_OUTPUT"
echo "is_prerelease=${is_prerelease}" >> "$GITHUB_OUTPUT"
build-frontend:
name: Build Frontend
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path)" >> "$GITHUB_OUTPUT"
- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Build frontend release assets
working-directory: web
run: pnpm release
- name: Upload frontend artifacts
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: server/router/frontend/dist
retention-days: 1
build-binaries:
name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }}
needs: [prepare, build-frontend]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: linux
goarch: arm
goarm: "7"
- goos: darwin
goarch: amd64
- goos: darwin
goarch: arm64
- goos: windows
goarch: amd64
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Download frontend artifacts
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Build binary
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
CGO_ENABLED: "0"
run: |
output_name="memos"
if [ "$GOOS" = "windows" ]; then
output_name="memos.exe"
fi
mkdir -p build
go build \
-trimpath \
-ldflags="-s -w -X github.com/usememos/memos/internal/version.Version=${{ needs.prepare.outputs.version }} -X github.com/usememos/memos/internal/version.Commit=${{ github.sha }} -extldflags '-static'" \
-tags netgo,osusergo \
-o "build/${output_name}" \
./cmd/memos
- name: Package binary
env:
VERSION: ${{ needs.prepare.outputs.version }}
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
run: |
cd build
package_name="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}"
if [ -n "$GOARM" ]; then
package_name="${package_name}v${GOARM}"
fi
if [ "$GOOS" = "windows" ]; then
artifact_name="${package_name}.zip"
zip -q "${artifact_name}" memos.exe
else
artifact_name="${package_name}.tar.gz"
tar czf "${artifact_name}" memos
fi
echo "artifact_name=${artifact_name}" >> "$GITHUB_ENV"
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_name }}
path: build/${{ env.artifact_name }}
retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
checksums:
name: Generate Checksums
needs: [prepare, build-binaries]
runs-on: ubuntu-latest
steps:
- name: Download binary artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: ${{ env.ARTIFACT_PREFIX }}_*
merge-multiple: true
- name: Generate checksums
working-directory: artifacts
run: sha256sum * > checksums.txt
- name: Upload checksum artifact
uses: actions/upload-artifact@v4
with:
name: checksums
path: artifacts/checksums.txt
retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
release:
name: Publish GitHub Release
needs: [prepare, build-binaries, checksums]
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download binary artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: ${{ env.ARTIFACT_PREFIX }}_*
merge-multiple: true
- name: Download checksum artifact
uses: actions/download-artifact@v4
with:
name: checksums
path: artifacts
- name: Publish release assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare.outputs.tag }}
name: ${{ needs.prepare.outputs.tag }}
prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }}
files: artifacts/*
build-push:
name: Build Image ${{ matrix.platform }}
needs: [prepare, build-frontend]
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Download frontend artifacts
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
build-args: |
VERSION=${{ needs.prepare.outputs.version }}
COMMIT=${{ github.sha }}
cache-from: type=gha,scope=release-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=release-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ strategy.job-index }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge-images:
name: Publish Release Image Tags
needs: [prepare, build-push]
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digests-*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
version="${{ needs.prepare.outputs.version }}"
if [ "${{ needs.prepare.outputs.is_prerelease }}" = "true" ]; then
docker buildx imagetools create \
-t "neosmemo/memos:${version}" \
-t "ghcr.io/usememos/memos:${version}" \
$(printf 'neosmemo/memos@sha256:%s ' *)
exit 0
fi
docker buildx imagetools create \
-t "neosmemo/memos:${version}" \
-t "neosmemo/memos:${{ needs.prepare.outputs.major_minor }}" \
-t "neosmemo/memos:stable" \
-t "ghcr.io/usememos/memos:${version}" \
-t "ghcr.io/usememos/memos:${{ needs.prepare.outputs.major_minor }}" \
-t "ghcr.io/usememos/memos:stable" \
$(printf 'neosmemo/memos@sha256:%s ' *)
- name: Inspect images
run: |
docker buildx imagetools inspect neosmemo/memos:${{ needs.prepare.outputs.version }}
if [ "${{ needs.prepare.outputs.is_prerelease }}" = "true" ]; then
exit 0
fi
docker buildx imagetools inspect neosmemo/memos:stable
+24
View File
@@ -0,0 +1,24 @@
name: Close Stale
on:
schedule:
- cron: "0 */8 * * *" # Every 8 hours
jobs:
close-stale:
name: Close Stale Issues and PRs
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Mark and close stale issues and PRs
uses: actions/stale@v10.1.1
with:
# Issues: mark stale after 14 days of inactivity, close after 3 more days
days-before-issue-stale: 14
days-before-issue-close: 3
# Pull requests: mark stale after 14 days of inactivity, close after 3 more days
days-before-pr-stale: 14
days-before-pr-close: 3
-85
View File
@@ -1,85 +0,0 @@
name: Build PR Image
on:
pull_request:
types: [opened, synchronize, reopened, closed]
jobs:
build-memos:
name: Build and push `Memos`
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
if: ${{ github.event.action != 'closed' }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate UUID image name
id: uuid
run: echo "UUID_WORKER=$(uuidgen)" >> $GITHUB_ENV
- name: Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_WORKER }}
tags: |
type=raw,value=60d
- name: Build and Push Image to registry.uffizzi.com - Uffizzi's ephemeral Registry
uses: docker/build-push-action@v3
with:
context: ./
file: Dockerfile
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
cache-from: type=gha
cache-to: type=gha, mode=max
render-compose-file:
name: Render Docker Compose File
# Pass output of this workflow to another triggered by `workflow_run` event.
runs-on: ubuntu-latest
needs:
- build-memos
outputs:
compose-file-cache-key: ${{ steps.hash.outputs.hash }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Render Compose File
run: |
MEMOS_IMAGE=${{ needs.build-memos.outputs.tags }}
export MEMOS_IMAGE
# Render simple template from environment variables.
envsubst < docker-compose.uffizzi.yml > docker-compose.rendered.yml
cat docker-compose.rendered.yml
- name: Upload Rendered Compose File as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: docker-compose.rendered.yml
retention-days: 2
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: ${{github.event_path}}
retention-days: 2
delete-preview:
name: Call for Preview Deletion
runs-on: ubuntu-latest
if: ${{ github.event.action == 'closed' }}
steps:
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: ${{github.event_path}}
retention-days: 2
-88
View File
@@ -1,88 +0,0 @@
name: Deploy Uffizzi Preview
on:
workflow_run:
workflows:
- "Build PR Image"
types:
- completed
jobs:
cache-compose-file:
name: Cache Compose File
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
outputs:
compose-file-cache-key: ${{ env.HASH }}
pr-number: ${{ env.PR_NUMBER }}
steps:
- name: 'Download artifacts'
# Fetch output (zip archive) from the workflow run that triggered this workflow.
uses: actions/github-script@v6
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "preview-spec"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
- name: 'Unzip artifact'
run: unzip preview-spec.zip
- name: Read Event into ENV
run: |
echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
cat event.json >> $GITHUB_ENV
echo -e '\nEOF' >> $GITHUB_ENV
- name: Hash Rendered Compose File
id: hash
# If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
run: echo "HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
- name: Cache Rendered Compose File
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
uses: actions/cache@v3
with:
path: docker-compose.rendered.yml
key: ${{ env.HASH }}
- name: Read PR Number From Event Object
id: pr
run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
- name: DEBUG - Print Job Outputs
if: ${{ runner.debug }}
run: |
echo "PR number: ${{ env.PR_NUMBER }}"
echo "Compose file hash: ${{ env.HASH }}"
cat event.json
deploy-uffizzi-preview:
name: Use Remote Workflow to Preview on Uffizzi
if: ${{ github.event.workflow_run.conclusion == 'success' }}
needs:
- cache-compose-file
uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2
with:
# If this workflow was triggered by a PR close event, cache-key will be an empty string
# and this reusable workflow will delete the preview deployment.
compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
compose-file-cache-path: docker-compose.rendered.yml
server: https://app.uffizzi.com
pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
permissions:
contents: read
pull-requests: write
id-token: write
+21 -6
View File
@@ -1,18 +1,33 @@
# Air (hot reload) generated
.air
# temp folder
tmp
# Frontend asset
web/dist
# build folder
build
# Build artifacts
build/
bin/
memos
.DS_Store
# Jetbrains
.idea
bin/air
# Docker Compose Environment File
.env
dist
# VSCode settings
.vscode
# Git worktrees
.worktrees/
# Local pnpm store (project-scoped, created when --config.store-dir is set
# without an existing store; contains a symlink back to the workspace).
.pnpm-store/
# Frontend test coverage output (Vitest + @vitest/coverage-v8).
web/coverage/
+89 -52
View File
@@ -1,6 +1,7 @@
version: "2"
linters:
enable:
- goimports
- revive
- govet
- staticcheck
@@ -10,55 +11,91 @@ linters:
- rowserrcheck
- nilerr
- godot
- forbidigo
- mirror
- bodyclose
disable:
- errcheck
settings:
exhaustive:
explicit-exhaustive-switch: false
staticcheck:
checks:
- all
- -ST1000
- -ST1003
- -ST1021
- -QF1003
revive:
# Default to run all linters so that new rules in the future could automatically be added to the static check.
enable-all-rules: true
rules:
# The following rules are too strict and make coding harder. We do not enable them for now.
- name: file-header
disabled: true
- name: line-length-limit
disabled: true
- name: function-length
disabled: true
- name: max-public-structs
disabled: true
- name: function-result-limit
disabled: true
- name: banned-characters
disabled: true
- name: argument-limit
disabled: true
- name: cognitive-complexity
disabled: true
- name: cyclomatic
disabled: true
- name: confusing-results
disabled: true
- name: add-constant
disabled: true
- name: flag-parameter
disabled: true
- name: nested-structs
disabled: true
- name: import-shadowing
disabled: true
- name: early-return
disabled: true
- name: use-any
disabled: true
- name: exported
disabled: true
- name: unhandled-error
disabled: true
- name: if-return
disabled: true
- name: max-control-nesting
disabled: true
- name: redefines-builtin-id
disabled: true
- name: package-comments
disabled: true
gocritic:
disabled-checks:
- ifElseChain
govet:
settings:
printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers
funcs: # Run `go tool vet help printf` to see the full configuration of `printf`.
- common.Errorf
enable-all: true
disable:
- fieldalignment
- shadow
forbidigo:
forbid:
- pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
- pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?'
issues:
exclude:
- Rollback
- fmt.Printf
- fmt.Print
linters-settings:
revive:
enable-all-rules: true
rules:
- name: file-header
disabled: true
- name: line-length-limit
disabled: true
- name: function-length
disabled: true
- name: max-public-structs
disabled: true
- name: function-result-limit
disabled: true
- name: banned-characters
disabled: true
- name: argument-limit
disabled: true
- name: cognitive-complexity
disabled: true
- name: cyclomatic
disabled: true
- name: confusing-results
disabled: true
- name: add-constant
disabled: true
- name: flag-parameter
disabled: true
- name: nested-structs
disabled: true
- name: import-shadowing
disabled: true
- name: early-return
disabled: true
gocritic:
disabled-checks:
- ifElseChain
govet:
settings:
printf:
funcs:
- common.Errorf
forbidigo:
forbid:
- 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
formatters:
enable:
- goimports
settings:
goimports:
local-prefixes:
- github.com/usememos/memos
+3
View File
@@ -0,0 +1,3 @@
{
".": "0.29.1"
}
-3
View File
@@ -1,3 +0,0 @@
{
"recommendations": ["golang.go"]
}
-12
View File
@@ -1,12 +0,0 @@
{
"folders": [
{
"name": "server",
"path": "../"
},
{
"name": "web",
"path": "../web"
}
]
}
-5
View File
@@ -1,5 +0,0 @@
{
"go.lintOnSave": "workspace",
"go.lintTool": "golangci-lint",
"go.inferGopath": false
}
+106
View File
@@ -0,0 +1,106 @@
# AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 6 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL.
## Commands
```bash
# Backend
go run ./cmd/memos --port 8081 # Start dev server
go test ./... # Run all tests
go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers)
go test -v -race ./server/... # Run server tests with race detection
go test -v -race ./internal/... # Run internal package tests with race detection
go test -v -run TestFoo ./pkg/... # Run a single test
go mod tidy -go=1.26.2 # Match CI tidy check
golangci-lint run # Lint (v2, config: .golangci.yaml)
golangci-lint run --fix # Auto-fix lint issues (includes goimports)
# Frontend (cd web)
pnpm install # Install deps
pnpm dev # Dev server (:3001, proxies API to :8081)
pnpm lint # Type check + Biome lint
pnpm lint:fix # Auto-fix lint issues
pnpm format # Format code
pnpm build # Production build
pnpm release # Build to server/router/frontend/dist
# Protocol Buffers (cd proto)
buf generate # Regenerate Go + TypeScript + OpenAPI
buf lint # Lint proto files
buf format -w # Format proto files
```
## Architecture
```
cmd/memos/main.go # Cobra CLI + Viper config, server init
server/
├── server.go # Echo v5 HTTP server, background runners
├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT
├── router/
│ ├── api/v1/ # 8 gRPC services (Connect + Gateway)
│ │ ├── acl_config.go # Public endpoints whitelist
│ │ ├── sse_hub.go # Server-Sent Events (live updates)
│ │ └── mcp/ # MCP server for AI assistants
│ ├── frontend/ # SPA static file serving
│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests)
│ └── rss/ # RSS feeds
└── runner/ # Background: memo payload processing, S3 presign refresh
store/
├── driver.go # Database driver interface
├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000)
├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades)
└── db/{sqlite,mysql,postgres}/ # Driver implementations
proto/
├── api/v1/ # Service definitions
├── store/ # Internal storage messages
└── gen/ # Generated Go, TypeScript, OpenAPI
internal/ # app-private packages: scheduler, cron, email, filter (CEL),
# webhook, markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3
web/src/
├── connect.ts # Connect RPC client + auth interceptor + token refresh
├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab)
├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext
├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.)
├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min)
├── router/index.tsx # Route definitions
├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.)
├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens
└── pages/ # Page components
```
## Conventions
### Go
- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo).
- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods.
- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter).
- **Comments:** All exported functions must have doc comments (godot enforced).
### Frontend
- **Imports:** Use `@/` alias for absolute imports.
- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent.
- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`).
- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants.
### Database & Proto
- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`.
- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`.
- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`.
## CI/CD
- **backend-tests.yml:** Go 1.26.2, `go mod tidy -go=1.26.2`, golangci-lint v2.11.3, tests parallelized by group (store, server, internal, other)
- **build-canary-image.yml:** Builds frontend with `pnpm release`, then publishes canary multi-arch container images for linux/amd64 and linux/arm64
- **frontend-tests.yml:** Node 24, pnpm 11, lint + build
- **proto-linter.yml:** buf lint + format check
- **release.yml:** On version tags, builds frontend once, packages binaries for Linux/macOS/Windows, and publishes release container images/tags
- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7)
+183
View File
@@ -0,0 +1,183 @@
# Changelog
## [0.29.1](https://github.com/usememos/memos/compare/v0.29.0...v0.29.1) (2026-06-04)
### Bug Fixes
* **markdown:** keep task item content in one grid column ([7c3bff4](https://github.com/usememos/memos/commit/7c3bff4e98223fb99a5d49f093e3cd57dd140ba4))
* support &lt;meta name=description&gt; in link previews ([#6000](https://github.com/usememos/memos/issues/6000)) ([e8d32e8](https://github.com/usememos/memos/commit/e8d32e87d1d6e4927250ad5794ba5965e0260153))
* **web:** render video attachment posters on mobile ([0e2a9a9](https://github.com/usememos/memos/commit/0e2a9a9c0ce0e2da63535210c553b3ae2f79b239))
## [0.29.0](https://github.com/usememos/memos/compare/v0.28.0...v0.29.0) (2026-05-27)
### Features
* **about:** add about page with bird sprites ([411ba7b](https://github.com/usememos/memos/commit/411ba7b34c0c23ad217a7897835097887a28a036))
* **activity-calendar:** aggregate by ViewContext.timeBasis ([8daef1d](https://github.com/usememos/memos/commit/8daef1dc89544512fff78fd64d8216b2babc2e42))
* add &lt;Placeholder&gt; component with ASCII bird states ([#5949](https://github.com/usememos/memos/issues/5949)) ([8c16ffa](https://github.com/usememos/memos/commit/8c16ffa1f1410f9413cb57ebe251b4b604f9aeff))
* add configurable `--log-level` flag ([#5934](https://github.com/usememos/memos/issues/5934)) ([f1e2a06](https://github.com/usememos/memos/commit/f1e2a06b46c7f45ba6562c308d2703fdfb4067b0))
* add dedicated shortcuts page ([#5942](https://github.com/usememos/memos/issues/5942)) ([1df6479](https://github.com/usememos/memos/commit/1df6479443c334732b862d60a0f76e61f00ebb89))
* add link metadata endpoints ([9c5c604](https://github.com/usememos/memos/commit/9c5c604944428d3f682f35c9d05a87c1d4c3152f))
* **frontend:** add pixel bird tilemaps ([cf55f11](https://github.com/usememos/memos/commit/cf55f1107273c928e7c2d6bc26df5f3efea26458))
* **memo:** add task list quick actions ([#5983](https://github.com/usememos/memos/issues/5983)) ([648b3bd](https://github.com/usememos/memos/commit/648b3bd812e5bf2b1abb9f8b3529efefe4734e7c))
* **memo:** create memos on the selected calendar date ([#5925](https://github.com/usememos/memos/issues/5925)) ([ef55013](https://github.com/usememos/memos/commit/ef55013418d68e2d6a24a6d02a0365c1ffff03d7))
* **notification:** add smtp email settings ([cd4f28a](https://github.com/usememos/memos/commit/cd4f28ae1058a125e245ea0a6eae16aea71b8f9d))
* **placeholder:** add woodpecker tilemap ([638e4f3](https://github.com/usememos/memos/commit/638e4f398e90c556f70af150a79538312c8fc760))
* render link metadata cards ([0bc5669](https://github.com/usememos/memos/commit/0bc56694b0ca347ab1eb083f62997a22007b763d))
* **stats:** admin instance resource statistics ([ea0625d](https://github.com/usememos/memos/commit/ea0625da45a419e08158ab4102051f3fe5e59b87))
* **stats:** support filtered all-user stats ([88ac3ec](https://github.com/usememos/memos/commit/88ac3ec31ee3e808db82663c04a31cf730d1221e))
* **transcription:** explicit STT settings with provider, model, prompt ([#5926](https://github.com/usememos/memos/issues/5926)) ([238f27d](https://github.com/usememos/memos/commit/238f27dea149492a78a8994470b0aac55fece78d))
### Bug Fixes
* avoid update event on memo create attachments ([#5961](https://github.com/usememos/memos/issues/5961)) ([3c3382a](https://github.com/usememos/memos/commit/3c3382a3c652bed3b58058931ff3cbf1d875b9a8))
* delete user cleanup ([#5981](https://github.com/usememos/memos/issues/5981)) ([e53b7d9](https://github.com/usememos/memos/commit/e53b7d96e70965529ba3b04ea720ea6966f77b60))
* **editor:** wrap selected text when pasting URL ([e0bb3a2](https://github.com/usememos/memos/commit/e0bb3a2e684e932309df2f9fb0ff774ce8e6b692))
* **fileserver:** preserve HDR image metadata in thumbnails ([c724232](https://github.com/usememos/memos/commit/c7242324a18962e453e7f2a0309a7c07b358bdbe))
* **frontend:** correct static cache headers ([084f40b](https://github.com/usememos/memos/commit/084f40bc9e5922ff2d41c08dce837b96696437aa))
* **frontend:** use correct url path for memos in sitemap.xml ([#5921](https://github.com/usememos/memos/issues/5921)) ([603781f](https://github.com/usememos/memos/commit/603781f792b2603fbda93146988a64a93c92d760))
* **httpgetter:** prevent DNS rebinding in link metadata fetch ([078488c](https://github.com/usememos/memos/commit/078488ca818626fbcab69bdfb4b93b58dca6b6eb))
* **markdown:** align list items with checkboxes ([e008b1a](https://github.com/usememos/memos/commit/e008b1a23c77945eff87707eb15578d4d6d74e4c))
* **memo:** enforce parent visibility for comments ([4a1e401](https://github.com/usememos/memos/commit/4a1e401bd99c7850ac48e9693b25c9ebeecfb042))
* **s3presign:** preserve motion media payload ([7f1f53f](https://github.com/usememos/memos/commit/7f1f53ffc417962f6930d1e6e3783eacd911003d))
* **security:** enforce attachment ownership on memo updates ([35bf761](https://github.com/usememos/memos/commit/35bf761b8c2c3f155bdc06e9b373b6076116a725))
* **sse:** stream initial response and refresh tokens ([21303e8](https://github.com/usememos/memos/commit/21303e879d2c7a857306206d2cbdae83f61983e6))
* **user:** omit internal settings from list responses ([#5917](https://github.com/usememos/memos/issues/5917)) ([1df3fe7](https://github.com/usememos/memos/commit/1df3fe79559ccf94b6c71e9ffb58e870ed43820d))
* **web:** sync avatar changes immediately after profile update ([#5903](https://github.com/usememos/memos/issues/5903)) ([328396a](https://github.com/usememos/memos/commit/328396a97f2219592032e8418c383e0ab7edaca6))
### Performance Improvements
* lazy load heavy first-screen dependencies ([#5947](https://github.com/usememos/memos/issues/5947)) ([a6024ee](https://github.com/usememos/memos/commit/a6024eebf129c4b8fb65ee0cba09c6657274bfde))
## [0.28.0](https://github.com/usememos/memos/compare/v0.27.1...v0.28.0) (2026-04-27)
### Features
* **auth:** add SSO user identity linkage ([#5883](https://github.com/usememos/memos/issues/5883)) ([d688914](https://github.com/usememos/memos/commit/d688914b2864791eeadbf21c882608632875f17c))
* **memos:** choose created or updated time for memos ([#5894](https://github.com/usememos/memos/issues/5894)) ([c268551](https://github.com/usememos/memos/commit/c268551a16929a2cbea6891951feff91926bba59))
* redesign account and SSO management ([#5886](https://github.com/usememos/memos/issues/5886)) ([ee17998](https://github.com/usememos/memos/commit/ee1799851e88674a6920c7a56d93428fcf95e662))
### Bug Fixes
* **auth:** harden authorization and username validation ([#5890](https://github.com/usememos/memos/issues/5890)) ([0fb83a7](https://github.com/usememos/memos/commit/0fb83a745dd5057ade45a3caad2c444af2239113))
* disable modal prop on DropdownMenu to prevent scroll disappearing ([#5861](https://github.com/usememos/memos/issues/5861)) ([d98f665](https://github.com/usememos/memos/commit/d98f6659190b8d1a8252e64549d9120d85e05d33))
* fix legacy username auth flows ([#5885](https://github.com/usememos/memos/issues/5885)) ([30c0611](https://github.com/usememos/memos/commit/30c0611a82f9254952a74650095105254f2940e4))
* **markdown:** split mixed task and bullet lists ([e2c6084](https://github.com/usememos/memos/commit/e2c60845eaff9a78b8d8eb3ccc9a067ef5690976))
* reduce list memo query overhead ([#5880](https://github.com/usememos/memos/issues/5880)) ([5063804](https://github.com/usememos/memos/commit/50638040f618b02b0c6d010e1d41554c75067517))
* **web:** preserve task checkbox state ([#5867](https://github.com/usememos/memos/issues/5867)) ([b5863d7](https://github.com/usememos/memos/commit/b5863d76be3cfbf3e0f8237d8e762122b5a0a679))
## [0.27.1](https://github.com/usememos/memos/compare/v0.27.0...v0.27.1) (2026-04-19)
### Bug Fixes
* mixed-case user resource names ([#5853](https://github.com/usememos/memos/issues/5853)) ([01be01f](https://github.com/usememos/memos/commit/01be01f4b7676af41bdd1758b1e9b096aa922546))
* **release:** inject build version into artifacts ([f8a304b](https://github.com/usememos/memos/commit/f8a304bae33086320b39095d631288156eec4249))
* user resource names can be uuidv4 from idp sub claim ([#5856](https://github.com/usememos/memos/issues/5856)) ([bbded58](https://github.com/usememos/memos/commit/bbded584ce85a856d863485768e08b53adec7244))
## [0.27.0](https://github.com/usememos/memos/compare/v0.26.2...v0.27.0) (2026-04-18)
### Features
* add --allow-private-webhooks flag to bypass SSRF protection ([#5694](https://github.com/usememos/memos/issues/5694)) ([cd5816c](https://github.com/usememos/memos/commit/cd5816c428931f56561f7d48b649a33858812539))
* add blur_content attribute to tag metadata settings ([#5767](https://github.com/usememos/memos/issues/5767)) ([45b2153](https://github.com/usememos/memos/commit/45b21530d9ebbc730e77bcbcf407f4c295b52e93))
* add Gemini transcription provider ([#5830](https://github.com/usememos/memos/issues/5830)) ([d87539a](https://github.com/usememos/memos/commit/d87539a1e1261590ab355220e33fa0ae00bd9431))
* add GitHub release installer and release workflow ([1ed542c](https://github.com/usememos/memos/commit/1ed542c21db421e9aa0cc47417a92c6bd103e257))
* add live refresh via Server-Sent Events (SSE) with visual indicator ([#5638](https://github.com/usememos/memos/issues/5638)) ([ea0892a](https://github.com/usememos/memos/commit/ea0892a8b26d8806a093e3a942562dfc22794f68))
* add MCP server with PAT authentication ([47d9414](https://github.com/usememos/memos/commit/47d9414702dc18966af385352b960bfe451511b7))
* add outline navigation to memo detail sidebar ([#5771](https://github.com/usememos/memos/issues/5771)) ([6b30579](https://github.com/usememos/memos/commit/6b3057990396f9cb6f21706c2e99dddebc35ffd5))
* **ai:** add BYOK audio transcription ([#5832](https://github.com/usememos/memos/issues/5832)) ([101704c](https://github.com/usememos/memos/commit/101704c8eac17c7f34508d8db6c53bc972061cdb))
* **ai:** add instance AI providers and transcription ([#5829](https://github.com/usememos/memos/issues/5829)) ([83ed32f](https://github.com/usememos/memos/commit/83ed32f1195841d2d6c057c3e00086a3147879a2))
* **attachments:** add Live Photo and Motion Photo support ([#5810](https://github.com/usememos/memos/issues/5810)) ([4b4e719](https://github.com/usememos/memos/commit/4b4e719470184e49cd62084b1aa53c9a777a9fec))
* **cli:** add version subcommand ([#5731](https://github.com/usememos/memos/issues/5731)) ([0ba4c0f](https://github.com/usememos/memos/commit/0ba4c0f397c532a5a314f35ddeb3ce3633e84d42))
* **editor:** add voice note recording to the memo composer ([#5801](https://github.com/usememos/memos/issues/5801)) ([c0d5854](https://github.com/usememos/memos/commit/c0d5854f678f357cf4054d448e0311f2ee90f8ac))
* extract title from first H1 heading into memo property ([#5726](https://github.com/usememos/memos/issues/5726)) ([1e688b2](https://github.com/usememos/memos/commit/1e688b2a5d78c2972f4b0078a7b033dae5d1cbf3))
* **i18n:** update sse connect label in Chinese ([#5732](https://github.com/usememos/memos/issues/5732)) ([89c6902](https://github.com/usememos/memos/commit/89c69028953fa33dbb6e0e257d764636c0fc2d09))
* **instance:** add canonical tag metadata setting ([#5736](https://github.com/usememos/memos/issues/5736)) ([65d14fb](https://github.com/usememos/memos/commit/65d14fbb63053fc1fbf1f63881c81adbc9d01671))
* **instance:** add notification transport setting ([#5737](https://github.com/usememos/memos/issues/5737)) ([a249d06](https://github.com/usememos/memos/commit/a249d06e2e0f33e0e3fea34471a891352dacc466))
* **mcp:** enhance MCP server with full capabilities and new tools ([#5720](https://github.com/usememos/memos/issues/5720)) ([b8e9ee2](https://github.com/usememos/memos/commit/b8e9ee2b26a59e1b19aab6db3ca39656fc18785a))
* **mcp:** harden tool exposure and side effects ([#5850](https://github.com/usememos/memos/issues/5850)) ([583c3d2](https://github.com/usememos/memos/commit/583c3d24f4d785faa5e034c1b88ed90eda119baa))
* **mcp:** refactor MCP server to standard protocol structure ([803d488](https://github.com/usememos/memos/commit/803d488a5f8f55477cd3ad4cc4cf0fac98901dd3))
* **memo-editor:** add compact live waveform recorder panel ([#5817](https://github.com/usememos/memos/issues/5817)) ([e51985a](https://github.com/usememos/memos/commit/e51985a29ffeeecd318b2fb793358ed45bb0eff4))
* **memo-preview:** support comment metadata in previews ([#5768](https://github.com/usememos/memos/issues/5768)) ([e176b28](https://github.com/usememos/memos/commit/e176b28c801cc3bb3718208a96a7d64c36620d0f))
* **memo:** add image sharing in detail view ([38fc22b](https://github.com/usememos/memos/commit/38fc22b7541b8a9ddcd848cf77054fcf844eb87f))
* **memo:** add share links for private memos ([#5742](https://github.com/usememos/memos/issues/5742)) ([3f3133d](https://github.com/usememos/memos/commit/3f3133d6e2f404061e147f9dd2424680dc0303a3))
* **mentions:** add memo mention parsing, notifications, and rendering ([#5811](https://github.com/usememos/memos/issues/5811)) ([24fc8ab](https://github.com/usememos/memos/commit/24fc8ab8ca68d092e7b12a5d51c48ca9420f72b5))
* replace auto-increment ID with UID for identity provider resource names ([#5687](https://github.com/usememos/memos/issues/5687)) ([92d937b](https://github.com/usememos/memos/commit/92d937b1aa87365152edc005a3b736e6bf9b9e45))
* show inline comment preview in list view ([3a5d3c8](https://github.com/usememos/memos/commit/3a5d3c8ff92ae5c24559dc4574300d6475820a87))
* **store:** change default storage type to local filesystem ([78efa68](https://github.com/usememos/memos/commit/78efa6802e2fd96c981e86c5b658fb4b5c05091f))
* treat tag setting keys as anchored regex patterns ([#5759](https://github.com/usememos/memos/issues/5759)) ([9e04049](https://github.com/usememos/memos/commit/9e04049632e63f1cf53535773f170c1aa5af7168))
* **ui:** allow navigating between images with arrows in preview dialog ([#5669](https://github.com/usememos/memos/issues/5669)) ([104d2ec](https://github.com/usememos/memos/commit/104d2ec0a6973e983c46724165fdc0916515ad16))
* **user:** add per-user tag metadata settings ([#5735](https://github.com/usememos/memos/issues/5735)) ([330291d](https://github.com/usememos/memos/commit/330291d4d9fa95649e940001898929b4f6f0367e))
* **web:** add demo mode banner ([#5836](https://github.com/usememos/memos/issues/5836)) ([35504cc](https://github.com/usememos/memos/commit/35504cc8bd6f9921291fb565633d549388a3f948))
* **webhook:** dispatch webhook on memo comment creation ([7c1defb](https://github.com/usememos/memos/commit/7c1defba01fbc91cc81e1a0841cecb6738056db7))
### Bug Fixes
* access token refresh on web app ([#5681](https://github.com/usememos/memos/issues/5681)) ([3010f10](https://github.com/usememos/memos/commit/3010f10eafb49af5aadd71a94b3ef7a6ec71f617))
* add unix socket file permission setting (755 -&gt; 660) ([#5849](https://github.com/usememos/memos/issues/5849)) ([0fc1dab](https://github.com/usememos/memos/commit/0fc1dab28b33f7fdbe9a21cd3bd3affe75dd7f19))
* **api:** appease image size lint ([ff6389a](https://github.com/usememos/memos/commit/ff6389a5ef73772fcb5c132bf1cb169fb4744c00))
* **api:** improve SSE hub design and fix double-broadcast on comments ([c53677f](https://github.com/usememos/memos/commit/c53677fcba202a8eed35c8ecdfaacea5152b8691))
* **api:** make credentials write-only and restrict sensitive settings to admins ([9d3a74b](https://github.com/usememos/memos/commit/9d3a74bcccf934aa2fa95ee240b56cc3b3a25776))
* **api:** reduce memory pressure in backend paths ([c456637](https://github.com/usememos/memos/commit/c45663761d148e94d3e1b30f4810922e7c2571ab))
* **api:** remove public activity service ([#5734](https://github.com/usememos/memos/issues/5734)) ([04f239a](https://github.com/usememos/memos/commit/04f239a2fc74f7090c779a6a7b8a08238fd31b88))
* **api:** restrict user email exposure to self and admins ([#5784](https://github.com/usememos/memos/issues/5784)) ([a24d420](https://github.com/usememos/memos/commit/a24d4209222814e4a8bedfc0392e91462bc855ad))
* **api:** switch user resource names to usernames ([#5779](https://github.com/usememos/memos/issues/5779)) ([acddef1](https://github.com/usememos/memos/commit/acddef1f3dcca44806bcbb85e9dc5cae7daa5285))
* **api:** tolerate missing related users in memo conversions ([#5809](https://github.com/usememos/memos/issues/5809)) ([25feef3](https://github.com/usememos/memos/commit/25feef3aadd34bfd474d7e3b685815a6509bc4c6))
* **auth:** recover session via refresh cookie when localStorage is empty ([#5748](https://github.com/usememos/memos/issues/5748)) ([551ee1d](https://github.com/usememos/memos/commit/551ee1d81f398abdcaf73a0c2b782c8379b0e3f2))
* backend tests action ([065e817](https://github.com/usememos/memos/commit/065e817470b1d3b6b00222525791b85d825c1492))
* clear content search filter when selecting shortcut ([#5499](https://github.com/usememos/memos/issues/5499)) ([2c3f9e3](https://github.com/usememos/memos/commit/2c3f9e3bfbe09e5d0028d1525c1df83c03f547c9))
* correct typos in comments, error messages, and identifiers ([#5704](https://github.com/usememos/memos/issues/5704)) ([8f43e80](https://github.com/usememos/memos/commit/8f43e8075b62706f99da4005ab04b165b35215f6))
* detect legacy installations with empty schema version ([9628d3d](https://github.com/usememos/memos/commit/9628d3de21289e887ffeb6cc4b6710913a0de44e))
* **editor:** show newly linked memos when editing a memo with attachments ([026ea92](https://github.com/usememos/memos/commit/026ea92f7b4005c30ca84340c22018740659ab51))
* ensure comment divs span full width in MemoDetail ([ce44164](https://github.com/usememos/memos/commit/ce441644af34ffff156f1793c40011c2b82e8d5f))
* **fileserver:** render SVG attachment previews ([40fd700](https://github.com/usememos/memos/commit/40fd700fb8be27a8d7a300a2636cf4f366572176))
* **filter:** enforce CEL syntax semantics ([0e89407](https://github.com/usememos/memos/commit/0e89407ee91deda87e0df7464a89d26d1e9a88b3))
* **frontend:** restore sitemap and robots routes ([fee7fcd](https://github.com/usememos/memos/commit/fee7fcd6608b9d07da1f146c33c9bb8f898f708f))
* handle chunk load errors after redeployment with auto-reload ([#5703](https://github.com/usememos/memos/issues/5703)) ([bdd3554](https://github.com/usememos/memos/commit/bdd3554b897246bac5c1e6fd801495c24b6a656e))
* harden memo content iframe and HTML sanitization ([7e21b72](https://github.com/usememos/memos/commit/7e21b728b346e80023c93e8986130f83e70584f9))
* hide transcribe button without AI provider ([ab53329](https://github.com/usememos/memos/commit/ab5332901fd6626f0a2ae6b99671af9663f68078))
* improve image preview dialog and live photo trigger ([aafcc21](https://github.com/usememos/memos/commit/aafcc21ae6f96a313fb372365dd1af8a1a69d1ba))
* improve installer compatibility and docs ([f90d9a4](https://github.com/usememos/memos/commit/f90d9a49a78d0764a6c5cf8f6720e69ea1164b25))
* improve KaTeX and Mermaid error handling and overflow ([6b37fcc](https://github.com/usememos/memos/commit/6b37fcc01b5dcded6a2ec254fbaf895f7812d072))
* include plain URLs and tags in memo snippet generation ([#5688](https://github.com/usememos/memos/issues/5688)) ([3d4f793](https://github.com/usememos/memos/commit/3d4f793f97b567bda823a60b7fe10e09e14499ce))
* **lint:** correct goimports struct literal alignment after removing write-only credential fields ([#5794](https://github.com/usememos/memos/issues/5794)) ([9610ed8](https://github.com/usememos/memos/commit/9610ed8fc809b3e7aa4b93e4909634957fa94cf7))
* **map:** align dark mode map styling ([7ac9989](https://github.com/usememos/memos/commit/7ac9989d43f3967b466f340da3841290d86b20f1))
* **map:** refine Leaflet controls and memo map styling ([894b3eb](https://github.com/usememos/memos/commit/894b3eb045c7d2c2acce847c34a85295c909dcf7))
* **markdown:** support height/width attributes on img elements ([737acbb](https://github.com/usememos/memos/commit/737acbba2f5e3dd911da3a77d2d5d1cde1bf8ba1))
* **memo-editor:** scope Cmd+Enter save to the active editor ([#5745](https://github.com/usememos/memos/issues/5745)) ([05810e7](https://github.com/usememos/memos/commit/05810e7882cb03d448d9d8fa84bc6ca54eafbed0))
* **mysql:** handle CreateMemo custom timestamps with FROM_UNIXTIME ([#5673](https://github.com/usememos/memos/issues/5673)) ([09d73e8](https://github.com/usememos/memos/commit/09d73e8b6e16c43a61767817909a472916c83daa))
* normalize attachment MIME types before validation ([c3e7e2c](https://github.com/usememos/memos/commit/c3e7e2c316d01bf857931c38303efc87307f2a19))
* preserve draft content when tab is suspended or editor remounts ([9ca7122](https://github.com/usememos/memos/commit/9ca71229a6c0dfad44b76ed06fced46c5bef49c7))
* prevent local attachment uploads from overwriting files ([4add9b0](https://github.com/usememos/memos/commit/4add9b04ad5d0b7608c985281f5975dc39f9a572))
* prevent stale comment drafts from being restored ([e520b63](https://github.com/usememos/memos/commit/e520b637fd8d0f6331674003abe72f9dfbae8231))
* remove duplicate Japanese locale keys ([efeb28c](https://github.com/usememos/memos/commit/efeb28c872a2bd6edd28fa3b68bd0b15af923d50))
* render audio attachments as inline players ([#5699](https://github.com/usememos/memos/issues/5699)) ([2ccb98a](https://github.com/usememos/memos/commit/2ccb98a6cbc40544e81eeeca2a2cbbaf8348f45e))
* restrict archived memo access to creator only ([#5707](https://github.com/usememos/memos/issues/5707)) ([f4154d0](https://github.com/usememos/memos/commit/f4154d090be3896c8e0dd83440f24953bbeb308c))
* **routing:** redirect unauthenticated users to /explore when public visibility is allowed ([98859eb](https://github.com/usememos/memos/commit/98859eb5e5065a7c12ada983b7c38c5af5035bb6))
* **server:** close SSE clients during shutdown ([a5ddd5a](https://github.com/usememos/memos/commit/a5ddd5adafef282f00b23e00e145119d4316f24f))
* sync html lang attribute with active locale ([#5753](https://github.com/usememos/memos/issues/5753)) ([be00abe](https://github.com/usememos/memos/commit/be00abe852479820b7c574e15e276d70961ab7bd))
* tag parsing truncates emojis with variation selectors ([#5496](https://github.com/usememos/memos/issues/5496)) ([3ea6ea3](https://github.com/usememos/memos/commit/3ea6ea3108f58dc34f39fa6f21d761bd2e97732b))
* **tags:** allow blur-only tag metadata ([#5800](https://github.com/usememos/memos/issues/5800)) ([1921b57](https://github.com/usememos/memos/commit/1921b57662c2129d179930f71e5c42caf9070a19))
* toggle focus mode do not reset editor height ([#5504](https://github.com/usememos/memos/issues/5504)) ([0729779](https://github.com/usememos/memos/commit/0729779e0427c68bdbc5b6b711a5683f66ba9bbc))
* **ui:** show comment editor above the comment list ([#5662](https://github.com/usememos/memos/issues/5662)) ([6b0736b](https://github.com/usememos/memos/commit/6b0736b29325ff7698b7395dc761f2ca41e6521c))
* **ui:** unify metadata component styles across MemoView and MemoEditor ([664b8c5](https://github.com/usememos/memos/commit/664b8c56290026ba2beb7b75db24c684824b8670))
* unify live photo previews around LIVE badge playback ([6b0487d](https://github.com/usememos/memos/commit/6b0487dcd857ba72189ca0624cb4985961f08f25))
* **webhooks:** trigger memo updates for attachment and relation changes ([#5795](https://github.com/usememos/memos/issues/5795)) ([acbc914](https://github.com/usememos/memos/commit/acbc914dea8d4e533028b03929193a4af1ac32b4))
* **web:** prevent MemoContent prop leaks ([22519b5](https://github.com/usememos/memos/commit/22519b57a0a971ab927a03015c994c63b8c3f1da))
* **web:** refine attachment media layout ([a0d83e1](https://github.com/usememos/memos/commit/a0d83e1a9e9d0ba50a0103e594adb011728faf8c))
* **web:** refresh memo detail cache after editor save ([333c9df](https://github.com/usememos/memos/commit/333c9df233240a843a9e62d17c6ff464690636f8))
* **web:** use BroadcastChannel to sync token refreshes across tabs ([bbdc998](https://github.com/usememos/memos/commit/bbdc998646e8093223a448378a2c29690f0d8612))
### Performance Improvements
* batch load memo relations when listing memos ([#5692](https://github.com/usememos/memos/issues/5692)) ([1e82714](https://github.com/usememos/memos/commit/1e82714a52c72455a6ba02605cc641d7ad4fbf1a))
+1 -1
View File
@@ -1,2 +1,2 @@
# These owners will be the default owners for everything in the repo.
* @boojack
* @usememos/moderators
-38
View File
@@ -1,38 +0,0 @@
# Build frontend dist.
FROM node:18.12.1-alpine3.16 AS frontend
WORKDIR /frontend-build
COPY ./web/package.json ./web/pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm i --frozen-lockfile
COPY ./web/ .
RUN pnpm build
# Build backend exec file.
FROM golang:1.19.3-alpine3.16 AS backend
WORKDIR /backend-build
RUN apk update && apk add --no-cache gcc musl-dev
COPY . .
COPY --from=frontend /frontend-build/dist ./server/dist
RUN go build -o memos ./main.go
# Make workspace with above generated files.
FROM alpine:3.16 AS monolithic
WORKDIR /usr/local/memos
RUN apk add --no-cache tzdata
ENV TZ="UTC"
COPY --from=backend /backend-build/memos /usr/local/memos/
EXPOSE 5230
# Directory to store the data, which can be referenced as the mounting point.
RUN mkdir -p /var/opt/memos
ENTRYPOINT ["./memos", "--mode", "prod", "--port", "5230"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Memos
Copyright (c) 2025 Memos
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+97 -42
View File
@@ -1,62 +1,117 @@
# memos
<div align="center">
<p><b>Featured Sponsors</b></p>
<table>
<tr>
<td align="center" width="50%">
<a href="https://go.warp.dev/memos" target="_blank" rel="noopener">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/warpdotdev/brand-assets/refs/heads/main/Logos/Warp-Wordmark-White.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/warpdotdev/brand-assets/refs/heads/main/Logos/Warp-Wordmark-Black.png" />
<img alt="Warp" height="44" src="https://raw.githubusercontent.com/warpdotdev/brand-assets/refs/heads/main/Logos/Warp-Wordmark-Black.png" />
</picture>
<br/>
<span>Warp is an agentic development environment.</span>
</a>
</td>
<td align="center" width="50%">
<a href="https://coderabbit.link/usememos" target="_blank" rel="noopener">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://victorious-bubble-f69a016683.media.strapiapp.com/White_Typemark_79b9189d19.svg" />
<source media="(prefers-color-scheme: light)" srcset="https://victorious-bubble-f69a016683.media.strapiapp.com/Orange_Typemark_43bf516c9d.svg" />
<img alt="CodeRabbit" height="44" src="https://victorious-bubble-f69a016683.media.strapiapp.com/Orange_Typemark_43bf516c9d.svg" />
</picture>
<br/>
<span>Cut code review time &amp; bugs in half, instantly.</span>
</a>
</td>
</tr>
</table>
</div>
<img height="72px" src="https://usememos.com/logo.webp" alt="✍️ memos" align="right" />
# Memos
A lightweight, self-hosted memo hub. Open Source and Free forever.
<img align="right" height="96px" src="https://raw.githubusercontent.com/usememos/.github/refs/heads/main/assets/logo-rounded.png" alt="Memos" />
<a href="https://demo.usememos.com/">Live Demo</a> •
Discuss in <a href="https://t.me/+-_tNF1k70UU4ZTc9">Telegram</a> / <a href="https://discord.gg/tfPJa4UmAv">Discord</a>
Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours.
<p>
<a href="https://github.com/usememos/memos/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/usememos/memos" /></a>
<a href="https://discord.gg/tfPJa4UmAv"><img alt="Discord" src="https://img.shields.io/badge/discord-chat-5865f2?logo=discord&logoColor=f5f5f5" /></a>
</p>
[![Home](https://img.shields.io/badge/🏠-usememos.com-blue?style=flat-square)](https://usememos.com)
[![Live Demo](https://img.shields.io/badge/✨-Try%20Demo-orange?style=flat-square)](https://demo.usememos.com/)
[![Docs](https://img.shields.io/badge/📚-Documentation-green?style=flat-square)](https://usememos.com/docs)
[![Discord](https://img.shields.io/badge/💬-Discord-5865f2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/tfPJa4UmAv)
[![Docker Pulls](https://img.shields.io/docker/pulls/neosmemo/memos?style=flat-square&logo=docker)](https://hub.docker.com/r/neosmemo/memos)
![demo](https://usememos.com/demo.webp)
<img src="https://raw.githubusercontent.com/usememos/.github/refs/heads/main/assets/demo.png" alt="Memos Demo Screenshot" height="512" />
## Key points
## Features
- Open source and free forever
- Self-hosting with Docker in seconds
- Markdown support
- Customizable and sharable
- RESTful API for self-service
- **Instant Capture** — Timeline-first UI. Open, write, done — no folders to navigate.
- **Total Data Ownership** — Self-hosted on your infrastructure. Notes stored in Markdown, always portable. Zero telemetry.
- **Radical Simplicity** — Single Go binary, ~20MB Docker image. One command to deploy with SQLite, MySQL, or PostgreSQL.
- **Open & Extensible** — MIT-licensed with full REST and gRPC APIs for integration.
## Deploy with Docker in seconds
## Quick Start
### Docker (Recommended)
```bash
docker run -d --name memos -p 5230:5230 -v ~/.memos/:/var/opt/memos ghcr.io/usememos/memos:latest
docker run -d \
--name memos \
-p 5230:5230 \
-v ~/.memos:/var/opt/memos \
neosmemo/memos:stable
```
> The `~/.memos/` directory will be used as the data directory on your local machine, while `/var/opt/memos` is the directory of the volume in Docker and should not be modified.
Open `http://localhost:5230` and start writing!
Learn more about [other installation methods](https://usememos.com/docs/install).
### Native Binary
## Contribution
```bash
curl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh
```
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. We greatly appreciate any contributions you make. Thank you for being a part of our community! 🥰
### Try the Live Demo
<a href="https://github.com/usememos/memos/graphs/contributors">
<img src="https://contrib.rocks/image?repo=usememos/memos" />
</a>
Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first!
### Other Installation Methods
- **Docker Compose** - Recommended for production deployments
- **Pre-built Binaries** - Available for Linux, macOS, and Windows
- **Kubernetes** - Helm charts and manifests available
- **Build from Source** - For development and customization
See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions.
## Contributing
Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations.
- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md)
- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md)
- [Submit pull requests](https://github.com/usememos/memos/pulls)
- [Improve documentation](https://github.com/usememos/dotcom)
- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales)
## Sponsors
* [**CodeRabbit** - Cut code review time & bugs in half, instantly](https://coderabbit.link/usememos)
* [**Warp** - The agentic development environment](https://go.warp.dev/memos)
* [**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor)
* [**InstaPods** - Get your app online in seconds](https://instapods.com/?utm_source=memos&utm_medium=sponsor) • [Deploy Memos in 30 Seconds](https://instapods.com/apps/memos/?utm_source=memos&utm_medium=sponsor)
Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing!
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=usememos/memos&type=Date)](https://star-history.com/#usememos/memos&Date)
## License
Memos is open-source software licensed under the [MIT License](LICENSE). See our [Privacy Policy](https://usememos.com/privacy) for details on data handling.
---
- [Moe Memos](https://memos.moe/) - Third party client for iOS and Android
- [lmm214/memos-bber](https://github.com/lmm214/memos-bber) - Chrome extension
- [Rabithua/memos_wmp](https://github.com/Rabithua/memos_wmp) - WeChat MiniProgram
- [qazxcdswe123/telegramMemoBot](https://github.com/qazxcdswe123/telegramMemoBot) - Telegram bot
- [eallion/memos.top](https://github.com/eallion/memos.top) - Static page rendered with the Memos API
- [eindex/logseq-memos-sync](https://github.com/EINDEX/logseq-memos-sync) - Logseq plugin
- [JakeLaoyu/memos-import-from-flomo](https://github.com/JakeLaoyu/memos-import-from-flomo) - Import data. Support from flomo, wechat reading
- [Send to memos](https://sharecuts.cn/shortcut/12640) - A shortcut for iOS
- [Memos Raycast Extension](https://www.raycast.com/JakeYu/memos) - Raycast extension
- [Memos Desktop](https://github.com/xudaolong/memos-desktop) - Third party client for MacOS and Windows
**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)**
## Acknowledgements
- Thanks [Uffizzi](https://www.uffizzi.com/) for sponsoring preview environments for PRs.
## Star history
[![Star History Chart](https://api.star-history.com/svg?repos=usememos/memos&type=Date)](https://star-history.com/#usememos/memos&Date)
<a href="https://vercel.com/oss">
<img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge.svg" />
</a>
+37 -3
View File
@@ -1,7 +1,41 @@
# Security Policy
## Reporting a bug
## Supported Versions
Report security bugs via GitHub [issues](https://github.com/usememos/memos/issues).
Memos is currently a `0.x` project. Security fixes are only provided for the latest release. Older releases are not supported for security updates, and fixes are not backported.
For more information, please contact [stevenlgtm@gmail.com](stevenlgtm@gmail.com).
If you run Memos in production, keep your instance updated to the latest release.
## Reporting a Vulnerability
Please report security issues privately by email: `dev@usememos.com`
Do not open public GitHub issues, discussions, or pull requests for suspected vulnerabilities.
Please include:
- A clear description of the issue
- Steps to reproduce
- Affected version or commit
- Deployment details that matter to reproduction
- Your assessment of impact
We will review reports as time permits and fix valid issues in regular releases.
## Disclosure and CVEs
Memos is self-hosted software and is still in the `0.x` stage. At this stage, we do not run a formal disclosure program, publish separate security advisories for every issue, or request CVE IDs.
Security fixes may be shipped directly in normal releases or noted briefly in release notes and changelogs.
## Self-Hosted Deployment Notes
The security posture of a Memos instance depends heavily on how it is deployed and operated. In particular:
- Keep Memos updated
- Put it behind a properly configured reverse proxy when exposed to the internet
- Require authentication for any non-public deployment
- Use TLS in production
- Limit access to trusted users and administrators
Reports that depend entirely on intentionally unsafe deployment choices, unsupported local patches, or administrator actions may be treated as deployment issues rather than product vulnerabilities.
-137
View File
@@ -1,137 +0,0 @@
package api
import "github.com/usememos/memos/server/profile"
// ActivityType is the type for an activity.
type ActivityType string
const (
// User related.
// ActivityUserCreate is the type for creating users.
ActivityUserCreate ActivityType = "user.create"
// ActivityUserUpdate is the type for updating users.
ActivityUserUpdate ActivityType = "user.update"
// ActivityUserDelete is the type for deleting users.
ActivityUserDelete ActivityType = "user.delete"
// ActivityUserAuthSignIn is the type for user signin.
ActivityUserAuthSignIn ActivityType = "user.auth.signin"
// ActivityUserAuthSignUp is the type for user signup.
ActivityUserAuthSignUp ActivityType = "user.auth.signup"
// ActivityUserSettingUpdate is the type for updating user settings.
ActivityUserSettingUpdate ActivityType = "user.setting.update"
// Memo related.
// ActivityMemoCreate is the type for creating memos.
ActivityMemoCreate ActivityType = "memo.create"
// ActivityMemoUpdate is the type for updating memos.
ActivityMemoUpdate ActivityType = "memo.update"
// ActivityMemoDelete is the type for deleting memos.
ActivityMemoDelete ActivityType = "memo.delete"
// Shortcut related.
// ActivityShortcutCreate is the type for creating shortcuts.
ActivityShortcutCreate ActivityType = "shortcut.create"
// ActivityShortcutUpdate is the type for updating shortcuts.
ActivityShortcutUpdate ActivityType = "shortcut.update"
// ActivityShortcutDelete is the type for deleting shortcuts.
ActivityShortcutDelete ActivityType = "shortcut.delete"
// Resource related.
// ActivityResourceCreate is the type for creating resources.
ActivityResourceCreate ActivityType = "resource.create"
// ActivityResourceDelete is the type for deleting resources.
ActivityResourceDelete ActivityType = "resource.delete"
// Tag related.
// ActivityTagCreate is the type for creating tags.
ActivityTagCreate ActivityType = "tag.create"
// ActivityTagDelete is the type for deleting tags.
ActivityTagDelete ActivityType = "tag.delete"
// Server related.
// ActivityServerStart is the type for starting server.
ActivityServerStart ActivityType = "server.start"
)
// ActivityLevel is the level of activities.
type ActivityLevel string
const (
// ActivityInfo is the INFO level of activities.
ActivityInfo ActivityLevel = "INFO"
// ActivityWarn is the WARN level of activities.
ActivityWarn ActivityLevel = "WARN"
// ActivityError is the ERROR level of activities.
ActivityError ActivityLevel = "ERROR"
)
type ActivityUserCreatePayload struct {
UserID int `json:"userId"`
Username string `json:"username"`
Role Role `json:"role"`
}
type ActivityUserAuthSignInPayload struct {
UserID int `json:"userId"`
IP string `json:"ip"`
}
type ActivityUserAuthSignUpPayload struct {
Username string `json:"username"`
IP string `json:"ip"`
}
type ActivityMemoCreatePayload struct {
Content string `json:"content"`
Visibility string `json:"visibility"`
}
type ActivityShortcutCreatePayload struct {
Title string `json:"title"`
Payload string `json:"payload"`
}
type ActivityResourceCreatePayload struct {
Filename string `json:"filename"`
Type string `json:"type"`
Size int64 `json:"size"`
}
type ActivityTagCreatePayload struct {
TagName string `json:"tagName"`
}
type ActivityServerStartPayload struct {
ServerID string `json:"serverId"`
Profile *profile.Profile `json:"profile"`
}
type Activity struct {
ID int `json:"id"`
// Standard fields
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
// Domain specific fields
Type ActivityType `json:"type"`
Level ActivityLevel `json:"level"`
Payload string `json:"payload"`
}
// ActivityCreate is the API message for creating an activity.
type ActivityCreate struct {
// Standard fields
CreatorID int
// Domain specific fields
Type ActivityType `json:"type"`
Level ActivityLevel
Payload string `json:"payload"`
}
-17
View File
@@ -1,17 +0,0 @@
package api
type SignIn struct {
Username string `json:"username"`
Password string `json:"password"`
}
type SSOSignIn struct {
IdentityProviderID int `json:"identityProviderId"`
Code string `json:"code"`
RedirectURI string `json:"redirectUri"`
}
type SignUp struct {
Username string `json:"username"`
Password string `json:"password"`
}
-24
View File
@@ -1,24 +0,0 @@
package api
// UnknownID is the ID for unknowns.
const UnknownID = -1
// RowStatus is the status for a row.
type RowStatus string
const (
// Normal is the status for a normal row.
Normal RowStatus = "NORMAL"
// Archived is the status for an archived row.
Archived RowStatus = "ARCHIVED"
)
func (e RowStatus) String() string {
switch e {
case Normal:
return "NORMAL"
case Archived:
return "ARCHIVED"
}
return ""
}
-58
View File
@@ -1,58 +0,0 @@
package api
type IdentityProviderType string
const (
IdentityProviderOAuth2 IdentityProviderType = "OAUTH2"
)
type IdentityProviderConfig struct {
OAuth2Config *IdentityProviderOAuth2Config `json:"oauth2Config"`
}
type IdentityProviderOAuth2Config struct {
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
AuthURL string `json:"authUrl"`
TokenURL string `json:"tokenUrl"`
UserInfoURL string `json:"userInfoUrl"`
Scopes []string `json:"scopes"`
FieldMapping *FieldMapping `json:"fieldMapping"`
}
type FieldMapping struct {
Identifier string `json:"identifier"`
DisplayName string `json:"displayName"`
Email string `json:"email"`
}
type IdentityProvider struct {
ID int `json:"id"`
Name string `json:"name"`
Type IdentityProviderType `json:"type"`
IdentifierFilter string `json:"identifierFilter"`
Config *IdentityProviderConfig `json:"config"`
}
type IdentityProviderCreate struct {
Name string `json:"name"`
Type IdentityProviderType `json:"type"`
IdentifierFilter string `json:"identifierFilter"`
Config *IdentityProviderConfig `json:"config"`
}
type IdentityProviderFind struct {
ID *int
}
type IdentityProviderPatch struct {
ID int
Type IdentityProviderType `json:"type"`
Name *string `json:"name"`
IdentifierFilter *string `json:"identifierFilter"`
Config *IdentityProviderConfig `json:"config"`
}
type IdentityProviderDelete struct {
ID int
}
-97
View File
@@ -1,97 +0,0 @@
package api
// MaxContentLength means the max memo content bytes is 1MB.
const MaxContentLength = 1 << 30
// Visibility is the type of a visibility.
type Visibility string
const (
// Public is the PUBLIC visibility.
Public Visibility = "PUBLIC"
// Protected is the PROTECTED visibility.
Protected Visibility = "PROTECTED"
// Private is the PRIVATE visibility.
Private Visibility = "PRIVATE"
)
func (e Visibility) String() string {
switch e {
case Public:
return "PUBLIC"
case Protected:
return "PROTECTED"
case Private:
return "PRIVATE"
}
return "PRIVATE"
}
type Memo struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Content string `json:"content"`
Visibility Visibility `json:"visibility"`
Pinned bool `json:"pinned"`
// Related fields
CreatorName string `json:"creatorName"`
ResourceList []*Resource `json:"resourceList"`
}
type MemoCreate struct {
// Standard fields
CreatorID int `json:"-"`
CreatedTs *int64 `json:"createdTs"`
// Domain specific fields
Visibility Visibility `json:"visibility"`
Content string `json:"content"`
// Related fields
ResourceIDList []int `json:"resourceIdList"`
}
type MemoPatch struct {
ID int `json:"-"`
// Standard fields
CreatedTs *int64 `json:"createdTs"`
UpdatedTs *int64
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Content *string `json:"content"`
Visibility *Visibility `json:"visibility"`
// Related fields
ResourceIDList []int `json:"resourceIdList"`
}
type MemoFind struct {
ID *int
// Standard fields
RowStatus *RowStatus
CreatorID *int
// Domain specific fields
Pinned *bool
ContentSearch *string
VisibilityList []Visibility
// Pagination
Limit *int
Offset *int
}
type MemoDelete struct {
ID int
}
-26
View File
@@ -1,26 +0,0 @@
package api
type MemoOrganizer struct {
ID int
// Domain specific fields
MemoID int
UserID int
Pinned bool
}
type MemoOrganizerUpsert struct {
MemoID int `json:"-"`
UserID int `json:"-"`
Pinned bool `json:"pinned"`
}
type MemoOrganizerFind struct {
MemoID int
UserID int
}
type MemoOrganizerDelete struct {
MemoID *int
UserID *int
}
-24
View File
@@ -1,24 +0,0 @@
package api
type MemoResource struct {
MemoID int
ResourceID int
CreatedTs int64
UpdatedTs int64
}
type MemoResourceUpsert struct {
MemoID int `json:"-"`
ResourceID int
UpdatedTs *int64
}
type MemoResourceFind struct {
MemoID *int
ResourceID *int
}
type MemoResourceDelete struct {
MemoID *int
ResourceID *int
}
-69
View File
@@ -1,69 +0,0 @@
package api
type Resource struct {
ID int `json:"id"`
// Standard fields
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Filename string `json:"filename"`
Blob []byte `json:"-"`
InternalPath string `json:"internalPath"`
ExternalLink string `json:"externalLink"`
Type string `json:"type"`
Size int64 `json:"size"`
PublicID string `json:"publicId"`
// Related fields
LinkedMemoAmount int `json:"linkedMemoAmount"`
}
type ResourceCreate struct {
// Standard fields
CreatorID int `json:"-"`
// Domain specific fields
Filename string `json:"filename"`
Blob []byte `json:"-"`
InternalPath string `json:"internalPath"`
ExternalLink string `json:"externalLink"`
Type string `json:"type"`
Size int64 `json:"-"`
PublicID string `json:"publicId"`
}
type ResourceFind struct {
ID *int `json:"id"`
// Standard fields
CreatorID *int `json:"creatorId"`
// Domain specific fields
Filename *string `json:"filename"`
MemoID *int
PublicID *string `json:"publicId"`
GetBlob bool
// Pagination
Limit *int
Offset *int
}
type ResourcePatch struct {
ID int `json:"-"`
// Standard fields
UpdatedTs *int64
// Domain specific fields
Filename *string `json:"filename"`
ResetPublicID *bool `json:"resetPublicId"`
PublicID *string `json:"-"`
}
type ResourceDelete struct {
ID int
}
-53
View File
@@ -1,53 +0,0 @@
package api
type Shortcut struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Title string `json:"title"`
Payload string `json:"payload"`
}
type ShortcutCreate struct {
// Standard fields
CreatorID int `json:"-"`
// Domain specific fields
Title string `json:"title"`
Payload string `json:"payload"`
}
type ShortcutPatch struct {
ID int `json:"-"`
// Standard fields
UpdatedTs *int64
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Title *string `json:"title"`
Payload *string `json:"payload"`
}
type ShortcutFind struct {
ID *int
// Standard fields
CreatorID *int
// Domain specific fields
Title *string `json:"title"`
}
type ShortcutDelete struct {
ID *int
// Standard fields
CreatorID *int
}
-57
View File
@@ -1,57 +0,0 @@
package api
const (
// LocalStorage means the storage service is local file system.
LocalStorage = -1
// DatabaseStorage means the storage service is database.
DatabaseStorage = 0
)
type StorageType string
const (
StorageS3 StorageType = "S3"
)
type StorageConfig struct {
S3Config *StorageS3Config `json:"s3Config"`
}
type StorageS3Config struct {
EndPoint string `json:"endPoint"`
Path string `json:"path"`
Region string `json:"region"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
URLPrefix string `json:"urlPrefix"`
URLSuffix string `json:"urlSuffix"`
}
type Storage struct {
ID int `json:"id"`
Name string `json:"name"`
Type StorageType `json:"type"`
Config *StorageConfig `json:"config"`
}
type StorageCreate struct {
Name string `json:"name"`
Type StorageType `json:"type"`
Config *StorageConfig `json:"config"`
}
type StoragePatch struct {
ID int `json:"id"`
Type StorageType `json:"type"`
Name *string `json:"name"`
Config *StorageConfig `json:"config"`
}
type StorageFind struct {
ID *int `json:"id"`
}
type StorageDelete struct {
ID int `json:"id"`
}
-27
View File
@@ -1,27 +0,0 @@
package api
import "github.com/usememos/memos/server/profile"
type SystemStatus struct {
Host *User `json:"host"`
Profile profile.Profile `json:"profile"`
DBSize int64 `json:"dbSize"`
// System settings
// Allow sign up.
AllowSignUp bool `json:"allowSignUp"`
// Ignore upgrade
IgnoreUpgrade bool `json:"ignoreUpgrade"`
// Disable public memos.
DisablePublicMemos bool `json:"disablePublicMemos"`
// Additional style.
AdditionalStyle string `json:"additionalStyle"`
// Additional script.
AdditionalScript string `json:"additionalScript"`
// Customized server profile, including server name and external url.
CustomizedProfile CustomizedProfile `json:"customizedProfile"`
// Storage service ID.
StorageServiceID int `json:"storageServiceId"`
// Local storage path
LocalStoragePath string `json:"localStoragePath"`
}
-180
View File
@@ -1,180 +0,0 @@
package api
import (
"encoding/json"
"errors"
"fmt"
"golang.org/x/exp/slices"
)
type SystemSettingName string
const (
// SystemSettingServerIDName is the name of server id.
SystemSettingServerIDName SystemSettingName = "server-id"
// SystemSettingSecretSessionName is the name of secret session.
SystemSettingSecretSessionName SystemSettingName = "secret-session"
// SystemSettingAllowSignUpName is the name of allow signup setting.
SystemSettingAllowSignUpName SystemSettingName = "allow-signup"
// SystemSettingIgnoreUpgradeName is the name of ignore upgrade.
SystemSettingIgnoreUpgradeName SystemSettingName = "ignore-upgrade"
// SystemSettingDisablePublicMemosName is the name of disable public memos setting.
SystemSettingDisablePublicMemosName SystemSettingName = "disable-public-memos"
// SystemSettingAdditionalStyleName is the name of additional style.
SystemSettingAdditionalStyleName SystemSettingName = "additional-style"
// SystemSettingAdditionalScriptName is the name of additional script.
SystemSettingAdditionalScriptName SystemSettingName = "additional-script"
// SystemSettingCustomizedProfileName is the name of customized server profile.
SystemSettingCustomizedProfileName SystemSettingName = "customized-profile"
// SystemSettingStorageServiceIDName is the name of storage service ID.
SystemSettingStorageServiceIDName SystemSettingName = "storage-service-id"
// SystemSettingLocalStoragePathName is the name of local storage path.
SystemSettingLocalStoragePathName SystemSettingName = "local-storage-path"
// SystemSettingOpenAIConfigName is the name of OpenAI config.
SystemSettingOpenAIConfigName SystemSettingName = "openai-config"
)
// CustomizedProfile is the struct definition for SystemSettingCustomizedProfileName system setting item.
type CustomizedProfile struct {
// Name is the server name, default is `memos`
Name string `json:"name"`
// LogoURL is the url of logo image.
LogoURL string `json:"logoUrl"`
// Description is the server description.
Description string `json:"description"`
// Locale is the server default locale.
Locale string `json:"locale"`
// Appearance is the server default appearance.
Appearance string `json:"appearance"`
// ExternalURL is the external url of server. e.g. https://usermemos.com
ExternalURL string `json:"externalUrl"`
}
type OpenAIConfig struct {
Key string `json:"key"`
Host string `json:"host"`
}
func (key SystemSettingName) String() string {
switch key {
case SystemSettingServerIDName:
return "server-id"
case SystemSettingSecretSessionName:
return "secret-session"
case SystemSettingAllowSignUpName:
return "allow-signup"
case SystemSettingIgnoreUpgradeName:
return "ignore-upgrade"
case SystemSettingDisablePublicMemosName:
return "disable-public-memos"
case SystemSettingAdditionalStyleName:
return "additional-style"
case SystemSettingAdditionalScriptName:
return "additional-script"
case SystemSettingCustomizedProfileName:
return "customized-profile"
case SystemSettingStorageServiceIDName:
return "storage-service-id"
case SystemSettingLocalStoragePathName:
return "local-storage-path"
case SystemSettingOpenAIConfigName:
return "openai-config"
}
return ""
}
type SystemSetting struct {
Name SystemSettingName `json:"name"`
// Value is a JSON string with basic value.
Value string `json:"value"`
Description string `json:"description"`
}
type SystemSettingUpsert struct {
Name SystemSettingName `json:"name"`
Value string `json:"value"`
Description string `json:"description"`
}
func (upsert SystemSettingUpsert) Validate() error {
if upsert.Name == SystemSettingServerIDName {
return errors.New("update server id is not allowed")
} else if upsert.Name == SystemSettingAllowSignUpName {
value := false
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting allow signup value")
}
} else if upsert.Name == SystemSettingIgnoreUpgradeName {
value := false
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting ignore upgrade value")
}
} else if upsert.Name == SystemSettingDisablePublicMemosName {
value := false
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting disable public memos value")
}
} else if upsert.Name == SystemSettingAdditionalStyleName {
value := ""
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting additional style value")
}
} else if upsert.Name == SystemSettingAdditionalScriptName {
value := ""
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting additional script value")
}
} else if upsert.Name == SystemSettingCustomizedProfileName {
customizedProfile := CustomizedProfile{
Name: "memos",
LogoURL: "",
Description: "",
Locale: "en",
Appearance: "system",
ExternalURL: "",
}
err := json.Unmarshal([]byte(upsert.Value), &customizedProfile)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting customized profile value")
}
if !slices.Contains(UserSettingLocaleValue, customizedProfile.Locale) {
return fmt.Errorf("invalid locale value")
}
if !slices.Contains(UserSettingAppearanceValue, customizedProfile.Appearance) {
return fmt.Errorf("invalid appearance value")
}
} else if upsert.Name == SystemSettingStorageServiceIDName {
value := DatabaseStorage
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting storage service id value")
}
return nil
} else if upsert.Name == SystemSettingLocalStoragePathName {
value := ""
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting local storage path value")
}
} else if upsert.Name == SystemSettingOpenAIConfigName {
value := OpenAIConfig{}
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal system setting openai api config value")
}
} else {
return fmt.Errorf("invalid system setting name")
}
return nil
}
type SystemSettingFind struct {
Name SystemSettingName `json:"name"`
}
-20
View File
@@ -1,20 +0,0 @@
package api
type Tag struct {
Name string
CreatorID int
}
type TagUpsert struct {
Name string
CreatorID int `json:"-"`
}
type TagFind struct {
CreatorID int
}
type TagDelete struct {
Name string `json:"name"`
CreatorID int
}
-158
View File
@@ -1,158 +0,0 @@
package api
import (
"fmt"
"github.com/usememos/memos/common"
)
// Role is the type of a role.
type Role string
const (
// Host is the HOST role.
Host Role = "HOST"
// Admin is the ADMIN role.
Admin Role = "ADMIN"
// NormalUser is the USER role.
NormalUser Role = "USER"
)
func (e Role) String() string {
switch e {
case Host:
return "HOST"
case Admin:
return "ADMIN"
case NormalUser:
return "USER"
}
return "USER"
}
type User struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Username string `json:"username"`
Role Role `json:"role"`
Email string `json:"email"`
Nickname string `json:"nickname"`
PasswordHash string `json:"-"`
OpenID string `json:"openId"`
AvatarURL string `json:"avatarUrl"`
UserSettingList []*UserSetting `json:"userSettingList"`
}
type UserCreate struct {
// Domain specific fields
Username string `json:"username"`
Role Role `json:"role"`
Email string `json:"email"`
Nickname string `json:"nickname"`
Password string `json:"password"`
PasswordHash string
OpenID string
}
func (create UserCreate) Validate() error {
if len(create.Username) < 3 {
return fmt.Errorf("username is too short, minimum length is 3")
}
if len(create.Username) > 32 {
return fmt.Errorf("username is too long, maximum length is 32")
}
if len(create.Password) < 3 {
return fmt.Errorf("password is too short, minimum length is 6")
}
if len(create.Password) > 512 {
return fmt.Errorf("password is too long, maximum length is 512")
}
if len(create.Nickname) > 64 {
return fmt.Errorf("nickname is too long, maximum length is 64")
}
if create.Email != "" {
if len(create.Email) > 256 {
return fmt.Errorf("email is too long, maximum length is 256")
}
if !common.ValidateEmail(create.Email) {
return fmt.Errorf("invalid email format")
}
}
return nil
}
type UserPatch struct {
ID int `json:"-"`
// Standard fields
UpdatedTs *int64
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Username *string `json:"username"`
Email *string `json:"email"`
Nickname *string `json:"nickname"`
Password *string `json:"password"`
ResetOpenID *bool `json:"resetOpenId"`
AvatarURL *string `json:"avatarUrl"`
PasswordHash *string
OpenID *string
}
func (patch UserPatch) Validate() error {
if patch.Username != nil && len(*patch.Username) < 3 {
return fmt.Errorf("username is too short, minimum length is 3")
}
if patch.Username != nil && len(*patch.Username) > 32 {
return fmt.Errorf("username is too long, maximum length is 32")
}
if patch.Password != nil && len(*patch.Password) < 3 {
return fmt.Errorf("password is too short, minimum length is 6")
}
if patch.Password != nil && len(*patch.Password) > 512 {
return fmt.Errorf("password is too long, maximum length is 512")
}
if patch.Nickname != nil && len(*patch.Nickname) > 64 {
return fmt.Errorf("nickname is too long, maximum length is 64")
}
if patch.AvatarURL != nil {
if len(*patch.AvatarURL) > 2<<20 {
return fmt.Errorf("avatar is too large, maximum is 2MB")
}
}
if patch.Email != nil && *patch.Email != "" {
if len(*patch.Email) > 256 {
return fmt.Errorf("email is too long, maximum length is 256")
}
if !common.ValidateEmail(*patch.Email) {
return fmt.Errorf("invalid email format")
}
}
return nil
}
type UserFind struct {
ID *int `json:"id"`
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Username *string `json:"username"`
Role *Role
Email *string `json:"email"`
Nickname *string `json:"nickname"`
OpenID *string
}
type UserDelete struct {
ID int
}
-114
View File
@@ -1,114 +0,0 @@
package api
import (
"encoding/json"
"fmt"
"golang.org/x/exp/slices"
)
type UserSettingKey string
const (
// UserSettingLocaleKey is the key type for user locale.
UserSettingLocaleKey UserSettingKey = "locale"
// UserSettingAppearanceKey is the key type for user appearance.
UserSettingAppearanceKey UserSettingKey = "appearance"
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
UserSettingMemoVisibilityKey UserSettingKey = "memo-visibility"
)
// String returns the string format of UserSettingKey type.
func (key UserSettingKey) String() string {
switch key {
case UserSettingLocaleKey:
return "locale"
case UserSettingAppearanceKey:
return "appearance"
case UserSettingMemoVisibilityKey:
return "memo-visibility"
}
return ""
}
var (
UserSettingLocaleValue = []string{
"de",
"en",
"es",
"fr",
"it",
"ko",
"nl",
"pl",
"pt-BR",
"ru",
"sl",
"sv",
"tr",
"uk",
"vi",
"zh-Hans",
"zh-Hant",
}
UserSettingAppearanceValue = []string{"system", "light", "dark"}
UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public}
)
type UserSetting struct {
UserID int
Key UserSettingKey `json:"key"`
// Value is a JSON string with basic value
Value string `json:"value"`
}
type UserSettingUpsert struct {
UserID int `json:"-"`
Key UserSettingKey `json:"key"`
Value string `json:"value"`
}
func (upsert UserSettingUpsert) Validate() error {
if upsert.Key == UserSettingLocaleKey {
localeValue := "en"
err := json.Unmarshal([]byte(upsert.Value), &localeValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting locale value")
}
if !slices.Contains(UserSettingLocaleValue, localeValue) {
return fmt.Errorf("invalid user setting locale value")
}
} else if upsert.Key == UserSettingAppearanceKey {
appearanceValue := "system"
err := json.Unmarshal([]byte(upsert.Value), &appearanceValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting appearance value")
}
if !slices.Contains(UserSettingAppearanceValue, appearanceValue) {
return fmt.Errorf("invalid user setting appearance value")
}
} else if upsert.Key == UserSettingMemoVisibilityKey {
memoVisibilityValue := Private
err := json.Unmarshal([]byte(upsert.Value), &memoVisibilityValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting memo visibility value")
}
if !slices.Contains(UserSettingMemoVisibilityValue, memoVisibilityValue) {
return fmt.Errorf("invalid user setting memo visibility value")
}
} else {
return fmt.Errorf("invalid user setting key")
}
return nil
}
type UserSettingFind struct {
UserID int
Key UserSettingKey `json:"key"`
}
type UserSettingDelete struct {
UserID int
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

-166
View File
@@ -1,166 +0,0 @@
package cmd
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/usememos/memos/server"
_profile "github.com/usememos/memos/server/profile"
"github.com/usememos/memos/setup"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
)
const (
greetingBanner = `
███╗ ███╗███████╗███╗ ███╗ ██████╗ ███████╗
████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔════╝
██╔████╔██║█████╗ ██╔████╔██║██║ ██║███████╗
██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║╚════██║
██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝███████║
╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
`
)
var (
profile *_profile.Profile
mode string
port int
data string
rootCmd = &cobra.Command{
Use: "memos",
Short: `An open-source, self-hosted memo hub with knowledge management and social networking.`,
Run: func(_cmd *cobra.Command, _args []string) {
ctx, cancel := context.WithCancel(context.Background())
s, err := server.NewServer(ctx, profile)
if err != nil {
cancel()
fmt.Printf("failed to create server, error: %+v\n", err)
return
}
c := make(chan os.Signal, 1)
// Trigger graceful shutdown on SIGINT or SIGTERM.
// The default signal sent by the `kill` command is SIGTERM,
// which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
sig := <-c
fmt.Printf("%s received.\n", sig.String())
s.Shutdown(ctx)
cancel()
}()
println(greetingBanner)
fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
if err := s.Start(ctx); err != nil {
if err != http.ErrServerClosed {
fmt.Printf("failed to start server, error: %+v\n", err)
cancel()
}
}
// Wait for CTRL-C.
<-ctx.Done()
},
}
setupCmd = &cobra.Command{
Use: "setup",
Short: "Make initial setup for memos",
Run: func(cmd *cobra.Command, _ []string) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
hostUsername, err := cmd.Flags().GetString(setupCmdFlagHostUsername)
if err != nil {
fmt.Printf("failed to get owner username, error: %+v\n", err)
return
}
hostPassword, err := cmd.Flags().GetString(setupCmdFlagHostPassword)
if err != nil {
fmt.Printf("failed to get owner password, error: %+v\n", err)
return
}
db := db.NewDB(profile)
if err := db.Open(ctx); err != nil {
fmt.Printf("failed to open db, error: %+v\n", err)
return
}
store := store.New(db.DBInstance, profile)
if err := setup.Execute(ctx, store, hostUsername, hostPassword); err != nil {
fmt.Printf("failed to setup, error: %+v\n", err)
return
}
},
}
)
func Execute() error {
return rootCmd.Execute()
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "demo", `mode of server, can be "prod" or "dev" or "demo"`)
rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 8081, "port of server")
rootCmd.PersistentFlags().StringVarP(&data, "data", "d", "", "data directory")
err := viper.BindPFlag("mode", rootCmd.PersistentFlags().Lookup("mode"))
if err != nil {
panic(err)
}
err = viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))
if err != nil {
panic(err)
}
err = viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data"))
if err != nil {
panic(err)
}
viper.SetDefault("mode", "demo")
viper.SetDefault("port", 8081)
viper.SetEnvPrefix("memos")
setupCmd.Flags().String(setupCmdFlagHostUsername, "", "Owner username")
setupCmd.Flags().String(setupCmdFlagHostPassword, "", "Owner password")
rootCmd.AddCommand(setupCmd)
}
func initConfig() {
viper.AutomaticEnv()
var err error
profile, err = _profile.GetProfile()
if err != nil {
fmt.Printf("failed to get profile, error: %+v\n", err)
return
}
println("---")
println("Server profile")
println("dsn:", profile.DSN)
println("port:", profile.Port)
println("mode:", profile.Mode)
println("version:", profile.Version)
println("---")
}
const (
setupCmdFlagHostUsername = "host-username"
setupCmdFlagHostPassword = "host-password"
)
+28
View File
@@ -0,0 +1,28 @@
package main
import (
"io"
"log/slog"
"strings"
"github.com/pkg/errors"
)
func parseSlogLevel(s string) (slog.Level, error) {
switch strings.ToLower(s) {
case "debug":
return slog.LevelDebug, nil
case "info":
return slog.LevelInfo, nil
case "warn":
return slog.LevelWarn, nil
case "error":
return slog.LevelError, nil
default:
return slog.LevelInfo, errors.Errorf("unknown log level %q: must be debug, info, warn, or error", s)
}
}
func newLogger(level slog.Level, w io.Writer) *slog.Logger {
return slog.New(slog.NewTextHandler(w, &slog.HandlerOptions{Level: level}))
}
+107
View File
@@ -0,0 +1,107 @@
package main
import (
"bytes"
"context"
"log/slog"
"strings"
"testing"
)
func TestParseSlogLevel(t *testing.T) {
tests := []struct {
input string
wantLevel slog.Level
wantErr bool
}{
{"debug", slog.LevelDebug, false},
{"info", slog.LevelInfo, false},
{"warn", slog.LevelWarn, false},
{"error", slog.LevelError, false},
{"DEBUG", slog.LevelDebug, false},
{"INFO", slog.LevelInfo, false},
{"WARN", slog.LevelWarn, false},
{"ERROR", slog.LevelError, false},
{"invalid", slog.LevelInfo, true},
{"", slog.LevelInfo, true},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
got, err := parseSlogLevel(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("parseSlogLevel(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr)
}
if got != tt.wantLevel {
t.Errorf("parseSlogLevel(%q) = %v, want %v", tt.input, got, tt.wantLevel)
}
})
}
}
func TestNewLoggerLevelFiltering(t *testing.T) {
tests := []struct {
level slog.Level
logAt slog.Level
msg string
shouldAppear bool
}{
// debug passes all
{slog.LevelDebug, slog.LevelDebug, "debug-msg", true},
{slog.LevelDebug, slog.LevelInfo, "info-msg", true},
{slog.LevelDebug, slog.LevelWarn, "warn-msg", true},
{slog.LevelDebug, slog.LevelError, "error-msg", true},
// info suppresses debug
{slog.LevelInfo, slog.LevelDebug, "debug-suppressed", false},
{slog.LevelInfo, slog.LevelInfo, "info-visible", true},
{slog.LevelInfo, slog.LevelWarn, "warn-visible", true},
// warn suppresses debug+info
{slog.LevelWarn, slog.LevelDebug, "debug-suppressed", false},
{slog.LevelWarn, slog.LevelInfo, "info-suppressed", false},
{slog.LevelWarn, slog.LevelWarn, "warn-visible", true},
{slog.LevelWarn, slog.LevelError, "error-visible", true},
// error suppresses everything below
{slog.LevelError, slog.LevelDebug, "debug-suppressed", false},
{slog.LevelError, slog.LevelInfo, "info-suppressed", false},
{slog.LevelError, slog.LevelWarn, "warn-suppressed", false},
{slog.LevelError, slog.LevelError, "error-visible", true},
}
for _, tt := range tests {
var buf bytes.Buffer
logger := newLogger(tt.level, &buf)
logger.Log(context.TODO(), tt.logAt, tt.msg)
appeared := strings.Contains(buf.String(), tt.msg)
if appeared != tt.shouldAppear {
t.Errorf("level=%s logAt=%s msg=%q: appeared=%v want=%v",
tt.level, tt.logAt, tt.msg, appeared, tt.shouldAppear)
}
}
}
func TestNewLoggerOutputFormat(t *testing.T) {
var buf bytes.Buffer
logger := newLogger(slog.LevelDebug, &buf)
logger.Info("hello-world", "key", "value")
out := buf.String()
if !strings.Contains(out, "hello-world") {
t.Errorf("expected message in output, got: %s", out)
}
if !strings.Contains(out, "key=value") {
t.Errorf("expected key=value attr in output, got: %s", out)
}
if !strings.Contains(out, "INFO") {
t.Errorf("expected level in output, got: %s", out)
}
}
func TestNewLoggerDoesNotMutateGlobalDefault(t *testing.T) {
original := slog.Default()
var buf bytes.Buffer
_ = newLogger(slog.LevelError, &buf)
if slog.Default() != original {
t.Error("newLogger must not change slog.Default()")
}
}
+206
View File
@@ -0,0 +1,206 @@
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/usememos/memos/internal/profile"
"github.com/usememos/memos/internal/version"
"github.com/usememos/memos/internal/webhook"
"github.com/usememos/memos/server"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
)
func initSlogDefault() {
level, err := parseSlogLevel(viper.GetString("log-level"))
if err != nil {
slog.Warn("invalid log-level value, defaulting to info", "error", err)
}
slog.SetDefault(newLogger(level, os.Stderr))
}
var (
rootCmd = &cobra.Command{
Use: "memos",
Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`,
Run: func(_ *cobra.Command, _ []string) {
instanceProfile := &profile.Profile{
Demo: viper.GetBool("demo"),
Addr: viper.GetString("addr"),
Port: viper.GetInt("port"),
UNIXSock: viper.GetString("unix-sock"),
Data: viper.GetString("data"),
Driver: viper.GetString("driver"),
DSN: viper.GetString("dsn"),
InstanceURL: viper.GetString("instance-url"),
}
instanceProfile.Version = version.GetCurrentVersion()
instanceProfile.Commit = version.Commit
webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks")
if err := instanceProfile.Validate(); err != nil {
slog.Error("failed to validate profile", "error", err)
return
}
ctx, cancel := context.WithCancel(context.Background())
dbDriver, err := db.NewDBDriver(instanceProfile)
if err != nil {
cancel()
slog.Error("failed to create db driver", "error", err)
return
}
storeInstance := store.New(dbDriver, instanceProfile)
if err := storeInstance.Migrate(ctx); err != nil {
cancel()
slog.Error("failed to migrate", "error", err)
return
}
s, err := server.NewServer(ctx, instanceProfile, storeInstance)
if err != nil {
cancel()
slog.Error("failed to create server", "error", err)
return
}
c := make(chan os.Signal, 1)
// Trigger graceful shutdown on SIGINT or SIGTERM.
// The default signal sent by the `kill` command is SIGTERM,
// which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
if err := s.Start(ctx); err != nil {
if err != http.ErrServerClosed {
slog.Error("failed to start server", "error", err)
cancel()
return
}
}
printGreetings(instanceProfile)
go func() {
<-c
s.Shutdown(ctx)
cancel()
}()
// Wait for CTRL-C.
<-ctx.Done()
},
}
versionCmd = &cobra.Command{
Use: "version",
Short: "Print the current Memos version",
Run: func(_ *cobra.Command, _ []string) {
fmt.Println(version.GetCurrentVersion())
},
}
)
func init() {
cobra.OnInitialize(initSlogDefault)
viper.SetDefault("demo", false)
viper.SetDefault("driver", "sqlite")
viper.SetDefault("port", 8081)
rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode")
rootCmd.PersistentFlags().String("addr", "", "address of server")
rootCmd.PersistentFlags().Int("port", 8081, "port of server")
rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port")
rootCmd.PersistentFlags().String("data", "", "data directory")
rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance")
rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses")
rootCmd.PersistentFlags().String("log-level", "info", "log verbosity level (debug, info, warn, error)")
if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil {
panic(err)
}
if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil {
panic(err)
}
if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil {
panic(err)
}
if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil {
panic(err)
}
if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil {
panic(err)
}
if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil {
panic(err)
}
if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil {
panic(err)
}
if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil {
panic(err)
}
if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil {
panic(err)
}
if err := viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level")); err != nil {
panic(err)
}
viper.SetEnvPrefix("memos")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv()
rootCmd.AddCommand(versionCmd)
}
func printGreetings(profile *profile.Profile) {
fmt.Printf("Memos %s started successfully!\n", profile.Version)
if profile.Demo {
fmt.Fprint(os.Stderr, "Development mode is enabled\n")
if profile.DSN != "" {
fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN)
}
}
// Server information
fmt.Printf("Data directory: %s\n", profile.Data)
fmt.Printf("Database driver: %s\n", profile.Driver)
// Connection information
if len(profile.UNIXSock) == 0 {
if len(profile.Addr) == 0 {
fmt.Printf("Server running on port %d\n", profile.Port)
fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port)
} else {
fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port)
fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port)
}
} else {
fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock)
}
fmt.Println()
fmt.Printf("Documentation: %s\n", "https://usememos.com")
fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos")
fmt.Println("\nHappy note-taking!")
}
func main() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
-72
View File
@@ -1,72 +0,0 @@
package common
import (
"errors"
)
// Code is the error code.
type Code int
// Application error codes.
const (
// 0 ~ 99 general error.
Ok Code = 0
Internal Code = 1
NotAuthorized Code = 2
Invalid Code = 3
NotFound Code = 4
Conflict Code = 5
NotImplemented Code = 6
)
// Error represents an application-specific error. Application errors can be
// unwrapped by the caller to extract out the code & message.
//
// Any non-application error (such as a disk error) should be reported as an
// Internal error and the human user should only see "Internal error" as the
// message. These low-level internal error details should only be logged and
// reported to the operator of the application (not the end user).
type Error struct {
// Machine-readable error code.
Code Code
// Embedded error.
Err error
}
// Error implements the error interface. Not used by the application otherwise.
func (e *Error) Error() string {
return e.Err.Error()
}
// ErrorCode unwraps an application error and returns its code.
// Non-application errors always return EINTERNAL.
func ErrorCode(err error) Code {
var e *Error
if err == nil {
return Ok
} else if errors.As(err, &e) {
return e.Code
}
return Internal
}
// ErrorMessage unwraps an application error and returns its message.
// Non-application errors always return "Internal error".
func ErrorMessage(err error) string {
var e *Error
if err == nil {
return ""
} else if errors.As(err, &e) {
return e.Err.Error()
}
return "Internal error."
}
// Errorf is a helper function to return an Error with a given code and error.
func Errorf(code Code, err error) *Error {
return &Error{
Code: code,
Err: err,
}
}
-67
View File
@@ -1,67 +0,0 @@
// Package log implements a simple logging package.
package log
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
// `gl` is the global logger.
// Other packages should use public methods such as Info/Error to do the logging.
// For other types of logging, e.g. logging to a separate file, they should use their own loggers.
gl *zap.Logger
gLevel zap.AtomicLevel
)
// Initializes the global console logger.
func init() {
gLevel = zap.NewAtomicLevelAt(zap.InfoLevel)
gl, _ = zap.Config{
Level: gLevel,
Development: true,
// Use "console" to print readable stacktrace.
Encoding: "console",
EncoderConfig: zap.NewDevelopmentEncoderConfig(),
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}.Build(
// Skip one caller stack to locate the correct caller.
zap.AddCallerSkip(1),
)
}
// SetLevel wraps the zap Level's SetLevel method.
func SetLevel(level zapcore.Level) {
gLevel.SetLevel(level)
}
// EnabledLevel wraps the zap Level's Enabled method.
func EnabledLevel(level zapcore.Level) bool {
return gLevel.Enabled(level)
}
// Debug wraps the zap Logger's Debug method.
func Debug(msg string, fields ...zap.Field) {
gl.Debug(msg, fields...)
}
// Info wraps the zap Logger's Info method.
func Info(msg string, fields ...zap.Field) {
gl.Info(msg, fields...)
}
// Warn wraps the zap Logger's Warn method.
func Warn(msg string, fields ...zap.Field) {
gl.Warn(msg, fields...)
}
// Error wraps the zap Logger's Error method.
func Error(msg string, fields ...zap.Field) {
gl.Error(msg, fields...)
}
// Sync wraps the zap Logger's Sync method.
func Sync() {
_ = gl.Sync()
}
-17
View File
@@ -1,17 +0,0 @@
version: "3.0"
# uffizzi integration
x-uffizzi:
ingress:
service: memos
port: 5230
services:
memos:
image: "${MEMOS_IMAGE}"
volumes:
- memos_volume:/var/opt/memos
command: ["--mode", "demo"]
volumes:
memos_volume:
-18
View File
@@ -1,18 +0,0 @@
# Adding A Custom Theme
1. Open the Settings Dialog
2. Navigate to the System Tab
3. In the "Additional Styles" box add these lines of code:
```css
.memo-list-container {
background-color: #INSERT COLOR HERE;
}
.page-container {
background-color: #INSERT COLOR HERE;
}
```
It is recommended that you choose the same color for both options
4. Refresh the page and the background color of your memos app will successfully update to reflect your changes
-133
View File
@@ -1,133 +0,0 @@
# A Beginner's Guide to Deploying Memos on Render.com
written by [AJ](https://memos.ajstephens.website/) (also a noob)
<img height="64px" src="https://usememos.com/logo-full.png" alt="✍️ memos" />
[Live Demo](https://demo.usememos.com) • [Official Website](https://usememos.com) • [Source Code](https://github.com/usememos/memos)
## Who is this guide for?
Someone who...
- doesn't have much experience with self hosting
- has a minimal understanding of docker
Someone who wants...
- to use memos
- to support the memos project
- a cost effective and simple way to host it on the cloud with reliablity and persistance
- to share memos with friends
## Requirements
- Can follow instructions
- Have 7ish USD a month on a debit/credit card
## Guide
Create an account at [Render](https://dashboard.render.com/register)
![ss1](https://i.imgur.com/l3K7aqC.png)
1. Go to your dashboard
[https://dashboard.render.com/](https://dashboard.render.com/)
2. Select New Web Service
![ss2](https://i.imgur.com/IIDdK2y.png)
3. Scroll down to "Public Git repository"
4. Paste in the link for the public git repository for memos (https://github.com/usememos/memos) and press continue
![ss3](https://i.imgur.com/OXoCWoJ.png)
5. Render will pre-fill most of the fields but you will need to create a unique name for your web service
6. Adjust region if you want to
7. Don't touch the "branch", "root directory", and "environment" fields
![ss4](https://i.imgur.com/v7Sw3fp.png)
8. Click "enter your payment information" and do so
![ss5](https://i.imgur.com/paKcQFl.png)
![ss6](https://i.imgur.com/JdcO1HC.png)
9. Select the starter plan ($7 a month - a requirement for persistant data - render's free instances spin down when inactive and lose all data)
10. Click "Create Web Service"
![ss7](https://i.imgur.com/MHe45J4.png)
11. Wait patiently while the _magic_ happens 🤷‍♂️
![ss8](https://i.imgur.com/h1PXHHJ.png)
12. After some time (~ 6 min for me) the build will finish and you will see the web service is live
![ss9](https://i.imgur.com/msapkRw.png)
13. Now it's time to add the disk so your data won't dissappear when the webservice redeploys (redeploys happen automatically when the public repo is updated)
14. Select the "Disks" tab on the left menu and then click "Add Disk"
![ss10](https://i.imgur.com/rGeI0bv.png)
15. Name your disk (can be whatever)
16. Set the "Mount Path" to `/var/opt/memos`
17. Set the disk size (default is 10GB but 1GB is plenty and can be increased at any time)
18. Click "Save"
![ss11](https://i.imgur.com/Jbg7O6q.png)
19. Wait...again...while the webservice redeploys with the persistant disk
![ss12](https://i.imgur.com/pTzpE34.png)
20. aaaand....we're back online!
![ss13](https://i.imgur.com/qdsFfSa.png)
21. Time to test! We're going to make sure everything is working correctly.
22. Click the link in the top left, it should look like `https://the-name-you-chose.onrender.com` - this is your self hosted memos link!
![ss14](https://i.imgur.com/cgzFSIn.png)
23. Create a Username and Password (remember these) then click "Sign up as Host"
![ss15](https://i.imgur.com/kuRStAj.png)
24. Create a test memo then click save
![ss16](https://i.imgur.com/Eh2AB44.png)
25. Sign out of your self-hosted memos
![ss17](https://i.imgur.com/0mMb88G.png)
26. Return to your Render dashboard, click the "Manual Deploy" dropdown button and click "Deploy latest commit" and wait until the webservice is live again (This is to test that your data is persistant)
![ss18](https://i.imgur.com/w1N7VTb.png)
27. Once the webservice is live go back to your self-hosted memos page and sign in! (If your memos screen looks different then something went wrong)
28. Once you're logged in, verify your test memo is still there after the redeploy
![ss19](https://i.imgur.com/dTcEQZS.png)
![ss20](https://i.imgur.com/VE2lu8H.png)
## 🎉Celebrate!🎉
You did it! Enjoy using memos!
Want to learn more or need more guidance? Join the community on [telegram](https://t.me/+-_tNF1k70UU4ZTc9) and [discord](https://discord.gg/tfPJa4UmAv).
-40
View File
@@ -1,40 +0,0 @@
# Development
Memos is built with a curated tech stack. It is optimized for developer experience and is very easy to start working on the code:
1. It has no external dependency.
2. It requires zero config.
3. 1 command to start backend and 1 command to start frontend, both with live reload support.
## Tech Stack
![tech-stack](https://raw.githubusercontent.com/usememos/memos/main/assets/tech-stack.png)
## Prerequisites
- [Go](https://golang.org/doc/install)
- [Air](https://github.com/cosmtrek/air#installation) for backend live reload
- [Node.js](https://nodejs.org/)
- [pnpm](https://pnpm.io/installation)
## Steps
1. pull source code
```bash
git clone https://github.com/usememos/memos
```
2. start backend using air(with live reload)
```bash
air -c scripts/.air.toml
```
3. start frontend dev server
```bash
cd web && pnpm i && pnpm dev
```
Memos should now be running at [http://localhost:3001](http://localhost:3001) and change either frontend or backend code would trigger live reload.
@@ -0,0 +1,35 @@
## Background & Context
The MemoDetail page (`web/src/pages/MemoDetail.tsx`) renders a memo's full content with a right sidebar (`MemoDetailSidebar`) on desktop. The sidebar currently shows share controls, timestamps, property badges (links, to-do, code), and tags. Memo content is rendered via `react-markdown` with custom heading components (h1h6) in `MemoContent/markdown/Heading.tsx`. The page already has hash-based scroll-to-element infrastructure for comments (lines 3943 of MemoDetail.tsx).
## Issue Statement
When viewing a memo with structured headings, there is no outline or table of contents in the MemoDetail sidebar, so readers cannot see the document structure at a glance or jump to specific sections. Heading elements rendered by the `Heading` component do not have `id` attributes, preventing any anchor-based navigation to them.
## Current State
- **`web/src/pages/MemoDetail.tsx`** (93 lines) — MemoDetail page. Hash-based `scrollIntoView` logic exists at lines 3943 but only targets comment elements. The sidebar is rendered at lines 8286 as `<MemoDetailSidebar>`.
- **`web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx`** (109 lines) — Desktop sidebar. Contains sections: Share (lines 5865), Created-at (lines 6776), Properties (lines 7889), Tags (lines 91102). Uses a reusable `SidebarSection` helper (lines 2432). No outline section exists.
- **`web/src/components/MemoDetailSidebar/MemoDetailSidebarDrawer.tsx`** (36 lines) — Mobile drawer wrapper for the sidebar.
- **`web/src/components/MemoContent/markdown/Heading.tsx`** (30 lines) — Renders h1h6 with Tailwind classes. Does not generate `id` attributes on heading elements.
- **`web/src/components/MemoContent/index.tsx`** (157 lines) — ReactMarkdown renderer. Maps h1h6 to the `Heading` component (lines 72101). No rehype-slug or equivalent plugin is installed.
- **`web/src/utils/markdown-manipulation.ts`** (143 lines) — Contains `fromMarkdown()` MDAST parsing with GFM extensions. Used for task extraction; no heading extraction exists.
## Non-Goals
- Redesigning the overall MemoDetail layout or sidebar structure beyond adding the outline section.
- Supporting outline for the mobile drawer — the outline section should appear in the desktop sidebar only for now.
- Adding active heading highlighting on scroll (scroll-spy behavior).
- Supporting outline in the memo list/timeline view (compact mode).
- Changing the existing heading visual styles in the content area.
## Open Questions
- Which heading levels to include in the outline? (default: h1h4, matching user request)
- How to generate slug IDs — install `rehype-slug` or custom implementation? (default: lightweight custom slug generation in the Heading component to avoid a new dependency)
- Should the outline section be hidden when no headings exist? (default: yes, hide entirely like Properties/Tags sections)
- Should duplicate heading text produce unique slugs (e.g. `my-heading`, `my-heading-1`)? (default: yes, append numeric suffix for duplicates)
## Scope
**M** — Touches 34 files (Heading component, MemoDetailSidebar, possibly a new outline component, and a slug utility). Existing patterns (SidebarSection, hash scrolling) apply directly. No new subsystem or novel approach required.
@@ -0,0 +1,47 @@
## Task List
T1: Add heading extraction utility [S] — T2: Add slug IDs to Heading component [S] — T3: Create MemoOutline sidebar component [M] — T4: Integrate outline into MemoDetailSidebar [S]
### T1: Add heading extraction utility [S]
**Objective**: Provide a function to extract h1h4 headings from markdown content with slugified IDs, reusing the existing MDAST parsing pattern from `markdown-manipulation.ts`.
**Files**: `web/src/utils/markdown-manipulation.ts`
**Implementation**: Add `HeadingItem` interface (text, level, slug) and `extractHeadings(markdown: string): HeadingItem[]` function. Use existing `fromMarkdown()` + `visit()` pattern. Visit `"heading"` nodes with depth 14, extract text from children, generate slug via `slugify()` helper (lowercase, replace non-alphanumeric with hyphens, deduplicate). Export both.
**Validation**: `cd web && pnpm lint` — no new errors
### T2: Add slug IDs to Heading component [S]
**Objective**: Generate deterministic `id` attributes on h1h6 elements so outline links can scroll to them via `#hash`.
**Files**: `web/src/components/MemoContent/markdown/Heading.tsx`
**Implementation**: In `Heading` (~line 13), extract text from `children` using a `getTextContent(children)` helper that recursively extracts string content from React children. Generate slug with the same `slugify` logic. Apply `id={slug}` to the rendered `<Component>`.
**Validation**: `cd web && pnpm lint` — no new errors
### T3: Create MemoOutline sidebar component [M]
**Objective**: Create a modern, Claude/Linear-style outline component that renders h1h4 headings as anchor links with indentation by level.
**Size**: M (new component file, modern styling)
**Files**:
- Create: `web/src/components/MemoDetailSidebar/MemoOutline.tsx`
**Implementation**:
1. Props: `{ headings: HeadingItem[] }` from `markdown-manipulation.ts`
2. Render a `<nav>` with vertical list of `<a href="#slug">` links
3. Styling per level: h1 no indent, h2 `pl-3`, h3 `pl-6`, h4 `pl-9`. Text size: h1 `text-[13px] font-medium`, h2h4 `text-[13px] font-normal`. Color: `text-muted-foreground` with `hover:text-foreground` transition. Left border accent line (2px) along the nav. Smooth scroll on click via `scrollIntoView`.
4. Each link: `block py-1 truncate transition-colors` with level-based indentation
**Boundaries**: No scroll-spy / active state tracking. No mobile drawer integration.
**Dependencies**: T1
**Expected Outcome**: Component renders a clean, modern outline navigation.
**Validation**: `cd web && pnpm lint` — no new errors
### T4: Integrate outline into MemoDetailSidebar [S]
**Objective**: Add the outline section as the first section in `MemoDetailSidebar`, shown only when headings exist.
**Files**: `web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx`
**Implementation**: Import `extractHeadings` and `MemoOutline`. In `MemoDetailSidebar` (~line 48), compute `headings = useMemo(() => extractHeadings(memo.content), [memo.content])`. Before the Share section (~line 58), add conditional: `{headings.length > 0 && <SidebarSection label="Outline"><MemoOutline headings={headings} /></SidebarSection>}`.
**Validation**: `cd web && pnpm lint && pnpm build` — no errors
## Out-of-Scope Tasks
- Scroll-spy / active heading highlighting in the outline
- Mobile drawer outline support
- Outline in memo list view (compact mode)
- Changing existing heading visual styles in content area
@@ -0,0 +1,98 @@
## Background & Context
Memos has a content-blur feature: when a memo's tag list contains the literal string `NSFW`
(case-insensitive), the memo body is rendered with a `blur-lg` CSS class and a click-to-reveal
overlay is shown. This was simplified in v0.26.x from a previous admin-configurable system
(which had an on/off toggle and a custom-tag-list) down to a single hardcoded tag name.
In the same release cycle, an `InstanceTagsSetting` system was introduced that lets admins attach
metadata (currently only `background_color`) to tag name patterns via a regex-keyed map. This
system has its own proto definitions, store layer, API service handlers, frontend context, utility
library, and settings UI — all independent of the blur feature.
A sponsor raised (orgs/usememos/discussions/5708) that the hardcoded tag name is inconvenient:
users who organised their content under a different tag (e.g. a non-English word, a project-
specific label, or simply a term they prefer) must re-tag all existing memos just to use the blur
feature. Community comments echo the same concern and additionally ask for the ability to disable
the blur globally.
## Issue Statement
The memo content-blur trigger is evaluated exclusively against the hardcoded string `"NSFW"`
(case-insensitive) in `MemoView.tsx`, with no connection to the `InstanceTagsSetting` system,
making it impossible for an administrator to designate any other tag name — or set of tag name
patterns — as a blur trigger, and preventing users from re-using existing tag taxonomies to
activate content blurring.
## Current State
**Blur detection — frontend**
| File | Lines | Behaviour |
|------|-------|-----------|
| `web/src/components/MemoView/MemoView.tsx` | 2730 | `const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;` — single hardcoded string comparison |
| `web/src/components/MemoView/MemoViewContext.tsx` | 1619 | Context shape exposes `nsfw: boolean`, `showNSFWContent: boolean`, `toggleNsfwVisibility` |
| `web/src/components/MemoView/components/MemoBody.tsx` | 1123, 37, 53 | Applies `blur-lg transition-all duration-200` when `nsfw && !showNSFWContent`; renders `NsfwOverlay` button using i18n key `memo.click-to-show-nsfw-content` |
| `web/src/components/MemoPreview/MemoPreview.tsx` | 2427 | Stub context value: `nsfw: false`, `showNSFWContent: false` — blur never active in preview |
**Localisation strings that contain the "NSFW" term**
| File | Keys |
|------|------|
| `web/src/locales/en.json` (and ~30 other locale files) | `memo.click-to-hide-nsfw-content`, `memo.click-to-show-nsfw-content`, `settings.enable-blur-nsfw-content` |
Note: most non-English translations already use "sensitive content" rather than "NSFW" in these
keys; English is the outlier.
**Tag metadata system — proto**
| File | Lines | Content |
|------|-------|---------|
| `proto/api/v1/instance_service.proto` | 168181 | `message TagMetadata { google.type.Color background_color = 1; }` nested inside `InstanceSetting`; `TagsSetting` is a `map<string, TagMetadata>` |
| `proto/store/instance_setting.proto` | 113124 | `message InstanceTagMetadata { google.type.Color background_color = 1; }` inside `InstanceTagsSetting` |
**Tag metadata system — backend**
| File | Lines | Content |
|------|-------|---------|
| `store/instance_setting.go` | 166192 | `GetInstanceTagsSetting()` retrieves and caches the tags map |
| `server/router/api/v1/instance_service.go` | 300328 | `convertInstanceTagsSettingFromStore()` / `convertInstanceTagsSettingToStore()` convert between store and API representations, field-by-field |
| `server/router/api/v1/instance_service.go` | 387409 | `validateInstanceTagsSetting()` validates each key as a regex pattern and the color value |
**Tag metadata system — frontend**
| File | Lines | Content |
|------|-------|---------|
| `web/src/lib/tag.ts` | 2843 | `findTagMetadata(tag, tagsSetting)` — exact-match then regex-match lookup returning `TagMetadata \| undefined` |
| `web/src/components/MemoContent/Tag.tsx` | 2338 | Calls `findTagMetadata()` to apply `background_color` to inline tag chips |
| `web/src/components/Settings/TagsSection.tsx` | 36206 | Admin settings UI for managing the tag→metadata map; currently shows only a colour picker per tag |
| `web/src/contexts/InstanceContext.tsx` | 8399 | `tagsSetting` selector and fetch during app initialisation |
## Non-Goals
- Redesigning or replacing the `InstanceTagsSetting` proto or store structure beyond adding one field.
- Providing a per-user (as opposed to per-instance) blur preference.
- Changing how background-color metadata is stored, validated, or rendered.
- Adding a global on/off toggle for blurring (separate from per-tag configuration).
- Modifying the blur visual effect (CSS class, animation, overlay button layout).
- Migrating or auto-converting any existing memos that were tagged with `NSFW`.
- Changing non-English locale strings that already use neutral terminology.
## Open Questions
1. Should the `blur_content` field in tag metadata be configurable per-tag only by admins, or also by individual users via user-level tag settings? (default: admin-only, matching the existing `InstanceTagsSetting` access model)
2. When a memo has multiple tags and more than one of them has `blur_content = true`, should the blur activate if _any_ matching tag has the flag set, or only if _all_ matching tags do? (default: any — OR semantics, consistent with the current single-tag check)
3. Should there be a migration that automatically sets `blur_content = true` for any existing `InstanceTagsSetting` entry whose key is `"NSFW"` (case-insensitive)? (default: no automatic migration; admins reconfigure manually)
4. What should the English-locale i18n key strings say, given that "NSFW" is to be avoided? (default: "Click to show sensitive content" / "Click to hide sensitive content")
## Scope
**M** — the change adds one `bool` field to two existing proto messages, threads it through two
existing conversion functions in the backend, replaces one hardcoded string comparison in
`MemoView.tsx` with a call to the already-present `findTagMetadata()` utility, adds a checkbox to
the existing `TagsSection.tsx` settings UI, and renames three i18n keys. All required patterns
(field addition, conversion, `findTagMetadata` lookup, settings UI checkbox) already exist in the
codebase.
@@ -0,0 +1,63 @@
## Execution Log
### T1: Add blur_content field to proto messages
**Status**: Completed
**Files Changed**: `proto/api/v1/instance_service.proto`, `proto/store/instance_setting.proto`
**Validation**: `buf lint` — PASS
**Path Corrections**: None
**Deviations**: None
### T2: Regenerate proto code
**Status**: Completed
**Files Changed**: `proto/gen/` (Go + OpenAPI), `web/src/types/proto/` (TypeScript)
**Validation**: `grep blur_content` in generated files — PASS (field present in Go, TS, OpenAPI)
**Path Corrections**: None
**Deviations**: None
### T3: Thread blur_content through backend conversions
**Status**: Completed
**Files Changed**: `server/router/api/v1/instance_service.go`
**Validation**: `go build ./...` — PASS
**Path Corrections**: None
**Deviations**: None
### T4: Replace hardcoded NSFW check with tag metadata lookup
**Status**: Completed
**Files Changed**: `web/src/components/MemoView/MemoView.tsx`, `web/src/components/MemoView/MemoViewContext.tsx`, `web/src/components/MemoView/components/MemoBody.tsx`, `web/src/components/MemoPreview/MemoPreview.tsx`
**Validation**: `pnpm lint` — PASS
**Path Corrections**: i18n key update (T6) was pulled forward to unblock TypeScript type checking, since the i18n key type is statically checked.
**Deviations**: None
### T5: Add blur checkbox to TagsSection settings UI
**Status**: Completed
**Files Changed**: `web/src/components/Settings/TagsSection.tsx`
**Validation**: `pnpm lint` — PASS
**Path Corrections**: None
**Deviations**: None
### T6: Update English i18n keys
**Status**: Completed
**Files Changed**: `web/src/locales/en.json`
**Validation**: `grep -c "nsfw\|NSFW" en.json` — returns 0, PASS
**Path Corrections**: Executed during T4/T5 to unblock type checking. Added `setting.tags.blur-content` key (not in original plan but required by T5's new checkbox column).
**Deviations**: None
## Completion Declaration
**All tasks completed successfully.**
Summary of changes:
- Added `bool blur_content = 2` to both API and store proto TagMetadata messages
- Regenerated Go, TypeScript, and OpenAPI code
- Threaded `blur_content` through `convertInstanceTagsSettingFromStore()` and `convertInstanceTagsSettingToStore()`
- Replaced hardcoded `tag.toUpperCase() === "NSFW"` with `findTagMetadata(tag, tagsSetting)?.blurContent` lookup
- Renamed context fields: `nsfw``blurred`, `showNSFWContent``showBlurredContent`, `toggleNsfwVisibility``toggleBlurVisibility`
- Renamed `NsfwOverlay``BlurOverlay` component
- Expanded TagsSection local state to track `{ color, blur }` per tag and added a "Blur content" checkbox column
- Updated English i18n: renamed NSFW keys to "sensitive content", removed unused key, added `blur-content` setting key
@@ -0,0 +1,89 @@
## Task List
T1: Add blur_content field to proto messages [S] — T2: Regenerate proto code [S] — T3: Thread blur_content through backend conversions [S] — T4: Replace hardcoded NSFW check with tag metadata lookup [M] — T5: Add blur checkbox to TagsSection settings UI [S] — T6: Update English i18n keys [S]
### T1: Add blur_content field to proto messages [S]
**Objective**: Add a `bool blur_content` field to both the API and store proto TagMetadata messages.
**Files**: `proto/api/v1/instance_service.proto`, `proto/store/instance_setting.proto`
**Implementation**:
- In `proto/api/v1/instance_service.proto` (~line 171), add `bool blur_content = 2;` to `message TagMetadata` after `background_color`
- In `proto/store/instance_setting.proto` (~line 115), add `bool blur_content = 2;` to `message InstanceTagMetadata` after `background_color`
**Validation**: `cd proto && buf lint` — no errors
### T2: Regenerate proto code [S]
**Objective**: Regenerate Go + TypeScript + OpenAPI from updated proto definitions.
**Files**: `proto/gen/` (generated), `web/src/types/proto/` (generated)
**Implementation**: Run `cd proto && buf generate`
**Dependencies**: T1
**Validation**: `grep -r "blur_content\|blurContent" proto/gen/ web/src/types/proto/ | head -10` — shows new field in generated Go and TS files
### T3: Thread blur_content through backend conversion functions [S]
**Objective**: Pass `blur_content` through the store↔API conversion functions so the field round-trips correctly.
**Files**: `server/router/api/v1/instance_service.go`
**Implementation**:
- In `convertInstanceTagsSettingFromStore()` (~line 306): add `BlurContent: metadata.GetBlurContent()` to the `InstanceSetting_TagMetadata` struct literal
- In `convertInstanceTagsSettingToStore()` (~line 321): add `BlurContent: metadata.GetBlurContent()` to the `InstanceTagMetadata` struct literal
**Dependencies**: T2
**Validation**: `cd /Users/steven/Projects/usememos/memos && go build ./...` — compiles without errors
### T4: Replace hardcoded NSFW check with tag metadata lookup [M]
**Objective**: Replace the hardcoded `tag.toUpperCase() === "NSFW"` check with a lookup against `InstanceTagsSetting` via the existing `findTagMetadata()` utility, so any tag with `blur_content: true` triggers the blur.
**Size**: M (3 files, moderate logic)
**Files**:
- Modify: `web/src/components/MemoView/MemoView.tsx`
- Modify: `web/src/components/MemoView/MemoViewContext.tsx`
- Modify: `web/src/components/MemoView/components/MemoBody.tsx`
- Modify: `web/src/components/MemoPreview/MemoPreview.tsx`
**Implementation**:
1. In `MemoView.tsx`:
- Import `useInstance` from `@/contexts/InstanceContext` and `findTagMetadata` from `@/lib/tag`
- Replace `const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;` with a check that iterates `memoData.tags` and uses `findTagMetadata(tag, tagsSetting)?.blurContent` — OR semantics (any match triggers blur)
- Rename state/variables: `showNSFWContent``showBlurredContent`, `nsfw``blurred`, `toggleNsfwVisibility``toggleBlurVisibility`
2. In `MemoViewContext.tsx`:
- Rename interface fields: `nsfw``blurred`, `showNSFWContent``showBlurredContent`, `toggleNsfwVisibility``toggleBlurVisibility`
3. In `MemoBody.tsx`:
- Update destructured context fields to use new names (`blurred`, `showBlurredContent`, `toggleBlurVisibility`)
- Rename `NsfwOverlay` component to `BlurOverlay`
- Change i18n key from `memo.click-to-show-nsfw-content` to `memo.click-to-show-sensitive-content`
4. In `MemoPreview.tsx`:
- Update stub context to use new field names (`blurred`, `showBlurredContent`, `toggleBlurVisibility`)
**Boundaries**: Do NOT change blur CSS classes, animation, or overlay layout
**Dependencies**: T2
**Validation**: `cd web && pnpm lint` — no type or lint errors
### T5: Add blur checkbox to TagsSection settings UI [S]
**Objective**: Add a "Blur content" checkbox column to the tag settings table so admins can toggle `blur_content` per tag pattern.
**Files**: `web/src/components/Settings/TagsSection.tsx`
**Implementation**:
- Expand `localTags` state from `Record<string, string>` (hex only) to `Record<string, { color: string; blur: boolean }>` to track both fields
- Update `useEffect` sync, `originalHexMap` comparison, `handleColorChange`, `handleRemoveTag`, `handleAddTag` to work with the new shape
- Add a new `[newTagBlur, setNewTagBlur]` state for the add-tag row (default `false`)
- In `handleSave`, pass `blurContent` when creating `InstanceSetting_TagMetadata`
- Add a new column to `SettingTable` between "Background color" and "Actions": header `t("setting.tags.blur-content")`, renders a checkbox bound to `localTags[row.name].blur`
- Add the i18n key `setting.tags.blur-content` to `en.json` with value `"Blur content"`
**Dependencies**: T2
**Validation**: `cd web && pnpm lint` — no type or lint errors
### T6: Update English i18n keys [S]
**Objective**: Rename NSFW-specific i18n keys in `en.json` to use neutral "sensitive content" terminology.
**Files**: `web/src/locales/en.json`
**Implementation**:
- Change key `memo.click-to-show-nsfw-content``memo.click-to-show-sensitive-content` with value `"Click to show sensitive content"`
- Change key `memo.click-to-hide-nsfw-content``memo.click-to-hide-sensitive-content` with value `"Click to hide sensitive content"` (dead key but renamed for consistency)
- The key `settings.enable-blur-nsfw-content` is unused in code — remove it
**Dependencies**: T4 (key rename must match code references)
**Validation**: `grep -c "nsfw" web/src/locales/en.json` — returns `0`
## Out-of-Scope Tasks
- Updating non-English locale files (per non-goals: "Changing non-English locale strings that already use neutral terminology")
- Adding automatic migration for existing NSFW tag entries
- Per-user blur preferences
- Global on/off toggle for blurring
- Modifying blur visual effect (CSS, animation, overlay layout)
@@ -0,0 +1,41 @@
## Background & Context
User resources in Memos v1 are exposed through Connect/gRPC-Gateway handlers in `server/router/api/v1`, proto resource definitions in `proto/api/v1`, frontend profile flows in `web/src`, and MCP JSON helpers in `server/router/mcp`. The store schema already persists both an internal integer `id` and a unique `username` for each user. The GitHub issue reports that public user resource names such as `users/2` are still emitted across responses and nested user-scoped resources. Existing code already mixes identifier forms: `GetUser` accepts either `users/{id}` or `users/{username}`, the fileserver avatar route accepts either identifier, and the frontend profile page already enters the API through `users/{username}` before reusing the returned `user.name`.
## Issue Statement
Across the v1 API surface, canonical user resource names are currently constructed from `store.User.ID` rather than `store.User.Username`, and many handlers parse those emitted names back into integers for authorization and lookup. As a result, top-level user resources and nested user-scoped references in settings, stats, shortcuts, webhooks, notifications, memo creators, reactions, and MCP payloads expose sequential database IDs and couple downstream callers to integer-based user tokens in server-emitted names.
## Current State
- `store/user.go:26-42` defines `store.User` with both `ID int32` and `Username string`; `store/migration/sqlite/LATEST.sql:10-21` declares `username TEXT NOT NULL UNIQUE`.
- `server/router/api/v1/user_service.go:72-102` handles `GetUser` by extracting `users/{id_or_username}` and resolving either a numeric ID or a username; `server/router/api/v1/user_service.go:914-937` still serializes `User.name` as `users/{id}` and derives avatar URLs from that name.
- `server/router/api/v1/resource_name.go:67-89` has two different parsing paths: `ExtractUserIDFromName` only accepts numeric user tokens, while `extractUserIdentifierFromName` accepts either token and is currently only used by `GetUser`.
- `server/router/api/v1/user_service.go:335-369`, `server/router/api/v1/user_service.go:372-460`, `server/router/api/v1/user_service.go:463-517`, `server/router/api/v1/user_service.go:536-676`, `server/router/api/v1/user_service.go:679-911`, and `server/router/api/v1/user_service.go:1400-1488` parse numeric user segments for settings, personal access tokens, webhooks, and notifications, and emit names such as `users/%d/settings/...`, `users/%d/webhooks/...`, and `users/%d/notifications/%d`.
- `server/router/api/v1/shortcut_service.go:20-43` parses `users/{user}/shortcuts/{shortcut}` by converting the `user` segment to `int32`, and constructs shortcut names as `users/%d/shortcuts/%s`.
- `server/router/api/v1/user_service_stats.go:63-65`, `server/router/api/v1/user_service_stats.go:113`, `server/router/api/v1/user_service_stats.go:132-145`, `server/router/api/v1/user_service_stats.go:214-223` emit `users/%d/stats` and `users/%d/memos/%d`, and resolve stats requests through numeric `ExtractUserIDFromName`.
- `server/router/api/v1/memo_service_converter.go:26-37` serializes `Memo.creator` as `users/{id}`; `server/router/api/v1/reaction_service.go:154-164` serializes `Reaction.creator` as `users/{id}`; `server/router/api/v1/memo_service.go:636-643` and `server/router/api/v1/memo_service.go:815-845` parse `memo.Creator` through the numeric helper for inbox and webhook flows.
- `server/router/mcp/tools_memo.go:75-86`, `server/router/mcp/tools_attachment.go:29-37`, and `server/router/mcp/tools_reaction.go:64-71` plus `server/router/mcp/tools_reaction.go:133-138` serialize creator fields as `users/{id}` in MCP tool output.
- `server/router/fileserver/fileserver.go:153-181` and `server/router/fileserver/fileserver.go:533-539` currently resolve avatar requests by either numeric ID or username.
- `proto/api/v1/user_service.proto:22-29` and `proto/api/v1/user_service.proto:247-256` document `GetUser` accepting both `users/{id}` and `users/{username}`. The same proto file defines the `User` resource at `proto/api/v1/user_service.proto:161-178` and nested user resource formats at `proto/api/v1/user_service.proto:307-317` and `proto/api/v1/user_service.proto:361-373`; example text still uses numeric user tokens such as `users/123/settings/GENERAL`.
- `web/src/pages/UserProfile.tsx:74-86` requests `users/{username}` from the route param, and `web/src/layouts/MainLayout.tsx:37-48` stores the returned canonical `user.name` for later stats requests.
## Non-Goals
- Replacing internal `user.id` primary keys, foreign keys, or existing store schemas.
- Introducing a new opaque UUID-based public user identifier.
- Changing user discovery, public profile visibility, or authorization rules beyond how user resource names are parsed and emitted.
- Adding username history, redirect, or alias preservation for old usernames after a rename.
- Redesigning unrelated resource naming schemes such as memo, attachment, share, or identity-provider identifiers.
## Open Questions
- Which public surfaces are in scope for username-based canonical output? (default: all server-emitted v1 API and MCP payload fields that currently contain `users/{...}` resource names)
- Should legacy numeric inputs continue to resolve on user-scoped endpoints beyond `GetUser`? (default: no, accept only username-based user resource names)
- If a username changes, must previously emitted `users/{old-username}` names continue to resolve? (default: no additional alias or redirect layer; only the current username remains valid)
- Should notification, webhook, shortcut, and personal-access-token child identifiers keep their existing child token formats while only the parent user token changes? (default: yes)
- Does the issue include avatar URLs and other derived file paths that are built from `User.name`? (default: yes, because avatar URLs are emitted from the same canonical user name field)
## Scope
**L** — Current behavior spans `server/router/api/v1`, `server/router/mcp`, `server/router/fileserver`, `proto/api/v1`, frontend consumers in `web/src`, and the request parsers that turn user resource names back into internal IDs. Changing both emitted and accepted user resource names across those surfaces is a broad API contract change rather than a single local edit.
@@ -0,0 +1,63 @@
## References
- [AIP-122: Resource names](https://google.aip.dev/122)
- [AIP-123: Resource types](https://google.aip.dev/123)
- [AIP-148: Standard fields](https://google.aip.dev/148)
- [AIP-180: Backwards compatibility](https://google.aip.dev/180)
- [Insecure Direct Object Reference Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html)
- [REST API endpoints for users - GitHub Docs](https://docs.github.com/en/enterprise-server%403.19/rest/users/users)
- [Users API - GitLab Docs](https://docs.gitlab.com/api/users/)
- [API Usage - Gitea Documentation](https://docs.gitea.com/next/development/api-usage)
## Industry Baseline
`AIP-122: Resource names` and `AIP-148: Standard fields` treat `name` as the canonical identifier that clients store and reuse, and expect request `name` and `parent` fields to accept the same resource-name vocabulary across a service. `AIP-122` also allows aliases for lookup, but requires responses to emit the canonical resource name.
`REST API endpoints for users - GitHub Docs` and `API Usage - Gitea Documentation` use username-based public user paths and nested user-scoped routes, while keeping numeric or system-assigned identifiers as separate data or alternate endpoints when a durable internal identifier is required.
`Users API - GitLab Docs` shows a mixed-input compatibility pattern on some endpoints with `id_or_username`, which keeps older callers working while allowing username-oriented public routes.
`Insecure Direct Object Reference Prevention Cheat Sheet` treats enumerable numeric identifiers as a defense-in-depth concern, but not a substitute for authorization. Replacing `users/{id}` with `users/{username}` changes discoverability characteristics, but permission checks still have to enforce access from internal user IDs.
`AIP-180: Backwards compatibility` treats changes to resource-name format and server-generated field construction as breaking. Any design that changes emitted `User.name` values inside `v1` has to preserve as much request compatibility as possible and document the remaining response-format risk explicitly.
## Research Summary
Memos already has most of the prerequisites for username-based canonical names. The schema stores a unique username, `GetUser` already resolves either ID or username, the fileserver avatar route already uses an `identifier` abstraction, and the frontend profile page already starts from `users/{username}`. No database migration is required to identify users by username at the API boundary.
The current coupling problem is concentrated in two places. First, response builders serialize `users/{id}` in many modules, including memo conversion, stats, settings, shortcuts, notifications, webhooks, and MCP JSON helpers. Second, many request handlers assume they can parse a numeric ID back out of those names for authorization and storage lookups.
Research points to a common pattern of canonical public resource names plus server-side resolution to internal IDs. In Memos, switching the canonical token from numeric ID to username can reuse the existing unique username column and existing username lookups, but `AIP-123: Resource types` and `AIP-180: Backwards compatibility` still make clear that changing accepted and emitted resource-name formats inside `v1` is a breaking API contract change. That makes this design a deliberate contract replacement rather than a compatibility layer.
## Design Goals
- All server-emitted v1 and MCP response fields that serialize user resource names under `users/{...}` use the current username token instead of the numeric database ID.
- User-scoped request fields that reference `users/{...}` accept username-based resource names only.
- Authorization, ownership checks, inbox/webhook dispatch, and other internal workflows continue to operate on `store.User.ID` after resolving the public resource name.
- List and batch endpoints avoid introducing per-item user lookups when serializing username-based names.
- No database schema, foreign-key, or storage-key redesign is required.
## Non-Goals
- Replacing internal `user.id` primary keys, foreign keys, or existing store schemas.
- Introducing a new opaque UUID-based public user identifier.
- Changing user discovery, public profile visibility, or authorization rules beyond how user resource names are parsed and emitted.
- Adding username history, redirect, or alias preservation for old usernames after a rename.
- Redesigning unrelated resource naming schemes such as memo, attachment, share, or identity-provider identifiers.
- Adding a new API version as part of this issue.
## Proposed Design
Introduce a single canonical user-name builder in the v1 API layer that serializes `users/{username}` from resolved user data, and route every public user-name emitter through it. This includes `convertUserFromStore`, memo and reaction creator fields, user stats, settings, shortcuts, webhooks, notifications, personal-access-token names, webhook payloads, avatar URLs derived from `User.name`, and the MCP JSON helpers. This satisfies the first design goal and aligns the public resource shape with `AIP-122: Resource names`.
Introduce a shared user-token resolver in `server/router/api/v1` that extracts the `users/{token}` segment, validates it as a username-form resource token, resolves the corresponding `store.User`, and then passes the resolved internal ID into permission checks and storage lookups. This replaces numeric-only parsing in helpers such as `ExtractUserIDFromName`, `ExtractUserIDAndSettingKeyFromName`, shortcut and webhook parsers, personal-access-token deletion, and notification parsing. The fileserver's current `getUserByIdentifier` behavior shows both lookup styles exist today, but the API-layer contract for this issue becomes username-only rather than dual-mode.
Keep child resource tokens unchanged and only change the user segment. For names such as `users/{user}/settings/{setting}`, `users/{user}/webhooks/{webhook}`, `users/{user}/notifications/{notification}`, `users/{user}/shortcuts/{shortcut}`, and `users/{user}/personalAccessTokens/{token}`, the parent `user` token is resolved from the username, while the child token keeps its existing format and storage mapping. This is narrower than redesigning child identifiers and keeps the issue bounded to the user-resource segment.
Use response-side user resolution strategies that match endpoint shape. Single-resource handlers can resolve one user directly and serialize the username immediately. List and batch handlers such as memo conversion, stats aggregation, notifications, and MCP list output should collect distinct user IDs first and resolve usernames once per response, reusing the store's existing user lookup path and cache where available. This keeps username-based output from turning into hidden N+1 query behavior and satisfies the performance goal without changing persistence.
Replace the public user-resource contract rather than extending it. Server-emitted `name`, `parent`, `creator`, and `sender` fields become username-based canonical output, and handlers that currently accept `users/{id}` are updated to require `users/{username}`. `AIP-180: Backwards compatibility` indicates that changing both the construction and accepted format of an existing resource name is a breaking change for clients that persist, compare, or generate old `name` values. The design therefore requires updated proto comments, API examples, handler tests, and release notes to make the new canonical form and the removed numeric form explicit.
Do not add a username alias table in this issue. If a username changes, newly serialized resource names use the current username, and previously emitted username-based names stop resolving unless they match the current username. This keeps the scope aligned with existing `UpdateUser` behavior and avoids introducing a new subsystem for historical username resolution. The alternative of adding permanent old-username aliases was rejected because it expands the problem from canonical serialization into identity-history management.
Do not solve this by adding a second public identifier field and leaving `User.name` numeric. `AIP-122: Resource names` treats `name` as the canonical resource identifier, and the GitHub issue is specifically about the public names currently emitted under `users/{id}`. Adding a second field would preserve the exposed sequential identifier in the canonical slot and fail the primary design goal. Likewise, introducing a new opaque UUID-based public identifier was rejected because the repository already has a unique username field and the issue is scoped to replacing numeric user resource names with that existing identifier.
@@ -0,0 +1,62 @@
## Execution Log
### T1: Add username-only user resource helpers
**Status**: Completed
**Files Changed**:
- `server/router/api/v1/user_resource_name.go`
- `server/router/api/v1/resource_name.go`
- `server/router/api/v1/user_service.go`
- `server/router/api/v1/test/user_resource_name_test.go`
**Validation**: `go test -v ./server/router/api/v1/test -run 'TestUserResourceName'` — PASS
**Path Corrections**: Tightened username-token validation so numeric-only `users/1` fails at the resource-name layer instead of falling through to `NotFound`.
**Deviations**: None
### T2: Migrate user-scoped API handlers
**Status**: Completed
**Files Changed**:
- `server/router/api/v1/user_service.go`
- `server/router/api/v1/shortcut_service.go`
- `server/router/api/v1/user_service_stats.go`
- `server/router/api/v1/test/shortcut_service_test.go`
- `server/router/api/v1/test/user_service_stats_test.go`
- `server/router/api/v1/test/user_notification_test.go`
- `server/router/api/v1/test/user_service_registration_test.go`
**Validation**: `go test -v ./server/router/api/v1/test -run 'Test(ListShortcuts|GetShortcut|CreateShortcut|UpdateShortcut|DeleteShortcut|ShortcutFiltering|ShortcutCRUDComplete|GetUserStats_TagCount|ListUserNotifications|UserRegistration)'` — PASS
**Path Corrections**: Updated test fixtures to use valid username-form resource names (`users/testuser`, `users/test-user`) and corrected one stale registration-name expectation during the later broader suite rerun.
**Deviations**: None
### T3: Migrate memo, reaction, MCP, and avatar user references
**Status**: Completed
**Files Changed**:
- `server/router/api/v1/memo_service_converter.go`
- `server/router/api/v1/memo_service.go`
- `server/router/api/v1/reaction_service.go`
- `server/router/mcp/tools_memo.go`
- `server/router/mcp/tools_attachment.go`
- `server/router/mcp/tools_reaction.go`
- `server/router/fileserver/fileserver.go`
- `server/router/api/v1/test/memo_service_test.go`
- `server/router/api/v1/test/reaction_service_test.go`
**Validation**: `go test ./server/router/api/v1/... ./server/router/mcp/... ./server/router/fileserver/...` — PASS
**Path Corrections**: Removed an unused fileserver import after the first package build failed; kept MCP tool helper signatures stable for undeclared callers and switched tool call sites to username-aware wrappers.
**Deviations**: None
### T4: Update contract docs and regression tests
**Status**: Completed
**Files Changed**:
- `proto/api/v1/user_service.proto`
- `proto/api/v1/shortcut_service.proto`
- `web/src/layouts/MainLayout.tsx`
- `web/src/components/MemoExplorer/ShortcutsSection.tsx`
- `server/router/fileserver/README.md`
**Validation**: `go test -v ./server/router/api/v1/test/...` — PASS
**Path Corrections**: None
**Deviations**: None
## Completion Declaration
All tasks completed successfully
@@ -0,0 +1,106 @@
## Task List
Task Index
T1: Add username-only user resource helpers [L] — T2: Migrate user-scoped API handlers [L] — T3: Migrate memo, reaction, MCP, and avatar user references [L] — T4: Update contract docs and regression tests [L]
### T1: Add username-only user resource helpers [L]
**Objective**: Establish one v1 API mechanism for serializing `users/{username}` and resolving username-based user resource names back to internal user records, including root `GetUser` handling.
**Size**: L (multiple files, shared identifier logic used across handlers)
**Files**:
- Create: `server/router/api/v1/user_resource_name.go`
- Modify: `server/router/api/v1/resource_name.go`
- Modify: `server/router/api/v1/user_service.go`
- Test: `server/router/api/v1/test/user_resource_name_test.go`
**Implementation**:
1. In `server/router/api/v1/user_resource_name.go`: add the shared helper surface for canonical user-name construction, extracting the `users/{token}` segment, validating the username-form token, and resolving the corresponding `store.User`.
2. In `server/router/api/v1/resource_name.go`: replace `ExtractUserIDFromName()`s numeric-only behavior with username-oriented resolution helpers or thin wrappers that delegate to the new shared module.
3. In `server/router/api/v1/user_service.go`: update `GetUser()` (~lines 72-102) and `convertUserFromStore()` (~lines 914-937) to use username-only resource names and reject legacy numeric `users/{id}` requests.
4. In `server/router/api/v1/test/user_resource_name_test.go`: add direct coverage for `GetUser users/{username}` success, canonical `User.name == users/{username}`, and rejection of `users/{id}`.
**Boundaries**: Do not migrate nested user-scoped handlers, memo/reaction emitters, MCP output, or fileserver behavior in this task.
**Dependencies**: None
**Expected Outcome**: Shared username-only helper logic exists, root user resources serialize as `users/{username}`, and root numeric user-name requests fail.
**Validation**: `go test -v ./server/router/api/v1/test -run 'TestUserResourceName'` — expected output includes `PASS` and `ok`
### T2: Migrate user-scoped API handlers [L]
**Objective**: Convert user-scoped v1 handlers and nested resource emitters to require `users/{username}` while continuing to authorize and store by resolved internal user ID.
**Size**: L (multiple handlers in one large service plus shortcut and stats code)
**Files**:
- Modify: `server/router/api/v1/user_service.go`
- Modify: `server/router/api/v1/shortcut_service.go`
- Modify: `server/router/api/v1/user_service_stats.go`
- Test: `server/router/api/v1/test/shortcut_service_test.go`
- Test: `server/router/api/v1/test/user_service_stats_test.go`
- Test: `server/router/api/v1/test/user_notification_test.go`
- Test: `server/router/api/v1/test/user_service_registration_test.go`
**Implementation**:
1. In `server/router/api/v1/user_service.go`: update settings, PAT, webhook, and notification parsing/emission paths (~lines 335-911 and ~1400-1488) to resolve `users/{username}` and emit username-based parent/child resource names.
2. In `server/router/api/v1/shortcut_service.go`: update shortcut name parsing and construction (~lines 20-43) plus handler entry points to use username parents and nested names.
3. In `server/router/api/v1/user_service_stats.go`: update stats request parsing and `UserStats.name` / `PinnedMemos` serialization (~lines 63-65, 113, 132-145, 214-223) to use usernames.
4. In the listed tests: replace numeric user-name inputs with username-based parents, assert username-based emitted names, and add numeric-request rejection coverage for representative user-scoped endpoints.
**Boundaries**: Do not change memo/reaction creator fields, MCP JSON output, or fileserver avatar routing in this task.
**Dependencies**: T1
**Expected Outcome**: User settings, notifications, shortcuts, stats, PATs, and webhooks all accept only `users/{username}` and emit only username-based user resource names.
**Validation**: `go test -v ./server/router/api/v1/test -run 'Test(ListShortcuts|GetShortcut|CreateShortcut|UpdateShortcut|DeleteShortcut|ShortcutFiltering|ShortcutCRUDComplete|GetUserStats_TagCount|ListUserNotifications|UserRegistration)'` — expected output includes `PASS` and `ok`
### T3: Migrate memo, reaction, MCP, and avatar user references [L]
**Objective**: Remove numeric user resource names from memo/reaction-related API responses, dependent webhook/inbox flows, MCP JSON output, and avatar URLs/routing.
**Size**: L (cross-package serialization and lookup changes, including response-side user resolution)
**Files**:
- Modify: `server/router/api/v1/memo_service_converter.go`
- Modify: `server/router/api/v1/memo_service.go`
- Modify: `server/router/api/v1/reaction_service.go`
- Modify: `server/router/mcp/tools_memo.go`
- Modify: `server/router/mcp/tools_attachment.go`
- Modify: `server/router/mcp/tools_reaction.go`
- Modify: `server/router/fileserver/fileserver.go`
- Test: `server/router/api/v1/test/memo_service_test.go`
- Test: `server/router/api/v1/test/reaction_service_test.go`
**Implementation**:
1. In `server/router/api/v1/memo_service_converter.go`: update `convertMemoFromStore()` (~lines 16-73) to serialize `Memo.creator` from resolved usernames rather than numeric IDs, using response-side batching or shared lookup helpers so list responses do not regress into hidden per-item lookups.
2. In `server/router/api/v1/reaction_service.go`: update `convertReactionFromStore()` (~lines 154-164) to emit username-based creators.
3. In `server/router/api/v1/memo_service.go`: update memo comment, webhook dispatch, and webhook payload helpers (~lines 636-643 and 815-845) to resolve username-based memo creators before using internal IDs.
4. In `server/router/mcp/tools_memo.go`, `server/router/mcp/tools_attachment.go`, and `server/router/mcp/tools_reaction.go`: replace `users/%d` creator serialization with username-based values.
5. In `server/router/fileserver/fileserver.go`: change avatar lookup to accept username identifiers only and ensure avatar URLs derived from `User.name` continue to resolve under `users/{username}`.
6. In the listed tests: update creator assertions to `users/{username}` and add representative rejection coverage where numeric user names previously flowed through memo/reaction-related paths.
**Boundaries**: Do not update proto comments, README examples, or frontend comments in this task.
**Dependencies**: T1
**Expected Outcome**: Memo/reaction creators, webhook payload creators, MCP creator fields, and avatar-derived user paths no longer expose numeric user IDs.
**Validation**: `go test ./server/router/api/v1/... ./server/router/mcp/... ./server/router/fileserver/...` — expected output includes `ok` for all touched packages
### T4: Update contract docs and regression tests [L]
**Objective**: Align public contract comments/examples and the final regression suite with the username-only user resource-name contract.
**Size**: L (multiple contract/documentation files plus end-to-end regression coverage)
**Files**:
- Modify: `proto/api/v1/user_service.proto`
- Modify: `proto/api/v1/shortcut_service.proto`
- Modify: `web/src/layouts/MainLayout.tsx`
- Modify: `web/src/components/MemoExplorer/ShortcutsSection.tsx`
- Modify: `server/router/fileserver/README.md`
- Modify: `server/router/api/v1/test/user_resource_name_test.go`
- Modify: `server/router/api/v1/test/shortcut_service_test.go`
- Modify: `server/router/api/v1/test/user_service_stats_test.go`
- Modify: `server/router/api/v1/test/user_notification_test.go`
- Modify: `server/router/api/v1/test/memo_service_test.go`
- Modify: `server/router/api/v1/test/reaction_service_test.go`
- Modify: `server/router/api/v1/test/user_service_registration_test.go`
**Implementation**:
1. In `proto/api/v1/user_service.proto` and `proto/api/v1/shortcut_service.proto`: rewrite resource-name comments and examples so they document username-only user resource names and remove `users/{id}` examples.
2. In `web/src/layouts/MainLayout.tsx` and `web/src/components/MemoExplorer/ShortcutsSection.tsx`: update inline comments/examples that still describe numeric user resource names.
3. In `server/router/fileserver/README.md`: replace numeric avatar examples with username-based examples.
4. In the listed test files: finish any remaining request/response assertions so the suite consistently encodes the username-only contract and explicitly rejects numeric user resource names where that contract is externally visible.
**Boundaries**: Do not add schema migrations, generated proto output refreshes, or username-history behavior.
**Dependencies**: T2, T3
**Expected Outcome**: Source comments, examples, and regression tests all describe and enforce a username-only `users/{username}` public contract.
**Validation**: `go test -v ./server/router/api/v1/test/...` — expected output includes `PASS` and `ok`
## Out-of-Scope Tasks
- Database schema or migration changes for the `user` table or foreign keys.
- Username history, alias, redirect, or backward-compatibility layers.
- A new opaque public user identifier or a new API version.
- Opportunistic refactors outside the files listed above.
- Generated code refreshes (`buf generate`) unless a later approved plan revision explicitly requires schema changes.
@@ -0,0 +1,47 @@
## Background & Context
Memos is a self-hosted note-taking product whose main write path is the React memo composer in `web/src/components/MemoEditor`. Memo content is stored as Markdown text, attachments are uploaded through the v1 attachment API, and the server already has dedicated file-serving behavior for media playback. The most recent relevant change in this area was commit `63a17d89`, which refactored audio attachment rendering into reusable playback components. That change improved how audio files are displayed after upload; it did not add a microphone-driven input path inside the compose flow.
## Issue Statement
Memo creation currently starts from typed text plus file upload and metadata pickers, while audio support in the product begins only after an audio file already exists as an attachment. Users who want to capture memo content by speaking must leave the compose flow to record elsewhere, then upload or manually transcribe the result, because the editor has no direct path from microphone input to memo text or an in-progress audio attachment.
## Current State
- `web/src/components/MemoEditor/index.tsx:26-154` assembles the compose flow from `EditorContent`, `EditorMetadata`, and `EditorToolbar`, and persists drafts through `memoService.save`.
- `web/src/components/MemoEditor/Editor/index.tsx:27-214` implements the editor surface as a `<textarea>` with slash commands and tag suggestions. It has no microphone entrypoint, recording lifecycle, or transcript state.
- `web/src/components/MemoEditor/components/EditorToolbar.tsx:10-54` renders the bottom toolbar with `InsertMenu`, visibility, cancel, and save actions. There is no first-class voice action in the primary control row.
- `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx:40-189` exposes upload, link-memo, location, and focus-mode actions, and uses a hidden `<input type="file">` for attachments. It does not expose microphone capture or dictation.
- `web/src/components/MemoEditor/components/EditorContent.tsx:12-54` handles drag-and-drop and paste for binary files only, and `web/src/components/MemoEditor/hooks/useFileUpload.ts:4-33` handles file-picker selection only.
- `web/src/components/MemoEditor/state/types.ts:8-30`, `web/src/components/MemoEditor/state/actions.ts:6-78`, and `web/src/components/MemoEditor/state/reducer.ts:4-130` track memo text, metadata, local files, and loading flags. There is no state for microphone permission, recording mode, partial transcript, cleanup review, or a pending audio blob.
- `web/src/components/MemoEditor/hooks/useAutoSave.ts:4-8` saves only the current `content` string to local storage. There is no draft persistence model for an in-progress voice session.
- `web/src/components/MemoEditor/services/validationService.ts:9-30` allows save when the draft has text, saved attachments, or local files, and `web/src/components/MemoEditor/services/uploadService.ts:8-26` uploads local files to `AttachmentService`. This means the existing save path can already persist an audio blob if one is present as a `LocalFile`.
- `web/src/components/MemoEditor/types/attachment.ts:4-28` classifies editor-side files only as `image`, `video`, or `document`, so an unsaved audio recording would currently fall into the generic document path in the editor draft surface.
- `web/src/utils/attachment.ts:15-38` recognizes `audio/*`, `web/src/components/MemoMetadata/Attachment/AttachmentListView.tsx:98-130` groups persisted attachments into visual/audio/docs sections, and `web/src/components/MemoMetadata/Attachment/AudioAttachmentItem.tsx:48-173` renders the dedicated audio playback card added by the last commit.
- `server/server.go:71-74` and `server/router/fileserver/fileserver.go:120-149,187-214` already treat video/audio attachments as native HTTP media streams once an attachment exists.
- `proto/api/v1/attachment_service.proto:48-90` and `server/router/api/v1/attachment_service.go:64-167` define binary attachment upload and metadata only. There is no transcription request/response shape, language hint, transcript cleanup option, or voice-session metadata in the API.
- `proto/api/v1/memo_service.proto:176-245` defines memo content as a single Markdown string plus optional attachments and relations. There is no separate speech transcript field or audio-note abstraction in the memo resource.
- `proto/api/v1/instance_service.proto:56-90` and `server/router/api/v1/instance_service.go:36-139` expose instance settings for `GENERAL`, `STORAGE`, `MEMO_RELATED`, `TAGS`, and `NOTIFICATION` only. There is no speech-provider or transcription-retention configuration surface.
- No existing implementation found for `getUserMedia`, `MediaRecorder`, browser speech recognition, or server-side transcription anywhere under `web/src`, `server`, `proto`, `plugin`, or `store`.
## Non-Goals
- Redesigning the current persisted audio attachment playback UI introduced in commit `63a17d89`.
- Building a full duplex spoken assistant or chatbot response loop inside Memos.
- Replacing the Markdown textarea editor with a different editor architecture.
- Shipping native desktop or mobile OS integrations such as global system-wide hotkeys.
- Redesigning attachment storage backends or the general file upload pipeline beyond voice-related usage.
- Adding broad AI rewrite/edit commands unrelated to capturing spoken memo text into the current draft.
## Open Questions
- Which client surfaces are in scope for the first rollout? (default: the existing React memo composer in the web app, including touch-friendly mobile-browser behavior)
- Is the first release a conversational voice mode or a dictation workflow? (default: dictation-first voice capture that inserts text into the current memo draft rather than opening a separate assistant session)
- Should Memos retain the raw recording after transcription? (default: no by default; keeping the recording is an explicit user choice that stores it as a normal attachment)
- Where does transcription execute? (default: behind a server-owned API so behavior, provider choice, and privacy copy are instance-controlled rather than browser-vendor specific)
- How much transcript cleanup is in scope? (default: punctuation plus limited filler/self-correction cleanup, with a review step before insertion)
- Does this issue include spoken edit commands such as “rewrite this shorter”? (default: no, only spoken text capture and insertion or replacement)
## Scope
**L** — The current gap spans the memo composer UI, editor state model, local file preview behavior, attachment save path, public API surface, and instance settings. There is no existing microphone or transcription implementation to extend, and a complete voice-input workflow would introduce both a new client interaction model and a new server contract rather than a single local edit.
@@ -0,0 +1,58 @@
## References
- [OpenAI Help: ChatGPT Release Notes](https://help.openai.com/en/articles/6825453-chatgpt-release-notes%3F.ejs)
- [Anthropic Support: Using voice mode on Claude mobile apps](https://support.anthropic.com/en/articles/11101966-using-voice-mode-on-claude-mobile-apps)
- [Typeless](https://www.typeless.com/)
- [Typeless FAQ](https://www.typeless.com/help/faqs)
- [DeltaCircuit/react-media-recorder README](https://github.com/DeltaCircuit/react-media-recorder/blob/master/README.md)
## Industry Baseline
ChatGPT, Claude, and Typeless all treat voice capture as a first-class entrypoint near the main compose surface rather than as a secondary attachment action. The common pattern is immediate access to the microphone, visible recording state, and explicit stop/discard control.
Those products also keep the capture loop short. The user starts recording, sees a clear recording state, and either keeps or cancels the result. Even when the product supports richer voice features, the initial interaction cost stays low.
The `react-media-recorder` reference reflects the common browser implementation pattern behind that interaction: explicit recorder states, start/stop commands, generated blob URLs, and preview playback of the recorded media. That maps well to the current Memos editor because the editor already knows how to persist local files through the attachment upload path.
## Research Summary
The current Memos composer already has the downstream path needed for recorded audio files: local draft files can be attached in the editor, `uploadService` can persist them through `AttachmentService`, and persisted audio attachments already have dedicated playback UI. What is missing is the upstream capture step inside the composer.
Given the revised scope, the right fit is not dictation or voice chat. The immediate problem is only that users cannot create an audio file from the memo composer itself. That means the smallest useful design is a browser voice recorder that produces a normal draft attachment.
Because the scope is now frontend-only, the design should not introduce new server contracts, new instance settings, or any transcription workflow. The recorded clip should flow through the existing `LocalFile -> uploadService -> attachment` path exactly like other draft files.
## Design Goals
- A user can start recording from the memo composer in one explicit action without opening the attachment menu.
- Recording state is visible and explicit: idle, requesting permission, recording, recorded, unsupported, or error.
- A completed recording can be kept as a draft audio file or discarded before memo save.
- Kept recordings reuse the existing local-file and attachment-save flow with no backend changes.
- The draft attachment surface renders recorded audio as playable audio, not as a generic document row.
- Save is blocked while recording is actively in progress, but succeeds once a recording has been stopped and kept.
## Non-Goals
- Transcribing audio to text.
- Adding any proto, store, server, or instance-settings changes.
- Building a spoken assistant or voice-chat mode.
- Redesigning persisted audio playback beyond the minimum draft preview needed for local recordings.
- Adding background recording, global hotkeys, or native device integrations.
## Proposed Design
Add a `Voice note` entry to `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx` rather than keeping a separate always-visible mic button in `web/src/components/MemoEditor/components/EditorToolbar.tsx`. This keeps the recorder close to the existing file and metadata insertion actions, reduces toolbar clutter, and still gives the user a direct path to create an audio attachment from the composer.
Introduce a `VoiceRecorderPanel` inside the memo editor layout, rendered between the editor body and the bottom metadata/toolbar area in `web/src/components/MemoEditor/index.tsx`. The panel is responsible for showing recorder state and actions, but it does not alter memo content. Its job is only to create or discard a draft audio file.
Add a dedicated `voiceRecorder` slice to `web/src/components/MemoEditor/state/types.ts` and `web/src/components/MemoEditor/state/reducer.ts`. The slice should hold support state, permission state, recorder status, elapsed time, pending error, and the most recent recorded draft clip before the user decides to keep or discard it. Keeping this state separate from `content`, `metadata`, and `localFiles` prevents recorder lifecycle state from leaking into unrelated editor behaviors.
Implement the browser media lifecycle in a dedicated hook such as `useVoiceRecorder`, following the `MediaRecorder` state pattern shown in `react-media-recorder`. The hook owns capability detection, `getUserMedia` requests, recorder start/stop, elapsed-time updates, blob assembly, and cleanup of tracks and blob URLs. The editor UI consumes only the hook output and dispatches reducer actions from it.
When the user stops a recording, convert the captured blob into a `File` and then into the existing `LocalFile` shape already used by file upload, paste, and drag-and-drop flows. The user can then either keep that `LocalFile`, which appends it to `state.localFiles`, or discard it, which revokes the blob URL and clears the recorder state. This keeps the design aligned with the existing upload path and avoids introducing a parallel attachment model.
Extend `web/src/components/MemoEditor/types/attachment.ts` so local `audio/*` files are classified as audio rather than falling back to `document`. Then update `web/src/components/MemoMetadata/Attachment/AttachmentListEditor.tsx` so draft audio files render with playable audio controls and normal remove behavior. This reuses the recent product investment in better audio presentation without requiring persisted attachments before preview is possible.
Update `web/src/components/MemoEditor/services/validationService.ts` so save remains allowed for normal local files and kept audio drafts, but not while `voiceRecorder.status` is actively `recording` or `requesting_permission`. That avoids saving a memo in the middle of a live recording session while preserving the existing rule that a memo may be saved with attachments and no text.
Do not introduce transcription, transcript review, speech-provider configuration, or server upload-before-save behavior in this design. Those alternatives were intentionally rejected because they expand the problem from “create an audio file quickly” into a larger speech-input subsystem. The current narrowed issue only requires fast recording and clean integration with the existing attachment flow.
@@ -0,0 +1,40 @@
## Execution Log
### T1: Add recorder state and browser capture hook
**Status**: Completed
**Files Changed**:
- `web/src/components/MemoEditor/hooks/useVoiceRecorder.ts`
- `web/src/components/MemoEditor/hooks/index.ts`
- `web/src/components/MemoEditor/state/types.ts`
- `web/src/components/MemoEditor/state/actions.ts`
- `web/src/components/MemoEditor/state/reducer.ts`
- `web/src/components/MemoEditor/services/memoService.ts`
**Validation**: `cd web && pnpm lint` — PASS
**Path Corrections**: Added `web/src/components/MemoEditor/services/memoService.ts` after plan update because `memoService.fromMemo()` also constructs `EditorState`.
**Deviations**: None after the approved plan correction.
Implemented a dedicated `voiceRecorder` editor state slice, reducer/actions for recorder lifecycle updates, a browser `MediaRecorder` hook that produces a `LocalFile` preview, and the matching `fromMemo()` defaults needed to keep the editor state shape valid for existing memo edit flows.
### T2: Add composer recorder UI and draft audio handling
**Status**: Completed
**Files Changed**:
- `web/src/components/MemoEditor/components/VoiceRecorderPanel.tsx`
- `web/src/components/MemoEditor/components/EditorToolbar.tsx`
- `web/src/components/MemoEditor/components/index.ts`
- `web/src/components/MemoEditor/index.tsx`
- `web/src/components/MemoEditor/types/components.ts`
- `web/src/components/MemoEditor/types/attachment.ts`
- `web/src/components/MemoMetadata/Attachment/AttachmentListEditor.tsx`
- `web/src/components/MemoEditor/services/validationService.ts`
- `web/src/locales/en.json`
**Validation**: `cd web && pnpm lint` — PASS
**Path Corrections**: None
**Deviations**: None
Added a `Voice note` action to the editor tool dropdown, wired the memo editor to start recording and render an inline recorder/review panel, let users keep a completed clip as a normal draft `LocalFile`, rendered local audio drafts with playable controls in the attachment editor, and blocked save only while permission is pending or recording is live.
## Completion Declaration
**Execution completed successfully** — the frontend memo composer now has a tool-dropdown voice recorder entrypoint that creates draft audio files through the existing attachment flow, with no backend or transcription changes.
@@ -0,0 +1,63 @@
## Task List
Task Index
T1: Add recorder state and browser capture hook [M] — T2: Add composer recorder UI and draft audio handling [L]
### T1: Add recorder state and browser capture hook [M]
**Objective**: Introduce the frontend-only state and hook needed to record audio in the browser and convert the finished clip into the existing `LocalFile` draft format.
**Size**: M (2-3 files, moderate logic)
**Files**:
- Create: `web/src/components/MemoEditor/hooks/useVoiceRecorder.ts`
- Modify: `web/src/components/MemoEditor/state/types.ts`
- Modify: `web/src/components/MemoEditor/state/actions.ts`
- Modify: `web/src/components/MemoEditor/state/reducer.ts`
- Modify: `web/src/components/MemoEditor/hooks/index.ts`
- Modify: `web/src/components/MemoEditor/services/memoService.ts`
**Implementation**:
1. In `web/src/components/MemoEditor/state/types.ts`, add a `voiceRecorder` state slice for recorder support, permission, status, elapsed seconds, pending error, and the latest temporary recording preview.
2. In `web/src/components/MemoEditor/state/actions.ts`, add actions for support/permission updates, recorder status changes, timer updates, temporary recording storage, and recorder reset.
3. In `web/src/components/MemoEditor/state/reducer.ts`, implement the new voice-recorder actions without changing existing content, metadata, or save behavior.
4. In new `web/src/components/MemoEditor/hooks/useVoiceRecorder.ts`, implement browser capability detection, `getUserMedia`, `MediaRecorder` setup, start/stop lifecycle, blob collection, cleanup, and conversion of the stopped recording into a `File` plus preview URL compatible with `LocalFile`.
5. In `web/src/components/MemoEditor/services/memoService.ts`, update `fromMemo()` so loaded memo state includes the new `voiceRecorder` defaults required by `EditorState`.
6. In `web/src/components/MemoEditor/hooks/index.ts`, export the new hook for editor integration.
**Boundaries**: This task must not add any toolbar/panel UI, attachment rendering updates, or transcription/network behavior.
**Dependencies**: None
**Expected Outcome**: The memo editor has a recorder state model and a reusable browser recording hook that can produce a draft audio file.
**Validation**: `cd web && pnpm lint` — expected output: TypeScript and Biome checks pass.
### T2: Add composer recorder UI and draft audio handling [L]
**Objective**: Add a voice-recorder entry inside the composer tool dropdown and make kept recordings behave like draft audio attachments in the existing save flow.
**Size**: L (multiple files, coordinated UI/state integration)
**Files**:
- Create: `web/src/components/MemoEditor/components/VoiceRecorderPanel.tsx`
- Modify: `web/src/components/MemoEditor/index.tsx`
- Modify: `web/src/components/MemoEditor/components/EditorToolbar.tsx`
- Modify: `web/src/components/MemoEditor/components/index.ts`
- Modify: `web/src/components/MemoEditor/types/components.ts`
- Modify: `web/src/components/MemoEditor/types/attachment.ts`
- Modify: `web/src/components/MemoMetadata/Attachment/AttachmentListEditor.tsx`
- Modify: `web/src/components/MemoEditor/services/validationService.ts`
- Modify: `web/src/locales/en.json`
**Implementation**:
1. In `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx` and `web/src/components/MemoEditor/components/EditorToolbar.tsx`, add a `Voice note` action to the existing compose tool dropdown instead of a separate toolbar button.
2. In new `web/src/components/MemoEditor/components/VoiceRecorderPanel.tsx`, render the recorder states `unsupported`, `idle`, `requesting_permission`, `recording`, `recorded`, and `error`, with explicit `Start`, `Stop`, `Keep`, and `Discard` actions.
3. In `web/src/components/MemoEditor/index.tsx`, render the recorder panel between editor content and the metadata/toolbar group, wire it to the editor context, and on `Keep` append the produced `LocalFile` to `state.localFiles`.
4. In `web/src/components/MemoEditor/types/attachment.ts`, classify local `audio/*` files as audio instead of generic documents.
5. In `web/src/components/MemoMetadata/Attachment/AttachmentListEditor.tsx`, render local draft audio items with playable audio controls while preserving existing remove behavior and existing attachment reordering rules.
6. In `web/src/components/MemoEditor/services/validationService.ts`, block save while a recording is actively running or permission is still being requested, but continue to allow save for kept draft audio files.
7. In `web/src/components/MemoEditor/components/index.ts`, `web/src/components/MemoEditor/types/components.ts`, and `web/src/locales/en.json`, add the exports, prop types, and English labels needed for the recorder UI.
**Boundaries**: This task must not add transcription, backend/API calls, settings UI, or redesign persisted audio playback beyond local draft preview.
**Dependencies**: T1
**Expected Outcome**: A user can choose `Voice note` from the memo composer tool dropdown, record audio in the browser, keep or discard the clip, preview a kept clip as a draft audio attachment, and save it through the existing attachment upload path.
**Validation**: `cd web && pnpm lint` — expected output: TypeScript and Biome checks pass with the new recorder workflow.
## Out-of-Scope Tasks
- Any transcription or speech-to-text behavior.
- Any proto, store, server, or instance-settings changes.
- Any speech provider configuration.
- Assistant-style voice conversations or spoken edit commands.
- Full locale backfill beyond the required English copy for this feature.
@@ -0,0 +1,49 @@
## Background & Context
Memos stores memo bodies as markdown, rebuilds derived memo metadata into `MemoPayload`, exposes user notifications through the inbox model, and renders memo content in the React client with custom markdown plugins. The requested `@someone` feature spans both top-level memos and memo comments: users need to type `@`, pick a valid person, render the mention inline, and notify the mentioned user. The current product already has adjacent primitives for this work: a backend markdown extension for `#tag`, an inbox-backed notification center, a generic editor suggestion popup, public user profiles under username-based routes, and a memo update path that already rebuilds payloads on create and edit.
External product behavior is consistent on the core interaction but different on scope. Notion supports real-time `@` suggestions inside pages, comments, and discussions, stores mention notifications in an inbox, and suppresses notification if the mentioned user cannot access the content. Confluence supports autocomplete mentions for people and teams, sends a notification on the first mention, and does not keep notifying on repeated mentions in the same page. Coda supports `@` mentions inside comment threads, treats mentions and thread participation as notification triggers, and allows broader comment-subscription settings beyond explicit mentions. These patterns suggest that the common baseline for Memos is inline autocomplete, access-aware notification, deduplication, and a clear separation between mention notifications and broader thread-subscription features.
## Issue Statement
Memos does not currently recognize `@username` tokens as structured content in memo bodies or comment bodies, does not expose any non-admin user-search endpoint that the editor can use to suggest mentionable users, does not persist or diff mention metadata during memo create or update flows, and does not have an inbox or API notification type for mentions. As a result, `@someone` currently behaves as plain text and cannot drive inline rendering, target validation, or notification delivery.
## Current State
- `server/router/api/v1/memo_service.go:32-159` creates memos by copying raw `request.Memo.Content` into `store.Memo`, enforcing length limits, and calling `memopayload.RebuildMemoPayload`; `server/router/api/v1/memo_service.go:404-510` rebuilds payload only when `content` changes during memo updates.
- `server/router/api/v1/memo_service.go:590-681` creates memo comments by internally creating another memo and only generates inbox notifications for non-private comments to the parent memo creator via `InboxMessage_MEMO_COMMENT`.
- `server/router/api/v1/memo_update_helpers.go:27-77` only dispatches webhook and SSE side effects after memo updates; there is no mention-diff side-effect hook.
- `internal/markdown/markdown.go:20-24` defines extracted markdown metadata as `Tags` plus `Property`; `internal/markdown/markdown.go:68-89` only wires the custom tag extension; `internal/markdown/markdown.go:324-386` extracts tags and properties but no mention metadata.
- `internal/markdown/extensions/tag.go:13-23` and the related tag parser/AST types are the only custom inline markdown extension path today.
- `proto/store/memo.proto:7-29` limits `MemoPayload` to `property`, `location`, and `tags`; there is no repeated mention field or structured mention metadata.
- `proto/store/inbox.proto:7-24` defines only `InboxMessage_MEMO_COMMENT`; `proto/api/v1/user_service.proto:592-679` defines only `UserNotification_MEMO_COMMENT`.
- `server/router/api/v1/user_service.go:1272-1312` lists notifications by filtering inbox rows to `InboxMessage_MEMO_COMMENT` only; `server/router/api/v1/user_service.go:1433-1524` converts only that message type into API notifications.
- `web/src/pages/Inboxes.tsx:19-114` and `web/src/components/Inbox/MemoCommentMessage.tsx` only render memo comment notifications; other notification types would currently be dropped.
- `server/router/api/v1/user_service.go:32-70` exposes `ListUsers` only to admins, and `store/user.go:59-74` plus `store/db/sqlite/user.go:88-175` support exact-match user filtering but no general search, ranking, or pagination for mention autocomplete.
- `server/router/api/v1/acl_config.go:20-27` whitelists `/memos.api.v1.UserService/SearchUsers`, but `proto/api/v1/user_service.proto:16-120` does not define a `SearchUsers` RPC and there is no server implementation.
- `web/src/components/MemoEditor/Editor/index.tsx:189-214`, `web/src/components/MemoEditor/Editor/useSuggestions.ts:28-158`, and `web/src/components/MemoEditor/Editor/TagSuggestions.tsx:10-49` provide a reusable textarea suggestion popup, but it is only instantiated for `#tag`.
- `web/src/components/MemoContent/index.tsx:53-136`, `web/src/utils/remark-plugins/remark-tag.ts:24-112`, and `web/src/components/MemoContent/Tag.tsx` parse and render `#tag` as a structured inline element; there is no `remarkMention` equivalent.
- `web/src/hooks/useUserQueries.ts:176-245` has `useListUsers()` for admin listing and `useUsersByNames()` for fetching known usernames one by one, but nothing that returns ranked candidates for an in-editor `@` query.
- `web/src/router/index.tsx:65-72` already routes public user profiles at `u/:username`, so inline mention rendering can target username-based profile URLs without inventing a new frontend route.
## Non-Goals
- Adding group mentions, team mentions, page mentions, or date mentions.
- Building a general “watch this memo/thread” subscription system beyond explicit mentions.
- Adding email, push, Slack, or webhook delivery for mentions in this issue.
- Redesigning memo visibility, access control, or per-user sharing semantics.
- Making old mentions follow username changes automatically.
- Redesigning the editor away from the current textarea-based implementation.
## Open Questions
- Which content surfaces are in scope for `@mention`? (default: top-level memos and memo comments, because both already share the same memo content pipeline)
- What mention token syntax should be recognized? (default: `@username` only, using canonical usernames rather than display names)
- Should edits trigger mention notifications after the initial create? (default: yes, but only for newly added mention targets compared with the memos previous mention set)
- What happens if someone types `@username` in content the target cannot access? (default: render the token as a mention in the authors view, but do not send a notification unless the target can already access the memo/comment under existing visibility rules)
- Should mentioning yourself create an inbox item? (default: no, because self-mentions do not require attention routing)
- Should the mention candidate API be public like `GetUser`, or authenticated like the editor? (default: authenticated only, because ranked user search is a broader directory-enumeration surface than fetching a known public profile)
## Scope
**L** — The work crosses markdown parsing, memo payload extraction, memo create/update side effects, inbox and notification protos, user search APIs, three SQL drivers, React editor autocomplete, markdown rendering, and inbox UI. The repository already contains adjacent pieces for tags and comment notifications, but `@mention` requires stitching several existing subsystems together rather than extending a single isolated module.
@@ -0,0 +1,69 @@
## References
- [Comments, mentions & reactions - Notion Help Center](https://www.notion.com/help/comments-mentions-and-reminders)
- [Notification settings - Notion Help Center](https://www.notion.com/help/notification-settings)
- [Mention a person or team - Confluence Cloud](https://support.atlassian.com/confluence-cloud/docs/mention-a-person-or-team/)
- [Comment on Coda docs - Coda Help](https://help.coda.io/hc/en-us/articles/39555917053069-Comment-on-Coda-docs)
- [Customize notifications from comments - Coda Help](https://help.coda.io/hc/en-us/articles/39555901119117-Customize-notifications-from-comments)
## Industry Baseline
`Comments, mentions & reactions - Notion Help Center` shows the most common editor-side behavior: typing `@` triggers real-time search, mentions can live inline in page bodies and comments, clicking an inbox item takes the user back to the exact context, and no notification is sent when the target cannot access the page. `Notification settings - Notion Help Center` also separates in-product inbox behavior from secondary delivery like desktop or email.
`Mention a person or team - Confluence Cloud` adds two useful guardrails for a collaborative editor: autocomplete suggestions appear directly from `@`, and notifications are intentionally deduplicated so people are notified on the first mention rather than on every repeated mention in the same page.
`Comment on Coda docs` and `Customize notifications from comments` show a narrower scope for mentions inside comments, but reinforce two patterns that matter for Memos: explicit `@` mentions are a distinct notification trigger from generic participation, and products often keep mention notifications separate from broader thread-subscription or owner-subscription rules.
Across these products, the default implementation is not “parse arbitrary display text and hope it matches a user.” The stable interaction is: search among valid workspace members, insert a canonical mention token, render it differently from plain text, and only notify when access and deduplication rules say the event is meaningful.
## Research Summary
Memos already has the right extension points to adopt that baseline without a storage redesign. The backend has a custom inline markdown extension pipeline for `#tag`, memo create and update both rebuild `MemoPayload`, and the inbox model already represents user-facing attention items. The frontend editor already has a trigger-character suggestion popup, the markdown renderer already recognizes custom inline nodes, and public user profiles are already routed by username.
The biggest mismatch is user discovery. The current `ListUsers` path is admin-only and exact-match oriented, while mention autocomplete needs a normal authenticated user search API that can return ranked candidates by username and display name. The second mismatch is notification shape: the inbox and API layers only understand memo-comment notifications today, so a mention feature cannot be expressed as a first-class notification without extending the inbox proto and inbox UI.
Research also suggests that Memos should stay narrower than Notion or Confluence. There is no existing concept of teams, group mentions, page mentions, or per-page ACLs. The codebase already treats usernames as the public user token and memo visibility as a coarse `PUBLIC/PROTECTED/PRIVATE` rule. The best fit is therefore person mentions only, keyed by canonical username, with notification rules that are access-aware and deduplicated across repeated edits.
## Design Goals
- Typing `@` in the memo editor or comment editor shows ranked, authenticated user candidates and inserts a canonical `@username` token on selection.
- The backend extracts mention targets from memo/comment content during create, update, and payload rebuild, and produces the same mention set for equivalent content across all supported databases.
- Mention notifications are created only for newly added targets, at most once per target per memo revision, and never for self-mentions or inaccessible private content.
- Memo content renders resolved mentions as interactive inline entities and degrades unresolved tokens to plain text.
- The inbox API and inbox UI expose mention notifications as a first-class type distinct from comment notifications.
- The design does not require a relational schema migration; it only extends existing proto-backed JSON payloads and server/frontend code paths.
## Non-Goals
- Adding group mentions, team mentions, page mentions, or date mentions.
- Building a generic watch/subscription system for memo activity.
- Sending mention notifications through email, push, Slack, or webhooks.
- Making mention references survive username changes automatically.
- Replacing the textarea editor with a richer block editor.
- Redesigning memo visibility or introducing user-level memo sharing.
## Proposed Design
Support only canonical `@username` mentions in this issue. The parser should recognize the same username token vocabulary that the API already accepts for public user names, instead of trying to match display names or arbitrary free text. This keeps mention authoring aligned with existing user resource naming and avoids ambiguous matches when multiple users share similar display names. Mention suggestions may show both display name and username, but the inserted source text remains `@username`.
Add a backend markdown mention extension parallel to the existing tag extension. Introduce `internal/markdown/ast.MentionNode`, `internal/markdown/parser.NewMentionParser()`, and `internal/markdown/extensions.MentionExtension`, then wire it into `internal/markdown/markdown.go` next to `TagExtension`. The mention parser should require a word boundary before `@` so email addresses and URLs do not become mentions, and it should normalize the captured token to lowercase before lookup because usernames are canonicalized that way in the API layer.
Extend `storepb.MemoPayload` with a repeated mention metadata field, for example `repeated Mention mentions`, where each item stores at least `username` and resolved `user_id`. The raw markdown remains the source of truth for author-visible text, but the payload becomes the normalized server-side mention set for diffing and notification decisions. This reuses the existing memo payload rebuild path and avoids reparsing memo bodies in multiple side-effect handlers. No SQL migration is required because memo payloads are already stored as proto-backed JSON blobs in each database driver.
Teach `memopayload.RebuildMemoPayload` to resolve mention metadata while rebuilding tags and properties. The extraction step should walk the markdown AST once, collect raw `@username` tokens, resolve them to active users via the store, deduplicate by `user_id`, and populate `memo.Payload.Mentions`. Unresolved usernames should not fail memo creation; they should simply be omitted from normalized mention metadata so the feature remains tolerant of free-typed text. This mirrors how the frontend can degrade unresolved tokens back to plain text.
Add a dedicated mention side-effect helper around memo create and update flows. On create, after the memo is persisted and the final payload is available, compute the normalized mentioned user set from `memo.Payload.Mentions` and create inbox items for allowed targets. On update, diff the previous and new normalized mention sets and only notify targets that were newly added in the latest saved revision. This follows the Confluence-style deduplication pattern and prevents repeated notifications when a memo is edited without changing its mention set. If a mention is removed and later re-added, it counts as newly added again and may generate a fresh inbox item.
Apply access and duplication rules before writing inbox rows. Self-mentions are ignored. For top-level memos, notify only when the target can already read the memo under current visibility rules. For comments, notify the mentioned user when they can read the comment context and are not already covered by the existing memo-comment notification to the parent memo owner for that same event. This keeps mention notifications meaningful and avoids sending an owner both a comment notification and a mention notification for the same comment creation unless future product requirements explicitly want both. For `PRIVATE` memos and `PRIVATE` comments, mentions remain author-visible text but do not generate inbox notifications for other users.
Extend inbox storage and API notifications with a dedicated mention type instead of overloading the existing comment type. Add `MEMO_MENTION` to `proto/store/inbox.proto` with a payload that can represent both top-level memos and comments, such as `memo_id` plus optional `related_memo_id`. Mirror that in `proto/api/v1/user_service.proto` with `UserNotification_MEMO_MENTION` and `MemoMentionPayload`. Reuse the current notification conversion pattern in `server/router/api/v1/user_service.go`: resolve memo names from stored IDs, return a first-class mention payload, and let the inbox page render a separate mention card component. This keeps the notification center composable as new activity types appear.
Add an authenticated user-search endpoint specifically for mention autocomplete. The repository already has a stale public-method placeholder for `SearchUsers`, but no proto or handler. Define `SearchUsers` in `proto/api/v1/user_service.proto`, remove it from the public ACL list, and implement it in `server/router/api/v1/user_service.go` as an authenticated RPC that accepts a short query string plus page size. Extend `store.FindUser` with search-oriented fields and implement driver-specific case-insensitive matching in SQLite, MySQL, and PostgreSQL over `username` and `nickname`, ordered by exact username match, username prefix, nickname prefix, then a stable fallback. This produces a usable editor candidate list without reusing the admin-only `ListUsers` contract.
Implement frontend mention suggestions by reusing the existing generic textarea suggestion system. Add a `MentionSuggestions` component beside `TagSuggestions`, hook it into `web/src/components/MemoEditor/Editor/index.tsx`, and back it with a debounced `useSearchUsers(query)` hook. The popup should render avatar, display name, and `@username`, while selection inserts `@username ` exactly. Because `useSuggestions` currently operates on local item arrays, it can stay generic if the mention hook owns the remote query and passes the current ranked results down as `items`.
Implement frontend mention rendering with a dedicated markdown plugin and component instead of trying to infer mentions from links or plain spans. Add `remarkMention` beside `remarkTag`, a `Mention` inline component beside `Tag`, and a mention type guard in `web/src/types/markdown.ts`. The renderer should link resolved mentions to `/u/:username`, show display name or username with avatar-based affordance when lookup data is available, and render unresolved mention text non-interactively. To avoid N-per-mention network fetches, `MemoContent` should collect mentioned usernames from content and hydrate them through the existing `useUsersByNames()` hook once per memo render tree.
Render mention notifications as their own inbox card. Reuse the existing `MemoCommentMessage` pattern, but resolve the source memo/comment and optional related memo from the `MemoMentionPayload`. The card should show who mentioned the user, in what memo or comment, a short snippet, and navigate to the relevant memo detail on click. `web/src/pages/Inboxes.tsx` should switch on both `MEMO_COMMENT` and `MEMO_MENTION` so the inbox can grow by type without silently discarding new notifications.
Do not solve username drift in this issue. If a user later changes username, existing raw markdown still contains the old `@username` text, and rebuilt payload metadata will stop resolving unless the old token still matches a live username. This is acceptable for the current scope because username-history and alias resolution are already out of scope elsewhere in the codebase. The alternative of storing opaque mention IDs in source markdown or adding a username-alias subsystem was rejected because it turns a contained collaboration feature into a broader identity migration project.
@@ -0,0 +1,37 @@
## Execution Log
### T1: Add backend mention parsing and payload extraction
**Status**: Completed
**Files Changed**: `internal/markdown/ast/mention.go`, `internal/markdown/parser/mention.go`, `internal/markdown/extensions/mention.go`, `internal/markdown/markdown.go`, `internal/markdown/renderer/markdown_renderer.go`, `server/runner/memopayload/runner.go`, `server/router/api/v1/memo_service.go`, `server/router/api/v1/v1.go`, `server/router/api/v1/test/test_helper.go`, `internal/markdown/markdown_test.go`
**Validation**: `go test ./internal/markdown` — PASS
**Path Corrections**: `RebuildMemoPayload` needed `context + store` so mention resolution could happen during payload rebuild.
**Deviations**: None
### T2: Add mention notifications and user search APIs
**Status**: Completed
**Files Changed**: `proto/store/memo.proto`, `proto/store/inbox.proto`, `proto/api/v1/user_service.proto`, `server/router/api/v1/user_service.go`, `server/router/api/v1/connect_services.go`, `server/router/api/v1/acl_config.go`, `server/router/api/v1/acl_config_test.go`, `server/router/api/v1/memo_mention_helpers.go`, `store/user.go`, `store/db/sqlite/user.go`, `store/db/postgres/user.go`, `store/db/mysql/user.go`, `server/router/api/v1/test/user_notification_test.go`, `server/router/api/v1/test/user_search_test.go`
**Validation**: `go test ./server/router/api/v1/...` — PASS
**Path Corrections**: Unknown legacy inbox message types are filtered server-side to keep unread counts aligned with rendered cards.
**Deviations**: None
### T3: Add frontend mention autocomplete, rendering, and inbox UI
**Status**: Completed
**Files Changed**: `web/src/components/MemoEditor/Editor/MentionSuggestions.tsx`, `web/src/components/MemoEditor/Editor/index.tsx`, `web/src/components/MemoEditor/Editor/useSuggestions.ts`, `web/src/hooks/useUserQueries.ts`, `web/src/utils/remark-plugins/remark-mention.ts`, `web/src/components/MemoContent/MentionContext.tsx`, `web/src/components/MemoContent/Mention.tsx`, `web/src/components/MemoContent/index.tsx`, `web/src/components/MemoContent/ConditionalComponent.tsx`, `web/src/types/markdown.ts`, `web/src/components/Inbox/MemoMentionMessage.tsx`, `web/src/pages/Inboxes.tsx`
**Validation**: `pnpm lint && pnpm build` — PASS
**Path Corrections**: Editor autocomplete reused the existing generic suggestion hook by exposing the live query rather than duplicating keyboard navigation logic.
**Deviations**: None
### T4: Regenerate code and validate the feature
**Status**: Completed
**Files Changed**: `proto/gen/**`, `web/src/types/proto/**`
**Validation**: `buf generate` — PASS; `go test ./internal/markdown ./server/router/api/v1/...` — PASS; `pnpm lint` — PASS; `pnpm build` — PASS
**Path Corrections**: None
**Deviations**: None
## Completion Declaration
All tasks completed successfully
+104
View File
@@ -0,0 +1,104 @@
## Task List
### Task Index
T1: Add backend mention parsing and payload extraction [M] — T2: Add mention notifications and user search APIs [L] — T3: Add frontend mention autocomplete, rendering, and inbox UI [L] — T4: Regenerate code and validate the feature [M]
### T1: Add backend mention parsing and payload extraction [M]
**Objective**: Parse `@username` tokens into structured mention metadata during memo payload rebuilds.
**Size**: M
**Files**:
- Create: `internal/markdown/ast/mention.go`
- Create: `internal/markdown/parser/mention.go`
- Create: `internal/markdown/extensions/mention.go`
- Modify: `internal/markdown/markdown.go`
- Modify: `internal/markdown/renderer/markdown_renderer.go`
- Modify: `server/runner/memopayload/runner.go`
- Modify: `server/router/api/v1/memo_service.go`
- Test: `internal/markdown/markdown_test.go`
**Implementation**:
1. Add mention AST/parser/extension parallel to the existing tag implementation.
2. Extend extracted markdown data and `MemoPayload` rebuild to collect normalized mentions and resolve them to users.
3. Update memo create/update and background payload rebuild paths to use the new mention-aware payload builder.
**Boundaries**: Do not add a relational schema migration.
**Dependencies**: None
**Expected Outcome**: Memo payloads carry normalized mention metadata rebuilt from markdown content.
**Validation**: `go test ./internal/markdown` — expected `ok`
### T2: Add mention notifications and user search APIs [L]
**Objective**: Expose mention-aware APIs and create inbox items for newly added mentions.
**Size**: L
**Files**:
- Modify: `proto/store/memo.proto`
- Modify: `proto/store/inbox.proto`
- Modify: `proto/api/v1/user_service.proto`
- Modify: `server/router/api/v1/user_service.go`
- Modify: `server/router/api/v1/connect_services.go`
- Modify: `server/router/api/v1/acl_config.go`
- Modify: `server/router/api/v1/acl_config_test.go`
- Create: `server/router/api/v1/memo_mention_helpers.go`
- Modify: `store/user.go`
- Modify: `store/db/sqlite/user.go`
- Modify: `store/db/postgres/user.go`
- Modify: `store/db/mysql/user.go`
- Test: `server/router/api/v1/test/user_notification_test.go`
- Test: `server/router/api/v1/test/user_search_test.go`
**Implementation**:
1. Extend proto contracts with `MemoPayload.mentions`, `InboxMessage.MEMO_MENTION`, `UserNotification.MEMO_MENTION`, and `SearchUsers`.
2. Implement authenticated user search over username and nickname.
3. Add mention notification side effects for memo create/update/comment flows with diffing and duplicate suppression.
4. Convert inbox rows into either comment or mention notifications and filter unknown legacy types.
**Boundaries**: Do not add email/push/webhook mention delivery.
**Dependencies**: T1
**Expected Outcome**: Mentioned users receive inbox notifications and the editor has an API to fetch mention candidates.
**Validation**: `go test ./server/router/api/v1/...` — expected `ok`
### T3: Add frontend mention autocomplete, rendering, and inbox UI [L]
**Objective**: Let users insert mentions from the editor and render/read them in the UI.
**Size**: L
**Files**:
- Create: `web/src/components/MemoEditor/Editor/MentionSuggestions.tsx`
- Modify: `web/src/components/MemoEditor/Editor/index.tsx`
- Modify: `web/src/components/MemoEditor/Editor/useSuggestions.ts`
- Modify: `web/src/hooks/useUserQueries.ts`
- Create: `web/src/utils/remark-plugins/remark-mention.ts`
- Create: `web/src/components/MemoContent/MentionContext.tsx`
- Create: `web/src/components/MemoContent/Mention.tsx`
- Modify: `web/src/components/MemoContent/index.tsx`
- Modify: `web/src/components/MemoContent/ConditionalComponent.tsx`
- Modify: `web/src/types/markdown.ts`
- Create: `web/src/components/Inbox/MemoMentionMessage.tsx`
- Modify: `web/src/pages/Inboxes.tsx`
**Implementation**:
1. Add `@` autocomplete backed by `SearchUsers`.
2. Add markdown mention parsing/rendering and hydrate mentioned users once per memo render.
3. Add a dedicated inbox card for memo mention notifications.
**Boundaries**: Do not redesign the textarea editor.
**Dependencies**: T2
**Expected Outcome**: Users can insert, see, and open mentions from memo content and inbox notifications.
**Validation**: `pnpm lint && pnpm build` — expected success
### T4: Regenerate code and validate the feature [M]
**Objective**: Regenerate generated code and verify backend/frontend behavior.
**Size**: M
**Files**:
- Modify: `proto/gen/**`
- Modify: `web/src/types/proto/**`
**Implementation**:
1. Run `buf generate` after proto changes.
2. Re-run focused Go tests and frontend lint/build.
**Boundaries**: Do not broaden into unrelated CI cleanup.
**Dependencies**: T1, T2, T3
**Expected Outcome**: Generated code matches the new APIs and validations pass.
**Validation**: `buf generate`, `go test ./internal/markdown ./server/router/api/v1/...`, `pnpm lint`, `pnpm build`
## Out-of-Scope Tasks
- Group/team mentions
- Username alias migration
- Email or push delivery for mentions
- Watch/subscription semantics beyond explicit mentions
@@ -0,0 +1,70 @@
## Background & Context
SSO sign-in in memos currently treats the IdP-provided identifier as the local username. The identifier value comes from the OAuth2 UserInfo claim named in `FieldMapping.identifier`, while local usernames are validated by `validateUsername` against `base.UIDMatcher`. Real IdPs frequently emit identifiers such as email addresses, opaque subject IDs, or provider-specific account IDs that are valid authentication subjects but are not valid memos usernames.
The existing issue artifacts under `docs/plans/2026-04-21-sso-user-identity-linkage/` already scope a persistent linkage between SSO identities and local users. A broader review of upstream open source schemas now shows that similar systems converge on separating external identity from the local user row, but do not converge on one universal table name or one exact column set. That difference matters because the implementation problem is narrower than "copy one upstream schema exactly" and broader than "pick any new table name locally."
## Issue Statement
The SSO sign-in path in `server/router/api/v1/auth_service.go` resolves and creates users from `userInfo.Identifier` through `User.Username`, and no provider-scoped external identity record exists to resolve a local user independently of that username; as a result, provider-issued identifiers that are valid authentication subjects but invalid memos usernames fail the sign-in path, and the future persistence model still requires an explicit schema decision among several verified upstream identity-link patterns.
## Current State
**Sign-in path**`server/router/api/v1/auth_service.go:124-173`
- Lines 124-132 apply `identifier_filter` to `userInfo.Identifier`.
- Lines 135-137 call `GetUser(FindUser{Username: &userInfo.Identifier})`.
- Lines 151-159 create a new `store.User` with `Username: userInfo.Identifier`.
- No persistent linkage record is read or written during SSO sign-in.
**Username validation**`server/router/api/v1/user_resource_name.go:33-38`
- `validateUsername` rejects empty strings, fully numeric usernames, and values that fail `base.UIDMatcher`.
- `base.UIDMatcher` is defined in `internal/base/resource_name.go:5-6` as `^[a-zA-Z0-9]([a-zA-Z0-9-]{0,34}[a-zA-Z0-9])?$`.
**User model**`store/user.go:26-77`
- `store.User` contains `Username`, `Email`, `Nickname`, `AvatarURL`, and other local account fields.
- `store.FindUser` supports lookup by `ID`, `Username`, `Email`, and related filters.
- No external identity field exists on the user model.
**Current database schema**`store/migration/sqlite/LATEST.sql:9-79`
- `user` table (`lines 10-22`) stores `username` as a unique column and has no external identity column.
- `idp` table (`lines 72-79`) stores `uid` as the stable identifier for an IdP instance.
- The latest checked-in migration version is `0.27` under all three backends (`store/migration/sqlite/0.27`, `store/migration/postgres/0.27`, `store/migration/mysql/0.27`).
**IdP user info mapping**`internal/idp/idp.go:3-8`, `internal/idp/oauth2/oauth2.go:105-129`
- `IdentityProviderUserInfo` carries `Identifier`, `DisplayName`, `Email`, and `AvatarURL`.
- `Identifier` is loaded from the configured claim and is required to be non-empty.
- `DisplayName` falls back to `Identifier` when not mapped.
**No existing linkage persistence**
- No `identity`, `identities`, `user_identity`, `external_login_user`, or similar structure exists anywhere under `store/`.
## Non-Goals
- Changing `UIDMatcher` or `validateUsername`.
- Changing how `FieldMapping` maps OAuth2 claims into `IdentityProviderUserInfo`.
- Changing how password-based local sign-in works.
- Changing `identifier_filter` behavior.
- Supporting IdP types other than `OAUTH2` in this issue.
- Providing UI or API surfaces for linking or unlinking external identities.
- Migrating or renaming existing usernames already stored in `user`.
- Automatically linking pre-existing users whose current `User.Username` happens to match an IdP identifier.
- Adding SCIM, directory sync, or per-group / multi-tenant IdP scoping.
- Storing provider access tokens or profile payloads unless a live memos code path requires them.
## Open Questions
1. When a new SSO user's `userInfo.Identifier` does not yield a valid username, what value is used as the initial `User.Username`? (default: derive from `DisplayName`, then `Email`, then `Identifier`, normalizing to a valid username and retrying with a short suffix on collision)
2. Should an existing local user be linkable to an SSO identity after registration? (default: no — out of scope for this issue)
3. Should one local user be linkable to multiple external identities across different IdP instances? (default: yes — allow multiple rows per `user_id`, one per provider-scoped external identifier)
4. What schema vocabulary should represent the provider-scoped external identity record? (default: use table `user_identity` to match current memos table naming, with `provider` and `extern_uid` as the stored linkage fields)
5. Should the linkage schema store only lookup fields or also provider metadata such as tokens and raw profile data? (default: lookup fields only for this issue)
6. Should the linkage table be added across SQLite, PostgreSQL, and MySQL? (default: yes — mirror the existing migration strategy across all supported backends)
## Scope
**L** — the work still spans a new persistence structure across three database backends, store-layer types and driver implementations, sign-in path changes, username derivation behavior, and now an explicit design choice among several verified upstream schema patterns rather than a single assumed naming scheme.
@@ -0,0 +1,173 @@
## References
1. **GitLab `db/init_structure.sql` — `identities` table** (verified)
https://gitlab.com/gitlab-org/gitlab/-/raw/master/db/init_structure.sql?ref_type=heads
GitLab stores external identities in a separate `identities` table with fields including `extern_uid`, `provider`, `user_id`, `created_at`, and `updated_at`, plus provider-specific extensions such as `saml_provider_id`.
2. **Gitea `models/user/external_login_user.go` — `ExternalLoginUser`** (verified)
https://raw.githubusercontent.com/go-gitea/gitea/main/models/user/external_login_user.go
Gitea persists external account links separately from the user row. The core linkage fields are `ExternalID`, `LoginSourceID`, and `UserID`, with optional provider metadata and tokens.
3. **Discourse `app/models/user_associated_account.rb` — `user_associated_accounts`** (verified)
https://raw.githubusercontent.com/discourse/discourse/main/app/models/user_associated_account.rb
Discourse uses a dedicated association table with `provider_name`, `provider_uid`, `user_id`, timestamps, and JSONB metadata. It enforces uniqueness on both `(provider_name, provider_uid)` and `(provider_name, user_id)`.
4. **Keycloak `FederatedIdentityEntity.java` — `FEDERATED_IDENTITY`** (verified)
https://raw.githubusercontent.com/keycloak/keycloak/main/model/jpa/src/main/java/org/keycloak/models/jpa/entities/FederatedIdentityEntity.java
Keycloak models brokered identities separately with `USER_ID`, `IDENTITY_PROVIDER`, `FEDERATED_USER_ID`, `FEDERATED_USERNAME`, `REALM_ID`, and `TOKEN`, using provider-scoped lookup queries rather than local username lookup.
5. **Immich `user.table.ts` and initial migration — `users.oauthId`** (verified)
https://raw.githubusercontent.com/immich-app/immich/main/server/src/schema/tables/user.table.ts
https://raw.githubusercontent.com/immich-app/immich/main/server/src/schema/migrations/1744910873969-InitialMigration.ts
Immich stores a single `oauthId` column directly on the `users` table instead of a separate linkage table.
6. **Mattermost `server/public/model/user.go` — `AuthData` and `AuthService` on `User`** (verified)
https://raw.githubusercontent.com/mattermost/mattermost/master/server/public/model/user.go
Mattermost stores external-auth linkage directly on the user model through `AuthData` and `AuthService`.
## Industry Baseline
There is no single universal table name for SSO identity linkage across open source systems. The consistent pattern is structural rather than nominal: systems that support multiple external providers or explicit account linking separate the external identity from the local username and from the core user row.
Three recurring schema families appear in the references:
- **Provider-scoped identity-link table**. GitLab `identities` and Gitea `ExternalLoginUser` both persist a provider discriminator, an external identifier, and a local `user_id` in a separate structure. This is the most direct fit when one local user may be linked to multiple IdPs.
- **Association table with richer metadata**. Discourse `user_associated_accounts` uses the same provider-plus-external-id pattern, but also stores provider payloads and enforces one account per provider per user.
- **User-row coupling**. Immich and Mattermost place the external identifier on the user row itself. This minimizes schema surface area, but it ties the user record to one external binding shape and reduces flexibility when multiple providers or multiple linked identities are in scope.
Keycloak's `FEDERATED_IDENTITY` falls in the separate-table family as well, but introduces an additional realm scope and stores broker-specific metadata because Keycloak is itself an identity broker rather than an application with a local username model.
Known trade-offs:
- Separate tables add one extra lookup during sign-in compared with `GetUser(Username)`, but they avoid coupling authentication subjects to user-facing usernames.
- Richer association tables support future linking, unlinking, and metadata sync, but they increase write paths and retention of provider data.
- User-row columns are simpler for one-provider or one-link systems, but they do not fit a product that already supports multiple configured IdP instances.
## Research Summary
- GitLab, Gitea, Discourse, and Keycloak all separate the external identity record from the local username.
- The recurring core fields are a **provider scope**, an **external subject/UID**, and a **local user ID**. Exact names vary: `provider`, `login_source_id`, `provider_name`, `identity_provider`, `extern_uid`, `external_id`, `provider_uid`, `federated_user_id`.
- Table naming is not standardized across projects. `identities` is common and recognizable, but `external_login_user`, `user_associated_accounts`, and `FEDERATED_IDENTITY` are also established patterns.
- Single-column user-row designs such as Immich `oauthId` and Mattermost `AuthData` / `AuthService` are simpler, but they align with products that bind one external identity shape directly to the user row rather than a product that already has multiple `idp` records.
- For memos, the verified references support a provider-scoped link table and do not support continuing to use `User.Username` as the external identity lookup key. They also suggest that `provider` and `extern_uid` are clearer linkage-field names than repo-specific names like `idp_id`, even if the table name itself follows memos naming conventions.
## Design Goals
1. **G1 — Username-independent lookup**: SSO sign-in resolves an existing user without requiring `userInfo.Identifier` to pass `validateUsername`. Verifiable: a sign-in flow with `Identifier = "jane@example.com"` or an opaque subject string reaches user lookup through the linkage table, not through `FindUser{Username: ...}`.
2. **G2 — Provider-scoped uniqueness**: Two configured IdP instances may issue the same external identifier string without colliding. Verifiable: uniqueness is enforced on the pair `(provider, extern_uid)`, not on `extern_uid` alone.
3. **G3 — No new external-auth column on `user`**: The local `user` table remains a local account record rather than the storage site for external identity subjects. Verifiable: migration files do not add `oauth_id`, `auth_data`, `provider_uid`, or similar columns to `user`.
4. **G4 — Repo-aligned table naming with reference-aligned linkage fields**: The new linkage schema follows memos table naming conventions while using linkage field names that map directly to upstream patterns. Verifiable: the design uses table `user_identity` together with fields `provider` and `extern_uid`.
5. **G5 — Minimal persistence surface for this issue**: The linkage record stores lookup fields required by sign-in and excludes provider payloads that no current memos code path reads. Verifiable: the initial schema contains no token, JSON payload, or raw-profile columns.
## Non-Goals
All non-goals from `definition.md` apply. Additionally:
- Matching GitLab, Gitea, Discourse, or Keycloak field-for-field beyond the linkage concepts required by memos.
- Adding SCIM-, SAML-, or realm-specific columns such as Keycloak `REALM_ID` or GitLab `saml_provider_id`.
- Enforcing a one-provider-per-user rule like Discourse's `(provider_name, user_id)` uniqueness.
- Storing provider tokens, raw payloads, or synchronization metadata in the initial linkage table.
## Proposed Design
### 1. Use a separate `user_identity` table
Adopt the separate-table family used by GitLab `identities`, Gitea `ExternalLoginUser`, Discourse `user_associated_accounts`, and Keycloak `FEDERATED_IDENTITY`, while keeping the stored fields limited to what memos currently needs for sign-in (G1, G2, G3, G5). The table name should follow memos' existing singular / relationship-style naming pattern rather than copying GitLab's pluralized table name directly (G4).
Proposed logical schema:
```sql
CREATE TABLE user_identity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
provider TEXT NOT NULL, -- stores idp.uid
extern_uid TEXT NOT NULL,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
UNIQUE (provider, extern_uid)
);
CREATE INDEX user_identity_user_id_idx ON user_identity(user_id);
```
Naming decisions:
- **`user_identity`** follows the repo's current table naming pattern. Existing memos tables are singular or singular relationship tables such as `user`, `memo`, `memo_relation`, `memo_share`, and `idp`, so `user_identity` is more consistent locally than GitLab's plural `identities` (G4).
- **`provider`** is the stored `idp.uid`. This maps directly to GitLab `provider`, Keycloak `IDENTITY_PROVIDER`, Discourse `provider_name`, and Gitea's effective provider scope via `LoginSourceID`.
- **`extern_uid`** uses GitLab's term for the provider-issued subject and avoids coupling the schema to a specific protocol word such as `sub`, `email`, or `external_id`.
Rejected alternatives:
- **`identities`**: recognizable from GitLab, but inconsistent with the repo's current schema naming pattern.
- **`user_identity` with `idp_id`**: workable on naming, but less reference-aligned on the linkage fields than `provider` / `extern_uid`.
- **Add `oauth_id`-style column(s) to `user`**: simpler, but inconsistent with memos supporting multiple `idp` rows and weaker on G2 and G3, matching the Immich and Mattermost trade-off rather than the multi-provider references.
No foreign key is proposed from `provider` to `idp.uid` in the initial design. The current memos migrations do not rely heavily on cross-backend foreign-key behavior, and the linkage record must remain stable even if IdP rows are reworked at the application layer.
### 2. Add a dedicated store model and driver methods
Add a new store module for the linkage record instead of extending `store.User` (G3):
- `store/user_identity.go`
- `store/db/sqlite/user_identity.go`
- `store/db/postgres/user_identity.go`
- `store/db/mysql/user_identity.go`
The store type should mirror the lookup schema:
- `UserIdentity`: `ID`, `UserID`, `Provider`, `ExternUID`, `CreatedTs`, `UpdatedTs`
- `FindUserIdentity`: `Provider`, `ExternUID`, `UserID`
Only create and read operations are required in this issue. Update and delete paths are deferred because no current sign-in flow needs them (G5). The create path must surface provider/external-UID uniqueness conflicts so the sign-in flow can reconcile concurrent first-login races instead of leaving an unlinked local user behind.
### 3. Route SSO lookup through the linkage record
Change the `auth_service.SignIn` SSO branch so that, after `identifier_filter` passes, the flow is:
1. Resolve the current IdP instance from `idp.uid`.
2. Query `user_identity` by `(provider = idp.uid, extern_uid = userInfo.Identifier)`.
3. On hit, load the local user by `user_id`.
4. On miss, apply the existing registration gate, derive a valid local username from display-oriented fields, and execute local user creation plus `user_identity` insertion in a single transaction.
5. If the `user_identity` insert loses a race on the unique `(provider, extern_uid)` key, discard the provisional linkage result, re-read `user_identity`, and continue sign-in using the winning row's `user_id`.
This directly addresses the current runtime coupling in `server/router/api/v1/auth_service.go:135-169` and satisfies G1 and G2. `User.Username` becomes a local account attribute again instead of the SSO subject store, and the miss path becomes idempotent under concurrent first sign-ins for the same external identity.
### 4. Keep username derivation separate from external identity persistence
The initial local username for new SSO-created users should be derived from user-facing profile data rather than copied from `extern_uid`:
- first choice: `DisplayName`
- fallback: `Email`
- fallback: `Identifier`
Normalization and collision handling remain local username concerns, not identity-link concerns. This keeps the `user_identity` table focused on lookup semantics (G1, G5) and avoids implying that external identifiers must resemble usernames.
### 5. Versioned migrations across all three backends
Add a new migration version after `0.27` for SQLite, PostgreSQL, and MySQL. Update `LATEST.sql` for each backend to include the `user_identity` table and its `user_id` index.
The migrations should preserve the same logical fields across backends:
- `id`
- `user_id`
- `provider`
- `extern_uid`
- `created_ts`
- `updated_ts`
- unique key on `(provider, extern_uid)`
- secondary index on `user_id`
The implementation derived from these migrations should treat `(provider, extern_uid)` as both the lookup key and the concurrency guard for first login. A uniqueness conflict on that pair is a recoverable race outcome, not an unrecoverable error path.
### 6. Document the pattern families explicitly in the issue docs
Keep the issue docs explicit that memos is selecting one member of a broader family of established designs:
- GitLab / Gitea / Keycloak / Discourse: separate identity record
- Immich / Mattermost: user-row external-auth fields
That distinction matters because the design choice is not "copy GitLab exactly"; it is "use the multi-provider separate-identity family, keep memos-compatible table naming, and adopt upstream-aligned linkage fields where they improve recognizability" (G4).
@@ -0,0 +1,105 @@
## Execution Log
### T1: Add `user_identity` migrations + LATEST.sql updates
**Status**: Completed
**Files Changed**:
- Created: `store/migration/sqlite/0.28/00__user_identity.sql`
- Created: `store/migration/postgres/0.28/00__user_identity.sql`
- Created: `store/migration/mysql/0.28/00__user_identity.sql`
- Modified: `store/migration/sqlite/LATEST.sql`
- Modified: `store/migration/postgres/LATEST.sql`
- Modified: `store/migration/mysql/LATEST.sql`
**Validation**:
- `rg 'CREATE TABLE \`?user_identity\`?' store/migration` — PASS (hits in all 6 expected files).
- `rg 'UNIQUE \(\`?provider\`?, \`?extern_uid\`?\)' store/migration` — PASS (6 hits).
- `go build ./...` — PASS.
**Path Corrections**: None.
**Deviations**: None.
### T2: Add `store.UserIdentity` model, `Store` methods, and driver interface
**Status**: Completed
**Files Changed**:
- Created: `store/user_identity.go`
- Modified: `store/driver.go`
**Validation**:
- Interface-only build is expected to fail until T3T5; deferred compile check to T5.
- `rg 'CreateUserIdentity|ListUserIdentities' store/driver.go store/user_identity.go` — PASS (method declarations present in both files).
**Path Corrections**: None.
**Deviations**: None.
### T3: Implement SQLite driver for `user_identity`
**Status**: Completed
**Files Changed**:
- Created: `store/db/sqlite/user_identity.go`
**Validation**:
- `go build ./store/db/sqlite/...` — PASS.
**Path Corrections**: None.
**Deviations**: None.
### T4: Implement Postgres driver for `user_identity`
**Status**: Completed
**Files Changed**:
- Created: `store/db/postgres/user_identity.go`
**Validation**:
- `go build ./store/db/postgres/...` — PASS.
**Path Corrections**: None.
**Deviations**: None.
### T5: Implement MySQL driver for `user_identity`
**Status**: Completed
**Files Changed**:
- Created: `store/db/mysql/user_identity.go`
**Validation**:
- `go build ./...` — PASS (whole repo compiles; all drivers satisfy the `Driver` interface).
**Path Corrections**: None.
**Deviations**: None.
### T6: Add store-layer tests for `user_identity`
**Status**: Completed
**Files Changed**:
- Created: `store/test/user_identity_test.go`
**Validation**:
- `DRIVER=sqlite go test ./store/test/ -run TestUserIdentity -count=1 -v` — PASS:
- `TestUserIdentityCreateAndGet` — PASS
- `TestUserIdentityListByUserID` — PASS
- `TestUserIdentityUniqueConflict` — PASS
- `TestUserIdentitySameExternUIDDifferentProviders` — PASS
**Path Corrections**: None.
**Deviations**: None.
### T7: Add SSO username derivation helper
**Status**: Completed
**Files Changed**:
- Created: `server/router/api/v1/sso_username.go`
**Validation**:
- `go build ./server/router/api/v1/...` — PASS.
- `go vet ./server/router/api/v1/...` — PASS.
**Path Corrections**: None.
**Deviations**: None.
### T8: Route SSO sign-in through `user_identity` linkage
**Status**: Completed
**Files Changed**:
- Modified: `server/router/api/v1/auth_service.go`
- `SignIn` SSO branch now delegates user resolution to a new `resolveSSOUser` method.
- `resolveSSOUser` does: `user_identity` lookup → hit path (load user by linked `user_id`); miss path (registration gate → `deriveSSOUsername` → create user → create linkage → race recovery on unique(provider, extern_uid)).
- Added `isUserIdentityUniqueViolation` helper (string match on the three backends' unique-constraint error strings, matching the pattern in `memo_service.go:103105`).
**Validation**:
- `go build ./...` — PASS.
- `go vet ./...` — PASS.
- `DRIVER=sqlite go test ./store/test/ -run TestUserIdentity -count=1` — PASS (regression check).
**Path Corrections**:
- The plan pseudocode referenced `identityProvider.UID`; the actual protobuf type `storepb.IdentityProvider` exposes the field as `Uid`. Used `identityProvider.Uid` in the implementation. No semantic deviation.
**Deviations**: None.
## Completion Declaration
**All tasks completed successfully.**
@@ -0,0 +1,328 @@
## Task List
**Task Index**
> T1: Add `user_identity` migrations + LATEST.sql updates for all three backends [M] — T2: Add `store.UserIdentity` model and `Store` methods + driver interface [M] — T3: Implement SQLite driver for `user_identity` [M] — T4: Implement Postgres driver for `user_identity` [M] — T5: Implement MySQL driver for `user_identity` [M] — T6: Add store-layer tests for `user_identity` [M] — T7: Add SSO username derivation helper [M] — T8: Route SSO sign-in through `user_identity` linkage [L]
### T1: Add `user_identity` migrations + LATEST.sql updates [M]
**Objective**: Create the `user_identity` persistence structure across SQLite, Postgres, and MySQL, and reflect it in `LATEST.sql` for fresh installs (G1, G2, G3, G4, G5; design §1, §5).
**Size**: M (3 new migration files, 3 LATEST.sql edits; straightforward DDL).
**Files**:
- Create: `store/migration/sqlite/0.28/00__user_identity.sql`
- Create: `store/migration/postgres/0.28/00__user_identity.sql`
- Create: `store/migration/mysql/0.28/00__user_identity.sql`
- Modify: `store/migration/sqlite/LATEST.sql`
- Modify: `store/migration/postgres/LATEST.sql`
- Modify: `store/migration/mysql/LATEST.sql`
**Implementation**:
1. `store/migration/sqlite/0.28/00__user_identity.sql`:
```sql
CREATE TABLE user_identity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
provider TEXT NOT NULL,
extern_uid TEXT NOT NULL,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
UNIQUE (provider, extern_uid)
);
CREATE INDEX idx_user_identity_user_id ON user_identity(user_id);
```
2. `store/migration/postgres/0.28/00__user_identity.sql`: same logical schema with Postgres types — `id SERIAL PRIMARY KEY`, `user_id INTEGER NOT NULL`, `provider TEXT NOT NULL`, `extern_uid TEXT NOT NULL`, `created_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())`, `updated_ts BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())`, `UNIQUE(provider, extern_uid)`, plus `CREATE INDEX idx_user_identity_user_id ON user_identity(user_id);`. Include a 2-line header comment describing the table purpose (pattern-match `04__memo_share.sql`).
3. `store/migration/mysql/0.28/00__user_identity.sql`: same logical schema with MySQL syntax — backticked identifiers, `INT NOT NULL AUTO_INCREMENT PRIMARY KEY`, `VARCHAR(256)` for `provider`, `VARCHAR(256)` for `extern_uid` (so unique key fits within index limits), `BIGINT NOT NULL DEFAULT (UNIX_TIMESTAMP())` for timestamps, `UNIQUE(provider, extern_uid)`, plus `CREATE INDEX idx_user_identity_user_id ON user_identity(user_id);`.
4. Append a `-- user_identity` section to each `LATEST.sql` mirroring the corresponding migration file (schema only, same indentation style used by neighboring tables in that file).
**Boundaries**: Must NOT alter the `user` or `idp` tables; must NOT add FK from `user_identity.provider` to `idp.uid`; must NOT add columns beyond `id`, `user_id`, `provider`, `extern_uid`, `created_ts`, `updated_ts`.
**Dependencies**: None.
**Expected Outcome**: New migration files exist; `LATEST.sql` for each backend contains a `user_identity` table block and its `user_id` index.
**Validation**:
- `rg -n "CREATE TABLE user_identity" store/migration` — expects one hit per backend in both the 0.28 migration and `LATEST.sql` (6 hits total).
- `rg -n "UNIQUE ?\\(provider, extern_uid\\)" store/migration` — expects 6 hits total.
- `go build ./...` — expects PASS (no code changes affect the build; confirms no stray syntax issues).
---
### T2: Add `store.UserIdentity` model, `Store` methods, and driver interface [M]
**Objective**: Provide a Go-level abstraction for the `user_identity` record with create/read operations wired through `store.Driver` (design §2, G3, G5).
**Size**: M (one new store file, one interface edit; simple CRUD-shaped code).
**Files**:
- Create: `store/user_identity.go`
- Modify: `store/driver.go`
**Implementation**:
1. `store/user_identity.go`:
- Types:
```go
type UserIdentity struct {
ID int32
UserID int32
Provider string
ExternUID string
CreatedTs int64
UpdatedTs int64
}
type FindUserIdentity struct {
ID *int32
UserID *int32
Provider *string
ExternUID *string
}
```
- Store methods (thin passthroughs to driver):
```go
func (s *Store) CreateUserIdentity(ctx context.Context, create *UserIdentity) (*UserIdentity, error)
func (s *Store) ListUserIdentities(ctx context.Context, find *FindUserIdentity) ([]*UserIdentity, error)
func (s *Store) GetUserIdentity(ctx context.Context, find *FindUserIdentity) (*UserIdentity, error) // returns (nil, nil) on no match
```
- No update/delete methods in this issue (design §2: create/read only).
2. `store/driver.go`: extend the `Driver` interface with:
```go
// UserIdentity model related methods.
CreateUserIdentity(ctx context.Context, create *UserIdentity) (*UserIdentity, error)
ListUserIdentities(ctx context.Context, find *FindUserIdentity) ([]*UserIdentity, error)
```
`GetUserIdentity` in `store` can be implemented locally by calling `ListUserIdentities` with `Limit`-free semantics and returning the first row, matching the `GetMemoShare`/`GetIdentityProvider` pattern (no new driver method required for "get").
**Boundaries**: Must NOT add fields to `store.User` or `store.UpdateUser`; must NOT add update/delete methods.
**Dependencies**: None (T3T5 will satisfy the new interface methods).
**Expected Outcome**: `store.UserIdentity`, `FindUserIdentity`, and three `Store` methods exist; `Driver` interface declares the two new methods.
**Validation**:
- `go build ./store/...` — expects FAIL until T3T5 implement the interface on each driver. Record as expected; final pass comes at end of T5.
- `rg -n "CreateUserIdentity|ListUserIdentities" store/driver.go store/user_identity.go` — expects method declarations in both files.
---
### T3: Implement SQLite driver for `user_identity` [M]
**Objective**: Implement `CreateUserIdentity` and `ListUserIdentities` for SQLite so the interface declared in T2 is satisfied (design §2).
**Size**: M (one new driver file; mirrors existing `memo_share.go` patterns).
**Files**:
- Create: `store/db/sqlite/user_identity.go`
**Implementation**:
1. `CreateUserIdentity`:
- Insert columns `user_id`, `provider`, `extern_uid` using `?` placeholders.
- Use `RETURNING id, created_ts, updated_ts` to populate generated fields, same pattern as `store/db/sqlite/memo_share.go:24`.
- Return the passed-in `create` struct with generated fields populated, or the error from `QueryRowContext(...).Scan(...)` (unique-constraint violation surfaces to caller unchanged).
2. `ListUserIdentities`:
- `where := []string{"1 = 1"}`; append clauses for `find.ID`, `find.UserID`, `find.Provider`, `find.ExternUID` when non-nil.
- `SELECT id, user_id, provider, extern_uid, created_ts, updated_ts FROM user_identity WHERE ... ORDER BY id ASC`.
- Scan rows into `[]*store.UserIdentity`; return `[]*store.UserIdentity{}` on no rows (not nil).
**Boundaries**: Must NOT introduce transaction helpers, upsert semantics, or extra scan columns.
**Dependencies**: T2.
**Expected Outcome**: SQLite driver compiles and returns populated rows.
**Validation**:
- `go build ./store/db/sqlite/...` — expects PASS.
---
### T4: Implement Postgres driver for `user_identity` [M]
**Objective**: Mirror T3 for Postgres using `$N` placeholders and `SERIAL` semantics (design §2).
**Size**: M (one new driver file; mirrors `store/db/postgres/memo_share.go`).
**Files**:
- Create: `store/db/postgres/user_identity.go`
**Implementation**:
- Same shape as T3, but:
- Use `placeholder(n)` / `placeholders(n)` helpers from `store/db/postgres/common.go`.
- Insert stmt `INSERT INTO user_identity (user_id, provider, extern_uid) VALUES (...) RETURNING id, created_ts, updated_ts`.
- List query identical SQL shape to SQLite (no backticks in Postgres; match `memo_share.go` style).
**Boundaries**: Same as T3.
**Dependencies**: T2.
**Expected Outcome**: Postgres driver compiles.
**Validation**:
- `go build ./store/db/postgres/...` — expects PASS.
---
### T5: Implement MySQL driver for `user_identity` [M]
**Objective**: Mirror T3/T4 for MySQL, using `LastInsertId()` + re-read pattern (MySQL's driver does not support `RETURNING`; design §2).
**Size**: M (one new driver file; mirrors `store/db/mysql/memo_share.go`).
**Files**:
- Create: `store/db/mysql/user_identity.go`
**Implementation**:
- `CreateUserIdentity`:
- `INSERT INTO user_identity (user_id, provider, extern_uid) VALUES (?, ?, ?)` via `ExecContext`.
- Get `LastInsertId()`, re-fetch via `GetUserIdentity(... ID: &id)` helper (internal unexported `listUserIdentitiesByID` or reuse `ListUserIdentities` with `FindUserIdentity{ID: &id}` + take first result).
- Mirror `memo_share.go` error-handling style (return `errors.Errorf("failed to create user identity")` when re-fetch returns nil, like memo_share does).
- `ListUserIdentities`:
- Same shape as T3, using backticked column names (`` `user_id` ``, `` `provider` ``, `` `extern_uid` ``) and `?` placeholders, matching the MySQL idiom used in `memo_share.go`.
**Boundaries**: Same as T3.
**Dependencies**: T2.
**Expected Outcome**: MySQL driver compiles; full repo builds.
**Validation**:
- `go build ./...` — expects PASS (entire repo compiles with all drivers satisfying the `Driver` interface introduced in T2).
---
### T6: Add store-layer tests for `user_identity` [M]
**Objective**: Exercise create + read paths plus the `(provider, extern_uid)` uniqueness guard across the active driver (G2).
**Size**: M (one new test file; patterns match existing store tests).
**Files**:
- Create: `store/test/user_identity_test.go`
**Implementation**:
1. `TestUserIdentityCreateAndGet`:
- Create host user via `createTestingHostUser`.
- `CreateUserIdentity` with `UserID=user.ID`, `Provider="idp-uid-1"`, `ExternUID="jane@example.com"`.
- `GetUserIdentity` by `(Provider, ExternUID)` — assert match on `UserID`, `Provider`, `ExternUID`, non-zero `ID`, non-zero `CreatedTs`.
2. `TestUserIdentityListByUserID`:
- Create two identities under the same `UserID` with two different `Provider` values.
- `ListUserIdentities` by `UserID` — assert length 2.
3. `TestUserIdentityUniqueConflict`:
- Insert one row with `(Provider="idp-A", ExternUID="sub-1")`.
- Insert a second row with identical `(Provider, ExternUID)` for a different `UserID`.
- Assert the second `CreateUserIdentity` returns a non-nil error (detection via `err != nil`; do not assert message since error strings differ per backend).
4. `TestUserIdentitySameExternUIDDifferentProviders`:
- Insert `(Provider="idp-A", ExternUID="sub-1")` and `(Provider="idp-B", ExternUID="sub-1")` under the same or different users.
- Assert both inserts succeed (G2: uniqueness is scoped to the pair, not `extern_uid` alone).
**Boundaries**: Must NOT test SSO sign-in or auth service behavior; must NOT test migration contents beyond what `NewTestingStore` already executes.
**Dependencies**: T1T5.
**Expected Outcome**: All four tests pass against SQLite.
**Validation**:
- `go test ./store/test/ -run TestUserIdentity -count=1` — expects all 4 tests PASS.
---
### T7: Add SSO username derivation helper [M]
**Objective**: Produce a valid `User.Username` for new SSO-created users from profile fields, independent of `extern_uid` (design §4).
**Size**: M (one new file with helper + small unit test; self-contained logic).
**Files**:
- Create: `server/router/api/v1/sso_username.go`
**Implementation**:
1. `deriveSSOUsername(ctx context.Context, stores *store.Store, userInfo *idp.IdentityProviderUserInfo) (string, error)`:
- Build ordered candidate list: `[userInfo.DisplayName, userInfo.Email, userInfo.Identifier]`, skipping empty values.
- For each candidate:
1. `base := normalizeToUsername(candidate)`
2. If `validateUsername(base) == nil`:
- If no existing user with `Username=base` (via `stores.GetUser(&FindUser{Username: &base})`), return `base`.
- Else: try up to N=8 suffix retries `base + "-" + randomSuffix(6)`, where the trimmed base ensures total length ≤ 36. If a candidate passes `validateUsername` and is unique, return it.
3. If all candidates are exhausted: fall back to a purely random username `"user-" + randomSuffix(10)` validated via `validateUsername`; retry up to 5 times before returning an error.
4. `normalizeToUsername(s string) string`:
- ASCII-fold / lowercase.
- Replace every character not in `[a-zA-Z0-9]` with `-`.
- Collapse consecutive `-` into one `-`.
- Trim leading/trailing `-`.
- Truncate to 36 chars, then re-trim trailing `-` so the string still ends in alphanumeric.
- Return `""` if the result is empty or fully numeric (so the caller falls through to the next candidate).
5. Use `internal/util.RandomString` for the random suffix (already imported by `auth_service.go`).
**Boundaries**: Must NOT modify `validateUsername` or `base.UIDMatcher`; must NOT write to `user_identity` or `user` directly; must NOT call `CreateUser`.
**Dependencies**: None.
**Expected Outcome**: New file `server/router/api/v1/sso_username.go` containing the exported-for-package helper `deriveSSOUsername` and internal `normalizeToUsername`.
**Validation**:
- `go build ./server/router/api/v1/...` — expects PASS.
- `go vet ./server/router/api/v1/...` — expects PASS.
---
### T8: Route SSO sign-in through `user_identity` linkage [L]
**Objective**: Replace the `FindUser{Username: &userInfo.Identifier}` lookup and `Username: userInfo.Identifier` user creation with `user_identity`-backed lookup and derived-username user creation, satisfying G1 and G2 end-to-end (design §3).
**Size**: L (non-trivial branching logic: lookup, miss path, registration gate, race recovery).
**Files**:
- Modify: `server/router/api/v1/auth_service.go`
**Implementation** (in `SignIn`, SSO branch, replacing current lines ~124173):
1. After `identifier_filter` check succeeds (existing `lines 124-133` unchanged), resolve the linkage:
```go
provider := identityProvider.Uid
externUID := userInfo.Identifier
existingIdentity, err := s.Store.GetUserIdentity(ctx, &store.FindUserIdentity{
Provider: &provider,
ExternUID: &externUID,
})
// error handling → codes.Internal
```
2. **Hit path**: if `existingIdentity != nil`, load `s.Store.GetUser(ctx, &store.FindUser{ID: &existingIdentity.UserID})`; set `existingUser`; skip creation.
3. **Miss path**: gate on `instanceGeneralSetting.DisallowUserRegistration` (reuse existing flow at current lines 143149), then:
1. `username, err := deriveSSOUsername(ctx, s.Store, userInfo)` — from T7. `codes.Internal` on error.
2. Generate random password + bcrypt hash (unchanged from current lines 160168).
3. `user, err := s.Store.CreateUser(ctx, &store.User{Username: username, Role: store.RoleUser, Nickname: userInfo.DisplayName, Email: userInfo.Email, AvatarURL: userInfo.AvatarURL, PasswordHash: string(passwordHash)})`.
4. `_, err := s.Store.CreateUserIdentity(ctx, &store.UserIdentity{UserID: user.ID, Provider: provider, ExternUID: externUID})`.
5. **Race recovery**: if `CreateUserIdentity` returns an error whose message matches one of the known unique-constraint markers (`strings.Contains(err.Error(), "UNIQUE constraint failed")`, `"duplicate key"`, `"Duplicate entry")` — reusing the same pattern as `server/router/api/v1/memo_service.go:103105`):
- `_ = s.Store.DeleteUser(ctx, &store.DeleteUser{ID: user.ID})` (best-effort cleanup of the provisional local user).
- Re-read the winning `user_identity` via `s.Store.GetUserIdentity(ctx, &FindUserIdentity{Provider: &provider, ExternUID: &externUID})`; if still nil, return `codes.Internal` (should not happen under correct semantics).
- Load its user via `s.Store.GetUser(ctx, &FindUser{ID: &winner.UserID})`; set `existingUser`.
6. On any other `CreateUserIdentity` error: best-effort `DeleteUser` cleanup, then return `codes.Internal`.
7. On full success: set `existingUser = user`.
4. Leave the remainder of `SignIn` (row-status check, `doSignIn`, response construction) untouched.
**Boundaries**: Must NOT touch the password-credentials branch; must NOT modify `identifier_filter` logic; must NOT touch `doSignIn`, `SignOut`, or `RefreshToken`; must NOT add new fields to `SignInRequest`/`SignInResponse`.
**Dependencies**: T2, T3, T6 minimum for SQLite confidence; T7 for the derivation helper.
**Expected Outcome**:
- Sign-in with an IdP-issued identifier that fails `base.UIDMatcher` (e.g., `jane@example.com`) succeeds: a `user_identity` row is created, and the local `User.Username` is a derived valid username.
- Repeat sign-in for the same `(provider, extern_uid)` pair loads the same user by linkage, not by username.
- Two IdPs emitting the same `extern_uid` can each link to their own local users without colliding (G2).
**Validation**:
- `go build ./...` — expects PASS.
- `go vet ./...` — expects PASS.
- `go test ./store/test/ -run TestUserIdentity -count=1` — expects PASS (T6 regression check; ensures no store-layer drift).
## Out-of-Scope Tasks
The following are explicitly deferred per `definition.md` / `design.md` and will NOT be attempted during this execution:
- UI or API surfaces for linking/unlinking external identities.
- Update or delete paths for `user_identity` rows.
- Backfill / migration of existing users whose current `Username` matches an IdP identifier.
- Non-OAUTH2 IdP types.
- Protobuf or API changes to `SignInRequest`/`SignInResponse`.
- Adding foreign keys between `user_identity.provider` and `idp.uid`.
- Running PostgreSQL or MySQL integration tests locally (validation commands only cover SQLite, which is the default `DRIVER` in `store/test/store.go`).
-6
View File
@@ -1,6 +0,0 @@
# Setup
After deploying and running Memos in `prod` mode, you should create "host" user. There are two ways to do this:
1. Navigate to the Memos application URL, such as `http://localhost:5230`, and follow the prompts to create a username and password for the "host" user.
2. Use the command `memos setup --host-username=$USERNAME --host-password=$PASSWORD --mode=prod` to set up the host user. This method may be more convenient for deploying through Ansible or other provisioning softwares.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,738 @@
# Calendar-Date Memo Prefill — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** When the user picks a date in the activity calendar, the home memo editor pre-fills its `createTime`/`updateTime` to that date and exposes the existing `TimestampPopover` so the user can adjust before saving. Empty calendar dates also become clickable.
**Architecture:** Frontend-only. A new pure helper derives a `Date` from the `displayTime` filter; `PagedMemoList` reads `MemoFilterContext` and passes the derived `Date` into `MemoEditor` via a new `defaultCreateTime` prop; `MemoEditor` seeds its reducer state from the prop, renders the popover when the prop is set in create mode, and re-syncs on prop change. `CalendarCell` drops the `count > 0` gate on click handling.
**Tech Stack:** React 18 + TypeScript, Vite 7, Vitest + jsdom + @testing-library/react, Tailwind v4, react-router. State via React Context + `useReducer`.
**Spec:** `docs/superpowers/specs/2026-05-02-calendar-date-prefill-design.md`
---
## File map
**Created**
- `web/src/components/MemoEditor/utils/deriveDefaultCreateTime.ts` — pure helper `(filters, now?) => Date | undefined`.
- `web/tests/derive-default-create-time.test.ts` — Vitest unit tests for the helper.
- `web/tests/calendar-cell-empty-clickable.test.tsx` — RTL test that count=0 in-month cells are clickable.
**Modified**
- `web/src/components/ActivityCalendar/CalendarCell.tsx` — drop `day.count > 0` gate from click/interactivity/tooltip.
- `web/src/components/MemoEditor/types/components.ts` — add `defaultCreateTime?: Date` to `MemoEditorProps`.
- `web/src/components/MemoEditor/hooks/useMemoInit.ts` — accept optional `defaultCreateTime`; in create mode, dispatch `SET_TIMESTAMPS` to seed `{ createTime, updateTime }`.
- `web/src/components/MemoEditor/index.tsx` — accept the new prop, pass it to `useMemoInit`, add a `useEffect` that re-syncs timestamps when the prop changes in create mode, render `TimestampPopover` when `(!memo && state.timestamps.createTime)`.
- `web/src/components/PagedMemoList/PagedMemoList.tsx` — read `useMemoFilterContext`, derive `defaultCreateTime`, pass to `<MemoEditor>` at line ~155.
---
## Task 1: Pure helper `deriveDefaultCreateTimeFromFilters`
**Files:**
- Create: `web/src/components/MemoEditor/utils/deriveDefaultCreateTime.ts`
- Test: `web/tests/derive-default-create-time.test.ts`
The helper takes the `filters` array from `MemoFilterContext` plus an injectable `now`, finds any `displayTime` filter (value format `YYYY-MM-DD`, local-date — produced by `useDateFilterNavigation` which forwards the `dayjs().format("YYYY-MM-DD")` string from `CalendarDayCell.date`), and returns a `Date` of `selected_date + now's hh:mm:ss`. Returns `undefined` if no `displayTime` filter or the value is malformed.
- [ ] **Step 1: Write the failing tests**
Create `web/tests/derive-default-create-time.test.ts`:
```ts
import { describe, expect, it } from "vitest";
import { deriveDefaultCreateTimeFromFilters } from "@/components/MemoEditor/utils/deriveDefaultCreateTime";
import type { MemoFilter } from "@/contexts/MemoFilterContext";
describe("deriveDefaultCreateTimeFromFilters", () => {
const now = new Date(2026, 4, 2, 14, 32, 10); // 2026-05-02 14:32:10 local
it("returns undefined when no filters are set", () => {
expect(deriveDefaultCreateTimeFromFilters([], now)).toBeUndefined();
});
it("returns undefined when no displayTime filter is present", () => {
const filters: MemoFilter[] = [
{ factor: "tagSearch", value: "work" },
{ factor: "pinned", value: "true" },
];
expect(deriveDefaultCreateTimeFromFilters(filters, now)).toBeUndefined();
});
it("merges the displayTime date with the current local hh:mm:ss", () => {
const filters: MemoFilter[] = [{ factor: "displayTime", value: "2025-05-01" }];
const result = deriveDefaultCreateTimeFromFilters(filters, now);
expect(result).toBeDefined();
expect(result!.getFullYear()).toBe(2025);
expect(result!.getMonth()).toBe(4); // May (0-indexed)
expect(result!.getDate()).toBe(1);
expect(result!.getHours()).toBe(14);
expect(result!.getMinutes()).toBe(32);
expect(result!.getSeconds()).toBe(10);
});
it("ignores extra non-displayTime filters", () => {
const filters: MemoFilter[] = [
{ factor: "tagSearch", value: "work" },
{ factor: "displayTime", value: "2025-05-01" },
{ factor: "pinned", value: "true" },
];
const result = deriveDefaultCreateTimeFromFilters(filters, now);
expect(result?.getDate()).toBe(1);
});
it("returns undefined for a malformed YYYY-MM-DD value", () => {
const cases: MemoFilter[][] = [
[{ factor: "displayTime", value: "not-a-date" }],
[{ factor: "displayTime", value: "2025-13-40" }],
[{ factor: "displayTime", value: "" }],
[{ factor: "displayTime", value: "2025-5-1" }], // single-digit month/day
];
for (const filters of cases) {
expect(deriveDefaultCreateTimeFromFilters(filters, now)).toBeUndefined();
}
});
it("uses real `new Date()` when `now` is omitted", () => {
const filters: MemoFilter[] = [{ factor: "displayTime", value: "2025-05-01" }];
const before = new Date();
const result = deriveDefaultCreateTimeFromFilters(filters);
const after = new Date();
expect(result).toBeDefined();
// Time-of-day should fall between before and after (within 1s tolerance).
const resultTimeOnly = result!.getHours() * 3600 + result!.getMinutes() * 60 + result!.getSeconds();
const beforeTimeOnly = before.getHours() * 3600 + before.getMinutes() * 60 + before.getSeconds();
const afterTimeOnly = after.getHours() * 3600 + after.getMinutes() * 60 + after.getSeconds();
// Handle midnight rollover by allowing any value if before > after.
if (beforeTimeOnly <= afterTimeOnly) {
expect(resultTimeOnly).toBeGreaterThanOrEqual(beforeTimeOnly);
expect(resultTimeOnly).toBeLessThanOrEqual(afterTimeOnly);
}
});
});
```
- [ ] **Step 2: Run tests to verify they fail**
Run: `cd web && pnpm test derive-default-create-time`
Expected: FAIL — module `@/components/MemoEditor/utils/deriveDefaultCreateTime` does not exist.
- [ ] **Step 3: Implement the helper**
Create `web/src/components/MemoEditor/utils/deriveDefaultCreateTime.ts`:
```ts
import type { MemoFilter } from "@/contexts/MemoFilterContext";
const DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
/**
* Derive a default `createTime` for a new memo from the active memo filters.
* If a `displayTime:YYYY-MM-DD` filter is present, returns that local date
* combined with `now`'s wall-clock hh:mm:ss. Returns undefined otherwise or
* when the filter value is malformed.
*/
export function deriveDefaultCreateTimeFromFilters(
filters: MemoFilter[],
now: Date = new Date(),
): Date | undefined {
const dateFilter = filters.find((f) => f.factor === "displayTime");
if (!dateFilter) return undefined;
const match = DATE_RE.exec(dateFilter.value);
if (!match) return undefined;
const year = Number(match[1]);
const month = Number(match[2]);
const day = Number(match[3]);
// Construct a local-time Date and verify the components round-trip
// (catches things like 2025-13-40 that JS would silently roll forward).
const candidate = new Date(year, month - 1, day, now.getHours(), now.getMinutes(), now.getSeconds());
if (
candidate.getFullYear() !== year ||
candidate.getMonth() !== month - 1 ||
candidate.getDate() !== day
) {
return undefined;
}
return candidate;
}
```
- [ ] **Step 4: Run tests to verify they pass**
Run: `cd web && pnpm test derive-default-create-time`
Expected: PASS — all 6 cases.
- [ ] **Step 5: Run lint**
Run: `cd web && pnpm lint`
Expected: PASS (TypeScript + Biome happy).
- [ ] **Step 6: Commit**
```bash
git add web/src/components/MemoEditor/utils/deriveDefaultCreateTime.ts web/tests/derive-default-create-time.test.ts
git commit -m "feat(memo-editor): add deriveDefaultCreateTimeFromFilters helper"
```
---
## Task 2: Make empty calendar cells clickable
**Files:**
- Modify: `web/src/components/ActivityCalendar/CalendarCell.tsx`
- Test: `web/tests/calendar-cell-empty-clickable.test.tsx`
`CalendarCell` currently gates `handleClick`, `isInteractive`, and `shouldShowTooltip` on `day.count > 0`. Drop those gates so any in-month cell is clickable when `onClick` is provided. Out-of-month cells (early-returned at line ~38) stay unclickable.
- [ ] **Step 1: Write the failing test**
Create `web/tests/calendar-cell-empty-clickable.test.tsx`:
```tsx
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { CalendarCell } from "@/components/ActivityCalendar/CalendarCell";
import type { CalendarDayCell } from "@/components/ActivityCalendar/types";
const makeDay = (overrides: Partial<CalendarDayCell> = {}): CalendarDayCell => ({
date: "2025-05-01",
label: "1",
count: 0,
isCurrentMonth: true,
isToday: false,
isSelected: false,
...overrides,
});
describe("CalendarCell empty-day clickability", () => {
it("fires onClick for an in-month day with count=0", () => {
const onClick = vi.fn();
render(<CalendarCell day={makeDay()} maxCount={5} tooltipText="May 1, 2025" onClick={onClick} />);
const button = screen.getByRole("button", { name: /May 1, 2025/ });
fireEvent.click(button);
expect(onClick).toHaveBeenCalledWith("2025-05-01");
});
it("renders an empty in-month day as interactive (tabIndex 0, not aria-disabled)", () => {
render(<CalendarCell day={makeDay()} maxCount={5} tooltipText="May 1, 2025" onClick={() => {}} />);
const button = screen.getByRole("button", { name: /May 1, 2025/ });
expect(button).toHaveAttribute("tabindex", "0");
expect(button).toHaveAttribute("aria-disabled", "false");
});
it("still renders a populated in-month day as interactive", () => {
const onClick = vi.fn();
render(<CalendarCell day={makeDay({ count: 3 })} maxCount={5} tooltipText="May 1, 2025" onClick={onClick} />);
fireEvent.click(screen.getByRole("button", { name: /May 1, 2025/ }));
expect(onClick).toHaveBeenCalledWith("2025-05-01");
});
it("does not render out-of-month days as interactive (no role=button)", () => {
render(
<CalendarCell
day={makeDay({ isCurrentMonth: false })}
maxCount={5}
tooltipText="May 1, 2025"
onClick={() => {}}
/>,
);
expect(screen.queryByRole("button")).toBeNull();
});
});
```
- [ ] **Step 2: Run test to verify it fails**
Run: `cd web && pnpm test calendar-cell-empty-clickable`
Expected: FAIL — first two tests fail because the empty cell currently has `tabindex="-1"`, `aria-disabled="true"`, and `onClick` is not invoked.
- [ ] **Step 3: Edit `CalendarCell.tsx` to drop the count gate**
Modify `web/src/components/ActivityCalendar/CalendarCell.tsx`. Three edits:
(a) Replace `handleClick`:
```tsx
const handleClick = () => {
if (onClick) {
onClick(day.date);
}
};
```
(b) Replace `isInteractive`:
```tsx
const isInteractive = Boolean(onClick);
```
(c) Replace `shouldShowTooltip`:
```tsx
const shouldShowTooltip = tooltipText && !disableTooltip;
```
Leave the out-of-month early return (`if (!day.isCurrentMonth) { ... }`) untouched — out-of-month cells remain non-buttons.
- [ ] **Step 4: Run test to verify it passes**
Run: `cd web && pnpm test calendar-cell-empty-clickable`
Expected: PASS — all 4 cases.
- [ ] **Step 5: Run the full test suite to catch regressions**
Run: `cd web && pnpm test`
Expected: PASS. The existing `activity-calendar-tooltip.test.ts` covers `getTooltipText` (a separate utility) and shouldn't be affected.
- [ ] **Step 6: Run lint**
Run: `cd web && pnpm lint`
Expected: PASS.
- [ ] **Step 7: Commit**
```bash
git add web/src/components/ActivityCalendar/CalendarCell.tsx web/tests/calendar-cell-empty-clickable.test.tsx
git commit -m "feat(activity-calendar): allow clicking empty in-month dates"
```
---
## Task 3: Add `defaultCreateTime` prop to `MemoEditorProps`
**Files:**
- Modify: `web/src/components/MemoEditor/types/components.ts`
Type-only change. No tests at this step — TypeScript compiler is the gate. Subsequent tasks consume the prop.
- [ ] **Step 1: Add the prop**
Modify `web/src/components/MemoEditor/types/components.ts`. Replace the `MemoEditorProps` interface (lines 616) with:
```ts
export interface MemoEditorProps {
className?: string;
cacheKey?: string;
placeholder?: string;
/** Existing memo to edit. When provided, the editor initializes from it without fetching. */
memo?: Memo;
parentMemoName?: string;
autoFocus?: boolean;
/**
* Default `createTime` for a *new* memo (create mode only). When set, the
* editor seeds both `createTime` and `updateTime` to this value and renders
* the timestamp popover so the user can adjust before saving. Tracked live:
* if the prop changes after mount, the editor's timestamps re-sync. Ignored
* in edit mode (when `memo` is set).
*/
defaultCreateTime?: Date;
onConfirm?: (memoName: string) => void;
onCancel?: () => void;
}
```
- [ ] **Step 2: Verify compilation**
Run: `cd web && pnpm lint`
Expected: PASS (no consumer changes yet, prop is optional).
- [ ] **Step 3: Commit**
```bash
git add web/src/components/MemoEditor/types/components.ts
git commit -m "feat(memo-editor): add defaultCreateTime prop type"
```
---
## Task 4: Seed editor timestamps in `useMemoInit` (create mode)
**Files:**
- Modify: `web/src/components/MemoEditor/hooks/useMemoInit.ts`
`useMemoInit` currently handles edit mode (`if (memo)`) by calling `memoService.fromMemo(memo)` and `actions.initMemo(...)`. In create mode it only restores cached content and sets default visibility — it never touches timestamps. Extend the create branch so that when `defaultCreateTime` is set, it dispatches `SET_TIMESTAMPS` with `{ createTime: defaultCreateTime, updateTime: defaultCreateTime }`. This handles the *initial mount* case.
- [ ] **Step 1: Update `UseMemoInitOptions` and `useMemoInit`**
Modify `web/src/components/MemoEditor/hooks/useMemoInit.ts`. Replace the entire file with:
```ts
import { useEffect, useRef, useState } from "react";
import type { Memo, Visibility } from "@/types/proto/api/v1/memo_service_pb";
import type { EditorRefActions } from "../Editor";
import { cacheService, memoService } from "../services";
import { useEditorContext } from "../state";
interface UseMemoInitOptions {
editorRef: React.RefObject<EditorRefActions | null>;
memo?: Memo;
cacheKey?: string;
username: string;
autoFocus?: boolean;
defaultVisibility?: Visibility;
defaultCreateTime?: Date;
}
export const useMemoInit = ({
editorRef,
memo,
cacheKey,
username,
autoFocus,
defaultVisibility,
defaultCreateTime,
}: UseMemoInitOptions) => {
const { actions, dispatch } = useEditorContext();
const initializedRef = useRef(false);
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
if (initializedRef.current) return;
initializedRef.current = true;
const key = cacheService.key(username, cacheKey);
if (memo) {
const initialState = memoService.fromMemo(memo);
cacheService.clear(key);
dispatch(actions.initMemo(initialState));
} else {
const cachedContent = cacheService.load(key);
if (cachedContent) {
dispatch(actions.updateContent(cachedContent));
}
if (defaultVisibility !== undefined) {
dispatch(actions.setMetadata({ visibility: defaultVisibility }));
}
if (defaultCreateTime) {
dispatch(actions.setTimestamps({ createTime: defaultCreateTime, updateTime: defaultCreateTime }));
}
}
if (autoFocus) {
setTimeout(() => editorRef.current?.focus(), 100);
}
setIsInitialized(true);
}, [memo, cacheKey, username, autoFocus, defaultVisibility, defaultCreateTime, actions, dispatch, editorRef]);
return { isInitialized };
};
```
Notes:
- The `defaultCreateTime` dependency is added to the effect's deps to satisfy the linter, but `initializedRef` ensures the body runs only once. Live re-sync after mount is handled by a separate effect in Task 5.
- Edit mode is unchanged — `defaultCreateTime` is intentionally ignored when `memo` is set.
- [ ] **Step 2: Verify compilation**
Run: `cd web && pnpm lint`
Expected: PASS.
- [ ] **Step 3: Commit**
```bash
git add web/src/components/MemoEditor/hooks/useMemoInit.ts
git commit -m "feat(memo-editor): seed timestamps from defaultCreateTime on init"
```
---
## Task 5: Wire `defaultCreateTime` through `MemoEditor` and render popover
**Files:**
- Modify: `web/src/components/MemoEditor/index.tsx`
Three changes:
1. Destructure `defaultCreateTime` from props.
2. Pass it into `useMemoInit`.
3. Add a `useEffect` that dispatches `setTimestamps` whenever `defaultCreateTime` changes after mount (live re-sync per design Q3-A). Skip when `memo` is set.
4. Update the popover render condition so it shows in create mode too when timestamps are seeded.
- [ ] **Step 1: Destructure the prop and pass it to `useMemoInit`**
In `web/src/components/MemoEditor/index.tsx`, update the `MemoEditorImpl` destructuring (around line 42):
```tsx
const MemoEditorImpl: React.FC<MemoEditorProps> = ({
className,
cacheKey,
memo,
parentMemoName,
autoFocus,
placeholder,
defaultCreateTime,
onConfirm,
onCancel,
}) => {
```
And update the `useMemoInit` call (around line 71):
```tsx
const { isInitialized } = useMemoInit({
editorRef,
memo,
cacheKey,
username: currentUser?.name ?? "",
autoFocus,
defaultVisibility,
defaultCreateTime,
});
```
- [ ] **Step 2: Add the live re-sync effect**
In the same file, add a new `useEffect` after `useMemoInit` (and after `useAutoSave`) that re-syncs timestamps when `defaultCreateTime` changes in create mode. Place it just before the existing `useEffect` that fetches AI settings (around line 80):
```tsx
// Live-sync the draft's createTime/updateTime to the calendar-derived prop.
// Only applies in create mode; edit mode owns its own timestamps. Runs after
// initial mount (the seed value is set in useMemoInit), and again whenever
// the prop changes — e.g., when the user picks a different calendar date
// while the editor is open.
useEffect(() => {
if (memo) return;
if (!isInitialized) return;
dispatch(
actions.setTimestamps({
createTime: defaultCreateTime,
updateTime: defaultCreateTime,
}),
);
}, [defaultCreateTime, memo, isInitialized, actions, dispatch]);
```
Notes:
- We pass `undefined` through when the prop becomes undefined (filter cleared) — this resets timestamps to undefined so the editor falls back to "server-stamped now" on save, exactly the pre-feature behavior.
- The `isInitialized` guard avoids racing with `useMemoInit`'s one-shot seed.
- [ ] **Step 3: Update the popover render condition**
In the same file, find the existing block (around line 294):
```tsx
{memoName && (
<div className="w-full -mb-1">
<TimestampPopover />
</div>
)}
```
Replace with:
```tsx
{(memoName || (!memo && state.timestamps.createTime)) && (
<div className="w-full -mb-1">
<TimestampPopover />
</div>
)}
```
Now the popover renders in edit mode (unchanged) AND in create mode whenever a default timestamp has been seeded.
- [ ] **Step 4: Verify compilation**
Run: `cd web && pnpm lint`
Expected: PASS.
- [ ] **Step 5: Run all tests**
Run: `cd web && pnpm test`
Expected: PASS (no editor-specific tests added; existing tests continue to pass).
- [ ] **Step 6: Commit**
```bash
git add web/src/components/MemoEditor/index.tsx
git commit -m "feat(memo-editor): live-sync timestamps and reveal popover from defaultCreateTime"
```
---
## Task 6: Wire calendar selection through `PagedMemoList`
**Files:**
- Modify: `web/src/components/PagedMemoList/PagedMemoList.tsx`
The home memo editor is rendered at line ~155 of `PagedMemoList.tsx`. Read the current `MemoFilterContext` filters, derive the `defaultCreateTime`, and pass it to `<MemoEditor>`. Wrap in `useMemo` so the reference stays stable when filters don't change (avoids re-firing the live-sync effect).
- [ ] **Step 1: Add the imports and derivation**
Modify `web/src/components/PagedMemoList/PagedMemoList.tsx`. Add to the existing imports near the top:
```tsx
import { useMemo } from "react";
import { useMemoFilterContext } from "@/contexts/MemoFilterContext";
import { deriveDefaultCreateTimeFromFilters } from "@/components/MemoEditor/utils/deriveDefaultCreateTime";
```
If `useMemo` is already imported from `react` in this file, merge into the existing import rather than duplicating.
Inside the component body (above the `children` JSX, near the top of the function), add:
```tsx
const { filters } = useMemoFilterContext();
const defaultCreateTime = useMemo(
() => deriveDefaultCreateTimeFromFilters(filters),
[filters],
);
```
- [ ] **Step 2: Pass the prop to `<MemoEditor>`**
Replace the existing line ~155:
```tsx
{showMemoEditor ? <MemoEditor className="mb-2" cacheKey="home-memo-editor" placeholder={t("editor.any-thoughts")} /> : null}
```
with:
```tsx
{showMemoEditor ? (
<MemoEditor
className="mb-2"
cacheKey="home-memo-editor"
placeholder={t("editor.any-thoughts")}
defaultCreateTime={defaultCreateTime}
/>
) : null}
```
- [ ] **Step 3: Verify compilation**
Run: `cd web && pnpm lint`
Expected: PASS.
- [ ] **Step 4: Run all tests**
Run: `cd web && pnpm test`
Expected: PASS.
- [ ] **Step 5: Commit**
```bash
git add web/src/components/PagedMemoList/PagedMemoList.tsx
git commit -m "feat(home): pass calendar-selected date as default createTime to memo editor"
```
---
## Task 7: Manual smoke test
No code changes. Per `CLAUDE.md`: "For UI or frontend changes, start the dev server and use the feature in a browser before reporting the task as complete." Walk through the user-visible flows.
- [ ] **Step 1: Start the backend and frontend**
In one terminal:
```bash
go run ./cmd/memos --port 8081
```
In another:
```bash
cd web && pnpm dev
```
Open `http://localhost:3001`.
- [ ] **Step 2: Smoke — populated past date**
1. Sign in. Confirm the activity calendar is visible (statistics view).
2. Click a *past* date that already has memos.
3. Confirm the URL gains `?filter=displayTime:YYYY-MM-DD`.
4. Confirm the home memo editor shows the timestamp popover above the textarea, populated with the selected date.
5. Type a memo and click Save.
6. Clear the date filter (chip X). Reapply by clicking the same date.
7. Confirm the new memo appears under that date.
- [ ] **Step 3: Smoke — empty past date**
1. Pick a past date with **zero memos** in the calendar (lightest cell).
2. Confirm it is now clickable, the URL filter applies, and the empty-state shows.
3. Type and save a memo.
4. Confirm the memo appears for that date and the calendar cell tints up.
- [ ] **Step 4: Smoke — future date**
1. Click a future date in the current month.
2. Confirm the popover shows that date.
3. Save a memo. Confirm it appears under that date.
- [ ] **Step 5: Smoke — clear filter mid-draft**
1. Pick May 1 (or any non-today date). Type some content, do **not** save.
2. Click the filter chip X to clear the date filter.
3. Confirm the popover disappears and the draft content is preserved (autoSave behavior).
4. Save and confirm the memo gets a server-stamped "now" timestamp (i.e., appears under today).
- [ ] **Step 6: Smoke — change filter mid-draft**
1. Pick May 1. Type content.
2. Without saving, click May 3.
3. Confirm the popover updates to May 3.
4. Save. Confirm the memo appears under May 3.
- [ ] **Step 7: Smoke — comment editor unaffected**
1. Open any memo's detail view (or open the comments thread).
2. Confirm the reply editor does **not** show a timestamp popover.
3. Confirm the date filter has no visible effect on the reply editor.
- [ ] **Step 8: Smoke — edit mode unaffected**
1. Edit an existing memo (pencil icon).
2. Confirm the existing timestamp popover still works exactly as before, regardless of any active calendar filter.
- [ ] **Step 9: Smoke — empty-date click on Explore page**
1. Navigate to the Explore page (which also renders the calendar).
2. Click an empty date.
3. Confirm the URL filter applies and the empty-state shows. (No editor on Explore — that's correct.)
- [ ] **Step 10: Record results**
Note any unexpected behavior (especially: selection-ring contrast on the lowest-intensity background, mentioned as a flag in the spec). If the ring is too subtle, file a follow-up — *not* part of this plan.
---
## Self-review
**Spec coverage check:**
| Spec requirement | Task |
|---|---|
| Empty calendar dates clickable | Task 2 |
| Editor shows TimestampPopover in create mode when filter active | Task 5 (popover condition) |
| `createTime` = selected date + current local hh:mm:ss | Task 1 (helper) + Task 4 (seed) |
| `updateTime` mirrored to same value | Task 4 (seed) + Task 5 (live sync) |
| Live-derived: filter change re-syncs timestamps | Task 5 (live-sync `useEffect`) |
| Filter cleared → undefined → server-stamped "now" | Task 5 (passes `undefined` through) + Task 6 (helper returns undefined) |
| Future dates allowed (no clamp) | Task 1 (no clamp in helper); confirmed in Task 7 step 4 |
| Comment editor unaffected | Task 6 wires only `PagedMemoList`; confirmed in Task 7 step 7 |
| Edit mode unaffected | Task 4 + 5 explicitly guard on `memo`; confirmed in Task 7 step 8 |
| Empty-date click on Explore/Archived/Profile | Task 2 (calendar-side change); confirmed in Task 7 step 9 |
| DST/timezone uses local time | Task 1 (`new Date(y, m-1, d, h, mi, s)`) |
| Helper unit tests | Task 1 |
| `CalendarCell` empty-cell test | Task 2 |
| Manual smoke | Task 7 |
All spec requirements have a task. No gaps.
**Placeholder scan:** No "TBD"/"TODO" steps. Every code step shows the actual code.
**Type/name consistency check:**
- `MemoFilter` and `useMemoFilterContext` exist at `@/contexts/MemoFilterContext` (verified during exploration).
- `editorActions.setTimestamps` exists in `state/actions.ts:75` and accepts `Partial<EditorState["timestamps"]>` (verified). Calls in Tasks 4 and 5 match.
- `state.timestamps.createTime` is `Date | undefined` (verified `state/types.ts:27-29`). The popover render condition uses it as a truthy guard — `Date` instances are truthy, `undefined` is falsy.
- `useMemoFilterContext` (alias used in PagedMemoList) is exported from `MemoFilterContext.tsx:151` (verified).
- `deriveDefaultCreateTimeFromFilters` signature is identical between Task 1 (definition) and Task 6 (consumer).
- `defaultCreateTime: Date | undefined` flows consistently through `MemoEditorProps` (Task 3) → `MemoEditorImpl` destructuring (Task 5) → `useMemoInit` options (Task 4) → reducer payloads.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,774 @@
# First Screen Lazy Heavy Dependencies Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Keep Mermaid, Leaflet, React Leaflet, marker cluster, and feature CSS out of the auth/signup initial screen while preserving diagram, math, and map behavior when those features are used.
**Architecture:** Move runtime Leaflet objects behind plain coordinate data at parent boundaries, then lazy-load map implementations from small wrapper components. Replace Mermaid's static import with effect-time dynamic import, and move KaTeX/Leaflet CSS from the app entry into feature modules.
**Tech Stack:** React 19, TypeScript 6, Vite 8/Rolldown, React Router 7, React Query 5, Mermaid, KaTeX, Leaflet, React Leaflet, pnpm.
---
## File Structure
- Create `web/src/components/map/types.ts`
- Defines a lightweight `MapPoint` interface used by parents that must not import Leaflet.
- Create `web/src/components/map/LazyLocationPicker.tsx`
- Provides a `React.lazy` boundary and map-sized fallback for `LocationPicker`.
- Modify `web/src/main.tsx`
- Removes global Leaflet and KaTeX CSS imports.
- Modify `web/src/router/index.tsx`
- Lazy-loads the Home route so memo/editor/markdown modules are not part of the auth/signup entry graph.
- Modify `web/vite.config.mts`
- Keeps optional heavy dependency split groups from becoming entry preloads.
- Modify `web/src/components/map/LocationPicker.tsx`
- Imports Leaflet CSS inside the lazy implementation path.
- Accepts and emits plain `MapPoint` values at the public component boundary.
- Keeps `LatLng` runtime use internal to the map implementation.
- Modify `web/src/components/map/index.ts`
- Stops exporting `LocationPicker` and map utility helpers from the barrel so non-map imports do not pull Leaflet into parent chunks.
- Keeps exporting `useReverseGeocoding` because it has no Leaflet dependency.
- Modify `web/src/components/MemoEditor/types/insert-menu.ts`
- Replaces `LatLng` in editor state with `MapPoint`.
- Modify `web/src/components/MemoEditor/hooks/useLocation.ts`
- Removes runtime Leaflet import and stores plain coordinates.
- Modify `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`
- Removes runtime Leaflet import.
- Imports `useReverseGeocoding` directly from its file.
- Constructs plain coordinates from geolocation.
- Modify `web/src/components/MemoMetadata/Location/LocationDialog.tsx`
- Uses `LazyLocationPicker` and `MapPoint`.
- Only mounts the lazy picker while the dialog is open.
- Modify `web/src/components/MemoMetadata/Location/LocationDisplayView.tsx`
- Removes runtime Leaflet import and uses `LazyLocationPicker` inside the popover.
- Modify `web/src/pages/UserProfile.tsx`
- Lazy-loads `UserMemoMap` only when the map tab is active.
- Modify `web/src/components/MemoContent/MemoMarkdownRenderer.tsx`
- Imports KaTeX CSS from the markdown-rendering path.
- Modify `web/src/components/MemoContent/MermaidBlock.tsx`
- Dynamically imports Mermaid only when rendering a Mermaid block.
- Modify `web/src/components/UserMemoMap/UserMemoMap.tsx`
- Keeps marker cluster CSS in the lazy map implementation path.
- Verify with `pnpm lint`, `pnpm build`, and a production preview/browser network check.
## Task 1: Remove Leaflet From Editor Location State
**Files:**
- Create: `web/src/components/map/types.ts`
- Modify: `web/src/components/MemoEditor/types/insert-menu.ts`
- Modify: `web/src/components/MemoEditor/hooks/useLocation.ts`
- Modify: `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`
- [x] **Step 1: Add a Leaflet-free map coordinate type**
Create `web/src/components/map/types.ts`:
```ts
export interface MapPoint {
lat: number;
lng: number;
}
```
- [x] **Step 2: Replace editor location state type**
In `web/src/components/MemoEditor/types/insert-menu.ts`, replace the entire file with:
```ts
import type { MapPoint } from "@/components/map/types";
export interface LocationState {
placeholder: string;
position?: MapPoint;
latInput: string;
lngInput: string;
}
```
- [x] **Step 3: Remove Leaflet runtime usage from `useLocation`**
In `web/src/components/MemoEditor/hooks/useLocation.ts`, remove `import { LatLng } from "leaflet";`, add a type import, and use plain coordinate objects:
```ts
import { create } from "@bufbuild/protobuf";
import { useCallback, useMemo, useRef, useState } from "react";
import type { MapPoint } from "@/components/map/types";
import { Location, LocationSchema } from "@/types/proto/api/v1/memo_service_pb";
import { LocationState } from "../types/insert-menu";
export const useLocation = (initialLocation?: Location) => {
const [locationInitialized, setLocationInitialized] = useState(false);
const locationInitializedRef = useRef(locationInitialized);
locationInitializedRef.current = locationInitialized;
const [state, setState] = useState<LocationState>({
placeholder: initialLocation?.placeholder || "",
position: initialLocation ? { lat: initialLocation.latitude, lng: initialLocation.longitude } : undefined,
latInput: initialLocation ? String(initialLocation.latitude) : "",
lngInput: initialLocation ? String(initialLocation.longitude) : "",
});
const stateRef = useRef(state);
stateRef.current = state;
const updatePosition = useCallback((position?: MapPoint) => {
setState((prev) => ({
...prev,
position,
latInput: position ? String(position.lat) : "",
lngInput: position ? String(position.lng) : "",
}));
}, []);
const handlePositionChange = useCallback(
(position: MapPoint) => {
if (!locationInitializedRef.current) setLocationInitialized(true);
updatePosition(position);
},
[updatePosition],
);
const updateCoordinate = useCallback((type: "lat" | "lng", value: string) => {
const num = parseFloat(value);
const isValid = type === "lat" ? !isNaN(num) && num >= -90 && num <= 90 : !isNaN(num) && num >= -180 && num <= 180;
setState((prev) => {
const next = { ...prev, [type === "lat" ? "latInput" : "lngInput"]: value };
if (isValid && prev.position) {
const newPos = type === "lat" ? { lat: num, lng: prev.position.lng } : { lat: prev.position.lat, lng: num };
return { ...next, position: newPos, latInput: String(newPos.lat), lngInput: String(newPos.lng) };
}
return next;
});
}, []);
const setPlaceholder = useCallback((placeholder: string) => {
setState((prev) => ({ ...prev, placeholder }));
}, []);
const reset = useCallback(() => {
setState({
placeholder: "",
position: undefined,
latInput: "",
lngInput: "",
});
setLocationInitialized(false);
}, []);
const getLocation = useCallback((): Location | undefined => {
const { position, placeholder } = stateRef.current;
if (!position || !placeholder.trim()) {
return undefined;
}
return create(LocationSchema, {
latitude: position.lat,
longitude: position.lng,
placeholder,
});
}, []);
return useMemo(
() => ({ state, locationInitialized, handlePositionChange, updateCoordinate, setPlaceholder, reset, getLocation }),
[state, locationInitialized, handlePositionChange, updateCoordinate, setPlaceholder, reset, getLocation],
);
};
```
- [x] **Step 4: Remove Leaflet import from `InsertMenu`**
In `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`:
Remove:
```ts
import { LatLng } from "leaflet";
```
Replace:
```ts
import { useReverseGeocoding } from "@/components/map";
```
with:
```ts
import { useReverseGeocoding } from "@/components/map/useReverseGeocoding";
```
Replace the geolocation success handler body:
```ts
handleLocationPositionChange(new LatLng(position.coords.latitude, position.coords.longitude));
```
with:
```ts
handleLocationPositionChange({ lat: position.coords.latitude, lng: position.coords.longitude });
```
- [x] **Step 5: Run focused type check**
Run:
```bash
cd web && pnpm lint
```
Expected: TypeScript may still fail because map component props have not been converted yet. If the only failures are `LatLng`/`MapPoint` mismatches in map/location components, continue to Task 2. If unrelated failures appear, stop and inspect before editing further.
## Task 2: Lazy-Load Location Picker And Keep Leaflet Inside Map Modules
**Files:**
- Create: `web/src/components/map/LazyLocationPicker.tsx`
- Modify: `web/src/components/map/LocationPicker.tsx`
- Modify: `web/src/components/map/index.ts`
- Modify: `web/src/components/MemoMetadata/Location/LocationDialog.tsx`
- Modify: `web/src/components/MemoMetadata/Location/LocationDisplayView.tsx`
- [x] **Step 1: Create lazy location picker wrapper**
Create `web/src/components/map/LazyLocationPicker.tsx`:
```tsx
import { lazy, Suspense } from "react";
import { cn } from "@/lib/utils";
import type { MapPoint } from "./types";
interface LazyLocationPickerProps {
readonly?: boolean;
latlng?: MapPoint;
onChange?: (position: MapPoint) => void;
className?: string;
}
const LocationPicker = lazy(() => import("./LocationPicker"));
export const LazyLocationPicker = ({ className, ...props }: LazyLocationPickerProps) => {
return (
<Suspense
fallback={
<div
className={cn(
"memo-location-map relative isolate h-72 w-full overflow-hidden rounded-xl border border-border bg-muted/30 shadow-sm",
className,
)}
/>
}
>
<LocationPicker className={className} {...props} />
</Suspense>
);
};
```
- [x] **Step 2: Convert `LocationPicker` public props to `MapPoint`**
In `web/src/components/map/LocationPicker.tsx`:
Add CSS and type imports near the top:
```ts
import "leaflet/dist/leaflet.css";
import type { MapPoint } from "./types";
```
Keep Leaflet runtime import:
```ts
import L, { LatLng } from "leaflet";
```
Add helper functions after imports:
```ts
const toLatLng = (point: MapPoint): LatLng => new LatLng(point.lat, point.lng);
const fromLatLng = (latlng: LatLng): MapPoint => ({ lat: latlng.lat, lng: latlng.lng });
```
Update public-facing props:
```ts
interface LocationMarkerProps {
position: LatLng | undefined;
onChange: (position: MapPoint) => void;
readonly?: boolean;
}
```
In `LocationMarker`, replace:
```ts
onChange(e.latlng);
```
with:
```ts
onChange(fromLatLng(e.latlng));
```
Update `MapControlsProps`:
```ts
interface MapControlsProps {
position: MapPoint | undefined;
}
```
Update `LocationPickerProps`:
```ts
interface LocationPickerProps {
readonly?: boolean;
latlng?: MapPoint;
onChange?: (position: MapPoint) => void;
className?: string;
}
```
Replace:
```ts
const DEFAULT_CENTER_LAT_LNG = new LatLng(48.8584, 2.2945);
```
with:
```ts
const DEFAULT_CENTER: MapPoint = { lat: 48.8584, lng: 2.2945 };
```
Inside `LocationPicker`, replace:
```ts
const position = latlng || DEFAULT_CENTER_LAT_LNG;
```
with:
```ts
const position = latlng || DEFAULT_CENTER;
const mapCenter = toLatLng(position);
const markerPosition = latlng ? toLatLng(latlng) : mapCenter;
```
Replace the `MapContainer` props and marker call:
```tsx
<MapContainer
className="h-full w-full !bg-muted"
center={mapCenter}
zoom={13}
scrollWheelZoom={false}
zoomControl={false}
attributionControl={false}
>
<ThemedTileLayer />
<LocationMarker position={markerPosition} readonly={readOnly} onChange={onChange} />
<MapControls position={latlng} />
<MapCleanup />
</MapContainer>
```
- [x] **Step 3: Keep the map barrel Leaflet-free**
Replace `web/src/components/map/index.ts` with:
```ts
export { useReverseGeocoding } from "./useReverseGeocoding";
```
Do not export `LocationPicker`, `LazyLocationPicker`, `map-utils`, or Leaflet helpers from this barrel. Import map UI directly from `@/components/map/LazyLocationPicker` or the implementation file.
- [x] **Step 4: Use lazy picker in `LocationDialog`**
In `web/src/components/MemoMetadata/Location/LocationDialog.tsx`:
Remove:
```ts
import type { LatLng } from "leaflet";
import { LocationPicker } from "@/components/map";
```
Add:
```ts
import { LazyLocationPicker } from "@/components/map/LazyLocationPicker";
import type { MapPoint } from "@/components/map/types";
```
Change the prop type:
```ts
onPositionChange: (position: MapPoint) => void;
```
Replace:
```tsx
<LocationPicker className="h-full" latlng={position} onChange={onPositionChange} />
```
with:
```tsx
{open && <LazyLocationPicker className="h-full" latlng={position} onChange={onPositionChange} />}
```
- [x] **Step 5: Use lazy picker in `LocationDisplayView`**
In `web/src/components/MemoMetadata/Location/LocationDisplayView.tsx`:
Remove:
```ts
import { LatLng } from "leaflet";
import { LocationPicker } from "@/components/map";
```
Add:
```ts
import { LazyLocationPicker } from "@/components/map/LazyLocationPicker";
```
Replace:
```tsx
<LocationPicker latlng={new LatLng(location.latitude, location.longitude)} readonly={true} />
```
with:
```tsx
{popoverOpen && <LazyLocationPicker latlng={{ lat: location.latitude, lng: location.longitude }} readonly={true} />}
```
- [x] **Step 6: Run lint**
Run:
```bash
cd web && pnpm lint
```
Expected: PASS for the files changed so far, or only failures unrelated to this work. Fix any `MapPoint`/`LatLng` type errors before continuing.
## Task 3: Lazy-Load Profile Map
**Files:**
- Modify: `web/src/pages/UserProfile.tsx`
- Modify: `web/src/components/UserMemoMap/UserMemoMap.tsx`
- [x] **Step 1: Move `UserMemoMap` behind `React.lazy`**
In `web/src/pages/UserProfile.tsx`, replace the React import section:
```ts
import copy from "copy-to-clipboard";
import { ExternalLinkIcon, LayoutListIcon, type LucideIcon, MapIcon } from "lucide-react";
import { toast } from "react-hot-toast";
```
with:
```ts
import copy from "copy-to-clipboard";
import { lazy, Suspense } from "react";
import { ExternalLinkIcon, LayoutListIcon, type LucideIcon, MapIcon } from "lucide-react";
import { toast } from "react-hot-toast";
```
Remove:
```ts
import UserMemoMap from "@/components/UserMemoMap";
```
Add after the `type TabView = "memos" | "map";` line:
```ts
const UserMemoMap = lazy(() => import("@/components/UserMemoMap"));
```
Replace:
```tsx
<div className="">
<UserMemoMap creator={user.name} className="h-[60dvh] sm:h-[500px] rounded-xl" />
</div>
```
with:
```tsx
<div className="">
<Suspense fallback={<div className="h-[60dvh] sm:h-[500px] rounded-xl border border-border bg-muted/30" />}>
<UserMemoMap creator={user.name} className="h-[60dvh] sm:h-[500px] rounded-xl" />
</Suspense>
</div>
```
- [x] **Step 2: Keep Leaflet CSS in the lazy profile map implementation**
In `web/src/components/UserMemoMap/UserMemoMap.tsx`, add the Leaflet CSS import above marker cluster CSS:
```ts
import "leaflet/dist/leaflet.css";
import "leaflet.markercluster/dist/MarkerCluster.css";
```
The file should continue to import Leaflet, React Leaflet, marker clustering, and `map-utils` directly because this component is now loaded only from a lazy boundary.
- [x] **Step 3: Run lint**
Run:
```bash
cd web && pnpm lint
```
Expected: PASS, or only unrelated pre-existing failures.
## Task 4: Move KaTeX CSS And Dynamically Import Mermaid
**Files:**
- Modify: `web/src/main.tsx`
- Modify: `web/src/components/MemoContent/MemoMarkdownRenderer.tsx`
- Modify: `web/src/components/MemoContent/MermaidBlock.tsx`
- [x] **Step 1: Remove feature CSS from app entry**
In `web/src/main.tsx`, remove:
```ts
import "leaflet/dist/leaflet.css";
import "katex/dist/katex.min.css";
```
- [x] **Step 2: Load KaTeX CSS from markdown renderer**
In `web/src/components/MemoContent/MemoMarkdownRenderer.tsx`, add this import with the existing dependency imports:
```ts
import "katex/dist/katex.min.css";
```
- [x] **Step 3: Remove static Mermaid import**
In `web/src/components/MemoContent/MermaidBlock.tsx`, remove:
```ts
import mermaid from "mermaid";
```
- [x] **Step 4: Replace Mermaid initialization/render effects with dynamic import**
In `web/src/components/MemoContent/MermaidBlock.tsx`, remove the existing Mermaid initialization effect:
```ts
useEffect(() => {
mermaid.initialize({
startOnLoad: false,
theme: toMermaidTheme(currentTheme),
securityLevel: "strict",
fontFamily: "inherit",
suppressErrorRendering: true,
});
}, [currentTheme]);
```
Replace the existing render effect with:
```ts
useEffect(() => {
if (!codeContent) return;
let cancelled = false;
const renderDiagram = async () => {
try {
const { default: mermaid } = await import("mermaid");
if (cancelled) return;
mermaid.initialize({
startOnLoad: false,
theme: toMermaidTheme(currentTheme),
securityLevel: "strict",
fontFamily: "inherit",
suppressErrorRendering: true,
});
const id = `mermaid-${Math.random().toString(36).substring(7)}`;
const { svg: renderedSvg } = await mermaid.render(id, codeContent);
if (cancelled) return;
setSvg(renderedSvg);
setError("");
} catch (err) {
if (cancelled) return;
console.error("Failed to render mermaid diagram:", err);
setSvg("");
setError(formatErrorMessage(err));
}
};
renderDiagram();
return () => {
cancelled = true;
};
}, [codeContent, currentTheme]);
```
- [x] **Step 5: Run lint**
Run:
```bash
cd web && pnpm lint
```
Expected: PASS, or only unrelated pre-existing failures.
## Task 4.5: Remove Remaining Entry Preloads Found During Verification
**Files:**
- Modify: `web/src/router/index.tsx`
- Modify: `web/vite.config.mts`
- [x] **Step 1: Lazy-load the Home route**
`web/src/router/index.tsx` now uses `lazyWithReload(() => import("@/pages/Home"))` instead of a static Home import. This prevents Home, `PagedMemoList`, `MemoEditor`, `MemoContent`, KaTeX, and Mermaid code from entering the auth/signup app entry graph.
- [x] **Step 2: Tighten optional vendor split groups**
`web/vite.config.mts` no longer defines a manual `mermaid-vendor` group, because Rolldown emitted the preload helper from that group and forced an entry preload. The Leaflet group now matches only the `leaflet` package, not `react-leaflet`, so React does not get bundled into a Leaflet-named entry preload.
- [x] **Step 3: Re-run lint and build**
Run:
```bash
cd web && pnpm lint && pnpm build
```
Expected: PASS.
## Task 5: Build And Verify Initial Network Behavior
**Files:**
- No source edits expected unless verification finds a regression.
- [x] **Step 1: Build production frontend**
Run:
```bash
cd web && pnpm build
```
Expected: PASS. Build output should still contain separate Mermaid and Leaflet chunks, but they should not be required by the auth/signup initial route.
- [x] **Step 2: Inspect build output for heavy chunks**
Run:
```bash
cd web && find dist/assets -maxdepth 1 -type f \( -name '*mermaid*' -o -name '*leaflet*' -o -name '*katex*' \) -print | sort
```
Expected: Mermaid and Leaflet assets may exist as lazy chunks. Their existence is fine; the goal is that auth/signup does not request them initially.
- [x] **Step 3: Start production preview**
Run:
```bash
cd web && pnpm exec vite preview --host 127.0.0.1 --port 4173
```
Expected: Preview server starts on `http://127.0.0.1:4173/`. Keep this session running until browser verification is complete.
- [x] **Step 4: Verify `/auth/signup` network with browser tooling**
Open:
```text
http://127.0.0.1:4173/auth/signup
```
Expected initial document and asset requests do not include filenames containing:
```text
mermaid
leaflet
```
If KaTeX CSS still appears on `/auth/signup`, inspect the chunk initiator and remove any remaining static import path that reaches `MemoMarkdownRenderer` from auth/signup.
- [ ] **Step 5: Smoke test feature lazy loading**
Use the running app or a local backend/dev setup to verify:
```text
1. A memo containing a Mermaid code block renders the diagram and requests the Mermaid chunk only when the memo content appears.
2. A memo containing inline or block math displays KaTeX styling when memo content appears.
3. Opening the location picker loads Leaflet assets and the picker remains interactive.
4. Opening a memo location popover loads Leaflet assets and shows the pinned map.
5. Opening `/u/:username?view=map` loads the profile map and marker cluster behavior still works.
```
Expected: Features behave as before after their lazy chunks load.
Result in this session: live feature smoke was not completed because the production preview has no authenticated backend session or seeded memo data. Static verification confirmed the relevant feature chunks still exist and load paths are behind lazy imports.
- [x] **Step 6: Stop preview server**
Stop the preview command from Step 3 with `Ctrl-C`.
## Task 6: Commit Implementation
**Files:**
- All source files modified by Tasks 1-4.
- [x] **Step 1: Review final diff**
Run:
```bash
git diff -- web/src/main.tsx web/src/components/map web/src/components/MemoEditor web/src/components/MemoMetadata/Location web/src/pages/UserProfile.tsx web/src/components/MemoContent web/src/components/UserMemoMap/UserMemoMap.tsx
```
Expected: Diff is limited to lazy-loading heavy optional dependencies and plain coordinate type changes.
- [x] **Step 2: Run final verification**
Run:
```bash
cd web && pnpm lint && pnpm build
```
Expected: PASS.
- [x] **Step 3: Commit**
Run:
```bash
git add web/src/main.tsx web/src/components/map web/src/components/MemoEditor web/src/components/MemoMetadata/Location web/src/pages/UserProfile.tsx web/src/components/MemoContent web/src/components/UserMemoMap/UserMemoMap.tsx
git commit -m "perf: lazy load heavy first-screen dependencies"
```
Expected: Commit succeeds with only the intended source changes.
## Self-Review
- Spec coverage: The plan removes global Leaflet/KaTeX CSS, dynamically imports Mermaid, lazy-loads map UI, keeps Leaflet types out of parent boundaries, and verifies auth/signup network behavior.
- Placeholder scan: No placeholder markers, unresolved decisions, or vague generic handling steps remain.
- Type consistency: `MapPoint` is the shared parent-facing coordinate type; `LatLng` remains internal to `LocationPicker` and map implementation files only.
@@ -0,0 +1,776 @@
# Placeholder Component Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Replace `Empty.tsx` with a reusable `<Placeholder>` component covering empty / loading / noResults / notFound states, each rendering a hand-curated ASCII bird from a pool-shaped data file with subtle CSS-only animation.
**Architecture:** Single component (`Placeholder/index.tsx`) reads from a co-located `ascii-pool.ts` data file via a `pickPiece(variant)` picker. Motion is CSS keyframes in `Placeholder.css`, gated by `prefers-reduced-motion`. Default messages live in a `messages.ts` seam ready for future i18n. Integration is narrow: only `Inboxes.tsx` is rewired in this PR; `Empty.tsx` is deleted.
**Tech Stack:** React 19 · TypeScript · Tailwind v4 (via `@tailwindcss/vite`) · Vitest + `@testing-library/react` + jsdom · Biome for lint/format · `cn` helper from `@/lib/utils` for class composition.
---
## File Structure
**Create:**
- `web/src/components/Placeholder/index.tsx` — public component (default export)
- `web/src/components/Placeholder/Placeholder.css` — keyframes + motion classes
- `web/src/components/Placeholder/ascii-pool.ts` — types, `ASCII_POOL` array, `pickPiece()`
- `web/src/components/Placeholder/messages.ts``DEFAULT_MESSAGES` map
- `web/src/components/Placeholder/CREDITS.md` — Joan Stark attribution
- `web/tests/placeholder-pool.test.ts` — picker + pool integrity tests
- `web/tests/placeholder-component.test.tsx` — component render tests
**Modify:**
- `web/src/pages/Inboxes.tsx` — replace `<Empty />` with `<Placeholder variant="empty" message={…} />`
**Delete:**
- `web/src/components/Empty.tsx`
---
## Task 0: Commit this plan
**Files:**
- Add: `docs/superpowers/plans/2026-05-12-placeholder-component.md`
- [ ] **Step 1: Commit the plan document on its own**
```bash
git add docs/superpowers/plans/2026-05-12-placeholder-component.md
git commit -m "docs: add Placeholder component implementation plan"
```
This keeps the planning artifact separate from feature commits.
---
## Task 1: Scaffold pool types and picker (TDD)
**Files:**
- Create: `web/src/components/Placeholder/ascii-pool.ts`
- Test: `web/tests/placeholder-pool.test.ts`
- [ ] **Step 1: Write the failing tests for `pickPiece` and pool shape**
Create `web/tests/placeholder-pool.test.ts`:
```ts
import { describe, expect, it } from "vitest";
import { ASCII_POOL, pickPiece, type PlaceholderVariant } from "@/components/Placeholder/ascii-pool";
const VARIANTS: PlaceholderVariant[] = ["empty", "loading", "noResults", "notFound"];
describe("ASCII_POOL integrity", () => {
it("contains at least one piece per variant", () => {
for (const variant of VARIANTS) {
const matches = ASCII_POOL.filter((p) => p.variant === variant);
expect(matches.length, `variant=${variant}`).toBeGreaterThanOrEqual(1);
}
});
it("uses unique ids", () => {
const ids = ASCII_POOL.map((p) => p.id);
expect(new Set(ids).size).toBe(ids.length);
});
it("preserves the jgs credit on every piece", () => {
for (const piece of ASCII_POOL) {
expect(piece.credit, `piece=${piece.id}`).toMatch(/jgs/);
}
});
it("uses a known motion style on every piece", () => {
for (const piece of ASCII_POOL) {
expect(["bob", "flutter", "none"]).toContain(piece.motion);
}
});
});
describe("pickPiece", () => {
it("returns a piece matching the requested variant", () => {
for (const variant of VARIANTS) {
const piece = pickPiece(variant);
expect(piece.variant).toBe(variant);
}
});
it("returns a non-empty ascii string", () => {
const piece = pickPiece("empty");
expect(piece.ascii.length).toBeGreaterThan(0);
});
});
```
- [ ] **Step 2: Run the tests and verify they fail**
```bash
cd web && pnpm test placeholder-pool
```
Expected: FAIL — module `@/components/Placeholder/ascii-pool` not found.
- [ ] **Step 3: Implement `ascii-pool.ts` with types, an empty pool, and the picker**
Create `web/src/components/Placeholder/ascii-pool.ts`:
```ts
export type PlaceholderVariant = "empty" | "loading" | "noResults" | "notFound";
export type MotionStyle = "bob" | "flutter" | "none";
export interface AsciiPiece {
/** Stable identifier — used as React key and for debugging. */
id: string;
/** Which placeholder state this piece is shown for. */
variant: PlaceholderVariant;
/** ASCII art preserved verbatim — must keep every space. */
ascii: string;
/** Attribution shown beneath the bird, e.g. "jgs · 4/97". */
credit: string;
/** Motion hint applied to the <pre>. */
motion: MotionStyle;
}
export const ASCII_POOL: AsciiPiece[] = [];
export function pickPiece(variant: PlaceholderVariant): AsciiPiece {
const matches = ASCII_POOL.filter((p) => p.variant === variant);
if (matches.length === 0) {
throw new Error(`No ASCII piece registered for variant "${variant}"`);
}
return matches[Math.floor(Math.random() * matches.length)];
}
```
- [ ] **Step 4: Run the tests and verify they still fail (pool is empty)**
```bash
cd web && pnpm test placeholder-pool
```
Expected: FAIL — "contains at least one piece per variant" expectations not met (because `ASCII_POOL` is `[]`).
This is the expected red — pool gets seeded in the next task.
- [ ] **Step 5: Commit**
```bash
git add web/src/components/Placeholder/ascii-pool.ts web/tests/placeholder-pool.test.ts
git commit -m "feat(placeholder): scaffold ASCII pool types and picker"
```
---
## Task 2: Seed the four ASCII pieces
**Files:**
- Modify: `web/src/components/Placeholder/ascii-pool.ts`
- [ ] **Step 1: Replace the empty `ASCII_POOL` array with the four seed entries**
In `web/src/components/Placeholder/ascii-pool.ts`, replace `export const ASCII_POOL: AsciiPiece[] = [];` with the four entries below. Preserve every space and newline in the `ascii` strings exactly — they are template literals with escaped backslashes/backticks per JS rules.
```ts
export const ASCII_POOL: AsciiPiece[] = [
{
id: "jgs-crested-parrot",
variant: "empty",
credit: "jgs · 4/97",
motion: "bob",
ascii: ` .---.
/ 6_6
\\_ (__\\
// \\\\
(( ))
=====""===""=====
|||
|`,
},
{
id: "jgs-hummingbird-sm",
variant: "loading",
credit: "jgs · 7/98",
motion: "flutter",
ascii: ` , _
{ \\/\`o;====-
.----'-/\`-/
\`'-..-| /
/\\/\\
\`--\``,
},
{
id: "jgs-wide-eyed-owl",
variant: "noResults",
credit: "jgs · 2/01",
motion: "bob",
ascii: ` __ __
\\ \`-'"'-\` /
/ \\_ _/ \\
| d\\_/b |
.'\\ V /'.
/ '-...-' \\
| / \\ |
\\/\\ /\\/
==(||)---(||)==`,
},
{
id: "jgs-bird-flown-away",
variant: "notFound",
credit: "jgs · 7/96",
motion: "flutter",
ascii: ` ___
_,-' ______
.' .-' ____7
/ / ___7
_| / ___7
>(')\\ | ___7
\\\\/ \\_______
' _======>
\`'----\\\\\``,
},
];
```
- [ ] **Step 2: Run the pool tests and verify they pass**
```bash
cd web && pnpm test placeholder-pool
```
Expected: PASS for all six assertions.
- [ ] **Step 3: Commit**
```bash
git add web/src/components/Placeholder/ascii-pool.ts
git commit -m "feat(placeholder): seed pool with four jgs ASCII bird pieces"
```
---
## Task 3: Default messages
**Files:**
- Create: `web/src/components/Placeholder/messages.ts`
- [ ] **Step 1: Add a tiny test for the messages map**
Append to `web/tests/placeholder-pool.test.ts`:
```ts
import { DEFAULT_MESSAGES } from "@/components/Placeholder/messages";
describe("DEFAULT_MESSAGES", () => {
it("provides a non-empty message for every variant", () => {
for (const variant of VARIANTS) {
expect(DEFAULT_MESSAGES[variant], `variant=${variant}`).toBeTruthy();
expect(DEFAULT_MESSAGES[variant].trim().length).toBeGreaterThan(0);
}
});
});
```
- [ ] **Step 2: Run the test and verify it fails**
```bash
cd web && pnpm test placeholder-pool
```
Expected: FAIL — module `@/components/Placeholder/messages` not found.
- [ ] **Step 3: Create `messages.ts`**
```ts
import type { PlaceholderVariant } from "./ascii-pool";
/**
* Default copy shown beneath the ASCII art when no `message` prop is supplied.
*
* Future i18n: swap these strings for `t("placeholder.<variant>")` lookups via
* `react-i18next` without touching the component.
*/
export const DEFAULT_MESSAGES: Record<PlaceholderVariant, string> = {
empty: "No memos yet",
loading: "Loading…",
noResults: "Nothing matches that search",
notFound: "This page flew the coop",
};
```
- [ ] **Step 4: Run the test and verify it passes**
```bash
cd web && pnpm test placeholder-pool
```
Expected: PASS — all variants have a non-empty default message.
- [ ] **Step 5: Commit**
```bash
git add web/src/components/Placeholder/messages.ts web/tests/placeholder-pool.test.ts
git commit -m "feat(placeholder): add DEFAULT_MESSAGES map"
```
---
## Task 4: Animation keyframes
**Files:**
- Create: `web/src/components/Placeholder/Placeholder.css`
- [ ] **Step 1: Create the stylesheet**
```css
/*
* Animations for <Placeholder>.
*
* All keyframes are wrapped in a prefers-reduced-motion guard so users who
* opt out of motion see a static bird and an instantly-visible message.
*/
@media (prefers-reduced-motion: no-preference) {
.placeholder-motion-bob {
animation: placeholder-bob 3.4s ease-in-out infinite;
}
.placeholder-motion-flutter {
animation: placeholder-flutter 0.7s ease-in-out infinite;
}
.placeholder-fade-in {
animation: placeholder-fade 1s ease-out 0.3s both;
opacity: 0;
}
}
@keyframes placeholder-bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
@keyframes placeholder-flutter {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(2px, -1px); }
}
@keyframes placeholder-fade {
to { opacity: 1; }
}
```
- [ ] **Step 2: Commit**
```bash
git add web/src/components/Placeholder/Placeholder.css
git commit -m "feat(placeholder): add motion keyframes with reduced-motion guard"
```
---
## Task 5: Placeholder component (TDD)
**Files:**
- Create: `web/src/components/Placeholder/index.tsx`
- Test: `web/tests/placeholder-component.test.tsx`
- [ ] **Step 1: Write the failing component tests**
Create `web/tests/placeholder-component.test.tsx`:
```tsx
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import Placeholder from "@/components/Placeholder";
import { DEFAULT_MESSAGES } from "@/components/Placeholder/messages";
describe("<Placeholder>", () => {
it("renders the default message for variant=empty", () => {
render(<Placeholder variant="empty" />);
expect(screen.getByText(DEFAULT_MESSAGES.empty)).toBeInTheDocument();
});
it("renders the default message for variant=loading", () => {
render(<Placeholder variant="loading" />);
expect(screen.getByText(DEFAULT_MESSAGES.loading)).toBeInTheDocument();
});
it("renders the default message for variant=noResults", () => {
render(<Placeholder variant="noResults" />);
expect(screen.getByText(DEFAULT_MESSAGES.noResults)).toBeInTheDocument();
});
it("renders the default message for variant=notFound", () => {
render(<Placeholder variant="notFound" />);
expect(screen.getByText(DEFAULT_MESSAGES.notFound)).toBeInTheDocument();
});
it("overrides the default message when `message` prop is passed", () => {
render(<Placeholder variant="empty" message="Custom copy goes here" />);
expect(screen.getByText("Custom copy goes here")).toBeInTheDocument();
expect(screen.queryByText(DEFAULT_MESSAGES.empty)).not.toBeInTheDocument();
});
it("renders the ASCII art inside a <pre> with aria-hidden", () => {
const { container } = render(<Placeholder variant="empty" />);
const pre = container.querySelector("pre");
expect(pre).not.toBeNull();
expect(pre).toHaveAttribute("aria-hidden", "true");
expect(pre!.textContent!.length).toBeGreaterThan(0);
});
it("renders a jgs credit string", () => {
render(<Placeholder variant="empty" />);
expect(screen.getByText(/jgs/)).toBeInTheDocument();
});
it('applies role="status" and aria-live="polite" ONLY when variant=loading', () => {
const { rerender, container } = render(<Placeholder variant="empty" />);
expect(container.querySelector('[role="status"]')).toBeNull();
rerender(<Placeholder variant="loading" />);
const live = container.querySelector('[role="status"]');
expect(live).not.toBeNull();
expect(live).toHaveAttribute("aria-live", "polite");
});
it("renders children below the message when provided", () => {
render(
<Placeholder variant="notFound">
<button type="button">Go home</button>
</Placeholder>,
);
expect(screen.getByRole("button", { name: "Go home" })).toBeInTheDocument();
});
it("merges a custom className onto the outer wrapper", () => {
const { container } = render(<Placeholder variant="empty" className="custom-test-class" />);
expect(container.firstChild).toHaveClass("custom-test-class");
});
});
```
- [ ] **Step 2: Run the tests and verify they fail**
```bash
cd web && pnpm test placeholder-component
```
Expected: FAIL — module `@/components/Placeholder` not found.
- [ ] **Step 3: Implement `index.tsx`**
Create `web/src/components/Placeholder/index.tsx`:
```tsx
import { useMemo, type ReactNode } from "react";
import { cn } from "@/lib/utils";
import { pickPiece, type MotionStyle, type PlaceholderVariant } from "./ascii-pool";
import { DEFAULT_MESSAGES } from "./messages";
import "./Placeholder.css";
interface PlaceholderProps {
variant: PlaceholderVariant;
message?: string;
children?: ReactNode;
className?: string;
}
const MOTION_CLASS: Record<MotionStyle, string> = {
bob: "placeholder-motion-bob",
flutter: "placeholder-motion-flutter",
none: "",
};
const Placeholder = ({ variant, message, children, className }: PlaceholderProps) => {
// Stable for the lifetime of this mount; re-rolls only if `variant` changes
// (which is rare in practice — most callers pass a constant).
const piece = useMemo(() => pickPiece(variant), [variant]);
const resolvedMessage = message ?? DEFAULT_MESSAGES[variant];
const isLoading = variant === "loading";
return (
<div
role={isLoading ? "status" : undefined}
aria-live={isLoading ? "polite" : undefined}
className={cn("flex flex-col items-center justify-center max-w-md mx-auto px-4 py-8", className)}
>
<pre
aria-hidden="true"
className={cn(
"font-mono text-xs sm:text-sm leading-tight text-muted-foreground whitespace-pre m-0",
MOTION_CLASS[piece.motion],
)}
>
{piece.ascii}
</pre>
<p className="mt-3 font-mono text-sm text-muted-foreground placeholder-fade-in">
{resolvedMessage}
</p>
<p className="mt-1 font-mono text-[10px] text-muted-foreground/60 placeholder-fade-in">
{piece.credit}
</p>
{children && <div className="mt-4">{children}</div>}
</div>
);
};
export default Placeholder;
```
- [ ] **Step 4: Run the tests and verify they pass**
```bash
cd web && pnpm test placeholder-component
```
Expected: PASS — all ten assertions green.
- [ ] **Step 5: Commit**
```bash
git add web/src/components/Placeholder/index.tsx web/tests/placeholder-component.test.tsx
git commit -m "feat(placeholder): implement <Placeholder> with variant-driven ASCII pool"
```
---
## Task 6: Attribution credits
**Files:**
- Create: `web/src/components/Placeholder/CREDITS.md`
- [ ] **Step 1: Create `CREDITS.md`**
```markdown
# ASCII Art Credits
The ASCII bird illustrations rendered by `<Placeholder>` are from **Joan Stark's**
classic ASCII art collection. Each piece is signed with her `jgs` tag and the
month/year it was published.
- Source archive: https://github.com/oldcompcz/jgs (Joan Stark's ASCII Art Gallery)
- Original site (preserved via WebArchive): https://web.archive.org/web/20091028013825/http://www.geocities.com/SoHo/7373/
- Wikipedia: https://en.wikipedia.org/wiki/Joan_Stark
Joan Stark distributed her art freely on Usenet and the early web. We retain
the `jgs` signature visible beneath each piece in the UI so attribution travels
with the art wherever it is shown.
If you add new ASCII pieces to `ascii-pool.ts`:
- Prefer well-attributed art from established collections.
- Keep the original artist signature in the `credit` field (e.g. `"jgs · 4/97"`).
- If using a different artist, link the source in this file.
```
- [ ] **Step 2: Commit**
```bash
git add web/src/components/Placeholder/CREDITS.md
git commit -m "docs(placeholder): credit Joan Stark for ASCII bird art"
```
---
## Task 7: Wire into `Inboxes.tsx` and delete `Empty.tsx`
**Files:**
- Modify: `web/src/pages/Inboxes.tsx`
- Delete: `web/src/components/Empty.tsx`
- [ ] **Step 1: Read the current empty-state block in `Inboxes.tsx`**
Open `web/src/pages/Inboxes.tsx`. The relevant block is at lines 99105:
```tsx
{notifications.length === 0 ? (
<div className="w-full py-16 flex flex-col justify-center items-center">
<Empty />
<p className="mt-4 text-sm text-muted-foreground">
{filter === "unread" ? t("inbox.no-unread") : filter === "archived" ? t("inbox.no-archived") : t("message.no-data")}
</p>
</div>
) : (
```
The outer `<div className="w-full py-16 flex flex-col justify-center items-center">` and the inner `<p>` both become redundant — `<Placeholder>` handles its own centering and message.
- [ ] **Step 2: Swap the import**
In `web/src/pages/Inboxes.tsx`, replace the import line:
```tsx
import Empty from "@/components/Empty";
```
with:
```tsx
import Placeholder from "@/components/Placeholder";
```
- [ ] **Step 3: Replace the empty-state JSX**
Replace lines 99105 (the existing empty-state block above) with:
```tsx
{notifications.length === 0 ? (
<Placeholder
variant="empty"
message={
filter === "unread"
? t("inbox.no-unread")
: filter === "archived"
? t("inbox.no-archived")
: t("message.no-data")
}
/>
) : (
```
(Only the truthy branch of the ternary changes; leave the `: (` start of the falsy branch and everything below it untouched.)
- [ ] **Step 4: Delete `Empty.tsx`**
```bash
git rm web/src/components/Empty.tsx
```
- [ ] **Step 5: Verify nothing else imports `Empty`**
```bash
cd /Users/steven/Projects/usememos/memos && grep -rn 'from "@/components/Empty"\|from "./Empty"\|from "../Empty"' web/src 2>/dev/null
```
Expected: no output. If anything matches, update that file to use `<Placeholder variant="empty" />` before continuing.
- [ ] **Step 6: Commit**
```bash
git add web/src/pages/Inboxes.tsx web/src/components/Empty.tsx
git commit -m "feat(inboxes): use <Placeholder variant=empty> in place of <Empty>"
```
---
## Task 8: Verification — lint, types, tests, build, dev preview
**Files:** none modified (verification only)
- [ ] **Step 1: Run the lint + typecheck**
```bash
cd web && pnpm lint
```
Expected: exits 0. If Biome flags anything (formatting, sort-order, unused imports), run `pnpm lint:fix` and re-run `pnpm lint`. Commit the fix separately if any changes are required:
```bash
git add -p web/src web/tests
git commit -m "chore(placeholder): biome auto-fixes"
```
- [ ] **Step 2: Run the full test suite**
```bash
cd web && pnpm test
```
Expected: all suites green, including `placeholder-pool` (8 assertions) and `placeholder-component` (10 assertions). Existing tests must still pass.
- [ ] **Step 3: Run the production build**
```bash
cd web && pnpm build
```
Expected: exits 0. Confirms TypeScript still compiles end-to-end and the new CSS import is picked up by Vite.
- [ ] **Step 4: Manual visual check — start the dev server**
```bash
cd web && pnpm dev
```
In a browser, navigate to the running URL (Vite prints it). Sign in with any test account, open the **Inbox** page, and confirm:
1. When inbox is empty, the crested-parrot ASCII bird is visible.
2. It bobs gently every ~3.4 seconds.
3. The message text (one of "no unread", "no archived", or "no data") appears below with a soft fade-in.
4. The small `jgs · 4/97` credit is visible below the message.
5. No console errors or warnings.
Stop the dev server with `Ctrl+C`.
- [ ] **Step 5: (Optional) Reduced-motion check**
Open browser DevTools → command menu → "Emulate CSS prefers-reduced-motion: reduce". Reload the inbox empty state. The bird should be **static** and the message should appear instantly (no fade).
- [ ] **Step 6: No-op commit point**
If steps 14 all passed and no further changes were needed, there is nothing to commit. Proceed to the next task.
---
## Task 9: Document the work in the PR body
**Files:** none modified
- [ ] **Step 1: Draft a PR description**
When opening the PR, use a body like:
```markdown
## Summary
- Adds a new `<Placeholder variant="empty | loading | noResults | notFound">` component that renders a hand-curated ASCII bird from a pool-shaped data file, with subtle CSS-only motion that respects `prefers-reduced-motion`.
- Replaces the single-purpose `Empty.tsx` (used in `Inboxes.tsx`) with `<Placeholder variant="empty">`.
- ASCII art is from Joan Stark's (jgs) classic collection — attribution is preserved on every piece and in a co-located `CREDITS.md`.
## Out of scope (follow-up opportunities)
- Wire `<Placeholder variant="noResults">` into the memo search results page.
- Wire `<Placeholder variant="notFound">` into the router 404 catch-all.
- Wire `<Placeholder variant="loading">` into Suspense fallbacks.
- Seed additional ASCII pieces per variant — the pool architecture supports it; just append entries to `ASCII_POOL`.
## Test plan
- [ ] `pnpm lint` clean
- [ ] `pnpm test` green (incl. new `placeholder-pool` and `placeholder-component` suites)
- [ ] `pnpm build` succeeds
- [ ] Inbox empty state shows the ASCII parrot, bobs, and renders the filter-specific message
- [ ] `prefers-reduced-motion: reduce` produces a static bird and an instantly-visible message
```
- [ ] **Step 2: Open the PR** (skip if user prefers to do this themselves)
This step is left as a manual handoff — do not push or open the PR unless the user has explicitly authorized it.
---
## Self-Review Notes
This plan covers the spec's nine sections as follows:
| Spec section | Implemented by |
|---|---|
| Public Component | Task 5 |
| ASCII Pool | Tasks 1, 2 |
| Default Messages | Task 3 |
| Animation | Task 4 (CSS) + Task 5 (component wires classes) |
| Accessibility | Task 5 (test assertions + impl) |
| File Layout | Tasks 16 (all five files created) |
| Integration | Task 7 (Inboxes rewire + Empty delete) |
| Credits | Task 6 |
| Testing | Tasks 1, 3, 5 (pool tests + component tests) |
No spec section is unimplemented. No "TBD" / "TODO" / vague-handwave language is used in any step. Types, method signatures, and class names referenced across tasks match:
- `PlaceholderVariant`, `MotionStyle`, `AsciiPiece`, `ASCII_POOL`, `pickPiece` — consistent across Tasks 1, 2, 3, 5
- `DEFAULT_MESSAGES` — defined in Task 3, consumed in Task 5
- `placeholder-motion-bob`, `placeholder-motion-flutter`, `placeholder-fade-in` — defined in Task 4 CSS, consumed in Task 5 component
- `cn` from `@/lib/utils` — matches existing codebase convention (verified in pre-plan exploration)
- `Placeholder` is a default export — matches the convention used by `Empty.tsx` and most other `web/src/components/*.tsx` files
@@ -0,0 +1,673 @@
# Remove react-use Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Remove `react-use` from the frontend while preserving current hook behavior and eliminating the transitive `js-cookie@2.2.1` dependency.
**Architecture:** Replace simple one-off `react-use` helpers with native React hooks inside the consuming components. Add two focused local hooks in `web/src/hooks/` for reused debounce behavior and typed localStorage state. Regenerate the pnpm lockfile from `web/package.json` instead of manually editing lockfile entries.
**Tech Stack:** React 19, TypeScript 6, Vite 8, Vitest 4, Testing Library, pnpm 11.
---
## File Structure
- Create `web/src/hooks/useDebouncedEffect.ts`
- Shared debounce hook for effect-style callbacks.
- Create `web/src/hooks/useLocalStorage.ts`
- Typed localStorage state hook for persisted UI preferences.
- Modify `web/src/hooks/index.ts`
- Export the two new hooks for existing `@/hooks` barrel import style.
- Create `web/tests/hooks.test.tsx`
- Unit tests for the two new local hooks.
- Modify `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`
- Replace `react-use` debounce import with local `useDebouncedEffect`.
- Modify `web/src/components/MemoEditor/hooks/useLinkMemo.ts`
- Replace deep `react-use` debounce import with local `useDebouncedEffect`.
- Modify `web/src/components/MemoExplorer/TagsSection.tsx`
- Replace deep `react-use` localStorage import with local `useLocalStorage`.
- Modify `web/src/components/TagTree.tsx`
- Replace `useToggle` with native `useState`.
- Modify `web/src/components/MobileHeader.tsx`
- Replace `useWindowScroll` with native `useState` and `useEffect`.
- Modify `web/src/layouts/RootLayout.tsx`
- Replace `usePrevious` with native `useRef` and `useEffect`.
- Modify `web/package.json`
- Remove the direct `react-use` dependency.
- Modify `web/pnpm-lock.yaml`
- Regenerate through pnpm after `react-use` is removed.
---
### Task 1: Add Failing Hook Tests
**Files:**
- Create: `web/tests/hooks.test.tsx`
- [ ] **Step 1: Write tests for local hook behavior**
Create `web/tests/hooks.test.tsx`:
```tsx
import { act, renderHook } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { useDebouncedEffect, useLocalStorage } from "@/hooks";
describe("useLocalStorage", () => {
beforeEach(() => {
window.localStorage.clear();
});
afterEach(() => {
window.localStorage.clear();
});
it("uses the default value when storage is empty", () => {
const { result } = renderHook(() => useLocalStorage("hook-test-empty", false));
expect(result.current[0]).toBe(false);
});
it("reads and writes JSON values", () => {
window.localStorage.setItem("hook-test-existing", JSON.stringify(true));
const { result } = renderHook(() => useLocalStorage("hook-test-existing", false));
expect(result.current[0]).toBe(true);
act(() => {
result.current[1](false);
});
expect(result.current[0]).toBe(false);
expect(window.localStorage.getItem("hook-test-existing")).toBe("false");
});
it("supports updater functions", () => {
const { result } = renderHook(() => useLocalStorage("hook-test-updater", false));
act(() => {
result.current[1]((current) => !current);
});
expect(result.current[0]).toBe(true);
expect(window.localStorage.getItem("hook-test-updater")).toBe("true");
});
it("falls back to the default value for malformed storage", () => {
window.localStorage.setItem("hook-test-malformed", "{bad json");
const { result } = renderHook(() => useLocalStorage("hook-test-malformed", true));
expect(result.current[0]).toBe(true);
});
});
describe("useDebouncedEffect", () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.runOnlyPendingTimers();
vi.useRealTimers();
});
it("runs the latest callback after the delay", () => {
const calls: string[] = [];
const { rerender } = renderHook(
({ value }) => {
useDebouncedEffect(
() => {
calls.push(value);
},
100,
[value],
);
},
{ initialProps: { value: "first" } },
);
act(() => {
vi.advanceTimersByTime(99);
});
expect(calls).toEqual([]);
rerender({ value: "second" });
act(() => {
vi.advanceTimersByTime(100);
});
expect(calls).toEqual(["second"]);
});
it("clears the pending timeout on unmount", () => {
const calls: string[] = [];
const { unmount } = renderHook(() => {
useDebouncedEffect(
() => {
calls.push("called");
},
100,
[],
);
});
unmount();
act(() => {
vi.advanceTimersByTime(100);
});
expect(calls).toEqual([]);
});
});
```
- [ ] **Step 2: Run tests and verify they fail because hooks do not exist**
Run:
```bash
cd web
pnpm test tests/hooks.test.tsx
```
Expected: FAIL with missing exports for `useDebouncedEffect` and `useLocalStorage` from `@/hooks`.
- [ ] **Step 3: Commit failing tests**
```bash
git add web/tests/hooks.test.tsx
git commit -m "test: cover local frontend hooks"
```
---
### Task 2: Implement Local Shared Hooks
**Files:**
- Create: `web/src/hooks/useDebouncedEffect.ts`
- Create: `web/src/hooks/useLocalStorage.ts`
- Modify: `web/src/hooks/index.ts`
- Test: `web/tests/hooks.test.tsx`
- [ ] **Step 1: Add `useDebouncedEffect`**
Create `web/src/hooks/useDebouncedEffect.ts`:
```ts
import { type DependencyList, useEffect } from "react";
export const useDebouncedEffect = (effect: () => void | Promise<void>, delay: number, deps: DependencyList): void => {
useEffect(() => {
const timeout = window.setTimeout(() => {
void effect();
}, delay);
return () => {
window.clearTimeout(timeout);
};
}, [delay, ...deps]);
};
```
- [ ] **Step 2: Add `useLocalStorage`**
Create `web/src/hooks/useLocalStorage.ts`:
```ts
import { useCallback, useEffect, useState } from "react";
type SetLocalStorageValue<T> = T | ((currentValue: T) => T);
const readLocalStorageValue = <T>(key: string, defaultValue: T): T => {
if (typeof window === "undefined") {
return defaultValue;
}
try {
const storedValue = window.localStorage.getItem(key);
return storedValue === null ? defaultValue : (JSON.parse(storedValue) as T);
} catch {
return defaultValue;
}
};
export const useLocalStorage = <T>(key: string, defaultValue: T): [T, (value: SetLocalStorageValue<T>) => void] => {
const [storedValue, setStoredValue] = useState<T>(() => readLocalStorageValue(key, defaultValue));
useEffect(() => {
setStoredValue(readLocalStorageValue(key, defaultValue));
}, [key, defaultValue]);
const setValue = useCallback(
(value: SetLocalStorageValue<T>) => {
setStoredValue((currentValue) => {
const nextValue = typeof value === "function" ? (value as (currentValue: T) => T)(currentValue) : value;
if (typeof window !== "undefined") {
try {
window.localStorage.setItem(key, JSON.stringify(nextValue));
} catch {
// Keep React state updated even if persistence is unavailable.
}
}
return nextValue;
});
},
[key],
);
return [storedValue, setValue];
};
```
- [ ] **Step 3: Export hooks from the barrel**
Modify `web/src/hooks/index.ts` to include:
```ts
export * from "./useAsyncEffect";
export * from "./useCurrentUser";
export * from "./useDateFilterNavigation";
export * from "./useDebouncedEffect";
export * from "./useFilteredMemoStats";
export * from "./useLoading";
export * from "./useLocalStorage";
export * from "./useMediaQuery";
export * from "./useMemoFilters";
export * from "./useMemoSorting";
export * from "./useNavigateTo";
export * from "./useUserLocale";
export * from "./useUserTheme";
```
- [ ] **Step 4: Run hook tests and verify they pass**
Run:
```bash
cd web
pnpm test tests/hooks.test.tsx
```
Expected: PASS for all `useLocalStorage` and `useDebouncedEffect` tests.
- [ ] **Step 5: Commit shared hooks**
```bash
git add web/src/hooks/useDebouncedEffect.ts web/src/hooks/useLocalStorage.ts web/src/hooks/index.ts web/tests/hooks.test.tsx
git commit -m "feat: add local frontend hooks"
```
---
### Task 3: Replace Simple react-use Helpers With React Hooks
**Files:**
- Modify: `web/src/components/TagTree.tsx`
- Modify: `web/src/components/MobileHeader.tsx`
- Modify: `web/src/layouts/RootLayout.tsx`
- [ ] **Step 1: Replace `useToggle` in `TagTree`**
In `web/src/components/TagTree.tsx`, change the imports:
```ts
import { ChevronRightIcon, HashIcon } from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { type MemoFilter, useMemoFilterContext } from "@/contexts/MemoFilterContext";
```
Replace the toggle state in `TagItemContainer` with:
```ts
const [showSubTags, setShowSubTags] = useState(false);
useEffect(() => {
setShowSubTags(expandSubTags);
}, [expandSubTags]);
```
Replace `handleToggleBtnClick` with:
```ts
const handleToggleBtnClick = useCallback((event: React.MouseEvent) => {
event.stopPropagation();
setShowSubTags((current) => !current);
}, []);
```
- [ ] **Step 2: Replace `useWindowScroll` in `MobileHeader`**
In `web/src/components/MobileHeader.tsx`, replace the first import with React hooks:
```ts
import { useEffect, useState } from "react";
import useMediaQuery from "@/hooks/useMediaQuery";
import { cn } from "@/lib/utils";
import NavigationDrawer from "./NavigationDrawer";
```
Inside `MobileHeader`, replace `const { y: offsetTop } = useWindowScroll();` with:
```ts
const [offsetTop, setOffsetTop] = useState(() => {
if (typeof window === "undefined") return 0;
return window.scrollY;
});
useEffect(() => {
const handleScroll = () => {
setOffsetTop(window.scrollY);
};
window.addEventListener("scroll", handleScroll, { passive: true });
handleScroll();
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
```
- [ ] **Step 3: Replace `usePrevious` in `RootLayout`**
In `web/src/layouts/RootLayout.tsx`, change the React import and remove the `react-use` import:
```ts
import { useEffect, useRef } from "react";
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
```
Replace:
```ts
const prevPathname = usePrevious(pathname);
```
with:
```ts
const prevPathnameRef = useRef<string | undefined>(undefined);
```
Replace the route filter clearing effect with:
```ts
useEffect(() => {
const prevPathname = prevPathnameRef.current;
// When the route changes and there is no filter in the search params, remove all filters.
if (prevPathname !== undefined && prevPathname !== pathname && !searchParams.has("filter")) {
removeFilter(() => true);
}
prevPathnameRef.current = pathname;
}, [pathname, searchParams, removeFilter]);
```
- [ ] **Step 4: Run TypeScript/lint check**
Run:
```bash
cd web
pnpm lint
```
Expected: PASS.
- [ ] **Step 5: Commit simple helper replacements**
```bash
git add web/src/components/TagTree.tsx web/src/components/MobileHeader.tsx web/src/layouts/RootLayout.tsx
git commit -m "refactor: replace simple react-use helpers"
```
---
### Task 4: Replace Debounce And LocalStorage Call Sites
**Files:**
- Modify: `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`
- Modify: `web/src/components/MemoEditor/hooks/useLinkMemo.ts`
- Modify: `web/src/components/MemoExplorer/TagsSection.tsx`
- Test: `web/tests/hooks.test.tsx`
- [ ] **Step 1: Update `InsertMenu` debounce import and call**
In `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`, remove:
```ts
import { useDebounce } from "react-use";
```
Add:
```ts
import { useDebouncedEffect } from "@/hooks";
```
Replace:
```ts
useDebounce(
() => {
setDebouncedPosition(locationState.position);
},
1000,
[locationState.position],
);
```
with:
```ts
useDebouncedEffect(
() => {
setDebouncedPosition(locationState.position);
},
1000,
[locationState.position],
);
```
- [ ] **Step 2: Update `useLinkMemo` debounce import and call**
In `web/src/components/MemoEditor/hooks/useLinkMemo.ts`, remove:
```ts
import useDebounce from "react-use/lib/useDebounce";
```
Add:
```ts
import { useDebouncedEffect } from "@/hooks";
```
Replace:
```ts
useDebounce(
```
with:
```ts
useDebouncedEffect(
```
Keep the existing async callback body, `300` delay, and `[isOpen, searchText]` dependency list unchanged.
- [ ] **Step 3: Update `TagsSection` localStorage import**
In `web/src/components/MemoExplorer/TagsSection.tsx`, replace:
```ts
import useLocalStorage from "react-use/lib/useLocalStorage";
```
with:
```ts
import { useLocalStorage } from "@/hooks";
```
Keep both call sites unchanged:
```ts
const [treeMode, setTreeMode] = useLocalStorage<boolean>("tag-view-as-tree", false);
const [treeAutoExpand, setTreeAutoExpand] = useLocalStorage<boolean>("tag-tree-auto-expand", false);
```
- [ ] **Step 4: Verify no source imports from `react-use` remain**
Run:
```bash
rg -n 'react-use' web/src web/package.json
```
Expected: only `web/package.json` still reports `react-use` before the dependency removal task.
- [ ] **Step 5: Run targeted hook tests and lint**
Run:
```bash
cd web
pnpm test tests/hooks.test.tsx
pnpm lint
```
Expected: both commands PASS.
- [ ] **Step 6: Commit call-site replacements**
```bash
git add web/src/components/MemoEditor/Toolbar/InsertMenu.tsx web/src/components/MemoEditor/hooks/useLinkMemo.ts web/src/components/MemoExplorer/TagsSection.tsx web/tests/hooks.test.tsx
git commit -m "refactor: use local debounce and storage hooks"
```
---
### Task 5: Remove react-use Dependency And Regenerate Lockfile
**Files:**
- Modify: `web/package.json`
- Modify: `web/pnpm-lock.yaml`
- [ ] **Step 1: Remove `react-use` from `web/package.json`**
In `web/package.json`, remove this dependency line:
```json
"react-use": "^17.6.0",
```
Do not add `js-cookie` as a direct dependency.
- [ ] **Step 2: Regenerate the lockfile**
Run:
```bash
cd web
pnpm install --lockfile-only
```
Expected: command succeeds and updates `web/pnpm-lock.yaml`.
- [ ] **Step 3: Verify dependency graph removal**
Run:
```bash
cd web
pnpm why react-use js-cookie
```
Expected: output does not list installed versions for `react-use` or `js-cookie`.
- [ ] **Step 4: Verify repository text references**
Run:
```bash
rg -n '"react-use"|react-use/lib|react-use@17\.6\.0|^\s+react-use:|js-cookie' web/package.json web/pnpm-lock.yaml web/src
```
Expected: no matches.
- [ ] **Step 5: Commit dependency removal**
```bash
git add web/package.json web/pnpm-lock.yaml
git commit -m "chore: remove react-use dependency"
```
---
### Task 6: Final Verification
**Files:**
- Verify: all files changed by Tasks 1-5
- [ ] **Step 1: Run frontend tests for the new hook coverage**
Run:
```bash
cd web
pnpm test tests/hooks.test.tsx
```
Expected: PASS.
- [ ] **Step 2: Run frontend lint**
Run:
```bash
cd web
pnpm lint
```
Expected: PASS.
- [ ] **Step 3: Run frontend build**
Run:
```bash
cd web
pnpm build
```
Expected: PASS.
- [ ] **Step 4: Confirm no removed dependency remains**
Run:
```bash
cd web
pnpm why react-use js-cookie
rg -n '"react-use"|react-use/lib|react-use@17\.6\.0|^\s+react-use:|js-cookie' src package.json pnpm-lock.yaml
```
Expected: no `react-use` or `js-cookie` dependency remains. The `rg` command returns no matches.
- [ ] **Step 5: Inspect final diff**
Run:
```bash
git diff --stat HEAD~5..HEAD
git status --short
```
Expected: diff contains only hook tests, local hooks, six call-site rewrites, and dependency files. Working tree is clean after all task commits.
@@ -0,0 +1,124 @@
# ActivityCalendar: Honor `timeBasis` (Create vs Update)
## Problem
The ActivityCalendar in `web/src/components/ActivityCalendar/` always aggregates by memo creation time, regardless of how the surrounding memo list is sorted.
The application already supports a global "time basis" toggle (`web/src/contexts/ViewContext.tsx:3`):
```ts
export type MemoTimeBasis = "create_time" | "update_time";
```
The toggle is persisted in `localStorage` and drives memo list ordering across the app. When a user switches the list to `update_time`, the heatmap below it continues to show creation counts — the two views literally disagree about what "today" means.
This is the user-visible bug we are fixing.
## Non-goals
The following were considered and explicitly excluded:
- **Tracking every individual edit event.** This would require resurrecting the `activity` table that was deliberately dropped in migration `0.27/03__drop_activity.sql`. The cost (write-path instrumentation, storage growth, privacy review) is not justified by this UI bug.
- **Tracking archive / restore / delete events.** Housekeeping actions, not contributions; would also leak private behavior on public Profile/Explore pages.
- **Adding comments or reactions to the heatmap count.** A reasonable separate feature, but a different decision (event-type expansion). Out of scope for this spec — one ticket, one problem.
- **Renaming `ActivityCalendar` to `ContributionCalendar`.** Out of scope.
## Design
### Semantics
The heatmap aggregates one timestamp per memo:
- When `timeBasis === "create_time"`: use `memo.created_ts` (current behavior).
- When `timeBasis === "update_time"`: use `memo.updated_ts`.
Each memo contributes exactly one cell of color, on the day of its chosen timestamp. This matches the list view's semantics exactly: in `update_time` mode, a memo edited on 5/1 and again on 5/2 appears once at 5/2 in the list, and the heatmap will show +1 on 5/2 and nothing on 5/1. The "lossiness" is identical to the lossiness already accepted by the list view — so by definition, the two are consistent.
### Backend
`UserStats` (proto/api/v1/user_service.proto) gains one field:
```proto
// The latest update timestamps of the user's memos.
repeated google.protobuf.Timestamp memo_updated_timestamps = 8;
```
The implementation mirrors `memo_created_timestamps` in `server/router/api/v1/user_service_stats.go`: in the same loop that appends `memo.CreatedTs` (line 115), also append `memo.UpdatedTs` to a parallel slice. The same `FindMemo` filters apply automatically: `RowStatus: NORMAL` (archived excluded), `ExcludeComments: true`, and the viewer-based visibility filter. Both `GetUserStats` and `ListAllUserStats` paths must be updated symmetrically.
No DB migration. No new tables. No new write paths.
### Frontend
`web/src/hooks/useFilteredMemoStats.ts` reads `useView().timeBasis` and switches its data source:
- `create_time``userStats.memoCreatedTimestamps` (today's behavior, untouched)
- `update_time``userStats.memoUpdatedTimestamps`
The `explore` context branch (which derives stats from the in-memory memo list rather than `userStats`) applies the same switch using `memo.createTime` vs `memo.updateTime` from the cached memos.
The `MonthCalendar` / `YearCalendar` components themselves require no changes — they receive an opaque `Record<date, count>` and render it. The change is confined to the data-source layer.
### Tooltip / labeling
A small but necessary clarification for the user: the cell tooltip should reflect which basis is active, e.g.
- `create_time` mode: "3 memos on May 2"
- `update_time` mode: "3 memos updated on May 2"
This belongs in `ActivityCalendar/utils.ts:getTooltipText`, which already takes a `t` translator. Add a `timeBasis` argument and pick the right i18n key.
## Components
| Unit | Responsibility | Depends on |
|---|---|---|
| `UserStats` proto | Carry both timestamp arrays | — |
| `GetUserStats` server impl | Populate both arrays from `memo` table | store |
| `useFilteredMemoStats` | Pick the correct array based on `timeBasis`; aggregate by day | `useView`, `useUserStats`, `useMemos` |
| `getTooltipText` | Render basis-aware tooltip | i18n |
| `MonthCalendar` / `YearCalendar` | Unchanged — render `Record<date, count>` | — |
## Data flow
```
ViewContext.timeBasis ──┐
useFilteredMemoStats ── pick array ── countBy(day) ── Record<date,count> ── MonthCalendar
userStats ───────────┤ (memo_created_timestamps OR memo_updated_timestamps)
memos cache ─────────┘ (createTime OR updateTime — explore context only)
```
## Error handling
No new failure modes.
`protobuf-es` generates `repeated` fields as non-optional `T[]`, so an older server that doesn't populate the new field deserializes it as `[]` (never `undefined`). Naïvely treating empty as "no data" would be wrong, because a user with zero memos also gets `[]`. Detection uses **length divergence**: since `memo.updated_ts` is initialized to `created_ts` at row creation, the two arrays are the same length whenever there are any memos. So:
- `created.length === 0 && updated.length === 0` — user has no memos, render empty.
- `created.length > 0 && updated.length === created.length` — new server, normal path.
- `created.length > 0 && updated.length === 0` — old server, fall back to `memoCreatedTimestamps` regardless of `timeBasis`, with a one-line `console.warn`.
## Testing
- Unit test `useFilteredMemoStats`: given a fixed `userStats`, switching `timeBasis` returns aggregations matching the expected source array.
- Unit test the new `getTooltipText` branch.
- Manual verification: in dev, toggle the global time basis and confirm:
- Heatmap recomputes
- A memo edited yesterday but created last week shows up "yesterday" in update mode and "last week" in create mode
- Tooltip text reflects the basis
## Migration / compatibility
- Proto field is additive (tag 8 is unused; tag 2 is `reserved`).
- Old clients ignore the new field.
- New clients tolerate old servers via the fallback above.
- No DB migration.
- No data backfill — `updated_ts` already exists on every memo row.
## Out-of-scope follow-ups (not part of this work)
These came up during brainstorming and are tracked here only so they aren't lost:
1. Adding comment / reaction event types to the heatmap count.
2. A "Memo History / Versions" feature (per-edit snapshots, diffs, optional commit messages). If pursued, the heatmap would become a downstream consumer of that history, and the field added here may be revisited.
@@ -0,0 +1,165 @@
# Create memo on selected calendar date — design
**Date:** 2026-05-02
**Scope:** Frontend-only.
## Problem
Clicking a date in the activity calendar filters the memo list to that date but does nothing for the inline editor. To create a memo dated for the selected day, the user must (1) create with today's timestamp, then (2) open the timestamp popover on the saved memo and edit `createTime`. This is a two-step retro-fill that defeats the calendar selection. Empty dates are also not clickable today, so the user cannot start the first memo for an empty day from the calendar at all.
## Goal
When a user picks a calendar date and immediately writes in the home editor, the resulting memo is created on that date — single-step.
## Non-goals
- Backend changes. The API already accepts custom `createTime` and `updateTime`.
- Changes to the comment/reply editor or the edit-mode editor.
- Changes outside the home page's editor render site (Explore/Archived/Profile pages have no editor).
- Reworking the timestamp popover UI itself.
- Empty-state copy changes on non-Home pages when an empty date is selected.
## User-visible behavior
1. **Empty calendar dates are clickable.** Clicking a date with zero memos sets the `displayTime` filter the same way a populated date does. Tooltip and selection ring still work.
2. **When the home editor renders with an active `displayTime` filter:**
- The `TimestampPopover` (already used in edit mode) appears in create mode, pre-populated with the selected date.
- The draft's `createTime` is set to **selected local date + current local hh:mm:ss** (e.g., picking May 1 at 14:32 → `2025-05-01 14:32`).
- The draft's `updateTime` is set to the same value, to avoid the saved memo immediately reading "updated today" relative to a back-dated `createTime`.
- The user can adjust either field via the popover before saving.
3. **When no `displayTime` filter is active**, the editor is identical to today: no popover in create mode, no override, server stamps with "now".
4. **Live derivation.** If the filter changes while a draft is in progress, the editor's prefilled timestamps re-sync to the new date. The popover stays visible so the change is observable. (Manual popover edits before the next filter change are overwritten — chosen tradeoff.)
5. **Future dates are allowed** (e.g., May 15 when today is May 2). Backend already accepts future timestamps.
6. **Other contexts** (Explore/Archived/Profile) gain empty-date clickability for navigation consistency, but have no editor and so no prefill behavior.
## Architecture
Four touch points, all in `web/src/`:
| File | Change |
|------|--------|
| `components/ActivityCalendar/CalendarCell.tsx` | Drop `day.count > 0` gate so empty in-month cells are clickable. |
| `components/MemoEditor/index.tsx` | Accept `defaultCreateTime?: Date` prop; render `TimestampPopover` in create mode when set; sync state on prop change. |
| `components/MemoEditor/utils/deriveDefaultCreateTime.ts` (new) | Pure helper: `(filters, now?) => Date \| undefined` derived from any `displayTime` filter. |
| `components/PagedMemoList/PagedMemoList.tsx` | At the home-editor render site (line 155), read `MemoFilterContext`, compute `defaultCreateTime`, pass as prop. |
### Data flow
```
CalendarCell click
→ useDateFilterNavigation
→ URL ?filter=displayTime:YYYY-MM-DD
→ MemoFilterContext re-renders
→ PagedMemoList recomputes defaultCreateTime via deriveDefaultCreateTimeFromFilters(filters)
→ <MemoEditor defaultCreateTime={...}> re-renders
→ editor reducer syncs state.timestamps (create + update) and renders TimestampPopover
→ save → memoService.ts:111 sends createTime/updateTime to API
```
## Component contracts
### `MemoEditor` — new prop
```ts
interface MemoEditorProps {
// ...existing props
/**
* When set in create mode (no `memo` prop), seeds the draft's
* createTime/updateTime and reveals the TimestampPopover so the
* user can adjust. Tracked live: changes after mount re-sync state.
* Ignored in edit mode (when `memo` is set).
*/
defaultCreateTime?: Date;
}
```
Internal behavior:
- On `INIT_MEMO` for create mode, if `defaultCreateTime` is set, payload `timestamps` is `{ createTime: defaultCreateTime, updateTime: defaultCreateTime }`.
- A `useEffect` keyed on `[defaultCreateTime?.getTime(), memo]` dispatches `SET_TIMESTAMPS` whenever the prop changes in create mode.
- Popover render condition becomes `memoName || (!memo && state.timestamps.createTime)`.
### `deriveDefaultCreateTimeFromFilters` — pure helper
```ts
// web/src/components/MemoEditor/utils/deriveDefaultCreateTime.ts
export function deriveDefaultCreateTimeFromFilters(
filters: MemoFilter[],
now: Date = new Date(),
): Date | undefined {
const dateFilter = filters.find((f) => f.factor === "displayTime");
if (!dateFilter) return undefined;
const [y, m, d] = dateFilter.value.split("-").map(Number);
if (!y || !m || !d) return undefined;
return new Date(y, m - 1, d, now.getHours(), now.getMinutes(), now.getSeconds());
}
```
Notes:
- Defensive parse — returns `undefined` for malformed values rather than throwing.
- `now` is injectable for deterministic tests.
- Multiple `displayTime` filters are not produced by current UI; `find` ignores extras safely.
### `PagedMemoList.tsx` — call-site change
```tsx
const { filters } = useMemoFilterContext();
const defaultCreateTime = useMemo(
() => deriveDefaultCreateTimeFromFilters(filters),
[filters],
);
// ...
{showMemoEditor ? (
<MemoEditor
className="mb-2"
cacheKey="home-memo-editor"
placeholder={t("editor.any-thoughts")}
defaultCreateTime={defaultCreateTime}
/>
) : null}
```
`useMemo` keyed on `filters` keeps the reference stable when the filter doesn't change, avoiding unnecessary editor re-syncs. `now` is captured once per filter change — matches "the local time when you picked the date".
### `CalendarCell.tsx` — empty-cell clickability
- `handleClick`: drop the `day.count > 0` check; just call `onClick(day.date)` if `onClick` is provided.
- `isInteractive`: `Boolean(onClick)`.
- `tabIndex` / `aria-disabled` / hover-cursor classes follow the new `isInteractive`.
- `shouldShowTooltip`: drop the `day.count > 0` gate; tooltip text already conveys the count.
- Out-of-month cells (existing early return) stay unclickable.
- The `selected` ring already works on count=0 cells. Visual contrast on the lowest-intensity background may need a small ring-weight bump in light theme; eyeball during implementation.
## Edge cases
- **No filter / filter cleared:** `defaultCreateTime` becomes `undefined`; editor falls back to current behavior.
- **User edits draft, then re-picks date:** live-derived; editor's `createTime` updates, popover reflects new value.
- **User manually edits via popover, then changes filter:** prop sync overwrites manual edit. Acceptable per design choice; popover keeps the change observable.
- **Draft cache (`cacheKey="home-memo-editor"`):** caches `content`, not `timestamps`. Reload restores text but `createTime` is freshly derived from current filter — consistent.
- **Future dates:** allowed. No clamp.
- **DST / timezone:** date arithmetic uses local time (`new Date(y, m-1, d, h, mi, s)`), matching `useDateFilterNavigation`'s local-date convention. Server receives an absolute `Timestamp`.
- **Comment editor (`MemoCommentSection`):** doesn't pass `defaultCreateTime` → no behavior change.
- **Edit mode (`memo` prop set):** prop is ignored; existing edit-mode popover is unchanged.
- **Empty-date click on Explore/Archived/Profile:** filters to empty date → "no memos" empty state. Acceptable.
## Testing
- **Unit (Vitest)** for `deriveDefaultCreateTimeFromFilters`:
- no `displayTime` filter → `undefined`
- valid `displayTime:2025-05-01` + injected `now=14:32:10``2025-05-01 14:32:10` local
- malformed value (`"not-a-date"`, `"2025-13-40"`) → `undefined`
- extra non-`displayTime` filters present → still works
- **Component (React Testing Library) for `CalendarCell`:** count=0 in-month cell is clickable, has correct `tabIndex`/`aria-disabled`, fires `onClick` with date.
- **Component for `MemoEditor`:** with `defaultCreateTime` prop, popover renders in create mode and `state.timestamps.createTime` matches; without prop, no popover; changing the prop re-syncs state.
- **Manual smoke (per CLAUDE.md UI-changes rule):** `pnpm dev`, click a non-today date (with and without existing memos), type a memo, save, confirm it appears under that date. Clear the filter chip; confirm a new memo posts to today.
## Risks
- The `useEffect` re-sync overwriting an in-progress popover edit is a *chosen* behavior. If users later complain, a "manual override sticky" flag is the natural follow-up. Not pre-built.
- Selection-ring contrast on the lowest-intensity background may need a small visual tweak; flagged for implementation.
## Out of scope (explicit)
- Sticky manual-override semantics for the popover.
- New empty-state copy on Explore/Archived/Profile when filtering to a date with zero memos.
- Any backend/API change.
- Any change to the comment editor, edit mode, or non-Home editor sites.
@@ -0,0 +1,511 @@
# STT and Audio-LLM Split — Design Spec
**Date:** 2026-05-02
**Status:** Draft, pending user review
## 1. Goal
Refactor `internal/ai/` to split **speech-to-text (STT)** and **audio-multimodal-LLM (Audio-LLM)** into two separate Go interfaces, aligning with mainstream OSS conventions (Vercel AI SDK, LiteLLM, the Go AI ecosystem). Update the public API handler to dispatch to the right interface based on provider type. Make two small comment improvements to `proto/store/instance_setting.proto` and the generated bindings; **no proto field changes**.
## 2. Non-Goals
The following are intentionally **out of scope** for this design:
- **`enabled` boolean field on `TranscriptionConfig`** (improvement #1 from the brainstorming) — keep using `provider_id == ""` as the disabled signal.
- **Direction C (audio → structured note pipeline)** — auto-summarization / tag extraction. Independent future feature.
- **Multi-provider STT with default-model selector** (Dify-style) — Memos has a single transcription config; that stays.
- **Per-model credential overrides**, **load balancing**, **capability YAML schemas** — Dify-style enterprise complexity.
- **Streaming transcription, retry policy, OpenAI Translations endpoint** — YAGNI.
- **`gpt-4o-audio-preview` user-facing support** — the `audiollm/openai` package will be implementable after this refactor, but UI support is a follow-up.
- **TTS** (text-to-speech) — different concern, not affected.
## 3. Background
The current `internal/ai/` has one `Transcriber` interface with two implementations: `openAITranscriber` (calls `/audio/transcriptions`, a real STT endpoint) and `geminiTranscriber` (calls `generateContent`, a multimodal-LLM endpoint dressed up to act like STT). This conflation has caused real symptoms:
- `TranscribeResponse.Language` and `Duration` are silently empty for Gemini (Gemini multimodal doesn't return them).
- The `Prompt` field has different semantics across providers — Whisper treats it as a soft hint that may be ignored; Gemini treats it as a literal instruction.
- Gemini's multimodal failure modes (safety filter, token-truncation, refusals) are flattened to a single "did not include text" error.
- Gemini-specific code (WebM transcoding, `maxGeminiInlineAudioSize`, `genai` SDK) lives in the same package as the OpenAI Whisper integration.
The brainstorming session (this conversation, 2026-05-02) ran two rounds of OSS research to validate the corrective direction.
## 4. Research Findings Summary
Detailed findings in conversation history; abridged here for design accountability.
### 4.1 SDK-Layer Research
| Source | Key Decision |
|---|---|
| **Vercel AI SDK** (`vercel/ai`) | `TranscriptionModelV3` is implemented **only** by providers with a dedicated STT endpoint (OpenAI Whisper/gpt-4o-transcribe, Deepgram, ElevenLabs, AssemblyAI). **Google provider deliberately does not implement it** — Gemini audio rides through `generateText` with `FilePart`. Two completely separate code paths. No "source" discriminator. Provider id is `vendor.modality` (`openai.transcription`); model is a free string. |
| **LiteLLM** (`BerriAI/litellm`) | `litellm.transcription()` only routes to providers with `/audio/transcriptions`-style endpoints. **Gemini is absent** from the transcription router (`litellm/llms/gemini/` has no `audio_transcription/` subdirectory). Multimodal audio rides through `litellm.completion()` with `{"type":"input_audio"}` content parts. Response is `text + usage`, no provider discriminator. |
| **Go AI SDKs** (`cloudwego/eino`, `tmc/langchaingo`, `sashabaranov/go-openai`) | One package per provider; provider identity = import path; **no provider enum**. `Model` is opaque string. OpenAI-compatible endpoints handled via `BaseURL` config field, never via separate package. go-openai's `audio.go` is structurally separate from `chat.go`. |
**Convergent finding:** All three ecosystems split STT and multimodal-audio into separate interfaces. None expose a "this came from a multimodal LLM" discriminator. None encode wire-format into the provider type enum.
### 4.2 Application-Layer Research
| Source | STT-Storage Design |
|---|---|
| **Open WebUI** | STT is a **flat singleton config block** (`audio.stt.*` namespace), completely separate from chat providers (`openai.*` namespace). `STT_ENGINE` enum dispatches; per-engine credentials side-by-side in one config. |
| **LobeChat** | STT is a **separate global user setting** (`UserTTSConfig`). But credentials silently piggyback on the `openai` chat provider's `keyVaults` — author has marked the helper `@deprecated`. |
| **Dify** | `ProviderEntity.supported_model_types` declares capabilities; STT is the `SPEECH2TEXT` enum value. STT info lives in a **separate "system model" config row** (`tenant_default_models(model_type='speech2text', provider_name, model_name)`) that **references** an existing provider. |
**Convergent finding:** Zero apps add STT-specific fields onto the AI provider entity. All three keep providers capability-agnostic and put STT config in a separate place.
### 4.3 Proto Schema Assessment
The current `proto/store/instance_setting.proto` `InstanceAISetting` + `TranscriptionConfig` is **already aligned with the mainstream pattern**:
-`AIProviderConfig` carries no STT-specific field (capability-agnostic)
-`TranscriptionConfig` is a separate pointer (`provider_id` references a provider)
-`AIProviderType` is vendor-level (`OPENAI`, `GEMINI`) — no wire-format suffix
-`model` is a free string
- ✅ Comments already document Whisper vs Gemini prompt semantics (though could be clearer)
The proto schema requires **no field changes**. Only two comment improvements (§7 below).
## 5. Current State (Files Touched)
```
internal/ai/
ai.go # ProviderType, ProviderConfig, errors
client.go # NewTranscriber factory, transcriberOptions, normalizeEndpoint, requireAPIKey
transcription.go # Transcriber interface, TranscribeRequest, TranscribeResponse
openai.go # openAITranscriber → /audio/transcriptions
openai_test.go
gemini.go # geminiTranscriber → generateContent (multimodal)
gemini_test.go
models.go # DefaultOpenAITranscriptionModel, DefaultGeminiTranscriptionModel
resolver.go # FindProvider
errors.go # ErrProviderNotFound, ErrCapabilityUnsupported
audio/
webm.go # IsWebMContentType, WebMOpusToWAV (used by Gemini path)
webm_test.go
server/router/api/v1/
ai_service.go # Transcribe handler (lines 42123)
proto/store/
instance_setting.proto # InstanceAISetting, AIProviderConfig, AIProviderType, TranscriptionConfig
web/src/components/Settings/
AISection.tsx # Provider list UI, TranscriptionForm
```
The handler at `server/router/api/v1/ai_service.go:42` is the **single integration point** between proto config and the `internal/ai/` SDK. It already discards Language/Duration (returns `{Text}` only), so the response narrowing is already in place.
## 6. Target Design
### 6.1 Package Structure
```
internal/ai/
ai.go # ProviderType (unchanged: OPENAI, GEMINI), ProviderConfig (unchanged)
resolver.go # FindProvider (unchanged)
errors.go # add ErrSTTNotSupported, ErrAudioLLMNotSupported
audio/
webm.go # unchanged — moves with audiollm/gemini consumer
webm_test.go
stt/
stt.go # Transcriber interface, Request, Response, Segment
factory.go # NewTranscriber(cfg ai.ProviderConfig, opts...) (Transcriber, error)
options.go # TranscriberOption, WithHTTPClient
openai/
openai.go # openAITranscriber → POST /audio/transcriptions
openai_test.go
audiollm/
audiollm.go # Model interface, Request, Response, FinishReason
factory.go # NewModel(cfg ai.ProviderConfig, opts...) (Model, error)
options.go # ModelOption, WithHTTPClient
gemini/
gemini.go # geminiModel → POST :generateContent (multimodal audio)
gemini_test.go
# openai/ — NOT created in this refactor; reserved for future gpt-4o-audio support
```
**Rationale (Go-ecosystem convention, per §4.1):** one package per provider; provider identity is import path; capability is implied by which umbrella package (`stt` vs `audiollm`) you import from. The runtime dispatch (factory) is the only place that translates `ProviderConfig.Type` enum → concrete implementation.
### 6.2 Interfaces
#### `internal/ai/stt/stt.go`
```go
package stt
import (
"context"
"io"
)
// Transcriber transcribes audio into text using a provider's dedicated STT endpoint
// (e.g. OpenAI /audio/transcriptions). Implementations are deterministic STT —
// they are NOT for multimodal LLMs that happen to accept audio input. For
// multimodal audio understanding, see internal/ai/audiollm.
type Transcriber interface {
Transcribe(ctx context.Context, req Request) (*Response, error)
}
type Request struct {
Audio io.Reader
Size int64
Filename string
ContentType string // IANA media type, e.g. "audio/wav"
Model string // provider-specific model id (e.g. "whisper-1", "gpt-4o-transcribe")
Prompt string // soft spelling/vocabulary hint (Whisper "prompt" parameter)
Language string // ISO 639-1, optional
}
type Response struct {
Text string
Language string // empty if provider did not return it (best-effort)
Segments []Segment // empty unless provider returned timestamps
}
type Segment struct {
Text string
Start float64
End float64
Speaker string // empty unless using a diarization-capable model (e.g. gpt-4o-transcribe-diarize)
}
```
#### `internal/ai/audiollm/audiollm.go`
```go
package audiollm
import (
"context"
"io"
)
// Model invokes a multimodal LLM with audio input. Implementations call
// chat-completions or generate-content style APIs that happen to accept audio.
// They are NOT deterministic STT — outputs may be refused, truncated, or
// rephrased per the LLM's behavior. For pure transcription, prefer
// internal/ai/stt where available.
type Model interface {
GenerateFromAudio(ctx context.Context, req Request) (*Response, error)
}
type Request struct {
Audio io.Reader
Size int64
ContentType string
Model string
Instructions string // literal instruction the model is expected to follow
Temperature *float32 // optional; nil leaves provider default
}
type Response struct {
Text string
FinishReason FinishReason
}
type FinishReason string
const (
FinishStop FinishReason = "stop" // model finished normally
FinishLength FinishReason = "length" // truncated by max-tokens
FinishSafety FinishReason = "safety" // safety filter blocked output
FinishOther FinishReason = "other" // anything else (incl. unknown)
)
```
#### Factory dispatch
```go
// internal/ai/stt/factory.go
package stt
import (
"github.com/pkg/errors"
"github.com/usememos/memos/internal/ai"
"github.com/usememos/memos/internal/ai/stt/openai"
)
func NewTranscriber(cfg ai.ProviderConfig, opts ...TranscriberOption) (Transcriber, error) {
switch cfg.Type {
case ai.ProviderOpenAI:
return openai.New(cfg, applyOptions(opts...))
case ai.ProviderGemini:
return nil, errors.Wrapf(ai.ErrSTTNotSupported,
"Gemini does not provide a dedicated STT endpoint; use audiollm.NewModel instead")
default:
return nil, errors.Wrapf(ai.ErrCapabilityUnsupported, "provider type %q", cfg.Type)
}
}
```
```go
// internal/ai/audiollm/factory.go
package audiollm
import (
"github.com/pkg/errors"
"github.com/usememos/memos/internal/ai"
"github.com/usememos/memos/internal/ai/audiollm/gemini"
)
func NewModel(cfg ai.ProviderConfig, opts ...ModelOption) (Model, error) {
switch cfg.Type {
case ai.ProviderGemini:
return gemini.New(cfg, applyOptions(opts...))
case ai.ProviderOpenAI:
// NOTE: gpt-4o-audio-preview support belongs here but is out of scope;
// see §2 (Non-Goals).
return nil, errors.Wrapf(ai.ErrAudioLLMNotSupported,
"OpenAI multimodal audio (gpt-4o-audio) is not yet implemented in this codebase")
default:
return nil, errors.Wrapf(ai.ErrCapabilityUnsupported, "provider type %q", cfg.Type)
}
}
```
### 6.3 Backend Handler Dispatch
The handler at `server/router/api/v1/ai_service.go:Transcribe` dispatches based on `provider.Type`:
```go
func (s *APIV1Service) Transcribe(ctx context.Context, request *v1pb.TranscribeRequest) (*v1pb.TranscribeResponse, error) {
// ... existing config loading, provider resolution, audio reading ...
switch provider.Type {
case ai.ProviderOpenAI:
text, err := s.transcribeViaSTT(ctx, provider, transcriptionCfg, audio, contentType)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to transcribe: %v", err)
}
return &v1pb.TranscribeResponse{Text: text}, nil
case ai.ProviderGemini:
text, err := s.transcribeViaAudioLLM(ctx, provider, transcriptionCfg, audio, contentType)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to transcribe: %v", err)
}
return &v1pb.TranscribeResponse{Text: text}, nil
default:
return nil, status.Errorf(codes.FailedPrecondition,
"provider type %q is not supported for transcription", provider.Type)
}
}
func (s *APIV1Service) transcribeViaSTT(ctx context.Context, provider ai.ProviderConfig,
cfg *storepb.TranscriptionConfig,
audio io.Reader, contentType string) (string, error) {
t, err := stt.NewTranscriber(provider)
if err != nil { return "", err }
resp, err := t.Transcribe(ctx, stt.Request{
Audio: audio,
Filename: "audio",
ContentType: contentType,
Model: resolveModel(provider, cfg.Model),
Prompt: cfg.Prompt, // Whisper: soft hint, may be ignored
Language: cfg.Language,
})
if err != nil { return "", err }
return resp.Text, nil
}
func (s *APIV1Service) transcribeViaAudioLLM(ctx context.Context, provider ai.ProviderConfig,
cfg *storepb.TranscriptionConfig,
audio io.Reader, contentType string) (string, error) {
m, err := audiollm.NewModel(provider)
if err != nil { return "", err }
resp, err := m.GenerateFromAudio(ctx, audiollm.Request{
Audio: audio,
ContentType: contentType,
Model: resolveModel(provider, cfg.Model),
Instructions: buildTranscriptionInstructions(cfg.Prompt, cfg.Language),
})
if err != nil { return "", err }
if resp.FinishReason != audiollm.FinishStop {
return "", errors.Errorf("transcription incomplete (finish reason: %s)", resp.FinishReason)
}
return resp.Text, nil
}
```
`buildTranscriptionInstructions` lives next to the handler and centralizes the literal instruction sent to multimodal LLMs:
```go
func buildTranscriptionInstructions(prompt, language string) string {
parts := []string{
"Transcribe the audio accurately. Return only the transcript text. " +
"Do not summarize, explain, or add content that is not spoken.",
}
if language != "" {
parts = append(parts, fmt.Sprintf("The input language is %s.", language))
}
if prompt != "" {
parts = append(parts, "Context and spelling hints:\n"+prompt)
}
return strings.Join(parts, "\n\n")
}
```
`resolveModel` returns `cfg.Model` if non-empty, else the per-provider default from `ai/models.go` (unchanged from today).
### 6.4 Implementation Notes Per Package
#### `internal/ai/stt/openai/openai.go`
- Identical wire behavior to current `internal/ai/openai.go::openAITranscriber.Transcribe`.
- Uses `github.com/openai/openai-go/v3` SDK (already a dep).
- Defaults `endpoint` to `https://api.openai.com/v1`. Trims trailing slash. Validates URL.
- Honors `cfg.Endpoint` to support OpenAI-compatible providers (Groq Whisper, faster-whisper self-hosted, Azure Whisper deployments). The user simply adds another `AIProviderConfig` row with `Type=OPENAI` and a different `Endpoint`.
- Supports any model the underlying endpoint accepts: `whisper-1`, `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-transcribe-diarize`, etc. The model string is opaque.
- Returns `Response.Language` and `Response.Segments` populated when the API returns them; otherwise empty.
#### `internal/ai/audiollm/gemini/gemini.go`
- Identical wire behavior to current `internal/ai/gemini.go::geminiTranscriber.Transcribe`, EXCEPT:
- Reads `Instructions` from the caller (not hardcoded inside the package).
- Maps `genai.FinishReason` to `audiollm.FinishReason` (`STOP→FinishStop`, `MAX_TOKENS→FinishLength`, `SAFETY→FinishSafety`, anything else → `FinishOther`).
- Returns `Response{Text, FinishReason}` instead of swallowing the finish reason into a generic error.
- Continues to use `internal/ai/audio.WebMOpusToWAV` for WebM transcoding (Gemini doesn't accept WebM).
- Continues to enforce `maxGeminiInlineAudioSize` (14 MiB) — File API support is out of scope.
- Uses `google.golang.org/genai` SDK (already a dep).
#### `internal/ai/errors.go`
Add:
```go
var ErrSTTNotSupported = errors.New("provider does not support speech-to-text capability")
var ErrAudioLLMNotSupported = errors.New("provider does not support multimodal audio capability")
```
Keep existing `ErrProviderNotFound` and `ErrCapabilityUnsupported`.
### 6.5 Proto Schema Changes
**Two comment-only updates. No field additions, no field renames, no breaking changes.**
#### Improvement #2 — `TranscriptionConfig.model` comment
Replace lines 179181 of `proto/store/instance_setting.proto`:
```proto
// model is the provider-specific model identifier.
// Empty string falls back to the engine default
// (whisper-1 for OPENAI providers, gemini-2.5-flash for GEMINI providers).
string model = 2;
```
with:
```proto
// model is the provider-specific model identifier.
// Empty string falls back to the engine default.
// OPENAI examples:
// - whisper-1 (legacy, lower cost)
// - gpt-4o-transcribe, gpt-4o-mini-transcribe (higher quality)
// - gpt-4o-transcribe-diarize (includes speaker labels)
// GEMINI examples:
// - gemini-2.5-flash (default, multimodal call)
// - gemini-2.5-pro
string model = 2;
```
**Rationale:** OpenAI's `/audio/transcriptions` endpoint now supports the `gpt-4o-transcribe` family in addition to `whisper-1`. The current comment is misleading — it implies Whisper is the only OpenAI option.
#### Improvement #3 — `TranscriptionConfig.prompt` comment
Replace lines 188191:
```proto
// prompt is a default spelling/vocabulary hint passed to the provider.
// Used as the OpenAI Whisper "prompt" parameter and folded into the Gemini
// generation prompt as a "Context and spelling hints" block.
string prompt = 4;
```
with:
```proto
// prompt is a default spelling/vocabulary hint passed to the provider.
// Used as the OpenAI Whisper "prompt" parameter (a soft hint that the model
// may ignore) and folded into the Gemini generation prompt as a "Context and
// spelling hints" block (which the LLM will treat more literally).
string prompt = 4;
```
**Rationale:** Same field, two semantically different behaviors. Surfacing this in the schema documentation (which propagates to generated Go and TypeScript via JSDoc) makes the cross-provider variability explicit for any caller reading the bindings cold.
After editing the proto, regenerate via `cd proto && buf format -w && buf generate`. The two regenerated files are:
- `proto/gen/store/instance_setting.pb.go`
- `web/src/types/proto/store/instance_setting_pb.ts`
#### Why NOT add an `enabled` field (improvement #1)
Out of scope per §2. Doing it would add a new field that the frontend, backend, and migration logic all need to handle, for the sole benefit of letting users "disable but keep the config." The current `provider_id == ""` semantics work; the cost of the change exceeds the benefit at this moment.
### 6.6 Frontend Impact
Minimal. `web/src/components/Settings/AISection.tsx` already:
- Switches the model placeholder per provider (`placeholderForProvider` at line 371, using `setting.ai.transcription-model-placeholder-gemini` / `-openai`).
- Disables the form when `providerId == ""`.
- Validates that the referenced provider exists.
Recommended adjustments (in scope):
1. **Update i18n model placeholder strings** in `web/src/locales/en.json` to reflect the new model examples:
- `setting.ai.transcription-model-placeholder-openai`: include `gpt-4o-transcribe` family alongside `whisper-1`.
- `setting.ai.transcription-model-placeholder-gemini`: confirm `gemini-2.5-flash` is the listed example.
2. **Update the prompt help text** (`setting.ai.transcription-prompt-help`) to note the cross-provider semantic difference, mirroring the new proto comment in user-facing language.
No structural component changes. No new fields. No state-shape changes.
### 6.7 What Stays Identical
- Database storage (`InstanceSetting` rows, `AISetting` blob) — proto field tags unchanged.
- API surface (`TranscribeRequest`, `TranscribeResponse` messages) — unchanged.
- gRPC/Connect endpoint paths — unchanged.
- Frontend state shape (`LocalTranscription`) — unchanged.
- All existing tests semantically unchanged (will be ported to new package paths).
## 7. Migration Path
The refactor is internal to the Go server. End-to-end behavior is preserved. Migration is staged so each stage is independently buildable, testable, and revertable.
| Stage | What | Compiles? | Tests pass? |
|---|---|---|---|
| A | Add `internal/ai/stt/` and `internal/ai/audiollm/` with new interfaces and (empty) factories. Add new errors. | ✅ | ✅ (no callers yet) |
| B | Implement `internal/ai/stt/openai/` — port behavior from current `openai.go::openAITranscriber`. Port tests to `stt/openai/openai_test.go`. | ✅ | ✅ |
| C | Implement `internal/ai/audiollm/gemini/` — port behavior from current `gemini.go::geminiTranscriber`, but: lift instructions out into the caller, return `FinishReason` instead of swallowing it. Port tests. | ✅ | ✅ |
| D | Refactor `server/router/api/v1/ai_service.go::Transcribe` to dispatch via the new factories. Add `transcribeViaSTT` and `transcribeViaAudioLLM`. Add `buildTranscriptionInstructions`. | ✅ | ✅ |
| E | Delete old files: `internal/ai/transcription.go`, `client.go`, `openai.go`, `openai_test.go`, `gemini.go`, `gemini_test.go`. | ✅ | ✅ |
| F | Update proto comments (#2 and #3), run `buf format -w && buf generate`. | ✅ | ✅ |
| G | Update `web/src/locales/en.json` strings for model placeholders and prompt help. | ✅ | ✅ |
Each stage is one commit. Reverting any single stage leaves the system in a working state.
## 8. Anti-Patterns Avoided (and Why)
| Anti-pattern | Where it would have come from | Why we're avoiding it |
|---|---|---|
| `ProviderType` enum with wire-format suffix (`OPENAI_TRANSCRIPTIONS`, `OPENAI_CHAT_AUDIO`) | Earlier brainstorming draft | Vercel/LiteLLM/Go ecosystem all use vendor-level identity; capability is implied by which interface you call. |
| `Response.Source` enum (`NativeSTT`, `MultimodalLLM`) | Earlier brainstorming draft | None of the three SDKs surveyed has this. It re-introduces the "pretend STT" smell at a different layer. |
| Adapter wrapping `audiollm.Model` as `stt.Transcriber` | Earlier brainstorming draft | Adapter would re-create the conflation we're trying to remove. Application-layer dispatch is honest. |
| Adding `transcription_*` fields to `AIProviderConfig` | Naive instinct | Three of three OSS apps surveyed (Open WebUI, LobeChat, Dify) do **not** do this. Pollutes the provider entity; repeats with every new capability. |
| Silently reusing chat provider credentials for STT (LobeChat's deprecated pattern) | LobeChat-style shortcut | LobeChat's own author marked the helper `@deprecated`. Memos's existing `provider_id` reference is more flexible (user can configure a different OpenAI-compatible endpoint, e.g. Groq, just for STT). |
| Per-model credential overrides, capability YAML, load balancing | Dify | Enterprise complexity that doesn't fit Memos's scope. |
| Auto-fallback from STT failure to multimodal-LLM transcription | Plausible "smart" idea | LiteLLM doesn't do this; failure modes and cost differ enough that fallback would surprise users. Explicit dispatch by provider type is what LiteLLM ships. |
## 9. Open Decisions
All resolved during brainstorming. None remain open. For the record:
1. **Direction A (split STT/Audio-LLM into separate interfaces) over Direction B (capability-flag system) over Direction C (audio-to-structured-note pipeline).** Resolved: A. Rationale: most honest abstraction, matches mainstream SDKs, leaves the door open to C as a future addition without rework.
2. **Provider type naming: vendor-level (`openai`/`gemini`) over wire-format-encoded.** Resolved: vendor-level. Rationale: matches Vercel/LiteLLM/Go convention; new OpenAI transcription model snapshots require zero schema or code changes.
3. **`TranscriptionConfig.Duration` field decision.** Not present in current proto; not added. Audio duration belongs to resource metadata (computed from the file at upload time), not to the transcription response.
4. **Multimodal failure-mode surface.** Resolved: expose `FinishReason` from `audiollm.Model` to the application layer; the Transcribe handler converts non-`Stop` reasons into informative errors.
## 10. Implementation Plan Pointer
Once this spec is approved, the implementation plan will be created at `docs/superpowers/plans/2026-05-02-stt-audiollm-split.md` covering Stages AG from §7 above as discrete, bite-sized tasks with TDD steps and per-stage commits.
@@ -0,0 +1,155 @@
# Transcription (STT) settings — design
**Date:** 2026-05-02
**Scope:** Backend + frontend. Schema-additive (no migration required).
## Problem
Memos has one AI feature today: audio transcription (speech-to-text). The current design has three concrete problems:
1. **Model is hard-coded per provider type.** `internal/ai/models.go` pins OpenAI to `gpt-4o-transcribe` and Gemini to `gemini-2.5-flash`. Users who want `whisper-1` (cheaper, often more accurate for non-English) or third-party Whisper-compatible endpoints (Groq's `whisper-large-v3-turbo`, self-hosted whisper.cpp / Speaches via OpenAI-compatible URL) cannot configure them at all.
2. **No explicit transcription configuration.** `InstanceAISetting.providers` is a generic credentials list. The frontend (`MemoEditor/index.tsx:65`) implicitly picks "the first provider with an API key whose type is in TRANSCRIPTION_PROVIDER_TYPES." Users cannot:
- Choose which provider runs transcription when they have multiple.
- Set a default language (Whisper API supports it but it is never sent).
- Set a `prompt` hint to bias spelling of proper nouns / jargon (a documented Whisper feature, surfaced by every other STT product).
3. **Gemini fails for browser-recorded audio.** `internal/ai/gemini.go:23` does not list `audio/webm` in `geminiSupportedContentTypes`, but `MediaRecorder` in browsers defaults to `audio/webm`. So selecting a Gemini provider for in-editor recording produces a content-type error every time.
## Goal
Let the operator configure transcription explicitly: which provider, which model, default language, and a spelling-hint prompt. Make the OpenAI provider work as a universal "OpenAI-compatible" engine so Groq / self-hosted Whisper / Speaches are reachable through endpoint override.
## Non-goals
- Adding STT engines beyond OpenAI and Gemini (Azure, Deepgram, AWS Transcribe — out of scope; the schema admits them later via `AIProviderType` enum).
- Other AI features (summarization, embeddings, tag suggestion). The schema is shaped so they fit later, but none are designed here.
- Per-call provider override at recording time. Research across all surveyed products (OpenWebUI, LibreChat, Whisper Memos, Superwhisper, etc.) confirms STT engine is a global preference, not an action-time choice. We follow the same pattern.
- Server-side audio transcoding (e.g., webm → wav for Gemini). See "Gemini webm" below for the chosen mitigation.
- Multi-user or per-user override of admin defaults. Memos' STT setting is instance-scoped, like every other instance setting.
## Naming
Field and message names follow cross-platform STT conventions, not Memos-internal shorthand:
| Concept | Chosen name | Rationale |
|---|---|---|
| Config message | `TranscriptionConfig` | AssemblyAI uses this exact identifier; matches OpenAI's `CreateTranscription*` verb family and Memos' existing `Transcribe` RPC. The `STT` acronym is not used as a type name in any major STT API. |
| Provider reference | `provider_id` (string) | Plain protobuf convention for a string-ID reference (`field_id`, `user_id` style). `engine` was rejected as an OpenWebUI-only term; typed message refs are not needed since providers are addressed by string ID. |
| Model | `model` | Unanimous across OpenAI, Google v2, Deepgram, OpenWebUI, LibreChat. Not `model_id`. |
| Default language | `language` | Bare `language` is the modern convention (OpenAI, Whisper family, Deepgram, Wyoming). `language_code` is the older Google/AWS form; we accept ISO 639-1 short codes the same way OpenAI does. |
| Spelling hint | `prompt` | OpenAI's public API field name and AssemblyAI's. Whisper's internal name is `initial_prompt`, but `prompt` is what users of `audio.transcriptions.create` recognize. |
A note on the message name collision: `proto/api/v1/ai_service.proto` already declares a `TranscriptionConfig` for **per-call** prompt/language overrides. The new store-level `TranscriptionConfig` lives in package `memos.store`, so the two compile cleanly. Memos already uses parallel `api.v1.X` / `store.X` message pairs (e.g. `User`, `Memo`); this matches that pattern.
## Architecture
### Schema (additive)
`proto/store/instance_setting.proto`:
```proto
message InstanceAISetting {
repeated AIProviderConfig providers = 1; // unchanged — credential pool
TranscriptionConfig transcription = 2; // NEW — feature config
}
message TranscriptionConfig {
// References an entry in providers[].id. Empty string = transcription disabled.
string provider_id = 1;
// Free text. Empty string = engine default (whisper-1 for OPENAI, gemini-2.5-flash for GEMINI).
string model = 2;
// ISO 639-1 short code. Empty string = auto-detect.
string language = 3;
// Up to ~200 tokens. Used as the OpenAI Whisper `prompt` parameter and as
// a "Context and spelling hints:" block in the Gemini prompt.
string prompt = 4;
}
```
`proto/api/v1/ai_service.proto`:
- `TranscribeRequest.provider_id` becomes optional. When omitted, the server resolves the provider from `InstanceAISetting.transcription.provider_id`.
- `TranscribeRequest.config` (per-call `TranscriptionConfig` with `prompt` / `language`) is kept for advanced overrides but its fields, when empty, fall back to the persisted defaults from `InstanceAISetting.transcription`.
### Backend changes
1. **`internal/ai/models.go`** — `DefaultTranscriptionModel` already exists; reuse it as the fallback when `TranscriptionConfig.model` is empty. No new code, just used from a new call site.
2. **`server/router/api/v1/ai_service.go`**:
- Read `InstanceAISetting.transcription` at the start of `Transcribe`.
- Resolve `provider_id` from request → fall back to `transcription.provider_id`. If both empty, return `FailedPrecondition` with a clear "transcription not configured" message.
- Resolve `model` similarly: request override → `transcription.model` → engine default via `DefaultTranscriptionModel`.
- Merge `language` and `prompt`: per-call overrides win; otherwise fall through to persisted defaults.
3. **`internal/ai/gemini.go`** — out of scope to fix the webm content-type list here. See mitigation below.
### Frontend changes
`web/src/components/Settings/AISection.tsx` is restructured into two settings groups inside the existing `SettingSection`:
1. **AI Integrations** (renamed from "Providers" — current behavior): list of credential entries (id, title, type, endpoint, api key). No functional changes; the rename communicates that this section is just credentials.
2. **Transcription** (new): three-segment form
- **Provider** — Select dropdown listing entries from group 1 by `title`. First option is "None — transcription disabled". Disabled with a hint "Add an AI integration first ↑" when group 1 is empty.
- **Model** — text input. Placeholder updates dynamically based on the selected provider's type (`whisper-1` for OPENAI, `gemini-2.5-flash` for GEMINI). Help text below: "Free text. Use the provider's model identifier — e.g., whisper-1, gpt-4o-transcribe, whisper-large-v3-turbo."
- **Default language** — text input, ISO 639-1 placeholder, empty = auto.
- **Prompt hints** — textarea, ~200 token soft limit, help text "Improves spelling of proper nouns and jargon. Whisper limit is ~224 tokens."
`web/src/components/MemoEditor/index.tsx:65` changes:
- Replace the "first provider with apiKey in TRANSCRIPTION_PROVIDER_TYPES" lookup with this enable rule: transcribe button shows iff `aiSetting.transcription.providerId` is non-empty AND the referenced provider exists in `aiSetting.providers` AND that provider has `apiKeySet === true`.
- The editor no longer needs to know the provider object itself for the call — see service change below.
`web/src/components/MemoEditor/services/transcriptionService.ts` is simplified: it stops accepting a `provider` argument and simply omits `provider_id` from the request. The server resolves the provider, model, language, and prompt from `InstanceAISetting.transcription`. (No override path is exposed at the editor layer; advanced callers can still pass `provider_id` directly via the proto if needed in the future.)
### How "OpenAI-compatible" backends work
To use Groq, Speaches, or self-hosted whisper.cpp:
1. In **AI Integrations**, add a provider with type `OPENAI`, set `endpoint` to e.g. `https://api.groq.com/openai/v1` or `http://speaches:8000/v1`, set the API key, give it a recognizable title ("Groq", "Self-hosted Whisper").
2. In **Transcription**, select that provider and set `model` to the backend's model identifier (`whisper-large-v3-turbo`, `Systran/faster-distil-whisper-large-v3`, etc.).
This is the universal escape hatch confirmed across OpenWebUI, LibreChat, and Whisper Obsidian plugin: don't enumerate every backend — let the OpenAI engine be a transport, not a brand.
## Gemini webm mitigation
The Gemini `audio/webm` failure is a real user-blocking bug but separate from the settings redesign. Three options were considered:
- **(a) Server-side transcode** with ffmpeg. Adds a heavy runtime dep; rejected as YAGNI.
- **(b) Switch MediaRecorder format** when STT engine is Gemini. Browser support for `audio/mp4` and `audio/wav` in `MediaRecorder` is patchy across Firefox / Safari / Chrome; rejected as fragile.
- **(c) Inline hint + accept the limitation.** Selected. The Transcription section shows a small warning under the model field when the chosen provider type is `GEMINI`: "Gemini does not accept browser-recorded `audio/webm`. For in-editor recording, use an OpenAI-compatible provider."
Server-side transcoding can be revisited later as a self-contained change if Gemini demand grows.
## Validation
Server validation (`server/router/api/v1/ai_service.go`):
- `transcription.provider_id`, when set, must reference an existing entry in `providers[]`. On `UpdateInstanceSetting` for the AI key, reject with `InvalidArgument` if it doesn't.
- `transcription.model` length cap: 256 chars (covers `Systran/faster-distil-whisper-large-v3`-style names with margin).
- `transcription.language` length cap: 32 chars (existing constant `maxTranscriptionLanguageLength`).
- `transcription.prompt` length cap: 4096 chars (existing constant `maxTranscriptionPromptLength`).
Frontend validation in `AISection.tsx`:
- "Save" disabled if `transcription.providerId` is set but the referenced provider was just deleted from the integrations list (in the same unsaved edit).
- Inline warning shown (but Save still allowed) if the referenced provider exists but has `apiKeySet === false` — surfacing the broken state so the operator can fix it without blocking unrelated edits to other settings.
## Backwards compatibility
The schema change is purely additive. Existing instances with `providers` configured but no `transcription` field default to `provider_id = ""`, which means transcription is disabled until the operator visits the new Transcription section and selects a provider.
This is a small UX regression for instances that were relying on the implicit "first provider wins" behavior — they now must make a one-click selection. Acceptable trade-off because:
- It makes the choice explicit (the implicit pick was the source of confusion when users had multiple providers).
- A one-time migration that auto-fills `transcription.provider_id` with the first STT-capable provider is feasible but adds complexity for a one-line user action. Skip the migration; document the change in the release notes.
## Testing
- `internal/ai/transcription_test.go` (existing) covers the transcribe RPC. Add cases for: empty `provider_id` falls back to setting; empty `model` falls back to `DefaultTranscriptionModel`; per-call overrides win over settings.
- `server/router/api/v1/test/ai_service_test.go` (existing) covers the API service. Add cases for the validation rules above (unknown provider_id, oversized model/language/prompt).
- Frontend: manual verification via the dev server (`pnpm dev` in `web/`) — load Settings, add a provider, configure transcription, verify the home editor's record button enables/disables based on `provider_id`. No new component tests required (existing AISection has none).
## Out of scope, explicitly
- Multiple transcription configurations / per-tag or per-user routing.
- Per-call provider override exposed in the editor UI.
- Test-transcription button in settings (worth doing later; deferred to keep this scope tight).
- Glossary / vocabulary list as a separate field — folded into `prompt` for now (Joplin/Superwhisper split this; we can add later if users ask).
- TTS settings. Memos has none today and none planned.
@@ -0,0 +1,113 @@
# First Screen Lazy Heavy Dependencies Design
## Context
The auth and signup pages currently fetch JavaScript and CSS assets for features that are not used on the first screen, including Mermaid, KaTeX, Leaflet, and React Leaflet. The current routing already uses lazy route components, so the remaining problem is eager imports from shared app entry points and feature modules.
The goal is to reduce first screen load time, especially for `/auth` and `/auth/signup`, without changing memo rendering, map behavior, or authenticated workflows.
## Goals
- Prevent Mermaid and Leaflet vendor chunks from loading on auth/signup before they are needed.
- Prevent Leaflet and KaTeX CSS from loading globally at app startup.
- Preserve current behavior when users view Mermaid diagrams, math content, memo location previews, profile maps, or location pickers.
- Keep fallbacks small and consistent with existing async rendering patterns.
- Verify the production build and confirm auth/signup network requests no longer include Mermaid or Leaflet chunks during initial render.
## Non-Goals
- Rewriting the markdown rendering pipeline.
- Removing support for Mermaid, KaTeX, Leaflet, or React Leaflet.
- Optimizing every authenticated route in this change.
- Changing server behavior, route guards, or authentication flow.
## Recommended Approach
Use feature-level lazy loading for heavy optional features. Keep the app shell and auth routes free of diagram, math styling, and map dependencies. Load those dependencies from the feature boundary where the user actually needs them.
This approach has the best balance of impact and risk because it removes known eager imports while preserving existing route structure and feature internals.
## Architecture
### App Entry
`web/src/main.tsx` should no longer import:
- `leaflet/dist/leaflet.css`
- `katex/dist/katex.min.css`
These styles are feature-specific and should be loaded from the map and markdown rendering paths.
### Mermaid
`web/src/components/MemoContent/MermaidBlock.tsx` should replace the static `import mermaid from "mermaid"` with an async `import("mermaid")` inside the render effect.
The component should keep its current behavior:
- initialize Mermaid with the resolved app theme;
- render when code content or theme changes;
- show the existing error fallback when rendering fails.
The Mermaid chunk should only be requested when a memo actually renders a Mermaid code block.
### KaTeX
KaTeX CSS should load from the memo markdown rendering path instead of the app entry. Since `rehype-katex` is only useful when memo markdown is rendered, loading the stylesheet near `MemoMarkdownRenderer` keeps auth/signup free of KaTeX CSS while preserving math output styling.
This change does not need content-level math detection. Loading KaTeX CSS with memo markdown is simpler and still removes it from the first auth/signup screen.
### Leaflet Maps
Leaflet-dependent UI should be moved behind lazy component boundaries:
- `UserMemoMap` should be lazy-loaded by the user profile route or by a small wrapper component.
- `LocationPicker` should be lazy-loaded where location UI is opened or displayed.
The underlying map implementations can continue using Leaflet, React Leaflet, marker clustering, and their current helpers. The key boundary is that parent components must not statically import the map implementation if that parent can be pulled into non-map first-screen chunks.
Leaflet CSS and marker cluster CSS should load inside the lazy map implementation path, not from `main.tsx`.
### Type Imports
Any imports from `leaflet` that are used only as TypeScript types should use `import type`. Runtime construction such as `new LatLng(...)` should be avoided in parent components that are meant to stay Leaflet-free; pass plain latitude/longitude data into lazy map wrappers and construct Leaflet objects inside the lazy implementation.
## Data Flow
Auth/signup initial render:
1. App entry initializes theme, locale, providers, auth, and instance data.
2. Router loads only the auth/signup route component and shared app shell dependencies.
3. Mermaid, Leaflet, React Leaflet, marker cluster, and feature CSS are not requested.
Memo markdown render:
1. Memo content renders with the existing markdown renderer.
2. KaTeX CSS loads with the markdown rendering path.
3. If a code block language is `mermaid`, `MermaidBlock` dynamically imports Mermaid and renders the diagram.
Map render:
1. A map feature mounts through a lazy boundary.
2. The lazy implementation imports Leaflet, React Leaflet, and required map CSS.
3. Existing map interactions and display behavior continue inside the loaded implementation.
## Error Handling
- Mermaid import or render failures should use the existing Mermaid error UI with the original code content visible.
- Lazy map boundaries should use minimal fallbacks sized like the eventual map container to avoid layout shift.
- Chunk load failures should continue to use the existing router chunk reload behavior where applicable.
## Testing
- Run `pnpm build` in `web`.
- Run `pnpm lint` in `web`.
- Inspect production build output to ensure Mermaid and Leaflet remain split chunks.
- Use a production preview or equivalent browser check for `/auth/signup` and confirm initial network requests do not include Mermaid or Leaflet JavaScript chunks.
- Smoke test memo content with Mermaid and math.
- Smoke test location picker, location popover, and user profile map.
## Risks
- Loading CSS from lazy paths can cause a small style delay the first time a map or math content appears. Use map-sized fallbacks and keep CSS imports in the feature implementation to minimize visible shifts.
- Moving Leaflet runtime types out of parent components may require small prop shape changes.
- Dynamic Mermaid import needs effect cancellation to avoid setting state after unmount.
@@ -0,0 +1,282 @@
# Placeholder Component Design
## Context
The web frontend currently renders empty states with a single `Empty.tsx` component that displays a lucide `BirdIcon`. It is used in exactly one place (`web/src/pages/Inboxes.tsx`) and offers no support for other state varieties — loading, no-search-results, or 404 pages — each of which is currently handled inconsistently or not at all.
The goal is to replace `Empty.tsx` with a single reusable `<Placeholder>` component that renders a hand-curated ASCII bird illustration plus a short muted message, supports four distinct variants, and ships with the architectural seam needed to grow a randomized pool of ASCII pieces per variant in future work.
The visual register is "cozy and minimal": muted colors, monospace throughout, gentle motion that respects `prefers-reduced-motion`. The ASCII art itself is drawn from Joan Stark's (jgs) classic ASCII bird collection (https://github.com/oldcompcz/jgs), preserving the `jgs` signature and date as a visible credit beneath each piece.
## Goals
- Provide a single `<Placeholder variant="…">` component covering empty, loading, no-results, and 404 states.
- Render real, recognizable ASCII bird art (not freehand sketches), preserving Joan Stark's attribution.
- Apply subtle CSS-only animation (bob for perched birds, flutter for in-flight birds, fade-in on the message).
- Respect `prefers-reduced-motion` — no animation when the user opts out.
- Provide a pool-shaped data file so future PRs can drop in additional ASCII pieces per variant without component changes.
- Replace the existing `Empty.tsx` in `Inboxes.tsx` as the proof of integration.
## Non-Goals
- Adding additional ASCII pieces beyond the four initial picks (one per variant). The pool architecture supports growth, but seeding more pieces is a follow-up.
- Wiring the component into search results, the 404 route, or Suspense fallbacks. Each is a candidate; each is a separate PR.
- Translating the default messages. The file structure leaves a seam for `i18next`, but the initial PR ships plain strings.
- Adding a JS animation library (Framer Motion, react-spring, etc.). Three keyframe animations do not justify a new dependency.
- Visual regression testing infrastructure.
## Recommended Approach
Build a single `<Placeholder>` component with a `variant` prop that selects a randomized ASCII piece from a co-located pool data file. Animation is CSS-only, with motion presets keyed off each piece's `motion` field. Accessibility uses `aria-hidden` on the decorative ASCII and a semantic `<p>` for the message.
This approach has the best balance of present-day simplicity and future extensibility: the initial pool contains one piece per variant, so the component is deterministic today, but the picker function and pool shape impose no constraints on how many pieces are added later.
## Architecture
### Public Component
**Path:** `web/src/components/Placeholder/index.tsx`
```tsx
import { useMemo } from "react";
import clsx from "clsx";
import { pickPiece, MotionStyle, PlaceholderVariant } from "./ascii-pool";
import { DEFAULT_MESSAGES } from "./messages";
import "./Placeholder.css";
interface PlaceholderProps {
variant: PlaceholderVariant;
message?: string;
children?: React.ReactNode;
className?: string;
}
const MOTION_CLASS: Record<MotionStyle, string> = {
bob: "placeholder-motion-bob",
flutter: "placeholder-motion-flutter",
none: "",
};
export function Placeholder({ variant, message, children, className }: PlaceholderProps) {
const piece = useMemo(() => pickPiece(variant), [variant]);
const resolvedMessage = message ?? DEFAULT_MESSAGES[variant];
const isLoading = variant === "loading";
return (
<div
role={isLoading ? "status" : undefined}
aria-live={isLoading ? "polite" : undefined}
className={clsx("flex flex-col items-center justify-center max-w-md mx-auto px-4 py-8", className)}
>
<pre
aria-hidden="true"
className={clsx(
"font-mono text-xs sm:text-sm leading-tight text-muted-foreground whitespace-pre",
MOTION_CLASS[piece.motion],
)}
>
{piece.ascii}
</pre>
<p className="mt-3 font-mono text-sm text-muted-foreground placeholder-fade-in">
{resolvedMessage}
</p>
<p className="mt-1 font-mono text-[10px] text-muted-foreground/60">{piece.credit}</p>
{children && <div className="mt-4">{children}</div>}
</div>
);
}
```
The `useMemo` keyed on `variant` ensures the piece is stable for the mount but re-rolls if the variant prop changes (rare in practice). Re-mounting re-rolls naturally.
### ASCII Pool
**Path:** `web/src/components/Placeholder/ascii-pool.ts`
```ts
export type PlaceholderVariant = "empty" | "loading" | "noResults" | "notFound";
export type MotionStyle = "bob" | "flutter" | "none";
export interface AsciiPiece {
id: string;
variant: PlaceholderVariant;
ascii: string;
credit: string;
motion: MotionStyle;
}
export const ASCII_POOL: AsciiPiece[] = [
{
id: "jgs-crested-parrot",
variant: "empty",
credit: "jgs · 4/97",
motion: "bob",
ascii: ` .---.
/ 6_6
\\_ (__\\
// \\\\
(( ))
=====""===""=====
|||
|`,
},
{
id: "jgs-hummingbird-sm",
variant: "loading",
credit: "jgs · 7/98",
motion: "flutter",
ascii: ` , _
{ \\/\`o;====-
.----'-/\`-/
\`'-..-| /
/\\/\\
\`--\``,
},
{
id: "jgs-wide-eyed-owl",
variant: "noResults",
credit: "jgs · 2/01",
motion: "bob",
ascii: ` __ __
\\ \`-'"'-\` /
/ \\_ _/ \\
| d\\_/b |
.'\\ V /'.
/ '-...-' \\
| / \\ |
\\/\\ /\\/
==(||)---(||)==`,
},
{
id: "jgs-bird-flown-away",
variant: "notFound",
credit: "jgs · 7/96",
motion: "flutter",
ascii: ` ___
_,-' ______
.' .-' ____7
/ / ___7
_| / ___7
>(')\\ | ___7
\\\\/ \\_______
' _======>
\`'----\\\\\``,
},
];
export function pickPiece(variant: PlaceholderVariant): AsciiPiece {
const matches = ASCII_POOL.filter(p => p.variant === variant);
return matches[Math.floor(Math.random() * matches.length)];
}
```
> Each `ascii` value is a template literal; backslashes and backticks are escaped per JS rules. The art shown here is verbatim from the brainstorm sign-off; implementation must preserve every space.
The `ascii` field of each entry holds the verbatim ASCII string. The four initial pieces are the ones validated during brainstorming:
- **empty** — Joan Stark's "early-bird" parrot with crest, perched on a branch
- **loading** — Joan Stark's compact hummingbird (mid-flight, fluttering)
- **noResults** — Joan Stark's wide-eyed two-feathered owl
- **notFound** — Joan Stark's flying-away bird with motion trails
Each piece's `ascii` is committed as a template literal preserving exact whitespace; the file is the source of truth and is small enough (~510 lines of art per piece) to keep inline rather than splitting into per-piece files.
### Default Messages
**Path:** `web/src/components/Placeholder/messages.ts`
```ts
export const DEFAULT_MESSAGES: Record<PlaceholderVariant, string> = {
empty: "No memos yet",
loading: "Loading…",
noResults: "Nothing matches that search",
notFound: "This page flew the coop",
};
```
Plain strings for the initial PR. A future i18n pass swaps these for `t("placeholder.empty")` etc. without touching the component.
### Animation
CSS keyframes live in a small co-located stylesheet (`Placeholder.css`) imported by `index.tsx`, scoped via a `.placeholder-…` class prefix to avoid leakage. The codebase uses Tailwind v4 plus plain CSS imports elsewhere; this matches the existing pattern.
```css
@media (prefers-reduced-motion: no-preference) {
.placeholder-motion-bob { animation: placeholder-bob 3.4s ease-in-out infinite; }
.placeholder-motion-flutter { animation: placeholder-flutter 0.7s ease-in-out infinite; }
.placeholder-fade-in { animation: placeholder-fade 1s ease-out 0.3s both; opacity: 0; }
}
@keyframes placeholder-bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
@keyframes placeholder-flutter {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(2px, -1px); }
}
@keyframes placeholder-fade {
to { opacity: 1; }
}
```
The reduced-motion guard wraps all three rules. When the user prefers reduced motion, the bird is static and the message appears without fading.
### Accessibility
- ASCII `<pre>` carries `aria-hidden="true"`; screen readers do not announce it character-by-character.
- The message is a semantic `<p>`. It is the accessible name of the placeholder for assistive tech.
- For `variant="loading"` only, the wrapper has `role="status"` and `aria-live="polite"` so the loading message is announced when the placeholder appears.
- The credit line (`jgs · 4/97`) is visible-but-small below the message. It is not aria-hidden because it is intentionally part of the visual presentation.
- The component itself is not focusable. Anything passed as `children` (e.g. a "Go home" button on 404) participates normally in tab order.
- Color contrast relies on the existing `text-muted-foreground` token, which already meets WCAG AA in the project's theme.
### File Layout
```
web/src/components/Placeholder/
index.tsx # the <Placeholder> component (public export)
Placeholder.css # keyframes + .placeholder-motion-* classes
ascii-pool.ts # AsciiPiece type, ASCII_POOL array, pickPiece()
messages.ts # DEFAULT_MESSAGES map (i18n-ready seam)
CREDITS.md # Joan Stark attribution + link to oldcompcz/jgs
```
### Integration
- **Delete:** `web/src/components/Empty.tsx`.
- **Modify:** `web/src/pages/Inboxes.tsx` — replace the `<Empty />` import and usage with `<Placeholder variant="empty" />`.
Other potential call sites (search results page, router 404 catch-all, Suspense fallbacks) are explicitly out of scope for this PR. They are noted in the PR description as follow-up opportunities.
### Credits
**Path:** `web/src/components/Placeholder/CREDITS.md`
A short Markdown file pointing to https://github.com/oldcompcz/jgs and acknowledging Joan Stark's work. This survives even if the per-piece `credit` field is ever cleaned up by a refactor.
## Testing
A small Vitest suite covers:
- Each variant renders without throwing.
- The chosen `<pre>` content contains text from the matching pool entry.
- `aria-hidden="true"` on the `<pre>`.
- `role="status"` only present when `variant="loading"`.
- A custom `message` prop overrides the default.
- The credit text is present in the DOM.
No visual regression testing is added.
## Open Questions
None. All design decisions were validated during the brainstorming session — animation register (cozy), bird selections (jgs collection), naming (`Placeholder`, no "bird" in the name), text treatment (plain muted monospace), and integration scope (replace `Empty.tsx`, do not wire other sites yet).
## References
- Joan Stark's ASCII Art Gallery (jgs collection): https://github.com/oldcompcz/jgs
- Existing component being replaced: `web/src/components/Empty.tsx`
- Existing call site: `web/src/pages/Inboxes.tsx`
- Visual brainstorm artifacts: `.superpowers/brainstorm/1991-1778593581/content/` (mascot-approach, animation-vibe, bird-shapes-v2, jgs-bird-set, text-treatment-c)
@@ -0,0 +1,82 @@
# Remove react-use Design
## Context
The frontend has a direct dependency on `react-use@17.6.0`. Current source usage is limited to six imports:
- `usePrevious` in `web/src/layouts/RootLayout.tsx`
- `useLocalStorage` in `web/src/components/MemoExplorer/TagsSection.tsx`
- `useWindowScroll` in `web/src/components/MobileHeader.tsx`
- `useToggle` in `web/src/components/TagTree.tsx`
- `useDebounce` in `web/src/components/MemoEditor/Toolbar/InsertMenu.tsx`
- `useDebounce` in `web/src/components/MemoEditor/hooks/useLinkMemo.ts`
`react-use` pulls in `js-cookie@2.2.1` transitively. A direct `js-cookie@3.0.7` dependency does not remove that vulnerable transitive copy, so the better remediation is to remove `react-use` rather than adding another copy of `js-cookie`.
## Goals
- Remove `react-use` from `web/package.json` and `web/pnpm-lock.yaml`.
- Remove all source imports from `react-use` and `react-use/lib/*`.
- Prefer built-in React hooks directly where the replacement is simple.
- Add local hooks only where reuse or browser-side-effect cleanup makes the code clearer and safer.
- Confirm `react-use` and `js-cookie` are no longer present in the frontend dependency graph.
## Non-Goals
- Do not introduce another general-purpose React hooks library.
- Do not refactor unrelated frontend state management.
- Do not change user-visible behavior of tag preferences, tag tree expansion, scroll shadow behavior, route filter clearing, memo link search, or reverse geocoding debounce.
## Approach
Use native React hooks for one-off, simple behavior:
- Replace `useToggle` in `TagTree` with `useState(false)` plus local callbacks.
- Replace `usePrevious` in `RootLayout` with local `useRef` and `useEffect` while preserving the existing previous-path comparison.
- Replace `useWindowScroll` in `MobileHeader` with local `useState` and `useEffect` for the scroll listener.
Create focused local hooks where repeated behavior or cleanup consistency matters:
- Add `useDebouncedEffect` under `web/src/hooks/` for the two debounce call sites. It schedules a callback after the configured delay and clears the timeout when dependencies change or the component unmounts.
- Add a typed `useLocalStorage` under `web/src/hooks/` for tag display settings. It reads the stored value on initialization, falls back to the provided default, writes updates to `localStorage`, and tolerates unavailable or malformed storage by using the default.
Update imports to use `@/hooks/...` for local hooks. Keep hook APIs small and shaped around current usage rather than cloning the full `react-use` API.
## Data Flow And Behavior
Tag view settings continue to persist in `localStorage` under the same keys:
- `tag-view-as-tree`
- `tag-tree-auto-expand`
Debounced effects continue to defer:
- reverse-geocoding position updates in the memo editor insert menu by 1000 ms
- memo link search requests by 300 ms
The route filter clearing logic continues to run only when navigation changes route and the URL has no `filter` parameter.
The mobile header continues to show its shadow when the window has scrolled below the top.
## Error Handling
The local storage hook catches read and write failures. On read failure or malformed JSON, it returns the default value. On write failure, it keeps React state updated so the current UI interaction still works, while avoiding a thrown render or event-handler error.
Debounced effects do not swallow errors inside the user callback. Existing call sites already handle their own asynchronous errors where needed.
## Testing And Verification
Run frontend validation after implementation:
- `pnpm install --lockfile-only` from `web/` to regenerate `pnpm-lock.yaml`
- `pnpm why react-use js-cookie` from `web/` and confirm neither dependency remains
- `pnpm lint` from `web/`
- `pnpm build` from `web/`
Manual checks should cover:
- toggling tag tree mode and auto-expand persists across reload
- opening tag tree nodes still works
- mobile header shadow appears after scrolling
- memo link search still debounces and updates results
- location reverse geocoding still waits for position changes before lookup
+142 -66
View File
@@ -1,76 +1,152 @@
module github.com/usememos/memos
go 1.19
go 1.26.2
require (
github.com/aws/aws-sdk-go-v2 v1.17.4
github.com/aws/aws-sdk-go-v2/config v1.18.12
github.com/aws/aws-sdk-go-v2/credentials v1.13.12
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.51
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.3
github.com/google/uuid v1.3.0
github.com/gorilla/feeds v1.1.1
github.com/labstack/echo/v4 v4.9.0
github.com/mattn/go-sqlite3 v1.14.9
connectrpc.com/connect v1.19.2
github.com/at-wat/ebml-go v0.18.0
github.com/aws/aws-sdk-go-v2 v1.41.6
github.com/aws/aws-sdk-go-v2/config v1.32.16
github.com/aws/aws-sdk-go-v2/credentials v1.19.15
github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0
github.com/go-sql-driver/mysql v1.9.3
github.com/google/cel-go v0.28.0
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v5 v5.1.0
github.com/lib/pq v1.12.3
github.com/lithammer/shortuuid/v4 v4.2.0
github.com/mark3labs/mcp-go v0.49.0
github.com/moby/moby/api v1.54.2
github.com/openai/openai-go/v3 v3.32.0
github.com/pion/opus v0.0.0-20260430223319-81a9c5dc5013
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.1
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.1.0
golang.org/x/exp v0.0.0-20230111222715-75897c7a292a
golang.org/x/mod v0.6.0
golang.org/x/net v0.7.0
golang.org/x/oauth2 v0.5.0
github.com/spf13/cobra v1.10.2
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.42.0
github.com/testcontainers/testcontainers-go/modules/mysql v0.42.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0
github.com/yuin/goldmark v1.8.2
golang.org/x/crypto v0.50.0
golang.org/x/mod v0.35.0
golang.org/x/net v0.53.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.20.0
google.golang.org/genai v1.54.0
google.golang.org/genproto v0.0.0-20260427160629-7cedc36a6bc4
google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4
google.golang.org/grpc v1.80.0
modernc.org/sqlite v1.50.0
)
require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.20 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.23 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.22 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.22 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.1.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
cel.dev/expr v0.25.1 // indirect
cloud.google.com/go v0.123.0 // indirect
cloud.google.com/go/auth v0.20.0 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
dario.cat/mergo v1.0.2 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/jsonschema-go v0.4.3 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.15 // indirect
github.com/googleapis/gax-go/v2 v2.22.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.2.0 // indirect
github.com/moby/moby/client v0.4.1 // indirect
github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/image v0.39.0 // indirect
google.golang.org/api v0.276.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 // indirect
modernc.org/libc v1.72.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)
require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect
github.com/aws/smithy-go v1.25.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/disintegration/imaging v1.6.2
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/mattn/go-isatty v0.0.22 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/text v0.36.0
golang.org/x/time v0.15.0 // indirect
google.golang.org/protobuf v1.36.11
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+348 -584
View File
@@ -1,597 +1,361 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/aws/aws-sdk-go-v2 v1.17.4 h1:wyC6p9Yfq6V2y98wfDsj6OnNQa4w2BLGCLIxzNhwOGY=
github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/config v1.18.12 h1:fKs/I4wccmfrNRO9rdrbMO1NgLxct6H9rNMiPdBxHWw=
github.com/aws/aws-sdk-go-v2/config v1.18.12/go.mod h1:J36fOhj1LQBr+O4hJCiT8FwVvieeoSGOtPuvhKlsNu8=
github.com/aws/aws-sdk-go-v2/credentials v1.13.12 h1:Cb+HhuEnV19zHRaYYVglwvdHGMJWbdsyP4oHhw04xws=
github.com/aws/aws-sdk-go-v2/credentials v1.13.12/go.mod h1:37HG2MBroXK3jXfxVGtbM2J48ra2+Ltu+tmwr/jO0KA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.22 h1:3aMfcTmoXtTZnaT86QlVaYh+BRMbvrrmZwIQ5jWqCZQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.22/go.mod h1:YGSIJyQ6D6FjKMQh16hVFSIUD54L4F7zTGePqYMYYJU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.51 h1:iTFYCAdKzSAjGnVIUe88Hxvix0uaBqr0Rv7qJEOX5hE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.51/go.mod h1:7Grl2gV+dx9SWrUIgwwlUvU40t7+lOSbx34XwfmsTkY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 h1:r+XwaCLpIvCKjBIYy/HVZujQS9tsz5ohHG3ZIe0wKoE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 h1:7AwGYXDdqRQYsluvKFmWoqpcOQJ4bH634SkYf3FNj/A=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29 h1:J4xhFd6zHhdF9jPP0FQJ6WknzBboGMBNjKOv4iTuw4A=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29/go.mod h1:TwuqRBGzxjQJIwH16/fOZodwXt2Zxa9/cwJC5ke4j7s=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.19/go.mod h1:8W88sW3PjamQpKFUQvHWWKay6ARsNvZnzU7+a4apubw=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.20 h1:YIvKIfPXQVp0EhXUV644kmQo6cQPPSRmC44A1HSoJeg=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.20/go.mod h1:8W88sW3PjamQpKFUQvHWWKay6ARsNvZnzU7+a4apubw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.23 h1:c5+bNdV8E4fIPteWx4HZSkqI07oY9exbfQ7JH7Yx4PI=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.23/go.mod h1:1jcUfF+FAOEwtIcNiHPaV4TSoZqkUIPzrohmD7fb95c=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.22 h1:LjFQf8hFuMO22HkV5VWGLBvmCLBCLPivUAmpdpnp4Vs=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.22/go.mod h1:xt0Au8yPIwYXf/GYPy/vl4K3CgwhfQMYbrH7DlUUIws=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.22 h1:ISLJ2BKXe4zzyZ7mp5ewKECiw0U7KpLgS3S6OxY9Cm0=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.22/go.mod h1:QFVbqK54XArazLvn2wvWMRBi/jGrWii46qbr5DyPGjc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.2/go.mod h1:SXDHd6fI2RhqB7vmAzyYQCTQnpZrIprVJvYxpzW3JAM=
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.3 h1:PVieHTwugdlHedlxLpYLQsOZAq736RScuEb/m4zhzc4=
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.3/go.mod h1:XN3YcdmnWYZ3Hrnojvo5p2mc/wfF973nkq3ClXPDMHk=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.1 h1:lQKN/LNa3qqu2cDOQZybP7oL4nMGGiFqob0jZJaR8/4=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.1/go.mod h1:IgV8l3sj22nQDd5qcAGY0WenwCzCphqdbFOpfktZPrI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1 h1:0bLhH6DRAqox+g0LatcjGKjjhU6Eudyys6HB6DJVPj8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1/go.mod h1:O1YSOg3aekZibh2SngvCRRG+cRHKKlYgxf/JBF/Kr/k=
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3 h1:s49mSnsBZEXjfGBkRfmK+nPqzT7Lt3+t2SmAKNyHblw=
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3/go.mod h1:b+psTJn33Q4qGoDaM7ZiOVVG8uVjGI6HaZ8WBHdgDgU=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY=
github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA=
cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/at-wat/ebml-go v0.18.0 h1:SNkpBFR4jCQV1rI4Bm1tSuIYnusxe2qQ4GHJia9eQg4=
github.com/at-wat/ebml-go v0.18.0/go.mod h1:w1cJs7zmGsb5nnSvhWGKLCxvfu4FVx5ERvYDIalj1ww=
github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg=
github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg=
github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM=
github.com/aws/aws-sdk-go-v2/config v1.32.16/go.mod h1:duCCnJEFqpt2RC6no1iK6q+8HpwOAkiUua0pY507dQc=
github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTtEVmAVyo+NFLHBhH4=
github.com/aws/aws-sdk-go-v2/credentials v1.19.15/go.mod h1:gJiYyMOjNg8OEdRWOf3CrFQxM2a98qmrtjx1zuiQfB8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8OuZZBtMJLZbk4P5HDjJO0jQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 h1:xnvDEnw+pnj5mctWiYuFbigrEzSm35x7k4KS/ZkCANg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14/go.mod h1:yS5rNogD8e0Wu9+l3MUwr6eENBzEeGejvINpN5PAYfY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22/go.mod h1:nO6egFBoAaoXze24a2C0NjQCvdpk8OueRoYimvEB9jo=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22 h1:SE+aQ4DEqG53RRCAIHlCf//B2ycxGH7jFkpnAh/kKPM=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.22/go.mod h1:ES3ynECd7fYeJIL6+oax+uIEljmfps0S70BaQzbMd/o=
github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0 h1:7G26Sae6PMKn4kMcU5JzNfrm1YrKwyOhowXPYR2WiWY=
github.com/aws/aws-sdk-go-v2/service/s3 v1.100.0/go.mod h1:Fw9aqhJicIVee1VytBBjH+l+5ov6/PhbtIK/u3rt/ls=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.10 h1:a1Fq/KXn75wSzoJaPQTgZO0wHGqE9mjFnylnqEPTchA=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.10/go.mod h1:p6+MXNxW7IA6dMgHfTAzljuwSKD0NCm/4lbS4t6+7vI=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 h1:x6bKbmDhsgSZwv6q19wY/u3rLk/3FGjJWyqKcIRufpE=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.16/go.mod h1:CudnEVKRtLn0+3uMV0yEXZ+YZOKnAtUJ5DmDhilVnIw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3VgHCT64RQKkZwh0DG5j8ak=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg=
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds=
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo=
github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI=
github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/cel-go v0.28.0 h1:KjSWstCpz/MN5t4a8gnGJNIYUsJRpdi/r97xWDphIQc=
github.com/google/cel-go v0.28.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/jsonschema-go v0.4.3 h1:/DBOLZTfDow7pe2GmaJNhltueGTtDKICi8V8p+DQPd0=
github.com/google/jsonschema-go v0.4.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas=
github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4=
github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY=
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/labstack/echo/v5 v5.1.0 h1:MvIRydoN+p9cx/zq8Lff6YXqUW2ZaEsOMISzEGSMrBI=
github.com/labstack/echo/v5 v5.1.0/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak=
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mark3labs/mcp-go v0.49.0 h1:7Ssx4d7/T86qnWoJIdye7wEEvUzv39UIbnZb/FqUZMY=
github.com/mark3labs/mcp-go v0.49.0/go.mod h1:BflTAZAzXlrTpiO44gmjMu89n2FO56rJ9m31fp4zd5k=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg=
github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY=
github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ=
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/openai/openai-go/v3 v3.32.0 h1:aHp/3wkX1W6jB8zTtf9xV0aK0qPFSVDqS7AHmlJ4hXs=
github.com/openai/openai-go/v3 v3.32.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pion/opus v0.0.0-20260430223319-81a9c5dc5013 h1:HDxWSNNH8R5G+y1xGM8AVsSu95rAmoOnVSdPTzoAtoI=
github.com/pion/opus v0.0.0-20260430223319-81a9c5dc5013/go.mod h1:t5Xog2n682JnawoykACE6nKVmupFvmJvkpM7x6bTv6g=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230111222715-75897c7a292a h1:/YWeLOBWYV5WAQORVPkZF3Pq9IppkcT72GKnWjNf5W8=
golang.org/x/exp v0.0.0-20230111222715-75897c7a292a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc=
github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/testcontainers/testcontainers-go v0.42.0 h1:He3IhTzTZOygSXLJPMX7n44XtK+qhjat1nI9cneBbUY=
github.com/testcontainers/testcontainers-go v0.42.0/go.mod h1:vZjdY1YmUA1qEForxOIOazfsrdyORJAbhi0bp8plN30=
github.com/testcontainers/testcontainers-go/modules/mysql v0.42.0 h1:Yhv1k7vDpyzZePntg5R5Oj4ZMCyWpAfpJeRu1ROsgiU=
github.com/testcontainers/testcontainers-go/modules/mysql v0.42.0/go.mod h1:Z7SCTuiZlghAdRjkv3Ir0iXJKC2T2avbtxLR0DRe+ng=
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0 h1:GCbb1ndrF7OTDiIvxXyItaDab4qkzTFJ48LKFdM7EIo=
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0/go.mod h1:IRPBaI8jXdrNfD0e4Zm7Fbcgaz5shKxOQv4axiL09xs=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY=
google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw=
google.golang.org/genai v1.54.0 h1:ZQCa70WMTJDI11FdqWCzGvZ5PanpcpfoO6jl/lrSnGU=
google.golang.org/genai v1.54.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk=
google.golang.org/genproto v0.0.0-20260427160629-7cedc36a6bc4 h1:2iMJZntwvmfgtse+s744JY7v7PgEdSBuFYXucvpOHNM=
google.golang.org/genproto v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:v14kaaboYyXQ1Gsu489Q+Hg/oN4B33mWtuOhF1HCeXA=
google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4 h1:yOzSCGPx+cp5VO7IxvZ9SBFF7j1tZVcNtlHR2iYKtVo=
google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:Q9HWtNeE7tM9npdIsEvqXj1QJIvVoeAV3rtXtS715Cw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 h1:tEkOQcXgF6dH1G+MVKZrfpYvozGrzb91k6ha7jireSM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
modernc.org/cc/v4 v4.28.1 h1:XpLbkYVQ24E8tX5u8+yWGvaxerxkR/S4zqxI8ZoSBuc=
modernc.org/cc/v4 v4.28.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.33.0 h1:dspBCm75jsj8Y/ufwAMVfe375L2iYdMyQ2QG/v3hL54=
modernc.org/ccgo/v4 v4.33.0/go.mod h1:+RhXBoRYzRwaH21mV/aj6XvQRDtfjcZfAlPMsQo8CR0=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.72.1 h1:db1xwJ6u1kE3KHTFTTbe2GCrczHPKzlURP0aDC4NGD0=
modernc.org/libc v1.72.1/go.mod h1:HRMiC/PhPGLIPM7GzAFCbI+oSgE3dhZ8FWftmRrHVlY=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM=
modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
+20
View File
@@ -0,0 +1,20 @@
package ai
// ProviderType identifies an AI provider implementation.
type ProviderType string
const (
// ProviderOpenAI is OpenAI's hosted API.
ProviderOpenAI ProviderType = "OPENAI"
// ProviderGemini is Google's Gemini API.
ProviderGemini ProviderType = "GEMINI"
)
// ProviderConfig configures a callable AI provider connection.
type ProviderConfig struct {
ID string
Title string
Type ProviderType
Endpoint string
APIKey string
}
+161
View File
@@ -0,0 +1,161 @@
// Package audio provides audio container/codec helpers for AI providers.
//
// The motivating use case is Gemini transcription: Gemini's audio inputs
// require WAV/MP3/AIFF/AAC/OGG/FLAC, but browser MediaRecorder defaults to
// WebM/Opus. This package converts WebM/Opus into 16-bit PCM WAV using
// pure-Go decoders — no ffmpeg or other system dependency.
package audio
import (
"bytes"
"encoding/binary"
"io"
"strings"
"github.com/at-wat/ebml-go"
"github.com/at-wat/ebml-go/webm"
"github.com/pion/opus"
"github.com/pkg/errors"
)
const (
opusOutputSampleRate = 48000
// maxOpusPacketSamples is Opus's spec maximum: 120 ms at 48 kHz.
maxOpusPacketSamples = 5760
// opusCodecID is the WebM TrackEntry CodecID for an Opus audio track.
opusCodecID = "A_OPUS"
// opusHeadMinLength is the minimum size of the OpusHead identification
// header stored in TrackEntry.CodecPrivate.
opusHeadMinLength = 19
)
// WebMOpusToWAV decodes a WebM/Opus file into 16-bit PCM WAV bytes.
//
// The output is mono or stereo at 48 kHz (Opus's native decode rate),
// regardless of the original encoder's hint. Pre-skip samples declared in
// the OpusHead are discarded to avoid the encoder's startup padding.
//
// The function reads the entire WebM document into memory; callers should
// enforce their own size limits before invoking it.
func WebMOpusToWAV(input []byte) ([]byte, error) {
var doc struct {
Header webm.EBMLHeader `ebml:"EBML"`
Segment webm.Segment `ebml:"Segment"`
}
if err := ebml.Unmarshal(bytes.NewReader(input), &doc); err != nil && !errors.Is(err, io.EOF) {
return nil, errors.Wrap(err, "parse webm")
}
track := findOpusTrack(doc.Segment.Tracks.TrackEntry)
if track == nil {
return nil, errors.New("webm has no Opus audio track")
}
if len(track.CodecPrivate) < opusHeadMinLength {
return nil, errors.Errorf("invalid OpusHead: expected at least %d bytes, got %d", opusHeadMinLength, len(track.CodecPrivate))
}
channels := int(track.Audio.Channels)
if channels < 1 || channels > 2 {
return nil, errors.Errorf("unsupported Opus channel count: %d", channels)
}
preSkip := int(binary.LittleEndian.Uint16(track.CodecPrivate[10:12]))
decoder := opus.NewDecoder()
if err := decoder.Init(opusOutputSampleRate, channels); err != nil {
return nil, errors.Wrap(err, "init opus decoder")
}
pcm := make([]int16, 0, 1<<16)
frame := make([]int16, maxOpusPacketSamples*channels)
decodeBlock := func(block ebml.Block) error {
if block.TrackNumber != track.TrackNumber {
return nil
}
for _, packet := range block.Data {
if len(packet) == 0 {
continue
}
n, err := decoder.DecodeToInt16(packet, frame)
if err != nil {
return errors.Wrap(err, "decode opus packet")
}
pcm = append(pcm, frame[:n*channels]...)
}
return nil
}
for _, cluster := range doc.Segment.Cluster {
for _, sb := range cluster.SimpleBlock {
if err := decodeBlock(sb); err != nil {
return nil, err
}
}
for _, bg := range cluster.BlockGroup {
if err := decodeBlock(bg.Block); err != nil {
return nil, err
}
}
}
skip := preSkip * channels
if skip > len(pcm) {
skip = len(pcm)
}
pcm = pcm[skip:]
return encodeWAV(pcm, opusOutputSampleRate, channels), nil
}
// IsWebMContentType reports whether the MIME type is WebM audio.
// Both "audio/webm" and "audio/webm; codecs=opus" return true.
func IsWebMContentType(contentType string) bool {
contentType = strings.TrimSpace(contentType)
if contentType == "" {
return false
}
if i := strings.IndexByte(contentType, ';'); i >= 0 {
contentType = contentType[:i]
}
return strings.EqualFold(strings.TrimSpace(contentType), "audio/webm")
}
func findOpusTrack(entries []webm.TrackEntry) *webm.TrackEntry {
for i := range entries {
entry := &entries[i]
if entry.CodecID == opusCodecID && entry.Audio != nil {
return entry
}
}
return nil
}
// encodeWAV writes a standard RIFF/WAVE container around 16-bit PCM samples.
// Reference layout: http://soundfile.sapp.org/doc/WaveFormat/
func encodeWAV(samples []int16, sampleRate, channels int) []byte {
const bitsPerSample = 16
const bytesPerSample = bitsPerSample / 8
blockAlign := channels * bytesPerSample
byteRate := sampleRate * blockAlign
dataSize := len(samples) * bytesPerSample
buf := bytes.NewBuffer(make([]byte, 0, 44+dataSize))
buf.WriteString("RIFF")
_ = binary.Write(buf, binary.LittleEndian, uint32(36+dataSize))
buf.WriteString("WAVE")
buf.WriteString("fmt ")
_ = binary.Write(buf, binary.LittleEndian, uint32(16))
_ = binary.Write(buf, binary.LittleEndian, uint16(1)) // PCM
_ = binary.Write(buf, binary.LittleEndian, uint16(channels))
_ = binary.Write(buf, binary.LittleEndian, uint32(sampleRate))
_ = binary.Write(buf, binary.LittleEndian, uint32(byteRate))
_ = binary.Write(buf, binary.LittleEndian, uint16(blockAlign))
_ = binary.Write(buf, binary.LittleEndian, uint16(bitsPerSample))
buf.WriteString("data")
_ = binary.Write(buf, binary.LittleEndian, uint32(dataSize))
_ = binary.Write(buf, binary.LittleEndian, samples)
return buf.Bytes()
}
+48
View File
@@ -0,0 +1,48 @@
package audio
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestIsWebMContentType(t *testing.T) {
cases := []struct {
in string
want bool
}{
{"audio/webm", true},
{"audio/webm;codecs=opus", true},
{"audio/webm; codecs=opus", true},
{"AUDIO/WEBM", true},
{" audio/webm ", true},
{"audio/wav", false},
{"audio/mp4", false},
{"video/webm", false},
{"", false},
{"webm", false},
}
for _, tc := range cases {
t.Run(tc.in, func(t *testing.T) {
require.Equal(t, tc.want, IsWebMContentType(tc.in))
})
}
}
func TestWebMOpusToWAV_RejectsInvalidInput(t *testing.T) {
t.Run("empty", func(t *testing.T) {
_, err := WebMOpusToWAV(nil)
require.Error(t, err)
})
t.Run("not webm", func(t *testing.T) {
_, err := WebMOpusToWAV([]byte("hello world this is not webm"))
require.Error(t, err)
})
t.Run("truncated webm header bytes", func(t *testing.T) {
// Valid EBML magic but no Segment.
_, err := WebMOpusToWAV([]byte{0x1A, 0x45, 0xDF, 0xA3})
require.Error(t, err)
})
}
+41
View File
@@ -0,0 +1,41 @@
// Package audiollm defines the multimodal-audio capability for AI providers.
// Implementations call chat-completions or generate-content style APIs that
// accept audio as input. For deterministic transcription, prefer internal/ai/stt
// where a dedicated STT endpoint exists.
package audiollm
import (
"context"
"io"
)
// Model invokes a multimodal LLM with audio input.
type Model interface {
GenerateFromAudio(ctx context.Context, req Request) (*Response, error)
}
// Request is the input to a multimodal-audio call.
type Request struct {
Audio io.Reader
Size int64
ContentType string
Model string
Instructions string // literal instruction the model is expected to follow
Temperature *float32 // optional; nil leaves the provider default in place
}
// Response is the output of a multimodal-audio call.
type Response struct {
Text string
FinishReason FinishReason
}
// FinishReason describes why the model stopped generating.
type FinishReason string
const (
FinishStop FinishReason = "stop" // model finished normally
FinishLength FinishReason = "length" // truncated by max-tokens
FinishSafety FinishReason = "safety" // safety filter blocked output
FinishOther FinishReason = "other" // anything else, including unknown
)

Some files were not shown because too many files have changed in this diff Show More