v0.0.1 fullscreen UI

This commit is contained in:
yazninja 2022-08-08 12:51:31 +08:00
parent 53ff9426f3
commit 0a95f937be
3 changed files with 833 additions and 426 deletions

View file

@ -1,42 +1,44 @@
.fullscreen-view-container { .fullscreen-view-container {
position: absolute; position : absolute;
top: 0; top : 0;
left: 0; left : 0;
width: 100%; width : 100%;
height: 100%; height : 100%;
background: black; background : black;
z-index: 99; z-index : 99;
display: flex; display : flex;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
opacity: 1; opacity : 1;
} }
.fullscreen-view { .fullscreen-view {
width: 100%; width : 100%;
height: 100%; height : 100%;
background: black; background : black;
display: flex; display : flex;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
--chromeHeight1: 70px; --chromeHeight1: 70px;
.app-content-container { .app-content-container {
width: 100%; width : 100%;
height: 100%; height: 100%;
#app-content { #app-content {
width: 100%; width : 100%;
height: 100%; height: 100%;
.fs-search { .fs-search {
.search-input--icon { .search-input--icon {
width: 4em; width : 4em;
background-size: 40%; background-size : 40%;
background-position: center; background-position: center;
} }
input { input {
padding-left: 2em; padding-left : 2em;
font-size: 2em; font-size : 2em;
border-radius: var(--mediaItemRadius); border-radius: var(--mediaItemRadius);
} }
} }
@ -44,52 +46,52 @@
} }
.fs-header { .fs-header {
position: fixed; position : fixed;
top: 0; top : 0;
left: 0; left : 0;
right: 0; right : 0;
height: var(--chromeHeight1); height : var(--chromeHeight1);
display: flex; display : flex;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
z-index: 9999; z-index : 9999;
.top-nav-group { .top-nav-group {
background: #1e1e1e99; background : #1e1e1e99;
border: 1px solid lighten(@baseColor, 8); border : 1px solid lighten(@baseColor, 8);
border-radius: 12px; border-radius : 12px;
display: flex; display : flex;
height: 55px; height : 55px;
width: 90%; width : 90%;
backdrop-filter: var(--glassFilter); backdrop-filter: var(--glassFilter);
.app-sidebar-item { .app-sidebar-item {
background-color: #1e1e1e00; background-color: #1e1e1e00;
border-radius: 10px !important; border-radius : 10px !important;
border: 0px; border : 0px;
min-width: 120px; min-width : 120px;
padding: 6px; padding : 6px;
justify-content: center; justify-content : center;
align-items: center; align-items : center;
margin: 0px; margin : 0px;
height: 100%; height : 100%;
position: relative; position : relative;
font-size: 1.1em; font-size : 1.1em;
font-weight: 500; font-weight : 500;
&:before { &:before {
--dist: 1px; --dist : 1px;
content: ""; content : "";
position: absolute; position : absolute;
top: var(--dist); top : var(--dist);
left: var(--dist); left : var(--dist);
right: var(--dist); right : var(--dist);
bottom: var(--dist); bottom : var(--dist);
background-color: #fff; background-color: #fff;
opacity: 0; opacity : 0;
border-radius: 10px; border-radius : 10px;
transform: scale(0.5); transform : scale(0.5);
transition: transform 0.2s ease-in-out, opacity 0.2s ease-in-out; transition : transform 0.2s ease-in-out, opacity 0.2s ease-in-out;
} }
&:after { &:after {
@ -101,8 +103,8 @@
&:before { &:before {
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out; transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
opacity: 0.1; opacity : 0.1;
transform: scale(1); transform : scale(1);
} }
} }
@ -110,20 +112,188 @@
background-color: transparent; background-color: transparent;
&:before { &:before {
opacity: 0.2; opacity : 0.2;
transform: scale(1); transform: scale(1);
} }
} }
&.md-btn-primary { &.md-btn-primary {
box-shadow: 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8); box-shadow : 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8);
background-color: lighten(@baseColor, @colorMixRate * 5); background-color: lighten(@baseColor, @colorMixRate * 5);
z-index: 1; z-index : 1;
} }
} }
} }
} }
.nowplaying-page {
position : absolute;
bottom : 0;
left : 0;
right : 0;
width : 100%;
height : calc(100% - var(--chromeHeight1));
/* background-color: white; */
}
.nowplaying-row {
display : flex;
flex-direction : row;
justify-content: center;
align-items : center;
height : 100%;
width : 100%;
/* margin-top : calc(var(--chromeHeight1) * -1); */
}
.nowplaying-row>.artwork-col {
flex : 35%;
margin-top: calc(var(--chromeHeight1) * -1);
}
.nowplaying-row>.right-col {
flex : 65%;
height : 100%;
justify-content: center;
align-items : center;
display : flex;
}
.nowplaying-row>.right-col>.lyrics-col {
height: 90%;
width : 100%;
}
.nowplaying-row>.right-col>.lyrics-col>.lyric-body {
padding-top: 25vh !important;
}
.mediaitem-artwork {
border-radius: 1rem;
box-shadow : 0 0 25px rgba(0, 0, 0, 0.5);
}
.playback-info {
padding : 1rem;
color : #fff;
display : flex;
justify-content: center;
align-items : center;
flex-direction : column;
opacity : 1;
z-index : 2;
}
.song-name {
font-weight : bold;
opacity : 1;
display : flex;
flex-direction: row;
position : relative;
}
.song-artist {
opacity: 0.65;
}
.controls-parents {
display : flex;
position : fixed;
bottom : 0;
left : 0;
right : 0;
height : 15vh;
/* background-color: #fff; */
justify-content : center;
align-items : center;
flex-direction : column;
}
.controls-parents>.song-progress {
width : calc(100% - 6rem);
position: relative;
}
.controls-parents>.song-progress:hover .song-duration {
display : flex !important;
font-size : 12px;
opacity : 0.8;
margin-top: 0.5rem;
left : 0.25rem;
right : 0.25rem;
position : absolute;
}
.controls-parents>.song-progress>input {
--songProgressBackground: rgba(255, 255, 255, 0.25);
width : 100%;
border-radius : 100vmax;
appearance : none;
height : 0.5rem;
margin : 0;
transition : all 0.2s ease-in-out;
}
.controls-parents>.song-progress>input::-webkit-slider-thumb {
-webkit-appearance: none;
height : 0.5rem;
width : 1px;
border-radius : 0;
background : rgba(255, 255, 255, 0.75);
cursor : default;
}
.controls-parents .control-buttons {
display : flex;
flex-direction: row;
margin-block : 1rem;
}
.loadbar-sound,
.loadbar-sound::after,
.loadbar-sound::before {
animation : load-bar 1.3s ease infinite alternate;
box-sizing: border-box;
width : 2.5px;
height : 75%;
box-shadow: inset 0 -12px 0;
}
.loadbar-sound {
position : absolute;
transform : scale(var(--load-bar, 1));
color : var(--textColorLight);
display : flex;
margin-left: -15px;
}
.loadbar-sound::after,
.loadbar-sound::before {
content : "";
position: absolute;
bottom : 0;
}
.loadbar-sound::before {
left : -4.5px;
animation-delay: -2.4s;
}
.loadbar-sound::after {
right : -4.2px;
animation-delay: -3.7s;
}
div.volume {
display : flex;
width : 100%;
justify-content: flex-end;
}
.volume>.input-container {
width: 120px !important;
}
.fs-row { .fs-row {
flex-grow: 0.5; flex-grow: 0.5;
} }
@ -154,30 +324,30 @@
display: flex; display: flex;
.slider { .slider {
width: 100%; width : 100%;
z-index: 1; z-index: 1;
} }
.input-container { .input-container {
display: flex; display : flex;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
width: 100%; width : 100%;
} }
.volume-button--small { .volume-button--small {
border-radius: 6px; border-radius : 6px;
color: inherit; color : inherit;
background-size: 16px; background-size : 16px;
background-repeat: no-repeat; background-repeat : no-repeat;
background-position: center; background-position: center;
background-color: transparent; background-color : transparent;
height: 15px; height : 15px;
width: 30px; width : 30px;
border: 0px; border : 0px;
box-shadow: unset; box-shadow : unset;
opacity: 0.7; opacity : 0.7;
background-image: url("./assets/feather/volume-2.svg"); background-image : url("./assets/feather/volume-2.svg");
} }
.volume-button--small:active { .volume-button--small:active {
@ -190,52 +360,52 @@
input[type="range"] { input[type="range"] {
-webkit-appearance: none; -webkit-appearance: none;
height: 4px; height : 4px;
background: rgba(255, 255, 255, 0.4); background : rgba(255, 255, 255, 0.4);
border-radius: 5px; border-radius : 5px;
background-size: 70% 100%; background-size : 70% 100%;
background-repeat: no-repeat; background-repeat : no-repeat;
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
height: 14px; height : 14px;
width: 14px; width : 14px;
border-radius: 50%; border-radius : 50%;
background: rgb(50 50 50); background : rgb(50 50 50);
cursor: default; cursor : default;
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.4); box-shadow : inset 0px 0px 0px 1px rgba(255, 255, 255, 0.4);
transition: all var(--appleTransition); transition : all var(--appleTransition);
} }
&::-webkit-slider-thumb:hover { &::-webkit-slider-thumb:hover {
background-image: radial-gradient(var(--songProgressColor) 2px, transparent 3px, transparent 10px); background-image: radial-gradient(var(--songProgressColor) 2px, transparent 3px, transparent 10px);
transform: scale(1.2); transform : scale(1.2);
} }
&::-webkit-slider-thumb:active { &::-webkit-slider-thumb:active {
background-image: radial-gradient(var(--songProgressColor) 3px, transparent 4px, transparent 10px); background-image: radial-gradient(var(--songProgressColor) 3px, transparent 4px, transparent 10px);
transform: scale(1); transform : scale(1);
} }
&::-webkit-slider-runnable-track { &::-webkit-slider-runnable-track {
-webkit-appearance: none; -webkit-appearance: none;
box-shadow: none; box-shadow : none;
border: none; border : none;
background: transparent; background : transparent;
} }
} }
} }
.background { .background {
position: absolute; position : absolute;
background-size: cover; background-size: cover;
width: 100%; width : 100%;
height: 100%; height : 100%;
.bgArtworkMaterial { .bgArtworkMaterial {
position: absolute; position: absolute;
width: 100%; width : 100%;
height: 100%; height : 100%;
.bg-artwork-container { .bg-artwork-container {
z-index: unset; z-index: unset;
@ -248,11 +418,11 @@
} }
.lyrics-col { .lyrics-col {
height: 62vh; height : 62vh;
display: flex; display : flex;
justify-content: center; justify-content: center;
align-content: center; align-content : center;
width: 80%; width : 80%;
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
box-shadow: unset; box-shadow: unset;
@ -263,9 +433,9 @@
} }
.no-lyrics { .no-lyrics {
width: 100%; width : 100%;
height: 100%; height : 100%;
display: flex; display : flex;
justify-content: center; justify-content: center;
} }
@ -275,14 +445,14 @@
} }
.queue-col { .queue-col {
width: 60vh; width : 60vh;
height: 62vh; height: 62vh;
.queue-title { .queue-title {
opacity: 0.6; opacity: 0.6;
} }
.queue-panel > * { .queue-panel>* {
z-index: 3; z-index: 3;
} }
@ -296,55 +466,55 @@
} }
.tab-toggles { .tab-toggles {
display: flex; display : flex;
position: absolute; position : absolute;
bottom: 0; bottom : 0;
right: 0; right : 0;
width: 15vh; width : 15vh;
height: 5vh; height : 5vh;
justify-content: space-evenly; justify-content: space-evenly;
.volume { .volume {
background-image: url("./assets/feathers/volume.svg"); background-image : url("./assets/feathers/volume.svg");
padding: 0.5vh; padding : 0.5vh;
width: 2vh; width : 2vh;
height: 2vh; height : 2vh;
background-origin: content-box; background-origin: content-box;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.queue { .queue {
background-image: url("./assets/list.svg"); background-image : url("./assets/list.svg");
padding: 0.5vh; padding : 0.5vh;
width: 2.5vh; width : 2.5vh;
height: 2.5vh; height : 2.5vh;
background-origin: content-box; background-origin: content-box;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.lyrics { .lyrics {
background-image: url("./assets/quote-right.svg"); background-image : url("./assets/quote-right.svg");
padding: 0.5vh; padding : 0.5vh;
width: 2.5vh; width : 2.5vh;
height: 2.5vh; height : 2.5vh;
background-origin: content-box; background-origin: content-box;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.active { .active {
background-color: rgba(200, 200, 200, 0.7); background-color: rgba(200, 200, 200, 0.7);
border-radius: 3px; border-radius : 3px;
} }
} }
.artwork-col { .artwork-col {
justify-content: center; justify-content: center;
align-items: center; align-items : center;
display: flex; display : flex;
flex-direction: column; flex-direction : column;
.artwork { .artwork {
width: 50vh; width : 50vh;
height: 50vh; height: 50vh;
} }
@ -353,130 +523,131 @@
} }
.app-playback-controls { .app-playback-controls {
.song-artist, .song-artist,
.song-name { .song-name {
font-weight: 600; font-weight : 600;
text-align: center; text-align : center;
font-size: 0.9em; font-size : 0.9em;
height: 1.2em; height : 1.2em;
line-height: 0.9em; line-height : 0.9em;
overflow: hidden; overflow : hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 360px; max-width : 360px;
.song-name-normal { .song-name-normal {
height: inherit; height: inherit;
} }
&.song-artist-marquee { &.song-artist-marquee {
> marquee { >marquee {
//margin-bottom: -3px; //margin-bottom: -3px;
} }
} }
} }
.song-artist { .song-artist {
font-size: 0.875em; font-size : 0.875em;
font-weight: 400; font-weight: 400;
} }
.song-name { .song-name {
width: unset !important; width : unset !important;
margin-top: 0.15vh; margin-top : 0.15vh;
display: -webkit-box; display : -webkit-box;
line-height: 1.2; line-height : 1.2;
text-overflow: ellipsis; text-overflow: ellipsis;
text-align: center; text-align : center;
} }
} }
.app-playback-controls .playback-info { .app-playback-controls .playback-info {
margin-top: 0.5vh; margin-top : 0.5vh;
width: 100%; width : 100%;
display: flex; display : flex;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
flex-direction: column; flex-direction : column;
position: relative; position : relative;
input[type="range"] { input[type="range"] {
width: 100%; width: 100%;
} }
> div { >div {
width: 100%; width : 100%;
text-align: center; text-align: center;
} }
} }
.app-playback-controls .song-progress { .app-playback-controls .song-progress {
@bgColor: transparent; @bgColor : transparent;
//height: 16px; //height: 16px;
position: absolute; position : absolute;
bottom: -1.5vh; bottom : -1.5vh;
left: 0px; left : 0px;
background: @bgColor; background: @bgColor;
.song-duration p { .song-duration p {
font-weight: 400; font-weight: 400;
font-size: 10px; font-size : 10px;
height: 1.2em; height : 1.2em;
line-height: 1.3em; line-height: 1.3em;
overflow: hidden; overflow : hidden;
margin: 0 0 0 0.25em; margin : 0 0 0 0.25em;
} }
&:hover { &:hover {
> input[type="range"] { >input[type="range"] {
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
opacity: 1; opacity : 1;
transform: scale(1); transform: scale(1);
z-index: 1; z-index : 1;
} }
} }
} }
input[type="range"] { input[type="range"] {
appearance: none; appearance : none;
width: 100%; width : 100%;
height: 4px; height : 4px;
background-color: rgb(200 200 200 / 10%); background-color: rgb(200 200 200 / 10%);
border-radius: 2px; border-radius : 2px;
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
opacity: 0; opacity : 0;
transform: scale(0.5); transform : scale(0.5);
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance : none;
width: 12px; width : 12px;
height: 12px; height : 12px;
border-radius: 100%; border-radius : 100%;
background: var(--songProgressColor); background : var(--songProgressColor);
cursor: default; cursor : default;
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase); transition : opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
} }
&::-moz-range-thumb { &::-moz-range-thumb {
width: 8px; width : 8px;
height: 8px; height : 8px;
border-radius: 100%; border-radius: 100%;
background: var(--songProgressColor); background : var(--songProgressColor);
cursor: default; cursor : default;
} }
} }
} }
.control-buttons { .control-buttons {
margin-top: 2vh; margin-top : 2vh;
display: inline-flex; display : inline-flex;
width: 100%; width : 100%;
justify-content: center; justify-content: center;
align-items: center; align-items : center;
} }
} }
.cd-mediaitem-square { .cd-mediaitem-square {
font-size: 17px; font-size : 17px;
font-weight: 500; font-weight: 500;
} }
@ -489,12 +660,12 @@
} }
.cd-mediaitem-list-item .title { .cd-mediaitem-list-item .title {
font-size: 1.2em; font-size : 1.2em;
font-weight: 450; font-weight: 450;
} }
.cd-mediaitem-list-item .subtitle { .cd-mediaitem-list-item .subtitle {
font-size: 1.1em; font-size : 1.1em;
font-weight: 380; font-weight: 380;
} }
@ -503,7 +674,7 @@
} }
.cd-mediaitem-list-item .artwork { .cd-mediaitem-list-item .artwork {
width: 50px; width : 50px;
height: 50px; height: 50px;
} }
@ -524,33 +695,33 @@
} }
.header-text { .header-text {
font-size: 3em; font-size : 3em;
height: 3em; height : 3em;
padding-left: 0.2em; padding-left: 0.2em;
} }
.grouping-container .grouping-btn { .grouping-container .grouping-btn {
font-size: 1.3em; font-size : 1.3em;
color: var(--textColor); color : var(--textColor);
background-color: var(--sidebarColor); background-color: var(--sidebarColor);
font-weight: 600; font-weight : 600;
padding: 32px; padding : 32px;
//box-shadow: var(--ciderShadow-Generic); //box-shadow: var(--ciderShadow-Generic);
} }
.content-inner.playlist-page { .content-inner.playlist-page {
display: flex; display : flex;
flex-direction: row; flex-direction: row;
} }
.playlist-page .playlist-display { .playlist-page .playlist-display {
width: 100%; width : 100%;
max-width: 500px; max-width : 500px;
flex: 1; flex : 1;
text-align: center; text-align: center;
.playlistInfo { .playlistInfo {
> .row { >.row {
justify-content: center; justify-content: center;
} }
} }
@ -561,13 +732,15 @@
} }
} }
} }
.playlist-page .mediaContainer { .playlist-page .mediaContainer {
width: 30vh; width : 30vh;
height: 30vh; height : 30vh;
aspect-ratio: 1; aspect-ratio: 1;
} }
.playlist-page .playlist-display .playlistInfo .playlist-info { .playlist-page .playlist-display .playlistInfo .playlist-info {
gap: 16px; gap : 16px;
margin-top: 40px; margin-top: 40px;
} }
@ -580,8 +753,8 @@
} }
.artist-page .artist-image { .artist-page .artist-image {
width: 20vh; width : 20vh;
height: 20vh; height : 20vh;
aspect-ratio: 1; aspect-ratio: 1;
} }
@ -592,4 +765,4 @@
.playlist-page .playlist-body { .playlist-page .playlist-body {
flex: 1; flex: 1;
} }
} }

