mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2026-04-05 02:16:54 +08:00
* feat: add copy track link * fix: various visual defects * feat: add track low res fallback * chore: remove redundant locale strings * chore: separate playbackState for a new PR * build: fix netlify failing to build site
182 lines
3.6 KiB
Vue
182 lines
3.6 KiB
Vue
<template>
|
|
<div ref="contextMenu" class="context-menu">
|
|
<div
|
|
v-if="showMenu"
|
|
ref="menu"
|
|
class="menu"
|
|
tabindex="-1"
|
|
:style="{ top: top, left: left }"
|
|
@blur="closeMenu"
|
|
@click="closeMenu"
|
|
>
|
|
<slot></slot>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState } from 'vuex';
|
|
|
|
export default {
|
|
name: 'ContextMenu',
|
|
data() {
|
|
return {
|
|
showMenu: false,
|
|
top: '0px',
|
|
left: '0px',
|
|
};
|
|
},
|
|
computed: {
|
|
...mapState(['player']),
|
|
},
|
|
methods: {
|
|
setMenu(top, left) {
|
|
let heightOffset = this.player.enabled ? 64 : 0;
|
|
let largestHeight =
|
|
window.innerHeight - this.$refs.menu.offsetHeight - heightOffset;
|
|
let largestWidth = window.innerWidth - this.$refs.menu.offsetWidth - 25;
|
|
if (top > largestHeight) top = largestHeight;
|
|
if (left > largestWidth) left = largestWidth;
|
|
this.top = top + 'px';
|
|
this.left = left + 'px';
|
|
},
|
|
|
|
closeMenu() {
|
|
this.showMenu = false;
|
|
if (this.$parent.closeMenu !== undefined) {
|
|
this.$parent.closeMenu();
|
|
}
|
|
this.$store.commit('enableScrolling', true);
|
|
},
|
|
|
|
openMenu(e) {
|
|
this.showMenu = true;
|
|
this.$nextTick(
|
|
function () {
|
|
this.$refs.menu.focus();
|
|
this.setMenu(e.y, e.x);
|
|
}.bind(this)
|
|
);
|
|
e.preventDefault();
|
|
this.$store.commit('enableScrolling', false);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.context-menu {
|
|
width: 100%;
|
|
height: 100%;
|
|
user-select: none;
|
|
}
|
|
|
|
.menu {
|
|
position: fixed;
|
|
min-width: 136px;
|
|
max-width: 240px;
|
|
list-style: none;
|
|
background: rgba(255, 255, 255, 0.88);
|
|
box-shadow: 0 6px 12px -4px rgba(0, 0, 0, 0.08);
|
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
backdrop-filter: blur(12px);
|
|
border-radius: 12px;
|
|
box-sizing: border-box;
|
|
padding: 6px;
|
|
z-index: 1000;
|
|
-webkit-app-region: no-drag;
|
|
transition: background 125ms ease-out, opacity 125ms ease-out,
|
|
transform 125ms ease-out;
|
|
|
|
&:focus {
|
|
outline: none;
|
|
}
|
|
}
|
|
|
|
[data-theme='dark'] {
|
|
.menu {
|
|
background: rgba(36, 36, 36, 0.78);
|
|
backdrop-filter: blur(16px) contrast(120%) brightness(60%);
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
box-shadow: 0 0 6px rgba(255, 255, 255, 0.08);
|
|
}
|
|
.menu .item:hover {
|
|
color: var(--color-text);
|
|
}
|
|
}
|
|
|
|
@supports (-moz-appearance: none) {
|
|
.menu {
|
|
background-color: var(--color-body-bg) !important;
|
|
}
|
|
}
|
|
|
|
.menu .item {
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
padding: 10px 14px;
|
|
border-radius: 8px;
|
|
cursor: default;
|
|
color: var(--color-text);
|
|
display: flex;
|
|
align-items: center;
|
|
&:hover {
|
|
color: var(--color-primary);
|
|
background: var(--color-primary-bg-for-transparent);
|
|
transition: opacity 125ms ease-out, transform 125ms ease-out;
|
|
}
|
|
&:active {
|
|
opacity: 0.75;
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.svg-icon {
|
|
height: 16px;
|
|
width: 16px;
|
|
margin-right: 5px;
|
|
}
|
|
}
|
|
|
|
hr {
|
|
margin: 4px 10px;
|
|
background: rgba(128, 128, 128, 0.18);
|
|
height: 1px;
|
|
box-shadow: none;
|
|
border: none;
|
|
}
|
|
|
|
.item-info {
|
|
padding: 10px 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
color: var(--color-text);
|
|
cursor: default;
|
|
img {
|
|
height: 38px;
|
|
width: 38px;
|
|
border-radius: 4px;
|
|
}
|
|
.info {
|
|
margin-left: 10px;
|
|
}
|
|
.title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 1;
|
|
overflow: hidden;
|
|
word-break: break-all;
|
|
}
|
|
.subtitle {
|
|
font-size: 12px;
|
|
opacity: 0.68;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 1;
|
|
overflow: hidden;
|
|
word-break: break-all;
|
|
}
|
|
}
|
|
</style>
|