Commit Graph
100 Commits
Author SHA1 Message Date
asepharyana 189ab1c1f6 feat(fe): real mic capture for voice transmit (kirim suara)
Sebelumnya tombol Live/Muted cuma kirim voice:transmit:start/stop ke
gateway — TIDAK ADA audio yang dikirim (0 getUserMedia/AudioContext di
frontend). MicControl cuma toggle state kosong.

- lib/audio/mic-transmit.ts (BARU): getUserMedia → AudioContext 48kHz →
  AudioWorklet (downsample 24kHz mono s16le + volume + chunk 20ms) →
  frame 'PCM\0' + Int16LE → ws.sendBinary. Worklet inline via Blob URL
  (aman untuk static export).
- useMicTransmit(ws): aktif = start capture + voice:transmit:start;
  nonaktif = stop capture + voice:transmit:stop; setVolume untuk slider.
- voice page: volume slider sekarang beneran ngatur gain mic; disconnect
  ikut matiin mic.

Verifikasi: tsc PASS, biome 0 error, next build PASS. Test mic butuh
real device (headless browser tidak punya mic) — protokol: connect voice
→ Live → ngomong → orang di channel denger.
2026-08-01 11:26:18 +07:00
asepharyana 9d60f00934 fix(infra): add ffmpeg + yt-dlp to gmw-discord-gateway runtime
Root cause voice tidak berfungsi di produksi: ffmpeg & yt-dlp cuma ada
di devShell, bukan di package discord-gateway. Bukti dari log gateway:
'FFmpeg/avconv not found!' saat voice:transmit:start (mic -> Discord),
yang juga mematikan music playback (StreamType.Arbitrary butuh ffmpeg)
dan segment muxing rekaman.

- buildInputs: pkgs.ffmpeg-headless + pkgs.yt-dlp
- wrapper export PATH ke keduanya sebelum exec node
Verifikasi: nix build PASS; closure berisi ffmpeg-8.1.2 + yt-dlp-2026.07.04;
wrapper PATH mengarah ke keduanya; ffmpeg/yt-dlp jalan.
2026-08-01 11:22:20 +07:00
asepharyana 903e7c4aeb feat(fe): remove Settings page from dashboard
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m7s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m28s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m28s
Hapus halaman /settings + nav item Settings (TopNav/HiddenSidebar
via navItems). GlassDivider ikut dihapus (cuma dipakai settings).
useConfig tetap (dipakai guild-selector).

Verifikasi: tsc PASS, biome 0 error, next build PASS (10 halaman
static, settings hilang).
2026-08-01 11:13:47 +07:00
asepharyana 0771e62223 feat(fe): remove Live tab from dashboard
Hapus tab Live + komponennya (LiveStream, ModQueue) dari halaman
dashboard — tab Stats/Users/Channels tetap. useReview tetap dipakai
messages page (review tab), jadi hook tidak dihapus.

Verifikasi: tsc PASS, biome 0 error, next build PASS.
2026-08-01 11:10:36 +07:00
asepharyana 8e7ba67248 fix: message detail shows only its own images, not everyone's
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m47s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m12s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m12s
useMessageDetail fetch attachments per-channel -> detail view nampilin
10 image terbaru di channel itu (semua orang), bukan image pesan yang
diklik. Root cause: getAttachmentsByChannel cuma filter channel_id.

- backend: messageQuerySchema + messageId optional; repository
  tambah eq(message_id) pas messageId ada. Sudah ada index
  idx_attachments_message.
- frontend: getAttachments(channelId, limit, cursor, messageId);
  useMessageDetail pass id pesan.

