feat(v2): remove old dashboard, add vitae + resizable windows
- Removed old Recharts dashboard view entirely (no more viewMode toggle, DashboardView lazy import, Ctrl+D shortcut) - Recharts chunk eliminated from build — bundle size reduced - Player Dashboard window: added Vitae column (red when > 0%) - ALL windows now resizable: drag bottom-right corner handle (min 300×200px). Subtle diagonal line grip indicator. - Sidebar: removed 📊 Dashboard toggle link, removed broken /quest-status.html external link (replaced by 📜 Quests window) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
938421999a
commit
a5bd659876
37 changed files with 168 additions and 178 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useRef, useCallback, useEffect } from 'react';
|
||||
import React, { useRef, useCallback, useEffect, useState } from 'react';
|
||||
import { useWindowManager } from '../../contexts/WindowManagerContext';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -14,7 +14,9 @@ export const DraggableWindow: React.FC<Props> = ({ id, title, zIndex, width = 70
|
|||
const { closeWindow, bringToFront } = useWindowManager();
|
||||
const winRef = useRef<HTMLDivElement>(null);
|
||||
const dragRef = useRef({ dragging: false, sx: 0, sy: 0, ox: 0, oy: 0 });
|
||||
const resizeRef = useRef({ resizing: false, sx: 0, sy: 0, sw: 0, sh: 0 });
|
||||
const posRef = useRef({ x: 420, y: 10 + Math.random() * 40 });
|
||||
const [size, setSize] = useState({ w: width, h: height });
|
||||
|
||||
const onHeaderDown = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -24,16 +26,34 @@ export const DraggableWindow: React.FC<Props> = ({ id, title, zIndex, width = 70
|
|||
dragRef.current = { dragging: true, sx: e.clientX, sy: e.clientY, ox: rect.left, oy: rect.top };
|
||||
}, [id, bringToFront]);
|
||||
|
||||
const onResizeDown = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
resizeRef.current = { resizing: true, sx: e.clientX, sy: e.clientY, sw: size.w, sh: size.h };
|
||||
}, [size.w, size.h]);
|
||||
|
||||
useEffect(() => {
|
||||
const onMove = (e: MouseEvent) => {
|
||||
// Drag
|
||||
const d = dragRef.current;
|
||||
if (!d.dragging || !winRef.current) return;
|
||||
posRef.current.x = d.ox + (e.clientX - d.sx);
|
||||
posRef.current.y = d.oy + (e.clientY - d.sy);
|
||||
winRef.current.style.left = `${posRef.current.x}px`;
|
||||
winRef.current.style.top = `${posRef.current.y}px`;
|
||||
if (d.dragging && winRef.current) {
|
||||
posRef.current.x = d.ox + (e.clientX - d.sx);
|
||||
posRef.current.y = d.oy + (e.clientY - d.sy);
|
||||
winRef.current.style.left = `${posRef.current.x}px`;
|
||||
winRef.current.style.top = `${posRef.current.y}px`;
|
||||
}
|
||||
// Resize
|
||||
const r = resizeRef.current;
|
||||
if (r.resizing) {
|
||||
const newW = Math.max(300, r.sw + (e.clientX - r.sx));
|
||||
const newH = Math.max(200, r.sh + (e.clientY - r.sy));
|
||||
setSize({ w: newW, h: newH });
|
||||
}
|
||||
};
|
||||
const onUp = () => {
|
||||
dragRef.current.dragging = false;
|
||||
resizeRef.current.resizing = false;
|
||||
};
|
||||
const onUp = () => { dragRef.current.dragging = false; };
|
||||
window.addEventListener('mousemove', onMove);
|
||||
window.addEventListener('mouseup', onUp);
|
||||
return () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); };
|
||||
|
|
@ -43,7 +63,7 @@ export const DraggableWindow: React.FC<Props> = ({ id, title, zIndex, width = 70
|
|||
<div
|
||||
ref={winRef}
|
||||
className="ml-window"
|
||||
style={{ zIndex, width, height, left: posRef.current.x, top: posRef.current.y }}
|
||||
style={{ zIndex, width: size.w, height: size.h, left: posRef.current.x, top: posRef.current.y }}
|
||||
onMouseDown={() => bringToFront(id)}
|
||||
>
|
||||
<div className="ml-window-header" onMouseDown={onHeaderDown}>
|
||||
|
|
@ -53,6 +73,8 @@ export const DraggableWindow: React.FC<Props> = ({ id, title, zIndex, width = 70
|
|||
<div className="ml-window-content">
|
||||
{children}
|
||||
</div>
|
||||
{/* Resize handle */}
|
||||
<div className="ml-window-resize" onMouseDown={onResizeDown} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export const PlayerDashboardWindow: React.FC<Props> = ({ id, zIndex, characters
|
|||
state: t.vt_state ?? 'idle',
|
||||
tapers: parseInt(t.prismatic_taper_count as string) || 0,
|
||||
hp: c.vitals?.health_percentage ?? 0,
|
||||
vitae: c.vitals?.vitae ?? 0,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -74,6 +75,7 @@ export const PlayerDashboardWindow: React.FC<Props> = ({ id, zIndex, characters
|
|||
<th style={{ ...thStyle('deaths'), textAlign: 'right' }} onClick={() => toggleSort('deaths')}>Deaths{arrow('deaths')}</th>
|
||||
<th style={{ ...thStyle('uptime'), textAlign: 'right' }} onClick={() => toggleSort('uptime')}>Uptime{arrow('uptime')}</th>
|
||||
<th style={{ textAlign: 'right', padding: '4px 6px', color: '#888', fontSize: '0.65rem', fontWeight: 600, borderBottom: '1px solid #444' }}>HP%</th>
|
||||
<th style={{ textAlign: 'right', padding: '4px 6px', color: '#888', fontSize: '0.65rem', fontWeight: 600, borderBottom: '1px solid #444' }}>Vitae</th>
|
||||
<th style={{ textAlign: 'right', padding: '4px 6px', color: '#888', fontSize: '0.65rem', fontWeight: 600, borderBottom: '1px solid #444' }}>Tapers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -98,6 +100,8 @@ export const PlayerDashboardWindow: React.FC<Props> = ({ id, zIndex, characters
|
|||
<td style={{ textAlign: 'right', padding: '3px 6px', color: '#888', fontVariantNumeric: 'tabular-nums' }}>{p.uptime}</td>
|
||||
<td style={{ textAlign: 'right', padding: '3px 6px', fontVariantNumeric: 'tabular-nums',
|
||||
color: p.hp > 80 ? '#4c4' : p.hp > 40 ? '#ca0' : '#c44' }}>{p.hp.toFixed(0)}%</td>
|
||||
<td style={{ textAlign: 'right', padding: '3px 6px', fontVariantNumeric: 'tabular-nums',
|
||||
color: p.vitae > 0 ? '#f66' : '#333' }}>{p.vitae > 0 ? `${p.vitae}%` : ''}</td>
|
||||
<td style={{ textAlign: 'right', padding: '3px 6px', color: '#888', fontVariantNumeric: 'tabular-nums' }}>{p.tapers.toLocaleString()}</td>
|
||||
</tr>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue