Feat/5914 | Add single click to expand/collapse memo content#5924
Feat/5914 | Add single click to expand/collapse memo content#5924KakshiDEV56 wants to merge 1 commit into
Conversation
- Add enable_single_click_memo_expand setting to proto - Add toggle in Settings → System page - Add click handler with guards for interactive elements - Fixes usememos#5914
📝 WalkthroughWalkthroughAdds support for single-click memo expand/collapse via a new Changes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
web/src/components/MemoView/MemoViewContext.tsx (1)
8-8: 💤 Low valueUse the
@/alias for this cross-directory import.Every other non-same-directory import in this file uses the
@/alias (e.g.,@/types/proto/...,@/utils/media-item), but the new import uses a relative path that crosses into a sibling component directory.✏️ Proposed fix
-import type { MemoContentCompactMode } from "../MemoContent/types"; +import type { MemoContentCompactMode } from "@/components/MemoContent/types";As per coding guidelines: "Use
@/alias for absolute imports in frontend TypeScript/React files."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/MemoView/MemoViewContext.tsx` at line 8, The import of MemoContentCompactMode uses a relative cross-directory path; replace it with the project alias style (use the "@/..." alias) so it matches other non-same-directory imports—update the import statement that brings in MemoContentCompactMode (from ../MemoContent/types) to use the aliased path (e.g., "@/components/MemoContent/types" or the appropriate "@/..." path in your codebase) so all external imports in MemoViewContext.tsx follow the "@/..." convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/components/MemoView/MemoView.tsx`:
- Around line 48-65: The single-click handler handleArticleClick currently uses
event.detail to try to ignore double-clicks but fires on the first click; change
it to schedule compactMode.toggle() via a short setTimeout (e.g., 200–300ms) and
store that timer in a ref (timerRef) so it can be cancelled; add a window
'dblclick' listener (registered/cleaned up in a useEffect) that clears timerRef
and prevents the pending toggle when a double-click occurs, and also clear the
timer on unmount and when handleArticleClick early-returns; keep references to
memoRelatedSetting.enableSingleClickMemoExpand and compactMode (and call
compactMode.toggle()) in the callback dependencies.
---
Nitpick comments:
In `@web/src/components/MemoView/MemoViewContext.tsx`:
- Line 8: The import of MemoContentCompactMode uses a relative cross-directory
path; replace it with the project alias style (use the "@/..." alias) so it
matches other non-same-directory imports—update the import statement that brings
in MemoContentCompactMode (from ../MemoContent/types) to use the aliased path
(e.g., "@/components/MemoContent/types" or the appropriate "@/..." path in your
codebase) so all external imports in MemoViewContext.tsx follow the "@/..."
convention.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 20812005-7196-4b51-bcc2-d8613cc37e2d
⛔ Files ignored due to path filters (3)
proto/gen/api/v1/instance_service.pb.gois excluded by!**/*.pb.go,!**/gen/**proto/gen/openapi.yamlis excluded by!**/gen/**proto/gen/store/instance_setting.pb.gois excluded by!**/*.pb.go,!**/gen/**
📒 Files selected for processing (13)
proto/api/v1/instance_service.protoproto/store/instance_setting.protoserver/router/api/v1/instance_service.goweb/src/components/MemoContent/hooks.tsweb/src/components/MemoContent/index.tsxweb/src/components/MemoContent/types.tsweb/src/components/MemoPreview/MemoPreview.tsxweb/src/components/MemoView/MemoView.tsxweb/src/components/MemoView/MemoViewContext.tsxweb/src/components/MemoView/components/MemoBody.tsxweb/src/components/Settings/MemoRelatedSettings.tsxweb/src/locales/en.jsonweb/src/types/proto/api/v1/instance_service_pb.ts
| const handleArticleClick = useCallback( | ||
| (event: React.MouseEvent<HTMLElement>) => { | ||
| if (!memoRelatedSetting.enableSingleClickMemoExpand || !compactMode.mode || event.defaultPrevented || event.detail > 1) { | ||
| return; | ||
| } | ||
|
|
||
| const target = event.target as HTMLElement; | ||
| if (target.closest("a, button, input, textarea, select, [role='button'], [data-ignore-memo-expand]") || target.tagName === "IMG") { | ||
| return; | ||
| } | ||
| if (window.getSelection()?.toString()) { | ||
| return; | ||
| } | ||
|
|
||
| compactMode.toggle(); | ||
| }, | ||
| [compactMode, memoRelatedSetting.enableSingleClickMemoExpand], | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
wc -l web/src/components/MemoView/MemoView.tsxRepository: usememos/memos
Length of output: 103
🏁 Script executed:
cat -n web/src/components/MemoView/MemoView.tsx | head -200Repository: usememos/memos
Length of output: 7270
🏁 Script executed:
rg -n "dblclick|double" web/src/components/MemoView/MemoView.tsxRepository: usememos/memos
Length of output: 40
🏁 Script executed:
rg -n "openEditor|dblclick" web/src/components/MemoView/Repository: usememos/memos
Length of output: 1433
🏁 Script executed:
rg -n "onDoubleClick|dblclick" web/src/components/MemoContent/Repository: usememos/memos
Length of output: 358
🏁 Script executed:
rg -n "openEditor" web/src/components/MemoView/components/Repository: usememos/memos
Length of output: 723
🏁 Script executed:
cat -n web/src/components/MemoView/hooks/useMemoHandlers.tsRepository: usememos/memos
Length of output: 1651
🏁 Script executed:
cat -n web/src/components/MemoView/components/MemoBody.tsx | head -50Repository: usememos/memos
Length of output: 2659
🏁 Script executed:
cat -n web/src/components/MemoContent/index.tsx | head -100Repository: usememos/memos
Length of output: 5397
🏁 Script executed:
cat -n web/src/components/MemoContent/index.tsx | sed -n '40,90p'Repository: usememos/memos
Length of output: 2390
🏁 Script executed:
# Verify browser event sequence for double-click: does first click fire before dblclick?
python3 <<'EOF'
print("Browser Double-Click Event Sequence (W3C Standard):")
print("=" * 50)
print("1. mousedown (first press)")
print("2. mouseup (first release)")
print("3. click (detail=1) <- This fires before dblclick")
print("4. mousedown (second press)")
print("5. mouseup (second release)")
print("6. click (detail=2)")
print("7. dblclick")
print()
print("The key insight:")
print("- First 'click' event fires with detail=1 BEFORE 'dblclick' event")
print("- event.detail > 1 only catches the SECOND click (after dblclick)")
print("- So first click's toggle() executes before dblclick's preventDefault()/openEditor()")
EOFRepository: usememos/memos
Length of output: 588
🏁 Script executed:
# Check if there's any stopPropagation or other event handling that might prevent bubbling
rg -n "stopPropagation|preventDefault|bubbl" web/src/components/MemoView/components/MemoBody.tsxRepository: usememos/memos
Length of output: 40
🏁 Script executed:
# Verify the actual element structure and event attachment points
rg -A5 "onClick=\{handleArticleClick\}" web/src/components/MemoView/MemoView.tsxRepository: usememos/memos
Length of output: 241
🏁 Script executed:
rg -n "stopPropagation" web/src/components/MemoView/components/MemoBody.tsx web/src/components/MemoContent/index.tsxRepository: usememos/memos
Length of output: 40
Use a timeout to delay expand/collapse, canceling if a double-click occurs within the window.
Line 50's event.detail > 1 check suppresses only the second click event. On a real double-click sequence, the first click fires with detail === 1 before the dblclick event, so compactMode.toggle() executes during the first click. When the double-click edit handler fires moments later, the card has already expanded/collapsed and reflowed, creating unwanted visual motion before entering edit mode.
Replace the detail check with a debounce/timeout pattern that can be canceled by detecting a dblclick event within the window, ensuring single-click and double-click behaviors don't interfere.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/components/MemoView/MemoView.tsx` around lines 48 - 65, The
single-click handler handleArticleClick currently uses event.detail to try to
ignore double-clicks but fires on the first click; change it to schedule
compactMode.toggle() via a short setTimeout (e.g., 200–300ms) and store that
timer in a ref (timerRef) so it can be cancelled; add a window 'dblclick'
listener (registered/cleaned up in a useEffect) that clears timerRef and
prevents the pending toggle when a double-click occurs, and also clear the timer
on unmount and when handleArticleClick early-returns; keep references to
memoRelatedSetting.enableSingleClickMemoExpand and compactMode (and call
compactMode.toggle()) in the callback dependencies.
Changes Made
enable_single_click_memo_expandsetting to protobuf definitionsuseCompactModeto expose toggle functionTesting
Settings Page
Demo
Memos.webm
Fixes #5914