diff --git a/docs_v1.0/M4_workspace/2026-05-29_library_page_flash_filter_fix.md b/docs_v1.0/M4_workspace/2026-05-29_library_page_flash_filter_fix.md new file mode 100644 index 0000000..9e5cf3d --- /dev/null +++ b/docs_v1.0/M4_workspace/2026-05-29_library_page_flash_filter_fix.md @@ -0,0 +1,66 @@ +# Library Page: Flash & Filter Fix + +- **Date**: 2026-05-29 +- **Author**: OpenCode +- **Status**: Completed + +## Summary + +Fixed three interconnected issues on the library page (`/library/`) where video cards would flash 3 times on load, and the enhanced filter panel (size slider, duration, registered/unregistered) stopped working after flash fixes. + +## Root Causes & Fixes + +### Issue 1: 3x Flash on Load + +**Root Cause**: Multiple redundant render cycles triggered by: + +1. **`delayedPeopleFilesLoader`** (snippet 55) schedules **6x** `setTimeout(startPeopleFilesLoader, ...)` — 3 from `DOMContentLoaded`, 3 from `window 'load'`. Each creates a `setInterval` that retries `initPeopleFilesMediaLoader` every 200ms. + +2. **`loadMediaItems`** (snippet 55) resets `root.dataset.mediaLoaded = ''` after successful load, allowing the next pending `setTimeout(startPeopleFilesLoader, 500/1200)` to trigger a second/third `loadMediaItems` call → each calls `renderItems()` → re-renders all cards. + +3. **`bootFilterOnly()`** (snippet 58) has no guard, runs 5+ times from multiple `setTimeout(start, 300/1000/2000)` and event listeners. + +4. **`loadMediaMeta()`** (snippet 58) had no guard, ran on every `bootFilterOnly()` call → `debouncedApply()` → `applyEnhancedFilters()` reordered cards via DOM appendChild after async completion. + +**Fix**: +- Snippet 55: Removed `root.dataset.mediaLoaded = ''` reset in `loadMediaItems` success path. `mediaLoaded` stays `'1'` after first successful load, preventing re-triggers. +- Snippet 58: Removed `debouncedApply()` from `loadMediaMeta()`. +- Snippet 58: `setGridView()` already had a class-duplicate guard. +- Snippet 58: `renderFinderRows()` already had a skip guard. + +### Issue 2: Filter Not Working + +**Root Cause**: `debouncedApply()` (which calls `applyEnhancedFilters()`) was only triggered automatically from `loadMediaMeta()`. After removing it (fix #1), the filter state was never applied to cards. + +**Fix** (snippet 58): +- Added `applyEnhancedFilters()` to the `ltPeopleFilesFiltered` event handler (after `renderFinderRows()`). +- Removed the `setTimeout(0)` re-dispatch loop inside `applyEnhancedFilters` that would cause infinite event chaining. Replaced with simple `isApplyingFilter = false`. + +### Issue 3: Infinite Event Loop + +**Root Cause**: `applyEnhancedFilters()` used `setTimeout(0)` to set `isApplyingFilter = false` and re-dispatch `ltPeopleFilesFiltered`, which would call back into the handler → `applyEnhancedFilters()` → re-dispatch → loop. + +**Fix**: Directly set `isApplyingFilter = false` at the end of `applyEnhancedFilters()`. + +## Files Modified + +| Snippet | ID | Changes | +|---------|-----|---------| +| LT-檔案管理-註冊 | 55 | Removed `mediaLoaded = ''` reset in `loadMediaItems` success | +| LT-檔案管理-篩選功能 | 58 | Added `applyEnhancedFilters()` to `ltPeopleFilesFiltered` handler; removed `debouncedApply()` from `loadMediaMeta`; removed re-dispatch loop in `applyEnhancedFilters` | + +## Verification + +- ✅ No flashes on page load (single paint) +- ✅ Filter panel works (registered/unregistered, search, sort, sliders) +- ✅ Video streaming works (snippet 61, curl-based proxy) +- ✅ `cargo clippy --lib` — N/A (WordPress PHP) +- ✅ `cargo test --lib` — N/A + +## Context Saved At + +- User confirmed "沒有閃了" (no more flashes) and filter working +- AGENTS.md development boundary: WordPress snippets #55, #58, #61 (Code Snippets plugin) +- All edits done via direct MySQL UPDATE on `wp_snippets` table +- Working directory: `/Users/accusys/momentry_core` +- Latest context: user asked to save handoff before changing topic