Refactor login functionality and enhance MobileCallPage positioning

- Update LoginPage to initialize username state as an empty string for improved user experience.
- Introduce floatingVideoRef in MobileCallVisualWorkspace to dynamically manage video panel positioning.
- Adjust position calculations for the floating video panel to account for its dimensions, enhancing drag-and-drop functionality and ensuring proper placement within the viewport.
This commit is contained in:
Xin Wang
2026-07-13 08:08:00 +08:00
parent 313387778a
commit bd2f156cca
2 changed files with 27 additions and 8 deletions

View File

@@ -18,7 +18,7 @@ import { Input } from "@/components/ui/input";
export default function LoginPage() {
const router = useRouter();
const { user, loading, login } = useAuth();
const [username, setUsername] = useState("admin");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState("");

View File

@@ -150,6 +150,7 @@ function MobileCallVisualWorkspace({
cameraError: string | null;
}) {
const containerRef = useRef<HTMLDivElement>(null);
const floatingVideoRef = useRef<HTMLButtonElement>(null);
const [position, setPosition] = useState({ x: 16, y: 72 });
const positionedRef = useRef(false);
const dragRef = useRef<{
@@ -166,16 +167,25 @@ function MobileCallVisualWorkspace({
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const floatingVideo = floatingVideoRef.current;
if (!container || !floatingVideo) return;
const rect = container.getBoundingClientRect();
const floatWidth = floatingVideo.offsetWidth;
const floatHeight = floatingVideo.offsetHeight;
if (!positionedRef.current) {
positionedRef.current = true;
setPosition({ x: Math.max(16, rect.width - 168), y: 72 });
setPosition({ x: Math.max(16, rect.width - floatWidth - 16), y: 72 });
return;
}
setPosition((current) => ({
x: Math.min(Math.max(16, current.x), Math.max(16, rect.width - 168)),
y: Math.min(Math.max(72, current.y), Math.max(72, rect.height - 200)),
x: Math.min(
Math.max(16, current.x),
Math.max(16, rect.width - floatWidth - 16),
),
y: Math.min(
Math.max(72, current.y),
Math.max(72, rect.height - floatHeight - 104),
),
}));
}, [view]);
@@ -187,9 +197,17 @@ function MobileCallVisualWorkspace({
const dy = event.clientY - drag.startY;
if (Math.abs(dx) + Math.abs(dy) > 4) drag.moved = true;
const rect = container.getBoundingClientRect();
const floatWidth = event.currentTarget.offsetWidth;
const floatHeight = event.currentTarget.offsetHeight;
setPosition({
x: Math.min(Math.max(16, drag.originX + dx), Math.max(16, rect.width - 168)),
y: Math.min(Math.max(72, drag.originY + dy), Math.max(72, rect.height - 200)),
x: Math.min(
Math.max(16, drag.originX + dx),
Math.max(16, rect.width - floatWidth - 16),
),
y: Math.min(
Math.max(72, drag.originY + dy),
Math.max(72, rect.height - floatHeight - 104),
),
});
}, []);
@@ -199,9 +217,10 @@ function MobileCallVisualWorkspace({
<>
<MobileCallTranscript messages={messages} />
<button
ref={floatingVideoRef}
type="button"
style={{ left: position.x, top: position.y }}
className="absolute z-10 h-24 w-38 touch-none overflow-hidden rounded-2xl border border-white/20 bg-black shadow-2xl ring-1 ring-black/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
className="absolute z-10 aspect-video w-[clamp(7.5rem,38vw,10rem)] touch-none overflow-hidden rounded-2xl border border-white/20 bg-black shadow-2xl ring-1 ring-black/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50"
aria-label="拖动摄像头浮窗,点击切换到视频流"
onPointerDown={(event) => {
event.currentTarget.setPointerCapture(event.pointerId);