View file

@ -0,0 +1,259 @@
<script type="text/x-template" id="fullscreen-view">
<div class="fullscreen-view" tabindex="0">
<div class="background">
<div class="bgArtworkMaterial">
<div class="bg-artwork-container">
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork a"
:src="(image ?? '').replace('{w}','30').replace('{h}','30')">
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork b"
:src="(image ?? '').replace('{w}','30').replace('{h}','30')">
<img v-if="!(app.cfg.visual.bg_artwork_rotation && app.animateBackground)"
class="bg-artwork no-animation" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
</div>
</div>
</div>
<div class="fs-header" v-if="immersiveEnabled">
<div class="top-nav-group">
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('home.title')"
svg-icon="./assets/feather/home.svg" svg-icon-name="home" page="home">
</sidebar-library-item>
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('term.listenNow')"
svg-icon="./assets/feather/play-circle.svg" svg-icon-name="listenNow"
page="listen_now"></sidebar-library-item>
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('term.browse')"
svg-icon="./assets/feather/globe.svg" svg-icon-name="browse" page="browse">
</sidebar-library-item>
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('term.radio')"
svg-icon="./assets/feather/radio.svg" svg-icon-name="radio" page="radio">
</sidebar-library-item>
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('term.library')"
svg-icon="./assets/feather/radio.svg" svg-icon-name="library" page="library">
</sidebar-library-item>
<sidebar-library-item @click.native="tabMode = ''" :name="$root.getLz('term.nowPlaying')"
svg-icon="./assets/play.svg" svg-icon-name="nowPlaying" page="nowPlaying">
</sidebar-library-item>
<sidebar-library-item @click.native="tabMode = 'catalog'" name="" svg-icon="./assets/search.svg"
svg-icon-name="search" page="search">
</sidebar-library-item>
</div>
</div>
<div class="row fs-row" v-if="tabMode != 'catalog'">
<div class="col artwork-col">
<div class="artwork" @click="app.fullscreen(false)">
<mediaitem-artwork
:size="600"
:video="video"
:videoPriority="true"
:url="(image ?? '').replace('{w}','600').replace('{h}','600')"
></mediaitem-artwork>
</div>
<div class="controls-parents">
<template v-if="app.mkReady()">
<div class="app-playback-controls" @mouseover="app.chrome.progresshover = true"
@mouseleave="app.chrome.progresshover = false" @contextmenu="app.nowPlayingContextMenu">
<div class="playback-info">
<div class="song-name">
{{ app.mk.nowPlayingItem["attributes"]["name"] }}
</div>
<div
style="display: inline-block; -webkit-box-orient: horizontal; white-space: nowrap; margin-top: 0.25vh; overflow: hidden;">
<div class="item-navigate song-artist" style="display: inline-block;"
@click="app.getNowPlayingItemDetailed(`artist`) && app.fullscreen(false)">
{{ app.mk.nowPlayingItem["attributes"]["artistName"] }}
</div>
<div class="song-artist" style="display: inline-block;">
{{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ? " — " : "" }}
</div>
<div class="song-artist item-navigate" style="display: inline-block;"
@click="app.getNowPlayingItemDetailed('album') && app.fullscreen(false)">
{{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ?
(app.mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
</div>
</div>
<div class="song-progress">
<div class="song-duration" style="justify-content: space-between; height: 1px;"
:style="[app.chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
<p style="width: auto">{{ app.convertTime(app.getSongProgress()) }}</p>
<p style="width: auto">{{ app.convertTime(app.mk.currentPlaybackDuration) }}</p>
</div>
<input type="range" step="0.01" min="0" :style="app.progressBarStyle()"
@input="app.playerLCD.desiredDuration = $event.target.value;app.playerLCD.userInteraction = true"
@mouseup="app.mk.seekToTime($event.target.value);app.playerLCD.desiredDuration = 0;app.playerLCD.userInteraction = false"
:max="app.mk.currentPlaybackDuration" :value="app.getSongProgress()">
</div>
</div>
<div class="control-buttons">
<div class="app-chrome-item display--large">
<button class="playback-button--small shuffle" v-if="$root.mk.shuffleMode == 0"
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')"
v-b-tooltip.hover></button>
<button class="playback-button--small shuffle active" v-else
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.shuffleMode = 0"
:title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button previous" @click="$root.prevButton()"
:class="$root.isPrevDisabled() && 'disabled'"
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button stop" @click="$root.mk.stop()"
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
<button class="playback-button pause" @click="$root.mk.pause()"
v-else-if="$root.mk.isPlaying"
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
<button class="playback-button play" @click="$root.mk.play()" v-else
:title="$root.getLz('term.play')"
v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button next" @click="$root.skipToNextItem()"
:class="$root.isNextDisabled() && 'disabled'"
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button--small repeat" v-if="$root.mk.repeatMode == 0"
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.repeatMode = 1"
:title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 1"
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat active"
@click="$root.mk.repeatMode = 0"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 2"
:title="$root.getLz('term.disableRepeat')"
v-b-tooltip.hover></button>
</div>
</div>
</div>
<div class="app-chrome-item volume display--large">
<div class="input-container">
<button class="volume-button--small volume" @click="app.muteButtonPressed()"
:class="{'active': app.cfg.audio.volume == 0}"
:title="app.cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')"
v-b-tooltip.hover></button>
<input type="range" class="slider" @wheel="app.volumeWheel"
:step="app.cfg.audio.volumeStep" min="0" :max="app.cfg.audio.maxVolume"
v-model="app.mk.volume"
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()"
v-b-tooltip.hover :title="$root.formatVolumeTooltip()">
</div>
</div>
</div>
</template>
</div>
<div class="col right-col" v-if="tabMode != ''">
<!-- <div class="fs-info">
<div>Name</div>
<div>Name</div>
<div>Name</div>
</div> -->
<div class="lyrics-col" v-if="tabMode == 'lyrics'">
<lyrics-view :yoffset="120" :time="time" :lyrics="lyrics"
:richlyrics="richlyrics"></lyrics-view>
</div>
<div class="queue-col" v-if="tabMode == 'queue'">
<cider-queue v-if="tabMode == 'queue'" ref="queue"></cider-queue>
</div>
</div>
</div>
<div class="app-content-container" v-else>
<app-content-area></app-content-area>
</div>
<div class="tab-toggles">
<div class="lyrics" :class="{active: tabMode == 'lyrics'}"
@click="tabMode = (tabMode == 'lyrics') ? '' : 'lyrics'"></div>
<div class="queue" :class="{active: tabMode == 'queue'}"
@click="tabMode = (tabMode == 'queue') ? '' :'queue'"></div>
<div class="queue" :class="{active: tabMode == 'catalog'}"
v-if="false"
@click="tabMode = (tabMode == 'catalog') ? '' :'catalog'"></div>
</div>
</div>
</script>
<script>
Vue.component('fullscreen-view', {
template: '#fullscreen-view',
props: {
time: {
type: Number,
required: false
},
lyrics: {
type: Array,
required: false
},
richlyrics: {
type: Array,
required: false
},
image: {
type: String,
required: false
},
},
data: function() {
return {
app: this.$root,
tabMode: "lyrics",
video: null,
immersiveEnabled: app.cfg.advanced.experiments.includes("immersive-preview")
}
},
async mounted() {
if (app.mk.nowPlayingItem._container.type == "albums") {
try {
const result = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${app.mk.nowPlayingItem._container.type}/${app.mk.nowPlayingItem._container.id}`, {
"fields": "editorialArtwork,editorialVideo",
})).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
if (result) {
this.video = result
} else {
this.video = null
}
} catch (e) {
this.video = null
e = null
}
} else if (app.mk.nowPlayingItem._container.type == "library-albums") {
try {
const result = (await app.mk.api.v3.music(`/v1/me/library/albums/${app.mk.nowPlayingItem._container.id}/catalog`
, { "fields": "editorialArtwork,editorialVideo" })).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
if (result) {
this.video = result
} else {
this.video = null
}
} catch (e) {
e = null
this.video = null
}
}
},
beforeMount() {
window.addEventListener('keyup', this.onEscapeKeyUp);
},
beforeDestroy() {
window.removeEventListener('keyup', this.onEscapeKeyUp)
},
methods: {
onEscapeKeyUp(event) {
if (event.which === 27) {
app.fullscreen(false);
console.log('js')
}
},
}
});
</script>

View file

@ -1,17 +1,5 @@
<script type="text/x-template" id="fullscreen-view"> <script type="text/x-template" id="fullscreen-view">
<div class="fullscreen-view" tabindex="0"> <div class="fullscreen-view" tabindex="0">
<div class="background">
<div class="bgArtworkMaterial">
<div class="bg-artwork-container">
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork a"
:src="(image ?? '').replace('{w}','30').replace('{h}','30')">
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork b"
:src="(image ?? '').replace('{w}','30').replace('{h}','30')">
<img v-if="!(app.cfg.visual.bg_artwork_rotation && app.animateBackground)"
class="bg-artwork no-animation" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
</div>
</div>
</div>
<div class="fs-header" v-if="immersiveEnabled"> <div class="fs-header" v-if="immersiveEnabled">
<div class="top-nav-group"> <div class="top-nav-group">
<sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('home.title')" <sidebar-library-item @click.native="tabMode = 'catalog'" :name="$root.getLz('home.title')"
@ -37,223 +25,210 @@
</sidebar-library-item> </sidebar-library-item>
</div> </div>
</div> </div>
<div class="row fs-row" v-if="tabMode != 'catalog'"> <div class="nowplaying-page">
<div class="col artwork-col"> <div class="background">
<div class="artwork" @click="app.fullscreen(false)"> <div class="bgArtworkMaterial">
<mediaitem-artwork <div class="bg-artwork-container">
:size="600" <img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork a"
:video="video" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
:videoPriority="true" <img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork b"
:src="(image ?? '').replace('{w}','30').replace('{h}','30')">
<img v-if="!(app.cfg.visual.bg_artwork_rotation && app.animateBackground)"
class="bg-artwork no-animation" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
</div>
</div>
</div>
<div class="row nowplaying-row" v-if="tabMode != 'catalog'">
<div class="col artwork-col">
<div class="artwork" @click="app.fullscreen(false)">
<mediaitem-artwork :size="600" :video="video" :videoPriority="true"
:url="(image ?? '').replace('{w}','600').replace('{h}','600')" :url="(image ?? '').replace('{w}','600').replace('{h}','600')"
></mediaitem-artwork> ></mediaitem-artwork>
</div> </div>
<div class="controls-parents"> <div class="playback-info">
<template v-if="app.mkReady()">
<div class="app-playback-controls" @mouseover="app.chrome.progresshover = true" <div class="song-name">
@mouseleave="app.chrome.progresshover = false" @contextmenu="app.nowPlayingContextMenu"> <div class="loadbar-sound" v-if="app.mk.isPlaying"></div>
<div class="playback-info"> {{ app.mk.nowPlayingItem["attributes"]["name"] }}
<div class="song-name"> </div>
{{ app.mk.nowPlayingItem["attributes"]["name"] }} <div
</div> style="display: inline-block; -webkit-box-orient: horizontal; white-space: nowrap; margin-top: 0.25vh; overflow: hidden;">
<div <div class="item-navigate song-artist" style="display: inline-block;"
style="display: inline-block; -webkit-box-orient: horizontal; white-space: nowrap; margin-top: 0.25vh; overflow: hidden;"> @click="app.getNowPlayingItemDetailed(`artist`) && app.fullscreen(false)">
<div class="item-navigate song-artist" style="display: inline-block;" {{ app.mk.nowPlayingItem["attributes"]["artistName"] }}
@click="app.getNowPlayingItemDetailed(`artist`) && app.fullscreen(false)">
{{ app.mk.nowPlayingItem["attributes"]["artistName"] }}
</div>
<div class="song-artist" style="display: inline-block;">
{{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ? " — " : "" }}
</div>
<div class="song-artist item-navigate" style="display: inline-block;"
@click="app.getNowPlayingItemDetailed('album') && app.fullscreen(false)">
{{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ?
(app.mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
</div>
</div>
<div class="song-progress">
<div class="song-duration" style="justify-content: space-between; height: 1px;"
:style="[app.chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
<p style="width: auto">{{ app.convertTime(app.getSongProgress()) }}</p>
<p style="width: auto">{{ app.convertTime(app.mk.currentPlaybackDuration) }}</p>
</div>
<input type="range" step="0.01" min="0" :style="app.progressBarStyle()"
@input="app.playerLCD.desiredDuration = $event.target.value;app.playerLCD.userInteraction = true"
@mouseup="app.mk.seekToTime($event.target.value);app.playerLCD.desiredDuration = 0;app.playerLCD.userInteraction = false"
:max="app.mk.currentPlaybackDuration" :value="app.getSongProgress()">
</div>
</div> </div>
<div class="control-buttons"> <div class="song-artist" style="display: inline-block;">
<div class="app-chrome-item display--large"> {{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ? " — " : "" }}
<button class="playback-button--small shuffle" v-if="$root.mk.shuffleMode == 0" </div>
:class="$root.isDisabled() && 'disabled'" <div class="song-artist item-navigate" style="display: inline-block;"
@click="$root.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')" @click="app.getNowPlayingItemDetailed('album') && app.fullscreen(false)">
v-b-tooltip.hover></button> {{ (app.mk.nowPlayingItem["attributes"]["albumName"]) ?
<button class="playback-button--small shuffle active" v-else (app.mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.shuffleMode = 0"
:title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button previous" @click="$root.prevButton()"
:class="$root.isPrevDisabled() && 'disabled'"
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button stop" @click="$root.mk.stop()"
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
<button class="playback-button pause" @click="$root.mk.pause()"
v-else-if="$root.mk.isPlaying"
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
<button class="playback-button play" @click="$root.mk.play()" v-else
:title="$root.getLz('term.play')"
v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button next" @click="$root.skipToNextItem()"
:class="$root.isNextDisabled() && 'disabled'"
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button--small repeat" v-if="$root.mk.repeatMode == 0"
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.repeatMode = 1"
:title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 1"
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat active"
@click="$root.mk.repeatMode = 0"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 2"
:title="$root.getLz('term.disableRepeat')"
v-b-tooltip.hover></button>
</div>
</div> </div>
</div> </div>
<div class="app-chrome-item volume display--large"> </div>
<div class="input-container"> </div>
<button class="volume-button--small volume" @click="app.muteButtonPressed()" <div class="col right-col" v-if="tabMode != ''">
:class="{'active': app.cfg.audio.volume == 0}" <div class="lyrics-col" v-if="tabMode == 'lyrics'">
:title="app.cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')" <lyrics-view :yoffset="120" :time="time" :lyrics="lyrics" :richlyrics="richlyrics"></lyrics-view>
v-b-tooltip.hover></button> </div>
<input type="range" class="slider" @wheel="app.volumeWheel" </div>
:step="app.cfg.audio.volumeStep" min="0" :max="app.cfg.audio.maxVolume" </div>
v-model="app.mk.volume" <div class="controls-parents">
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()" <div class="song-progress">
v-b-tooltip.hover :title="$root.formatVolumeTooltip()"> <div class="song-duration" style="justify-content: space-between; height: 1px;"
</div> :style="[app.chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
<p style="width: auto">{{ app.convertTime(app.getSongProgress()) }}</p>
<p style="width: auto">{{ app.convertTime(app.mk.currentPlaybackDuration) }}</p>
</div>
<input type="range" step="0.01" min="0" :style="app.progressBarStyle()"
@input="app.playerLCD.desiredDuration = $event.target.value;app.playerLCD.userInteraction = true"
@mouseup="app.mk.seekToTime($event.target.value);app.playerLCD.desiredDuration = 0;app.playerLCD.userInteraction = false"
:max="app.mk.currentPlaybackDuration" :value="app.getSongProgress()">
</div>
<div class="control-buttons">
<div class="app-chrome-item display--large">
<button class="playback-button--small shuffle" v-if="$root.mk.shuffleMode == 0"
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')"
v-b-tooltip.hover></button>
<button class="playback-button--small shuffle active" v-else
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.shuffleMode = 0"
:title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button previous" @click="$root.prevButton()"
:class="$root.isPrevDisabled() && 'disabled'"
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button stop" @click="$root.mk.stop()"
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
<button class="playback-button pause" @click="$root.mk.pause()"
v-else-if="$root.mk.isPlaying"
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
<button class="playback-button play" @click="$root.mk.play()" v-else
:title="$root.getLz('term.play')"
v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button next" @click="$root.skipToNextItem()"
:class="$root.isNextDisabled() && 'disabled'"
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button--small repeat" v-if="$root.mk.repeatMode == 0"
:class="$root.isDisabled() && 'disabled'"
@click="$root.mk.repeatMode = 1"
:title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 1"
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
<button class="playback-button--small repeat active"
@click="$root.mk.repeatMode = 0"
:class="$root.isDisabled() && 'disabled'"
v-else-if="$root.mk.repeatMode == 2"
:title="$root.getLz('term.disableRepeat')"
v-b-tooltip.hover></button>
</div>
<div class="app-chrome-item volume display--large">
<div class="input-container">
<button class="volume-button--small volume" @click="app.muteButtonPressed()"
:class="{'active': app.cfg.audio.volume == 0}"
:title="app.cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')"
v-b-tooltip.hover></button>
<input type="range" class="slider" @wheel="app.volumeWheel"
:step="app.cfg.audio.volumeStep" min="0" :max="app.cfg.audio.maxVolume"
v-model="app.mk.volume"
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()"
v-b-tooltip.hover :title="$root.formatVolumeTooltip()">
</div> </div>
</div>
</div> </div>
</template>
</div>
<div class="col right-col" v-if="tabMode != ''">
<!-- <div class="fs-info">
<div>Name</div>
<div>Name</div>
<div>Name</div>
</div> -->
<div class="lyrics-col" v-if="tabMode == 'lyrics'">
<lyrics-view :yoffset="120" :time="time" :lyrics="lyrics"
:richlyrics="richlyrics"></lyrics-view>
</div> </div>
<div class="queue-col" v-if="tabMode == 'queue'">
<cider-queue v-if="tabMode == 'queue'" ref="queue"></cider-queue>
</div>
</div>
</div>
<div class="app-content-container" v-else>
<app-content-area></app-content-area>
</div>
<div class="tab-toggles">
<div class="lyrics" :class="{active: tabMode == 'lyrics'}"
@click="tabMode = (tabMode == 'lyrics') ? '' : 'lyrics'"></div>
<div class="queue" :class="{active: tabMode == 'queue'}"
@click="tabMode = (tabMode == 'queue') ? '' :'queue'"></div>
<div class="queue" :class="{active: tabMode == 'catalog'}"
v-if="false"
@click="tabMode = (tabMode == 'catalog') ? '' :'catalog'"></div>
</div> </div>
</div> </div>
</script> </script>
<style scoped>
</style>
<script> <script>
Vue.component('fullscreen-view', { Vue.component('fullscreen-view', {
template: '#fullscreen-view', template: '#fullscreen-view',
props: { props: {
time: { time: {
type: Number, type: Number,
required: false required: false
}, },
lyrics: { lyrics: {
type: Array, type: Array,
required: false required: false
}, },
richlyrics: { richlyrics: {
type: Array, type: Array,
required: false required: false
}, },
image: { image: {
type: String, type: String,
required: false required: false
}, },
}, },
data: function() { data: function () {
return { return {
app: this.$root, app: this.$root,
tabMode: "lyrics", tabMode: "lyrics",
video: null, video: null,
immersiveEnabled: app.cfg.advanced.experiments.includes("immersive-preview") immersiveEnabled: app.cfg.advanced.experiments.includes("immersive-preview")
} }
}, },
async mounted() { async mounted() {
if (app.mk.nowPlayingItem._container.type == "albums") { if (app.mk.nowPlayingItem._container.type == "albums") {
try { try {
const result = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${app.mk.nowPlayingItem._container.type}/${app.mk.nowPlayingItem._container.id}`, { const result = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${app.mk.nowPlayingItem._container.type}/${app.mk.nowPlayingItem._container.id}`, {
"fields": "editorialArtwork,editorialVideo", "fields": "editorialArtwork,editorialVideo",
})).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video })).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
if (result) { if (result) {
this.video = result this.video = result
} else { } else {
this.video = null this.video = null
} }
} catch (e) { } catch (e) {
this.video = null this.video = null
e = null e = null
}
} else if (app.mk.nowPlayingItem._container.type == "library-albums") {
try {
const result = (await app.mk.api.v3.music(`/v1/me/library/albums/${app.mk.nowPlayingItem._container.id}/catalog`
, { "fields": "editorialArtwork,editorialVideo" })).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
if (result) {
this.video = result
} else {
this.video = null
}
} catch (e) {
e = null
this.video = null
}
}
},
beforeMount() {
window.addEventListener('keyup', this.onEscapeKeyUp);
},
beforeDestroy() {
window.removeEventListener('keyup', this.onEscapeKeyUp)
},
methods: {
onEscapeKeyUp(event) {
if (event.which === 27) {
app.fullscreen(false);
console.log('js')
}
},
} }
} else if (app.mk.nowPlayingItem._container.type == "library-albums") { });
try { </script>
const result = (await app.mk.api.v3.music(`/v1/me/library/albums/${app.mk.nowPlayingItem._container.id}/catalog`
, { "fields": "editorialArtwork,editorialVideo" })).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
if (result) {
this.video = result
} else {
this.video = null
}
} catch (e) {
e = null
this.video = null
}
}
},
beforeMount() {
window.addEventListener('keyup', this.onEscapeKeyUp);
},
beforeDestroy() {
window.removeEventListener('keyup', this.onEscapeKeyUp)
},
methods: {
onEscapeKeyUp(event) {
if (event.which === 27) {
app.fullscreen(false);
console.log('js')
}
},
}
});
</script>