@@ -33,6 +33,7 @@ export default function App() {
3333 const [ updateReady , setUpdateReady ] = useState < boolean > ( false )
3434 const [ manualMode , setManualMode ] = useState < boolean > ( false )
3535 const [ manualBpm , setManualBpm ] = useState < number | null > ( null )
36+ const manualModeRef = useRef < boolean > ( false )
3637 const mqlCleanupRef = useRef < null | ( ( ) => void ) > ( null )
3738 // 高亮锁:当某个值在高置信度下被高亮后,如果之后收到同值但低置信度的数据,仍保持高亮,直到值发生变化
3839 const bpmRef = useRef < number | null > ( null )
@@ -42,6 +43,10 @@ export default function App() {
4243 const lowConfPromoteThreshold = 5
4344 const manualTapTimesRef = useRef < number [ ] > ( [ ] )
4445
46+ useEffect ( ( ) => {
47+ manualModeRef . current = manualMode
48+ } , [ manualMode ] )
49+
4550 const darkTheme = {
4651 background : '#14060a' ,
4752 textPrimary : '#ffffff' ,
@@ -127,12 +132,15 @@ export default function App() {
127132 }
128133
129134 // 归零即刷新:抽取公共方法,供按钮与静音超时复用
130- async function doRefresh ( ) {
135+ async function doRefresh ( options ?: { keepManualMode ?: boolean } ) {
131136 if ( refreshSpin ) return
132137 setRefreshSpin ( true )
138+ const keepManualMode = options ?. keepManualMode ?? false
133139 try {
134140 // 清空前端可见状态
135- resetManualMode ( )
141+ if ( ! keepManualMode ) {
142+ resetManualMode ( )
143+ }
136144 setBpm ( null ) ; bpmRef . current = null
137145 setConf ( null )
138146 setState ( 'analyzing' )
@@ -261,7 +269,7 @@ export default function App() {
261269 const SILENT_TIMEOUT_MS = 10000
262270 if ( ! silenceTriggeredRef . current && ( nowTs - lastNonSilentAtRef . current >= SILENT_TIMEOUT_MS ) ) {
263271 silenceTriggeredRef . current = true
264- await doRefresh ( )
272+ await doRefresh ( { keepManualMode : manualModeRef . current } )
265273 }
266274 // 连续静音达到阈值才显示“等待声音”
267275 if ( ! showWaitingRef . current && rms <= SILENT_ENTER_THR && ( nowTs - lastNonSilentAtRef . current >= SILENT_LABEL_WAIT_MS ) ) {
@@ -441,23 +449,7 @@ export default function App() {
441449 < div style = { { position :'fixed' , right :12 , top :12 , display :'flex' , gap :8 , alignItems :'center' } } >
442450 < button
443451 onClick = { async ( ) => {
444- if ( refreshSpin ) return
445- setRefreshSpin ( true )
446- try {
447- // 清空前端可见状态
448- resetManualMode ( )
449- setBpm ( null ) ; bpmRef . current = null
450- setConf ( null )
451- setState ( 'analyzing' )
452- setViz ( null )
453- highlightLockRef . current = { locked : false , bpm : null }
454- lowConfStreakRef . current = { bpm : null , count : 0 }
455- // 通知后端软重置
456- try { await invoke ( 'reset_backend' ) } catch { }
457- } finally {
458- // 启动一次 360° 顺时针旋转动画
459- setTimeout ( ( ) => setRefreshSpin ( false ) , 420 )
460- }
452+ await doRefresh ( )
461453 } }
462454 title = { t ( 'refresh' ) || '刷新' }
463455 style = { {
0 commit comments