mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2025-02-17 00:55:30 +08:00
parent
b9cdade832
commit
6b690baef6
|
@ -14,6 +14,15 @@ import { decode as base642Buffer } from '@/utils/base64';
|
||||||
|
|
||||||
const PLAY_PAUSE_FADE_DURATION = 200;
|
const PLAY_PAUSE_FADE_DURATION = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @readonly
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
const UNPLAYABLE_CONDITION = {
|
||||||
|
PLAY_NEXT_TRACK: 'playNextTrack',
|
||||||
|
PLAY_PREV_TRACK: 'playPrevTrack',
|
||||||
|
};
|
||||||
|
|
||||||
const electron =
|
const electron =
|
||||||
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||||
const ipcRenderer =
|
const ipcRenderer =
|
||||||
|
@ -164,6 +173,9 @@ export default class {
|
||||||
get currentTrack() {
|
get currentTrack() {
|
||||||
return this._currentTrack;
|
return this._currentTrack;
|
||||||
}
|
}
|
||||||
|
get currentTrackID() {
|
||||||
|
return this._currentTrack?.id ?? 0;
|
||||||
|
}
|
||||||
get playlistSource() {
|
get playlistSource() {
|
||||||
return this._playlistSource;
|
return this._playlistSource;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +211,7 @@ export default class {
|
||||||
|
|
||||||
if (this._enabled) {
|
if (this._enabled) {
|
||||||
// 恢复当前播放歌曲
|
// 恢复当前播放歌曲
|
||||||
this._replaceCurrentTrack(this._currentTrack.id, false).then(() => {
|
this._replaceCurrentTrack(this.currentTrackID, false).then(() => {
|
||||||
this._howler?.seek(localStorage.getItem('playerCurrentTrackTime') ?? 0);
|
this._howler?.seek(localStorage.getItem('playerCurrentTrackTime') ?? 0);
|
||||||
}); // update audio source and init howler
|
}); // update audio source and init howler
|
||||||
this._initMediaSession();
|
this._initMediaSession();
|
||||||
|
@ -278,7 +290,7 @@ export default class {
|
||||||
// 返回 [trackID, index]
|
// 返回 [trackID, index]
|
||||||
return [this.list[next], next];
|
return [this.list[next], next];
|
||||||
}
|
}
|
||||||
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
|
async _shuffleTheList(firstTrackID = this.currentTrackID) {
|
||||||
let list = this._list.filter(tid => tid !== firstTrackID);
|
let list = this._list.filter(tid => tid !== firstTrackID);
|
||||||
if (firstTrackID === 'first') list = this._list;
|
if (firstTrackID === 'first') list = this._list;
|
||||||
this._shuffledList = shuffle(list);
|
this._shuffledList = shuffle(list);
|
||||||
|
@ -321,6 +333,25 @@ export default class {
|
||||||
this._nextTrackCallback();
|
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) {
|
if (autoplay) {
|
||||||
this.play();
|
this.play();
|
||||||
if (this._currentTrack.name) {
|
if (this._currentTrack.name) {
|
||||||
|
@ -452,33 +483,61 @@ export default class {
|
||||||
_replaceCurrentTrack(
|
_replaceCurrentTrack(
|
||||||
id,
|
id,
|
||||||
autoplay = true,
|
autoplay = true,
|
||||||
ifUnplayableThen = 'playNextTrack'
|
ifUnplayableThen = UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK
|
||||||
) {
|
) {
|
||||||
if (autoplay && this._currentTrack.name) {
|
if (autoplay && this._currentTrack.name) {
|
||||||
this._scrobble(this.currentTrack, this._howler?.seek());
|
this._scrobble(this.currentTrack, this._howler?.seek());
|
||||||
}
|
}
|
||||||
return getTrackDetail(id).then(data => {
|
return getTrackDetail(id).then(data => {
|
||||||
let track = data.songs[0];
|
const track = data.songs[0];
|
||||||
this._currentTrack = track;
|
this._currentTrack = track;
|
||||||
this._updateMediaSessionMetaData(track);
|
this._updateMediaSessionMetaData(track);
|
||||||
return this._getAudioSource(track).then(source => {
|
return this._replaceCurrentTrackAudio(
|
||||||
if (source) {
|
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);
|
this._playAudioSource(source, autoplay);
|
||||||
this._cacheNextTrack();
|
replaced = true;
|
||||||
return source;
|
|
||||||
} else {
|
|
||||||
store.dispatch('showToast', `无法播放 ${track.name}`);
|
|
||||||
if (ifUnplayableThen === 'playNextTrack') {
|
|
||||||
if (this.isPersonalFM) {
|
|
||||||
this.playNextFMTrack();
|
|
||||||
} else {
|
|
||||||
this.playNextTrack();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.playPrevTrack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
if (isCacheNextTrack) {
|
||||||
|
this._cacheNextTrack();
|
||||||
|
}
|
||||||
|
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() {
|
_cacheNextTrack() {
|
||||||
|
@ -511,11 +570,7 @@ export default class {
|
||||||
this.playPrevTrack();
|
this.playPrevTrack();
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||||
if (this.isPersonalFM) {
|
this._playNextTrack(this.isPersonalFM);
|
||||||
this.playNextFMTrack();
|
|
||||||
} else {
|
|
||||||
this.playNextTrack();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
navigator.mediaSession.setActionHandler('stop', () => {
|
navigator.mediaSession.setActionHandler('stop', () => {
|
||||||
this.pause();
|
this.pause();
|
||||||
|
@ -579,11 +634,9 @@ export default class {
|
||||||
_nextTrackCallback() {
|
_nextTrackCallback() {
|
||||||
this._scrobble(this._currentTrack, 0, true);
|
this._scrobble(this._currentTrack, 0, true);
|
||||||
if (!this.isPersonalFM && this.repeatMode === 'one') {
|
if (!this.isPersonalFM && this.repeatMode === 'one') {
|
||||||
this._replaceCurrentTrack(this._currentTrack.id);
|
this._replaceCurrentTrack(this.currentTrackID);
|
||||||
} else if (this.isPersonalFM) {
|
|
||||||
this.playNextFMTrack();
|
|
||||||
} else {
|
} else {
|
||||||
this.playNextTrack();
|
this._playNextTrack(this.isPersonalFM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_loadPersonalFMNextTrack() {
|
_loadPersonalFMNextTrack() {
|
||||||
|
@ -628,11 +681,14 @@ export default class {
|
||||||
}
|
}
|
||||||
ipcRenderer?.send('pauseDiscordPresence', track);
|
ipcRenderer?.send('pauseDiscordPresence', track);
|
||||||
}
|
}
|
||||||
|
_playNextTrack(isPersonal) {
|
||||||
currentTrackID() {
|
if (isPersonal) {
|
||||||
const { list, current } = this._getListAndCurrent();
|
this.playNextFMTrack();
|
||||||
return list[current];
|
} else {
|
||||||
|
this.playNextTrack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appendTrack(trackID) {
|
appendTrack(trackID) {
|
||||||
this.list.append(trackID);
|
this.list.append(trackID);
|
||||||
}
|
}
|
||||||
|
@ -697,7 +753,11 @@ export default class {
|
||||||
const [trackID, index] = this._getPrevTrack();
|
const [trackID, index] = this._getPrevTrack();
|
||||||
if (trackID === undefined) return false;
|
if (trackID === undefined) return false;
|
||||||
this.current = index;
|
this.current = index;
|
||||||
this._replaceCurrentTrack(trackID, true, 'playPrevTrack');
|
this._replaceCurrentTrack(
|
||||||
|
trackID,
|
||||||
|
true,
|
||||||
|
UNPLAYABLE_CONDITION.PLAY_PREV_TRACK
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
saveSelfToLocalStorage() {
|
saveSelfToLocalStorage() {
|
||||||
|
@ -838,20 +898,14 @@ export default class {
|
||||||
addTrackToPlayNext(trackID, playNow = false) {
|
addTrackToPlayNext(trackID, playNow = false) {
|
||||||
this._playNextList.push(trackID);
|
this._playNextList.push(trackID);
|
||||||
if (playNow) {
|
if (playNow) {
|
||||||
if (this.isPersonalFM) {
|
this.playNextTrack();
|
||||||
this.playNextFMTrack();
|
|
||||||
} else {
|
|
||||||
this.playNextTrack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playPersonalFM() {
|
playPersonalFM() {
|
||||||
this._isPersonalFM = true;
|
this._isPersonalFM = true;
|
||||||
if (!this._enabled) this._enabled = true;
|
if (!this._enabled) this._enabled = true;
|
||||||
if (this._currentTrack.id !== this._personalFMTrack.id) {
|
if (this.currentTrackID !== this._personalFMTrack.id) {
|
||||||
this._replaceCurrentTrack(this._personalFMTrack.id).then(() =>
|
this._replaceCurrentTrack(this._personalFMTrack.id, true);
|
||||||
this.playOrPause()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
this.playOrPause();
|
this.playOrPause();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user