Album view

This commit is contained in:
James Barnsley
2016-10-31 09:25:15 +13:00
parent c1cbcddef6
commit 869d73231b
38 changed files with 6467 additions and 5656 deletions

View File

@ -15,7 +15,7 @@ class SpotifyAuthenticationFrame extends React.Component{
super(props);
this.state = {
frameUrl: '//jamesbarnsley.co.nz/spotmop.php?action=frame',
frameUrl: '//jamesbarnsley.co.nz/auth.php?action=frame',
authorizing: false
}
}
@ -27,26 +27,34 @@ class SpotifyAuthenticationFrame extends React.Component{
// listen for incoming messages from the authorization iframe
// this is triggered when authentication is granted from the popup
window.addEventListener('message', function(event){
// only allow incoming data from our authorized authenticator proxy
if( !/^https?:\/\/jamesbarnsley\.co\.nz/.test(event.origin) ) return false;
var data = JSON.parse(event.data);
self.props.actions.authorizationGranted( data );
self.props.actions.getMe();
// and turn off our authorizing switch
self.setState({
frameUrl: '//jamesbarnsley.co.nz/spotmop.php?action=frame',
authorizing: false
})
if(event.data == 'closed'){
self.setState({
frameUrl: '//jamesbarnsley.co.nz/auth.php?action=frame',
authorizing: false
})
}else{
// only allow incoming data from our authorized authenticator proxy
if( !/^https?:\/\/jamesbarnsley\.co\.nz/.test(event.origin) ) return false;
var data = JSON.parse(event.data);
self.props.actions.authorizationGranted( data );
self.props.actions.getMe();
// and turn off our authorizing switch
self.setState({
frameUrl: '//jamesbarnsley.co.nz/auth.php?action=frame',
authorizing: false
})
}
}, false);
}
startAuthorization(){
this.setState({
frameUrl: '//jamesbarnsley.co.nz/spotmop.php?action=authorize&app='+location.protocol+'//'+window.location.host,
frameUrl: '//jamesbarnsley.co.nz/auth.php?action=authorize&app='+location.protocol+'//'+window.location.host,
authorizing: true
})
}

View File

