fix: 修复在长时间暂停后无法播放的问题 (#1627)

* fix: 修复在长时间暂停后无法播放的问题

* 增加doc
master
memorydream 2 years ago committed by GitHub
parent b9cdade832
commit 6b690baef6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,6 +14,15 @@ import { decode as base642Buffer } from '@/utils/base64';
const PLAY_PAUSE_FADE_DURATION = 200;
/**
* @readonly
* @enum {string}
*/
const UNPLAYABLE_CONDITION = {
PLAY_NEXT_TRACK: 'playNextTrack',
PLAY_PREV_TRACK: 'playPrevTrack',
};
const electron =
process.env.IS_ELECTRON === true ? window.require('electron') : null;
const ipcRenderer =
@ -164,6 +173,9 @@ export default class {
get currentTrack() {
return this._currentTrack;
}
get currentTrackID() {
return this._currentTrack?.id ?? 0;
}
get playlistSource() {
return this._playlistSource;
}
@ -199,7 +211,7 @@ export default class {
if (this._enabled) {
// 恢复当前播放歌曲
this._replaceCurrentTrack(this._currentTrack.id, false).then(() => {
this._replaceCurrentTrack(this.currentTrackID, false).then(() => {
this._howler?.seek(localStorage.getItem('playerCurrentTrackTime') ?? 0);
}); // update audio source and init howler
this._initMediaSession();
@ -278,7 +290,7 @@ export default class {
// 返回 [trackID, index]
return [this.list[next], next];
}
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
async _shuffleTheList(firstTrackID = this.currentTrackID) {
let list = this._list.filter(tid => tid !== firstTrackID);
if (firstTrackID === 'first') list = this._list;
this._shuffledList = shuffle(list);
@ -321,6 +333,25 @@ export default class {
this._nextTrackCallback();
},
});
this._howler.on('loaderror', (_, errCode) => {
// https://developer.mozilla.org/en-US/docs/Web/API/MediaError/code
// code 3: MEDIA_ERR_DECODE
if (errCode === 3) {
this._playNextTrack(this._isPersonalFM);
} else {
const t = this.progress;
this._replaceCurrentTrackAudio(this.currentTrack, false, false).then(
replaced => {
// 如果 replaced 为 false代表当前的 track 已经不是这里想要替换的track
// 此时则不修改当前的歌曲进度
if (replaced) {
this._howler?.seek(t);
this.play();
}
}
);
}
});
if (autoplay) {
this.play();
if (this._currentTrack.name) {
@ -452,33 +483,61 @@ export default class {
_replaceCurrentTrack(
id,
autoplay = true,
ifUnplayableThen = 'playNextTrack'
ifUnplayableThen = UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK
) {
if (autoplay && this._currentTrack.name) {
this._scrobble(this.currentTrack, this._howler?.seek());
}
return getTrackDetail(id).then(data => {
let track = data.songs[0];
const track = data.songs[0];
this._currentTrack = track;
this._updateMediaSessionMetaData(track);
return this._getAudioSource(track).then(source => {
if (source) {
return this._replaceCurrentTrackAudio(
track,
autoplay,
true,
ifUnplayableThen
);
});
}
/**
* @returns 是否成功加载音频并使用加载完成的音频替换了howler实例
*/
_replaceCurrentTrackAudio(
track,
autoplay,
isCacheNextTrack,
ifUnplayableThen = UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK
) {
return this._getAudioSource(track).then(source => {
if (source) {
let replaced = false;
if (track.id === this.currentTrackID) {
this._playAudioSource(source, autoplay);
replaced = true;
}
if (isCacheNextTrack) {
this._cacheNextTrack();
return source;
} else {
store.dispatch('showToast', `无法播放 ${track.name}`);
if (ifUnplayableThen === 'playNextTrack') {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
} else {
}
return replaced;
} else {
store.dispatch('showToast', `无法播放 ${track.name}`);
switch (ifUnplayableThen) {
case UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK:
this._playNextTrack(this.isPersonalFM);
break;
case UNPLAYABLE_CONDITION.PLAY_PREV_TRACK:
this.playPrevTrack();
}
break;
default:
store.dispatch(
'showToast',
`undefined Unplayable condition: ${ifUnplayableThen}`
);
break;
}
});
return false;
}
});
}
_cacheNextTrack() {
@ -511,11 +570,7 @@ export default class {
this.playPrevTrack();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
this._playNextTrack(this.isPersonalFM);
});
navigator.mediaSession.setActionHandler('stop', () => {
this.pause();
@ -579,11 +634,9 @@ export default class {
_nextTrackCallback() {
this._scrobble(this._currentTrack, 0, true);
if (!this.isPersonalFM && this.repeatMode === 'one') {
this._replaceCurrentTrack(this._currentTrack.id);
} else if (this.isPersonalFM) {
this.playNextFMTrack();
this._replaceCurrentTrack(this.currentTrackID);
} else {
this.playNextTrack();
this._playNextTrack(this.isPersonalFM);
}
}
_loadPersonalFMNextTrack() {
@ -628,11 +681,14 @@ export default class {
}
ipcRenderer?.send('pauseDiscordPresence', track);
}
currentTrackID() {
const { list, current } = this._getListAndCurrent();
return list[current];
_playNextTrack(isPersonal) {
if (isPersonal) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
}
appendTrack(trackID) {
this.list.append(trackID);
}
@ -697,7 +753,11 @@ export default class {
const [trackID, index] = this._getPrevTrack();
if (trackID === undefined) return false;
this.current = index;
this._replaceCurrentTrack(trackID, true, 'playPrevTrack');
this._replaceCurrentTrack(
trackID,
true,
UNPLAYABLE_CONDITION.PLAY_PREV_TRACK
);
return true;
}
saveSelfToLocalStorage() {
@ -838,20 +898,14 @@ export default class {
addTrackToPlayNext(trackID, playNow = false) {
this._playNextList.push(trackID);
if (playNow) {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
this.playNextTrack();
}
}
playPersonalFM() {
this._isPersonalFM = true;
if (!this._enabled) this._enabled = true;
if (this._currentTrack.id !== this._personalFMTrack.id) {
this._replaceCurrentTrack(this._personalFMTrack.id).then(() =>
this.playOrPause()
);
if (this.currentTrackID !== this._personalFMTrack.id) {
this._replaceCurrentTrack(this._personalFMTrack.id, true);
} else {
this.playOrPause();
}

Loading…
Cancel
Save