58 Commits

Author SHA1 Message Date
xfy
12a91e3b8e feat(comments): merge approved and pending comments in CommentList
- Accept both comments and pending props
- Merge into chronologically sorted list
- Route to CommentItem or PendingCommentItem per item type
2026-06-11 14:34:36 +08:00
xfy
9e658662cb fix(comments): add error logging for check_pending_status failure
Address code quality review: log warnings when the server call fails
instead of silently swallowing the error.
2026-06-11 14:33:13 +08:00
xfy
40cfd44d3a feat(comments): add pending_comments to CommentContext and sync on mount
- Extend CommentContext with pending_comments Signal
- Load pending comments from localStorage on provider init
- Run check_pending_status on mount to prune non-pending entries
- Pass both approved and pending comments to CommentList
- Include pending count in section heading
2026-06-11 14:30:49 +08:00
xfy
880c53d2a4 fix(comments): show name/email/url fields in reply form 2026-06-11 13:30:54 +08:00
xfy
59d5b9222a refactor(comments): remove privacy consent checkbox and consented param 2026-06-11 13:22:57 +08:00
xfy
04737300e6 feat(comments): add complete comment system with guest commenting, moderation, and admin UI
Implements a fully self-built comment system for the blog:

Data layer:
- comments table with BIGSERIAL PK, parent_id self-reference (ON DELETE SET NULL),
  depth tracking (max 20), status workflow (pending/approved/spam/trash),
  content hashing for dedup, GDPR consent tracking, IP/UA storage with auto-purge
- 5 partial indexes optimized for read patterns
- updated_at auto-trigger

API (9 Dioxus server functions):
- Public: get_comments, get_comment_count, create_comment
- Admin: get_pending_comments, get_pending_count, get_all_comments,
  approve_comment (with ancestor auto-approval), spam_comment, trash_comment,
  batch_update_comment_status

Security:
- Function-level rate limiting (1/sec, burst 5) via FullstackContext IP extraction
- Input validation (name, email, URL scheme, content length, consent)
- Parent chain validation (must be approved, same post)
- Strict comment Markdown renderer (headings→strong, no img/id/data URIs, nofollow links)
- Honeypot anti-spam field
- 5-minute dedup window via SHA-256 content hash

Frontend:
- CommentSection with SuspenseBoundary isolation
- Flat-list rendering with depth-based CSS indentation (responsive)
- Gravatar via cravatar.cn (server-computed, email never exposed)
- Inline reply forms (one-at-a-time via Signal)
- Admin action buttons (approve/spam/delete) visible per-comment
- CommentForm with privacy consent, Markdown hint, loading states

Admin:
- /admin/comments page with status tabs, batch operations, pagination
- Pending count badge on admin dashboard

