Commit Graph
154 Commits
Author SHA1 Message Date
asepharyana eae0d7ce56 feat: enhance MessagesPanel with improved UI components and functionality
Deploy to VPS / deploy (push) Successful in 2m13s
- Refactored MessagesPanel to utilize new UI components such as Avatar, Badge, Button, Card, Dialog, Input, Progress, ScrollArea, Select, Skeleton, and Tabs.
- Improved error handling and loading states with enhanced user feedback.
- Updated message rendering logic to support new design patterns and animations.
- Added support for image previews and improved layout for message details.
- Enhanced mobile responsiveness with useIsMobile hook adjustments.
- Cleaned up utility functions for better readability and consistency.
2026-07-26 15:13:18 +07:00
asepharyana f57a1caf62 refactor: standardize import statements and improve code consistency across components
Deploy to VPS / deploy (push) Failing after 1m35s
- Updated import statements to use consistent semicolon usage.
- Refactored component code to ensure consistent formatting and style.
- Improved readability by adding missing semicolons and adjusting spacing.
- Ensured all components follow the same structure for props and return statements.
2026-07-26 14:52:38 +07:00
asepharyana e2c2365208 feat: add UI components including Skeleton, Slider, Sonner, Spinner, Switch, Table, Tabs, Textarea, Toggle Group, Toggle, Tooltip, and custom hook for mobile detection 2026-07-26 14:45:47 +07:00
asepharyana 4e28136538 feat: enhance image message rendering with metadata extraction and error handling
Deploy to VPS / deploy (push) Successful in 2m12s
2026-07-26 14:42:16 +07:00
asepharyana 0a6a9fd982 feat: update dependencies and improve dashboard functionality
Deploy to VPS / deploy (push) Failing after 1m43s
- Added new dependencies for Next.js and lucide-react in pnpm-workspace.yaml.
- Refactored DashboardPage component to improve readability and error handling.
- Enhanced Header component to display error status with an alert icon.
- Updated MobileTabBar and Sidebar components to use a centralized tabs definition.
- Improved ChannelsView in dashboard-panel to handle channel fetching more cleanly.
- Fixed ActiveSpeaker type to use camelCase for userId.
- Updated MessagesPanel to handle guildId checks more gracefully.
- Adjusted API calls in dashboard and messages to align with backend expectations.
- Refined type definitions across various interfaces for consistency and clarity.
2026-07-26 14:27:36 +07:00
asepharyana 9ecc4a6caa refactor(docs): update project documentation for clarity and accuracy
Deploy to VPS / deploy (push) Failing after 1m38s
2026-07-26 13:45:05 +07:00
asepharyana d5253ebab0 ci: fix frontend build outside pnpm workspace
Deploy to VPS / deploy (push) Failing after 1m47s
Frontend not in pnpm workspace (uses bun.lock locally), so build it
directly with pnpm install + build in its own directory.
2026-07-26 13:03:49 +07:00
asepharyana cedce85087 ci: fix lint errors for CI
Deploy to VPS / deploy (push) Successful in 1m47s
- Fix noImplicitAnyLet: add type to let match variable
- Fix noAssignInExpressions: use matchAll() + for-of instead of while
- Suppress useExhaustiveDependencies in mascot scroll effect
- Suppress useSemanticElements for message card click handler
2026-07-26 12:01:51 +07:00
asepharyana 42595a75f3 ci: merge biome configs to fix nested config error
Deploy to VPS / deploy (push) Failing after 1m28s
Root and services/frontend each had a biome.json causing Biome to
error on nested configuration. Merged frontend-specific rules and
domains (next, react) into root biome.json, removed nested config.
2026-07-26 11:55:10 +07:00
asepharyana 2ecba1691b docs: update all markdown files, switch remote to Gitea
Deploy to VPS / deploy (push) Failing after 34s
- Update root README.md: remove Leptos/WASM/SQLite, document Next.js
- Update frontend README.md: replace create-next-app boilerplate
- Update frontend AGENTS.md: project-specific overview
- Update CLAUDE.md: remove all auth references
- Update backend ARCHITECTURE.md: remove adminAuth from middleware list
- Switch git remote from gitlab to gitea (origin → gitea)
2026-07-26 11:38:53 +07:00
asepharyana f9f1313ccd refactor: remove login/auth for public dashboard
Deploy to VPS / deploy (push) Failing after 34s
- Remove login page, redirect / to /dashboard directly
- Remove AuthProvider, DashboardGuard from dashboard layout
- Remove use-auth hook and auth API module
- Remove X-Admin-Password header from API client
- Remove logout button from sidebar
2026-07-26 11:30:27 +07:00
asepharyana 5e01ec0806 feat: migrate Leptos frontend to Next.js 16 (React 19)
Deploy to VPS / deploy (push) Failing after 42s
Complete migration from services/frontend.old/ (Leptos 0.7 WASM + Rust)
to services/frontend/ (Next.js 16 static export + TypeScript + Tailwind v4).