Verifikasi: backend tsc PASS, frontend tsc PASS + next build PASS.
E2E local (tsx + env prod, port 3901): tanpa messageId -> 3 row
(termasuk image.png punya message lain); dengan messageId -> tepat
2 row milik pesan itu. psql juga konfirmasi channel-only 3 vs
message-filtered 2.
2026-08-01 10:59:54 +07:00
asepharyana 8a4024f619 fix(fe): crash 'reading charAt' on message avatar fallback
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m47s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m2s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m19s
msg.username bisa undefined saat pesan live masuk lewat WS
(message_updated Partial payload / capture tidak lengkap) ->
msg.username.charAt(0) TypeError, halaman /messages mati.

- message-card + search-panel: username?.charAt(0) ?? '?'
- created_at di-guard juga biar tidak render 'Invalid Date'
Verifikasi: tsc PASS, build PASS, biome 0 error. DB saat ini 0 row
null username (1176 total) — crash murni dari jalur WS live.
2026-08-01 10:37:21 +07:00
asepharyana ec89d64dbf fix(fe): crash 'reading channel_id' + recharts width/height warnings
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m14s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m53s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m15s
- useMessageDetail: guard attachments fetcher — revalidate bisa race
  detail load, detail.data undefined saat fetcher jalan ->
  TypeError 'Cannot read properties of undefined (reading channel_id)'
  yang bikin halaman /messages mati (Next error boundary). Sekarang
  fetcher balikin [] kalau channel_id belum ada; hapus non-null
  assertion. Diverifikasi: /messages sebelumnya crash, sekarang render
  dengan data asli (list, verdict, confidence, sticker, emoji).
- ResponsiveContainer (recharts 3.8): initialDimension -1 di render
  pertama -> warning 'width(-1) and height(-1)'. Pakai height numerik
  tetap (192/160/48) + minWidth/minHeight 0 -> calculatedHeight >0,
  warning hilang; width tetap responsif via ResizeObserver. Chart
  baru dirender setelah mount (useMounted) biar container punya ukuran.
  Diverifikasi console: 0 warning, 0 error di dashboard & voice.
2026-08-01 10:21:23 +07:00
asepharyana 6f41c22cb5 fix(db): migration 0013 rename mascot_chat_messages to chatbot_messages
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m17s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m59s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m7s
/api/chat/history 500 (relation "chatbot_messages" does not exist):
codebase di-rename mascot->chatbot (977a6f9) tapi tabel DB tidak
pernah di-migrate — backend SELECT dari chatbot_messages, DB masih
mascot_chat_messages dengan kolom mascot_response.

- Migration 0013 (idempotent): ALTER TABLE mascot_chat_messages RENAME
  TO chatbot_messages, RENAME COLUMN mascot_response -> bot_response,
  RENAME INDEX -> idx_chatbot_messages_user_created; journal when >
  max(created_at) di __drizzle_migrations (0012)
- Diterapkan live via psql; riwayat chat lama tetap ada
- Verifikasi: GET /api/chat/history 200 + data, POST /api/chat 200
  + tersimpan (total history 1 -> 2)
2026-08-01 09:38:27 +07:00
asepharyana 01c18b2060 refactor(fe): replace TanStack Query with SWR + UI/data cleanup
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m56s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m42s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m59s
Rombak data layer frontend:
- Hapus @tanstack/react-query (package.json, lockfile, provider di
  dashboard layout) — ganti SWR 2.4.2 + SWRConfig (revalidateOnFocus
  false, deduping 10s, no retry on 404)
- Semua hooks data ditulis ulang ke useSWR; useAction() helper baru
  pengganti useMutation dengan surface kompatibel (mutate/mutateAsync/
  isPending/error)
- useMessages + useMessagesHasMore share satu SWR key — probe cursor
  yang tadinya dobel fetch API sekarang deduped
- WS sync (messages/media/recordings) pindah dari queryClient ke
  SWR mutate dengan filter key + revalidate:false
- useMessageSearch() dipakai search-panel & search-overlay; search
  overlay backdrop div -> button (fix a11y lint)

Rapikan UI + isi data:
- Tab stats recordings: placeholder 'coming soon' diganti stat asli
  (total, ukuran, speaker unik, top speakers)
