Skip to content

Commit b485a4f

Browse files
authored
Merge pull request #3 from BlockG-ws/copilot/fix-auto-enable-switch-audio-mode
fix(audio-only-mode): handle AbortError on no-refresh video switch; add auto-enable on blur
2 parents a11bb13 + 5db71d0 commit b485a4f

2 files changed

Lines changed: 74 additions & 4 deletions

File tree

registry/lib/components/video/audio-only-mode/AudioOnlyMode.vue

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Toast } from '@/core/toast'
1515
import { Options } from './index'
1616
1717
const console = useScopedConsole('听视频')
18+
const BLUR_AUTO_ENABLE_DELAY_MS = 30 * 1000
1819
1920
export default Vue.extend({
2021
components: {
@@ -26,6 +27,8 @@ export default Vue.extend({
2627
isAudioMode: false,
2728
disabled: false,
2829
settings,
30+
blurTimer: null as ReturnType<typeof setTimeout> | null,
31+
initialAutoEnableAttempted: false as boolean,
2932
}
3033
},
3134
computed: {
@@ -37,14 +40,19 @@ export default Vue.extend({
3740
},
3841
},
3942
async mounted() {
40-
videoChange(() => {
43+
videoChange(async () => {
4144
this.isAudioMode = false
42-
if (this.settings.options.autoEnable) {
45+
if (this.settings.options.autoEnable && !this.initialAutoEnableAttempted) {
46+
this.initialAutoEnableAttempted = true
47+
// Wait briefly for the player to settle after a no-refresh video change
48+
// before attempting to switch to audio mode, to avoid AbortError.
49+
await new Promise(r => setTimeout(r, 800))
4350
this.switchToAudioMode()
4451
}
4552
})
4653
47-
if (this.settings.options.autoEnable) {
54+
if (this.settings.options.autoEnable && !this.initialAutoEnableAttempted) {
55+
this.initialAutoEnableAttempted = true
4856
await this.switchToAudioMode()
4957
}
5058
@@ -53,8 +61,52 @@ export default Vue.extend({
5361
this.switchToAudioMode()
5462
}
5563
})
64+
65+
if (this.settings.options.autoEnableOnBlur) {
66+
this.setupBlurListener()
67+
}
68+
69+
addComponentListener('audioOnlyMode.autoEnableOnBlur', (value: boolean) => {
70+
if (value) {
71+
this.setupBlurListener()
72+
} else {
73+
this.teardownBlurListener()
74+
}
75+
})
76+
},
77+
beforeDestroy() {
78+
this.teardownBlurListener()
5679
},
5780
methods: {
81+
setupBlurListener() {
82+
// Remove first to prevent duplicate registrations if called multiple times.
83+
document.removeEventListener('visibilitychange', this.handleVisibilityChange)
84+
document.addEventListener('visibilitychange', this.handleVisibilityChange)
85+
},
86+
teardownBlurListener() {
87+
document.removeEventListener('visibilitychange', this.handleVisibilityChange)
88+
this.clearBlurTimer()
89+
},
90+
handleVisibilityChange() {
91+
if (document.hidden) {
92+
// Clear any existing timer before starting a new one to avoid orphaned timeouts.
93+
this.clearBlurTimer()
94+
this.blurTimer = setTimeout(() => {
95+
// Re-check visibility to avoid switching modes if the page is visible again.
96+
if (document.hidden && !this.isAudioMode) {
97+
this.switchToAudioMode()
98+
}
99+
}, BLUR_AUTO_ENABLE_DELAY_MS)
100+
} else {
101+
this.clearBlurTimer()
102+
}
103+
},
104+
clearBlurTimer() {
105+
if (this.blurTimer !== null) {
106+
clearTimeout(this.blurTimer)
107+
this.blurTimer = null
108+
}
109+
},
58110
async toggleAudioMode() {
59111
if (this.isAudioMode) {
60112
Toast.info('请刷新页面以退出音频模式', '听视频', 2000)
@@ -179,10 +231,24 @@ export default Vue.extend({
179231
180232
video.src = audioUrl
181233
video.load()
182-
await video.play().catch((err: Error) => {
234+
235+
let playAborted = false
236+
await video.play().catch((err: DOMException) => {
237+
if (err.name === 'AbortError') {
238+
// AbortError is expected when a no-refresh video navigation interrupts
239+
// the play() call before it can complete. This is not a real failure;
240+
// the next videoChange event will trigger another switch attempt.
241+
console.warn('播放被中止 (AbortError),可能由视频切换引起,将等待下次触发')
242+
playAborted = true
243+
return
244+
}
183245
throw new Error(`播放失败: ${err.message}`)
184246
})
185247
248+
if (playAborted) {
249+
return
250+
}
251+
186252
this.isAudioMode = true
187253
Toast.success('已切换到音频模式', '听视频', 2000)
188254
console.log('已切换到音频模式')

registry/lib/components/video/audio-only-mode/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export const options = defineOptionsMetadata({
1111
defaultValue: false,
1212
displayName: '自动启用',
1313
},
14+
autoEnableOnBlur: {
15+
defaultValue: false,
16+
displayName: '失去焦点后自动启用',
17+
},
1418
rememberProgress: {
1519
defaultValue: true,
1620
displayName: '记住播放进度',

0 commit comments

Comments
 (0)