Infrastructure:
- Shared get_current_admin_user moved from posts/helpers to auth module
- COMMENT_LIMITER rate limiter tier
- Moka caches (60s TTL for comments, 10s for pending count)
- IP/UA purge background task (daily, 90-day retention)
2026-06-11 12:34:26 +08:00
xfy
efa41b42c2 feat(auth): add loading state to login/register forms and update AGENTS.md 2026-06-11 10:44:27 +08:00
xfy
f9d23d1eed refactor(ui): redesign with warm palette, sage accent, and consistent theme vars
- Warm editorial color palette (#faf9f6 light / #141416 dark)
- Sage green accent (#5c7a5e) for nav, links, buttons, tags
- Replace all hardcoded hex colors with CSS theme utilities
- Serif font (system Georgia) only on header logo
- Better hover states: scale, brightness, color transitions
- Accent-colored focus rings on inputs
- Fix language mixing: Back to Home → 返回首页
- No external font dependencies
2026-06-11 10:29:11 +08:00
xfy
9cf6a7e4e6 fix(admin): replace use_delayed_loading with DelayedSkeleton for posts page
Use the same skeleton pattern as Home/Archives/Search pages.
Skeleton shows immediately (static gray blocks) instead of opacity-0 blank,
eliminating white flash during fast loads.
2026-06-10 18:15:46 +08:00
xfy
d3c5653808 feat: redesign admin write page with fixed-height editor layout
- Redesign write page UI with cleaner, more immersive editing experience
- Use CSS variables for theme-aware styling (paper-theme colors)
- Make editor fill remaining viewport height with internal scrolling
- Move action bar below editor (left-aligned, non-floating)
- Fix layout: page no longer scrolls, only editor content scrolls
- Update write skeleton to match new layout
- Update admin layout to use h-dvh for write routes to prevent page scroll
- Fix Dioxus.toml dev resource loading to include style.css

Fixes from review:
- Add missing relative positioning for loading overlay
- Use consistent root_class in unauthenticated state
- Use h-dvh instead of h-screen for mobile viewport compatibility
- Ensure skeleton matches actual component layout classes
2026-06-10 17:41:31 +08:00
xfy
2f433e8f11 feat: add 404 Not Found page
- Add NotFound component with elegant design
- Register catch-all route in router
- Add skeleton placeholder for NotFound route
- Remove unused design-taste-frontend skill
2026-06-10 15:43:05 +08:00
xfy
0319c927c6 chore: format code 2026-06-09 13:43:10 +08:00
xfy
44c1358da5 refactor: extract post content JS into standalone script 2026-06-09 13:18:40 +08:00
xfy
0345fa70f2 fix: add click handler for code block copy button 2026-06-09 11:33:26 +08:00
xfy
42b39266a6 fix: preserve data URI in img src during markdown rendering
ammonia's default url_schemes whitelist excludes 'data', causing
data:image/* URLs to be stripped from img src attributes. Add 'data'
to allowed schemes. Also skip data: URIs in JS thumbnail logic.
2026-06-09 10:06:34 +08:00
xfy
185bcab9f9 cleanup(forms): remove unused BUTTON_SECONDARY_CLASS 2026-06-08 16:19:35 +08:00
xfy
717266db1e fix: resolve conditional compilation and dead code warnings 2026-06-08 16:11:24 +08:00
xfy
b6f41e74e7 feat: image thumbnail + lightbox viewer
- Add ImageViewer reusable component with thumbnail and click-to-zoom
- PostCover: load ?w=1200 thumbnail, click to view full-size
- PostCard: display cover thumbnail (?thumb=400x300) in list view
- PostContent: inline images load ?w=800 thumbnail, click to zoom
- Add lightbox overlay styles with fade-in animation
- Add zoom cursor and hover effect for zoomable images
- Extend web-sys features for DOM image/lightbox manipulation
2026-06-08 15:52:47 +08:00
xfy
c776536678 fix(write-skeleton): align skeleton layout with actual write page
- fix bottom button bar layout (justify-end -> items-center with flex-1 spacer)
- remove extra p-6 padding from editor container
- add p-4 padding to toolbar area to match Tiptap editor padding
2026-06-05 18:21:35 +08:00
xfy
077573af67 fix(layout): highlight write nav for both /write and /write/:id 2026-06-05 17:55:18 +08:00
xfy
6d621d9ec4 feat(admin): remove '前台' nav item from admin header 2026-06-05 17:07:22 +08:00
xfy
28d1ee0d52 fix: reset UserContext on login/logout to prevent admin page stuck on re-login
Root cause: UserContext.checked was never reset on logout, causing AdminLayout's use_effect to skip get_current_user() on subsequent mounts, leaving the page in (checked=true, user=None) limbo.

- Reset ctx.user and ctx.checked on logout in admin_layout.rs
- Reset ctx.checked on login success in login.rs so AdminLayout re-validates session on mount
2026-06-05 10:42:20 +08:00
xfy
7866c53e36 feat: add dark mode toggle button to admin layout 2026-06-05 10:33:34 +08:00
xfy
5321b8cf97 refactor: reorganize admin write page layout with card-based sections 2026-06-05 09:58:26 +08:00
xfy
245fd83ec8 feat: replace in-footer scroll-to-top link with fixed floating button 2026-06-04 17:55:26 +08:00
xfy
1830fc9f2e cleanup: remove dead code, debug prints, and unused dead_code allow attributes 2026-06-04 16:20:43 +08:00
xfy
4e33bd3ee6 refactor: extract form atoms (FormInput, FormLabel, AlertBox) and replace repeated input/button styles 2026-06-04 15:55:40 +08:00
xfy
71abff1b3e refactor: add style prop to SkeletonBox, migrate last tags_skeleton div 2026-06-04 15:49:30 +08:00
xfy
4fbc938422 refactor: migrate tags_skeleton and admin_skeleton to SkeletonBox 2026-06-04 15:47:21 +08:00
xfy
6ed12ff1cb refactor: fix skeleton atoms - remove unused components, use &str, migrate all skeletons 2026-06-04 15:43:40 +08:00
xfy
ebf0f84733 refactor: extract skeleton atoms (SkeletonLine, SkeletonBox, SkeletonCard) and refactor skeleton components 2026-06-04 15:35:36 +08:00
xfy
9da060ac32 refactor: extract sleep_ms to utils/time.rs, deduplicate in hooks and skeletons 2026-06-04 15:11:08 +08:00
xfy
ce14c476b5 refactor: replace string-based navigation with typed Route and Link components 2026-06-04 14:55:18 +08:00
xfy
88cd23f74f fix: show route-specific skeleton screens in SuspenseBoundary fallback 2026-06-04 11:06:42 +08:00
xfy
c2f68b9c2d fix: wrap Outlet in SuspenseBoundary to prevent full-page flash on route change 2026-06-04 11:03:56 +08:00
xfy
e09a0f4616 chore: remove unused PageLayout component
- Delete src/components/page_layout.rs — no longer used by any page
- Remove 'pub mod page_layout' from components/mod.rs
- All frontend pages now use FrontendLayout via the router instead
2026-06-03 18:38:57 +08:00
xfy
e861b8a5be feat: add FrontendLayout component with Header, Footer and Outlet
- New FrontendLayout component wraps all frontend pages with shared
  Header (with nav items and theme toggle) and Footer
- Uses Outlet::<Route> to render child route components
- Similar pattern to existing AdminLayout but without auth checks
- Registered in components/mod.rs

This is the first step toward eliminating page transition flicker by
keeping Header/Footer mounted while only the main content area swaps.
2026-06-03 18:32:43 +08:00
xfy
326108ab68 fix: delay skeleton pulse animation instead of hiding skeleton, prevent blank flash 2026-06-03 17:47:51 +08:00
xfy
73e30d6f89 feat: add DelayedSkeleton wrapper to prevent skeleton flicker on fast loads 2026-06-03 17:41:49 +08:00
xfy
068d13c69f refactor: remove obsolete SuspenseWrapper, all pages now use dedicated skeleton screens 2026-06-03 17:33:44 +08:00
xfy
62519d620d feat: add SearchSkeleton component and replace inline skeleton on search page 2026-06-03 17:30:47 +08:00
xfy
c2e1fbe3ac feat: add TagsSkeleton/TagDetailSkeleton and replace generic fallback on tags pages 2026-06-03 17:25:47 +08:00
xfy
5becd73ebc feat: add ArchiveSkeleton and replace generic fallback on archives page 2026-06-03 17:19:29 +08:00
xfy
372c701b07 feat: add PostDetailSkeleton and replace generic fallback on post detail page 2026-06-03 17:13:39 +08:00
xfy
076448d6ed feat: add HomeSkeleton and replace generic fallback on home page 2026-06-03 17:09:20 +08:00
xfy
db8e88e1fe feat: add skeleton screens module and PostCardSkeleton component 2026-06-03 17:01:39 +08:00
xfy
60a2cd49ab feat: add SuspenseWrapper component for SSR 2026-06-03 14:14:45 +08:00
xfy
6b1f2e27c9 feat(components): add post page components (header, toc, content, footer, nav) 2026-06-02 18:21:25 +08:00
xfy
f3c1718cd0 feat: add use_delayed_loading hook to prevent skeleton flash 2026-06-02 17:53:04 +08:00
xfy
1950646bef feat: add shared components, new pages, and pagination 2026-06-02 17:33:28 +08:00