diff --git a/src/App.vue b/src/App.vue index c252bbf..68d2f1e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,7 +1,7 @@ @@ -31,6 +34,7 @@ import Player from "./components/Player.vue"; import Toast from "./components/Toast.vue"; import { ipcRenderer } from "./electron/ipcRenderer"; import { isAccountLoggedIn } from "@/utils/auth"; +import Lyrics from "./views/lyrics.vue"; export default { name: "App", @@ -40,6 +44,7 @@ export default { Toast, ModalAddTrackToPlaylist, ModalNewPlaylist, + Lyrics, }, data() { return { diff --git a/src/assets/css/slider.css b/src/assets/css/slider.css index 706c79e..2e5f40d 100644 --- a/src/assets/css/slider.css +++ b/src/assets/css/slider.css @@ -99,3 +99,32 @@ box-sizing: border-box; visibility: visible; } + +/* lyrics */ +.lyrics-page .vue-slider-rail { + background-color: rgba(128, 128, 128, 0.18); + border-radius: 2px; + height: 4px; + opacity: 0.88; +} + +.lyrics-page .vue-slider-process { + background-color: #060606; +} + +.lyrics-page .vue-slider-dot-handle { + background-color: #060606; + box-shadow: unset; +} + +.lyrics-page .vue-slider-dot-tooltip { + display: none; +} + +body[data-theme="dark"] .lyrics-page .vue-slider-process { + background-color: #fafafa; +} + +body[data-theme="dark"] .lyrics-page .vue-slider-dot-handle { + background-color: #fff; +} diff --git a/src/components/Player.vue b/src/components/Player.vue index 96cdbd0..62845e8 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -119,6 +119,14 @@ + + @@ -175,9 +183,12 @@ export default { let max = ~~(this.player.currentTrack.dt / 1000); return max > 1 ? max - 1 : max; }, + isCurrentTrackLiked() { + return this.liked.songs.includes(this.currentTrack.id); + }, }, methods: { - ...mapMutations(["updateLikedSongs"]), + ...mapMutations(["updateLikedSongs", "toggleLyrics"]), ...mapActions(["showToast"]), play() { this.player.playing ? this.player.pause() : this.player.play(); @@ -206,6 +217,9 @@ export default { this.progress = this.$refs.progress.getValue(); this.player.seek(this.$refs.progress.getValue()); }, + setProgress(value) { + this.progress = value; + }, goToNextTracksPage() { this.$route.name === "next" ? this.$router.go(-1) @@ -399,4 +413,13 @@ export default { .like-button { margin-left: 16px; } + +.lyrics-button { + position: fixed; + right: 18px; + .svg-icon { + height: 20px; + width: 20px; + } +} diff --git a/src/store/mutations.js b/src/store/mutations.js index e0f316c..66a66af 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -33,4 +33,7 @@ export default { updateModal(state, { modalName, key, value }) { state.modals[modalName][key] = value; }, + toggleLyrics(state) { + state.showLyrics = !state.showLyrics; + }, }; diff --git a/src/store/state.js b/src/store/state.js index 93f41d5..898bae8 100644 --- a/src/store/state.js +++ b/src/store/state.js @@ -8,7 +8,7 @@ if (localStorage.getItem("appVersion") === null) { } export default { - howler: null, + showLyrics: false, liked: { songs: [], }, diff --git a/src/utils/common.js b/src/utils/common.js index bdec810..23c67e6 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -208,3 +208,10 @@ export function bytesToSize(bytes) { return (bytes / megaBytes).toFixed(decimal) + " MB"; else return (bytes / gigaBytes).toFixed(decimal) + " GB"; } + +export function formatTrackTime(value) { + if (!value) return ""; + let min = ~~((value / 60) % 60); + let sec = (~~(value % 60)).toString().padStart(2, "0"); + return `${min}:${sec}`; +} diff --git a/src/utils/lyrics.js b/src/utils/lyrics.js new file mode 100644 index 0000000..230fa20 --- /dev/null +++ b/src/utils/lyrics.js @@ -0,0 +1,32 @@ +// copy from https://github.com/sl1673495/vue-netease-music/blob/master/src/utils/lrcparse.js + +export function lyricParser(lrc) { + return { + lyric: parseLyric(lrc.lrc.lyric || ""), + tlyric: parseLyric(lrc.tlyric.lyric || ""), + lyricuser: lrc.lyricUser, + transuser: lrc.transUser, + }; +} + +export function parseLyric(lrc) { + const lyrics = lrc.split("\n"); + const lrcObj = []; + for (let i = 0; i < lyrics.length; i++) { + const lyric = decodeURIComponent(lyrics[i]); + const timeReg = /\[\d*:\d*((\.|:)\d*)*\]/g; + const timeRegExpArr = lyric.match(timeReg); + if (!timeRegExpArr) continue; + const content = lyric.replace(timeReg, ""); + for (let k = 0, h = timeRegExpArr.length; k < h; k++) { + const t = timeRegExpArr[k]; + const min = Number(String(t.match(/\[\d*/i)).slice(1)); + const sec = Number(String(t.match(/:\d*/i)).slice(1)); + const time = min * 60 + sec; + if (content !== "") { + lrcObj.push({ time: time, content }); + } + } + } + return lrcObj; +} diff --git a/src/views/home.vue b/src/views/home.vue index eb4aae5..fab0f09 100644 --- a/src/views/home.vue +++ b/src/views/home.vue @@ -24,7 +24,11 @@
{{ $t("home.recommendArtist") }}
- +
diff --git a/src/views/lyrics.vue b/src/views/lyrics.vue new file mode 100644 index 0000000..b12a2d2 --- /dev/null +++ b/src/views/lyrics.vue @@ -0,0 +1,486 @@ + + + + +