mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 09:02:56 +08:00
refactor: player
This commit is contained in:
parent
0482e6a1ed
commit
f6c36fbcac
|
@ -47,6 +47,7 @@
|
|||
"howler": "^2.2.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"localforage": "^1.9.0",
|
||||
"lodash": "^4.17.20",
|
||||
"nprogress": "^0.2.0",
|
||||
"pac-proxy-agent": "^4.1.0",
|
||||
"plyr": "^3.6.2",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</main>
|
||||
<transition name="slide-up">
|
||||
<Player
|
||||
v-if="this.$store.state.player.enable"
|
||||
v-if="this.$store.state.player.enabled"
|
||||
ref="player"
|
||||
v-show="
|
||||
['mv', 'loginUsername', 'login', 'loginAccount'].includes(
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { playAlbumByID, playPlaylistByID, playArtistByID } from "@/utils/play";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: { type: Number, required: true },
|
||||
|
@ -74,12 +72,13 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
play() {
|
||||
const player = this.$store.state.player;
|
||||
const playActions = {
|
||||
album: playAlbumByID,
|
||||
playlist: playPlaylistByID,
|
||||
artist: playArtistByID,
|
||||
album: player.playAlbumByID,
|
||||
playlist: player.playPlaylistByID,
|
||||
artist: player.playArtistByID,
|
||||
};
|
||||
playActions[this.type](this.id);
|
||||
playActions[this.type].bind(player)(this.id);
|
||||
},
|
||||
goTo() {
|
||||
this.$router.push({ name: this.type, params: { id: this.id } });
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 账号登录才会显示 like 图标 -->
|
||||
<div class="like-button">
|
||||
<button-icon
|
||||
@click.native="likeCurrentSong"
|
||||
|
@ -60,9 +59,9 @@
|
|||
<button-icon
|
||||
class="play"
|
||||
@click.native="play"
|
||||
:title="$t(playing ? 'player.pause' : 'player.play')"
|
||||
:title="$t(player.playing ? 'player.pause' : 'player.play')"
|
||||
>
|
||||
<svg-icon :iconClass="playing ? 'pause' : 'play'"
|
||||
<svg-icon :iconClass="player.playing ? 'pause' : 'play'"
|
||||
/></button-icon>
|
||||
<button-icon @click.native="next" :title="$t('player.next')"
|
||||
><svg-icon icon-class="next"
|
||||
|
@ -77,15 +76,18 @@
|
|||
/></button-icon>
|
||||
<button-icon
|
||||
:title="
|
||||
player.repeat === 'one'
|
||||
player.repeatMode === 'one'
|
||||
? $t('player.repeatTrack')
|
||||
: $t('player.repeat')
|
||||
"
|
||||
@click.native="repeat"
|
||||
:class="{ active: player.repeat !== 'off' }"
|
||||
:class="{ active: player.repeatMode !== 'off' }"
|
||||
>
|
||||
<svg-icon icon-class="repeat" v-show="player.repeat !== 'one'" />
|
||||
<svg-icon icon-class="repeat-1" v-show="player.repeat === 'one'" />
|
||||
<svg-icon icon-class="repeat" v-show="player.repeatMode !== 'one'" />
|
||||
<svg-icon
|
||||
icon-class="repeat-1"
|
||||
v-show="player.repeatMode === 'one'"
|
||||
/>
|
||||
</button-icon>
|
||||
<button-icon
|
||||
@click.native="shuffle"
|
||||
|
@ -94,7 +96,7 @@
|
|||
><svg-icon icon-class="shuffle"
|
||||
/></button-icon>
|
||||
<div class="volume-control">
|
||||
<button-icon :title="$t('player.mute')" @click.native="mute">
|
||||
<button-icon :title="$t('player.mute')" @click.native="player.mute">
|
||||
<svg-icon icon-class="volume" v-show="volume > 0.5" />
|
||||
<svg-icon icon-class="volume-mute" v-show="volume === 0" />
|
||||
<svg-icon
|
||||
|
@ -121,13 +123,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { updateMediaSessionMetaData } from "@/utils/mediaSession";
|
||||
import { mapState, mapMutations, mapActions } from "vuex";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
import { userLikedSongsIDs } from "@/api/user";
|
||||
import { likeATrack } from "@/api/track";
|
||||
import "@/assets/css/slider.css";
|
||||
import { Howler } from "howler";
|
||||
|
||||
import ButtonIcon from "@/components/ButtonIcon.vue";
|
||||
import VueSlider from "vue-slider-component";
|
||||
|
@ -147,10 +147,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
setInterval(() => {
|
||||
// fix 歌曲播放完还设置进度的问题,及 _id 不存在的问题
|
||||
if (this.howler && this.howler._sounds?.[0]?._id) {
|
||||
this.progress = ~~this.howler.seek();
|
||||
}
|
||||
this.progress = ~~this.player.seek();
|
||||
}, 1000);
|
||||
if (isAccountLoggedIn()) {
|
||||
userLikedSongsIDs(this.data.user.userId).then((data) => {
|
||||
|
@ -159,7 +156,7 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(["player", "howler", "settings", "liked", "data"]),
|
||||
...mapState(["player", "settings", "liked", "data"]),
|
||||
currentTrack() {
|
||||
return this.player.currentTrack;
|
||||
},
|
||||
|
@ -168,92 +165,46 @@ export default {
|
|||
return this.player.volume;
|
||||
},
|
||||
set(value) {
|
||||
this.updatePlayerState({ key: "volume", value });
|
||||
Howler.volume(value);
|
||||
this.player.volume = value;
|
||||
},
|
||||
},
|
||||
playing() {
|
||||
if (this.howler) {
|
||||
if (this.howler.state() === "loading") {
|
||||
this.updatePlayerState({ key: "playing", value: true });
|
||||
return true;
|
||||
}
|
||||
const status = this.howler.playing();
|
||||
this.updatePlayerState({ key: "playing", value: status });
|
||||
return status;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return this.player.playing;
|
||||
},
|
||||
progressMax() {
|
||||
let max = ~~(this.currentTrack.dt / 1000);
|
||||
let max = ~~(this.player.currentTrack.dt / 1000);
|
||||
return max > 1 ? max - 1 : max;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
"turnOnShuffleMode",
|
||||
"turnOffShuffleMode",
|
||||
"updatePlayerState",
|
||||
"updateRepeatStatus",
|
||||
"updateLikedSongs",
|
||||
]),
|
||||
...mapActions([
|
||||
"nextTrack",
|
||||
"previousTrack",
|
||||
"playTrackOnListByID",
|
||||
"addNextTrackEvent",
|
||||
"showToast",
|
||||
]),
|
||||
...mapMutations(["updateLikedSongs"]),
|
||||
...mapActions(["showToast"]),
|
||||
play() {
|
||||
if (this.playing) {
|
||||
this.howler.pause();
|
||||
} else {
|
||||
if (this.howler.state() === "unloaded") {
|
||||
this.playTrackOnListByID(this.currentTrack.id);
|
||||
}
|
||||
this.howler.play();
|
||||
if (this.howler._onend.length === 0) {
|
||||
this.addNextTrackEvent();
|
||||
updateMediaSessionMetaData(this.currentTrack);
|
||||
}
|
||||
}
|
||||
this.player.playing ? this.player.pause() : this.player.play();
|
||||
},
|
||||
next() {
|
||||
this.progress = 0;
|
||||
this.nextTrack(true);
|
||||
if (this.player.playNextTrack()) this.progress = 0;
|
||||
},
|
||||
previous() {
|
||||
this.progress = 0;
|
||||
this.previousTrack();
|
||||
if (this.player.playPrevTrack()) this.progress = 0;
|
||||
},
|
||||
shuffle() {
|
||||
if (this.player.shuffle === true) {
|
||||
this.turnOffShuffleMode();
|
||||
} else {
|
||||
this.turnOnShuffleMode();
|
||||
}
|
||||
this.player.shuffle = !this.player.shuffle;
|
||||
console.log(this.player);
|
||||
},
|
||||
repeat() {
|
||||
if (this.player.repeat === "on") {
|
||||
this.updateRepeatStatus("one");
|
||||
} else if (this.player.repeat === "one") {
|
||||
this.updateRepeatStatus("off");
|
||||
console.log(this.player.repeatMode);
|
||||
if (this.player.repeatMode === "on") {
|
||||
this.player.repeatMode = "one";
|
||||
} else if (this.player.repeatMode === "one") {
|
||||
this.player.repeatMode = "off";
|
||||
} else {
|
||||
this.updateRepeatStatus("on");
|
||||
}
|
||||
},
|
||||
mute() {
|
||||
if (this.volume === 0) {
|
||||
this.volume = this.oldVolume;
|
||||
} else {
|
||||
this.oldVolume = this.volume;
|
||||
this.volume = 0;
|
||||
this.player.repeatMode = "on";
|
||||
}
|
||||
},
|
||||
setSeek() {
|
||||
this.progress = this.$refs.progress.getValue();
|
||||
this.howler.seek(this.$refs.progress.getValue());
|
||||
this.player.seek(this.$refs.progress.getValue());
|
||||
},
|
||||
goToNextTracksPage() {
|
||||
this.$route.name === "next"
|
||||
|
@ -285,15 +236,20 @@ export default {
|
|||
});
|
||||
},
|
||||
goToList() {
|
||||
if (this.player.listInfo.id === this.data.likedSongPlaylistID)
|
||||
if (this.player.playlistSource.id === this.data.likedSongPlaylistID)
|
||||
this.$router.push({ path: "/library/liked-songs" });
|
||||
else
|
||||
this.$router.push({
|
||||
path: "/" + this.player.listInfo.type + "/" + this.player.listInfo.id,
|
||||
path:
|
||||
"/" +
|
||||
this.player.playlistSource.type +
|
||||
"/" +
|
||||
this.player.playlistSource.id,
|
||||
});
|
||||
},
|
||||
goToAlbum() {
|
||||
this.$router.push({ path: "/album/" + this.currentTrack.al.id });
|
||||
if (this.player.currentTrack.al.id === 0) return;
|
||||
this.$router.push({ path: "/album/" + this.player.currentTrack.al.id });
|
||||
},
|
||||
goToArtist(id) {
|
||||
this.$router.push({ path: "/artist/" + id });
|
||||
|
|
|
@ -41,12 +41,6 @@
|
|||
<script>
|
||||
import { mapActions, mapMutations, mapState } from "vuex";
|
||||
import { likeATrack } from "@/api/track";
|
||||
import {
|
||||
playPlaylistByID,
|
||||
playAlbumByID,
|
||||
playAList,
|
||||
appendTrackToPlayerList,
|
||||
} from "@/utils/play";
|
||||
import { addOrRemoveTrackFromPlaylist } from "@/api/playlist";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
|
@ -140,24 +134,32 @@ export default {
|
|||
} else if (this.dbclickTrackFunc === "playTrackOnListByID") {
|
||||
this.playTrackOnListByID(trackID);
|
||||
} else if (this.dbclickTrackFunc === "playPlaylistByID") {
|
||||
playPlaylistByID(this.id, trackID);
|
||||
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
||||
}
|
||||
},
|
||||
playThisListDefault(trackID) {
|
||||
if (this.type === "playlist") {
|
||||
playPlaylistByID(this.id, trackID);
|
||||
this.$store.state.player.playPlaylistByID(this.id, trackID);
|
||||
} else if (this.type === "album") {
|
||||
playAlbumByID(this.id, trackID);
|
||||
this.$store.state.player.playAlbumByID(this.id, trackID);
|
||||
} else if (this.type === "tracklist") {
|
||||
let trackIDs = this.tracks.map((t) => t.id);
|
||||
playAList(trackIDs, this.tracks[0].ar[0].id, "artist", trackID);
|
||||
this.$store.state.player.replacePlaylist(
|
||||
trackIDs,
|
||||
this.id,
|
||||
"artist",
|
||||
trackID
|
||||
);
|
||||
}
|
||||
},
|
||||
play() {
|
||||
appendTrackToPlayerList(this.clickTrack.id, true);
|
||||
this.$store.state.player.addTrackToPlayNext(
|
||||
this.rightClickedTrack.id,
|
||||
true
|
||||
);
|
||||
},
|
||||
playNext() {
|
||||
appendTrackToPlayerList(this.clickTrack.id);
|
||||
this.$store.state.player.addTrackToPlayNext(this.rightClickedTrack.id);
|
||||
},
|
||||
like() {
|
||||
this.likeASong(this.rightClickedTrack.id);
|
||||
|
|
|
@ -62,9 +62,9 @@ export function createTouchBar(window) {
|
|||
},
|
||||
});
|
||||
|
||||
ipcMain.on("vuex-state", (e, { player, liked }) => {
|
||||
playButton.label = player.playing === true ? "" : "";
|
||||
likeButton.label = liked.songs.includes(player.currentTrack.id) ? "" : "";
|
||||
ipcMain.on("player", (e, { playing, likedCurrentTrack }) => {
|
||||
playButton.label = playing === true ? "" : "";
|
||||
likeButton.label = likedCurrentTrack ? "" : "";
|
||||
});
|
||||
|
||||
const touchBar = new TouchBar({
|
||||
|
|
|
@ -6,7 +6,6 @@ import store from "./store";
|
|||
import i18n from "@/locale";
|
||||
import "@/assets/icons";
|
||||
import "@/utils/filters";
|
||||
import { initMediaSession } from "@/utils/mediaSession";
|
||||
import "./registerServiceWorker";
|
||||
import { dailyTask } from "@/utils/common";
|
||||
|
||||
|
@ -21,8 +20,6 @@ Vue.use(VueAnalytics, {
|
|||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
initMediaSession();
|
||||
|
||||
if (process.env.VUE_APP_ENABLE_SENTRY === "true") {
|
||||
Sentry.init({
|
||||
dsn:
|
||||
|
|
|
@ -1,185 +1,4 @@
|
|||
import { updateMediaSessionMetaData } from "@/utils/mediaSession";
|
||||
import { getTrackDetail, scrobble, getMP3 as getMP3Api } from "@/api/track";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
import { updateHttps } from "@/utils/common";
|
||||
import localforage from "localforage";
|
||||
import store from "@/store";
|
||||
import { cacheTrack } from "@/utils/db";
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require("electron") : null;
|
||||
const ipcRenderer =
|
||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||
|
||||
export default {
|
||||
switchTrack(
|
||||
{ state, dispatch, commit },
|
||||
{ id, sort = 0, autoplay = true, ifUnplayableThen = "nextTrack" }
|
||||
) {
|
||||
getTrackDetail(id).then((data) => {
|
||||
let track = data.songs[0];
|
||||
track.sort = sort;
|
||||
|
||||
// 获取当前的播放时间。初始化为 loading 状态时返回 howler 的实例而不是浮点数时间,比如 1.332
|
||||
let time = state.howler ? state.howler.seek() : 0;
|
||||
let currentTime = 0;
|
||||
if (time === 0) {
|
||||
// state.howler._duration 可以获得当前实例的播放时长
|
||||
currentTime = 180;
|
||||
}
|
||||
if (time.toString() === "[object Object]") {
|
||||
currentTime = 0;
|
||||
}
|
||||
if (time > 0) {
|
||||
currentTime = time;
|
||||
}
|
||||
scrobble({
|
||||
id: state.player.currentTrack.id,
|
||||
sourceid: state.player.listInfo.id,
|
||||
time: currentTime,
|
||||
});
|
||||
|
||||
commit("updateCurrentTrack", track);
|
||||
updateMediaSessionMetaData(track);
|
||||
document.title = `${track.name} · ${track.ar[0].name} - YesPlayMusic`;
|
||||
|
||||
let unblockSongUrl = null;
|
||||
if (track.playable === false) {
|
||||
let res = undefined;
|
||||
if (process.env.IS_ELECTRON === true) {
|
||||
res = ipcRenderer.sendSync("unblock-music", track);
|
||||
}
|
||||
if (res?.url) {
|
||||
unblockSongUrl = res.url;
|
||||
} else {
|
||||
dispatch(ifUnplayableThen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function commitMP3(mp3) {
|
||||
commit("replaceMP3", { mp3, autoplay });
|
||||
state.howler.once("end", () => {
|
||||
dispatch("nextTrack");
|
||||
});
|
||||
}
|
||||
|
||||
function getMP3(id) {
|
||||
return getMP3Api(id).then((data) => {
|
||||
// 未知情况下会没有返回数据导致报错,增加防范逻辑
|
||||
if (data.data[0]) {
|
||||
const url = updateHttps(data.data[0].url);
|
||||
commitMP3(url);
|
||||
return url;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isAccountLoggedIn()) {
|
||||
if (store.state.settings.automaticallyCacheSongs === true) {
|
||||
let tracks = localforage.createInstance({
|
||||
name: "tracks",
|
||||
});
|
||||
tracks
|
||||
.getItem(`${track.id}`)
|
||||
.then((t) => {
|
||||
if (t !== null) {
|
||||
const blob = new Blob([t.mp3]);
|
||||
commitMP3(URL.createObjectURL(blob));
|
||||
} else {
|
||||
if (unblockSongUrl) {
|
||||
commitMP3(unblockSongUrl);
|
||||
cacheTrack(`${track.id}`, unblockSongUrl);
|
||||
} else {
|
||||
getMP3(track.id).then((url) => {
|
||||
cacheTrack(`${track.id}`, url);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.messaeg);
|
||||
if (unblockSongUrl) {
|
||||
commitMP3(unblockSongUrl);
|
||||
} else {
|
||||
getMP3(track.id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (unblockSongUrl) {
|
||||
commitMP3(unblockSongUrl);
|
||||
} else {
|
||||
getMP3(track.id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
commitMP3(
|
||||
unblockSongUrl ||
|
||||
`https://music.163.com/song/media/outer/url?id=${track.id}`
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
playFirstTrackOnList({ state, dispatch }) {
|
||||
dispatch(
|
||||
"switchTrack",
|
||||
state.player.list.find((t) => t.sort === 0)
|
||||
);
|
||||
},
|
||||
playTrackOnListByID({ state, commit, dispatch }, trackID) {
|
||||
let track = state.player.list.find((t) => t.id === trackID);
|
||||
dispatch("switchTrack", track);
|
||||
if (state.player.shuffle) {
|
||||
// 当随机模式开启时,双击列表的一首歌进行播放,此时要把这首歌的sort调到第一(0),这样用户就能随机播放完整的歌单
|
||||
let otherTrack = state.player.list.find((t) => t.sort === 0);
|
||||
commit("switchSortBetweenTwoTracks", {
|
||||
trackID1: track.id,
|
||||
trackID2: otherTrack.id,
|
||||
});
|
||||
}
|
||||
},
|
||||
nextTrack({ state, dispatch }, realNext = false) {
|
||||
let nextTrack = state.player.list.find(
|
||||
(track) => track.sort === state.player.currentTrack.sort + 1
|
||||
);
|
||||
|
||||
if (state.player.repeat === "one" && realNext === false) {
|
||||
nextTrack = state.player.currentTrack;
|
||||
}
|
||||
|
||||
if (nextTrack === undefined) {
|
||||
if (state.player.repeat !== "off") {
|
||||
nextTrack = state.player.list.find((t) => t.sort === 0);
|
||||
} else {
|
||||
document.title = "YesPlayMusic";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch("switchTrack", nextTrack);
|
||||
},
|
||||
previousTrack({ state, dispatch }) {
|
||||
let previousTrack = state.player.list.find(
|
||||
(track) => track.sort === state.player.currentTrack.sort - 1
|
||||
);
|
||||
if (previousTrack == undefined) {
|
||||
if (state.player.repeat !== "off") {
|
||||
previousTrack = state.player.list.reduce((x, y) => (x > y ? x : y));
|
||||
} else {
|
||||
previousTrack = state.player.list.find((t) => t.sort === 0);
|
||||
}
|
||||
}
|
||||
dispatch("switchTrack", {
|
||||
id: previousTrack.id,
|
||||
sort: previousTrack.sort,
|
||||
ifUnplayableThen: "previousTrack",
|
||||
});
|
||||
},
|
||||
addNextTrackEvent({ state, dispatch }) {
|
||||
state.howler.once("end", () => {
|
||||
dispatch("nextTrack");
|
||||
});
|
||||
},
|
||||
showToast({ state, commit }, text) {
|
||||
if (state.toast.timer !== null) {
|
||||
clearTimeout(state.toast.timer);
|
||||
|
|
|
@ -3,23 +3,13 @@ import Vuex from "vuex";
|
|||
import state from "./state";
|
||||
import mutations from "./mutations";
|
||||
import actions from "./actions";
|
||||
import initLocalStorage from "./initLocalStorage";
|
||||
import { Howler } from "howler";
|
||||
import { changeAppearance } from "@/utils/common";
|
||||
import updateApp from "@/utils/updateApp";
|
||||
import pkg from "../../package.json";
|
||||
import Player from "@/utils/Player";
|
||||
// vuex 自定义插件
|
||||
import { getBroadcastPlugin } from "./plugins/broadcast";
|
||||
import saveToLocalStorage from "./plugins/localStorage";
|
||||
|
||||
if (localStorage.getItem("appVersion") === null) {
|
||||
localStorage.setItem("player", JSON.stringify(initLocalStorage.player));
|
||||
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
||||
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
||||
localStorage.setItem("appVersion", pkg.version);
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
updateApp();
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
@ -39,19 +29,6 @@ const options = {
|
|||
|
||||
const store = new Vuex.Store(options);
|
||||
|
||||
Howler.volume(store.state.player.volume);
|
||||
// 防止软件第一次打开资源加载2次
|
||||
Howler.autoUnlock = false;
|
||||
|
||||
const currentTrack = store.state?.player?.currentTrack;
|
||||
if (currentTrack?.id) {
|
||||
store.dispatch("switchTrack", {
|
||||
id: currentTrack.id,
|
||||
sort: currentTrack.sort,
|
||||
autoplay: false,
|
||||
});
|
||||
}
|
||||
|
||||
if ([undefined, null].includes(store.state.settings.lang)) {
|
||||
let lang = "en";
|
||||
if (navigator.language.slice(0, 2) === "zh") lang = "zh-CN";
|
||||
|
@ -69,4 +46,17 @@ window
|
|||
}
|
||||
});
|
||||
|
||||
let player = new Player();
|
||||
player = new Proxy(player, {
|
||||
set(target, prop, val) {
|
||||
// console.log({ prop, val });
|
||||
target[prop] = val;
|
||||
if (prop === "_howler") return true;
|
||||
target.saveSelfToLocalStorage();
|
||||
target.sendSelfToIpcMain();
|
||||
return true;
|
||||
},
|
||||
});
|
||||
store.state.player = player;
|
||||
|
||||
export default store;
|
||||
|
|
|
@ -1,21 +1,7 @@
|
|||
import { playlistCategories } from "@/utils/staticData";
|
||||
|
||||
let localStorage = {
|
||||
player: {
|
||||
enable: false,
|
||||
show: true,
|
||||
playing: false,
|
||||
shuffle: false,
|
||||
volume: 1,
|
||||
repeat: "off", // on | off | one
|
||||
currentTrack: {},
|
||||
notShuffledList: [],
|
||||
list: [],
|
||||
listInfo: {
|
||||
type: "",
|
||||
id: "",
|
||||
},
|
||||
},
|
||||
player: {},
|
||||
settings: {
|
||||
playlistCategories,
|
||||
lang: null,
|
||||
|
|
|
@ -1,100 +1,7 @@
|
|||
import { Howl, Howler } from "howler";
|
||||
import { shuffleAList } from "@/utils/common";
|
||||
|
||||
export default {
|
||||
updatePlayerState(state, { key, value }) {
|
||||
state.player[key] = value;
|
||||
},
|
||||
updateCurrentTrack(state, track) {
|
||||
state.player.currentTrack = track;
|
||||
},
|
||||
replaceMP3(state, { mp3, autoplay }) {
|
||||
if (state.howler) {
|
||||
Howler.unload();
|
||||
}
|
||||
state.howler = new Howl({
|
||||
src: [mp3],
|
||||
autoplay,
|
||||
html5: true,
|
||||
format: ["mp3", "flac"],
|
||||
});
|
||||
},
|
||||
updatePlayerList(state, list) {
|
||||
state.player.list = list;
|
||||
if (state.player.enable !== true) state.player.enable = true;
|
||||
},
|
||||
updateListInfo(state, info) {
|
||||
state.player.listInfo = info;
|
||||
},
|
||||
updateRepeatStatus(state, status) {
|
||||
state.player.repeat = status;
|
||||
},
|
||||
appendTrackToPlayerList(state, { track, playNext = false }) {
|
||||
let existTrack = state.player.list.find((t) => t.id === track.id);
|
||||
if (
|
||||
(existTrack === null || existTrack === undefined) &&
|
||||
playNext === false
|
||||
) {
|
||||
state.player.list.push(track);
|
||||
return;
|
||||
}
|
||||
|
||||
// 把track加入到正在播放歌曲的下一首位置
|
||||
state.player.list = state.player.list.map((t) => {
|
||||
if (t.sort > state.player.currentTrack.sort) {
|
||||
t.sort = t.sort + 1;
|
||||
}
|
||||
return t;
|
||||
});
|
||||
track.sort = state.player.currentTrack.sort + 1;
|
||||
state.player.list.push(track);
|
||||
},
|
||||
turnOnShuffleMode(state) {
|
||||
state.player.notShuffledList = JSON.parse(
|
||||
JSON.stringify(state.player.list)
|
||||
);
|
||||
state.player.shuffle = true;
|
||||
|
||||
let newSorts = shuffleAList(
|
||||
state.player.list.filter((t) => t.sort > state.player.currentTrack.sort)
|
||||
);
|
||||
|
||||
state.player.list = state.player.list.map((track) => {
|
||||
if (newSorts[track.id] !== undefined) track.sort = newSorts[track.id];
|
||||
return track;
|
||||
});
|
||||
},
|
||||
turnOffShuffleMode(state) {
|
||||
state.player.shuffle = false;
|
||||
state.player.list = JSON.parse(
|
||||
JSON.stringify(state.player.notShuffledList)
|
||||
);
|
||||
state.player.currentTrack.sort = state.player.list.find(
|
||||
(t) => t.id === state.player.currentTrack.id
|
||||
).sort;
|
||||
},
|
||||
shuffleTheListBeforePlay(state) {
|
||||
state.player.notShuffledList = JSON.parse(
|
||||
JSON.stringify(state.player.list)
|
||||
);
|
||||
let newSorts = shuffleAList(state.player.list);
|
||||
state.player.list = state.player.list.map((track) => {
|
||||
track.sort = newSorts[track.id];
|
||||
return track;
|
||||
});
|
||||
},
|
||||
updateLikedSongs(state, trackIDs) {
|
||||
state.liked.songs = trackIDs;
|
||||
},
|
||||
switchSortBetweenTwoTracks(state, { trackID1, trackID2 }) {
|
||||
let t1 = state.player.list.find((t) => t.id === trackID1);
|
||||
let t2 = state.player.list.find((t) => t.id === trackID2);
|
||||
let sorts = [t1.sort, t2.sort];
|
||||
state.player.list = state.player.list.map((t) => {
|
||||
if (t.id === t1.id) t.sort = sorts[1];
|
||||
if (t.id === t2.id) t.sort = sorts[0];
|
||||
return t;
|
||||
});
|
||||
state.player.sendSelfToIpcMain();
|
||||
},
|
||||
changeLang(state, lang) {
|
||||
state.settings.lang = lang;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export default (store) => {
|
||||
store.subscribe((mutation, state) => {
|
||||
// console.log(mutation);
|
||||
localStorage.setItem("player", JSON.stringify(state.player));
|
||||
localStorage.setItem("settings", JSON.stringify(state.settings));
|
||||
localStorage.setItem("data", JSON.stringify(state.data));
|
||||
});
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
import initLocalStorage from "./initLocalStorage";
|
||||
import pkg from "../../package.json";
|
||||
|
||||
if (localStorage.getItem("appVersion") === null) {
|
||||
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
||||
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
||||
localStorage.setItem("appVersion", pkg.version);
|
||||
}
|
||||
|
||||
export default {
|
||||
howler: null,
|
||||
liked: {
|
||||
|
|
377
src/utils/Player.js
Normal file
377
src/utils/Player.js
Normal file
|
@ -0,0 +1,377 @@
|
|||
import { getTrackDetail, scrobble, getMP3 } from "@/api/track";
|
||||
import { shuffle } from "lodash";
|
||||
import { Howler, Howl } from "howler";
|
||||
import localforage from "localforage";
|
||||
import { cacheTrack } from "@/utils/db";
|
||||
import { getAlbum } from "@/api/album";
|
||||
import { getPlaylistDetail } from "@/api/playlist";
|
||||
import { getArtist } from "@/api/artist";
|
||||
import store from "@/store";
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require("electron") : null;
|
||||
const ipcRenderer =
|
||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||
|
||||
export default class {
|
||||
constructor() {
|
||||
this._enabled = false;
|
||||
this._repeatMode = "off"; // off | on | one
|
||||
this._shuffle = false; // true | false
|
||||
this._volume = 1; // 0 to 1
|
||||
this._volumeBeforeMuted = 1; // 用于保存静音前的音量
|
||||
this._list = [];
|
||||
this._current = 0; // current track index
|
||||
this._shuffledList = [];
|
||||
this._shuffledCurrent = 0;
|
||||
this._playlistSource = { type: "album", id: 123 };
|
||||
this._currentTrack = { id: 86827685 };
|
||||
this._playNextList = []; // 当这个list不为空时,会优先播放这个list的歌
|
||||
this._playing = false;
|
||||
|
||||
this._howler = null;
|
||||
Object.defineProperty(this, "_howler", {
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
this._init();
|
||||
}
|
||||
|
||||
get repeatMode() {
|
||||
return this._repeatMode;
|
||||
}
|
||||
set repeatMode(mode) {
|
||||
if (!["off", "on", "one"].includes(mode)) {
|
||||
console.warn("repeatMode: invalid args, must be 'on' | 'off' | 'one'");
|
||||
return;
|
||||
}
|
||||
this._repeatMode = mode;
|
||||
}
|
||||
get shuffle() {
|
||||
return this._shuffle;
|
||||
}
|
||||
set shuffle(shuffle) {
|
||||
if (shuffle !== true && shuffle !== false) {
|
||||
console.warn("shuffle: invalid args, must be Boolean");
|
||||
return;
|
||||
}
|
||||
this._shuffle = shuffle;
|
||||
if (shuffle) {
|
||||
this._shuffleTheList();
|
||||
}
|
||||
}
|
||||
get volume() {
|
||||
return this._volume;
|
||||
}
|
||||
set volume(volume) {
|
||||
this._volume = volume;
|
||||
Howler.volume(volume);
|
||||
}
|
||||
get list() {
|
||||
return this.shuffle ? this._shuffledList : this._list;
|
||||
}
|
||||
set list(list) {
|
||||
this._list = list;
|
||||
}
|
||||
get current() {
|
||||
return this.shuffle ? this._shuffledCurrent : this._current;
|
||||
}
|
||||
set current(current) {
|
||||
if (this.shuffle) {
|
||||
this._shuffledCurrent = current;
|
||||
} else {
|
||||
this._current = current;
|
||||
}
|
||||
}
|
||||
get enabled() {
|
||||
return this._enabled;
|
||||
}
|
||||
get playing() {
|
||||
return this._playing;
|
||||
}
|
||||
get currentTrack() {
|
||||
return this._currentTrack;
|
||||
}
|
||||
get playlistSource() {
|
||||
return this._playlistSource;
|
||||
}
|
||||
get playNextList() {
|
||||
return this._playNextList;
|
||||
}
|
||||
|
||||
_init() {
|
||||
Howler.autoUnlock = false;
|
||||
this._loadSelfFromLocalStorage();
|
||||
this._replaceCurrentTrack(this._currentTrack.id, false); // update audio source and init howler
|
||||
this._initMediaSession();
|
||||
}
|
||||
_getNextTrack() {
|
||||
// 返回 [trackID, index]
|
||||
if (this._playNextList.length > 0) {
|
||||
let trackID = this._playNextList.shift();
|
||||
return [trackID, this.current];
|
||||
}
|
||||
if (this.list.length === this.current + 1 && this.repeatMode === "on") {
|
||||
// 当歌曲是列表最后一首 && 循环模式开启
|
||||
return [this.list[0], 0];
|
||||
}
|
||||
return [this.list[this.current + 1], this.current + 1];
|
||||
}
|
||||
_getPrevTrack() {
|
||||
if (this.current === 0 && this.repeatMode === "on") {
|
||||
// 当歌曲是列表第一首 && 循环模式开启
|
||||
return [this.list[this.list.length - 1], this.list.length - 1];
|
||||
}
|
||||
return [this.list[this.current - 1], this.current - 1];
|
||||
}
|
||||
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
|
||||
let list = this._list.filter((tid) => tid !== firstTrackID);
|
||||
if (firstTrackID === "first") list = this._list;
|
||||
this._shuffledList = shuffle(list);
|
||||
if (firstTrackID !== "first") this._shuffledList.unshift(firstTrackID);
|
||||
}
|
||||
async _scrobble(complete = false) {
|
||||
let time = this._howler.seek();
|
||||
if (complete) {
|
||||
time = ~~(this._currentTrack.dt / 100);
|
||||
}
|
||||
scrobble({
|
||||
id: this._currentTrack.id,
|
||||
sourceid: this.playlistSource.id,
|
||||
time,
|
||||
});
|
||||
}
|
||||
_playAudioSource(source, autoplay = true) {
|
||||
Howler.unload();
|
||||
this._howler = new Howl({
|
||||
src: [source],
|
||||
html5: true,
|
||||
format: ["mp3", "flac"],
|
||||
});
|
||||
if (autoplay) this.play();
|
||||
this._howler.once("end", () => {
|
||||
this._nextTrackCallback();
|
||||
});
|
||||
}
|
||||
_getAudioSourceFromCache(id) {
|
||||
let tracks = localforage.createInstance({ name: "tracks" });
|
||||
return tracks.getItem(id).then((t) => {
|
||||
if (t === null) return null;
|
||||
const source = URL.createObjectURL(new Blob([t.mp3]));
|
||||
return source;
|
||||
});
|
||||
}
|
||||
_getAudioSourceFromNetease(track) {
|
||||
return getMP3(track.id).then((data) => {
|
||||
if (!data.data[0]) return null;
|
||||
if (data.data[0].freeTrialInfo !== null) return null; // 跳过只能试听的歌曲
|
||||
const source = data.data[0].url.replace(/^http:/, "https:");
|
||||
if (store.state.settings.automaticallyCacheSongs) {
|
||||
cacheTrack(track.id, source);
|
||||
}
|
||||
return source;
|
||||
});
|
||||
}
|
||||
_getAudioSourceFromUnblockMusic(track) {
|
||||
if (process.env.IS_ELECTRON !== true) return null;
|
||||
const source = ipcRenderer.sendSync("unblock-music", track);
|
||||
return source?.url;
|
||||
}
|
||||
_getAudioSource(track) {
|
||||
return this._getAudioSourceFromCache(String(track.id))
|
||||
.then((source) => {
|
||||
if (!source) return null;
|
||||
return source;
|
||||
})
|
||||
.then((source) => {
|
||||
if (source) return source;
|
||||
return this._getAudioSourceFromNetease(track);
|
||||
})
|
||||
.then((source) => {
|
||||
if (source) return source;
|
||||
return this._getAudioSourceFromUnblockMusic(track);
|
||||
});
|
||||
}
|
||||
_replaceCurrentTrack(
|
||||
id,
|
||||
autoplay = true,
|
||||
ifUnplayableThen = "playNextTrack"
|
||||
) {
|
||||
return getTrackDetail(id).then((data) => {
|
||||
let track = data.songs[0];
|
||||
this._currentTrack = track;
|
||||
this._updateMediaSessionMetaData(track);
|
||||
document.title = `${track.name} · ${track.ar[0].name} - YesPlayMusic`;
|
||||
this._getAudioSource(track).then((source) => {
|
||||
if (source) {
|
||||
this._playAudioSource(source, autoplay);
|
||||
return source;
|
||||
} else {
|
||||
ifUnplayableThen === "playNextTrack"
|
||||
? this.playNextTrack()
|
||||
: this.playPrevTrack();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
_loadSelfFromLocalStorage() {
|
||||
const player = JSON.parse(localStorage.getItem("player"));
|
||||
if (!player) return;
|
||||
for (const [key, value] of Object.entries(player)) {
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
_initMediaSession() {
|
||||
if ("mediaSession" in navigator) {
|
||||
navigator.mediaSession.setActionHandler("play", () => {
|
||||
this.play();
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("pause", () => {
|
||||
this.pause();
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("previoustrack", () => {
|
||||
this.playPrevTrack();
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("nexttrack", () => {
|
||||
this.playNextTrack();
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("stop", () => {
|
||||
this.pause();
|
||||
});
|
||||
}
|
||||
}
|
||||
_updateMediaSessionMetaData(track) {
|
||||
if ("mediaSession" in navigator === false) {
|
||||
return;
|
||||
}
|
||||
let artists = track.ar.map((a) => a.name);
|
||||
navigator.mediaSession.metadata = new window.MediaMetadata({
|
||||
title: track.name,
|
||||
artist: artists.join(","),
|
||||
album: track.al.name,
|
||||
artwork: [
|
||||
{
|
||||
src: track.al.picUrl + "?param=512y512",
|
||||
type: "image/jpg",
|
||||
sizes: "512x512",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
_nextTrackCallback() {
|
||||
this._scrobble(true);
|
||||
if (this.repeatMode === "one") {
|
||||
this._howler.play();
|
||||
} else {
|
||||
this.playNextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
currentTrackID() {
|
||||
const { list, current } = this._getListAndCurrent();
|
||||
return list[current];
|
||||
}
|
||||
appendTrack(trackID) {
|
||||
this.list.append(trackID);
|
||||
}
|
||||
playNextTrack() {
|
||||
// TODO: 切换歌曲时增加加载中的状态
|
||||
const [trackID, index] = this._getNextTrack();
|
||||
if (trackID === undefined) {
|
||||
this._howler.stop();
|
||||
return false;
|
||||
}
|
||||
this.current = index;
|
||||
this._replaceCurrentTrack(trackID);
|
||||
return true;
|
||||
}
|
||||
playPrevTrack() {
|
||||
const [trackID, index] = this._getPrevTrack();
|
||||
if (trackID === undefined) return false;
|
||||
this.current = index;
|
||||
this._replaceCurrentTrack(trackID, true, "playPrevTrack");
|
||||
return true;
|
||||
}
|
||||
saveSelfToLocalStorage() {
|
||||
let player = {};
|
||||
for (let [key, value] of Object.entries(this)) {
|
||||
if (key === "_playing") continue;
|
||||
player[key] = value;
|
||||
}
|
||||
|
||||
localStorage.setItem("player", JSON.stringify(player));
|
||||
}
|
||||
|
||||
pause() {
|
||||
this._howler.pause();
|
||||
this._playing = false;
|
||||
}
|
||||
play() {
|
||||
this._howler.play();
|
||||
this._playing = true;
|
||||
}
|
||||
seek(time = null) {
|
||||
if (time !== null) this._howler.seek(time);
|
||||
return this._howler.seek();
|
||||
}
|
||||
mute() {
|
||||
if (this.volume === 0) {
|
||||
this.volume = this._volumeBeforeMuted;
|
||||
} else {
|
||||
this._volumeBeforeMuted = this.volume;
|
||||
this.volume = 0;
|
||||
}
|
||||
}
|
||||
|
||||
replacePlaylist(
|
||||
trackIDs,
|
||||
playlistSourceID,
|
||||
playlistSourceType,
|
||||
autoPlayTrackID = "first"
|
||||
) {
|
||||
if (!this._enabled) this._enabled = true;
|
||||
this.list = trackIDs;
|
||||
this.current = 0;
|
||||
this._playlistSource = {
|
||||
type: playlistSourceType,
|
||||
id: playlistSourceID,
|
||||
};
|
||||
if (this.shuffle) this._shuffleTheList(autoPlayTrackID);
|
||||
if (autoPlayTrackID === "first") {
|
||||
this._replaceCurrentTrack(this.list[0]);
|
||||
} else {
|
||||
this.current = trackIDs.indexOf(autoPlayTrackID);
|
||||
this._replaceCurrentTrack(autoPlayTrackID);
|
||||
}
|
||||
}
|
||||
playAlbumByID(id, trackID = "first") {
|
||||
getAlbum(id).then((data) => {
|
||||
let trackIDs = data.songs.map((t) => t.id);
|
||||
this.replacePlaylist(trackIDs, id, "album", trackID);
|
||||
});
|
||||
}
|
||||
playPlaylistByID(id, trackID = "first", noCache = false) {
|
||||
getPlaylistDetail(id, noCache).then((data) => {
|
||||
let trackIDs = data.playlist.trackIds.map((t) => t.id);
|
||||
this.replacePlaylist(trackIDs, id, "playlist", trackID);
|
||||
});
|
||||
}
|
||||
playArtistByID(id, trackID = "first") {
|
||||
getArtist(id).then((data) => {
|
||||
let trackIDs = data.hotSongs.map((t) => t.id);
|
||||
this.replacePlaylist(trackIDs, id, "artist", trackID);
|
||||
});
|
||||
}
|
||||
addTrackToPlayNext(trackID, playNow = false) {
|
||||
this._playNextList.push(trackID);
|
||||
if (playNow) this.playNextTrack();
|
||||
}
|
||||
|
||||
sendSelfToIpcMain() {
|
||||
if (process.env.IS_ELECTRON !== true) return false;
|
||||
ipcRenderer.send("player", {
|
||||
playing: this.playing,
|
||||
likedCurrentTrack: store.state.liked.songs.includes(this.currentTrack.id),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
import store from "@/store";
|
||||
import { getAlbum } from "@/api/album";
|
||||
import { getPlaylistDetail } from "@/api/playlist";
|
||||
import { getArtist } from "@/api/artist";
|
||||
|
||||
export function playAList(list, id, type, trackID = "first") {
|
||||
let filteredList = list.map((id, index) => {
|
||||
return { sort: index, id };
|
||||
});
|
||||
store.commit("updatePlayerList", filteredList);
|
||||
if (store.state.player.shuffle) store.commit("shuffleTheListBeforePlay");
|
||||
|
||||
if (trackID === "first") store.dispatch("playFirstTrackOnList");
|
||||
else store.dispatch("playTrackOnListByID", trackID);
|
||||
|
||||
store.commit("updateListInfo", { type, id });
|
||||
}
|
||||
|
||||
export function playAlbumByID(id, trackID = "first") {
|
||||
getAlbum(id).then((data) => {
|
||||
let trackIDs = data.songs.map((t) => t.id);
|
||||
playAList(trackIDs, id, "album", trackID);
|
||||
});
|
||||
}
|
||||
|
||||
export function playPlaylistByID(id, trackID = "first", noCache = false) {
|
||||
getPlaylistDetail(id, noCache).then((data) => {
|
||||
let trackIDs = data.playlist.trackIds.map((t) => t.id);
|
||||
playAList(trackIDs, id, "playlist", trackID);
|
||||
});
|
||||
}
|
||||
|
||||
export function playArtistByID(id, trackID = "first") {
|
||||
getArtist(id).then((data) => {
|
||||
let trackIDs = data.hotSongs.map((t) => t.id);
|
||||
playAList(trackIDs, id, "artist", trackID);
|
||||
});
|
||||
}
|
||||
|
||||
export function appendTrackToPlayerList(trackID, playNext = false) {
|
||||
let filteredTrack = {
|
||||
sort: 0,
|
||||
id: trackID,
|
||||
};
|
||||
|
||||
store.commit("appendTrackToPlayerList", {
|
||||
track: filteredTrack,
|
||||
playNext,
|
||||
});
|
||||
if (playNext) {
|
||||
store.dispatch("nextTrack", true);
|
||||
}
|
||||
}
|
|
@ -24,8 +24,31 @@ const updateData = () => {
|
|||
localStorage.setItem("data", JSON.stringify(data));
|
||||
};
|
||||
|
||||
const updatePlayer = () => {
|
||||
let parsedData = JSON.parse(localStorage.getItem("player"));
|
||||
let appVersion = localStorage.getItem("appVersion");
|
||||
if (appVersion === `"0.2.5"`) parsedData = {}; // 0.2.6版本重构了player
|
||||
const data = {
|
||||
_repeatMode: "off",
|
||||
_shuffle: false,
|
||||
_list: [],
|
||||
_current: 0,
|
||||
_playlistSource: {},
|
||||
_volume: 1,
|
||||
_volumeBeforeMuted: 1,
|
||||
_currentTrack: {},
|
||||
_playNextList: [],
|
||||
_enabled: false,
|
||||
_shuffledList: [],
|
||||
_shuffledCurrent: 0,
|
||||
...parsedData,
|
||||
};
|
||||
localStorage.setItem("player", JSON.stringify(data));
|
||||
};
|
||||
|
||||
export default function () {
|
||||
updateSetting();
|
||||
updateData();
|
||||
updatePlayer();
|
||||
localStorage.setItem("appVersion", JSON.stringify(pkg.version));
|
||||
}
|
||||
|
|
|
@ -124,7 +124,6 @@
|
|||
import { mapMutations, mapActions, mapState } from "vuex";
|
||||
import { getArtistAlbum } from "@/api/artist";
|
||||
import { getTrackDetail } from "@/api/track";
|
||||
import { playAlbumByID } from "@/utils/play";
|
||||
import { getAlbum, albumDynamicDetail, likeAAlbum } from "@/api/album";
|
||||
import { splitSoundtrackAlbumTitle, splitAlbumTitle } from "@/utils/common";
|
||||
import NProgress from "nprogress";
|
||||
|
@ -202,7 +201,7 @@ export default {
|
|||
if (this.tracks.find((t) => t.playable !== false) === undefined) {
|
||||
return;
|
||||
}
|
||||
playAlbumByID(id, trackID);
|
||||
this.$store.state.player.playAlbumByID(id, trackID);
|
||||
},
|
||||
likeAlbum(toast = false) {
|
||||
if (!isAccountLoggedIn()) {
|
||||
|
|
|
@ -112,7 +112,6 @@ import {
|
|||
artistMv,
|
||||
followAArtist,
|
||||
} from "@/api/artist";
|
||||
import { playAList } from "@/utils/play";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
import NProgress from "nprogress";
|
||||
|
||||
|
@ -186,7 +185,12 @@ export default {
|
|||
},
|
||||
playPopularSongs(trackID = "first") {
|
||||
let trackIDs = this.popularTracks.map((t) => t.id);
|
||||
playAList(trackIDs, this.artist.id, "artist", trackID);
|
||||
this.$store.state.player.replacePlaylist(
|
||||
trackIDs,
|
||||
this.artist.id,
|
||||
"artist",
|
||||
trackID
|
||||
);
|
||||
},
|
||||
followArtist() {
|
||||
if (!isAccountLoggedIn()) {
|
||||
|
|
|
@ -125,7 +125,6 @@ import {
|
|||
import { randomNum, dailyTask } from "@/utils/common";
|
||||
import { getPlaylistDetail } from "@/api/playlist";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
import { playPlaylistByID } from "@/utils/play";
|
||||
import NProgress from "nprogress";
|
||||
|
||||
import TrackList from "@/components/TrackList.vue";
|
||||
|
@ -193,7 +192,11 @@ export default {
|
|||
...mapActions(["showToast"]),
|
||||
...mapMutations(["updateModal"]),
|
||||
playLikedSongs() {
|
||||
playPlaylistByID(this.playlists[0].id, "first", true);
|
||||
this.$store.state.player.playPlaylistByID(
|
||||
this.playlists[0].id,
|
||||
"first",
|
||||
true
|
||||
);
|
||||
},
|
||||
updateCurrentTab(tab) {
|
||||
if (!isAccountLoggedIn() && tab !== "playlists") {
|
||||
|
|
|
@ -182,7 +182,6 @@ import {
|
|||
subscribePlaylist,
|
||||
deletePlaylist,
|
||||
} from "@/api/playlist";
|
||||
import { playAList } from "@/utils/play";
|
||||
import { getTrackDetail } from "@/api/track";
|
||||
import { isAccountLoggedIn } from "@/utils/auth";
|
||||
|
||||
|
@ -335,7 +334,12 @@ export default {
|
|||
...mapActions(["playFirstTrackOnList", "playTrackOnListByID", "showToast"]),
|
||||
playPlaylistByID(trackID = "first") {
|
||||
let trackIDs = this.playlist.trackIds.map((t) => t.id);
|
||||
playAList(trackIDs, this.playlist.id, "playlist", trackID);
|
||||
this.$store.state.player.replacePlaylist(
|
||||
trackIDs,
|
||||
this.playlist.id,
|
||||
"playlist",
|
||||
trackID
|
||||
);
|
||||
},
|
||||
likePlaylist(toast = false) {
|
||||
if (!isAccountLoggedIn()) {
|
||||
|
|
|
@ -105,7 +105,6 @@
|
|||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import NProgress from "nprogress";
|
||||
import { appendTrackToPlayerList } from "@/utils/play";
|
||||
import { search } from "@/api/others";
|
||||
|
||||
import Cover from "@/components/Cover.vue";
|
||||
|
@ -148,7 +147,7 @@ export default {
|
|||
},
|
||||
playTrackInSearchResult(id) {
|
||||
let track = this.tracks.find((t) => t.id === id);
|
||||
appendTrackToPlayerList(track, true);
|
||||
this.$store.state.player.appendTrackToPlayerList(track, true);
|
||||
},
|
||||
getData(keywords) {
|
||||
search({ keywords: keywords, type: 1018 }).then((data) => {
|
||||
|
|
170
yarn.lock
170
yarn.lock
|
@ -1381,6 +1381,11 @@
|
|||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@tokenizer/token@^0.1.0", "@tokenizer/token@^0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3"
|
||||
integrity sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==
|
||||
|
||||
"@tootallnate/once@1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npm.taobao.org/@tootallnate/once/download/@tootallnate/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
|
@ -1536,6 +1541,14 @@
|
|||
resolved "https://registry.npm.taobao.org/@types/range-parser/download/@types/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
integrity sha1-fuMwunyq+5gJC+zoal7kQRWQTCw=
|
||||
|
||||
"@types/readable-stream@^2.3.9":
|
||||
version "2.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.9.tgz#40a8349e6ace3afd2dd1b6d8e9b02945de4566a9"
|
||||
integrity sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
safe-buffer "*"
|
||||
|
||||
"@types/semver@^7.3.1":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.npm.taobao.org/@types/semver/download/@types/semver-7.3.4.tgz?cache=0&sync_timestamp=1600115372478&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fsemver%2Fdownload%2F%40types%2Fsemver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
|
||||
|
@ -2765,6 +2778,19 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5:
|
|||
escalade "^3.1.0"
|
||||
node-releases "^1.1.61"
|
||||
|
||||
buffer-alloc-unsafe@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
||||
|
||||
buffer-alloc@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
||||
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
||||
dependencies:
|
||||
buffer-alloc-unsafe "^1.1.0"
|
||||
buffer-fill "^1.0.0"
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
|
@ -2775,7 +2801,12 @@ buffer-equal@0.0.1:
|
|||
resolved "https://registry.npm.taobao.org/buffer-equal/download/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
|
||||
integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
buffer-fill@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
||||
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
|
||||
|
||||
buffer-from@^1.0.0, buffer-from@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
@ -2812,6 +2843,14 @@ buffer@^5.2.0:
|
|||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
buffer@^5.4.3:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builder-util-runtime@8.7.2:
|
||||
version "8.7.2"
|
||||
resolved "https://registry.npm.taobao.org/builder-util-runtime/download/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72"
|
||||
|
@ -3093,6 +3132,11 @@ chardet@^0.7.0:
|
|||
resolved "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz?cache=0&sync_timestamp=1594010664806&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchardet%2Fdownload%2Fchardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=
|
||||
|
||||
charenc@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
check-types@^8.0.3:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.npm.taobao.org/check-types/download/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
|
||||
|
@ -3529,7 +3573,7 @@ content-disposition@0.5.3:
|
|||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
content-type@~1.0.4:
|
||||
content-type@^1.0.4, content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha1-4TjMdeBAxyexlm/l5fjJruJW/js=
|
||||
|
@ -3690,6 +3734,11 @@ cross-spawn@^7.0.0:
|
|||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypt@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
crypto-browserify@^3.11.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz?cache=0&sync_timestamp=1589682788096&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcrypto-browserify%2Fdownload%2Fcrypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
||||
|
@ -3947,7 +3996,7 @@ debug@^3.1.1, debug@^3.2.5:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1:
|
||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
|
@ -4144,6 +4193,11 @@ diffie-hellman@^5.0.0:
|
|||
miller-rabin "^4.0.0"
|
||||
randombytes "^2.0.0"
|
||||
|
||||
dijkstrajs@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
|
||||
integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
|
||||
|
||||
dir-glob@^2.0.0, dir-glob@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
|
||||
|
@ -5114,6 +5168,16 @@ file-loader@^4.2.0:
|
|||
loader-utils "^1.2.3"
|
||||
schema-utils "^2.5.0"
|
||||
|
||||
file-type@^16.1.0:
|
||||
version "16.1.0"
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.1.0.tgz#1c8a4458b2103e07d2b49ae7f76384abafe86529"
|
||||
integrity sha512-G4Klqf6tuprtG0pC4r9kni4Wv8XhAAsfHphVqsQGA+YiOlPAO40BZduDqKfv0RFsu9q9ZbFObWfwszY/NqhEZw==
|
||||
dependencies:
|
||||
readable-web-to-node-stream "^3.0.0"
|
||||
strtok3 "^6.0.3"
|
||||
token-types "^2.0.0"
|
||||
typedarray-to-buffer "^3.1.5"
|
||||
|
||||
file-type@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.npm.taobao.org/file-type/download/file-type-9.0.0.tgz?cache=0&sync_timestamp=1603046153408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffile-type%2Fdownload%2Ffile-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18"
|
||||
|
@ -6261,10 +6325,10 @@ is-binary-path@~2.1.0:
|
|||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-buffer@^1.1.5:
|
||||
is-buffer@^1.1.5, is-buffer@~1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha1-76ouqdqg16suoTqXsritUf776L4=
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
is-callable@^1.1.4, is-callable@^1.2.0:
|
||||
version "1.2.2"
|
||||
|
@ -6575,6 +6639,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isarray@^2.0.1:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
|
||||
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
|
||||
|
||||
isbinaryfile@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.npm.taobao.org/isbinaryfile/download/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b"
|
||||
|
@ -7121,7 +7190,7 @@ lodash.uniq@^4.5.0:
|
|||
resolved "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz?cache=0&sync_timestamp=1589682817275&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.uniq%2Fdownload%2Flodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.3:
|
||||
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597335994883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=
|
||||
|
@ -7225,6 +7294,15 @@ md5.js@^1.3.4:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
md5@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||
dependencies:
|
||||
charenc "0.0.2"
|
||||
crypt "0.0.2"
|
||||
is-buffer "~1.1.6"
|
||||
|
||||
mdn-data@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmdn-data%2Fdownload%2Fmdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
|
@ -7240,6 +7318,11 @@ media-typer@0.3.0:
|
|||
resolved "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
media-typer@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561"
|
||||
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==
|
||||
|
||||
memory-fs@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
|
||||
|
@ -7549,6 +7632,18 @@ multicast-dns@^6.0.1:
|
|||
dns-packet "^1.3.1"
|
||||
thunky "^1.0.2"
|
||||
|
||||
music-metadata@^7.6.2:
|
||||
version "7.6.2"
|
||||
resolved "https://registry.yarnpkg.com/music-metadata/-/music-metadata-7.6.2.tgz#7c46aaa32f37d3f747d653006e24c3f0efd83dc6"
|
||||
integrity sha512-yICd18bxEhphpUPwwzDe8wP3LSsbnKzPjuIDKAYpXgYVkMl2aZxvWx6qA59ccsVC0J5FeEhbRlWiAZ6IFZZYZg==
|
||||
dependencies:
|
||||
content-type "^1.0.4"
|
||||
debug "^4.3.1"
|
||||
file-type "^16.1.0"
|
||||
media-typer "^1.1.0"
|
||||
strtok3 "^6.0.6"
|
||||
token-types "^2.0.0"
|
||||
|
||||
mute-stream@0.0.8:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
||||
|
@ -8271,6 +8366,11 @@ pbkdf2@^3.0.3:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
peek-readable@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-3.1.1.tgz#795c1429374f256e4b5ab6c584cecfd3a110024f"
|
||||
integrity sha512-QHJag0oYYPVkx6rVPEgCLEUMo6VRYbV3GUrqy00lxXJBEIw9LhPCP5MQI6mEfahJO9KYUP8W8qD8kC0V9RyZFQ==
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
|
@ -8396,7 +8496,7 @@ pngjs-nozlib@^1.0.0:
|
|||
resolved "https://registry.npm.taobao.org/pngjs-nozlib/download/pngjs-nozlib-1.0.0.tgz#9e64d602cfe9cce4d9d5997d0687429a73f0b7d7"
|
||||
integrity sha1-nmTWAs/pzOTZ1Zl9BodCmnPwt9c=
|
||||
|
||||
pngjs@^3.0.0, pngjs@^3.3.3:
|
||||
pngjs@^3.0.0, pngjs@^3.3.0, pngjs@^3.3.3:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.npm.taobao.org/pngjs/download/pngjs-3.4.0.tgz?cache=0&sync_timestamp=1603551107900&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpngjs%2Fdownload%2Fpngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
|
||||
integrity sha1-mcp9clll+2VYFOr2XzjxK72/VV8=
|
||||
|
@ -8982,6 +9082,19 @@ q@^1.1.2:
|
|||
resolved "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz?cache=0&sync_timestamp=1589682817412&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fq%2Fdownload%2Fq-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
||||
|
||||
qrcode@^1.4.4:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"
|
||||
integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==
|
||||
dependencies:
|
||||
buffer "^5.4.3"
|
||||
buffer-alloc "^1.2.0"
|
||||
buffer-from "^1.1.1"
|
||||
dijkstrajs "^1.0.1"
|
||||
isarray "^2.0.1"
|
||||
pngjs "^3.3.0"
|
||||
yargs "^13.2.4"
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
|
@ -9140,6 +9253,14 @@ readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable
|
|||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-web-to-node-stream@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.1.tgz#3f619b1bc5dd73a4cfe5c5f9b4f6faba55dff845"
|
||||
integrity sha512-4zDC6CvjUyusN7V0QLsXVB7pJCD9+vtrM9bYDRv6uBQ+SKfx36rp5AFNPRgh9auKRul/a1iFZJYXcCbwRL+SaA==
|
||||
dependencies:
|
||||
"@types/readable-stream" "^2.3.9"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
readdirp@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
|
||||
|
@ -9472,16 +9593,16 @@ rxjs@^6.6.0:
|
|||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
safe-buffer@*, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589682795646&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=
|
||||
|
||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589682795646&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=
|
||||
|
||||
safe-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz?cache=0&sync_timestamp=1589682757445&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-regex%2Fdownload%2Fsafe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
|
||||
|
@ -10227,6 +10348,15 @@ strip-json-comments@~2.0.1:
|
|||
resolved "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz?cache=0&sync_timestamp=1594567532500&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-json-comments%2Fdownload%2Fstrip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
|
||||
strtok3@^6.0.3, strtok3@^6.0.6:
|
||||
version "6.0.6"
|
||||
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.0.6.tgz#65ad16df313c8dfbf075ab0bcb1edd070002fcb3"
|
||||
integrity sha512-fVxvAEKDwHFfbQO1yKxKBPfkWZyBr0Zf20UQ/mblbkAQe5h0Xdd2jDb3Mh7yRZd7LSItJ9JWgQWelpEmVoBe2g==
|
||||
dependencies:
|
||||
"@tokenizer/token" "^0.1.1"
|
||||
"@types/debug" "^4.1.5"
|
||||
peek-readable "^3.1.1"
|
||||
|
||||
stylehacks@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npm.taobao.org/stylehacks/download/stylehacks-4.0.3.tgz?cache=0&sync_timestamp=1599672034713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstylehacks%2Fdownload%2Fstylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
||||
|
@ -10595,6 +10725,14 @@ toidentifier@1.0.0:
|
|||
resolved "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
integrity sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=
|
||||
|
||||
token-types@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/token-types/-/token-types-2.0.0.tgz#b23618af744818299c6fbf125e0fdad98bab7e85"
|
||||
integrity sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==
|
||||
dependencies:
|
||||
"@tokenizer/token" "^0.1.0"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
toposort@^1.0.0:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
|
||||
|
@ -11718,10 +11856,10 @@ yargs-parser@^4.2.0:
|
|||
dependencies:
|
||||
camelcase "^3.0.0"
|
||||
|
||||
yargs@^13.3.2:
|
||||
yargs@^13.2.4, yargs@^13.3.2:
|
||||
version "13.3.2"
|
||||
resolved "https://registry.npm.taobao.org/yargs/download/yargs-13.3.2.tgz?cache=0&sync_timestamp=1600660037884&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||
integrity sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
|
||||
dependencies:
|
||||
cliui "^5.0.0"
|
||||
find-up "^3.0.0"
|
||||
|
|
Loading…
Reference in New Issue
Block a user