mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 09:41:49 +08:00
parent
b9cdade832
commit
6b690baef6
|
@ -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,34 +483,62 @@ 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._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;
|
||||
}
|
||||
return replaced;
|
||||
} else {
|
||||
store.dispatch('showToast', `无法播放 ${track.name}`);
|
||||
if (ifUnplayableThen === 'playNextTrack') {
|
||||
if (this.isPersonalFM) {
|
||||
this.playNextFMTrack();
|
||||
} else {
|
||||
this.playNextTrack();
|
||||
}
|
||||
} else {
|
||||
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() {
|
||||
let nextTrackID = this._isPersonalFM
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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…
Reference in New Issue
Block a user