This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
appcat
/
sonist
Archived
1
0
Fork 0

大重构

2.x
宇天 2020-11-16 19:38:44 +08:00
parent 6d5c72f235
commit df36541c70
43 changed files with 518 additions and 1014 deletions

File diff suppressed because one or more lines are too long

View File

@ -8,16 +8,30 @@
@import "./var.scss"; @import "./var.scss";
#app { .app {
position:relative;display:flex;flex-direction:column; position:relative;
width:100%;height:100%;background:linear-gradient(to bottom, #fff, nth($cp, 1)); display:flex;flex-direction:column;
width:100%;height:100%;
background:rgba(0, 0, 0, .2);
// //
.title-bar {position:relative;z-index:9;display:flex;height:5rem; .title-bar {
position:relative;
display:flex;
align-items:center;
z-index:9;
height:26px;
.btn-box {width:auto;height:3rem;padding:.9rem 0; .btn-box {
display:inline-flex;;
width:auto;height:12px;padding:0 8px;
.item {display:inline-block;width:1.2rem;height:1.2rem;margin:0 2rem;background:url(/images/btn-grey.svg) no-repeat;background-size:cover;} .item {
display:inline-flex;
width:12px;height:12px;
margin:0 3px;
background:url(/images/btn-grey.svg) no-repeat;background-size:cover;
}
&.focus { &.focus {
.quit {background-image:url(/images/btn-close.svg);} .quit {background-image:url(/images/btn-close.svg);}
@ -31,301 +45,294 @@
} }
} }
.btn-box-win {
width:auto;height:4rem;padding:.9rem 0;line-height:1.8rem;
.item,
.opt {position:relative;display:inline-block;width:2.2rem;height:2.2rem;margin:0 .2rem;padding:.2rem;font-size:1.6rem;
}
.item {text-align:center;
&:hover {background:rgba(0, 0, 0, .05);}
&.quit:hover {color:nth($cr, 1);}
&.disabled {color:nth($cp, 3);background:none}
}
.opt i {font-size:1.8rem;}
.opt-list {position:absolute;z-index:100;right:0;top:2.2rem;width:13rem;height:auto;padding:.8rem 0;background:#fff;box-shadow:0 .5rem 2rem rgba(0, 0, 0, .1);font-size:1.4rem;
span {display:flex;align-items:center;height:3rem;padding:0 2rem;line-height:3rem;
i {padding-right:.8rem;}
&.pipe {height:.1rem;margin:.5rem 0;border-bottom:.1rem solid nth($cp, 1)}
&:hover {background:nth($cp, 1)}
}
}
}
//
.holder {width:18rem;height:100%;}
.tools {flex:1;padding:1rem;
.search {display:flex;width:30rem;}
}
}
//
.main-body {overflow:hidden;;flex:1;display:flex;
//
.sidebar {width:18rem;position:relative;height:100%;
//
.music-box {width:100%;height:auto;padding:0 1.5rem;
dt.title {line-height:4rem;color:nth($cgr, 1)}
dd.item {height:3rem;margin:.3rem 0;padding:0 .8rem;line-height:3rem;color:nth($cgr, 3);
.icon {float:left;width:3rem;height:3rem;padding:0 .5rem;font-size:2.4rem;}
&:hover {padding-left:.9rem;color:nth($ct, 1);}
&.active {border-radius:.3rem;background:nth($ct, 1);color:#fff;}
&.disabled {opacity:.25}
}
}
}
//
.module {overflow:hidden;position:relative;flex:1;display:flex;height:100%;}
}
.contrl-bar {position:relative;z-index:99;display:flex;height:6.5rem;
//
.play-box {
display:flex;align-items:center;width:16rem;height:4.5rem;margin:1rem;padding:.5rem 1rem;border-radius:.75rem;background:#fff;box-shadow:0 .25rem 1rem rgba(0, 0, 0, .075);
.btn-bg {
position:absolute;
left:3.25rem;
height: 3.5rem;
border-left: 3.25rem solid nth($cp, 1);
border-top: .25rem solid transparent;
border-bottom: .25rem solid transparent;
&::before {position:absolute;left:-5rem;top:-.25rem;width:3.5rem;height:3.5rem;border-radius:50%;background:nth($cp, 1);content:""}
&::after {position:absolute;right:-1.5rem;top:0;width:3rem;height:3rem;border-radius:50%;background:nth($cp, 1);content:""}
}
.action {position:relative;display:flex;justify-content:center;align-items:center;
&.play {width:2.5rem;height:2.5rem;border-radius:50%;background:#fff;box-shadow:0 .25rem .5rem rgba(0, 0, 0, .2)}
&.next {width:2rem;height:2rem;margin-left:.75rem}
}
}
//
.stat-box {position:relative;flex:1;display:flex;justify-content:center;align-items:center;
.song-stat {flex:1;height:6.5rem;margin:0 2rem 0 0;
canvas {display:flex;width:100%;height:100%;}
}
.ctrl {position:relative;flex:0 1 3.5rem;height:3rem;line-height:3rem;text-align:center;color:nth($ct, 2);font-size:2rem;
&:hover {color:nth($ct, 1)}
&:active {color:nth($ct, 3)}
&.lrc {margin-right:2rem;font-size:1.6rem;}
.volume-ctrl {display:none;flex-direction:column;justify-content:flex-end;position:absolute;left:.5rem;bottom:3rem;width:2.4rem;height:12rem;padding:1rem .8rem;background:#fff;border-radius:.3rem;box-shadow:0 0 1rem rgba(0, 0, 0, .1);
em {flex:0 0;border-radius:.5rem;background:nth($ct, 1)}
}
&.volume:hover .volume-ctrl {display:flex}
}
}
}
//
&.blur {background:rgba(255, 255, 255, .85);backdrop-filter:blur(1rem);
.title-bar {
.holder {background:rgba(255, 255, 255, .3);}
.tools input {background:rgba(255, 255, 255, .8);}
} }
.main-body { .main-body {
overflow:hidden;
flex:1;
display: flex;
justify-content:space-between;
.sidebar {background:rgba(255, 255, 255, .3);} .aside {
width:180px;
height:100%;
padding:0 16px;
line-height:2;
fieldset {
border:0;
color:#ebebeb;
font-size:12px;
legend {
font-size:18px;
background:linear-gradient(to bottom,#58ffdf 50%, #459888);
background-clip:text;
color:transparent;
} }
.contrl-bar {background:rgba(255, 255, 255, .35)} .item {
padding-left:12px;
line-height:1.75;
} }
// ktv button {
&.ktv { width:42px;height:16px;
.contrl-bar {background:rgba(233, 233, 233, .1); margin-left:12px;
font-size:10px;
.play-box .item, border:0;
.stat-box .ctrl {color:#fff; border-radius:9px;
background:nth($cb, 1);
&:hover {color:nth($cr, 1)} color:#fff;
} }
} }
} }
.song-box {
width:618px;
.ktv-box { .preview {
overflow:hidden;position:absolute;z-index:80;left:0;top:0; position:relative;
width:100%;height:100%; display:flex;
background:nth($cd, 3);background-size:cover;background-repeat:no-repeat; align-items:center;
width:100%;
height:99px;
padding-bottom:16px;
border-bottom:1px solid rgba(200, 200, 200, .1);
.album {
width:80px;height:80px;
img {width:100%;height:100%;}
}
.info {
display:flex;
flex-direction:column;
justify-content:center;
width:320px;
margin-left:32px;
strong {
height:36px;
font-size:18px;
font-weight: normal;
}
cite {
font-size:12px;
font-style:normal;
}
p {font-size:12px;color:#bdbdbd;}
}
.duration {
position:absolute;
right:32px;
top:16px;
font-size:12px;
color:#bdbdbd;
}
.total {
position:absolute;
right:32px;
bottom:16px;
font-size:16px;
font-weight:bold;
font-family:Raleway;
}
}
.scroll-box {
width:100%;
height:269px;
padding:16px 6px;
border-top:1px solid rgba(32, 32, 32, .1);
}
.list {
height:237px;
font-size:12px;
.item {
display:flex;
align-items:center;
height:26px;
padding:0 12px;
border-radius:13px;
.idx {
position:relative;
width:64px;
padding-left:16px;
font-size:12px;
font-family:Raleway;
}
.name {
overflow:hidden;
flex:1;
}
.artist {
overflow:hidden;
width:128px;
margin-left:12px;
}
.duration {
width:42px;
margin-left:12px;
}
&.on {
color:#feac23;
font-size:14px;
.idx::before {
position:absolute;
left:0;top:3px;
font-size:10px;
content:"";
}
}
&.active, &:hover {
color:#58ffdf;
background: rgba(29, 77, 68, 0.15);
}
}
}
}
}
.play-bar {
height:66px;width:100%;
background:rgba(255, 255, 255, .25);
color:#fff; color:#fff;
.inner-content { .stat-bar {
display:flex;flex-flow:column wrap;width:100%;height:100%;padding-bottom:8rem;background:rgba(29, 35, 44, 0.767);backdrop-filter:blur(1rem); display:flex;
align-items:center;
justify-content:space-between;
height:20px;
color: #ebebeb;
.info {flex:1;display:flex;justify-content:center;align-items:center;padding:0 10rem;line-height:2; .time {
width:42px;
img {width:30rem;height:30rem;border:.5rem solid rgba(255, 255, 255, .5);border-radius:50%;} margin:0 6px;
.summary {flex:1; padding:0 5rem} text-align:center;
pre {overflow:auto;height:30rem} font-size:12px;
h3 {line-height:3;font-size:1.8rem;}
}
.lrc-box {flex:0 10rem;display:flex;flex-flow:column wrap;padding:0 5rem;line-height:5rem;color:#fff;font-size:3rem;
section {flex:1;display:flex;
&.left {justify-content:flex-start;}
&.right {justify-content:flex-end}
span {background-clip:text!important;color:transparent;}
} }
.progress {
flex:1;
display:flex;
align-items: flex-start;
height:3px;
background: #b2cfe3;
} }
.thumb {
.tool-box {position:absolute;right:0;top:15rem;width:13rem;height:auto;padding:1.5rem 0;background:rgba(255, 255, 255, .1);border-radius:.3rem 0 0 .3rem;opacity:.3;transform:translateX(8.8rem);@include ts(); width:8%;
height:3px;
.item {height:3.4rem;padding:0 .8rem;line-height:3.4rem; background:#58ffdf;
&:hover {background:rgba(255, 255, 255, .1);}
}
i {padding:0 1rem 0 .8rem}
&:hover {opacity:1;transform:translateX(0)}
}
.slide-down {position:absolute;right:1rem;top:1rem;width:3rem;height:2rem;line-height:1.8rem;border:.1rem solid nth($cgr, 1);border-radius:.3rem;text-align:center;
i {transform:rotate(90deg)}
}
.search-box {display:flex;justify-content:center;align-items:center;position:absolute;left:0;top:0;z-index:82;width:100%;height:56rem;background:rgba(29, 35, 44, 0.5);backdrop-filter:blur(.4rem);
.content {width:60rem;height:auto;padding:2rem;background:rgba(255, 255, 255, .8);color:nth($cd, 1);
.title {height:3rem;line-height:2rem;font-size:1.4rem;text-align:center;
i {float:right;font-size:2rem;color:nth($cr, 1);}
}
.section {height:3.5rem;
input {width:100%;}
}
.result {overflow-y:auto;width:100%;max-height:30rem;padding:1rem;background:rgba(255, 255, 255, .2);
.item {display:flex;justify-content:center;align-items:center;margin:.3rem 0;text-align:center;
&:nth-child(1) {line-height:2;border-bottom:.1rem solid nth($cgr, 1);}
span {flex:1;
&:nth-child(1) {flex:3}
} }
} }
.ctrl-box {
display:flex;
height:46px;
.holder {
flex:1;
} }
.info {
display:flex;
flex-direction:column;
justify-content:center;
width:320px;
height:42px;
padding-left:12px;
line-height:1.25;
strong {
font-size:14px;
font-weight: 500;
} }
cite {
font-size:12px;
font-style:normal;
color:#aeaeae;
}
} }
.play-btn {
display:flex;
align-items:center;
justify-content:space-between;
width:120px;
height:38px;
margin-left:32px;
text-align:center;
.item {
width:28px;height:28px;
line-height:28px;
border-radius:50%;
background:rgba(255, 255, 255, .1);
fill: currentColor;
cursor:pointer;
transition:color .1s ease-in-out;
&.on {
width:36px;height:36px;
line-height:36px;
font-size:16px;
} }
&:hover {
color: #58ffdf;
}
&:active {
color: #46d1b8;
}
}
} }
.play-action {
display:flex;
align-items:center;
justify-content:space-between;
width:64px;
height:38px;
margin-right:16px;
font-size:12px;
.loading { .item {
position:fixed;left:0;top:0;z-index:65536; width:28px;height:28px;
display:flex;justify-content:center;align-items:center; line-height:28px;
width:100%;height:100%; fill: currentColor;
transition:color .1s ease-in-out;
cursor:pointer;
.box {position:relative;display:flex;justify-content:center;align-items:center;width:8rem;height:8rem; &:hover {
color: #58ffdf;
i {position:absolute;width:8rem;height:8rem;border:3px solid nth($ct, 1);border-radius:50%;opacity:.5; }
&:nth-child(1) {animation:load 2.5s ease-in-out infinite;} &:active {
&:nth-child(2) {animation:load 2.5s .5s ease-in-out infinite;} color: #46d1b8;
&:nth-child(3) {animation:load 2.5s 1s ease-in-out infinite;} }
&:nth-child(4) {animation:load 2.5s 1.5s ease-in-out infinite;} }
&:nth-child(5) {animation:load 2.5s 2s ease-in-out infinite;}
} }
span {position:absolute;width:8rem;height:8rem;background:url(/images/load1.png) no-repeat center center;background-size:cover;
&:nth-child(6) {animation:play 1.5s linear infinite;}
&:nth-child(7) {background-image:url(/images/load2.png);animation:load2 2.5s linear infinite;}
} }
cite {font-size:2.4rem;}
} }
}
} }
.do-mod-contextmenu {width:145px;height:auto;padding:8px 0;line-height:35px;font-size:1.3rem;
li {overflow:hidden;width:100%;height:35px;padding:0 10px;@include ts(background);cursor:default;
&:hover {background:nth($cp, 1)}
i {padding:0 3px;font-size:1.6rem;vertical-align:bottom;}
}
}
.do-layer .layer-box.do-mod-contextmenu__fixed {padding:0}
@keyframes load {
from {opacity: .5; transform: scale(1)}
to {opacity: 0; transform: scale(1.5)}
}
@keyframes load2 {
from {transform:rotate(360deg)}
to {transform:rotate(0deg)}
}
@keyframes play {
from {transform:rotate(0deg)}
to {transform:rotate(360deg)}
}

View File

@ -1 +1 @@
.do-fn-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.do-fn-nodrag{-webkit-app-region:no-drag}html{font-size:1vw}body{position:fixed;left:0;top:0;width:100%;height:100%;line-height:1.5;font-size:1.4rem;color:#62778d}table{overflow:auto;display:table;width:100%;line-height:2.5rem}table thead tr{height:4.5rem;border-bottom:0.1rem solid rgba(200,200,200,0.15)}table thead th{padding:1rem .8rem;border:0}table tbody tr{height:auto;transition:background .3s ease-in-out}table tbody tr:hover{background:rgba(29,35,44,0.08)}table tbody td{padding:.9rem .8rem}table .ac{text-align:center}table .idx{color:#dae1e9;text-shadow:0 0.1rem 0 rgba(255,255,255,0.6)}table .active{color:#3fc2a7;background:rgba(255,255,255,0.6);font-weight:bold} .app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}body{position:fixed;left:0;top:0;width:100%;height:100%;line-height:1.5;font-size:14px;color:#fff}

View File

@ -8,20 +8,14 @@
@import "./var.scss"; @import "./var.scss";
.do-fn-drag {-webkit-app-region:drag;user-select: none;} .app-drag {-webkit-app-region:drag;user-select: none;}
.do-fn-nodrag {-webkit-app-region:no-drag;} .app-nodrag {-webkit-app-region:no-drag;}
html {font-size:1vw} body {
body {position:fixed;left:0;top:0;width:100%;height:100%;line-height:1.5;font-size:1.4rem;color:nth($cd, 1);} position:fixed;left:0;top:0;
width:100%;height:100%;
table {overflow:auto;display:table;width:100%;line-height:2.5rem; line-height:1.5;
thead tr {height:4.5rem;border-bottom:.1rem solid rgba(200, 200, 200, .15)} font-size:14px;
thead th {padding:1rem .8rem;border:0;} color:#fff;
tbody tr {height:auto;@include ts(background, .3s);
&:hover {background:rgba(29, 35, 44, .08);}
}
tbody td {padding:.9rem .8rem}
.ac {text-align:center}
.idx {color:nth($cp, 3);text-shadow:0 .1rem 0 rgba(255, 255, 255, 0.6)}
.active {color:nth($ct, 1);background:rgba(255, 255, 255, 0.6);font-weight:bold}
} }

View File

@ -39,22 +39,13 @@ a:focus,input,textarea,button:focus,input:focus,textarea:focus {outline:none;}
} }
body {font-family:Helvetica, Arial,"WenQuanYi Micro Hei","PingFang SC","Hiragino Sans GB","Segoe UI", "Microsoft Yahei", sans-serif;-webkit-font-smoothing: antialiased;text-size-adjust: 100%;-webkit-tap-highlight-color: transparent;} body {font-family:Helvetica, Arial,"WenQuanYi Micro Hei","PingFang SC","Hiragino Sans GB","Segoe UI", "Microsoft Yahei", sans-serif;-webkit-font-smoothing: antialiased;text-size-adjust: 100%;-webkit-tap-highlight-color: transparent;}
code,pre,samp {font-family:Menlo,Monaco,Consolas,"Courier New",monospace;} code,pre,samp {font-family:Menlo,Monaco,Consolas,"Courier New",monospace;}
[anot],[\:repeat],[\:if],[is-widget],slot {visibility:hidden;} [anot],[\:repeat],[\:if] {visibility:hidden;}
.do-fn-cl { *zoom: 1; }
.do-fn-cl::after { content: "."; display: block; height: 0; clear: both; visibility: hidden; overflow:hidden;}
.do-fn-clear {clear:both;display:inline;} .noselect {-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;user-select: none;}
.noselect img, .noselect a {-webkit-user-drag:none;}
.do-fn-show{display:block;} .text-ell {overflow:hidden; white-space:nowrap; text-overflow:ellipsis }
.do-fn-hide{display:none;} .osx-thin {-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
.do-fn-fl{float:left;}
.do-fn-fr{float:right;}
.do-fn-noselect {-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;user-select: none;}
.do-fn-noselect img, .do-fn-noselect a {-webkit-user-drag:none;}
.do-fn-ell {overflow:hidden; white-space:nowrap; text-overflow:ellipsis }
.do-st-thin {-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
.do-st-hand {cursor:pointer;}
[class^="do-icon-"], [class*=" do-icon-"] {display:inline-block;font-family:"uifont" !important;font-style:normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}

View File

@ -1,13 +1,17 @@
$ct: #3fc2a7 #19b491 #16967a; $ct: #4db6ac #26a69a #009688;
$cg: #58d68d #2ecc71 #27ae60; $cg: #81c784 #66bb6a #4caf50;
$cpp: #ac61ce #9b59b6 #8e44ad; $cpp: #9575cd #9575cd #673ab7;
$cb: #66b1ff #409eff #3a8ee6; $cb: #64b5f6 #42a5f5 #2196f3;
$cr: #ff5061 #eb3b48 #ce3742; $cr: #ff5061 #eb3b48 #ce3742;
$co: #ffb618 #f39c12 #e67e22; $co: #ffb618 #f39c12 #e67e22;
$cp: #f3f5fb #e8ebf4 #dae1e9; $cp: #f2f5fc #e8ebf4 #dae1e9;
$cgr: #aabac3 #90a3ae #7e909a; $cgr: #bdbdbd #9e9e9e #757575;
$cd: #62778d #526273 #425064; $cd: #62778d #526273 #425064;
@mixin ts($c: all, $t: .2s, $m: ease-in-out){ @mixin ts($c: all, $t: .2s, $m: ease-in-out){
transition:$c $t $m; transition:$c $t $m;
} }
@function px($n: 1) {
@return ($n / 10) + rem;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

5
src/images/ctrl/next.jsx Normal file
View File

@ -0,0 +1,5 @@
;<>
<svg viewBox='0 0 120 120'>
<path d='M41,38c0.4,0,0.7,0.1,1.1,0.3l32,20c0.9,0.6,1.2,1.8,0.6,2.8c-0.2,0.3-0.4,0.5-0.6,0.6l-32,20c-0.9,0.6-2.2,0.3-2.8-0.6C39.1,80.8,39,80.4,39,80V40C39,38.9,39.9,38,41,38z M79,40L79,40c1.7,0,3,1.3,3,3v34c0,1.7-1.3,3-3,3l0,0c-1.7,0-3-1.3-3-3V43C76,41.3,77.3,40,79,40z' />
</svg>
</>

View File

@ -0,0 +1,5 @@
;<>
<svg viewBox='0 0 120 120'>
<path d='M46,38c0.4,0,0.7,0.1,1.1,0.3l32,20c0.9,0.6,1.2,1.8,0.6,2.8c-0.2,0.3-0.4,0.5-0.6,0.6l-32,20c-0.9,0.6-2.2,0.3-2.8-0.6C44.1,80.8,44,80.4,44,80V40C44,38.9,44.9,38,46,38z' />
</svg>
</>

8
src/images/ctrl/play.jsx Normal file
View File

@ -0,0 +1,8 @@
;<>
<svg viewBox='0 0 120 120'>
<g fill='#ffffff'>
<rect width='8' height='50' x='45' y='35' rx='4' />
<rect width='8' height='50' x='67' y='35' rx='4' />
</g>
</svg>
</>

5
src/images/ctrl/prev.jsx Normal file
View File

@ -0,0 +1,5 @@
;<>
<svg viewBox='0 0 120 120'>
<path d='M80,82c-0.4,0-0.7-0.1-1.1-0.3l-32-20c-0.9-0.6-1.2-1.8-0.6-2.8c0.2-0.3,0.4-0.5,0.6-0.6l32-20c0.9-0.6,2.2-0.3,2.8,0.6c0.2,0.3,0.3,0.7,0.3,1.1v40C82,81.1,81.1,82,80,82z M42,80L42,80c-1.7,0-3-1.3-3-3V43c0-1.7,1.3-3,3-3l0,0c1.7,0,3,1.3,3,3v34C45,78.7,43.7,80,42,80z' />
</svg>
</>

11
src/images/ctrl/prev.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 120 120" style="enable-background:new 0 0 120 120;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
<path class="st0" d="M78,36.5c-0.4,0-0.7,0.1-1.1,0.3L42.4,58.3c-0.9,0.6-1.2,1.8-0.6,2.8c0.2,0.3,0.4,0.5,0.6,0.6l34.5,21.5
c0.9,0.6,2.2,0.3,2.8-0.6c0.2-0.3,0.3-0.7,0.3-1.1v-43C80,37.4,79.1,36.5,78,36.5z"/>
<path class="st0" d="M43,46h26c1.7,0,3,1.3,3,3v22c0,1.7-1.3,3-3,3H43c-1.7,0-3-1.3-3-3V49C40,47.3,41.3,46,43,46z"/>
</svg>

After

Width:  |  Height:  |  Size: 754 B

View File

@ -2,167 +2,179 @@
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<link href="lib/css/reset-basic.css" rel="stylesheet"> <link href="css/reset-basic.css" rel="stylesheet">
<link href="css/common.css" rel="stylesheet"> <link href="css/common.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet"> <link href="css/app.css" rel="stylesheet">
<link href="css/modules.css" rel="stylesheet">
<script type="module" src="js/app.js"></script> <script type="module" src="js/app.js"></script>
</head> </head>
<body class="do-fn-noselect"> <body class="noselect">
<div
id="app"
anot="app"
:class="{blur: isPlaying && !ktvMode, ktv: ktvMode}"
:css="{'background-image': coverBG}">
<div class="title-bar do-fn-drag"> <div class="app">
<nav class="btn-box do-fn-nodrag" :if="theme === 1" :class="{focus: winFocus}"> <div class="title-bar app-drag">
<i class="item quit" @click="quit(false)"></i> <div class="btn-box app-nodrag focus">
<i class="item min" @click="minimize"></i> <a class="item quit"></a>
<i class="item max"></i> <a class="item min"></a>
</nav> <a class="item max"></a>
</div>
<!-- 背景点位标签 -->
<div class="tools do-fn-drag">
<wc-input
class="search do-fn-nodrag"
label="搜索 音乐/歌手/专辑"
round
@submit="searchMusic"
:duplex="searchTxt"></wc-input>
</div> </div>
<main class="main-body">
<aside class="aside">
<fieldset class="playlist">
<legend>PLAYLISTS</legend>
<section class="item">Defaults</section>
<section class="item">Love</section>
<section class="item">Pop</section>
<section class="item">Light Music</section>
<button>+ new</button>
</fieldset>
<nav class="btn-box-win do-fn-nodrag"> <fieldset>
<div class="opt"> <legend>PREFERENCES</legend>
<i class="do-icon-menu-right" @click="toggleOptBox"></i> <section class="item">DSP</section>
<section class="opt-list" :visible="optBoxShow"> </fieldset>
<span @click="change2mini"><i class="do-icon-maximized"></i> 迷你模式</span>
<span @click="toggleModule('profile')">
<i class="do-icon-setting"></i> 首选项
</span>
<span class="pipe"></span>
<span @click="quit(true)"><i class="do-icon-logout"></i> 退出</span>
</section>
</div>
<span :if="theme === 2">
<i class="item do-icon-minimize" @click="minimize"></i>
<i class="item do-icon-maximize disabled"></i>
<i class="item do-icon-close quit" @click="quit(false)"></i>
</span>
</nav>
</div>
<div class="main-body">
<aside class="sidebar do-fn-drag">
<dl class="music-box do-fn-nodrag">
<dt class="title">酷狗在线</dt>
<dd class="item"
@click="toggleModule('rank')"
:class="{active: mod === 'rank'}">
<i class="s-icon-rank"></i> 排行榜
</dd>
<dd class="item"
@click="toggleModule('artist')"
:class="{active: mod === 'artist'}">
<i class="s-icon-singer"></i> 歌手
</dd>
<dd class="item disabled"
@click="toggleModule('mv')"
:class="{active: mod === 'mv'}">
<i class="s-icon-mv"></i> MV
</dd>
<dt class="title">我的音乐</dt>
<dd class="item"
@click="toggleModule('search')"
:class="{active: mod === 'search'}">
<i class="s-icon-heart"></i> 试听列表
</dd>
<dd class="item"
@click="toggleModule('local')"
:class="{active: mod === 'local'}">
<i class="s-icon-play-list"></i> 本地音乐
</dd>
</dl>
</aside> </aside>
<content class="module" :include="views" data-cache="true"></content> <div class="song-box">
<div class="preview">
<div class="album">
<img src="/images/disk.png">
</div>
<div class="info">
<strong>情是何物</strong>
<cite>周深</cite>
<p>经典咏流传第三季 第7期</p>
</div> </div>
<span class="duration">98:54</span>
<span class="total">118</span>
<div
class="ktv-box"
:if="ktvMode"
:include="'/views/ktv.htm'"
:css="{'background-image': coverBG}">
</div> </div>
<div class="scroll-box">
<wc-scroll class="list">
<section class="item">
<span class="idx">01</span>
<div class="contrl-bar"> <span class="name">情是何物</span>
<span class="artist">周深</span>
<div class="play-box"> <span class="duration">04:23</span>
<div class="btn-bg"></div>
<span
class="action play"
data-key="play"
:class="{'s-icon-play': !isPlaying, 's-icon-pause': isPlaying}">||
</span>
<span class="action next" data-key="next">>></span>
</div>
<div class="stat-box">
<div class="song-stat">
<canvas ref="player"></canvas>
</div>
<span
class="ctrl"
:class="{
's-icon-all': playMode === 0,
's-icon-single': playMode === 1,
's-icon-random': playMode === 2
}"
@click="togglePlayMode">
</span>
<section class="ctrl volume">
<i
:class="{
'do-icon-unmute' : volume > 0 && !muted,
'do-icon-mute' : volume === 0 || muted
}">
</i>
<span
class="volume-ctrl"
@click="changeValume">
<em :css="{flex: '0 ' + volume + '%'}"></em>
</span>
</section> </section>
<span class="ctrl s-icon-eq"></span> <section class="item">
<span class="ctrl lrc" @click="toggleDesktopLrc"></span> <span class="idx">02</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item on">
<span class="idx">03</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">04</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">05</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">06</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">07</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">08</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">09</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">10</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
<section class="item">
<span class="idx">11</span>
<span class="name">情是何物</span>
<span class="artist">周深</span>
<span class="duration">04:23</span>
</section>
</wc-scroll>
</div>
</div>
</main>
<div class="play-bar">
<section class="stat-bar">
<span class="time">00:13</span>
<div class="progress">
<span class="thumb"></span>
</div>
<span class="time">05:31</span>
</section>
<section class="ctrl-box">
<div class="info">
<strong>情是何物</strong>
<cite>周深</cite>
</div> </div>
<div class="play-btn">
<a class="item prev">
<svg viewBox='0 0 120 120'>
<path d="M80,82c-0.4,0-0.7-0.1-1.1-0.3l-32-20c-0.9-0.6-1.2-1.8-0.6-2.8c0.2-0.3,0.4-0.5,0.6-0.6l32-20c0.9-0.6,2.2-0.3,2.8,0.6c0.2,0.3,0.3,0.7,0.3,1.1v40C82,81.1,81.1,82,80,82z M42,80L42,80c-1.7,0-3-1.3-3-3V43c0-1.7,1.3-3,3-3l0,0c1.7,0,3,1.3,3,3v34C45,78.7,43.7,80,42,80z"/>
</svg>
</a>
<a class="item on">
<svg viewBox="0 0 120 120">
<rect width="8" height="50" x="45" y="35" rx="4"/>
<rect width="8" height="50" x="67" y="35" rx="4"/>
</svg>
</a>
<a class="item next">
<svg viewBox='0 0 120 120'>
<path d="M41,38c0.4,0,0.7,0.1,1.1,0.3l32,20c0.9,0.6,1.2,1.8,0.6,2.8c-0.2,0.3-0.4,0.5-0.6,0.6l-32,20c-0.9,0.6-2.2,0.3-2.8-0.6C39.1,80.8,39,80.4,39,80V40C39,38.9,39.9,38,41,38z M79,40L79,40c1.7,0,3,1.3,3,3v34c0,1.7-1.3,3-3,3l0,0c-1.7,0-3-1.3-3-3V43C76,41.3,77.3,40,79,40z"/>
</svg>
</a>
</div> </div>
<div class="holder"></div>
<div class="loading" :if="loading"> <div class="play-action">
<div class="box"> <a class="item mode">
<i></i><i></i><i></i><i></i><i></i> <svg viewBox='0 0 120 120'>
<span></span> <path d="M77,68c0.4,0,0.7,0.1,1.1,0.3l13.1,8.2c0.9,0.6,1.2,1.8,0.6,2.8c-0.2,0.3-0.4,0.5-0.6,0.6l-13.1,8.2c-0.9,0.6-2.2,0.3-2.8-0.6c-0.2-0.3-0.3-0.7-0.3-1.1V70C75,68.9,75.9,68,77,68z M34,55L34,55c1.7,0,3,1.3,3,3v20c0,1.7-1.3,3-3,3l0,0c-1.7,0-3-1.3-3-3V58C31,56.3,32.3,55,34,55z M34,75h53c1.7,0,3,1.3,3,3l0,0c0,1.7-1.3,3-3,3H34c-1.7,0-3-1.3-3-3l0,0C31,76.3,32.3,75,34,75z M44,52c-0.4,0-0.7-0.1-1.1-0.3l-13.1-8.2c-0.9-0.6-1.2-1.8-0.6-2.8c0.2-0.3,0.4-0.5,0.6-0.6l13.1-8.2c0.9-0.6,2.2-0.3,2.8,0.6c0.2,0.3,0.3,0.7,0.3,1.1V50C46,51.1,45.1,52,44,52z M89,65L89,65c-1.7,0-3-1.3-3-3V42c0-1.7,1.3-3,3-3l0,0c1.7,0,3,1.3,3,3v20C92,63.7,90.7,65,89,65z M89,45H36c-1.7,0-3-1.3-3-3l0,0c0-1.7,1.3-3,3-3h53c1.7,0,3,1.3,3,3l0,0C92,43.7,90.7,45,89,45z"/>
<span></span> </svg>
<cite>{{progress}}%</cite> </a>
<a class="item volume">
<svg viewBox='0 0 120 120'>
<path d="M78,36.5c-0.4,0-0.7,0.1-1.1,0.3L42.4,58.3c-0.9,0.6-1.2,1.8-0.6,2.8c0.2,0.3,0.4,0.5,0.6,0.6l34.5,21.5c0.9,0.6,2.2,0.3,2.8-0.6c0.2-0.3,0.3-0.7,0.3-1.1v-43C80,37.4,79.1,36.5,78,36.5z"/>
<path d="M43,46h26c1.7,0,3,1.3,3,3v22c0,1.7-1.3,3-3,3H43c-1.7,0-3-1.3-3-3V49C40,47.3,41.3,46,43,46z"/>
</svg>
</a>
</div> </div>
</section>
</div> </div>
</div> </div>

View File

@ -1,542 +1,7 @@
/** /**
* {sonist app} *
* @author yutent<yutent@doui.cc> * @author yutent<yutent.io@gmail.com>
* @date 2018/12/16 17:15:57 * @date 2020/11/16 16:21:52
*/ */
import '/lib/anot.js' import '/js/lib/scroll/index.js'
import '/lib/layer/index.js'
import '/lib/form/button.js'
import '/lib/form/input.js'
import '/lib/form/switch.js'
import '/lib/form/checkbox.js'
import '/lib/form/radio.js'
import '/lib/store/index.js'
import AudioPlayer from '/lib/audio/index.js'
import Lyrics from '/lib/lyrics/index.js'
import Api from '/js/api.js'
import Artist from '/js/modules/artist.js'
import Local from '/js/modules/local.js'
// import Profile from '/js/modules/profile.js'
import Search from '/js/modules/search.js'
import KTV from '/js/modules/ktv.js'
import PLAYCTRL from '/js/modules/play-ctrl.js'
const log = console.log
const fs = require('iofs')
const path = require('path')
const { remote, ipcRenderer } = require('electron')
// const { createDesktopLrcWindow, createMiniWindow } = remote.require(
// './tools/windows'
// )
// const WIN = remote.getCurrentWindow()
// const __LRC__ = createDesktopLrcWindow(screen)
// const __MINI__ = createMiniWindow(screen)
const PLAY_MODE = {
0: 'all',
1: 'single',
2: 'random'
}
// window.onblur = function() {
// location.reload()
// }
// 本地音乐和试用音乐列表
window.LS = store.collection('local')
window.TS = store.collection('temp')
// 音乐播放器
window.SONIST = new AudioPlayer()
window.LYRICS = new Lyrics()
let appInit = ipcRenderer.sendSync('sonist', { type: 'get-init' })
Anot.ss('app-init', appInit)
SONIST.target = 'local' //播放目标是本地音乐
Anot({
$id: 'app',
state: {
theme: appInit.theme || 1, // 1:macos, 2: deepin
winFocus: false,
winShow: true,
mod: 'local',
searchTxt: '',
playMode: Anot.ls('play-mode') >>> 0, // 0:all | 1:single | 2:random
ktvMode: 0,
isPlaying: false,
optBoxShow: false,
volumeCtrlShow: false,
volume: Anot.ls('volume') || 70,
muted: false,
curr: {
id: '',
cover: '',
title: '',
artist: '',
album: '',
time: 0,
duration: 0
},
ctrlLrc: '暂无歌词...',
...KTV.data,
loading: false,
progress: 0
},
skip: ['winShow'],
computed: {
views() {
if (!this.mod) {
return
}
return '/views/' + this.mod + '.htm'
},
coverBG() {
if (this.curr.cover) {
return `url(${this.curr.cover})`
} else {
return ''
}
}
},
watch: {
mod(val) {
this.activeModule(val)
}
},
mounted() {
let canvas = this.$refs.player
// 画布放大4倍, 以解决模糊的问题
this.__WIDTH__ = canvas.clientWidth * 4
this.__HEIGHT__ = canvas.clientHeight * 4
canvas.width = this.__WIDTH__
canvas.height = this.__HEIGHT__
this.__CTX__ = canvas.getContext('2d')
this.draw(true)
// 修改歌曲进度
canvas.addEventListener(
'click',
ev => {
if (!this.curr.id) {
return
}
let rect = canvas.getBoundingClientRect()
let aw = rect.width
let ax = ev.pageX - rect.left
let ay = ev.pageY - rect.top
if (ax < 80) {
this.ktvMode = this.ktvMode ^ 1
if (!this.isPlaying) {
this.draw()
}
return
}
if (ax > 124 && ay > 55 && ay < 64) {
let pp = (ax - 124) / (aw - 124)
this.curr.time = pp * this.curr.duration
SONIST.seek(this.curr.time)
LYRICS.seek(this.curr.time)
if (!this.isPlaying) {
this.draw()
}
}
},
false
)
// 设置循环模式
SONIST.mode = PLAY_MODE[this.playMode]
SONIST.volume = this.volume
SONIST.on('play', time => {
this.curr.time = time
LYRICS.update(time)
})
SONIST.on('end', time => {
this.nextSong(1)
})
// 控制条的单行歌词
LYRICS.on('ctrl-lrc', lrc => {
this.ctrlLrc = lrc
})
// ktv模式的歌词
LYRICS.on('ktv-lrc', lrc => {
this.lrc = lrc
__LRC__.emit('ktv-lrc', lrc)
})
// ktv模式的歌词
LYRICS.on('view-all', lrc => {
this.allLrc = lrc
})
this.activeModule(this.mod)
remote.app.on('browser-window-focus', _ => {
this.winFocus = true
})
remote.app.on('browser-window-blur', _ => {
this.winFocus = false
})
/**
* 响应mini窗口的事件
*/
WIN.on('mini-ctrl', ev => {
switch (ev) {
case 'prev':
this.nextSong(-1)
break
case 'play':
this.play()
break
case 'next':
this.nextSong(1)
break
case 'desktoplrc':
this.toggleDesktopLrc()
break
default:
if (ev.name === 'play-mode') {
this.playMode = ev.value
SONIST.mode = PLAY_MODE[ev.value]
Anot.ls('play-mode', ev.value)
}
}
})
/**
* 响应 全局快捷键的事件
*/
WIN.on('gs-ctrl', ev => {
switch (ev) {
case 'prev':
this.nextSong(-1)
break
case 'play':
this.play()
break
case 'next':
this.nextSong(1)
break
case 'stop':
this.isPlaying = false
this.curr.time = 0
SONIST.seek(0)
LYRICS.seek(0)
SONIST.pause()
this.draw()
break
case 'vu':
this.volume += 5
if (this.volume >= 100) {
this.volume = 100
}
SONIST.volume = this.volume
break
case 'vd':
this.volume -= 5
if (this.volume <= 0) {
this.volume = 0
}
SONIST.volume = this.volume
break
case 'lrc':
this.toggleDesktopLrc()
break
case 'mini':
this.change2mini()
break
default:
break
}
})
// 迷你模式开启时, 不响应托盘和dock栏的点击事件
ipcRenderer.on('dock-click', () => {
if (!__MINI__.isVisible()) {
WIN.show()
}
})
Anot(document).bind('keydown', ev => {
if (ev.target === document.body) {
switch (ev.keyCode) {
case 32: // 空格
this.play()
break
case 37: // 向左 (prev)
if (ev.metaKey) {
this.nextSong(-1)
}
break
case 39: // 向右 (next)
if (ev.metaKey) {
this.nextSong(1)
}
break
case 38: // 向上 (音量+
if (ev.metaKey) {
this.volume += 5
if (this.volume >= 100) {
this.volume = 100
}
SONIST.volume = this.volume
}
break
case 40: // 向下 (音量-
if (ev.metaKey) {
this.volume -= 5
if (this.volume <= 0) {
this.volume = 0
}
SONIST.volume = this.volume
}
break
case 77: // M (迷你模式)
if (ev.metaKey && ev.altKey) {
this.change2mini()
}
break
case 82: // R (桌面歌词)
if (ev.metaKey) {
this.toggleDesktopLrc()
}
break
}
}
})
WIN.on('show', ev => {
this.winShow = true
this.draw()
})
WIN.on('hide', ev => {
this.winShow = false
this.draw()
})
},
methods: {
quit(force) {
if (force) {
remote.app.exit()
} else {
if (appInit.allowPlayOnBack) {
WIN.hide()
} else {
remote.app.exit()
}
}
},
minimize() {
WIN.minimize()
},
change2mini() {
this.optBoxShow = false
WIN.hide()
__MINI__.show()
let song = this.curr.$model
if (!this.isPlaying) {
delete song.id
}
__MINI__.emit('mini-init', song)
},
activeModule(mod) {
switch (mod) {
case 'artist':
Artist.__init__()
break
case 'local':
Local.__init__()
break
case 'profile':
Profile.__init__()
break
case 'search':
Search.__init__()
break
default:
break
}
},
toggleOptBox() {
this.optBoxShow = !this.optBoxShow
},
toggleDesktopLrc() {
if (__LRC__.isVisible()) {
__LRC__.hide()
} else {
__LRC__.showInactive()
}
},
toggleModule(mod) {
if ('mv' === mod) {
return
}
this.optBoxShow = false
this.__last__ = this.mod
this.mod = mod
},
// 设置保存 回调
onProfileSaved() {
this.toggleModule(this.__last__)
appInit = JSON.parse(Anot.ss('app-init'))
},
// 切换循环模式
togglePlayMode() {
let mod = this.playMode
mod++
if (mod > 2) {
mod = 0
}
this.playMode = mod
SONIST.mode = PLAY_MODE[mod]
Anot.ls('play-mode', mod)
},
// 修改音量
changeValume(ev) {
let volume = 575 - ev.pageY
if (volume < 0) {
volume = 0
}
if (volume > 100) {
volume = 100
}
this.volume = volume
SONIST.volume = volume
Anot.ls('volume', volume)
},
searchMusic(ev) {
if (ev.keyCode === 13) {
let txt = this.searchTxt.trim()
if (!txt) {
return
}
if (txt === ':debug:') {
log('----- 调试模式 -----')
this.searchTxt = ''
WIN.openDevTools()
return
}
if (this.mod !== 'search') {
this.toggleModule('search')
}
Search.search(txt)
this.searchTxt = ''
// layer.toast('搜索功能还未开放')
}
},
/**
* 播放按钮的事件
*/
handleCtrl(ev) {
let key = ev.target.dataset.key
switch (key) {
case 'prev':
this.nextSong(-1)
break
case 'play':
this.play()
break
case 'next':
this.nextSong(1)
break
default:
break
}
},
nextSong(step) {
let _p = null
if (step > 0) {
_p = SONIST.next()
} else {
_p = SONIST.prev()
}
this.isPlaying = false
_p.then(it => {
if (this.mod === 'local') {
Local.__updateSong__(it)
}
// 通知子模块歌曲已经改变
this.$fire('child!curr', it.id)
this.play(it)
})
},
updateCurr(obj) {
let old = this.curr.$model
this.curr = Object.assign(old, obj)
__MINI__.emit('mini-init', this.curr.$model)
},
play(song) {
// 有参数的,说明是播放回调通知
// 此时仅更新播放控制条的信息即可
if (song) {
song.time = 0
this.ctrlLrc = '暂无歌词...'
this.updateCurr(song)
this.isPlaying = true
this.draw(true)
LYRICS.__init__(song.id)
} else {
if (SONIST.stat === 'ready') {
let played = this.isPlaying
this.isPlaying = !this.isPlaying
if (this.curr.id) {
if (played) {
SONIST.pause()
} else {
SONIST.play()
}
this.draw()
} else {
let lastPlay = Anot.ls('last-play') || 0
SONIST.play(lastPlay).then(it => {
it.time = 0
this.ctrlLrc = '暂无歌词...'
this.updateCurr(it)
this.draw(true)
// this.ktvMode = 1
LYRICS.__init__(it.id)
})
}
if (!this.winShow) {
__MINI__.emit('mini-ctrl', this.isPlaying ? 'play' : 'pause')
}
}
}
},
...PLAYCTRL.methods,
...KTV.methods
}
})

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -52,12 +52,9 @@ app.once('ready', () => {
}) })
// 修改app的UA // 修改app的UA
session.defaultSession.setUserAgent( session.defaultSession.setUserAgent(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
) )
// 判断依赖
exec('which ffprobe', (err, res) => {
if (res) {
let win = createMainWindow(path.resolve(ROOT, './images/app.png')) let win = createMainWindow(path.resolve(ROOT, './images/app.png'))
createTray(win) createTray(win)
@ -71,10 +68,6 @@ app.once('ready', () => {
win.webContents.send('dock-click') win.webContents.send('dock-click')
} }
}) })
} else {
createErrorWindow()
}
})
}) })
// 退出前清空所有快捷键 // 退出前清空所有快捷键

View File

@ -15,11 +15,16 @@ exports.createMainWindow = function(icon) {
// 创建浏览器窗口 // 创建浏览器窗口
let win = new BrowserWindow({ let win = new BrowserWindow({
title: 'sonist', title: 'sonist',
width: 1000, width: 820,
height: 640, height: 460,
frame: false, frame: false,
resizable: false, resizable: false,
maximizable: false,
icon, icon,
transparent: true,
backgroundColor: '#00ffffff',
vibrancy: 'dark',
visualEffectState: 'active',
webPreferences: { webPreferences: {
webSecurity: false, webSecurity: false,
experimentalFeatures: true, experimentalFeatures: true,
@ -51,7 +56,6 @@ exports.createErrorWindow = function() {
maximizable: false, maximizable: false,
minimizable: false, minimizable: false,
resizable: false, resizable: false,
titleBarStyle: 'hiddenInset',
webPreferences: { webPreferences: {
devTools: false devTools: false
} }