File structure update - all source files now in src directory, cider-ui renamed to renderer, main/backend-related files in main directory, base implementation of mpris and start of backend rework
Before Width: | Height: | Size: 1.6 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z"/></svg>
|
Before Width: | Height: | Size: 521 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M11.5 280.6l192 160c20.6 17.2 52.5 2.8 52.5-24.6V96c0-27.4-31.9-41.8-52.5-24.6l-192 160c-15.3 12.8-15.3 36.4 0 49.2zm256 0l192 160c20.6 17.2 52.5 2.8 52.5-24.6V96c0-27.4-31.9-41.8-52.5-24.6l-192 160c-15.3 12.8-15.3 36.4 0 49.2z"/></svg>
|
Before Width: | Height: | Size: 500 B |
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>ic_cast_black_24dp</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" sketch:type="MSPage">
|
||||
<g id="ic_cast_black_24dp" sketch:type="MSArtboardGroup">
|
||||
<g id="ic_remove_circle_white_24dp" sketch:type="MSLayerGroup">
|
||||
<path d="M1,18 L1,21 L4,21 C4,19.34 2.66,18 1,18 L1,18 Z M1,14 L1,16 C3.76,16 6,18.24 6,21 L8,21 C8,17.13 4.87,14 1,14 L1,14 Z M1,10 L1,12 C5.97,12 10,16.03 10,21 L12,21 C12,14.92 7.07,10 1,10 L1,10 Z M21,3 L3,3 C1.9,3 1,3.9 1,5 L1,8 L3,8 L3,5 L21,5 L21,19 L14,19 L14,21 L21,21 C22.1,21 23,20.1 23,19 L23,5 C23,3.9 22.1,3 21,3 L21,3 Z" id="cast" fill="white" sketch:type="MSShapeGroup"></path>
|
||||
<rect id="bounds" sketch:type="MSShapeGroup" x="0" y="0" width="24" height="24"></rect>
|
||||
</g>
|
||||
</g>
|
||||
<g id="assets" sketch:type="MSLayerGroup" transform="translate(-208.000000, -106.000000)">
|
||||
<g id="64px" transform="translate(0.000000, 114.000000)"></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"/></svg>
|
Before Width: | Height: | Size: 511 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M500.5 231.4l-192-160C287.9 54.3 256 68.6 256 96v320c0 27.4 31.9 41.8 52.5 24.6l192-160c15.3-12.8 15.3-36.4 0-49.2zm-256 0l-192-160C31.9 54.3 0 68.6 0 96v320c0 27.4 31.9 41.8 52.5 24.6l192-160c15.3-12.8 15.3-36.4 0-49.2z"/></svg>
|
Before Width: | Height: | Size: 493 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M80 368H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm0-320H16A16 16 0 0 0 0 64v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16zm0 160H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16zm416 176H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"/></svg>
|
Before Width: | Height: | Size: 831 B |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 12 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z"/></svg>
|
Before Width: | Height: | Size: 487 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"/></svg>
|
Before Width: | Height: | Size: 384 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z"/></svg>
|
Before Width: | Height: | Size: 640 B |
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 60 60" style="enable-background:new 0 0 60 60;" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="white" d="M42,12H20.414l7.293-7.293c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0l-8.999,8.999
|
||||
c-0.093,0.092-0.166,0.203-0.217,0.326c-0.101,0.244-0.101,0.52,0,0.764c0.051,0.123,0.124,0.234,0.217,0.326l8.999,8.999
|
||||
C26.488,22.902,26.744,23,27,23s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414L20.414,14H42c8.822,0,16,7.178,16,16
|
||||
c0,4.252-1.668,8.264-4.696,11.295c-0.391,0.391-0.391,1.024,0,1.414c0.195,0.195,0.451,0.293,0.707,0.293s0.512-0.098,0.707-0.293
|
||||
C58.124,39.3,60,34.786,60,30C60,20.075,51.925,12,42,12z"/>
|
||||
<path fill="white" d="M35.707,37.293c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L41.586,46H18C9.178,46,2,38.822,2,30
|
||||
c0-3.783,1.359-7.46,3.828-10.354c0.358-0.421,0.309-1.052-0.111-1.41c-0.419-0.359-1.052-0.31-1.41,0.111
|
||||
C1.529,21.604,0,25.741,0,30c0,9.925,8.075,18,18,18h23.586l-7.293,7.293c-0.391,0.391-0.391,1.023,0,1.414
|
||||
C34.488,56.902,34.744,57,35,57s0.512-0.098,0.707-0.293l9-9c0.391-0.391,0.391-1.023,0-1.414L35.707,37.293z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.6 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg>
|
Before Width: | Height: | Size: 618 B |
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 230.055 230.055" style="enable-background:new 0 0 230.055 230.055;" xml:space="preserve">
|
||||
<path fill="white" d="M199.419,124.497c-3.516-3.515-9.213-3.515-12.729,0c-3.515,3.515-3.515,9.213,0,12.728l12.637,12.636h-8.406
|
||||
c-8.177,0-16.151-2.871-22.453-8.083l-32.346-26.751l32.345-26.751c6.303-5.212,14.277-8.083,22.454-8.083h8.406L186.69,92.83
|
||||
c-3.515,3.515-3.515,9.213,0,12.728c1.758,1.757,4.061,2.636,6.364,2.636s4.606-0.879,6.364-2.636l28-28
|
||||
c3.515-3.515,3.515-9.213,0-12.728l-28-28c-3.516-3.515-9.213-3.515-12.729,0c-3.515,3.515-3.515,9.213,0,12.728l12.637,12.636
|
||||
h-8.406c-12.354,0-24.403,4.337-33.926,12.211L122,103.348L82.564,70.733c-6.658-5.507-15.084-8.54-23.724-8.54H9
|
||||
c-4.971,0-9,4.029-9,9s4.029,9,9,9h49.841c4.462,0,8.813,1.566,12.252,4.411l36.786,30.423L71.094,145.45
|
||||
c-3.439,2.844-7.791,4.411-12.253,4.411H9c-4.971,0-9,4.029-9,9s4.029,9,9,9h49.841c8.64,0,17.065-3.033,23.725-8.54L122,126.707
|
||||
l34.996,28.943c9.521,7.875,21.57,12.211,33.925,12.211h8.406l-12.637,12.636c-3.515,3.515-3.515,9.213,0,12.728
|
||||
c1.758,1.757,4.061,2.636,6.364,2.636s4.606-0.879,6.364-2.636l28-28c3.515-3.515,3.515-9.213,0-12.728L199.419,124.497z"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 584 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M215.03 72.04L126.06 161H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V89.02c0-21.47-25.96-31.98-40.97-16.98zm123.2 108.08c-11.58-6.33-26.19-2.16-32.61 9.45-6.39 11.61-2.16 26.2 9.45 32.61C327.98 229.28 336 242.62 336 257c0 14.38-8.02 27.72-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.87z"/></svg>
|
Before Width: | Height: | Size: 710 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="white" d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zm233.32-51.08c-11.17-7.33-26.18-4.24-33.51 6.95-7.34 11.17-4.22 26.18 6.95 33.51 66.27 43.49 105.82 116.6 105.82 195.58 0 78.98-39.55 152.09-105.82 195.58-11.17 7.32-14.29 22.34-6.95 33.5 7.04 10.71 21.93 14.56 33.51 6.95C528.27 439.58 576 351.33 576 256S528.27 72.43 448.35 19.97zM480 256c0-63.53-32.06-121.94-85.77-156.24-11.19-7.14-26.03-3.82-33.12 7.46s-3.78 26.21 7.41 33.36C408.27 165.97 432 209.11 432 256s-23.73 90.03-63.48 115.42c-11.19 7.14-14.5 22.07-7.41 33.36 6.51 10.36 21.12 15.14 33.12 7.46C447.94 377.94 480 319.54 480 256zm-141.77-76.87c-11.58-6.33-26.19-2.16-32.61 9.45-6.39 11.61-2.16 26.2 9.45 32.61C327.98 228.28 336 241.63 336 256c0 14.38-8.02 27.72-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.86z"/></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
|
@ -1,778 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<link rel="preconnect" href="https://amp-api.music.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://api.music.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is1-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is2-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is3-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is4-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is5-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://play.itunes.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://aod-ssl.itunes.apple.com/" crossorigin/>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>Cider</title>
|
||||
<link rel="stylesheet" href="style-old.css?v=2">
|
||||
<script src="vue.js"></script>
|
||||
<script src="sortable.min.js"></script>
|
||||
<script src="vuedraggable.umd.min.js"></script>
|
||||
<link rel="manifest" href="./manifest.json?v=2">
|
||||
</head>
|
||||
|
||||
<body oncontextmenu="return false;" loading="1">
|
||||
<div id="app">
|
||||
<div id="app-main">
|
||||
<div class="app-chrome">
|
||||
<div class="app-chrome--left">
|
||||
<div class="app-chrome-item full-height">
|
||||
<div class="app-title"></div>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||
@click="mk.shuffleMode = 1"></button>
|
||||
<button class="playback-button--small shuffle active" v-else @click="mk.shuffleMode = 0"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button previous" @click="mk.skipToPreviousItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button pause" @click="mk.pause()" v-if="mk.isPlaying"></button>
|
||||
<button class="playback-button play" @click="mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||
@click="mk.repeatMode = 1"></button>
|
||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 2"
|
||||
v-else-if="mk.repeatMode == 1"></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 0"
|
||||
v-else-if="mk.repeatMode == 2"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome--center">
|
||||
<div class="app-chrome-item playback-controls">
|
||||
<template v-if="mkReady()">
|
||||
<div class="app-playback-controls">
|
||||
<div class="artwork" :style="{'--artwork': getNowPlayingArtwork(42)}"></div>
|
||||
<div class="playback-info">
|
||||
<div class="song-name">
|
||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||
</div>
|
||||
<div class="song-artist">
|
||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }} - {{
|
||||
mk.nowPlayingItem["attributes"]["albumName"] }}
|
||||
</div>
|
||||
<div class="song-progress">
|
||||
<input type="range" step="0.01" min="0"
|
||||
@change="mk.seekToTime($event.target.value)"
|
||||
:max="mk.currentPlaybackDuration"
|
||||
:value="playerLCD.playbackDuration">
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">❤️</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome--right">
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<input type="range" class="" step="0.01" min="0" max="1" v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 22" version="1.1" fill="#fff"
|
||||
style="width: 100%; height: 100%; fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.41421">
|
||||
<path
|
||||
d="M16.811,12.75c0.245,-0.355 0.389,-0.786 0.389,-1.25c0,-1.215 -0.985,-2.2 -2.2,-2.2c-1.215,0 -2.2,0.985 -2.2,2.2c0,0.466 0.145,0.898 0.392,1.254l-0.83,1.047c-0.537,-0.616 -0.862,-1.42 -0.862,-2.301c0,-1.933 1.567,-3.5 3.5,-3.5c1.933,0 3.5,1.567 3.5,3.5c0,0.879 -0.324,1.683 -0.859,2.297l-0.83,-1.047Zm1.271,1.604c0.694,-0.749 1.118,-1.752 1.118,-2.854c0,-2.32 -1.88,-4.2 -4.2,-4.2c-2.32,0 -4.2,1.88 -4.2,4.2c0,1.103 0.425,2.107 1.121,2.857l-0.814,1.028c-0.993,-0.995 -1.607,-2.368 -1.607,-3.885c0,-3.038 2.462,-5.5 5.5,-5.5c3.038,0 5.5,2.462 5.5,5.5c0,1.515 -0.613,2.887 -1.604,3.882l-0.814,-1.028Zm1.252,1.58c1.151,-1.126 1.866,-2.697 1.866,-4.434c0,-3.424 -2.776,-6.2 -6.2,-6.2c-3.424,0 -6.2,2.776 -6.2,6.2c0,1.739 0.716,3.311 1.869,4.437l-0.811,1.023c-1.452,-1.368 -2.358,-3.308 -2.358,-5.46c0,-4.142 3.358,-7.5 7.5,-7.5c4.142,0 7.5,3.358 7.5,7.5c0,2.15 -0.905,4.089 -2.355,5.457l-0.811,-1.023Zm-0.227,2.066l-8.219,0c-0.355,0 -0.515,-0.434 -0.27,-0.717l4.058,-5.12c0.178,-0.217 0.474,-0.217 0.652,0l4.058,5.12c0.237,0.283 0.085,0.717 -0.279,0.717Z"
|
||||
style="fill-rule:nonzero"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small queue"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small lyrics"
|
||||
@click="drawertest = !drawertest; lyricon =!lyricon; if(drawertest == true){loadLyrics();}"
|
||||
></button>
|
||||
</div>
|
||||
<div class="app-chrome-item full-height">
|
||||
<div class="window-controls">
|
||||
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
||||
<div class="minmax restore" v-if="chrome.maximized" @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="minmax" v-else @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="close" @click="ipcRenderer.send('close')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-navigation">
|
||||
<div id="app-sidebar">
|
||||
<div class="app-sidebar-header">
|
||||
<div class="search-input-container">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
spellcheck="false"
|
||||
@click="showSearch()"
|
||||
@change="showSearch();searchQuery()"
|
||||
placeholder="Search..."
|
||||
v-model="search.term"
|
||||
class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-sidebar-content">
|
||||
<div class="app-sidebar-header-text">
|
||||
Apple Music
|
||||
</div>
|
||||
<sidebar-library-item name="Listen Now" page="listen_now"></sidebar-library-item>
|
||||
<sidebar-library-item name="Browse" page="browse"></sidebar-library-item>
|
||||
<sidebar-library-item name="Radio" page="radio"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text">
|
||||
Library
|
||||
</div>
|
||||
<sidebar-library-item name="Songs" page="library-songs"></sidebar-library-item>
|
||||
<sidebar-library-item name="Albums" page="library-albums"></sidebar-library-item>
|
||||
<sidebar-library-item name="Artists" page="library-artists"></sidebar-library-item>
|
||||
<sidebar-library-item name="Made For You" page="library-madeforyou"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text">
|
||||
Playlists
|
||||
</div>
|
||||
<button class="app-sidebar-item" v-for="item in playlists.listing" :key="item.id" :href="item.href"
|
||||
@click='app.page=`playlist_` + item.id ; showingPlaylist = [];getPlaylistFromID(app.page.substring(9))'>
|
||||
{{ item.attributes.name }}
|
||||
</button>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<div class="app-sidebar-content" v-if="chrome.menuOpened">
|
||||
<button class="app-sidebar-item" @click="chrome.hideUserInfo = !chrome.hideUserInfo">
|
||||
Toggle Personal Info
|
||||
</button>
|
||||
<button class="app-sidebar-item">
|
||||
About
|
||||
</button>
|
||||
<button class="app-sidebar-item">
|
||||
Discord
|
||||
</button>
|
||||
<button class="app-sidebar-item">
|
||||
Settings
|
||||
</button>
|
||||
<button class="app-sidebar-item">
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</transition>
|
||||
<div class="app-sidebar-footer">
|
||||
<input type="range" class="display--small">
|
||||
<button class="app-sidebar-button" style="width:100%"
|
||||
@click="chrome.menuOpened = !chrome.menuOpened">
|
||||
<template v-if="chrome.userinfo.attributes">
|
||||
<img class="sidebar-user-icon" loading="lazy"
|
||||
|
||||
:src="getMediaItemArtwork(chrome.userinfo.attributes['artwork'] ? chrome.userinfo.attributes['artwork']['url'] : '', 26)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div class="sidebar-user-text" v-if="!chrome.hideUserInfo">
|
||||
<template v-if="chrome.userinfo.attributes">
|
||||
<div class="fullname text-overflow-elipsis">{{ chrome.userinfo.attributes.name }}</div>
|
||||
<div class="handle-text text-overflow-elipsis">@{{ chrome.userinfo.attributes.handle
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
Sign in
|
||||
</template>
|
||||
</div>
|
||||
<div class="sidebar-user-text" v-else>
|
||||
Cider
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-sidebar-notification" v-if="library.songs.downloadState == 1">
|
||||
<div>Updating your library...</div>
|
||||
<div>{{ library.songs.meta.progress }} / {{ library.songs.meta.total }}</div>
|
||||
<div style="width: 100%">
|
||||
<progress style="width: 80%;" :value="library.songs.meta.progress"
|
||||
:max="library.songs.meta.total"></progress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app-content">
|
||||
<!-- Playlist / Album page-->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('playlist_')">
|
||||
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
||||
</template>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('album_')">
|
||||
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
||||
</template>
|
||||
</transition>
|
||||
</transition>
|
||||
<!-- Browse -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'browse'">
|
||||
<div class="content-inner">
|
||||
<button id="apple-music-authorize" class="md-btn md-btn-primary" @click="init()">Start
|
||||
MusicKit
|
||||
</button>
|
||||
<button id="apple-music-unauthorize" class="md-btn md-btn-primary" @click="unauthorize()">
|
||||
Stop
|
||||
MusicKit
|
||||
</button>
|
||||
<br>
|
||||
<template v-if="mk.nowPlayingItem">
|
||||
currentPlaybackProgress: {{ app.mk.currentPlaybackProgress }}
|
||||
<br>
|
||||
currentPlaybackDuration: {{ app.mk.currentPlaybackDuration }}
|
||||
</template>
|
||||
<div><input type="text" v-model="quickPlayQuery">
|
||||
<button @click="quickPlay(quickPlayQuery)">Play</button>
|
||||
</div>
|
||||
<h1 class="header-text">Browse</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, urna eu tincidunt
|
||||
consectetur, nisl nunc euismod nisi, eu porttitor nisl nisi euismod nisi.
|
||||
</p>
|
||||
<div class="media-item--small">
|
||||
<div class="artwork">
|
||||
|
||||
</div>
|
||||
<div class="text">
|
||||
Text
|
||||
</div>
|
||||
<div class="subtext">
|
||||
Subtext
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h1 class="header-text">Listen Now</h1>
|
||||
<div class="winbox">
|
||||
<div class="fancy">990kbps</div>
|
||||
<div class="">
|
||||
<button class="md-btn md-btn-primary">Audio Quality Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="md-btn" @click="drawertest = !drawertest">Toggle Drawer</button>
|
||||
<button class="md-btn">Button</button>
|
||||
<button class="md-btn md-btn-primary">Button</button>
|
||||
</div>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Listen Now -->
|
||||
<transition v-on:enter="getListenNow()" name="wpfade">
|
||||
<template v-if="page == 'listen_now'" @created="console.log('listennow')">
|
||||
<cider-listen-now :data="listennow"></cider-listen-now>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Radio -->
|
||||
<transition v-on:enter="getRadioStations()" name="wpfade">
|
||||
<template v-if="page == 'radio'" @created="console.log('radio')">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Radio</h1>
|
||||
<h3>Recent Stations</h3>
|
||||
<mediaitem-square :item="item" v-for="item in radio.personal"></mediaitem-square>
|
||||
</div>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Search -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'search'">
|
||||
<cider-search :search="search"></cider-search>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Library - Songs -->
|
||||
<transition name="wpfade" v-on:enter="getLibrarySongsFull()">
|
||||
<template v-if="page == 'library-songs'">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Songs</h1>
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibrarySongs"
|
||||
v-model="library.songs.search"
|
||||
class="search-input">
|
||||
</div>
|
||||
<mediaitem-list-item :item="item"
|
||||
v-for="item in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Library - Albums -->
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbums()">
|
||||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
class="search-input">
|
||||
</div>
|
||||
<mediaitem-square-large :item="item"
|
||||
v-for="item in library.albums.listing"></mediaitem-square-large>
|
||||
</div>
|
||||
</template>
|
||||
</transition>
|
||||
</div>
|
||||
<transition name="drawertransition">
|
||||
<div class="app-drawer" v-if="drawertest">
|
||||
<lyrics-view v-if="drawertest && lyricon" :time="lyriccurrenttime" :lyrics="lyrics"></lyrics-view>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<img v-show="chrome.artworkReady"
|
||||
@load="chrome.artworkReady = true"
|
||||
class="bg-artwork"
|
||||
:src="getNowPlayingArtworkBG(32)">
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<div class="bg-artwork--placeholder" v-else></div>
|
||||
</transition>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/x-template" id="mediaitem-artwork">
|
||||
<template v-if="type == 'artists'">
|
||||
<div class="mediaitem-artwork rounded"
|
||||
>
|
||||
<img :src="app.getMediaItemArtwork(url, size)"
|
||||
class="mediaitem-artwork--img">
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="mediaitem-artwork"
|
||||
>
|
||||
<img :src="app.getMediaItemArtwork(url, size)"
|
||||
class="mediaitem-artwork--img">
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- Generic Collection of MediaItems -->
|
||||
<script type="text/x-template" id="collection-view-generic">
|
||||
<template>
|
||||
<div class="content-inner">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- Listen Now -->
|
||||
<script type="text/x-template" id="cider-listen-now">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Listen Now</h1>
|
||||
<template v-for="recom in data.data">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ recom.attributes.title ? recom.attributes.title.stringForDisplay : ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="recom.relationships.contents.data.length >= 10">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.attributes.display.kind == 'MusicCoverShelf'">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else-if="recom.attributes.display.kind == 'MusicSuperHeroShelf'">
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-sp
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-sp>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Album / Playlist View -->
|
||||
<script type="text/x-template" id="cider-playlist">
|
||||
<div class="content-inner">
|
||||
<template v-if="data != [] && data.attributes != []">
|
||||
<div class="playlist-display row">
|
||||
<div class="col-auto">
|
||||
<mediaitem-artwork
|
||||
:url="(data.attributes != null && data.attributes.artwork != null) ? data.attributes.artwork.url : (data.relationships.tracks.data.length > 0 ? data.relationships.tracks.data[0].attributes.artwork.url ?? '':'')"
|
||||
size="200"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="col playlist-info">
|
||||
<div class="playlist-name">{{data.attributes.name ?? (data.attributes.title ?? '') ?? ''}}</div>
|
||||
<div class="playlist-artist" v-if="data.attributes.artistName">{{data.attributes.artistName ??
|
||||
''}}
|
||||
</div>
|
||||
<div class="playlist-desc"
|
||||
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.short ?? (data.attributes.editorialNotes.standard ?? '') ) : (data.attributes.description ? (data.attributes.description.short ?? (data.attributes.description.standard ?? '')) : ''))"></div>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-list-item :item="item"
|
||||
v-for="item in data.relationships.tracks.data"></mediaitem-list-item>
|
||||
<div class="playlist-time">{{app.getTotalTime()}}</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Search -->
|
||||
<script type="text/x-template" id="cider-search">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;" v-if="getTopResult()">
|
||||
<template>
|
||||
<h3>Top Result</h3>
|
||||
<mediaitem-square-large :item="getTopResult()"></mediaitem-square>
|
||||
</template>
|
||||
</div>
|
||||
<div class="col" v-if="search.results.songs">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results.songs.data.length >= 6">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<mediaitem-list-item :item="item"
|
||||
v-for="item in search.results.songs.data.limit(6)"></mediaitem-list-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="search.results['meta']">
|
||||
<template v-if="search.results.albums">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Albums</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results.albums.data.length >= 10">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.results.albums.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="search.results.artists">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Artists</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results.artists.data.length >= 5">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item"
|
||||
v-for="item in search.results.artists.data.limit(5)"></mediaitem-square-large>
|
||||
</template>
|
||||
<template v-if="search.results.playlists">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Playlists</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results.playlists.data.length >= 10">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item"
|
||||
v-for="item in search.results.playlists.data.limit(10)"></mediaitem-square-large>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="am-musiccovershelf">
|
||||
<h1>{{ component.attributes.title.stringForDisplay }}</h1>
|
||||
</script>
|
||||
|
||||
<!-- Sidebar Item -->
|
||||
<script type="text/x-template" id="sidebar-library-item">
|
||||
<button class="app-sidebar-item"
|
||||
:class="$parent.getSidebarItemClass(page)"
|
||||
@click="$parent.page = page">{{ name }}
|
||||
</button>
|
||||
</script>
|
||||
|
||||
<!-- Horizontal MediaItem Scroller -->
|
||||
<script type="text/x-template" id="mediaitem-scroller-horizontal">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square :item="item"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- Horizontal MediaItem Scroller (Large) -->
|
||||
<script type="text/x-template" id="mediaitem-scroller-horizontal-large">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square-large :item="item"
|
||||
v-for="item in items"></mediaitem-square-large>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- Horizontal MediaItem Scroller (SP : Special) -->
|
||||
|
||||
<script type="text/x-template" id="mediaitem-scroller-horizontal-sp">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square-sp :item="item"
|
||||
v-for="item in items"></mediaitem-square-sp>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- MediaItem List Item -->
|
||||
|
||||
<script type="text/x-template" id="mediaitem-list-item">
|
||||
<template>
|
||||
<div @click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
class="cd-mediaitem-list-item">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="34"
|
||||
:type="item.type"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="info-rect">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis">
|
||||
<template v-if="item.attributes.artistName">
|
||||
{{ item.attributes.artistName }}
|
||||
<template v-if="item.attributes.albumName">
|
||||
- {{ item.attributes.albumName }}
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-rating" v-if="item.attributes.contentRating">
|
||||
{{ item.attributes.contentRating }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- MediaItem Horizontal Rectangle -->
|
||||
<script type="text/x-template" id="mediaitem-hrect">
|
||||
<template>
|
||||
<div @click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
class="cd-mediaitem-hrect">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="70"
|
||||
:type="item.type"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="info-rect">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis">
|
||||
{{ item.type }}
|
||||
<template v-if="item.attributes.artistName">
|
||||
∙ {{ item.attributes.artistName }}
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- MediaItem Square -->
|
||||
|
||||
<script type="text/x-template" id="mediaitem-square">
|
||||
<template>
|
||||
<div @click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
class="cd-mediaitem-square">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:type="item.type"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" v-if="item.attributes.artistName">
|
||||
{{ item.attributes.artistName }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- MediaItem Square (Large) -->
|
||||
|
||||
<script type="text/x-template" id="mediaitem-square-large">
|
||||
<template>
|
||||
<div style="position: relative; display: inline-flex;">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-square-large">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:type="item.type"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]"
|
||||
@click="app.playMediaItem(item)">
|
||||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M11.3545232,18.4180929 L18.4676039,14.242665 C19.0452323,13.9290954 19.0122249,13.1204156 18.4676039,12.806846 L11.3545232,8.63141809 C10.7603912,8.26833741 9.98471883,8.54889976 9.98471883,9.19254279 L9.98471883,17.8404645 C9.98471883,18.5006112 10.7108802,18.7976773 11.3545232,18.4180929 Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
||||
{{ item.attributes.name ?? '' }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" v-if="item.attributes.artistName">
|
||||
{{ item.attributes.artistName ?? '' }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]"
|
||||
@click="app.playMediaItem(item)">
|
||||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M11.3545232,18.4180929 L18.4676039,14.242665 C19.0452323,13.9290954 19.0122249,13.1204156 18.4676039,12.806846 L11.3545232,8.63141809 C10.7603912,8.26833741 9.98471883,8.54889976 9.98471883,9.19254279 L9.98471883,17.8404645 C9.98471883,18.5006112 10.7108802,18.7976773 11.3545232,18.4180929 Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- MediaItem Square SP -->
|
||||
<script type="text/x-template" id="mediaitem-square-sp">
|
||||
<template>
|
||||
<div style="position: relative; display: inline-flex;">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-square-sp"
|
||||
:style="{'--spcolor' : (item.attributes.artwork.bgColor != null) ? ('#'+item.attributes.artwork.bgColor) : `black`}">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:type="item.type"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]"
|
||||
@click="app.playMediaItem(item)">
|
||||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M11.3545232,18.4180929 L18.4676039,14.242665 C19.0452323,13.9290954 19.0122249,13.1204156 18.4676039,12.806846 L11.3545232,8.63141809 C10.7603912,8.26833741 9.98471883,8.54889976 9.98471883,9.19254279 L9.98471883,17.8404645 C9.98471883,18.5006112 10.7108802,18.7976773 11.3545232,18.4180929 Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis"
|
||||
:style="{'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}"
|
||||
style="font-weight: 600">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis"
|
||||
:style="{'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}"
|
||||
style="padding-left: 4px;padding-right: 4px; display: -webkit-box;-webkit-box-orient: vertical; -webkit-line-clamp: 2;white-space: normal;">
|
||||
{{ (item.attributes.editorialNotes != null) ? item.attributes.editorialNotes.short
|
||||
:(item.attributes.artistName ?? '') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]"
|
||||
@click="app.playMediaItem(item)">
|
||||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M11.3545232,18.4180929 L18.4676039,14.242665 C19.0452323,13.9290954 19.0122249,13.1204156 18.4676039,12.806846 L11.3545232,8.63141809 C10.7603912,8.26833741 9.98471883,8.54889976 9.98471883,9.19254279 L9.98471883,17.8404645 C9.98471883,18.5006112 10.7108802,18.7976773 11.3545232,18.4180929 Z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
<script type="text/x-template" id="lyrics-view">
|
||||
<div class="md-body lyric-body">
|
||||
<template v-if="lyrics">
|
||||
<template v-for="lyric in lyrics" v-if="lyric.line != 'lrcInstrumental'">
|
||||
<h3 class="lyric-line" @click="app.seekTo(lyric.startTime, false)"
|
||||
v-bind:class="{ active: app.getLyricClass(lyric.startTime, lyric.endTime)}">
|
||||
{{ lyric.line }}
|
||||
<div class="lyrics-translation" v-if="lyric.translation && lyric.translation != ''">
|
||||
{{ lyric.translation }}
|
||||
<div>
|
||||
</h3>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h3 class="lyric-line" @click="app.seekTo(lyric.startTime, false)" :start="lyric.startTime"
|
||||
:end="lyric.endTime"
|
||||
v-bind:class="{ active: app.getLyricClass(lyric.startTime, lyric.endTime)}">
|
||||
<div class="lyricWaiting">
|
||||
<div class='WaitingDot1'></div>
|
||||
<div class='WaitingDot2'></div>
|
||||
<div class='WaitingDot3'></div>
|
||||
</div>
|
||||
</h3>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
No Lyrics Available
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
<script src="https://js-cdn.music.apple.com/musickit/v2/amp/musickit.js"></script>
|
||||
<script src="index.js?v=1"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
Before Width: | Height: | Size: 33 KiB |
3
resources/cider-ui/sortable.min.js
vendored
|
@ -1,2 +0,0 @@
|
|||
if(!self.define){let e,i={};const s=(s,r)=>(s=new URL(s+".js",r).href,i[s]||new Promise((i=>{if("document"in self){const e=document.createElement("script");e.src=s,e.onload=i,document.head.appendChild(e)}else e=s,importScripts(s),i()})).then((()=>{let e=i[s];if(!e)throw new Error(`Module ${s} didn’t register its module`);return e})));self.define=(r,c)=>{const n=e||("document"in self?document.currentScript.src:"")||location.href;if(i[n])return;let o={};const t=e=>s(e,n),a={module:{uri:n},exports:o,require:t};i[n]=Promise.all(r.map((e=>a[e]||t(e)))).then((e=>(c(...e),o)))}}define(["./workbox-962786f2"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"ameframework.css",revision:"4bcc8646bb5742638fad52b94e231601"},{url:"apple-hls.js",revision:"2b74055662676b0fcc2d4a4bf994a9dc"},{url:"hlscider.js",revision:"cf7f512e83e32694f2c94f904714fe4c"},{url:"index_old.html",revision:"c21f3e9c5b015599d3ab07639f64a7a8"},{url:"index.js",revision:"8591a69fc9c975a063eb264b7447f173"},{url:"less.js",revision:"b6e574e4d680686786a28e7e71a17bbc"},{url:"musickit.js",revision:"211d80891c3336c1795cb83df58d4b63"},{url:"sortable.min.js",revision:"5cbc31ebec32adf60e27b76418e79d93"},{url:"style-old.css",revision:"aea9ea49df13f2deee42b68654aeea06"},{url:"todo.js",revision:"18d49fabcb96de8bd11455877d8eacb6"},{url:"vue-observe-visibility.min.js",revision:"5a52e761f6aa71b4f65a7b458f698b95"},{url:"vue.js",revision:"0a9a4681294d8c5f476687eea6e74842"},{url:"vuedraggable.umd.min.js",revision:"9a84fec5263bb510cee88e1c3b9583cc"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/,/^X-Amz-Algorithm/,/^X-Amz-Date/,/^X-Amz-SignedHeaders/,/^X-Amz-Expires/,/^X-Amz-Credential/,/^X-Amz-Signature/]}),e.registerRoute(/\.(?:png|jpg|jpeg|svg|webp)$/,new e.CacheFirst({cacheName:"imageinternet",plugins:[]}),"GET"),e.registerRoute(/https:\/\/is[0-9]-ssl\.mzstatic\.com\/image+/,new e.CacheFirst,"GET"),e.registerRoute(/^https:\/\/store-\d{3}\.blobstore\.apple\.com\/.{65}\/image+/,new e.CacheFirst,"GET")}));
|
||||
//# sourceMappingURL=sw.js.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"sw.js","sources":["C:/Users/vieta/AppData/Local/Temp/b97cb0fb56dd447f95668d4898340903/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from 'C:/Users/vieta/AppData/Roaming/nvm/v14.18.1/node_modules/workbox-cli/node_modules/workbox-routing/registerRoute.mjs';\nimport {CacheFirst as workbox_strategies_CacheFirst} from 'C:/Users/vieta/AppData/Roaming/nvm/v14.18.1/node_modules/workbox-cli/node_modules/workbox-strategies/CacheFirst.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from 'C:/Users/vieta/AppData/Roaming/nvm/v14.18.1/node_modules/workbox-cli/node_modules/workbox-precaching/precacheAndRoute.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.type === 'SKIP_WAITING') {\n self.skipWaiting();\n }\n});\n\n\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"ameframework.css\",\n \"revision\": \"4bcc8646bb5742638fad52b94e231601\"\n },\n {\n \"url\": \"apple-hls.js\",\n \"revision\": \"2b74055662676b0fcc2d4a4bf994a9dc\"\n },\n {\n \"url\": \"hlscider.js\",\n \"revision\": \"cf7f512e83e32694f2c94f904714fe4c\"\n },\n {\n \"url\": \"index_old.html\",\n \"revision\": \"c21f3e9c5b015599d3ab07639f64a7a8\"\n },\n {\n \"url\": \"index.js\",\n \"revision\": \"8591a69fc9c975a063eb264b7447f173\"\n },\n {\n \"url\": \"less.js\",\n \"revision\": \"b6e574e4d680686786a28e7e71a17bbc\"\n },\n {\n \"url\": \"musickit.js\",\n \"revision\": \"211d80891c3336c1795cb83df58d4b63\"\n },\n {\n \"url\": \"sortable.min.js\",\n \"revision\": \"5cbc31ebec32adf60e27b76418e79d93\"\n },\n {\n \"url\": \"style-old.css\",\n \"revision\": \"aea9ea49df13f2deee42b68654aeea06\"\n },\n {\n \"url\": \"todo.js\",\n \"revision\": \"18d49fabcb96de8bd11455877d8eacb6\"\n },\n {\n \"url\": \"vue-observe-visibility.min.js\",\n \"revision\": \"5a52e761f6aa71b4f65a7b458f698b95\"\n },\n {\n \"url\": \"vue.js\",\n \"revision\": \"0a9a4681294d8c5f476687eea6e74842\"\n },\n {\n \"url\": \"vuedraggable.umd.min.js\",\n \"revision\": \"9a84fec5263bb510cee88e1c3b9583cc\"\n }\n], {\n \"ignoreURLParametersMatching\": [/^utm_/, /^fbclid$/, /^X-Amz-Algorithm/, /^X-Amz-Date/, /^X-Amz-SignedHeaders/, /^X-Amz-Expires/, /^X-Amz-Credential/, /^X-Amz-Signature/]\n});\n\n\n\n\nworkbox_routing_registerRoute(/\\.(?:png|jpg|jpeg|svg|webp)$/, new workbox_strategies_CacheFirst({ \"cacheName\":\"imageinternet\", plugins: [] }), 'GET');\nworkbox_routing_registerRoute(/https:\\/\\/is[0-9]-ssl\\.mzstatic\\.com\\/image+/, new workbox_strategies_CacheFirst(), 'GET');\nworkbox_routing_registerRoute(/^https:\\/\\/store-\\d{3}\\.blobstore\\.apple\\.com\\/.{65}\\/image+/, new workbox_strategies_CacheFirst(), 'GET');\n\n\n\n\n"],"names":["self","addEventListener","event","data","type","skipWaiting","workbox_strategies_CacheFirst","plugins"],"mappings":"0nBAqBAA,KAAKC,iBAAiB,WAAYC,IAC5BA,EAAMC,MAA4B,iBAApBD,EAAMC,KAAKC,MAC3BJ,KAAKK,oCAY2B,CAClC,KACS,4BACK,oCAEd,KACS,wBACK,oCAEd,KACS,uBACK,oCAEd,KACS,0BACK,oCAEd,KACS,oBACK,oCAEd,KACS,mBACK,oCAEd,KACS,uBACK,oCAEd,KACS,2BACK,oCAEd,KACS,yBACK,oCAEd,KACS,mBACK,oCAEd,KACS,yCACK,oCAEd,KACS,kBACK,oCAEd,KACS,mCACK,qCAEb,6BAC8B,CAAC,QAAS,WAAY,mBAAoB,cAAe,uBAAwB,iBAAkB,oBAAqB,sCAM3H,+BAAgC,IAAIC,aAA8B,WAAc,gBAAiBC,QAAS,KAAO,uBACjH,+CAAgD,IAAID,aAAiC,uBACrF,+DAAgE,IAAIA,aAAiC"}
|
|
@ -1,162 +0,0 @@
|
|||
// Apple Music Listen Now Page
|
||||
// URL : https://amp-api.music.apple.com/v1/me/recommendations?timezone=+00:00
|
||||
// &with=friendsMix,library,social&art[social-profiles:url]=c
|
||||
// &name=listen-now&art[url]=c,f&omit[resource]=autos
|
||||
// &relate[editorial-items]=contents
|
||||
// &extend=editorialCard,editorialVideo
|
||||
// &extend[albums]=artistUrl
|
||||
// &extend[library-albums]=artistUrl
|
||||
// &extend[playlists]=artistNames,editorialArtwork
|
||||
// &extend[library-playlists]=artistNames,editorialArtwork
|
||||
// &extend[social-profiles]=topGenreNames&include[albums]=artists
|
||||
// &include[songs]=artists&include[music-videos]=artists
|
||||
// &fields[albums]=artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url
|
||||
// &fields[artists]=name,url&extend[stations]=airDate,supportsAirTimeUpdates&meta[stations]=inflectionPoints
|
||||
// &types=artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-profiles,social-upsells
|
||||
// &l=en-gb&platform=web
|
||||
|
||||
await app.mk.api.personalRecommendations("",
|
||||
{
|
||||
name: "listen-now",
|
||||
with: "friendsMix,library,social",
|
||||
"art[social-profiles:url]":"c",
|
||||
"art[url]": "c,f",
|
||||
"omit[resource]": "autos",
|
||||
"relate[editorial-items]": "contents",
|
||||
extend: ["editorialCard", "editorialVideo"],
|
||||
"extend[albums]": ["artistUrl"],
|
||||
"extend[library-albums]": ["artistUrl"],
|
||||
"extend[playlists]": ["artistNames", "editorialArtwork"],
|
||||
"extend[library-playlists]": ["artistNames", "editorialArtwork"],
|
||||
"extend[social-profiles]": "topGenreNames",
|
||||
"include[albums]": "artists",
|
||||
"include[songs]": "artists",
|
||||
"include[music-videos]": "artists",
|
||||
"fields[albums]": ["artistName", "artistUrl", "artwork", "contentRating", "editorialArtwork", "editorialVideo", "name", "playParams", "releaseDate", "url"],
|
||||
"fields[artists]": ["name", "url"],
|
||||
"extend[stations]": ["airDate", "supportsAirTimeUpdates"],
|
||||
"meta[stations]": "inflectionPoints",
|
||||
types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-profiles,social-upsells",
|
||||
l:"en-gb",
|
||||
platform:"web"
|
||||
},
|
||||
{
|
||||
includeResponseMeta: !0,
|
||||
reload: !0
|
||||
});
|
||||
|
||||
// Browse page
|
||||
await app.mk.api.groupings("",
|
||||
{
|
||||
platform: "web",
|
||||
name: "music",
|
||||
l: "en-gb",
|
||||
"omit[resource:artists]": "relationships",
|
||||
"include[albums]": "artists",
|
||||
"include[songs]": "artists",
|
||||
"include[music-videos]": "artists",
|
||||
extend: "editorialArtwork,artistUrl",
|
||||
"fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes",
|
||||
"art[url]": "f"
|
||||
});
|
||||
|
||||
// Radio page
|
||||
await app.mk.api.recentRadioStations("",
|
||||
{l: "en-gb",
|
||||
"platform": "web",
|
||||
"art[url]": "f"});
|
||||
|
||||
// Recently Added
|
||||
await app.mk.api.library.recentlyAdded({
|
||||
"platform": "web",
|
||||
include: {
|
||||
"library-albums": ["artists"],
|
||||
"library-artists": ["catalog"]
|
||||
},
|
||||
fields: {
|
||||
artists: ["url"],
|
||||
albums: "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url"
|
||||
},
|
||||
includeOnly: ["catalog", "artists"],
|
||||
limit: 25
|
||||
}, {
|
||||
reload: !0,
|
||||
includePagination: !0
|
||||
})
|
||||
|
||||
// Songs
|
||||
await app.mk.api.library.songs({limit: 100}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// Artists
|
||||
await app.mk.api.library.artists({limit: 100}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// Artists
|
||||
await app.mk.api.library.albums({limit: 100}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// Albums
|
||||
// does not like limit = 100 for some reason
|
||||
await app.mk.api.library.albums({limit: 50}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// Made For You
|
||||
app.mk.api.recommendations("",{extend: "editorialArtwork,artistUrl"})
|
||||
|
||||
// Library with library length
|
||||
await app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// Artist View Top Songs
|
||||
app.mk.api.artistView("325096253", "top-songs", {}, {view: "top-songs", includeResponseMeta: !0})
|
||||
|
||||
// Artist Page Data
|
||||
app.mkapi("artists", false, "412778295", {
|
||||
"views": "featured-release,full-albums,appears-on-albums,featured-albums,featured-on-albums,singles,compilation-albums,live-albums,latest-release,top-music-videos,similar-artists,top-songs,playlists,more-to-hear,more-to-see",
|
||||
"extend": "artistBio,bornOrFormed,editorialArtwork,editorialVideo,isGroup,origin,hero",
|
||||
"extend[playlists]": "trackCount",
|
||||
"omit[resource:songs]": "relationships",
|
||||
"fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url,trackCount",
|
||||
"limit[artists:top-songs]": 20,
|
||||
"art[url]": "f"
|
||||
}, {includeResponseMeta: !0}).then((data)=>{
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
// download entire library
|
||||
var library = []
|
||||
var downloaded = null;
|
||||
function downloadChunk () {
|
||||
if(downloaded == null) {
|
||||
app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
||||
processChunk(response)
|
||||
})
|
||||
}else{
|
||||
downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
||||
processChunk(response)
|
||||
})
|
||||
}
|
||||
}
|
||||
function processChunk (response) {
|
||||
downloaded = response
|
||||
library = library.concat(downloaded.data)
|
||||
if (downloaded.meta.total > library.length) {
|
||||
console.log(`downloading next chunk - ${library.length} songs so far`)
|
||||
downloadChunk()
|
||||
} else {
|
||||
console.log(library)
|
||||
}
|
||||
}
|
||||
|
||||
//Some Available Functions from MusicKit
|
||||
// recentPlayed() -> recently played songs ?
|
||||
|
||||
// create Artist / Song/ Album stations:
|
||||
app.mk.setStationQueue({artist:"1258279972"})
|
||||
app.mk.setStationQueue({song:"1437308307"}) // yes the song id here can be the albumId, but just keep using the song:
|
|
@ -1,59 +0,0 @@
|
|||
<script type="text/x-template" id="animatedartwork-view">
|
||||
<template v-if="video">
|
||||
<div class="animated" v-bind:vid="app.hashCode(video).toString()">
|
||||
<video ref="video" class="animated-artwork-video" loop id="animated-artwork"></video>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('animatedartwork-view', {
|
||||
template: '#animatedartwork-view',
|
||||
props: ['video', 'hls'],
|
||||
mounted() {
|
||||
if (this.video) {
|
||||
|
||||
this.$nextTick(function () {
|
||||
var config = {
|
||||
backBufferLength: 0,
|
||||
enableWebVTT: false,
|
||||
enableCEA708Captions: false,
|
||||
emeEnabled: false,
|
||||
abrEwmaDefaultEstimate: 10000,
|
||||
testBandwidth: false
|
||||
};
|
||||
if (this.hls) {
|
||||
console.log('detached');
|
||||
this.hls.detachMedia();
|
||||
} else {
|
||||
|
||||
this.hls = new CiderHls(config);
|
||||
}
|
||||
// bind them together
|
||||
if (this.$refs.video) {
|
||||
let d = "WIDEVINE_SOFTWARE"
|
||||
let h = {
|
||||
initDataTypes: ["cenc", "keyids"],
|
||||
distinctiveIdentifier: "optional",
|
||||
persistentState: "required"
|
||||
}
|
||||
let p = {
|
||||
platformInfo: {requiresCDMAttachOnStart: !0, maxSecurityLevel: d, keySystemConfig: h},
|
||||
appData: {serviceName: "Apple Music"}
|
||||
}
|
||||
this.hls.attachMedia(this.$refs.video);
|
||||
this.hls.loadSource(this.video);
|
||||
this.hls.loadLevel = 4;
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
async beforeDestroy() {
|
||||
if(this.hls) {
|
||||
await this.hls.destroy();
|
||||
this.hls = null
|
||||
console.log('killed')
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,14 +0,0 @@
|
|||
<div class="modal-backdrop">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close">×</button>
|
||||
<h4 class="modal-title" v-html="title"></h4>
|
||||
</div>
|
||||
<div class="modal-content" v-html="content">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,14 +0,0 @@
|
|||
<script type="text/x-template" id="hello-world">
|
||||
<button @click="sayHello()">Hello world!</button>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('hello-world', {
|
||||
template: '#hello-world',
|
||||
methods: {
|
||||
sayHello: function () {
|
||||
alert('Hello world!');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,20 +0,0 @@
|
|||
<script type="text/x-template" id="karaoke-in">
|
||||
<div class="karaoke-viewer">
|
||||
<div class="lyric">
|
||||
<template v-for="segment in lyrics" v-if="segmentInRange(segment.ts, segment.te, segment.x)">
|
||||
<div class="verse-group active">
|
||||
<template v-for="(verse, verseIndex) in segment.l"
|
||||
v-if="verseInRange(segment.ts, segment.te, verse.o)">
|
||||
<span class="verse verse-active">{{ verse.c }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="verse">{{ verse.c }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="verse-group">{{ segment.x }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
|
@ -1,162 +0,0 @@
|
|||
<script type="text/x-template" id="lyrics-view">
|
||||
<div ref="lyricsview" class="md-body lyric-body">
|
||||
<template v-if="lyrics && lyrics != [] && lyrics.length > 0">
|
||||
<template v-for="(lyric, index) in lyrics" v-if="lyric.line != 'lrcInstrumental'">
|
||||
<h3 class="lyric-line" @click="if(lyric.startTime != 9999999) app.seekTo(lyric.startTime, false)"
|
||||
v-bind:line-index="index.toString()">
|
||||
<template v-if="richlyrics && richlyrics != [] && richlyrics.length > 0">
|
||||
<div class="richl" >
|
||||
<template v-for="verse in getVerseLine(index-1)" >
|
||||
<span class="verse" :lyricstart="lyric.startTime" :versestart="verse.o" >{{ verse.c }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="norm" >
|
||||
{{ lyric.line }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="lyrics-translation" v-if="lyric.translation && lyric.translation != ''">
|
||||
{{ lyric.translation }}
|
||||
</div>
|
||||
</h3>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h3 class="lyric-line" @click="if(lyric.startTime != 9999999) app.seekTo(lyric.startTime, false)"
|
||||
:start="lyric.startTime"
|
||||
:end="lyric.endTime" v-bind:line-index="index.toString()">
|
||||
<div class="lyricWaiting">
|
||||
<div class='WaitingDot1'></div>
|
||||
<div class='WaitingDot2'></div>
|
||||
<div class='WaitingDot3'></div>
|
||||
</div>
|
||||
</h3>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-lyrics">
|
||||
Loading... / Lyrics not found./ Instrumental.
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('lyrics-view', {
|
||||
template: '#lyrics-view',
|
||||
props: ["time", "lyrics", "richlyrics", "translation", "onindex"],
|
||||
watch: {
|
||||
time: function () {
|
||||
if (app.lyricon && app.drawer.open) {
|
||||
let currentLine = this.$refs.lyricsview.querySelector(`.lyric-line.active`)
|
||||
if (currentLine && currentLine.getElementsByClassName('lyricWaiting').length > 0) {
|
||||
let duration = currentLine.getAttribute("end") - currentLine.getAttribute("start");
|
||||
let u = (this.time - currentLine.getAttribute("start")) / duration;
|
||||
if (u < 0.25 && !currentLine.classList.contains('mode1')) {
|
||||
try {
|
||||
currentLine.classList.add('mode1');
|
||||
currentLine.classList.remove('mode3');
|
||||
currentLine.classList.remove('mode2');
|
||||
} catch (e) {
|
||||
}
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.animation = `dotOpacity ${0.25 * duration}s cubic-bezier(0.42, 0, 0.58, 1) forwards`;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot3')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.opacity = 0.25;
|
||||
currentLine.getElementsByClassName('WaitingDot3')[0].style.opacity = 0.25;
|
||||
|
||||
} else if (u >= 0.25 && u < 0.5 && !currentLine.classList.contains('mode2')) {
|
||||
try {
|
||||
currentLine.classList.add('mode2');
|
||||
currentLine.classList.remove('mode1');
|
||||
currentLine.classList.remove('mode3');
|
||||
} catch (e) {
|
||||
}
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.animation = `dotOpacity ${0.25 * duration}s cubic-bezier(0.42, 0, 0.58, 1) forwards`;
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot3')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.opacity = 1;
|
||||
currentLine.getElementsByClassName('WaitingDot3')[0].style.opacity = 0.25;
|
||||
} else if (u >= 0.5 && u < 0.75 && !currentLine.classList.contains('mode3')) {
|
||||
try {
|
||||
currentLine.classList.add('mode3');
|
||||
currentLine.classList.remove('mode1');
|
||||
currentLine.classList.remove('mode2');
|
||||
} catch (e) {
|
||||
}
|
||||
currentLine.getElementsByClassName('WaitingDot3')[0].style.animation = `dotOpacity ${0.25 * duration}s cubic-bezier(0.42, 0, 0.58, 1) forwards`;
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.opacity = 1;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.opacity = 1;
|
||||
} else if (u >= 0.75 && currentLine.classList.contains('mode3')) {
|
||||
try {
|
||||
currentLine.classList.remove('mode1');
|
||||
currentLine.classList.remove('mode2');
|
||||
currentLine.classList.remove('mode3');
|
||||
} catch (e) {
|
||||
}
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.animation = ``;
|
||||
currentLine.getElementsByClassName('WaitingDot1')[0].style.opacity = 1;
|
||||
currentLine.getElementsByClassName('WaitingDot2')[0].style.opacity = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
this.getActiveLyric();
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
getActiveLyric() {
|
||||
// console.log(this.time);
|
||||
const delayfix = 0.35
|
||||
const prevLine = app.currentLyricsLine;
|
||||
for (var i = 0; i < this.lyrics.length; i++) {
|
||||
if (this.time + delayfix >= this.lyrics[i].startTime && this.time + delayfix <= app.lyrics[i].endTime) {
|
||||
if (app.currentLyricsLine != i) {
|
||||
app.currentLyricsLine = i;
|
||||
if (app.lyricon && this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`)) {
|
||||
this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`).classList.remove("active");
|
||||
this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`).classList.add("active")
|
||||
if (checkIfScrollIsStatic) {
|
||||
this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`).scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center"
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (app.currentLyricsLine == 0) {
|
||||
if (this.$refs.lyricsview.querySelector(`.lyric-line[line-index="0"]`) && !this.$refs.lyricsview.querySelector(`.lyric-line[line-index="0"]`).classList.contains("active"))
|
||||
this.$refs.lyricsview.querySelector(`.lyric-line[line-index="0"]`).classList.add("active");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
try{
|
||||
try{this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`).childNodes.classList.remove("verse-active");} catch(e){
|
||||
|
||||
}
|
||||
for (child of this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${app.currentLyricsLine}"]`).querySelectorAll(".verse")){
|
||||
if (this.time + 0.1 >= child.getAttribute("lyricstart") * 1 + child.getAttribute("versestart") * 1){
|
||||
child.classList.add("verse-active");
|
||||
} else {child.classList.remove("verse-active");}
|
||||
}
|
||||
} catch(e){}
|
||||
|
||||
},
|
||||
getActiveVerse(timeStart, timeEnd, verseTime) {
|
||||
let relativeTime = this.time - timeStart
|
||||
console.log(this.time,timeEnd,timeStart,relativeTime >= verseTime && relativeTime <= timeEnd - timeStart)
|
||||
return relativeTime >= verseTime && relativeTime <= timeEnd - timeStart
|
||||
},
|
||||
getVerseLine(index) {
|
||||
if (this.richlyrics[index] != null && this.richlyrics[index].l != null) {
|
||||
return this.richlyrics[index].l
|
||||
}
|
||||
else return []
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,62 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-artwork">
|
||||
<template v-if="type == 'artists'">
|
||||
<div class="mediaitem-artwork rounded" :key="url" :style="{'box-shadow': shadow ? 'var(--mediaItemShadow-Shadow)' : ''}">
|
||||
<img :src="app.getMediaItemArtwork(url, size)"
|
||||
class="mediaitem-artwork--img">
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="mediaitem-artwork" :key="url" :style="{'box-shadow': shadow ? 'var(--mediaItemShadow-Shadow)' : ''}"
|
||||
v-observe-visibility="{callback: visibilityChanged}">
|
||||
<img :src="app.getMediaItemArtwork(url, size)" v-if="isVisible"
|
||||
class="mediaitem-artwork--img">
|
||||
<div v-if="video && isVisible" class="animatedartwork-view-box">
|
||||
<animatedartwork-view :video="video"></animatedartwork-view>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-artwork', {
|
||||
template: '#mediaitem-artwork',
|
||||
props: {
|
||||
size: {
|
||||
type: String,
|
||||
default: '120'
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
video: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
shadow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
isVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getArtworkStyle() {
|
||||
return {
|
||||
width: this.size + 'px',
|
||||
height: this.size + 'px'
|
||||
};
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
this.isVisible = isVisible
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,32 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-hrect">
|
||||
<template>
|
||||
<div @click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
class="cd-mediaitem-hrect">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="70"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="info-rect">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis">
|
||||
{{ item.type }}
|
||||
<template v-if="item.attributes.artistName">
|
||||
∙ {{ item.attributes.artistName }}
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-hrect', {
|
||||
template: '#mediaitem-hrect',
|
||||
props: ['item'],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,269 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-list-item">
|
||||
<template>
|
||||
<div v-observe-visibility="{callback: visibilityChanged}"
|
||||
@contextmenu="contextMenu"
|
||||
@click="select"
|
||||
:data-id="item.attributes.playParams.id ?? item.id"
|
||||
:data-type="item.attributes.playParams.kind ?? item.type"
|
||||
:data-index="index"
|
||||
:data-guid="guid"
|
||||
class="cd-mediaitem-list-item"
|
||||
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}">
|
||||
<template v-if="isVisible">
|
||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||
<button @click="addToLibrary()"
|
||||
v-if="!app.isInLibrary(item.attributes.playParams) && !addedToLibrary">🖤
|
||||
</button>
|
||||
<button v-else>❤️</button>
|
||||
</div>
|
||||
<div class="artwork" v-if="showArtwork == true">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="50"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
<button class="overlay-play" @click="playTrack()"><%- include("../svg/play.svg") %></button>
|
||||
</div>
|
||||
<div class="info-rect" :style="{'padding-left': (showArtwork ? '' : '16px')}" @dblclick="playTrack()">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" style="-webkit-box-orient: horizontal;">
|
||||
<template v-if="item.attributes.artistName">
|
||||
<div class="artist item-navigate text-overflow-elipsis"
|
||||
@click="app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName }}
|
||||
</div>
|
||||
<template v-if="item.attributes.albumName"> - </template>
|
||||
<template v-if="item.attributes.albumName">
|
||||
<div class="artist item-navigate text-overflow-elipsis"
|
||||
@click="app.searchAndNavigate(item,'album')">
|
||||
{{ item.attributes.albumName }}
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-rating" v-if="item.attributes.contentRating" @dblclick="playTrack()">
|
||||
{{ item.attributes.contentRating }}
|
||||
</div>
|
||||
<template v-if="showMetaData == true" @dblclick="playTrack()">
|
||||
<div class="metainfo">
|
||||
{{ item.attributes.releaseDate ? new Date(item.attributes.releaseDate).toLocaleDateString()
|
||||
: "" }}
|
||||
</div>
|
||||
<div class="metainfo">
|
||||
{{ item.attributes.genreNames[0] ?? "" }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="duration" v-if="showDuration" @dblclick="playTrack()">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-list-item', {
|
||||
template: '#mediaitem-list-item',
|
||||
data: function () {
|
||||
return {
|
||||
isVisible: false,
|
||||
addedToLibrary: false,
|
||||
guid: uuidv4()
|
||||
}
|
||||
},
|
||||
props: {
|
||||
'item': {type: Object, required: true},
|
||||
'parent': {type: Object, required: false},
|
||||
'index': {type: Object, required: false, default: -1},
|
||||
'show-artwork': {type: Boolean, default: true},
|
||||
'show-library-status': {type: Boolean, default: true},
|
||||
'show-meta-data': {type: Boolean, default: false},
|
||||
'show-duration': {type: Boolean, default: true},
|
||||
},
|
||||
methods: {
|
||||
select(e) {
|
||||
if (e.shiftKey) {
|
||||
if (this.index != -1) {
|
||||
if(app.selectedMediaItems.length == 0) {
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
}
|
||||
let allMediaItems = document.querySelectorAll(".cd-mediaitem-list-item[data-index]")
|
||||
let startIndex = Math.min(...app.selectedMediaItems.map(item => item.index))
|
||||
let endIndex = Math.max(...app.selectedMediaItems.map(item => item.index))
|
||||
if (this.index < startIndex) {
|
||||
for (let i = this.index; i <= endIndex; i++) {
|
||||
let item = allMediaItems[i]
|
||||
if (item) {
|
||||
app.select_selectMediaItem(item.getAttribute("data-id"),
|
||||
item.getAttribute("data-type"),
|
||||
item.getAttribute("data-index"),
|
||||
item.getAttribute("data-guid"))
|
||||
}
|
||||
}
|
||||
} else if (this.index > endIndex) {
|
||||
for (let i = startIndex; i <= this.index; i++) {
|
||||
let item = allMediaItems[i]
|
||||
if (item) {
|
||||
app.select_selectMediaItem(item.getAttribute("data-id"),
|
||||
item.getAttribute("data-type"),
|
||||
item.getAttribute("data-index"),
|
||||
item.getAttribute("data-guid"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
let item = allMediaItems[i]
|
||||
if (item) {
|
||||
app.select_selectMediaItem(item.getAttribute("data-id"),
|
||||
item.getAttribute("data-type"),
|
||||
item.getAttribute("data-index"),
|
||||
item.getAttribute("data-guid"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.ctrlKey) {
|
||||
if (app.select_hasMediaItem(this.guid)) {
|
||||
app.select_removeMediaItem(this.guid)
|
||||
} else {
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
}
|
||||
} else {
|
||||
if (app.select_hasMediaItem(this.guid)) {
|
||||
app.selectedMediaItems = []
|
||||
} else {
|
||||
app.selectedMediaItems = []
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
}
|
||||
}
|
||||
},
|
||||
contextMenu(event) {
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
if (app.selectedMediaItems.length <= 1) {
|
||||
app.selectedMediaItems = []
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
} else {
|
||||
useMenu = "multiple"
|
||||
}
|
||||
let menus = {
|
||||
multiple: {
|
||||
items: [
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks next`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playNext({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
console.log(itemsToPlay)
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks later`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playLater({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
normal: {
|
||||
items: [
|
||||
{
|
||||
"name": "Start Radio",
|
||||
"action": function () {
|
||||
app.mk.setStationQueue({song: self.item.attributes.playParams.id ?? self.item.id}).then(() => {
|
||||
app.mk.play()
|
||||
app.selectedMediaItems = []
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Play Next",
|
||||
"action": function () {
|
||||
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Play Later",
|
||||
"action": function () {
|
||||
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Go to Artist",
|
||||
"action": function () {
|
||||
app.searchAndNavigate(self.item, 'artist')
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Go to Album",
|
||||
"action": function () {
|
||||
app.searchAndNavigate(self.item, 'album')
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
this.isVisible = isVisible
|
||||
},
|
||||
addToLibrary() {
|
||||
let item = this.item
|
||||
if (item.attributes.playParams.id) {
|
||||
console.log('adding to library', item.attributes.playParams.id)
|
||||
app.addToLibrary(item.attributes.playParams.id.toString())
|
||||
this.addedToLibrary = true
|
||||
} else if (item.id) {
|
||||
console.log('adding to library', item.id)
|
||||
app.addToLibrary(item.id.toString())
|
||||
this.addedToLibrary = true
|
||||
}
|
||||
},
|
||||
playTrack() {
|
||||
let item = this.item
|
||||
let parent = this.parent
|
||||
let childIndex = this.index
|
||||
console.log(item,parent,childIndex)
|
||||
if (parent != null && childIndex != null) {
|
||||
app.queueParentandplayChild(parent, childIndex);
|
||||
} else {
|
||||
app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,61 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-mvview-sp">
|
||||
<template>
|
||||
<div style="position: relative; display: inline-flex;">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-mvview">
|
||||
<div class="title-browse-sp bold " @click='app.routeView(item)'>
|
||||
{{ badge ? badge.designBadge : ""}}
|
||||
</div>
|
||||
<div class="title-browse-sp " >
|
||||
{{ (badge != null && badge.designTag != null) ? badge.designTag : (item.attributes.name ?? '') }}
|
||||
</div>
|
||||
<div class="title-browse-sp semibold" v-if="!(badge != null && badge.designTag != null)" >
|
||||
{{ (item.attributes.artistName ?? (item.attributes.curatorName ?? '')) }}
|
||||
</div>
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
:size="imagesize ?? 300"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-mvview-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '200px',
|
||||
'margin-left': '250px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'margin-left': '95px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cd-mediaitem-mvview-overlay" @click.self='app.routeView(item)' tabindex="0">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '200px',
|
||||
'margin-left': '250px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'margin-left': '95px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-mvview-sp', {
|
||||
template: '#mediaitem-mvview-sp',
|
||||
props: ['item', "imagesize","badge"],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,59 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-mvview">
|
||||
<template>
|
||||
<div style="position: relative; display: inline-flex;">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-mvview">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
:size="imagesize ?? 300"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-mvview-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
'margin-left': '250px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'margin-left': '95px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
||||
{{ item.attributes.name ?? '' }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis item-navigate" v-if="item.attributes.artistName" :style = "{'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : ''}" @click="if(item.attributes.artistName)app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName ?? '' }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-mvview-overlay" @click.self='app.routeView(item)' tabindex="0">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
'margin-left': '250px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'margin-left': '95px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-mvview', {
|
||||
template: '#mediaitem-mvview',
|
||||
props: ['item', "imagesize"],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,17 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-large">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square-large :item="item"
|
||||
v-for="item in items"></mediaitem-square-large>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-scroller-horizontal-large', {
|
||||
template: '#mediaitem-scroller-horizontal-large',
|
||||
props: ['items'],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,23 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-mvview">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<template v-if="browsesp">
|
||||
<mediaitem-mvview-sp :item="item ? (item.attributes.kind ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []" :imagesize="imagesize"
|
||||
:badge="item.attributes" v-for="item in items"></mediaitem-mvview-sp>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-mvview :item="item ? (item.attributes.kind ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []" :imagesize="imagesize"
|
||||
v-for="item in items"></mediaitem-mvview>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-scroller-horizontal-mvview', {
|
||||
template: '#mediaitem-scroller-horizontal-mvview',
|
||||
props: ['items',"imagesize","browsesp"],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,16 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-sp">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square-sp :item="item"
|
||||
v-for="item in items"></mediaitem-square-sp>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-scroller-horizontal-sp', {
|
||||
template: '#mediaitem-scroller-horizontal-sp',
|
||||
props: ['items'],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,16 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller">
|
||||
<mediaitem-square :item="item"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-scroller-horizontal', {
|
||||
template: '#mediaitem-scroller-horizontal',
|
||||
props: ['items'],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,171 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-square-large">
|
||||
<template>
|
||||
<div ref="main" style="position: relative; display: inline-flex;" @contextmenu="contextMenu">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-square-large" ref="main2">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
size="300"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px','position': 'absolute',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext() ">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
||||
{{ item.attributes.name ?? '' }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis item-navigate" v-if="item.attributes.artistName" :style = "{'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : ''}" @click="if(item.attributes.artistName)app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName ?? '' }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)' tabindex="0">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="console.log('as');contextMenu()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-square-large', {
|
||||
template: '#mediaitem-square-large',
|
||||
props: ['item'],
|
||||
methods: {
|
||||
clickContext() {
|
||||
var evt = document.createEvent('MouseEvent');
|
||||
var rect = this.$refs.main2.getBoundingClientRect();
|
||||
evt.initMouseEvent(
|
||||
"contextmenu",
|
||||
true /* bubble */, true /* cancelable */,
|
||||
window, null,
|
||||
0, 0, rect.x + 100, rect.y +100, /* coordinates */
|
||||
false, false, false, false, /* modifier keys */
|
||||
0 /*left*/, null
|
||||
);
|
||||
this.$refs.main.dispatchEvent(evt);
|
||||
}
|
||||
,contextMenu(event) {
|
||||
if (!event){event = this.$refs.main} else {console.log(event)}
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
if (app.selectedMediaItems.length <= 1) {
|
||||
app.selectedMediaItems = []
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
} else {
|
||||
useMenu = "multiple"
|
||||
}
|
||||
let menus = {
|
||||
multiple: {
|
||||
items: [
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks next`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playNext({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
console.log(itemsToPlay)
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks later`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playLater({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
normal: {
|
||||
items: [
|
||||
{
|
||||
"name": "Play Next",
|
||||
"action": function () {
|
||||
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Play Later",
|
||||
"action": function () {
|
||||
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},}
|
||||
});
|
||||
</script>
|
|
@ -1,179 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-square-sp">
|
||||
<template>
|
||||
<div ref="main" style="position: relative; display: inline-flex;" @contextmenu="contextMenu">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-square-sp" ref="main2" :style="{'--spcolor' : (item.attributes.artwork.bgColor != null) ? ('#'+item.attributes.artwork.bgColor) : `black`}">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px','position': 'absolute',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis"
|
||||
:style="{'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}" style="font-weight: 600">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis "
|
||||
:class="{'item-navigate': ((item.attributes.editorialNotes == null) && item.attributes.artistName)}"
|
||||
:style="{ 'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : '' ,'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}" style="padding-left: 4px;padding-right: 4px; display: -webkit-box;-webkit-box-orient: vertical; -webkit-line-clamp: 2;white-space: normal;"
|
||||
@click="if((item.attributes.editorialNotes == null) && item.attributes.artistName)app.searchAndNavigate(item,'artist')"
|
||||
>
|
||||
{{ (item.attributes.editorialNotes != null) ? item.attributes.editorialNotes.short
|
||||
:(item.attributes.artistName ?? '') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)' tabindex="0">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-square-sp', {
|
||||
template: '#mediaitem-square-sp',
|
||||
props: ['item'],
|
||||
methods: { clickContext() {
|
||||
var evt = document.createEvent('MouseEvent');
|
||||
var rect = this.$refs.main2.getBoundingClientRect();
|
||||
evt.initMouseEvent(
|
||||
"contextmenu",
|
||||
true /* bubble */, true /* cancelable */,
|
||||
window, null,
|
||||
0, 0, rect.x + 100, rect.y +100, /* coordinates */
|
||||
false, false, false, false, /* modifier keys */
|
||||
0 /*left*/, null
|
||||
);
|
||||
this.$refs.main.dispatchEvent(evt);
|
||||
}
|
||||
,contextMenu(event) {
|
||||
if (!event){event = this.$refs.main} else {console.log(event)}
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
if (app.selectedMediaItems.length <= 1) {
|
||||
app.selectedMediaItems = []
|
||||
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid)
|
||||
} else {
|
||||
useMenu = "multiple"
|
||||
}
|
||||
let menus = {
|
||||
multiple: {
|
||||
items: [
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks next`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playNext({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
console.log(itemsToPlay)
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks later`,
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
if (!itemsToPlay[item.kind]) {
|
||||
itemsToPlay[item.kind] = []
|
||||
}
|
||||
itemsToPlay[item.kind].push(item.id)
|
||||
})
|
||||
// loop through itemsToPlay
|
||||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playLater({[kind + "s"]: itemsToPlay[kind]})
|
||||
}
|
||||
}
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
normal: {
|
||||
items: [
|
||||
|
||||
{
|
||||
"name": "Play Next",
|
||||
"action": function () {
|
||||
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Play Later",
|
||||
"action": function () {
|
||||
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},}
|
||||
});
|
||||
</script>
|
|
@ -1,27 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-square">
|
||||
<template>
|
||||
<div tabindex="0" @click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
class="cd-mediaitem-square">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" v-if="item.attributes.artistName">
|
||||
{{ item.attributes.artistName }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-square', {
|
||||
template: '#mediaitem-square',
|
||||
props: ['item'],
|
||||
methods: {}
|
||||
});
|
||||
</script>
|
|
@ -1,60 +0,0 @@
|
|||
<script type="text/x-template" id="queue-item">
|
||||
<template>
|
||||
<div v-observe-visibility="{callback: visibilityChanged}"
|
||||
@contextmenu="contextMenu"
|
||||
class="cd-mediaitem-list-item">
|
||||
<template v-if="isVisible">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="34"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="info-rect" :style="{'padding-left': '16px'}">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" style="-webkit-box-orient: horizontal;">
|
||||
<template v-if="item.attributes.artistName" >
|
||||
<div class="artist item-navigate text-overflow-elipsis" @click="app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName }}
|
||||
</div>
|
||||
<template v-if="item.attributes.albumName"> - </template>
|
||||
<template v-if="item.attributes.albumName">
|
||||
<div class="artist item-navigate text-overflow-elipsis" @click="app.searchAndNavigate(item,'album')">
|
||||
{{ item.attributes.albumName }}
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="duration">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('queue-item', {
|
||||
template: '#queue-item',
|
||||
props: ['item'],
|
||||
data: function () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
contextMenu(event) {
|
||||
let self = this
|
||||
CiderContextMenu.Create(event, {
|
||||
items: [{
|
||||
"name": "Remove from queue",
|
||||
"action": function () {
|
||||
|
||||
}
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,137 +0,0 @@
|
|||
<script type="text/x-template" id="cider-queue">
|
||||
<div class="queue-panel">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3 class="queue-header-text">Queue</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<button class="autoplay" :style="{'background': app.mk.autoplayEnabled ? 'var(--keyColor)' : ''}" @click="app.mk.autoplayEnabled = !app.mk.autoplayEnabled">AUTO</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="queue-body">
|
||||
<draggable v-model="queueItems" @start="drag=true" @end="drag=false;move()">
|
||||
<template v-for="(queueItem, position) in queueItems">
|
||||
<div v-if="position <= queuePosition" style="display: none;">{{ position }}</div>
|
||||
<div class="cd-queue-item"
|
||||
:class="{selected: selectedItems.includes(position)}"
|
||||
@click="select($event, position)"
|
||||
@dblclick="playQueueItem(position)" v-else :key="position"
|
||||
@contextmenu="selected = position;queueContext($event, queueItem.item, position)">
|
||||
<div class="row">
|
||||
<div class="col-auto flex-center">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork :url="queueItem.item.attributes.artwork ? queueItem.item.attributes.artwork.url : ''" :size="32"></mediaitem-artwork>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col queue-info">
|
||||
<div class="queue-title text-overflow-elipsis">{{ queueItem.item.attributes.name }}</div>
|
||||
<div class="queue-subtitle text-overflow-elipsis">{{ queueItem.item.attributes.albumName }} - {{ queueItem.item.attributes.artistName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="queue-footer">
|
||||
<button class="md-btn" style="width:100%;" v-if="queueItems.length > 1" @click="app.mk.clearQueue();updateQueue()">Clear All</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
Vue.component('cider-queue', {
|
||||
template: '#cider-queue',
|
||||
data: function () {
|
||||
return {
|
||||
drag: false,
|
||||
queuePosition: 0,
|
||||
queueItems: [],
|
||||
selected: -1,
|
||||
selectedItems: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateQueue()
|
||||
},
|
||||
methods: {
|
||||
select(e, position) {
|
||||
if(e.ctrlKey || e.shiftKey) {
|
||||
if(this.selectedItems.indexOf(position) == -1) {
|
||||
this.selectedItems.push(position)
|
||||
} else {
|
||||
this.selectedItems.splice(this.selectedItems.indexOf(position), 1)
|
||||
}
|
||||
} else {
|
||||
this.selectedItems = [position]
|
||||
}
|
||||
},
|
||||
queueContext(event, item, position) {
|
||||
let self = this
|
||||
let useMenu = "single"
|
||||
if(this.selectedItems.length > 1) {
|
||||
useMenu = "multiple"
|
||||
}
|
||||
let menus = {
|
||||
single: {
|
||||
items: [{
|
||||
"name": "Remove from queue",
|
||||
"action": function () {
|
||||
self.queueItems.splice(position, 1)
|
||||
app.mk.queue._queueItems = self.queueItems;
|
||||
app.mk.queue._reindex()
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Start Radio",
|
||||
"action": function () {
|
||||
app.mk.setStationQueue({
|
||||
song: item.attributes.playParams.id ?? item.id
|
||||
}).then(() => {
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
multiple: {
|
||||
items: [{
|
||||
"name": `Remove ${self.selectedItems.length} tracks from queue`,
|
||||
"action": function () {
|
||||
// add property to items to be removed
|
||||
self.selectedItems.forEach(function (item) {
|
||||
self.queueItems[item].remove = true
|
||||
})
|
||||
// remove items
|
||||
self.queueItems = self.queueItems.filter(function (item) {
|
||||
return !item.remove
|
||||
})
|
||||
app.mk.queue._reindex()
|
||||
self.selectedItems = []
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu]);
|
||||
},
|
||||
playQueueItem(index) {
|
||||
app.mk.changeToMediaAtIndex(index)
|
||||
},
|
||||
updateQueue() {
|
||||
this.selected = -1
|
||||
if (app.mk.queue) {
|
||||
this.queuePosition = app.mk.queue.position;
|
||||
this.queueItems = app.mk.queue._queueItems;
|
||||
} else {
|
||||
this.queuePosition = 0;
|
||||
this.queueItems = [];
|
||||
}
|
||||
},
|
||||
move() {
|
||||
this.selected = -1
|
||||
app.mk.queue._queueItems = this.queueItems;
|
||||
app.mk.queue._reindex()
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,507 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<link rel="preconnect" href="https://amp-api.music.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://api.music.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is1-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is2-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is3-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is4-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://is5-ssl.mzstatic.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://play.itunes.apple.com/" crossorigin/>
|
||||
<link rel="preconnect" href="https://aod-ssl.itunes.apple.com/" crossorigin/>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<title>Cider</title>
|
||||
<link rel="stylesheet/less" type="text/css" href="style.less"/>
|
||||
<script src="less.js"></script>
|
||||
<script src="vue.js"></script>
|
||||
<script src="sortable.min.js"></script>
|
||||
<script src="vue-observe-visibility.min.js"></script>
|
||||
<script src="sortable.min.js"></script>
|
||||
<script src="vuedraggable.umd.min.js"></script>
|
||||
<link rel="manifest" href="./manifest.json?v=2">
|
||||
<script src="https://js-cdn.music.apple.com/hls.js/2.141.0/hls.js/hls.js"></script>
|
||||
<script src="hlscider.js"></script>
|
||||
</head>
|
||||
|
||||
<body oncontextmenu="return false;" loading="1" platform="<%= env.platform %>">
|
||||
<div id="app">
|
||||
<div id="app-main">
|
||||
<div class="mv-chrome" v-if="chrome.topChromeVisible == false"></div>
|
||||
<div class="app-chrome" :style="{'display': chrome.topChromeVisible ? '' : 'none'}">
|
||||
<div class="app-chrome--left">
|
||||
<div class="app-chrome-item full-height">
|
||||
<div class="app-title"></div>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||
@click="mk.shuffleMode = 1"></button>
|
||||
<button class="playback-button--small shuffle active" v-else
|
||||
@click="mk.shuffleMode = 0"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button previous" @click="mk.skipToPreviousItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button pause" @click="mk.pause()" v-if="mk.isPlaying"></button>
|
||||
<button class="playback-button play" @click="mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||
@click="mk.repeatMode = 1"></button>
|
||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 2"
|
||||
v-else-if="mk.repeatMode == 1"></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 0"
|
||||
v-else-if="mk.repeatMode == 2"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome--center">
|
||||
<div class="app-chrome-item playback-controls">
|
||||
<template v-if="mkReady()">
|
||||
<div class="app-playback-controls" @mouseover="chrome.progresshover = true" @mouseleave="chrome.progresshover = false">
|
||||
<div class="artwork"></div>
|
||||
<div class="playback-info">
|
||||
<div class="song-name" >
|
||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||
</div>
|
||||
<div class="song-artist " style="display: inline-block; -webkit-box-orient: horizontal; white-space: nowrap;">
|
||||
<div class="item-navigate song-artist" style="display: inline-block;" @click="app.getNowPlayingItemDetailed(`artist`)">
|
||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||
</div>
|
||||
<div class="song-artist item-navigate" style="display: inline-block;" @click="app.getNowPlayingItemDetailed('album')">
|
||||
{{ (mk.nowPlayingItem["attributes"]["albumName"]) ? (" - " + mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="song-progress">
|
||||
<div class="song-duration" style="justify-content: space-between; height: 1px;" :style="[chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
|
||||
<p style="width: auto">{{ convertToMins(getSongProgress()) }}</p>
|
||||
<p style="width: auto">{{ convertToMins(mk.currentPlaybackDuration) }}</p>
|
||||
</div>
|
||||
|
||||
<input type="range" step="0.01" min="0" :style="progressBarStyle()"
|
||||
@input="playerLCD.desiredDuration = $event.target.value;playerLCD.userInteraction = true"
|
||||
@mouseup="mk.seekToTime($event.target.value);playerLCD.desiredDuration = 0;playerLCD.userInteraction = false"
|
||||
:max="mk.currentPlaybackDuration" :value="getSongProgress()">
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="mk.nowPlayingItem['attributes']['playParams']">
|
||||
<div class="actions" v-if="isInLibrary(mk.nowPlayingItem['attributes']['playParams'])">
|
||||
❤️
|
||||
</div>
|
||||
<div class="actions" v-else>🖤</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome--right">
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<input type="range" class="" step="0.01" min="0" max="1" v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small">
|
||||
<%- include("svg/cast.svg") %>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small queue" :class="{'active': drawer.panel == 'queue'}" @click="invokeDrawer('queue')"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button class="playback-button--small lyrics" :class="{'active': drawer.panel == 'lyrics'}"
|
||||
@click="invokeDrawer('lyrics')"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item full-height">
|
||||
<div class="window-controls">
|
||||
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
||||
<div class="minmax restore" v-if="chrome.maximized" @click="ipcRenderer.send('maximize')">
|
||||
</div>
|
||||
<div class="minmax" v-else @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="close" @click="ipcRenderer.send('close')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-navigation" v-cloak>
|
||||
<div id="app-sidebar">
|
||||
<div class="app-sidebar-header">
|
||||
<div class="search-input-container">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search" spellcheck="false" @click="showSearch()"
|
||||
@focus="search.showHints = true"
|
||||
@blur="setTimeout(()=>{search.showHints = false}, 100)"
|
||||
v-on:keyup.enter="searchQuery();search.showHints = false"
|
||||
@change="showSearch();" @input="getSearchHints()" placeholder="Search..."
|
||||
v-model="search.term"
|
||||
ref="searchInput"
|
||||
class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-hints-container" v-if="search.showHints && search.hints.length != 0">
|
||||
<div class="search-hints">
|
||||
<button class="search-hint" v-for="hint in search.hints"
|
||||
@click="search.term = hint;search.showHints = false;searchQuery(hint)">
|
||||
{{ hint }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-sidebar-content">
|
||||
<div class="app-sidebar-header-text">
|
||||
Apple Music
|
||||
</div>
|
||||
<sidebar-library-item name="Listen Now" page="listen_now"></sidebar-library-item>
|
||||
<sidebar-library-item name="Browse" page="browse"></sidebar-library-item>
|
||||
<sidebar-library-item name="Radio" page="radio"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text">
|
||||
Library
|
||||
</div>
|
||||
<sidebar-library-item name="Recently Added" page="library-recentlyadded"></sidebar-library-item>
|
||||
<sidebar-library-item name="Songs" page="library-songs"></sidebar-library-item>
|
||||
<sidebar-library-item name="Albums" page="library-albums"></sidebar-library-item>
|
||||
<sidebar-library-item name="Artists" page="library-artists"></sidebar-library-item>
|
||||
<sidebar-library-item name="Made For You" page="library-madeforyou"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text">
|
||||
Playlists
|
||||
</div>
|
||||
<button class="app-sidebar-item" v-for="item in playlists.listing" :key="item.id"
|
||||
:href="item.href"
|
||||
@click='appRoute(`playlist_` + item.id); showingPlaylist = [];getPlaylistFromID(app.page.substring(9))'>
|
||||
{{ item.attributes.name }}
|
||||
</button>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<div class="usermenu-container" v-if="chrome.menuOpened">
|
||||
<div class="usermenu-body">
|
||||
<button class="usermenu-item" @click="chrome.hideUserInfo = !chrome.hideUserInfo">
|
||||
Toggle Personal Info
|
||||
</button>
|
||||
<button class="usermenu-item">
|
||||
About
|
||||
</button>
|
||||
<button class="usermenu-item" @click="window.open('https://discord.gg/CezHYdXHEM')">
|
||||
Discord
|
||||
</button>
|
||||
<button class="usermenu-item" @click="page = 'settings'">
|
||||
Settings
|
||||
</button>
|
||||
<button class="usermenu-item" @click="mk.unauthorize()">
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<div class="app-sidebar-footer">
|
||||
<input type="range" class="web-slider display--small" step="0.01" min="0" max="1"
|
||||
v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
<button class="app-sidebar-button" style="width:100%"
|
||||
:class="{active: chrome.menuOpened}"
|
||||
@blur="setTimeout(()=>{chrome.menuOpened = false}, 100)"
|
||||
@click="(chrome.userinfo.id) ? chrome.menuOpened = !chrome.menuOpened : false">
|
||||
|
||||
<img class="sidebar-user-icon" loading="lazy"
|
||||
:src="getMediaItemArtwork(chrome.hideUserInfo ? 'http://localhost:9000/assets/logocut.png' : (chrome.userinfo.attributes['artwork'] ? chrome.userinfo.attributes['artwork']['url'] : ''), 26)"/>
|
||||
|
||||
<div class="sidebar-user-text" v-if="!chrome.hideUserInfo">
|
||||
<template v-if="chrome.userinfo.id">
|
||||
<div class="fullname text-overflow-elipsis">{{ chrome.userinfo.attributes.name }}
|
||||
</div>
|
||||
<div class="handle-text text-overflow-elipsis">@{{ chrome.userinfo.attributes.handle
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div @click="mk.authorize()">
|
||||
Sign In
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="sidebar-user-text" v-else>
|
||||
Cider
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-sidebar-notification" v-if="library.downloadNotification.show">
|
||||
<div>{{ library.downloadNotification.message }}</div>
|
||||
<div>{{ library.downloadNotification.progress }} / {{ library.downloadNotification.total }}</div>
|
||||
<div style="width: 100%">
|
||||
<progress style="width: 80%;" :value="library.downloadNotification.progress"
|
||||
:max="library.downloadNotification.total"></progress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app-content">
|
||||
<div id="navigation-bar">
|
||||
<button class="nav-item" @click="history.back()"><%- include('svg/chevron-left.svg') %></button>
|
||||
<button class="nav-item" @click="history.forward()"><%- include('svg/chevron-right.svg') %></button>
|
||||
</div>
|
||||
<!-- Artist Page -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'artist-page' && artistPage.data.attributes">
|
||||
<cider-artist :data="artistPage.data"></cider-artist>
|
||||
</template>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<%- include('pages/zoo') %>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<%- include('pages/webview') %>
|
||||
</transition>
|
||||
<!-- Collection List -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'collection-list'">
|
||||
<cider-collection-list :data="collectionList.response" :type="collectionList.type" :title="collectionList.title"></cider-collection-list>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Playlist / Album page-->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('playlist_')">
|
||||
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
||||
</template>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('album_')">
|
||||
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
||||
</template>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('recordLabel_')">
|
||||
<cider-recordlabel :data="showingPlaylist"></cider-recordlabel>
|
||||
</template>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<template v-if="page.includes('curator_')">
|
||||
<cider-recordlabel :data="showingPlaylist"></cider-recordlabel>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Browse -->
|
||||
<transition v-on:enter="app.getBrowsePage(); console.log('browse')" name="wpfade">
|
||||
<template v-if="page == 'browse'">
|
||||
<!-- <div class="content-inner">
|
||||
|
||||
<button id="apple-music-authorize" class="md-btn md-btn-primary" @click="init()">Start
|
||||
MusicKit
|
||||
</button>
|
||||
<button id="apple-music-unauthorize" class="md-btn md-btn-primary"
|
||||
@click="unauthorize()">
|
||||
Stop
|
||||
MusicKit
|
||||
</button>
|
||||
<br>
|
||||
<template v-if="mk.nowPlayingItem">
|
||||
currentPlaybackProgress: {{ app.mk.currentPlaybackProgress }}
|
||||
<br>
|
||||
currentPlaybackDuration: {{ app.mk.currentPlaybackDuration }}
|
||||
</template>
|
||||
<div><input type="text" v-model="quickPlayQuery">
|
||||
<button @click="quickPlay(quickPlayQuery)">Play</button>
|
||||
</div>
|
||||
<h1 class="header-text">Browse</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, urna eu
|
||||
tincidunt
|
||||
consectetur, nisl nunc euismod nisi, eu porttitor nisl nisi euismod nisi.
|
||||
</p>
|
||||
<div class="media-item--small">
|
||||
<div class="artwork">
|
||||
|
||||
</div>
|
||||
<div class="text">
|
||||
Text
|
||||
</div>
|
||||
<div class="subtext">
|
||||
Subtext
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h1 class="header-text">Listen Now</h1>
|
||||
<div class="winbox">
|
||||
<div class="fancy">990kbps</div>
|
||||
<div class="">
|
||||
<button class="md-btn md-btn-primary">Audio Quality Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="md-btn" @click="drawertest = !drawertest">Toggle Drawer</button>
|
||||
<button class="md-btn">Button</button>
|
||||
<button class="md-btn md-btn-primary">Button</button>
|
||||
</div> -->
|
||||
<cider-browse :data="browsepage"></cider-browse>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Listen Now -->
|
||||
<transition v-on:enter="getListenNow()" name="wpfade">
|
||||
<template v-if="page == 'listen_now'" @created="console.log('listennow')">
|
||||
<cider-listen-now :data="listennow"></cider-listen-now>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Radio -->
|
||||
<transition v-on:enter="getRadioStations()" name="wpfade">
|
||||
<template v-if="page == 'radio'" @created="console.log('radio')">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Radio</h1>
|
||||
<h3>Recent Stations</h3>
|
||||
<mediaitem-square :item="item" v-for="item in radio.personal"></mediaitem-square>
|
||||
</div>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Settings -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'settings'">
|
||||
<cider-settings></cider-settings>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Search -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'search'">
|
||||
<cider-search :search="search"></cider-search>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Library - Songs -->
|
||||
<transition name="wpfade" v-on:enter="getLibrarySongsFull()">
|
||||
<%- include('pages/library-songs') %>
|
||||
</transition>
|
||||
<!-- Library - Albums -->
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbumsFull()">
|
||||
<%- include('pages/library-albums') %>');
|
||||
%>
|
||||
</transition>
|
||||
</div>
|
||||
<transition name="drawertransition">
|
||||
<div class="app-drawer" v-if="drawer.open">
|
||||
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="lyriccurrenttime" :lyrics="lyrics" :richlyrics="richlyrics"></lyrics-view>
|
||||
<cider-queue ref="queue" v-if="drawer.panel == 'queue'"></cider-queue>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<img v-show="chrome.artworkReady" @load="chrome.artworkReady = true" class="bg-artwork"
|
||||
>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<div class="bg-artwork--placeholder" v-else></div>
|
||||
</transition>
|
||||
<div id="apple-music-video-container">
|
||||
<div id="apple-music-video-player-controls">
|
||||
<div id="player-exit" title="Close" onclick="app.exitMV()">
|
||||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"
|
||||
aria-role="presentation" focusable="false">
|
||||
<path
|
||||
d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
||||
fill-rule="nonzero"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="captions">{{((lyricon) ? ((lyrics.length > 0 ) ?
|
||||
lyrics[currentLyricsLine].line.replace('lrcInstrumental','') : "") : '') + ((lyricon) ? ((lyrics.length > 0 ) ?
|
||||
(lyrics[currentLyricsLine].translation ? ('\n\r' + lyrics[currentLyricsLine].translation) : ""): "") : '')}}
|
||||
</div>
|
||||
<div id="player-pip" @click="document.querySelector('video#apple-music-video-player').requestPictureInPicture()"
|
||||
title="Picture-in-Picture">
|
||||
<%- include("svg/fullscreen.svg") %>
|
||||
</div>
|
||||
<div id="player-fullscreen" @click="document.querySelector('video#apple-music-video-player').requestFullscreen()"
|
||||
title="Fullscreen">
|
||||
<%- include("svg/fullscreen.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div id="apple-music-video-player"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%- include("components/mediaitem-artwork"); %>
|
||||
|
||||
<!-- Generic Collection of MediaItems -->
|
||||
<script type="text/x-template" id="collection-view-generic">
|
||||
<template>
|
||||
<div class="content-inner">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<!-- Browse -->
|
||||
<%- include('pages/browse') %>
|
||||
|
||||
<!-- Settings -->
|
||||
<%- include('pages/settings') %>
|
||||
|
||||
<!-- Listen Now -->
|
||||
<%- include('pages/listen_now') %>
|
||||
|
||||
<!-- Playlists / Albums -->
|
||||
<%- include('pages/cider-playlist') %>
|
||||
|
||||
<!-- Record Label -->
|
||||
<%- include('pages/recordLabel') %>
|
||||
|
||||
<!-- Collection List -->
|
||||
<%- include('pages/collection-list') %>
|
||||
|
||||
<!-- Artist Page -->
|
||||
<%- include('pages/artist') %>
|
||||
|
||||
<!-- Search -->
|
||||
<%- include('pages/search') %>
|
||||
|
||||
<script type="text/x-template" id="am-musiccovershelf">
|
||||
<h1>{{ component.attributes.title.stringForDisplay }}</h1>
|
||||
</script>
|
||||
|
||||
<!-- Sidebar Item -->
|
||||
<script type="text/x-template" id="sidebar-library-item">
|
||||
<button class="app-sidebar-item"
|
||||
:class="$parent.getSidebarItemClass(page)" @click="app.appRoute(page)">
|
||||
{{ name }}
|
||||
</button>
|
||||
</script>
|
||||
|
||||
<!-- Queue -->
|
||||
<%- include('components/queue') %>
|
||||
<!-- Queue Item -->
|
||||
<%- include('components/queue-item') %>
|
||||
<!-- Horizontal MediaItem Scroller -->
|
||||
<%- include('components/mediaitem-scroller-horizontal') %>
|
||||
<!-- Horizontal MediaItem Scroller (Large) -->
|
||||
<%- include('components/mediaitem-scroller-horizontal-large') %>
|
||||
<!-- Horizontal MediaItem Scroller (SP : Special) -->
|
||||
<%- include('components/mediaitem-scroller-horizontal-sp') %>
|
||||
<!-- Horizontal MediaItem Scroller (MV) -->
|
||||
<%- include('components/mediaitem-scroller-horizontal-mvview') %>
|
||||
<!-- MediaItem List Item -->
|
||||
<%- include('components/mediaitem-list-item') %>
|
||||
<!-- MediaItem Horizontal Rectangle -->
|
||||
<%- include('components/mediaitem-hrect') %>
|
||||
<!-- MediaItem Square -->
|
||||
<%- include('components/mediaitem-square') %>
|
||||
<!-- MediaItem Square (Large) -->
|
||||
<%- include('components/mediaitem-square-large') %>
|
||||
<!-- MediaItem Square SP -->
|
||||
<%- include('components/mediaitem-square-sp') %>
|
||||
<!-- MediaItem MusicVideo -->
|
||||
<%- include('components/mediaitem-mvview') %>
|
||||
<!-- MediaItem MusicVideo SP -->
|
||||
<%- include('components/mediaitem-mvview-sp') %>
|
||||
<!-- Animated Artwork View -->
|
||||
<%- include('components/animatedartwork-view') %>
|
||||
<!-- Lyrics View -->
|
||||
<%- include('components/lyrics-view') %>
|
||||
|
||||
<script src="musickit.js?v=1"></script>
|
||||
<script>
|
||||
if (typeof MusicKit == 'undefined') {
|
||||
document.write(unescape("%3Cscript src='https://js-cdn.music.apple.com/musickit/v2/amp/musickit.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
}
|
||||
</script>
|
||||
<script src="index.js?v=1"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,19 +0,0 @@
|
|||
Major thanks to the Cider Development Team and all of our contributors.
|
||||
|
||||
<p>"Apple Music" - Copyright © 2021 <a href="https://www.apple.com/" class="dt-footer__link"
|
||||
target="_blank"
|
||||
rel="noopener" data-dt-link-to-exclude="">Apple Inc.</a>
|
||||
All Rights
|
||||
Reserved.</p>
|
||||
|
||||
cryptofyre - Developer - https://github.com/cryptofyre
|
||||
Core - Developer - https://github.com/coredev-uk
|
||||
Quacksire - Developer - https://github.com/child-duckling
|
||||
booploops - Developer - https://github.com/booploops
|
||||
vapormusic - Developer - https://github.com/vapormusic
|
||||
Void - Social Communications Team - https://twitter.com/MoonyVoid
|
||||
NoseySG - Social Communications Team - https://twitter.com/noah_grose
|
||||
|
||||
<img class="md-contributors"
|
||||
onclick="window.open('https://github.com/ciderapp/Cider/graphs/contributors')"
|
||||
src="https://contrib.rocks/image?repo=ciderapp/Cider"/>
|
|
@ -1,173 +0,0 @@
|
|||
<script type="text/x-template" id="cider-artist">
|
||||
<div class="content-inner artist-page">
|
||||
<div class="artist-header" :style="getArtistPalette(data)">
|
||||
<animatedartwork-view
|
||||
v-if="data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)"
|
||||
:video="data.attributes.editorialVideo.motionArtistWide16x9.video ?? (data.attributes.editorialVideo.motionArtistFullscreen16x9.video ?? '')">
|
||||
</animatedartwork-view>
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;">
|
||||
<div class="artist-image" v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9))">
|
||||
<mediaitem-artwork
|
||||
:shadow="true"
|
||||
|
||||
:url="data.attributes.artwork ? data.attributes.artwork.url : ''"
|
||||
size="220" type="artists"></mediaitem-artwork>
|
||||
<button class="overlay-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col flex-center artist-title"
|
||||
:class="{'artist-animation-on': (data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)) }"
|
||||
>
|
||||
<button class="artist-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})"><%- include("../svg/play.svg") %></button>
|
||||
<h1>{{ data.attributes.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<button class="artist-more" @click="artistMenu"></button>
|
||||
</div>
|
||||
<div class="artist-body">
|
||||
<div class="row well">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col-auto" v-if="data.views['latest-release'].data.length != 0">
|
||||
<h3>Latest Release</h3>
|
||||
<div style="width: auto;margin: 0 auto;">
|
||||
<mediaitem-square-sp v-for="song in data.views['latest-release'].data"
|
||||
:item="song">
|
||||
</mediaitem-square-sp>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col" v-if="data.views['top-songs']">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h3>Top Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 10" style="padding:0px;">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - Top Songs', 'top-songs')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-list-item
|
||||
v-for="(song, index) in data.views['top-songs'].data.limit(topSongsExpanded ? 10 : 5)"
|
||||
:index="index"
|
||||
:item="song"></mediaitem-list-item>
|
||||
<button class="showmoreless"
|
||||
@click="topSongsExpanded = !topSongsExpanded">
|
||||
<template v-if="!topSongsExpanded">
|
||||
Show more
|
||||
</template>
|
||||
<template v-else>
|
||||
Show less
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row well">
|
||||
<div class="col">
|
||||
<template v-for="(view) in data.meta.views.order"
|
||||
v-if="(data.views[view].data.length != 0) && (view != 'latest-release') && (view != 'top-songs')">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : "???"}}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views[view].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - ' + data.views[view].attributes.title, view)">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!((data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('Video') || (data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('More To See'))">
|
||||
<mediaitem-scroller-horizontal-large :items="data.views[view].data.limit(10)">
|
||||
</mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="data.views[view].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
<div class="row">
|
||||
<div class="col" v-if="data.attributes.artistBio">
|
||||
<h3>About {{ data.attributes.name }}</h3>
|
||||
<p v-html="data.attributes.artistBio"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div v-if="data.attributes.origin">
|
||||
<h3>{{ data.attributes.isGroup ? "Origin" : "Hometown" }}</h3>
|
||||
{{ data.attributes.origin }}
|
||||
</div>
|
||||
<div v-if="data.attributes.bornOrFormed">
|
||||
<h3>{{ data.attributes.isGroup ? "Formed" : "Born" }}</h3>
|
||||
{{ data.attributes.bornOrFormed }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-artist', {
|
||||
template: "#cider-artist",
|
||||
props: ['data'],
|
||||
data: function () {
|
||||
return {
|
||||
topSongsExpanded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
artistMenu (event) {
|
||||
let self = this
|
||||
CiderContextMenu.Create(event, {
|
||||
items: [
|
||||
{
|
||||
name: "Play Artist Radio",
|
||||
action: ()=>{
|
||||
app.mk.setStationQueue({artist:self.data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Follow Artist",
|
||||
action: ()=>{}
|
||||
},
|
||||
{
|
||||
name: "Share",
|
||||
action: ()=>{}
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
getArtistPalette(artist) {
|
||||
if (artist["attributes"]["artwork"]) {
|
||||
return {
|
||||
"background": "#" + artist["attributes"]["artwork"]["bgColor"],
|
||||
"color": "#" + artist["attributes"]["artwork"]["textColor1"],
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
"background": "#000000",
|
||||
"color": "#ffffff",
|
||||
}
|
||||
}
|
||||
},
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,37 +0,0 @@
|
|||
<script type="text/x-template" id="cider-browse">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Browse</h1>
|
||||
<template v-if="data.relationships && data.relationships.tabs">
|
||||
<template v-for="(recom,index) in data.relationships.tabs.data[0].relationships.children.data">
|
||||
<div class="row">
|
||||
<div class="col" v-if="recom.attributes.name != 'Chart Set'">
|
||||
<h3>{{ recom.attributes.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="index != 0 && recom.relationships && ((recom.relationships.children && recom.relationships.children.data.length > 10) || (recom.relationships.contents && recom.relationships.contents.data.length > 10))">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(recom.relationships.children ? recom.relationships.children : recom.relationships.contents, recom.attributes.name ?? '', 'listen_now')" >See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.relationships && ((recom.relationships.children && recom.relationships.children.data) || (recom.relationships.contents && recom.relationships.contents.data))">
|
||||
<template v-if="(['385']).includes(recom.attributes.editorialElementKind) || index === 0">
|
||||
<mediaitem-scroller-horizontal-mvview :imagesize="800" :browsesp="index == 0"
|
||||
:items="recom.relationships.children ? recom.relationships.children.data.limit(10) : recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
<template v-else-if="recom.attributes.name == 'Chart Set'">
|
||||
<!-- ignored -->
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.children ? recom.relationships.children.data.limit(10) : recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-browse', {
|
||||
template: "#cider-browse",
|
||||
props: ["data"]
|
||||
})
|
||||
</script>
|
|
@ -1,90 +0,0 @@
|
|||
<script type="text/x-template" id="cider-playlist">
|
||||
<template v-if="data != [] && data.attributes != null">
|
||||
<div class="content-inner playlist-page" :style="{'--bgColor': (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : ''}">
|
||||
<div class="playlist-display row"
|
||||
:style="{
|
||||
background: (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : '',
|
||||
color: (data.attributes.artwork != null && data.attributes.artwork['textColor1'] != null) ? ('#' + data.attributes.artwork.textColor1) : ''
|
||||
}">
|
||||
<div class="col-auto flex-center">
|
||||
<div style="width: 260px;height:260px;">
|
||||
<mediaitem-artwork
|
||||
:url="(data.attributes != null && data.attributes.artwork && data.attributes.artwork != null) ? data.attributes.artwork.url : ((data.relationships != null && data.relationships.tracks.data.length > 0) ? data.relationships.tracks.data[0].attributes.artwork.url ?? '':'')"
|
||||
:video="(data.attributes != null && data.attributes.editorialVideo != null) ? (data.attributes.editorialVideo.motionDetailSquare ? data.attributes.editorialVideo.motionDetailSquare.video : (data.attributes.editorialVideo.motionSquareVideo1x1 ? data.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
size="260"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col playlist-info">
|
||||
<template v-if="!editorialNotesExpanded">
|
||||
<div>
|
||||
<div class="playlist-name">{{data.attributes ? (data.attributes.name ??
|
||||
(data.attributes.title ?? '') ?? '') : ''}}
|
||||
</div>
|
||||
<div class="playlist-artist item-navigate" v-if="data.attributes && data.attributes.artistName" @click="if(data.attributes && data.attributes.artistName){ app.searchAndNavigate(data,'artist')}">
|
||||
{{data.attributes ? (data.attributes.artistName ?? '') :''}}
|
||||
</div>
|
||||
<div class="playlist-desc" v-if="data.attributes.editorialNotes">
|
||||
<div class="content"
|
||||
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.standard ?? (data.attributes.editorialNotes.short ?? '') ) : (data.attributes.description ? (data.attributes.description.standard ?? (data.attributes.description.short ?? '')) : ''))"></div>
|
||||
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">
|
||||
More
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="editorialNotesExpanded">
|
||||
<div class="playlist-desc-expanded">
|
||||
<div class="content"
|
||||
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.standard ?? (data.attributes.editorialNotes.short ?? '') ) : (data.attributes.description ? (data.attributes.description.standard ?? (data.attributes.description.short ?? '')) : ''))"></div>
|
||||
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">Less
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="playlist-controls">
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 0;app.playMediaItemById(data.attributes.playParams.id ?? data.id, data.attributes.playParams.kind ?? data.type, data.attributes.playParams.isLibrary ?? false, data.attributes.url)">
|
||||
Play
|
||||
</button>
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 1;app.playMediaItemById(data.attributes.playParams.id ?? data.id, data.attributes.playParams.kind ?? data.type, data.attributes.playParams.isLibrary ?? false, data.attributes.url)">
|
||||
Shuffle
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="playlist-body">
|
||||
<div class="well">
|
||||
<mediaitem-list-item :item="item" :parent="getItemParent(data)" :index="index"
|
||||
v-for="(item,index) in data.relationships.tracks.data"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="playlist-time">
|
||||
{{data.attributes.releaseDate}}
|
||||
</div>
|
||||
<div class="playlist-time item-navigate" @click="app.searchAndNavigate(data,'recordLabel') " style="width: 50%;">
|
||||
{{data.attributes.copyright}}
|
||||
</div>
|
||||
<div class="playlist-time">{{app.getTotalTime()}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-playlist', {
|
||||
template: "#cider-playlist",
|
||||
props: ["data"],
|
||||
data: function () {
|
||||
return {
|
||||
editorialNotesExpanded: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getItemParent: function (data) {
|
||||
kind = data.attributes.playParams.kind;
|
||||
id = data.attributes.playParams.id;
|
||||
return `${kind}:${id}`
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,124 +0,0 @@
|
|||
<script type="text/x-template" id="cider-collection-list">
|
||||
<div class="content-inner collection-page">
|
||||
<h3 class="header-text" v-observe-visibility="{callback: headerVisibility}">{{ title }}</h3>
|
||||
<div v-if="data['data'] != 'null'" class="well">
|
||||
<template v-for="(item, key) in data.data">
|
||||
<template v-if="item.type == 'artists'">
|
||||
<mediaitem-square-large :item="item"></mediaitem-square-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-list-item
|
||||
v-if="item.attributes.playParams.kind == 'song'"
|
||||
:index="key"
|
||||
:item="item"></mediaitem-list-item>
|
||||
<mediaitem-mvview v-else-if="item.attributes.playParams.kind == 'musicVideo'" :item="item"></mediaitem-mvview>
|
||||
<mediaitem-square-large v-else :item="item"></mediaitem-square-large>
|
||||
</template>
|
||||
</template>
|
||||
<button v-if="triggerEnabled" style="opacity:0;height: 32px;" v-observe-visibility="{callback: visibilityChanged}">Show More</button>
|
||||
</div>
|
||||
<transition name="fabfade">
|
||||
<button class="top-fab" v-show="showFab" @click="scrollToTop()">
|
||||
<%- include("../svg/arrow-up.svg") %>
|
||||
</button>
|
||||
</transition>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-collection-list', {
|
||||
template: "#cider-collection-list",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "artists"
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
triggerEnabled: true,
|
||||
canSeeTrigger: false,
|
||||
showFab: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scrollToTop() {
|
||||
let target = document.querySelector(".header-text")
|
||||
target.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"})
|
||||
},
|
||||
getNext() {
|
||||
// if this.data.next is not null, then we can run this.data.next() and concat to this.data.data to get the next page
|
||||
switch(this.type) {
|
||||
default:
|
||||
case "artists":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
this.data.next().then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data.next;
|
||||
this.data.data = this.data.data.concat(data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
case "search":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
this.data.next().then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data[this.data.groups].next;
|
||||
this.data.data = this.data.data.concat(data[this.data.groups].data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
case "listen_now":
|
||||
case "curator":
|
||||
if (this.data.next && this.triggerEnabled) {
|
||||
this.triggerEnabled = false;
|
||||
app.mk.api.v3.music(this.data.next).then(data => {
|
||||
console.log(data);
|
||||
this.data.next = data.data.next;
|
||||
this.data.data = this.data.data.concat(data.data.data);
|
||||
this.triggerEnabled = true;
|
||||
});
|
||||
}else{
|
||||
console.log("No next page");
|
||||
this.triggerEnabled = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
headerVisibility: function (isVisible, entry) {
|
||||
if(isVisible) {
|
||||
this.showFab = false;
|
||||
}else{
|
||||
this.showFab = true;
|
||||
}
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
if(isVisible) {
|
||||
this.canSeeTrigger = true;
|
||||
this.getNext();
|
||||
}else{
|
||||
this.canSeeTrigger = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,56 +0,0 @@
|
|||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.albums.downloadState == 2" @click="getLibraryAlbumsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibraryAlbums"
|
||||
v-model="library.albums.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sorting" @change="searchLibraryAlbums()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.albums.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sortOrder" @change="searchLibraryAlbums()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.viewAs">
|
||||
<optgroup label="View As">
|
||||
<option value="covers">Cover Art</option>
|
||||
<option value="list">List</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large v-if="library.albums.viewAs == 'covers'" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-square-large>
|
||||
<mediaitem-list-item v-if="library.albums.viewAs == 'list'" :show-duration="false" :show-meta-data="true" :show-library-status="false" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
|
@ -1,46 +0,0 @@
|
|||
<template v-if="page == 'library-songs'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h1 class="header-text">Songs</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.songs.downloadState == 2" @click="getLibrarySongsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibrarySongs"
|
||||
v-model="library.songs.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sorting" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.songs.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sortOrder" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
|
||||
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
|
@ -1,32 +0,0 @@
|
|||
<script type="text/x-template" id="cider-listen-now">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Listen Now</h1>
|
||||
<template v-for="recom in data.data">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ recom.attributes.title ? recom.attributes.title.stringForDisplay : ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="recom.relationships.contents.data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(recom.relationships.contents, recom.attributes.title ? recom.attributes.title.stringForDisplay : '', 'listen_now')" >See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.attributes.display.kind == 'MusicCoverShelf'">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else-if="recom.attributes.display.kind == 'MusicSuperHeroShelf'">
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-sp
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-sp>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-listen-now', {
|
||||
template: "#cider-listen-now",
|
||||
props: ["data"]
|
||||
})
|
||||
</script>
|
|
@ -1,101 +0,0 @@
|
|||
<script type="text/x-template" id="cider-recordlabel">
|
||||
<div class="content-inner artist-page">
|
||||
<div class="artist-header" :style="getArtistPalette(data)">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;">
|
||||
<div class="artist-image">
|
||||
<mediaitem-artwork
|
||||
:shadow="true"
|
||||
:url="data.attributes.artwork ? data.attributes.artwork.url : ''"
|
||||
size="220" type="artists"></mediaitem-artwork>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col flex-center"
|
||||
>
|
||||
<h1>{{ data.attributes.name }}</h1>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="artist-body">
|
||||
<div v-if = "app.showingPlaylist.attributes.description">
|
||||
<div class="row">
|
||||
<h3>About </h3>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div>{{ app.showingPlaylist.attributes.description.standard }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<template v-if="data.views && data.views['latest-releases']">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views["latest-releases"].attributes.title ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['latest-releases'].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showRecordLabelView(data.id, data.attributes.name + ' - Latest Releases', 'latest-releases')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.views['latest-releases'].data">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
<template v-if="data.views && data.views['top-releases']">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ data.views["top-releases"].attributes.title ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-releases'].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showRecordLabelView(data.id, data.attributes.name + ' - Top Releases', 'top-releases')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.views['top-releases'].data">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
<template v-if="data.relationships && data.relationships.playlists && data.relationships.playlists.data.length > 0">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Playlists</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.relationships.playlists.data.length >= 5">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(data.relationships.playlists, data.attributes.name + ' - Playlists', 'curator')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in data.relationships.playlists.data.limit(5)">
|
||||
</mediaitem-square-large>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-recordlabel', {
|
||||
template: "#cider-recordlabel",
|
||||
props: ['data'],
|
||||
data: function () {
|
||||
return {
|
||||
topSongsExpanded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getArtistPalette(artist) {
|
||||
if (artist["attributes"]["artwork"]) {
|
||||
return {
|
||||
"background": "#" + artist["attributes"]["artwork"]["bgColor"],
|
||||
"color": "#" + artist["attributes"]["artwork"]["textColor1"],
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
"background": "#000000",
|
||||
"color": "#ffffff",
|
||||
}
|
||||
}
|
||||
},
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,64 +0,0 @@
|
|||
<script type="text/x-template" id="cider-search">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;" v-if="getTopResult()">
|
||||
<template>
|
||||
<h3>Top Result</h3>
|
||||
<mediaitem-square-large :item="getTopResult()"></mediaitem-square-large>
|
||||
</template>
|
||||
</div>
|
||||
<div class="col" v-if="search.results.song">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" @click="app.showSearchView(app.search.term, 'song', app.friendlyTypes('song'))" v-if="search.results.song.data.length >= 6">
|
||||
<button class="cd-btn-seeall">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<mediaitem-list-item :item="item" :index="index"
|
||||
v-for="(item, index) in search.results.song.data.limit(6)"></mediaitem-list-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="search.results['meta']">
|
||||
<template
|
||||
v-for="section in search.results.meta.results.order" v-if="section != 'song' && section != 'top'">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ app.friendlyTypes(section) }}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results[section].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showSearchView(app.search.term, section, app.friendlyTypes(section))">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!app.friendlyTypes(section).includes('Video')">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-search', {
|
||||
template: "#cider-search",
|
||||
props: ['search'],
|
||||
methods: {
|
||||
getTopResult() {
|
||||
if (this.search.results["meta"]) {
|
||||
return this.search.results[this.search.results.meta.results.order[0]]["data"][0]
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,178 +0,0 @@
|
|||
<script type="text/x-template" id="cider-settings">
|
||||
<div class="content-inner settings-page">
|
||||
<h1 class="header-text">Settings <small>(non functional, stay tuned)</small></h1>
|
||||
<div class="md-option-container">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Audio Quality
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select" style="width:180px;">
|
||||
<option value="990">Extreme</option>
|
||||
<option value="256">High</option>
|
||||
<option value="64">Low</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Seamless Audio Transitions
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Animated Artwork
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Always</option>
|
||||
<option value="1">Limit to pages and special entries</option>
|
||||
<option value="2">Disable Everywhere</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Discord Rich Presence
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Disabled</option>
|
||||
<option value="1">Display as 'Cider'</option>
|
||||
<option value="2">Display as 'Apple Music'</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Enable AudioContext Functionality
|
||||
<br>
|
||||
<small>Enabling AudioContext functionality will allow for extended audio features like Equalizers and Visualizers, however on some systems this may cause stuttering in audio tracks.</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
LastFM Scrobbling
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
LastFM Scrobble Delay
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme Options
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="btn">Theme Options</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Scrollbars
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Show on hover</option>
|
||||
<option value="1">Always show</option>
|
||||
<option value="2">Hidden</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Refresh Rate
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Automatic</option>
|
||||
<option value='30'>30</option>
|
||||
<option value='60'>60</option>
|
||||
<option value='144'>144</option>
|
||||
<option value='175'>175</option>
|
||||
<option value='240'>240</option>
|
||||
<option value='360'>30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Enable Musixmatch Lyrics
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Musixmatch Preferred Language
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Close Button Behavior
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Minimize to system tray</option>
|
||||
<option value='1'>Minimize to taskbar ? dock</option>
|
||||
<option value='2'>Quit Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Open Cider on Startup
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Never</option>
|
||||
<option value='1'>Always</option>
|
||||
<option value='2'>Always, minimized</option>
|
||||
<option value='2'>Always, hidden in tray</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-settings', {
|
||||
template: "#cider-settings",
|
||||
props: [],
|
||||
data: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
<template v-if="page == 'webview'">
|
||||
<div style="display:flex;width:100%;height:100%">
|
||||
<webview id="foo" :src="webview.url" style="display:inline-flex; width:100%;"></webview>
|
||||
</div>
|
||||
</template>
|
|
@ -1,7 +0,0 @@
|
|||
<template v-if="page == 'zoo'">
|
||||
<div class="content-inner">
|
||||
<h3>Welcome to element park. *BERR NERR NERR NERR NERRRRR BERR NER NER NER NERRR BERRR NR NR NRRRR*</h3>
|
||||
<button @click="app.playMediaItemById('1592151778', 'album')">Play Test Album</button>
|
||||
<cider-queue ref="queue"></cider-queue>
|
||||
</div>
|
||||
</template>
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"/></svg>
|
Before Width: | Height: | Size: 531 B |
|
@ -1,4 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 22" version="1.1" fill="#fff"
|
||||
style="width: 100%; height: 100%; fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.41421">
|
||||
<path d="M16.811,12.75c0.245,-0.355 0.389,-0.786 0.389,-1.25c0,-1.215 -0.985,-2.2 -2.2,-2.2c-1.215,0 -2.2,0.985 -2.2,2.2c0,0.466 0.145,0.898 0.392,1.254l-0.83,1.047c-0.537,-0.616 -0.862,-1.42 -0.862,-2.301c0,-1.933 1.567,-3.5 3.5,-3.5c1.933,0 3.5,1.567 3.5,3.5c0,0.879 -0.324,1.683 -0.859,2.297l-0.83,-1.047Zm1.271,1.604c0.694,-0.749 1.118,-1.752 1.118,-2.854c0,-2.32 -1.88,-4.2 -4.2,-4.2c-2.32,0 -4.2,1.88 -4.2,4.2c0,1.103 0.425,2.107 1.121,2.857l-0.814,1.028c-0.993,-0.995 -1.607,-2.368 -1.607,-3.885c0,-3.038 2.462,-5.5 5.5,-5.5c3.038,0 5.5,2.462 5.5,5.5c0,1.515 -0.613,2.887 -1.604,3.882l-0.814,-1.028Zm1.252,1.58c1.151,-1.126 1.866,-2.697 1.866,-4.434c0,-3.424 -2.776,-6.2 -6.2,-6.2c-3.424,0 -6.2,2.776 -6.2,6.2c0,1.739 0.716,3.311 1.869,4.437l-0.811,1.023c-1.452,-1.368 -2.358,-3.308 -2.358,-5.46c0,-4.142 3.358,-7.5 7.5,-7.5c4.142,0 7.5,3.358 7.5,7.5c0,2.15 -0.905,4.089 -2.355,5.457l-0.811,-1.023Zm-0.227,2.066l-8.219,0c-0.355,0 -0.515,-0.434 -0.27,-0.717l4.058,-5.12c0.178,-0.217 0.474,-0.217 0.652,0l4.058,5.12c0.237,0.283 0.085,0.717 -0.279,0.717Z" style="fill-rule:nonzero"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 320 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"/></svg>
|
Before Width: | Height: | Size: 518 B |
|
@ -1 +0,0 @@
|
|||
<svg aria-hidden="true" data-prefix="fas" data-icon="chevron-right" fill="currentColor" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-chevron-right fa-w-10 fa-7x"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z" class=""/></svg>
|
Before Width: | Height: | Size: 538 B |
|
@ -1,55 +0,0 @@
|
|||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
fill="#eee" viewBox="0 0 384.97 384.97" style="enable-background:new 0 0 384.97 384.97;" xml:space="preserve">
|
||||
<g>
|
||||
<g id="Fullscreen_1_">
|
||||
<path d="M372.939,216.545c-6.123,0-12.03,5.269-12.03,12.03v132.333H24.061V24.061h132.333c6.388,0,12.03-5.642,12.03-12.03
|
||||
S162.409,0,156.394,0H24.061C10.767,0,0,10.767,0,24.061v336.848c0,13.293,10.767,24.061,24.061,24.061h336.848
|
||||
c13.293,0,24.061-10.767,24.061-24.061V228.395C384.97,221.731,380.085,216.545,372.939,216.545z"/>
|
||||
<path d="M372.939,0H252.636c-6.641,0-12.03,5.39-12.03,12.03s5.39,12.03,12.03,12.03h91.382L99.635,268.432
|
||||
c-4.668,4.668-4.668,12.235,0,16.903c4.668,4.668,12.235,4.668,16.891,0L360.909,40.951v91.382c0,6.641,5.39,12.03,12.03,12.03
|
||||
s12.03-5.39,12.03-12.03V12.03l0,0C384.97,5.558,379.412,0,372.939,0z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1,3 +0,0 @@
|
|||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M8.89547677 13.5330073c0-1.1057457-.97371638-2.0959657-2.09596577-2.0959657-1.13875305 0-2.0794621.99022-2.0794621 2.0959657 0 1.1222494.94070905 2.0794621 2.0794621 2.0794621 1.12224939 0 2.09596577-.9572127 2.09596577-2.0794621zm6.68398533 0c0-1.1057457-.9572127-2.0959657-2.0794621-2.0959657-1.1222494 0-2.0794621.99022-2.0794621 2.0959657 0 1.1222494.9572127 2.0794621 2.0794621 2.0794621 1.1222494 0 2.0794621-.9572127 2.0794621-2.0794621zm6.700489 0c0-1.1057457-.940709-2.0959657-2.0794621-2.0959657-1.1222494 0-2.0959658.99022-2.0959658 2.0959657 0 1.1222494.9737164 2.0794621 2.0959658 2.0794621 1.1387531 0 2.0794621-.9572127 2.0794621-2.0794621z"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 772 B |
|
@ -1,3 +0,0 @@
|
|||
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 27" class="glyph">
|
||||
<path d="M11.3545232,18.4180929 L18.4676039,14.242665 C19.0452323,13.9290954 19.0122249,13.1204156 18.4676039,12.806846 L11.3545232,8.63141809 C10.7603912,8.26833741 9.98471883,8.54889976 9.98471883,9.19254279 L9.98471883,17.8404645 C9.98471883,18.5006112 10.7108802,18.7976773 11.3545232,18.4180929 Z"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 409 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M500.33 0h-47.41a12 12 0 0 0-12 12.57l4 82.76A247.42 247.42 0 0 0 256 8C119.34 8 7.9 119.53 8 256.19 8.1 393.07 119.1 504 256 504a247.1 247.1 0 0 0 166.18-63.91 12 12 0 0 0 .48-17.43l-34-34a12 12 0 0 0-16.38-.55A176 176 0 1 1 402.1 157.8l-101.53-4.87a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12h200.33a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12z"/></svg>
|
Before Width: | Height: | Size: 622 B |
|
@ -1 +0,0 @@
|
|||
var VueObserveVisibility=function(e){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function n(e){return function(e){if(Array.isArray(e)){for(var t=0,i=new Array(e.length);t<e.length;t++)i[t]=e[t];return i}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}var r=function(){function e(t,i,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.el=t,this.observer=null,this.frozen=!1,this.createObserver(i,n)}var t,r,o;return t=e,(r=[{key:"createObserver",value:function(e,t){var i=this;if(this.observer&&this.destroyObserver(),!this.frozen){var r;if(this.options="function"==typeof(r=e)?{callback:r}:r,this.callback=function(e,t){i.options.callback(e,t),e&&i.options.once&&(i.frozen=!0,i.destroyObserver())},this.callback&&this.options.throttle){var o=(this.options.throttleOptions||{}).leading;this.callback=function(e,t){var i,r,o,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},l=function(l){for(var a=arguments.length,c=new Array(a>1?a-1:0),u=1;u<a;u++)c[u-1]=arguments[u];if(o=c,!i||l!==r){var f=s.leading;"function"==typeof f&&(f=f(l,r)),i&&l===r||!f||e.apply(void 0,[l].concat(n(o))),r=l,clearTimeout(i),i=setTimeout(function(){e.apply(void 0,[l].concat(n(o))),i=0},t)}};return l._clear=function(){clearTimeout(i),i=null},l}(this.callback,this.options.throttle,{leading:function(e){return"both"===o||"visible"===o&&e||"hidden"===o&&!e}})}this.oldResult=void 0,this.observer=new IntersectionObserver(function(e){var t=e[0];if(e.length>1){var n=e.find(function(e){return e.isIntersecting});n&&(t=n)}if(i.callback){var r=t.isIntersecting&&t.intersectionRatio>=i.threshold;if(r===i.oldResult)return;i.oldResult=r,i.callback(r,t)}},this.options.intersection),t.context.$nextTick(function(){i.observer&&i.observer.observe(i.el)})}}},{key:"destroyObserver",value:function(){this.observer&&(this.observer.disconnect(),this.observer=null),this.callback&&this.callback._clear&&(this.callback._clear(),this.callback=null)}},{key:"threshold",get:function(){return this.options.intersection&&"number"==typeof this.options.intersection.threshold?this.options.intersection.threshold:0}}])&&i(t.prototype,r),o&&i(t,o),e}();function o(e,t,i){var n=t.value;if(n)if("undefined"==typeof IntersectionObserver)console.warn("[vue-observe-visibility] IntersectionObserver API is not available in your browser. Please install this polyfill: https://github.com/w3c/IntersectionObserver/tree/master/polyfill");else{var o=new r(e,n,i);e._vue_visibilityState=o}}function s(e){var t=e._vue_visibilityState;t&&(t.destroyObserver(),delete e._vue_visibilityState)}var l={bind:o,update:function(e,i,n){var r=i.value;if(!function e(i,n){if(i===n)return!0;if("object"===t(i)){for(var r in i)if(!e(i[r],n[r]))return!1;return!0}return!1}(r,i.oldValue)){var l=e._vue_visibilityState;r?l?l.createObserver(r,n):o(e,{value:r},n):s(e)}},unbind:s};function a(e){e.directive("observe-visibility",l)}var c={version:"1.0.0",install:a},u=null;return"undefined"!=typeof window?u=window.Vue:"undefined"!=typeof global&&(u=global.Vue),u&&u.use(c),e.ObserveVisibility=l,e.default=c,e.install=a,e}({});
|
2
resources/cider-ui/vuedraggable.umd.min.js
vendored
|
@ -1,193 +0,0 @@
|
|||
const {BrowserWindow, ipcMain, shell, app} = require("electron")
|
||||
const {join} = require("path")
|
||||
const getPort = require("get-port");
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
const windowStateKeeper = require("electron-window-state");
|
||||
const os = require('os');
|
||||
|
||||
// Analytics for debugging.
|
||||
const ElectronSentry = require("@sentry/electron");
|
||||
ElectronSentry.init({dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214"});
|
||||
|
||||
const CiderBase = {
|
||||
|
||||
CreateBrowserWindow() {
|
||||
// Set default window sizes
|
||||
const mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 1024,
|
||||
defaultHeight: 600
|
||||
});
|
||||
|
||||
let win = null
|
||||
const options = {
|
||||
icon: join(__dirname, `../icons/icon.ico`),
|
||||
width: mainWindowState.width,
|
||||
height: mainWindowState.height,
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
minWidth: 844,
|
||||
minHeight: 410,
|
||||
frame: false,
|
||||
title: "Cider",
|
||||
vibrancy: 'dark',
|
||||
hasShadow: false,
|
||||
webPreferences: {
|
||||
webviewTag: true,
|
||||
plugins: true,
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
webSecurity: false,
|
||||
allowRunningInsecureContent: true,
|
||||
enableRemoteModule: true,
|
||||
sandbox: true,
|
||||
nativeWindowOpen: true,
|
||||
contextIsolation: false,
|
||||
preload: join(__dirname, '../preload/cider-preload.js')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CiderBase.InitWebServer()
|
||||
|
||||
// Create the BrowserWindow
|
||||
if (process.platform === "darwin" || process.platform === "linux") {
|
||||
win = new BrowserWindow(options)
|
||||
} else {
|
||||
const {BrowserWindow} = require("electron-acrylic-window");
|
||||
win = new BrowserWindow(options)
|
||||
}
|
||||
|
||||
// intercept "https://js-cdn.music.apple.com/hls.js/2.141.0/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead
|
||||
win.webContents.session.webRequest.onBeforeRequest(
|
||||
{
|
||||
urls: ["https://*/*.js"]
|
||||
},
|
||||
(details, callback) => {
|
||||
if (details.url.includes("hls.js")) {
|
||||
callback({
|
||||
redirectURL: "http://localhost:9000/apple-hls.js"
|
||||
})
|
||||
} else {
|
||||
callback({
|
||||
cancel: false
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let location = "http://localhost:9000/"
|
||||
win.loadURL(location)
|
||||
win.on("closed", () => {
|
||||
win = null
|
||||
})
|
||||
|
||||
// Register listeners on Window to track size and position of the Window.
|
||||
mainWindowState.manage(win);
|
||||
|
||||
// IPC stuff (senders)
|
||||
ipcMain.on("cider-platform", (event) => {
|
||||
event.returnValue = process.platform
|
||||
})
|
||||
|
||||
// IPC stuff (listeners)
|
||||
ipcMain.on('close', () => { // listen for close event
|
||||
win.close();
|
||||
})
|
||||
|
||||
ipcMain.handle('getStoreValue', (event, key, defaultValue) => {
|
||||
return (defaultValue ? app.cfg.get(key, true) : app.cfg.get(key));
|
||||
});
|
||||
|
||||
ipcMain.handle('setStoreValue', (event, key, value) => {
|
||||
app.cfg.set(key, value);
|
||||
});
|
||||
|
||||
ipcMain.on('getStore', (event) => {
|
||||
event.returnValue = app.cfg.store
|
||||
})
|
||||
|
||||
ipcMain.on('setStore', (event, store) => {
|
||||
app.cfg.store = store
|
||||
})
|
||||
|
||||
ipcMain.on('maximize', () => { // listen for maximize event
|
||||
if (win.isMaximized()) {
|
||||
win.unmaximize()
|
||||
} else {
|
||||
win.maximize()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('minimize', () => { // listen for minimize event
|
||||
win.minimize();
|
||||
})
|
||||
|
||||
if (process.platform === "win32") {
|
||||
let WND_STATE = {
|
||||
MINIMIZED: 0,
|
||||
NORMAL: 1,
|
||||
MAXIMIZED: 2,
|
||||
FULL_SCREEN: 3
|
||||
}
|
||||
let wndState = WND_STATE.NORMAL
|
||||
|
||||
win.on("resize", (_event) => {
|
||||
const isMaximized = win.isMaximized()
|
||||
const isMinimized = win.isMinimized()
|
||||
const isFullScreen = win.isFullScreen()
|
||||
const state = wndState;
|
||||
if (isMinimized && state !== WND_STATE.MINIMIZED) {
|
||||
wndState = WND_STATE.MINIMIZED
|
||||
} else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) {
|
||||
wndState = WND_STATE.FULL_SCREEN
|
||||
} else if (isMaximized && state !== WND_STATE.MAXIMIZED) {
|
||||
wndState = WND_STATE.MAXIMIZED
|
||||
win.webContents.executeJavaScript(`app.chrome.maximized = true`)
|
||||
} else if (state !== WND_STATE.NORMAL) {
|
||||
wndState = WND_STATE.NORMAL
|
||||
win.webContents.executeJavaScript(`app.chrome.maximized = false`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set window Handler
|
||||
win.webContents.setWindowOpenHandler(({url}) => {
|
||||
if (url.includes("apple") || url.includes("localhost")) {
|
||||
return { action: "allow"}
|
||||
}
|
||||
shell.openExternal(url).catch(() => {})
|
||||
return {
|
||||
action: 'deny'
|
||||
}
|
||||
})
|
||||
|
||||
return win
|
||||
},
|
||||
|
||||
EnvironmentVariables: {
|
||||
"env": {
|
||||
platform: os.platform()
|
||||
}
|
||||
},
|
||||
|
||||
async InitWebServer() {
|
||||
const webRemotePort = await getPort({port : 9000});
|
||||
const webapp = express();
|
||||
const webRemotePath = path.join(__dirname, '../cider-ui/');
|
||||
webapp.set("views", path.join(webRemotePath, "views"));
|
||||
webapp.set("view engine", "ejs");
|
||||
|
||||
webapp.use(express.static(webRemotePath));
|
||||
webapp.get('/', function (req, res) {
|
||||
//res.sendFile(path.join(webRemotePath, 'index_old.html'));
|
||||
res.render("main", CiderBase.EnvironmentVariables)
|
||||
});
|
||||
webapp.listen(webRemotePort, function () {
|
||||
console.log(`Web Remote listening on port ${webRemotePort}`);
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
module.exports = CiderBase;
|
|
@ -1,8 +0,0 @@
|
|||
const electron = require('electron')
|
||||
|
||||
console.log('Loaded Preload')
|
||||
|
||||
process.once('loaded', () => {
|
||||
console.log("Setting ipcRenderer")
|
||||
global.ipcRenderer = electron.ipcRenderer;
|
||||
});
|