- Empty states konsisten via EmptyState (images/review/recordings),
  EmptyState terima className
- biome check --write: 0 error, 8 warning pre-existing
- Verifikasi: tsc --noEmit PASS, next build PASS (11 halaman static),
  API live dicek — semua endpoint dashboard/messages/guilds/config/
  voice/media/recordings/review balikin data
2026-08-01 09:19:39 +07:00
asepharyana 1f91f99de3 feat(automod): render sticker, role & user names in moderation views
QoL lanjutan dari fix60084b3: content pesan mentah masih nampilin
snowflake (<@&roleid>, <@userid>, <:emoji:id>) di log moderasi dan
prompt LLM. Sekarang dirender ke nama yang bisa dibaca:

- Gateway capture: metadata menyimpan mentionedRoles + mentionedUsers
  (id+name) dari message.mentions, disimpan ke metadata JSON
- renderDiscordMentions(): <@&id> -> @RoleName, <@id> -> @Username,
  <:name:id> -> :name:, fallback @role/@user — dipakai di
  conversationContext (konteks LLM) dan moderationBuilders
  (getAnalysisContent) sehingga LLM lihat nama role/user beneran,
  bukan placeholder generik
- Frontend renderMessageContent() (mirror gateway) dipasang di semua
  tempat nampilin content: message-card, message-detail(-view),
  search-overlay, search-panel, users/channels section, live-stream,
  mod-queue, review list; sticker-only message tetap [Sticker: name],
  pesan teks+sticker kini ikut nampilin nama sticker
- tsc --noEmit PASS di gateway & frontend; renderDiscordMentions
  diverifikasi manual (6 kasus: role/user/emoji/unknown/plain)
