371 lines
8.9 KiB
Markdown
371 lines
8.9 KiB
Markdown
# Mascot Implementation Guide
|
|||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The Discord Moderation Watcher frontend features an intelligent anime mascot with AI-powered conversation insights and animated floating chat bubbles.
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Components
|
||
|
|
|
||
|
|
#### MascotImage (`src/widgets/mascot/MascotImage.tsx`)
|
||
|
|
Main mascot component that displays the PNG image with optional floating chat bubble.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
<MascotImage
|
||
|
|
size="sm" | "md" | "lg" // Size variant: sm (64px), md (128px), lg (192px)
|
||
|
|
className="..." // Additional Tailwind classes
|
||
|
|
showChat={boolean} // Show chat bubble
|
||
|
|
chatMessage="..." // Chat message text
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Features:**
|
||
|
|
- Framer Motion spring animations
|
||
|
|
- Responsive sizing
|
||
|
|
- Gradient chat bubble with backdrop blur
|
||
|
|
- Auto-hide after 8 seconds
|
||
|
|
- Message circle icon
|
||
|
|
|
||
|
|
#### useMascotSummary (`src/shared/hooks/useMascotSummary.ts`)
|
||
|
|
React hook that generates AI insights from message data.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const summary = useMascotSummary({
|
||
|
|
messages: MessageRecord[], // Recent messages
|
||
|
|
enabled: boolean // Enable/disable hook
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
**Analysis:**
|
||
|
|
- Message count tracking
|
||
|
|
- Unique participant counting
|
||
|
|
- Average message length analysis
|
||
|
|
- Activity intensity detection
|
||
|
|
- Conversation type identification
|
||
|
|
- Auto-rotating insights (5-second cycle)
|
||
|
|
|
||
|
|
### Data Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
App Component
|
||
|
|
├─ messages.messages
|
||
|
|
└─ Pass to DashboardLayout
|
||
|
|
│
|
||
|
|
├─ DashboardLayout
|
||
|
|
│ ├─ useMascotSummary hook
|
||
|
|
│ ├─ Generate mascotSummary
|
||
|
|
│ └─ Pass to Sidebar
|
||
|
|
│ │
|
||
|
|
│ ├─ Sidebar
|
||
|
|
│ │ └─ MascotImage
|
||
|
|
│ │ └─ Floating chat bubble
|
||
|
|
│ │
|
||
|
|
│ └─ Other components
|
||
|
|
│ ├─ EmptyStateMascot
|
||
|
|
│ ├─ EmptyStateMascot
|
||
|
|
│ └─ ...
|
||
|
|
```
|
||
|
|
|
||
|
|
## Assets
|
||
|
|
|
||
|
|
### Logo (SVG)
|
||
|
|
- **URL:** `https://raw.githubusercontent.com/IMPHNEN/imphnen-frontend-service/develop/docs/logo.svg`
|
||
|
|
- **Used in:** Favicon, Sidebar top
|
||
|
|
- **Size:** 8x8px
|
||
|
|
- **Cache:** 300 seconds (GitHub CDN)
|
||
|
|
|
||
|
|
### Mascot (PNG)
|
||
|
|
- **URL:** `https://raw.githubusercontent.com/IMPHNEN/imphnen-frontend-service/develop/apps/dimentorin/public/image/mascot-1.png`
|
||
|
|
- **Used in:** Sidebar, Empty states, Chat bubble
|
||
|
|
- **Sizes:** sm (64px), md (128px), lg (192px)
|
||
|
|
- **Cache:** 300 seconds (GitHub CDN)
|
||
|
|
|
||
|
|
## Locations
|
||
|
|
|
||
|
|
### Sidebar (sm - 64px)
|
||
|
|
- **Position:** Bottom corner, expanded sidebar only
|
||
|
|
- **Feature:** Chat bubble with rotating insights
|
||
|
|
- **Visibility:** Always visible when expanded
|
||
|
|
- **Chat Trigger:** Messages tab with active conversations
|
||
|
|
|
||
|
|
### Empty States (md - 128px, 60% opacity)
|
||
|
|
- Message Feed
|
||
|
|
- Image Grid
|
||
|
|
- Analytics Panel
|
||
|
|
- Active Speakers
|
||
|
|
- Voice Recordings
|
||
|
|
|
||
|
|
### NOT Displayed
|
||
|
|
- ❌ Auth/Login page
|
||
|
|
- ❌ Voice connection page
|
||
|
|
- ❌ Media control page
|
||
|
|
|
||
|
|
## Chat Bubble Design
|
||
|
|
|
||
|
|
### Visual Style
|
||
|
|
```
|
||
|
|
┌─────────────────────┐
|
||
|
|
│ 💬 "Diskusi aktif" │
|
||
|
|
│ • 5 peserta │
|
||
|
|
│ • Volume tinggi │
|
||
|
|
└─────────────────────┘
|
||
|
|
◯ (tail)
|
||
|
|
```
|
||
|
|
|
||
|
|
### CSS Classes
|
||
|
|
- Background: `bg-gradient-to-br from-primary/90 to-primary/80`
|
||
|
|
- Border: `border border-primary/50`
|
||
|
|
- Rounded: `rounded-2xl`
|
||
|
|
- Padding: `px-4 py-2.5`
|
||
|
|
- Effects: `shadow-lg backdrop-blur-sm`
|
||
|
|
|
||
|
|
### Animations
|
||
|
|
- **Entrance:** Spring (stiffness: 300, damping: 25)
|
||
|
|
- Scale: 0.8 → 1.0
|
||
|
|
- Opacity: 0 → 1
|
||
|
|
- Y Position: 10px → 0
|
||
|
|
- **Exit:** Reverse animation
|
||
|
|
- **Duration:** Auto-hide after 8 seconds
|
||
|
|
|
||
|
|
## AI Summary Logic
|
||
|
|
|
||
|
|
### generateInsight()
|
||
|
|
Analyzes message data to create meaningful insights.
|
||
|
|
|
||
|
|
**Factors Analyzed:**
|
||
|
|
1. **Message Count**
|
||
|
|
- Display: "📈 Total: X pesan"
|
||
|
|
|
||
|
|
2. **Participant Analysis**
|
||
|
|
- Count unique user_ids
|
||
|
|
- Display: "👥 Partisipan: N orang"
|
||
|
|
|
||
|
|
3. **Content Length Analysis**
|
||
|
|
- Average message length
|
||
|
|
- > 150 chars: "Diskusi mendalam 🔬"
|
||
|
|
- 80-150: "Percakapan normal 💬"
|
||
|
|
- < 80: "Chat cepat ⚡"
|
||
|
|
|
||
|
|
4. **Activity Intensity**
|
||
|
|
- > 50 msgs: "Volume tinggi 🔥"
|
||
|
|
- > 20 msgs: "Percakapan aktif"
|
||
|
|
- < 20: "Quiet mode"
|
||
|
|
|
||
|
|
5. **Topic Detection**
|
||
|
|
- Keywords: voice, recording, audio, chat, message, user
|
||
|
|
- Maps to labels: Voice, Recording, Audio, Chat, Message, User
|
||
|
|
|
||
|
|
### Auto-Rotation
|
||
|
|
- Updates every 5 seconds
|
||
|
|
- Cycles between different insights
|
||
|
|
- Keeps conversation fresh
|
||
|
|
- Smart rotation logic
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### Basic Usage (Sidebar)
|
||
|
|
```typescript
|
||
|
|
<MascotImage
|
||
|
|
size="sm"
|
||
|
|
showChat={showChat && !collapsed}
|
||
|
|
chatMessage={mascotChatMessage}
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Empty State Usage
|
||
|
|
```typescript
|
||
|
|
<MascotImage size="md" className="opacity-60" />
|
||
|
|
```
|
||
|
|
|
||
|
|
### With Custom Message
|
||
|
|
```typescript
|
||
|
|
<MascotImage
|
||
|
|
size="md"
|
||
|
|
showChat={true}
|
||
|
|
chatMessage="🔥 Volume tinggi • 12 peserta"
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Integration
|
||
|
|
|
||
|
|
### In DashboardLayout
|
||
|
|
```typescript
|
||
|
|
const mascotSummary = useMascotSummary({
|
||
|
|
messages: recentMessages,
|
||
|
|
enabled: activeTab === "messages" && recentMessages.length > 0,
|
||
|
|
});
|
||
|
|
|
||
|
|
<Sidebar
|
||
|
|
activeTab={activeTab}
|
||
|
|
onTabChange={onTabChange}
|
||
|
|
mascotChatMessage={mascotSummary}
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
### In App
|
||
|
|
```typescript
|
||
|
|
<DashboardLayout
|
||
|
|
activeTab={activeTab}
|
||
|
|
wsStatus={socket.status}
|
||
|
|
voiceStatus={voice.voiceStatus}
|
||
|
|
onTabChange={(tab) => patchUIState({ activeTab: tab })}
|
||
|
|
recentMessages={messages.messages}
|
||
|
|
>
|
||
|
|
{/* content */}
|
||
|
|
</DashboardLayout>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Customization
|
||
|
|
|
||
|
|
### Size Variants
|
||
|
|
Edit `sizeMap` in `MascotImage.tsx`:
|
||
|
|
```typescript
|
||
|
|
const sizeMap = {
|
||
|
|
sm: "w-16 h-auto", // 64px
|
||
|
|
md: "w-32 h-auto", // 128px
|
||
|
|
lg: "w-48 h-auto", // 192px
|
||
|
|
xl: "w-64 h-auto", // 256px (custom)
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Chat Bubble Styling
|
||
|
|
Edit bubble classes in `MascotImage.tsx`:
|
||
|
|
- Change background: `bg-gradient-to-br from-primary/90 to-primary/80`
|
||
|
|
- Change corner radius: `rounded-2xl`
|
||
|
|
- Change padding: `px-4 py-2.5`
|
||
|
|
- Change effects: `shadow-lg backdrop-blur-sm`
|
||
|
|
|
||
|
|
### Animation Timing
|
||
|
|
Edit animation config:
|
||
|
|
- Spring stiffness: Higher = faster/snappier
|
||
|
|
- Spring damping: Higher = less bouncy
|
||
|
|
- Auto-hide delay: Change `setTimeout` in `useEffect`
|
||
|
|
|
||
|
|
### Summary Rotation
|
||
|
|
Edit rotation interval in `useMascotSummary`:
|
||
|
|
```typescript
|
||
|
|
const interval = setInterval(() => {
|
||
|
|
// Update summary
|
||
|
|
}, 5000); // 5 seconds
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance Considerations
|
||
|
|
|
||
|
|
### Bundle Size Impact
|
||
|
|
- ✅ ChibiMascot removed: -895 lines
|
||
|
|
- ✅ MascotImage added: +98 lines
|
||
|
|
- ✅ useMascotSummary hook: +98 lines
|
||
|
|
- ✅ Net: -779 lines (smaller bundle!)
|
||
|
|
- ✅ PNG from CDN (not bundled)
|
||
|
|
|
||
|
|
### Runtime Performance
|
||
|
|
- ✅ Framer Motion optimized
|
||
|
|
- ✅ useCallback for memoization
|
||
|
|
- ✅ 5-second update cycle (not constant)
|
||
|
|
- ✅ Proper cleanup on unmount
|
||
|
|
- ✅ No memory leaks
|
||
|
|
|
||
|
|
### CDN Performance
|
||
|
|
- ✅ GitHub CDN caching: 300 seconds
|
||
|
|
- ✅ Browser caching enabled
|
||
|
|
- ✅ Reduces server load
|
||
|
|
- ✅ Fast global delivery
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Chat Bubble Not Showing
|
||
|
|
**Check:**
|
||
|
|
- `showChat` prop is `true`
|
||
|
|
- `chatMessage` is not empty
|
||
|
|
- Sidebar is expanded
|
||
|
|
- Active tab is "messages"
|
||
|
|
|
||
|
|
### Images Not Loading
|
||
|
|
**Check:**
|
||
|
|
- GitHub URLs are accessible (curl -I)
|
||
|
|
- CDN cache not stale (check ETag)
|
||
|
|
- Browser cache cleared
|
||
|
|
- No CORS issues (GitHub allows)
|
||
|
|
|
||
|
|
### Animations Janky
|
||
|
|
**Check:**
|
||
|
|
- Browser hardware acceleration enabled
|
||
|
|
- Too many other animations
|
||
|
|
- Framer Motion version compatible
|
||
|
|
- Browser performance metrics
|
||
|
|
|
||
|
|
### Summary Not Updating
|
||
|
|
**Check:**
|
||
|
|
- `enabled` prop is true
|
||
|
|
- Messages array has data
|
||
|
|
- 5-second interval is running
|
||
|
|
- No console errors
|
||
|
|
|
||
|
|
## Maintenance
|
||
|
|
|
||
|
|
### Regular Checks
|
||
|
|
- Monitor mascot chat appearance in production
|
||
|
|
- Verify summary accuracy with live data
|
||
|
|
- Check animation performance on browsers
|
||
|
|
- Track bundle size metrics
|
||
|
|
|
||
|
|
### Updates
|
||
|
|
- To change summary logic: Edit `useMascotSummary.ts`
|
||
|
|
- To change styling: Edit `MascotImage.tsx` classes
|
||
|
|
- To change animation: Edit Framer Motion config
|
||
|
|
- To change CDN URLs: Update image URLs (2 places)
|
||
|
|
|
||
|
|
### Rollback
|
||
|
|
If issues occur:
|
||
|
|
```bash
|
||
|
|
git revert 9f454b5 # Revert AI integration
|
||
|
|
git revert bb65178 # Revert component replacement
|
||
|
|
git revert 2ea0ea5 # Revert logo/mascot integration
|
||
|
|
```
|
||
|
|
|
||
|
|
No database changes, safe to rollback anytime.
|
||
|
|
|
||
|
|
## Files Reference
|
||
|
|
|
||
|
|
| File | Purpose | Lines |
|
||
|
|
|------|---------|-------|
|
||
|
|
| `MascotImage.tsx` | Main component | 98 |
|
||
|
|
| `useMascotSummary.ts` | AI hook | 98 |
|
||
|
|
| `DashboardLayout.tsx` | Integration | Updated |
|
||
|
|
| `Sidebar.tsx` | Display | Updated |
|
||
|
|
| `App.tsx` | Data flow | Updated |
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
### Manual Testing Checklist
|
||
|
|
- [ ] Mascot displays in sidebar
|
||
|
|
- [ ] Chat bubble appears with message
|
||
|
|
- [ ] Animation smooth and performant
|
||
|
|
- [ ] Auto-hide after 8 seconds
|
||
|
|
- [ ] Summary rotates every 5 seconds
|
||
|
|
- [ ] Empty states show mascot
|
||
|
|
- [ ] No mascot on auth page
|
||
|
|
- [ ] Responsive sizing works
|
||
|
|
- [ ] No console errors
|
||
|
|
- [ ] Images load from CDN
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
- [ ] Click interaction handler
|
||
|
|
- [ ] ML-based summary generation
|
||
|
|
- [ ] Theme customization
|
||
|
|
- [ ] Sound effects
|
||
|
|
- [ ] Chat history
|
||
|
|
- [ ] Multi-language support
|
||
|
|
- [ ] Mobile optimization
|
||
|
|
- [ ] Settings panel
|
||
|
|
- [ ] User preferences
|
||
|
|
- [ ] Animation toggle
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Last Updated:** 2026-06-03
|
||
|
|
**Version:** 1.0.0
|
||
|
|
**Status:** Production Ready ✅
|