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 @@
-
+
@@ -20,6 +20,9 @@
+
+ ">
@@ -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 @@
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
{{ currentTrack.name }}
+
{{ currentTrack.ar[0].name }}
+ -
+ {{ currentTrack.al.name }}
+
+
+
+
+
+
+
+
{{ formatTrackTime(progress) || "0:00" }}
+
+
+
{{ formatTrackTime(progressMax) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+