
Added basis for library-songs, made search a component, changed search layout, added new app.mkapi
401 lines
No EOL
20 KiB
HTML
401 lines
No EOL
20 KiB
HTML
<!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.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"></button>
|
|
</div>
|
|
<div class="app-chrome-item full-height">
|
|
<div class="window-controls">
|
|
<div class="minimize"></div>
|
|
<div class="minmax"></div>
|
|
<div class="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">
|
|
{{ item.attributes.name }}
|
|
</button>
|
|
</div>
|
|
<div class="app-sidebar-footer">
|
|
<input type="range" class="display--small">
|
|
<button class="app-sidebar-button" style="width:100%">
|
|
<div class="sidebar-user-icon">
|
|
|
|
</div>
|
|
<div class="sidebar-user-text">Cider User</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="app-content">
|
|
<!-- 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>
|
|
<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 name="wpfade">
|
|
<template v-if="page == 'listen_now'">
|
|
<div class="content-inner">
|
|
|
|
</div>
|
|
</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="getLibrarySongs()">
|
|
<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..."
|
|
class="search-input">
|
|
</div>
|
|
<mediaitem-list-item :item="item"
|
|
v-for="item in library.songs.listing"></mediaitem-list-item>
|
|
</div>
|
|
</template>
|
|
</transition>
|
|
</div>
|
|
<div class="app-drawer" v-if="drawertest">
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="bg-artwork"></div>
|
|
</div>
|
|
|
|
<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 :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 == search.limit">
|
|
<button class="cd-btn-seeall">See All</button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<mediaitem-list-item :item="item"
|
|
v-for="item in search.results.songs.data"></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 == search.limit">
|
|
<button class="cd-btn-seeall">See All</button>
|
|
</div>
|
|
</div>
|
|
<mediaitem-square :item="item"
|
|
v-for="item in search.results.albums.data"></mediaitem-square>
|
|
</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 == search.limit">
|
|
<button class="cd-btn-seeall">See All</button>
|
|
</div>
|
|
</div>
|
|
<mediaitem-square :item="item"
|
|
v-for="item in search.results.artists.data"></mediaitem-square>
|
|
</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 == search.limit">
|
|
<button class="cd-btn-seeall">See All</button>
|
|
</div>
|
|
</div>
|
|
<mediaitem-square :item="item"
|
|
v-for="item in search.results.playlists.data"></mediaitem-square>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
</script>
|
|
|
|
<script type="text/x-template" id="am-musiccovershelf">
|
|
<h1>{{ component.attributes.title.stringForDisplay }}</h1>
|
|
</script>
|
|
|
|
<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>
|
|
|
|
<script type="text/x-template" id="mediaitem-list-item">
|
|
<template>
|
|
<div @click="app.playMediaItemById(item.id, item.type)"
|
|
class="cd-mediaitem-list-item">
|
|
<div class="artwork"
|
|
:class="{'round': item.type == 'artists'}"
|
|
:style="{'--artwork': app.getMediaItemArtwork(item.attributes.artwork.url, 34)}
|
|
"></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>
|
|
|
|
<script type="text/x-template" id="mediaitem-hrect">
|
|
<template>
|
|
<div @click="app.playMediaItemById(item.id, item.type)"
|
|
class="cd-mediaitem-hrect">
|
|
<div class="artwork"
|
|
:class="{'round': item.type == 'artists'}"
|
|
:style="{'--artwork': app.getMediaItemArtwork(item.attributes.artwork.url, 70)}
|
|
"></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 type="text/x-template" id="mediaitem-square">
|
|
<template>
|
|
<div @click="app.playMediaItemById(item.id, item.type)"
|
|
class="cd-mediaitem-square">
|
|
<div class="artwork"
|
|
:class="{'round': item.type == 'artists'}"
|
|
:style="{'--artwork': app.getMediaItemArtwork(item.attributes.artwork.url, 128)}"></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 src="https://js-cdn.music.apple.com/musickit/v2/amp/musickit.js"></script>
|
|
<script src="index.js?v=1"></script>
|
|
</body>
|
|
|
|
</html> |