Groundwork for crossfading now playing artwork; Initial Setup pre-fill from queryParams

This commit is contained in:
James Barnsley
2020-02-11 09:52:18 +13:00
parent ff8b7df8b1
commit 066da7f7ca
6 changed files with 83 additions and 69 deletions

View File

@ -16,7 +16,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="#121212" /> <meta name="apple-mobile-web-app-status-bar-style" content="#121212" />
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#222222" /> <meta name="theme-color" content="#222222" />
<!-- Icons --> <!-- Icons -->
<link rel="apple-touch-startup-image" href="/iris/assets/app-icon_512.png" /> <link rel="apple-touch-startup-image" href="/iris/assets/app-icon_512.png" />
<link rel="apple-touch-icon" sizes="192x192" href="/iris/assets/app-icon_192.png" /> <link rel="apple-touch-icon" sizes="192x192" href="/iris/assets/app-icon_192.png" />
@ -30,7 +30,7 @@
<!-- Loading screen styles --> <!-- Loading screen styles -->
<style> <style>
html { html {
background-color: #121212; background-color: #121212;
} }
@keyframes loader { @keyframes loader {
@ -52,7 +52,7 @@
#app-loading::before { #app-loading::before {
position: absolute; position: absolute;
display: block; display: block;
content: ''; content: '';
height: 100%; height: 100%;
animation-name: loader; animation-name: loader;
background: #444444; background: #444444;
@ -104,17 +104,22 @@
var version = "VERSION_HERE"; var version = "VERSION_HERE";
// Construct the script tag // Construct the script tag
var js = document.createElement("script"); var js = document.createElement("script");
js.type = "application/javascript"; js.type = "application/javascript";
// Construct our css tag // Construct our css tag
var css = document.createElement("link"); var css = document.createElement("link");
css.rel = "stylesheet"; css.rel = "stylesheet";
// Check for test mode. This is toggled under Settings > Debug > Test mode // Check for test mode. This is toggled under Settings > Debug > Test mode
try { try {
var ui = JSON.parse(localStorage.getItem('ui') ); var ui = JSON.parse(localStorage.getItem('ui') );
var test_mode = (typeof(ui) !== 'undefined' && ui && typeof(ui.test_mode) !== 'undefined' && ui.test_mode); var test_mode = (
typeof(ui) !== 'undefined'
&& ui
&& typeof(ui.test_mode) !== 'undefined'
&& ui.test_mode
);
} catch(error){ } catch(error){
console.error(error); console.error(error);
var test_mode = false; var test_mode = false;

View File

@ -77,10 +77,7 @@ export class App extends React.Component {
} }
componentDidMount() { componentDidMount() {
const { const {
location: {
search,
},
history, history,
snapcast_enabled, snapcast_enabled,
allow_reporting, allow_reporting,
@ -111,20 +108,7 @@ export class App extends React.Component {
} }
coreActions.getBroadcasts(); coreActions.getBroadcasts();
// Check for url-parsed configuration values if (!initial_setup_complete) {
const customHost = helpers.queryString('host', search);
const customPort = helpers.queryString('port', search);
if (customHost && customPort) {
mopidyActions.set({ host: customHost, port: customPort });
uiActions.set({ initial_setup_complete: true });
// Allow 100ms for the action above to complete before we re-route
setTimeout(() => {
history.push('/');
}, 100);
// Just show default initial setup for fresh installs
} else if (!initial_setup_complete) {
history.push('/initial-setup'); history.push('/initial-setup');
} }
} }

View File

@ -10,6 +10,7 @@ export default class Parallax extends React.Component {
this.state = { this.state = {
loaded: false, loaded: false,
url: null, url: null,
outgoingUrl: null,
}; };
} }
@ -20,7 +21,7 @@ export default class Parallax extends React.Component {
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.image != this.state.url) { if (nextProps.image !== this.state.url) {
this.loadImage(nextProps.image); this.loadImage(nextProps.image);
} }
} }
@ -53,26 +54,26 @@ export default class Parallax extends React.Component {
} }
render() { render() {
let class_name = 'parallax preserve-3d'; const {
if (this.props.blur) { blur,
class_name += ' parallax--blur'; fixedHeight,
} animate = true,
if (this.state.loaded) { } = this.props;
class_name += ' parallax--loaded'; const {
} loaded,
if (this.props.fixedHeight) { url,
class_name += ' parallax--fixed-height'; } = this.state;
} else {
class_name += ' parallax--flexible-height';
}
let style = {}; let className = 'parallax preserve-3d';
if (this.state.loaded && this.state.url) { className += ` parallax--${fixedHeight ? 'fixed' : 'flexible'}-height`;
style = { backgroundImage: `url("${this.state.url}")` }; if (blur) className += ' parallax--blur';
} if (loaded) className += ' parallax--loaded';
if (animate) className += ' parallax--animate';
const style = loaded && url ? { backgroundImage: `url("${url}")` } : {};
return ( return (
<div className={class_name}> <div className={className}>
<div className="parallax__layer preserve-3d"> <div className="parallax__layer preserve-3d">
<div className="parallax__image" style={style} /> <div className="parallax__image" style={style} />
<div className="parallax__overlay" /> <div className="parallax__overlay" />

View File

@ -233,7 +233,7 @@ class Queue extends React.Component {
<Icon name="play_arrow" type="material" /> <Icon name="play_arrow" type="material" />
Now playing Now playing
</Header> </Header>
<Parallax blur image={current_track_image} /> <Parallax image={current_track_image} blur />
<div className="content-wrapper"> <div className="content-wrapper">
<div className="current-track"> <div className="current-track">
{this.renderArtwork(current_track_image)} {this.renderArtwork(current_track_image)}

View File

@ -15,16 +15,35 @@ class InitialSetup extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const {
host,
port,
username,
allow_reporting,
} = props;
this.state = { this.state = {
username: this.props.username, username,
allow_reporting: this.props.allow_reporting, allow_reporting,
host: this.props.host, host,
port: this.props.port, port,
}; };
} }
componentDidMount() { componentDidMount() {
this.props.uiActions.setWindowTitle('Welcome to Iris'); const {
location: {
search,
},
uiActions,
} = this.props;
// Check for url-parsed configuration values
const customHost = helpers.queryString('host', search);
const customPort = helpers.queryString('port', search);
this.setState({ host: customHost, port: customPort });
uiActions.setWindowTitle('Welcome to Iris');
} }
handleSubmit(e) { handleSubmit(e) {
@ -49,7 +68,7 @@ class InitialSetup extends React.Component {
this.setState({ saving: true }); this.setState({ saving: true });
// Wait a jiffy to allow changes to apply to store // Wait a jiffy to allow changes to apply to store
setTimeout(() => { setTimeout(() => {
// We've changed a connection setting, so need to reload // We've changed a connection setting, so need to reload
if (self.state.host !== self.props.host || self.state.port !== self.props.port) { if (self.state.host !== self.props.host || self.state.port !== self.props.port) {
window.location = '/'; window.location = '/';
@ -78,7 +97,7 @@ class InitialSetup extends React.Component {
<input <input
type="text" type="text"
onChange={(e) => this.setState({ username: e.target.value.replace(/\W/g, '') })} onChange={(e) => this.setState({ username: e.target.value.replace(/\W/g, '') })}
value={this.state.username} value={this.state.username}
/> />
<div className="description"> <div className="description">
A non-unique string used to identify this client (no special characters) A non-unique string used to identify this client (no special characters)
@ -92,7 +111,7 @@ class InitialSetup extends React.Component {
<input <input
type="text" type="text"
onChange={(e) => this.setState({ host: e.target.value })} onChange={(e) => this.setState({ host: e.target.value })}
value={this.state.host} value={this.state.host}
/> />
</div> </div>
</div> </div>
@ -102,12 +121,12 @@ class InitialSetup extends React.Component {
<input <input
type="text" type="text"
onChange={(e) => this.setState({ port: e.target.value })} onChange={(e) => this.setState({ port: e.target.value })}
value={this.state.port} value={this.state.port}
/> />
</div> </div>
</div> </div>
{helpers.isHosted() ? null : ( {helpers.isHosted() ? null : (
<div className="field checkbox"> <div className="field checkbox">
<div className="input"> <div className="input">
<label> <label>
@ -115,21 +134,21 @@ class InitialSetup extends React.Component {
type="checkbox" type="checkbox"
name="allow_reporting" name="allow_reporting"
checked={this.state.allow_reporting} checked={this.state.allow_reporting}
onChange={(e) => this.setState({ allow_reporting: !this.state.allow_reporting })} onChange={(e) => this.setState({ allow_reporting: !this.state.allow_reporting })}
/> />
<span className="label"> <span className="label">
Allow reporting of anonymous usage statistics Allow reporting of anonymous usage statistics
</span> </span>
</label> </label>
<p className="description"> <p className="description">
This anonymous usage data is important in identifying errors and potential features that make Iris better for everyone. Want to know more? Read the This anonymous usage data is important in identifying errors and potential features that make Iris better for everyone. Want to know more? Read the
<a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a> <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a>
{!this.state.allow_reporting ? <span className="red-text"> Are you sure you don't want to support this?</span> : null} {!this.state.allow_reporting ? <span className="red-text"> Are you sure you don't want to support this?</span> : null}
. .
{' '} {' '}
</p> </p>
</div> </div>
</div> </div>
)} )}
<div className="actions centered-text"> <div className="actions centered-text">
@ -158,4 +177,4 @@ const mapDispatchToProps = (dispatch) => ({
mopidyActions: bindActionCreators(mopidyActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch),
}); });
export default connect(mapStateToProps, mapDispatchToProps)(InitialSetup); export default connect(mapStateToProps, mapDispatchToProps)(InitialSetup);

View File

@ -27,7 +27,6 @@ $parallax: 'parallax';
} }
&__image { &__image {
@include animate(0.5s);
position: absolute; position: absolute;
top: -10px; top: -10px;
left: -10px; left: -10px;
@ -40,6 +39,12 @@ $parallax: 'parallax';
z-index: 1; z-index: 1;
} }
&--animate {
.#{$parallax}__image {
@include animate(0.5s);
}
}
&__overlay { &__overlay {
content: ''; content: '';
display: block; display: block;