Files
xiaoxia-saas/apps/web/src/pages/editing-planner/hooks/usePlaybackControl.ts
T
SaaS Frontend a1bda3e484
AI Code Review / AI Code Review (pull_request) Failing after 0s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 32s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 47s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m16s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m16s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 57s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 15s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 54s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m3s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 28s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 2m14s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m36s
refactor(editing-planner): Phase 3 - extract business hooks
Extract 4 business hooks from EditingPlanner.tsx:
- useEditorDrawers (78行): 11个抽屉开关 + 目标ID + 快捷打开
- usePlaybackControl (56行): 播放/暂停、rAF帧推进、缩放、seek
- useClipOperations (231行): 片段CRUD、重排、裁剪、分割、转场、调速、TTS、配音
- useTemplateManagement (459行): 模板列表/详情/计划加载、保存、模式切换、筛选搜索

主文件: 997→415行(-58%)
2026-07-26 03:39:36 +08:00

57 lines
1.5 KiB
TypeScript

import { useState, useCallback, useEffect, useRef } from "react"
/**
* 播放控制 Hook
* 播放/暂停、rAF 帧推进、时间线缩放、seek
*/
export const usePlaybackControl = (totalDuration: number) => {
const [isPlaying, setIsPlaying] = useState(false)
const [currentTime, setCurrentTime] = useState(0)
const [pixelsPerSecond, setPixelsPerSecond] = useState(40)
const prevFrameTimeRef = useRef<number | null>(null)
/** 播放头跳转 */
const handleSeek = useCallback((time: number) => {
setCurrentTime(Math.max(0, time))
}, [])
/** 轨道缩放 */
const handleZoomChange = useCallback((pps: number) => {
setPixelsPerSecond(pps)
}, [])
/** rAF 帧推进 — 播放时平滑更新播放头位置 */
useEffect(() => {
if (!isPlaying) {
prevFrameTimeRef.current = null
return
}
let rafId: number
const tick = (timestamp: number) => {
if (prevFrameTimeRef.current !== null) {
const delta = (timestamp - prevFrameTimeRef.current) / 1000
setCurrentTime((prev) => {
const next = prev + delta
return next >= totalDuration ? totalDuration : next
})
}
prevFrameTimeRef.current = timestamp
rafId = requestAnimationFrame(tick)
}
rafId = requestAnimationFrame(tick)
return () => {
cancelAnimationFrame(rafId)
prevFrameTimeRef.current = null
}
}, [isPlaying, totalDuration])
return {
isPlaying,
setIsPlaying,
currentTime,
pixelsPerSecond,
handleSeek,
handleZoomChange,
}
}