@ -14,7 +14,7 @@ class VersionManager extends React.Component{
super(props);
}
renderUpdateButton(){
renderUpgradeButton(){
if( this.props.pusher.upgrading ){
return (
<button disabled>
@ -30,7 +30,7 @@ class VersionManager extends React.Component{
}
if( this.props.pusher.version.upgrade_available ){
return <button className="secondary" onClick={() => this.props.pusherActions.performUpdate()}>Update now</button>
return <button className="secondary" onClick={() => this.props.pusherActions.performUpgrade()}>Upgrade to { this.props.pusher.version.latest }</button>
}
return null;
@ -40,7 +40,7 @@ class VersionManager extends React.Component{
return (
<div className="version-manager">
<span>{ this.props.pusher.version.current } installed</span>
{ this.renderUpdateButton() }
{ this.renderUpgradeButton() }
</div>
);
}

View File

@ -14,18 +14,6 @@ const localstorageMiddleware = (function(){
switch( action.type ){
case 'PUSHER_SET_CONFIG':
var pusher = JSON.parse( localStorage.getItem('pusher') );
if( !pusher ) pusher = {};
Object.assign(
pusher,{
username: action.config.username,
port: action.config.port
}
);
localStorage.setItem('pusher', JSON.stringify(pusher));
break;
case 'PUSHER_CONNECTED':
var pusher = JSON.parse( localStorage.getItem('pusher') );
if( !pusher ) pusher = {};
@ -38,6 +26,13 @@ const localstorageMiddleware = (function(){
localStorage.setItem('pusher', JSON.stringify(pusher));
break;
case 'PUSHER_SET_PORT':
var pusher = JSON.parse( localStorage.getItem('pusher') );
if( !pusher ) pusher = {};
Object.assign( pusher, { port: action.port } );
localStorage.setItem('pusher', JSON.stringify(pusher));
break;
case 'PUSHER_CHANGE_USERNAME':
var pusher = JSON.parse( localStorage.getItem('pusher') );
if( !pusher ) pusher = {};

View File

@ -3,10 +3,10 @@
* Actions and Action Creators
**/
export function setConfig( config ){
export function setPort( port ){
return {
type: 'PUSHER_SET_CONFIG',
config: config
type: 'PUSHER_SET_PORT',
port: port
}
}

View File

@ -13,10 +13,8 @@ export default function reducer(pusher = {}, action){
case 'PUSHER_DISCONNECTED':
return Object.assign({}, pusher, { connected: false, connecting: false });
case 'PUSHER_SET_CONFIG':
return Object.assign({}, pusher, {
port: action.port
});
case 'PUSHER_SET_PORT':
return Object.assign({}, pusher, { port: action.port });
case 'PUSHER_CHANGE_USERNAME':
return Object.assign({}, pusher, { username: action.data.connection.username });

View File

@ -104,11 +104,9 @@ function refreshToken( dispatch, getState ){
if( getState().spotify.authorized ){
console.log('Refreshing token as '+getState().spotify.expires_in+' older than '+new Date().getTime())
$.ajax({
method: 'GET',
url: '//jamesbarnsley.co.nz/spotmop.php?action=refresh&refresh_token='+getState().spotify.refresh_token,
url: '//jamesbarnsley.co.nz/auth.php?action=refresh&refresh_token='+getState().spotify.refresh_token,
dataType: "json",
timeout: 10000
})

View File

@ -4,7 +4,9 @@ import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import TrackList from '../components/TrackList'
import Header from '../components/Header'
import Thumbnail from '../components/Thumbnail'
import Parallax from '../components/Parallax'
import ArtistSentence from '../components/ArtistSentence'
import * as spotifyActions from '../services/spotify/actions'
import * as mopidyActions from '../services/mopidy/actions'
@ -31,11 +33,14 @@ class Album extends React.Component{
if( this.props.spotify.album ){
return (
<div className="view album-view">
<Header
icon="cd"
title={ this.props.spotify.album.name }
/>
<TrackList tracks={this.props.spotify.album.tracks.items} />
<div className="intro">
<Thumbnail size="large" images={ this.props.spotify.album.images } />
</div>
<div className="main">
<h1>{ this.props.spotify.album.name }</h1>
<h3><ArtistSentence artists={ this.props.spotify.album.artists } /></h3>
<TrackList tracks={this.props.spotify.album.tracks.items} />
</div>
</div>
);
}

View File

@ -77,6 +77,9 @@ class App extends React.Component{
<main>
{this.props.children}
</main>
<footer>
Iris by James Barnsley &nbsp;|&nbsp; v{ this.props.pusher.version.current }
</footer>
{ this.props.ui.context_menu.test }
<ContextMenu state={this.props.ui.context_menu} />
</div>

View File

@ -41,13 +41,6 @@ class Settings extends React.Component{
return false;
}
setPusherConfig(e){
e.preventDefault();
this.props.pusherActions.changeUsername( this.state.pusher_username );
this.props.pusherActions.setConfig({ port: this.state.pusher_port });
return false;
}
setSpotifyConfig(e){
e.preventDefault();
this.props.spotifyActions.setConfig({ country: this.state.spotify_country, locale: this.state.spotify_locale });
@ -96,13 +89,14 @@ class Settings extends React.Component{
</form>
<h3 className="underline">Pusher</h3>
<form onSubmit={(e) => this.setPusherConfig(e)}>
<form>
<label>
<div className="label">Username</div>
<div className="input">
<input
type="text"
onChange={ e => this.setState({ pusher_username: e.target.value })}
onChange={ e => this.setState({ pusher_username: e.target.value }) }
onBlur={ e => this.props.pusherActions.changeUsername( this.state.pusher_username ) }
value={ this.state.pusher_username } />
</div>
</label>
@ -112,10 +106,10 @@ class Settings extends React.Component{
<input
type="text"
onChange={ e => this.setState({ pusher_port: e.target.value })}
onBlur={ e => this.props.pusherActions.setPort({ port: this.state.pusher_port }) }
value={ this.state.pusher_port } />
</div>
</label>
<button type="submit" className="secondary">Apply</button>
</form>
<h3 className="underline">Spotify</h3>
@ -126,6 +120,7 @@ class Settings extends React.Component{
<input
type="text"
onChange={ e => this.setState({ spotify_country: e.target.value })}
onBlur={ e => this.setSpotifyConfig(e) }
value={ this.state.spotify_country } />
</div>
</label>
@ -135,10 +130,10 @@ class Settings extends React.Component{
<input
type="text"
onChange={ e => this.setState({ spotify_locale: e.target.value })}
onBlur={ e => this.setSpotifyConfig(e) }
value={ this.state.spotify_locale } />
</div>
</label>
<button type="submit" className="secondary">Apply</button>
</form>
<SpotifyAuthenticationFrame />

View File

@ -16,4 +16,5 @@
@import 'components/header';
@import 'views/artist';
@import 'views/album';

View File

@ -13,9 +13,14 @@ body {
overflow-x: hidden;
}
main {
main,
footer {
margin-left: 200px;
}
padding-left: 200px;
main {
position: relative;
min-height: 100vh;
a {
color: inherit;
@ -32,8 +37,8 @@ main {
}
h1 {
font-weight: 100;
font-size: 26px;
font-weight: 500;
font-size: 40px;
}
h3 {
@ -99,4 +104,12 @@ main {
.grey-text {
color: $mid_grey;
}
footer {
display: block;
color: $light_grey;
padding-top: 50px;
padding-bottom: 50px;
text-align: center;
}

24
src/scss/views/_album.scss Executable file
View File

@ -0,0 +1,24 @@
.album-view {
.intro {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 300px;
background: $light_grey;
.thumbnail {
float: none;
margin: 0 auto;
}
h1 {
padding-top: 30px;
}
}
.main {
padding-left: 300px;
}
}

View File

@ -2,13 +2,18 @@
.artist-view {
.intro {
position: relative;
margin-bottom: 20px;
margin: -100px 0 20px 0;
@include clearfix;
.thumbnail {
max-width: 200px;
margin: -100px 20px 0 40px;
margin: 0 20px 0 40px;
float: left;
}
h1 {
color: #FFFFFF;
padding-top: 30px;
}
}
}

30
src/scss/views/_playlist.scss Executable file
View File

@ -0,0 +1,30 @@
.album-view {
.intro {
@include clearfix;
position: relative;
text-align: center;
color: #FFFFFF;
padding: 20px;
height: 40vh;
z-index: 2;
.parallax {
position: absolute;
top: 0;
left: 0;
height: 100%;
z-index: -1;
}
.thumbnail {
float: none;
margin: 0 auto;
max-width: 160px;
}
h1 {
padding-top: 30px;
}
}
}