Summary:
- Port all shared types (message, guild, voice, media, dashboard, recording, ui)
- Build fetch-based API client covering all 30+ backend endpoints
- WebSocket client with auto-reconnect (exponential backoff, 20 attempts)
- React context provider for WS with typed event subscription (22 event types)
- Login page with localStorage auth + auto-redirect
- Dashboard layout with sidebar, header (WS status + theme toggle)
- Messages: feed, search, images tab, review tab, channel filter, detail modal
- Live: voice connection, music player, recordings, mic transmit, active speakers
- Dashboard: stats, user list, channel list, detail views
- Mascot chatbot with history + clear
- uiStateApi persistence for selected tab
- Add static export config, update deploy scripts and CI
2026-07-26 11:27:21 +07:00
asepharyana af3c852a5b Refactor code structure for improved readability and maintainability 2026-07-06 00:58:41 +07:00
asepharyana 0ba4228042 feat: add WebSocket connection handling and UI styles
- Implemented WebSocket connection management in `connection.rs` with automatic reconnection and event handling.
- Created `handlers.rs` to define WebSocket event and status enums.
- Added global CSS reset styles in `reset.css`.
- Introduced design tokens in `tokens.css` for consistent theming.
- Developed UI component styles in `ui.css`, including buttons, cards, badges, and modals.
- Added utility classes in `utilities.css` for layout, spacing, and typography.
2026-07-05 21:18:59 +07:00
asepharyana e3228af196 feat(logging): Implement structured logging across the frontend
- Introduced a new `logger` module for structured logging with levels, timestamps, and styled console output.
- Replaced ad-hoc console logging with structured logger in various modules including API client, WebSocket, auth, and feature components.
- Enhanced logging in `app.rs`, `auth.rs`, `dashboard`, `messages`, `live`, and `polish` features.
- Updated UI components to include logging for user interactions and state changes.
- Rewrote `app.css` for a premium design overhaul, introducing glassmorphism, gradients, and improved responsiveness.
- Added a new `plan.md` file outlining the scope and changes made in this commit.
2026-07-05 19:55:13 +07:00
asepharyana c0edb0fa40 feat: enhance deployment instructions and exclude spam threads from message capture 2026-07-05 06:58:17 +07:00
asepharyana c3b2b3f334 feat: add /api/messages/images endpoint + ImageGrid fetch
Backend:
- New GET /api/messages/images?guildId=&limit= endpoint
- Queries attachments table for image/* MIME type, returns distinct messages
- Repository uses Drizzle subquery + join pattern

Frontend:
- New get_images() API client function
- ImageGrid fetches from /api/messages/images when Images tab selected
- Separate image_messages signal, fetched on tab switch

Deploy: hot-patched JS/WASM files to running containers
2026-07-05 04:48:29 +07:00
asepharyana e5c87a8ee6 Refactor image grid empty state, enhance header styles, and update ChannelRef struct
- Changed the empty state message in ImageGrid to use a dedicated class for styling.
- Adjusted padding and border-radius for the "Guild Watcher" label in the header for better aesthetics.
- Introduced a new class for the status indicator dot and linked its visibility to the connection state.
- Updated ChannelRef struct to include optional fields for thread_id and thread_name with appropriate serialization settings.
2026-07-05 03:53:56 +07:00
asepharyana 6bb9ade8b4 fix(fe): dismiss auth overlay on outside click 2026-07-05 03:32:08 +07:00
asepharyana 8e457c05b4 feat(fe): add close/skip button to auth overlay so users aren't stuck 2026-07-05 03:30:28 +07:00
asepharyana 09100e97aa fix(fe): light mode white text — remove background/color from body, set on .app-shell
body is outside the [data-theme] scope, so var(--text-primary)
on body always resolved to the dark :root value (#e8edf5, near-white).
Elements inside [data-theme] inherited this white color in light mode,
causing white-on-white text. Fix by moving background/color to
.app-shell which is inside the theme scope.
2026-07-05 03:26:15 +07:00
asepharyana 08ddad4077 fix(fe): restore .app-shell glass background for light mode support 2026-07-05 03:21:18 +07:00
asepharyana d0cd61f931 refactor(fe): convert remaining utility classes to semantic CSS in 12 files
- live/mod.rs: .live-body/head/grid, replace tailwind grid/flex
- screen_sub_panel: .scrn-actions/status
- waveform_player: .wave-wrap/progress/bar/info/time
- mic_level_meter: .mic-row/track/clip
- now_playing: .np-body/meta/tags/sep
- recordings_sub_panel: .rec-empty/list/item/info/meta/actions/footer
- active_speakers: .speak-list
- music_sub_panel: .music-body
- image_grid: .img-empty
- layout/header: .head-left/right/status
- mascot_chatbot: .mascot-controls/inline
2026-07-05 03:19:56 +07:00
asepharyana 5204a07976 refactor(fe): replace utility classes with semantic CSS across components
- add ~400 lines of clean semantic CSS classes (msg-*, panel-*,
  search-*, filter-*, feed-*, auth-*, sidebar-*, etc.)
- convert message_card.rs: .message-row -> .msg-row, .message-card
  -> .msg-card, remove all tailwind utility classes
- convert messages/mod.rs: .card -> .panel-card, .search-row ->
  .search-bar, .filter-chip -> .filter-chip-v2, .message-stats ->
  .stats-bar
- convert message_feed.rs: .space-y-4 -> .feed-wrap, .empty-state
  -> .feed-empty
- convert auth.rs: inline styles -> .auth-* semantic classes
- convert sidebar: .btn.btn-ghost -> .sidebar-btn.is-active
- keep utility classes in CSS for backward compatibility
  with non-refactored components (dashboard, live)
2026-07-05 03:12:57 +07:00
asepharyana 42ad1b4231 fix(fe): handle Discord embed thumbnail/image as plain URL string in serde deserialization
The Discord embed metadata sometimes returns thumbnail/image fields as
plain URL strings (e.g., "thumbnail":"https://...") instead of the
expected object format ({"url":"...","width":...,"height":...}).

Since serde deserializes the entire PageResult<MessageRecord> in one call,
even one message with a string-format embed field caused the entire response
to fail, making the message section appear empty despite the API returning
valid data.

Added a custom deserializer deser_embed_media that accepts null, a string
(interpreted as URL), or an object (standard struct deserialization).
Applied to both image and thumbnail fields in EmbedInfo with #[serde(default)]
so missing fields don't error. Includes 5 unit tests covering all formats.
2026-07-04 19:50:55 +07:00
asepharyana e73abf596d fix(fe): handle JSON-stringified fields from backend in message deserialization
Backend returns metadata, ai_moderation_flags, and ai_categories as raw
JSON strings (PostgreSQL JSONB cast to string). Frontend expected parsed
structs/arrays, causing serde to fail silently — entire PageResult parse
failed and user saw empty message list with no error indicator.

Add custom deserialize_with handler (from_json_string_or_value) that
transparently handles null / direct value / JSON-string cases for the
three affected fields.
2026-07-04 09:10:32 +07:00
asepharyana efb1f4e4a5 fix(fe): wiring WS voice/media events, perbaiki race condition, leak, dan history fetch
- Wiring WS events di LivePanel:
  - on_voice_active_user -> update ActiveSpeakers signal
  - on_media_state -> update NowPlaying signal
  - on_voice_recording_uploaded -> trigger RecordingsSubPanel refresh
  - on_binary -> process PCM data dan auto-start audio playback
- AudioPlaybackState: tambah Clone derive + abort AtomicBool
  untuk mencegah loop leak saat teardown
- MusicSubPanel: hapus loading state yang premature reset
  (race condition: loading false sebelum async selesai)
- NowPlaying: ganti prop state jadi RwSignal agar reaktif ke WS
- RecordingsSubPanel: tambah refresh_trigger signal untuk reload
  dari WS event
- MascotChatbot: fetch chat history dari backend saat panel dibuka
- get_review_messages: hapus guildId param (backend ignore)
2026-07-04 05:59:15 +07:00
asepharyana b063524759 fix(fe): perbaiki infinite loop dashboard, config fetching, infinite scroll, dan visualizer reactivity
- Dashboard: ganti Effect::new dengan spawn_local untuk initial fetch agar
  tidak terjadi infinite loop karena reactive dependency tracking
- Config: tambah api/config.rs dan jadikan AppConfig.monitor_guild_id
  RwSignal supaya di-fetch dari backend (saat startup & setelah login)
- Messages: perbaiki messageFetch agar guild_id terbaca dari config reaktif
- Infinite scroll: tambah observer_ready signal + spawn_local trigger
  agar IntersectionObserver setup setelah DOM mount; tambah fallback button
- AudioVisualizer & MicLevelMeter: tambah periodic tick signal (100ms)
  agar efek re-run dan update bars/level dari shared PCM buffer
- pcm_decoder: ganti js_sys::eval dengan wasm-bindgen binding langsung ke btoa
2026-07-04 05:47:47 +07:00
asepharyana 9614546243 feat: upgrade frontend deps — leptos 0.9.0-alpha, leptos-use 0.19, trunk 0.22.0-beta.1 2026-07-04 05:00:18 +07:00
asepharyana 27e929580e feat: update components and hooks to use get_untracked for improved performance 2026-07-04 03:03:36 +07:00
asepharyana 8166023f91 chore: remove React frontend, rename frontend-leptos to frontend 2026-07-03 23:11:00 +07:00
asepharyana 0926f235cb fix(auth): only reset activeTab on mount, don't block tab switching
Previous code continuously forced activeTab to 'messages' when not
authenticated, making dashboard and voice tabs unclickable.
Now uses useEffect once on mount to reset localStorage carryover,
then lets tab switching work normally.
2026-07-02 07:45:02 +07:00
asepharyana 948e41cec6 fix(ui): chat bubble max-w-xs broken by tailwind spacing override (4px not 320px)
tailwind.config.js overrides spacing.xs to 4px, which also overrides
max-w-xs to max-width: 4px instead of the default 20rem (320px).
Changed to explicit max-w-[280px] to bypass the corrupted token.
2026-07-02 07:08:58 +07:00
asepharyana 77812f9452 fix(auth): force activeTab to messages if not authenticated — prevent localStorage carryover
When a user visited the Live tab in a previous session, localStorage
stored activeTab: 'live'. On page reload, even with the new auth guard,
the app would try to render the Live tab and show the auth overlay.
Now if not authenticated, activeTab is always forced to 'messages'.
2026-07-02 07:06:33 +07:00
asepharyana 58de0df24b fix(ui): chat bubble text wrapping — replace break-words with overflow-wrap:anywhere
Fixes MascotChatbot messages wrapping 1 character per line.
overflow-wrap:anywhere handles long unbroken strings better
than break-words which only breaks at word boundaries.
2026-07-02 06:53:27 +07:00
asepharyana 0ae1ef1987 fix(auth): only guard Live tab, messages & dashboard are public
Auth overlay only shows when accessing Voice & Media without
authentication. Messages panel and Dashboard panel remain fully
accessible without login.
2026-07-02 06:40:39 +07:00
asepharyana 112b865a5b fix(infra): bypass Cloudflare Rocket Loader — breaks ES module scripts
Cloudflare Rocket Loader transforms <script type="module"> into
type="<hash>-module", which the browser cannot parse as ES module.
The React app never mounts — blank page on every route.

Fix: Vite plugin adds data-cfasync="false" attribute to the module
script tag, telling Rocket Loader to skip transformation.

Also: remove dist/ from the commit (build artifacts excluded).
2026-07-02 06:30:26 +07:00
asepharyana d53ec74d64 fix(build): resolve Tailwind 4 @apply breaking changes
- Replace @apply im-btn in im-btn-primary/secondary/ghost
  with inline Tailwind utilities + CSS properties
- Replace @apply im-status-dot in status dot variants
  with inline properties
- Tailwind 4 cannot @apply component-level classes from within
  @layer components — only standard utility classes are valid
2026-07-02 06:17:58 +07:00
asepharyana 81a004d250 feat(frontend): IMPHNEN design deep integration — full 5-layer redesign
Layer 0 — Foundation:
- Dark mode palette (30+ CSS var pairs in [data-theme='dark'])
- CSS-first theme engine in styles.css (@theme + CSS vars)
- UseTheme hook with light/dark/system support + localStorage persistence
- Fixed animation keyframes (shimmer 1.5s canonical, glowPulse moved to CSS)
- Smooth theme switch transitions via .theme-transitioning class

Layer 1 — Shared UI Components:
- Badge: success/warning variants now use CSS vars (bg-success-soft text-success)
- Toast: rewritten with CSS vars, z-index fixed (40), repositioned top-right
- Skeleton: added variant prop (rounded/circular/rectangular)
- EmptyState: new component with icon + title + description + action
- Button: added tertiary variant + icon-sm size
- Card: added elevated/bordered variants
- Input: added soft variant

Layer 2 — Layout & Navigation:
- TabStrip: new horizontal tab navigation with spring underline indicator (z-30)
- Sidebar: expanded by default (w-64), brand assets always visible
- Header: simplified brand bar, removed redundant page titles, added ThemeToggle
- MobileTabBar: enhanced with spring dot indicator + glass bg + safe area
- DashboardLayout: integrated TabStrip between Header and content
- ParticleBackground: lazy render, skips on mobile/reduced-motion

Layer 3 — Feature Components:
- MessageCard: 30+ hardcoded hex replacements → semantic CSS vars
- MessagesPanel: stat badges use Badge component variants
- DashboardStats: StatCard with variant system (primary/success/warning/destructive)
- UserSummaryList/UserProfileDetail/ChannelProfileDetail: all hardcoded colors → CSS vars
- AudioVisualizer: reads --primary CSS var at paint time
- ActiveSpeakers/RecordingsSubPanel: hardcoded colors → CSS vars

Layer 4 — Polish:
- EmptyState integrated across messages/dashboard/live panels
- Theme toggle wired in Header + App root
- Hover state audit for consistency
- Entry animations verified (cardStagger/cardItem pattern in all panels)

Resolves DESIGN_TOKENS.md §13.x issues: hardcoded colors, shimmer mismatch,
glow-pulse fragmentation, z-index collisions, toast positioning.
2026-07-02 05:58:36 +07:00
asepharyana 7efaf00c93 Revert "feat: migrate frontend to Astro + expand AI moderation + backend admin/runtime config"
This reverts commit d59b59a7a7.
2026-07-02 03:54:44 +07:00
asepharyana bf86fcda8e Revert "feat: migrate frontend to Astro SSG with design system"
This reverts commit 8ad888da28.
2026-07-02 03:54:44 +07:00
asepharyana 24c738dd19 Revert "fix: split LiveShell into Astro layout + individual islands"
This reverts commit 6e1757410a.
2026-07-02 03:54:44 +07:00
asepharyana 5a10bec67a Revert "fix: replace Astro.redirect with direct live content at /"
This reverts commit 34ac4be6c2.
2026-07-02 03:54:44 +07:00
asepharyana 34ac4be6c2 fix: replace Astro.redirect with direct live content at / 2026-07-02 03:47:23 +07:00
asepharyana 6e1757410a fix: split LiveShell into Astro layout + individual islands
- Rewrite live.astro to use Astro Sidebar/Header/Card components
- VoiceControls becomes self-contained (fetches guilds/channels internally)
- Remove LiveShell.tsx (no longer needed)
- Each React island uses appropriate client:load/idle directive
2026-07-02 03:13:54 +07:00
asepharyana 8ad888da28 feat: migrate frontend to Astro SSG with design system
- Replace monolithic React SPA (App.tsx) with 7 Astro pages (+ routing)
- Implement full design system from design/ (OKLCH tokens, Tailwind 4 @theme)
- Add 12 Astro components (Button, Badge, Card, Sidebar, Header, states)
- Add 11 React islands (AuthGuard, MessageFeed, VoiceControls, AudioVisualizer, etc.)
- Add 3 Zustand stores (UI, voice, message state)
- Add CSS architecture: dark/light themes, glassmorphism, fluid typography, animations
- Add 404, login, settings, recordings pages
- Remove 40+ legacy React SPA files
- Add Particles background and MascotChat deferred islands
- Wire WebSocket bridge for real-time messages and voice events

Build: 7 pages in ~900ms
Typecheck: clean (0 errors)
Lint: clean (0 errors)
2026-07-02 01:18:45 +07:00
asepharyana d59b59a7a7 feat: migrate frontend to Astro + expand AI moderation + backend admin/runtime config
Frontend:
- migrate from Vite to Astro (astro.config.mjs, pages/, layouts/)
- add admin panel, settings page, command palette, error boundary
- refactor App.tsx, MascotChatbot, Sidebar, Header, DashboardLayout
- update API client, WebSocket, auth, dashboard features

Backend:
- add admin module and config routes
- refactor middlewares, Redis connection, WebSocket server/bridge
- add runtime config loader

Discord Gateway:
- refactor AI moderation: circuit breaker, concurrency limiter, fallback processor
- add media analysis client, Seaxng search, user profile learner
- add new drizzle migration

Shared:
- extend database schema, add new config fields
2026-07-02 00:02:41 +07:00
MythEclipse f502918b27 feat: multimodal video detection + reply/forward/crosspost + batch optimization
- Video frame extraction via ffmpeg (4 key frames per video → vision LLM)
- Video display in FE MessageCard with HTML5 <video> player
- Reply/forward/crosspost indicator in FE + pipeline in DG/BE
- Fix: missing sanitizeAiContent + escapeXml in media path (prompt injection)
- Optimize: text-only batch results saved to DB immediately, no longer wait for media analysis
- BE mapper/schema/repo: add reference fields (is_reply, is_forward, etc.)
2026-06-22 09:46:06 +07:00
MythEclipse 21b818a344 feat: add forwarding & reply detection with frontend indicators
- Enhanced messageMetadata to capture referenced message content
- Added reply indicator (↩️ Replying to @username + content snippet)
- Added forward badge (🔁 Forwarded) and crosspost badge (📢 Crossposted)
- Frontend auto-fetches referenced message content when metadata is empty
- Added getMessageById API helper
2026-06-21 18:22:27 +07:00
MythEclipseandClaude 752d144dc0 refactor(fe): overhaul — split types, type-safe WS, remove dead deps/code
- Remove unused deps: gsap, @tanstack/react-query, three, r3f, drei, autoprefixer
- Split types from shared/api/client.ts into entities/{guild,voice,media,ui,recording,dashboard}
- Type-safe WebSocket handlers using WsEventMap — 0 'as' casts in App.tsx
- Replace gsap with framer-motion in AuthOverlay
- Remove dead code: useMascotSummary, gsapCardHover, live/components/index barrel
- Fix bare console calls → use createLogger from @bete/shared/logger
- Clean up unused imports and variables (aiVariant, etc.)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 22:44:28 +07:00