2026-08-01 08:56:10 +07:00
asepharyana 9ba2262446 refactor: improve image handling and accessibility in MessagesPage
Deploy to VPS / deploy (push) Successful in 2m17s
2026-07-26 17:31:44 +07:00
asepharyana eca0a378f9 fix: increase max length for user profile summary and sanitize function
Deploy to VPS / deploy (push) Successful in 2m19s
2026-07-26 17:27:51 +07:00
asepharyana b886b71bad feat: add user detail and selection functionality to dashboard
Deploy to VPS / deploy (push) Successful in 2m23s
2026-07-26 17:15:08 +07:00
asepharyana 05bbae66da Refactor voice page and hooks to use React Query for data fetching
Deploy to VPS / deploy (push) Successful in 2m57s
- Updated VoicePage component to utilize useVoiceConnect, useVoiceDisconnect, and useMicTransmit mutations.
- Replaced local state management with React Query's useQuery for voice status, guilds, and channels.
- Removed custom useAsync hook and replaced it with useQuery in useConfig, useStats, useUsers, useChannels, and useMessages hooks.
- Simplified useRecordings and useSpeakers hooks to leverage React Query for data fetching and mutations.
- Removed deprecated use-async hook and related code.
- Enhanced error handling and loading states across various hooks.
2026-07-26 16:55:20 +07:00
asepharyana 323fa207af refactor: streamline data fetching in various hooks and components
Deploy to VPS / deploy (push) Successful in 2m39s
2026-07-26 16:46:53 +07:00
asepharyana 1021301656 fix: add error logging for various API calls across components
Deploy to VPS / deploy (push) Successful in 2m20s
2026-07-26 16:34:06 +07:00
asepharyana 74eabb7231 feat: enhance guild selection logic with auto-selection based on config
Deploy to VPS / deploy (push) Successful in 2m25s
2026-07-26 16:25:04 +07:00
asepharyana 39a3bc6269 fix: add missing draining state variable in VoiceTransmitter class
Deploy to VPS / deploy (push) Successful in 2m18s
2026-07-26 16:18:33 +07:00
asepharyana d5a547eb25 feat: add app header, sidebar, and mobile navigation components
Deploy to VPS / deploy (push) Failing after 1m45s
- Implemented AppHeader component with theme toggle and connection status.
- Created AppSidebar component for navigation with connection status indicator.
- Added MobileNav component for mobile navigation with responsive design.
- Introduced shared components: DetailStat, EmptyState, ErrorState, LoadingSkeleton, and StatCard for consistent UI.
- Developed hooks for async data fetching: useAsync, useConfig, useDashboard, useGuilds, useMedia, useMessages, useRecordings, and useVoice.
- Added chatbot API functions for sending messages and managing chat history.
2026-07-26 16:14:32 +07:00
asepharyana 726ea8fca5 fix: improve readability of download URL handling in RecordingsPage
Deploy to VPS / deploy (push) Successful in 2m7s
2026-07-26 15:45:29 +07:00
asepharyana 779fb6b338 fix: prevent opening undefined download URLs in RecordingsPage
Deploy to VPS / deploy (push) Failing after 1m31s
2026-07-26 15:43:10 +07:00
asepharyana 300512b2cb refactor: clean up code formatting and improve consistency across multiple components
Deploy to VPS / deploy (push) Failing after 1m59s
2026-07-26 15:39:41 +07:00
asepharyana c2502a0e5f feat: add recordings, settings, and voice pages with WebSocket integration
Deploy to VPS / deploy (push) Failing after 1m36s
- Implemented RecordingsPage to display and manage voice recordings with live updates via WebSocket.
- Created SettingsPage for user preferences, including theme toggling and server configuration display.
- Developed VoicePage for managing voice connections, including guild and channel selection, and active speaker display.
- Introduced GuildSelector component for selecting Discord guilds with error handling and loading states.
- Added utility functions for formatting numbers and bytes, and safely parsing JSON.
- Established navigation structure for the dashboard with relevant links for new features.
2026-07-26 15:34:08 +07:00
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 12b23b4632 fix: initialize release variable to prevent potential errors in start/stop methods
Deploy to VPS / deploy (push) Successful in 2m9s
2026-07-26 14:30:36 +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 702f96262e ci: add frontend to pnpm workspace via services/*
Deploy to VPS / deploy (push) Successful in 2m26s
- Change pnpm-workspace.yaml from specific paths to services/* and packages/*
- Remove bun.lock (frontend now uses pnpm lockfile)
- Use --no-frozen-lockfile so lockfile auto-updates in CI
2026-07-26 13:13:59 +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 a85c7da5ed ci: add Rust for node-crc native build
Deploy to VPS / deploy (push) Failing after 1m26s
Install dependencies step fails because node-crc requires cargo
to compile its native N-API module. Restore Rust setup in CI.
2026-07-26 11:45:49 +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 831fddd1bf refactor(backend): remove auth for public API
Deploy to VPS / deploy (push) Failing after 35s
- Remove auth module (auth.routes.ts, /api/auth/login)
- Remove adminAuth middleware from voice and media routes
- Remove adminAuth() function from shared middlewares
- Remove auth-related e2e test
- Clean up .env.example
2026-07-26 11:33:45 +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 cbbe939fad ci: build shared package before services
Deploy to VPS / deploy (push) Successful in 10m26s
2026-07-08 01:52:51 +07:00
asepharyana 9621317a3c chore: format files for lint
Deploy to VPS / deploy (push) Failing after 8m8s
2026-07-08 01:37:46 +07:00
asepharyana a5cf780a65 ci: add gitea deploy workflow 2026-07-08 01:36:51 +07:00
asepharyana df5571664d ci: make deploy script provider neutral 2026-07-08 01:35:58 +07:00
asepharyana 7a4a9350b1 docs: add gitea migration implementation plan 2026-07-08 01:35:52 +07:00
asepharyana 74b05ee667 docs: add gitea migration design 2026-07-08 00:56:06 +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 e7d4a45391 feat: add design specifications for AeroNet Visualization, Nexus Capital Render, and Summit Cloud Migration Platform 2026-07-05 20:33:13 +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 03b257d5a7 fix(deploy): use trunk build for frontend, not pnpm 2026-07-05 07:06:34 +07:00
asepharyana 0668862db5 fix: use bind mounts for hot-deploy so changes survive container restart
deploy.sh now writes to host directories bind-mounted into containers
instead of docker exec tar-pipes (volatile). Added bind mounts to
docker-compose.yml for all 3 services (frontend, backend, gateway).

Memory: hotpatch-volatile-container.md
2026-07-05 07:05:01 +07:00
asepharyana c0edb0fa40 feat: enhance deployment instructions and exclude spam threads from message capture 2026-07-05 06:58:17 +07:00
asepharyana 5036cf0133 refactor(deploy): comprehensive deploy.sh with build + hotpatch 2026-07-05 06:36:37 +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 e0d6077a65 refactor(ci): remove automated deploy, add manual deploy.sh
CI now only builds + pushes images to GitLab Container Registry.
Deploy is done manually via deploy.sh with specific SHA tag support.

Usage: ./deploy.sh [sha]  # default: latest
2026-07-05 04:06:41 +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 b5d4e46b79 fix(ci): deploy by SHA tag, not mutable :latest
Deploy now pulls images pinned to $CI_COMMIT_SHA instead of :latest,
eliminating race-condition deployments where a concurrent pipeline
overwrites the mutable latest tag before deploy runs.

Changes:
- docker-compose.yml: image tags use ${IMAGE_TAG:-latest} env var
- deploy step: IMAGE_TAG=$CI_COMMIT_SHA docker compose pull + up
- scp docker-compose.yml to VPS before running deploy commands
2026-07-05 03:43:13 +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 5fa97da969 chore: remove WASM MIME type declaration from nginx configuration 2026-07-04 05:02:25 +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 f131bd12fb docs: add frontend dependency upgrade design 2026-07-04 03:36:38 +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 4390a3da5e Merge branch 'leptos-rewrite' 2026-07-03 22:58:18 +07:00
asepharyana 5216f2204e feat(leptos): Phase 6 polish components 2026-07-03 22:56:45 +07:00
asepharyana 8a2e914f08 feat(leptos): Phase 5 dashboard feature 2026-07-03 22:46:58 +07:00
asepharyana 52d53fc7f7 feat(leptos): Phase 4 Task 7 - LivePanel composition + app.rs wiring 2026-07-03 22:06:40 +07:00
asepharyana ca89dd7a03 feat(leptos): Phase 4 Task 6 - PCM audio playback + mic transmit hooks 2026-07-03 22:05:37 +07:00
asepharyana aaa8faad55 feat(leptos): Phase 4 Task 5 - RecordingsSubPanel + WaveformPlayer 2026-07-03 21:57:45 +07:00
asepharyana 1d7a433b3c feat(leptos): Phase 4 Task 4 - NowPlaying, MusicSubPanel, ScreenSubPanel 2026-07-03 21:54:47 +07:00
asepharyana 8a3ac78bde feat(leptos): Phase 4 Task 3 - AudioVisualizer + MicLevelMeter components 2026-07-03 21:50:48 +07:00
asepharyana d797b6b4c5 feat(leptos): Phase 4 Task 2 - ActiveSpeakers component 2026-07-03 21:04:41 +07:00
asepharyana 1cc04bda66 feat(leptos): Phase 4 Task 2 - VoiceConnectionCard component 2026-07-03 20:56:06 +07:00
asepharyana c9bc5f5b50 feat(leptos): Phase 4 Task 1 - voice/media control hooks 2026-07-03 20:55:19 +07:00
asepharyana 27f0b500f9 docs: implementation plan for leptos live phase 4 2026-07-03 20:50:28 +07:00
asepharyana 3de7f8d823 fix(leptos): resolve Phase 3 compilation errors
- Add PartialEq to MessageRecord and all nested types in shared-types
- Fix String references in view! macro by cloning owned values
- Fix match arm types with .into_any() in app.rs
- Clone on_load_more before FnMut closure in message_feed.rs
- Pre-compute class strings before passing to view! in message_card.rs
- Fix lifetime issues with imgs/vids/cats by using owned Vec<AttachmentRef>
- Use separate closures for different event types in mod.rs
- Fix disabled property to use signal pattern
- Fix filter chip closure signatures
2026-07-03 20:45:35 +07:00
asepharyana 63ddc1e112 fix(leptos): compile errors in Phase 3 message components - WIP
Fixed:
- Icon imports: Replaced lucide-leptos icons with SVG/emoji alternatives
- AnyView lifetime: Fixed render_emojis to use owned strings
- Missing html import in message_feed.rs
- use_messages: Removed #[component] to make it a regular function
- MessageRecord fields: Removed is_reply, is_forward, is_crosspost checks
- String wrapping in view! macros: Wrapped strings in <span> elements
- Closure handling: Changed .into_forget() to .forget() for web_sys Closure
- URL borrowing in image_grid: Clone URLs before using in view!

Remaining issues (in progress):
- String references in class attributes need owned values
- Type inference for None.into_any()
- Closure capture issues with on_load_more
- Match arm type incompatibilities

19 errors remaining out of 31 initial errors - ~61% fixed
2026-07-03 20:32:15 +07:00
asepharyana 9322434daa feat(leptos): messages module skeleton + use_messages hook 2026-07-03 20:14:59 +07:00
asepharyana b47194cc79 docs: implementation plan for leptos messages phase 3 2026-07-03 20:10:37 +07:00
asepharyana 1b970a4c51 fix(leptos): wire format corrections from whole-branch review 2026-07-03 18:43:25 +07:00
asepharyana bf36bf55fe feat(leptos): integrate auth with API + WS auth gating 2026-07-03 18:30:41 +07:00
asepharyana 2520faad47 feat(leptos): app shell with auth gate and tab routing 2026-07-03 18:22:28 +07:00
asepharyana 5389c82f31 feat(leptos): layout components -- Header, Sidebar, TabStrip, MobileTabBar 2026-07-03 18:16:08 +07:00
asepharyana aa20d1a633 feat(leptos): API client with all endpoint functions 2026-07-03 18:09:30 +07:00
asepharyana 20ef844682 feat(leptos): WebSocket singleton with event dispatch 2026-07-03 18:07:01 +07:00
asepharyana 5832ca7cd4 feat(leptos): UI primitives — Skeleton, StatusBadge, EmptyState, Modal 2026-07-03 17:59:38 +07:00
asepharyana b9e3a255bb feat(leptos): UI primitives — Input, Select, Tabs, ScrollArea, Toast 2026-07-03 17:47:21 +07:00
asepharyana 2b514142e6 feat(leptos): UI primitives — Button, Badge, Card 2026-07-03 17:41:07 +07:00
asepharyana 65804acaca feat(leptos): css design system with component classes and animations 2026-07-03 17:36:28 +07:00
asepharyana c4c43ce912 feat(leptos): frontend crate scaffold with empty app
- frontend/ crate compiles to WASM via trunk
- empty Leptos app mounted to body via wasm_bindgen(start)
- dependencies: leptos 0.7 CSR, leptos-use, lucide-leptos, gloo-net, web-sys
- workspace cargo check passes (first time the workspace compiles end-to-end)
- trunk build produces 65KB WASM + 25KB JS glue

Deviations from brief:
- lucide-leptos: 0.5 (brief) -> 3 (only version published)
- web-sys: removed invalid features ArrayBuffer/DataView (in js-sys/wasm-bindgen)
- src/main.rs -> src/lib.rs with #[wasm_bindgen(start)] to avoid bin/lib duplicate artifact
2026-07-03 17:09:44 +07:00
asepharyana f67bc5125b fix(leptos): correct shared-types timestamps to match JSON wire format 2026-07-03 07:24:28 +07:00