mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-22 06:15:26 +08:00
feat: 复制歌词
This commit is contained in:
parent
481ba6bce3
commit
9d807d1d63
|
@ -244,6 +244,8 @@ export default {
|
|||
minePlaylists: 'My Playlists',
|
||||
likedPlaylists: 'Liked Playlists',
|
||||
cardiacMode: 'Cardiac Mode',
|
||||
copyLyric: 'Copy Lyric',
|
||||
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: 'Saved to playlist',
|
||||
|
|
|
@ -230,6 +230,8 @@ export default {
|
|||
minePlaylists: 'My Playlists',
|
||||
likedPlaylists: 'Liked Playlists',
|
||||
cardiacMode: 'Cardiac Mode',
|
||||
copyLyric: 'Copy Lyric',
|
||||
copyLyricWithTranslation: 'Copy Lyric With Translation',
|
||||
},
|
||||
toast: {
|
||||
savedToMyLikedSongs: 'Beğendiğim Müziklere Kaydet',
|
||||
|
|
|
@ -243,6 +243,8 @@ export default {
|
|||
minePlaylists: '创建的歌单',
|
||||
likedPlaylists: '收藏的歌单',
|
||||
cardiacMode: '心动模式',
|
||||
copyLyric: '复制歌词',
|
||||
copyLyricWithTranslation: '复制歌词(含翻译)',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: '已添加到歌单',
|
||||
|
|
|
@ -240,6 +240,8 @@ export default {
|
|||
minePlaylists: '我建立的歌單',
|
||||
likedPlaylists: '收藏的歌單',
|
||||
cardiacMode: '心動模式',
|
||||
copyLyric: '複製歌詞',
|
||||
copyLyricWithTranslation: '複製歌詞(含翻譯)',
|
||||
},
|
||||
toast: {
|
||||
savedToPlaylist: '已新增至歌單',
|
||||
|
|
|
@ -84,3 +84,30 @@ function trimContent(content) {
|
|||
let t = content.trim();
|
||||
return t.length < 1 ? content : t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} lyric
|
||||
*/
|
||||
export async function copyLyric(lyric) {
|
||||
const textToCopy = lyric;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(textToCopy);
|
||||
} catch (err) {
|
||||
alert('复制失败,请手动复制!');
|
||||
}
|
||||
} else {
|
||||
const tempInput = document.createElement('textarea');
|
||||
tempInput.value = textToCopy;
|
||||
tempInput.style.position = 'absolute';
|
||||
tempInput.style.left = '-9999px';
|
||||
document.body.appendChild(tempInput);
|
||||
tempInput.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
} catch (err) {
|
||||
alert('复制失败,请手动复制!');
|
||||
}
|
||||
document.body.removeChild(tempInput);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,7 +248,11 @@
|
|||
@dblclick="clickLyricLine(line.time, true)"
|
||||
>
|
||||
<div class="content">
|
||||
<span v-if="line.contents[0]">{{ line.contents[0] }}</span>
|
||||
<span
|
||||
v-if="line.contents[0]"
|
||||
@click.right="openLyricMenu($event, line, 0)"
|
||||
>{{ line.contents[0] }}</span
|
||||
>
|
||||
<br />
|
||||
<span
|
||||
v-if="
|
||||
|
@ -256,10 +260,26 @@
|
|||
$store.state.settings.showLyricsTranslation
|
||||
"
|
||||
class="translation"
|
||||
@click.right="openLyricMenu($event, line, 1)"
|
||||
>{{ line.contents[1] }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<ContextMenu v-if="!noLyric" ref="lyricMenu">
|
||||
<div class="item" @click="copyLyric(false)">{{
|
||||
$t('contextMenu.copyLyric')
|
||||
}}</div>
|
||||
<div
|
||||
v-if="
|
||||
rightClickLyric &&
|
||||
rightClickLyric.contents[1] &&
|
||||
$store.state.settings.showLyricsTranslation
|
||||
"
|
||||
class="item"
|
||||
@click="copyLyric(true)"
|
||||
>{{ $t('contextMenu.copyLyricWithTranslation') }}</div
|
||||
>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
@ -284,9 +304,10 @@
|
|||
|
||||
import { mapState, mapMutations, mapActions } from 'vuex';
|
||||
import VueSlider from 'vue-slider-component';
|
||||
import ContextMenu from '@/components/ContextMenu.vue';
|
||||
import { formatTrackTime } from '@/utils/common';
|
||||
import { getLyric } from '@/api/track';
|
||||
import { lyricParser } from '@/utils/lyrics';
|
||||
import { lyricParser, copyLyric } from '@/utils/lyrics';
|
||||
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||
import * as Vibrant from 'node-vibrant/dist/vibrant.worker.min.js';
|
||||
import Color from 'color';
|
||||
|
@ -299,6 +320,7 @@ export default {
|
|||
components: {
|
||||
VueSlider,
|
||||
ButtonIcon,
|
||||
ContextMenu,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -312,6 +334,7 @@ export default {
|
|||
background: '',
|
||||
date: this.formatTime(new Date()),
|
||||
isFullscreen: !!document.fullscreenElement,
|
||||
rightClickLyric: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -587,6 +610,21 @@ export default {
|
|||
this.player.play();
|
||||
}
|
||||
},
|
||||
openLyricMenu(e, lyric, idx) {
|
||||
this.rightClickLyric = { ...lyric, idx };
|
||||
this.$refs.lyricMenu.openMenu(e);
|
||||
e.preventDefault();
|
||||
},
|
||||
copyLyric(withTranslation) {
|
||||
if (this.rightClickLyric) {
|
||||
const idx = this.rightClickLyric.idx;
|
||||
if (!withTranslation) {
|
||||
copyLyric(this.rightClickLyric.contents[idx]);
|
||||
} else {
|
||||
copyLyric(this.rightClickLyric.contents.join(' '));
|
||||
}
|
||||
}
|
||||
},
|
||||
setLyricsInterval() {
|
||||
this.lyricsInterval = setInterval(() => {
|
||||
const progress = this.player.seek(null, false) ?? 0;
|
||||
|
@ -926,6 +964,7 @@ export default {
|
|||
transform-origin: center left;
|
||||
transform: scale(0.95);
|
||||
transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
user-select: none;
|
||||
|
||||
span {
|
||||
opacity: 0.28;
|
||||
|
|
Loading…
Reference in New Issue
Block a user