Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Cher Stewart
committed
Feb 13, 2019
1 parent
e8511d1
commit 12d451f
Showing
10 changed files
with
538 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<template> | ||
<footer> | ||
This is a demo built by | ||
<a href="http://cherp.io">Cher Scarlett</a> using Nuxt.js, Redis, and Spotify. Made with 💙. | ||
<a | ||
href="https://github.com/cherscarlett/cherislistening/fork" | ||
>Fork your own 🐙.</a> | ||
</footer> | ||
</template> | ||
|
||
<style scoped> | ||
footer { | ||
width: 70%; | ||
min-width: 320px; | ||
max-width: 600px; | ||
margin: 0 auto; | ||
filter: blur(0); | ||
transition: all 600ms ease-out; | ||
padding-bottom: 1em; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<template> | ||
<header> | ||
<h1> | ||
{{ $options.title }} | ||
<nuxt-link | ||
to="/auth" | ||
name="auth" | ||
aria-label="Login" | ||
v-bind:aria-current="'/auth' === $nuxt.$route.path ? 'page' : false" | ||
/> | ||
</h1> | ||
</header> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
title: 'Cher is Listening' | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
h1 { | ||
line-height: 0.65em; | ||
font-family: 'Oswald', monospace; | ||
letter-spacing: 1px; | ||
font-size: 15em; | ||
transform: rotate(-3deg) translateY(-50%); | ||
-webkit-box-reflect: below 0px | ||
linear-gradient(transparent, rgba(255, 255, 255, 0.3)); | ||
} | ||
h1 a { | ||
display: inline-block; | ||
height: 20px; | ||
width: 20px; | ||
background-image: url(~assets/spotify.svg); | ||
background-size: cover; | ||
filter: brightness(300%) opacity(30%); | ||
} | ||
h1 a:hover { | ||
filter: brightness(300%) opacity(60%); | ||
} | ||
h1 a:after, | ||
h1 a:before { | ||
content: none; | ||
} | ||
header { | ||
filter: blur(0); | ||
transition: all 600ms ease-out; | ||
} | ||
p { | ||
width: 40%; | ||
margin: auto; | ||
min-width: 320px; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
<template> | ||
<transition name="fade"> | ||
<section> | ||
<aside> | ||
<img :src="image" alt="Album Artwork"> | ||
<Progress :class="isPlaying ? '' : 'is-paused'" :progressPercent="progress" :image="image"/> | ||
</aside> | ||
<div class="metadata"> | ||
<h2>{{name}}</h2> | ||
<p>{{artistsList}}</p> | ||
<p :class="isPlaying ? 'is-playing status' : 'status'"> | ||
<span>Cher {{ status }}.</span> | ||
<a :href="href">Listen?</a> | ||
</p> | ||
</div> | ||
</section> | ||
</transition> | ||
</template> | ||
|
||
<script> | ||
import Progress from './Progress.vue' | ||
export default { | ||
components: { Progress }, | ||
props: ['isPlaying', 'nowPlaying'], | ||
data() { | ||
return { staleTimer: '', trackTimer: '' } | ||
}, | ||
computed: { | ||
image() { | ||
if (Boolean(this.nowPlaying.album)) { | ||
return this.nowPlaying.album.images[0].url | ||
} | ||
return this.nowPlaying.image | ||
}, | ||
progress() { | ||
return this.$store.state.trackProgress | ||
}, | ||
artistsList() { | ||
return this.nowPlaying.artists.map(artist => artist.name).join(', ') | ||
}, | ||
href() { | ||
return this.nowPlaying.external_urls.spotify | ||
}, | ||
name() { | ||
return this.nowPlaying.name | ||
}, | ||
status() { | ||
return this.isPlaying | ||
? `is playing this track with ${Math.round( | ||
this.$store.state.trackProgress | ||
)}% complete` | ||
: 'has paused this track' | ||
} | ||
}, | ||
created() { | ||
this.getNowPlaying() | ||
this.staleTimer = setInterval(() => { | ||
this.getNowPlaying() | ||
}, 10000) | ||
}, | ||
methods: { | ||
updateProgress(progress = 0, duration = 0) { | ||
this.$store.dispatch('updateProgress', { progress, duration }) | ||
}, | ||
async getNowPlaying() { | ||
const { progress_ms, is_playing, item } = await this.$axios.$get( | ||
`/api/spotify/now-playing/` | ||
) | ||
if (Boolean(item)) { | ||
const progress = progress_ms | ||
const duration = item.duration_ms | ||
this.$store.dispatch('updateStatus', is_playing) | ||
clearInterval(this.trackTimer) | ||
if (is_playing) { | ||
this.timeTrack(Date.now(), duration, progress) | ||
} else { | ||
this.updateProgress(progress, duration) | ||
} | ||
let id = null | ||
if (Boolean(this.nowPlaying)) id = this.nowPlaying.id | ||
if (item && (is_playing && item.id !== id)) { | ||
this.$store.dispatch('updateTrack', item) | ||
} | ||
} | ||
}, | ||
timeTrack(now, duration, progress) { | ||
const remainder = duration - progress | ||
const until = now + remainder | ||
this.trackTimer = setInterval(() => { | ||
const newNow = Date.now() | ||
if (newNow < until + 2500) { | ||
const newRemainder = until - newNow | ||
const newProgressMs = duration - newRemainder | ||
this.updateProgress(newProgressMs, duration) | ||
} else { | ||
this.updateProgress(1, 1) | ||
clearInterval(this.trackTimer) | ||
this.getNowPlaying() | ||
} | ||
}, 100) | ||
} | ||
}, | ||
beforeDestroy() { | ||
clearInterval(this.staleTimer) | ||
clearInterval(this.trackTimer) | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
section { | ||
position: relative; | ||
display: grid; | ||
grid-template-columns: 42% 58%; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
aside { | ||
position: relative; | ||
min-width: 50px; | ||
} | ||
img { | ||
opacity: 0; | ||
position: absolute; | ||
height: 0; | ||
width: 0; | ||
} | ||
section:after, | ||
section:before { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
right: 0; | ||
left: 0; | ||
z-index: 0; | ||
} | ||
section:after { | ||
transform: rotate(1deg); | ||
background: rgba(255, 255, 255, 0.1); | ||
} | ||
section:before { | ||
transform: rotate(3deg); | ||
background: rgba(255, 255, 255, 0.03); | ||
} | ||
div.metadata { | ||
padding-left: 1.4em; | ||
position: relative; | ||
z-index: 2; | ||
} | ||
h2 { | ||
font-family: 'Oswald', monospace; | ||
margin: 0; | ||
font-size: 3em; | ||
} | ||
p { | ||
margin: 0; | ||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8); | ||
} | ||
.fade-enter-active { | ||
transition: opacity 600ms ease-out; | ||
} | ||
.fade-leave-active { | ||
opacity: 0; | ||
} | ||
.fade-enter, | ||
.fade-leave-to { | ||
opacity: 0; | ||
} | ||
.status span { | ||
opacity: 0.7; | ||
font-size: 0.8em; | ||
padding: 1em 0; | ||
display: block; | ||
white-space: nowrap; | ||
} | ||
.is-playing span { | ||
opacity: 0; | ||
transition: opacity 600ms ease-out; | ||
} | ||
@media (max-width: 600px) { | ||
section { | ||
grid-template-rows: 42% 58%; | ||
grid-template-columns: 100%; | ||
} | ||
aside { | ||
max-width: 160px; | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<template> | ||
<div aria-hidden="true"> | ||
<svg | ||
class="album" | ||
viewBox="0 0 33.83098862 33.83098862" | ||
xmlns="http://www.w3.org/2000/svg" | ||
role="img" | ||
> | ||
<defs> | ||
<pattern id="image" x="0%" y="0%" height="100%" width="100%" patternUnits="userSpaceOnUse"> | ||
<image x="0%" y="0%" width="100%" height="100%" v-bind="{'xlink:href': image }"></image> | ||
</pattern> | ||
</defs> | ||
<circle class="image" cx="16.91549431" cy="17.3" r="15.9"></circle> | ||
</svg> | ||
<svg class="progress" viewBox="0 0 33.83098862 33.83098862" xmlns="http://www.w3.org/2000/svg"> | ||
<defs> | ||
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%"> | ||
<stop offset="0%" stop-color="#333642"></stop> | ||
<stop offset="25%" stop-color="rgba(0, 112, 255, 0.8)"></stop> | ||
<stop offset="90%" stop-color="rgba(118, 120, 224, 0.5)"></stop> | ||
<stop offset="100%" stop-color="rgba(255, 255, 255, .5)"></stop> | ||
</linearGradient> | ||
</defs> | ||
<circle | ||
class="bar" | ||
:stroke-dasharray="`${progressPercent} 100`" | ||
fill="none" | ||
cx="16.91549431" | ||
cy="16.91549431" | ||
r="15.91549431" | ||
></circle> | ||
</svg> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
props: ['progressPercent', 'image'] | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
div { | ||
filter: grayscale(0); | ||
} | ||
.is-paused { | ||
filter: grayscale(80%); | ||
transition: all 600ms ease-out; | ||
} | ||
svg { | ||
height: 100%; | ||
width: 100%; | ||
} | ||
svg.album { | ||
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.3)); | ||
} | ||
svg.progress { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.2)) | ||
drop-shadow(0 0 2px var(--colorBrightBlue)) | ||
drop-shadow(0 0 3px var(--colorBrightBlue)) | ||
drop-shadow(0 0 5px var(--colorBrightBlue)) opacity(65%) contrast(150%); | ||
} | ||
.bar { | ||
stroke: url(#gradient); | ||
stroke-width: 0.03em; | ||
transform: rotate(-90deg); | ||
transform-origin: center; | ||
animation: fill 2s reverse; | ||
} | ||
.image { | ||
fill: url(#image); | ||
} | ||
@keyframes fill { | ||
to { | ||
stroke-dasharray: 0 100; | ||
} | ||
} | ||
</style> |
Oops, something went wrong.