fix(circuit): 偶数 set 数休息语音被一半/进度提示吞掉
偶数组数 sets×hold/2 正好压在组练完→休息切换的同一 tick: _circuitCue 先播 halfway 并占麦 2.6s,导致 _circuitPhase 的 restStart 被静音。修复:atRestBoundary 且 restStart 会播时, 跳过 halfway/last30/last10 让休息语音优先;奇数组数/短组 配置不动,无回归。
This commit is contained in:
@@ -5,3 +5,9 @@
|
|||||||
- **根因**:自定义 tabBar 组件的 `pageLifetimes.show()` 对自定义 tabBar **不触发**(微信框架特殊行为——自定义 tabBar 由框架管理,不走普通组件的页面生命周期)。各 tab 页 `onShow` 里只做了 `tb.setData({selected:X})` 设高亮,没有同步主题;`onSelectDarkMode` 里 `getCurrentPages()` 只返回当前 tab 页(其他 tab 不在页面栈里),所以 `tb.updateTheme()` 只刷新了设置页的 tabBar 实例。
|
- **根因**:自定义 tabBar 组件的 `pageLifetimes.show()` 对自定义 tabBar **不触发**(微信框架特殊行为——自定义 tabBar 由框架管理,不走普通组件的页面生命周期)。各 tab 页 `onShow` 里只做了 `tb.setData({selected:X})` 设高亮,没有同步主题;`onSelectDarkMode` 里 `getCurrentPages()` 只返回当前 tab 页(其他 tab 不在页面栈里),所以 `tb.updateTheme()` 只刷新了设置页的 tabBar 实例。
|
||||||
- **修复**:4 个 tab 页 `onShow` 里获取 tabBar 后,在 `setData({selected:X})` 之后加一行 `tb.updateTheme()`。`updateTheme()` 内部调 `applyThemeToPage(this)`(有"样式未变则跳过"的优化),不会产生多余渲染。涉及 `pages/index/index.js`、`pages/records/records.js`、`pages/leaderboard/leaderboard.js`、`pages/settings/settings.js`。
|
- **修复**:4 个 tab 页 `onShow` 里获取 tabBar 后,在 `setData({selected:X})` 之后加一行 `tb.updateTheme()`。`updateTheme()` 内部调 `applyThemeToPage(this)`(有"样式未变则跳过"的优化),不会产生多余渲染。涉及 `pages/index/index.js`、`pages/records/records.js`、`pages/leaderboard/leaderboard.js`、`pages/settings/settings.js`。
|
||||||
- **教训**:自定义 tabBar 不能依赖 `pageLifetimes` 做状态同步,必须在各 tab 页 `onShow` 里显式调 `this.getTabBar()` 更新。
|
- **教训**:自定义 tabBar 不能依赖 `pageLifetimes` 做状态同步,必须在各 tab 页 `onShow` 里显式调 `this.getTabBar()` 更新。
|
||||||
|
|
||||||
|
## 修复:循环训练偶数组数休息语音被「一半」提示吞掉
|
||||||
|
- **现象**:循环训练设 2 组时,第 1 组练完进入休息,本该播 `restStart`「休息一下」,实际播的是 `halfway`「已完成一半啦」,休息语音不响。
|
||||||
|
- **根因**:偶数 set 数时 `sets×hold/2` 正好落在某组练完→休息切换的那一 tick。`_circuitCue` 先播 halfway 并设 `_voiceBusyUntil=now+2600` 占麦;紧接着 `_advance()`→`_circuitPhase('resting')` 检查麦占用,`restStart` 被静音。原代码注释有意让"进度提示优先于阶段提示",但偶数组数下两者撞车。
|
||||||
|
- **修复**:`_circuitCue` 里先算 `atRestBoundary`(phaseRemaining<=0 && rest>0 && setIndex<sets) 与 `restWillSpeak`(hold>=10 && rest>=5);halfway/last30/last10 在"落在休息边界且 restStart 会播"时跳过自身,让休息语音优先。奇数组数一半点在中段不会撞车,不动;短组配置 rest 不播也保持原 halfway 行为,无回归。改 `pages/timer/timer.js` 的 `_circuitCue`。
|
||||||
|
- 顺带:last30/last10 在更长偶数组数(如 4 组×30s 的 set3→rest)也会撞同一问题,一并按同规则让位,行为一致。
|
||||||
|
|||||||
+13
-3
@@ -354,21 +354,31 @@ Page({
|
|||||||
const s = storage.getSettings()
|
const s = storage.getSettings()
|
||||||
const voiceOn = s.voiceGuide !== false
|
const voiceOn = s.voiceGuide !== false
|
||||||
|
|
||||||
|
// Even set counts land a progress threshold (halfway / last30 / last10)
|
||||||
|
// exactly on a work→rest transition. If that prompt speaks it grabs the
|
||||||
|
// mic for ~2.6s (see _playProgressVoice) and mutes the "休息一下" line
|
||||||
|
// fired on the same tick. Yield to rest whenever restStart will actually
|
||||||
|
// play (chatty + rest≥5); short-set configs keep the progress cue as
|
||||||
|
// before. Odd set counts never hit this because the halfway point sits
|
||||||
|
// mid-set, so their progress prompts are unaffected.
|
||||||
|
const atRestBoundary = t.phaseRemaining <= 0 && t.restPerSet > 0 && t.setIndex < t.sets
|
||||||
|
const restWillSpeak = this._circuitCfg.holdPerSet >= 10 && this._circuitCfg.restPerSet >= 5
|
||||||
|
|
||||||
// Same duration gates as _remind(), so short circuits (e.g. 3 sets × 5s)
|
// Same duration gates as _remind(), so short circuits (e.g. 3 sets × 5s)
|
||||||
// don't fire "最后30秒" on the very first tick. `<=` rather than `===`
|
// don't fire "最后30秒" on the very first tick. `<=` rather than `===`
|
||||||
// survives a skipped second when the app returns from background.
|
// survives a skipped second when the app returns from background.
|
||||||
if (total >= 10 && !this._halfwaySignaled && done >= Math.floor(total / 2)) {
|
if (total >= 10 && !this._halfwaySignaled && done >= Math.floor(total / 2)) {
|
||||||
this._halfwaySignaled = true
|
this._halfwaySignaled = true
|
||||||
if (voiceOn) this._playProgressVoice('halfway')
|
if (!(atRestBoundary && restWillSpeak) && voiceOn) this._playProgressVoice('halfway')
|
||||||
this._vibrateOnce(2, 150)
|
this._vibrateOnce(2, 150)
|
||||||
}
|
}
|
||||||
if (total > 60 && left <= 30 && !this._last30Signaled) {
|
if (total > 60 && left <= 30 && !this._last30Signaled) {
|
||||||
this._last30Signaled = true
|
this._last30Signaled = true
|
||||||
if (voiceOn) this._playProgressVoice('last30')
|
if (!(atRestBoundary && restWillSpeak) && voiceOn) this._playProgressVoice('last30')
|
||||||
}
|
}
|
||||||
if (total > 20 && left <= 10 && !this._last10Signaled) {
|
if (total > 20 && left <= 10 && !this._last10Signaled) {
|
||||||
this._last10Signaled = true
|
this._last10Signaled = true
|
||||||
if (voiceOn) this._playProgressVoice('last10')
|
if (!(atRestBoundary && restWillSpeak) && voiceOn) this._playProgressVoice('last10')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Countdown buzz over the last 5s of the FINAL set (the real finish line).
|
// Countdown buzz over the last 5s of the FINAL set (the real finish line).
|
||||||
|
|||||||
Reference in New Issue
Block a user