2016-10-17 10:39:11 +13:00
2019-02-10 19:51:33 +13:00
import React from 'react' ;
2019-01-09 16:56:35 +13:00
import { connect } from 'react-redux' ;
import { bindActionCreators } from 'redux' ;
2019-01-14 16:50:21 +13:00
import { Route , Link } from 'react-router-dom' ;
2016-11-29 15:36:01 +13:00
2019-04-16 20:06:56 +12:00
import ConfirmationButton from '../components/Fields/ConfirmationButton' ;
import PusherConnectionList from '../components/PusherConnectionList' ;
import SourcesPriority from '../components/Fields/SourcesPriority' ;
import Commands from '../components/Fields/Commands' ;
2019-05-10 10:34:58 +12:00
import TextField from '../components/Fields/TextField' ;
2019-04-16 20:06:56 +12:00
import Header from '../components/Header' ;
import Icon from '../components/Icon' ;
import Services from '../components/Services' ;
import * as helpers from '../helpers' ;
import * as coreActions from '../services/core/actions' ;
import * as uiActions from '../services/ui/actions' ;
import * as pusherActions from '../services/pusher/actions' ;
import * as mopidyActions from '../services/mopidy/actions' ;
import * as lastfmActions from '../services/lastfm/actions' ;
import * as spotifyActions from '../services/spotify/actions' ;
2017-08-05 22:25:25 +12:00
class Settings extends React . Component {
2017-10-10 13:05:28 +13:00
constructor ( props ) {
2017-08-05 22:25:25 +12:00
super ( props ) ;
this . state = {
mopidy _host : this . props . mopidy . host ,
mopidy _port : this . props . mopidy . port ,
2018-10-16 21:21:36 +13:00
mopidy _library _artists _uri : this . props . mopidy . library _artists _uri ,
mopidy _library _albums _uri : this . props . mopidy . library _albums _uri ,
2017-08-05 22:25:25 +12:00
pusher _username : this . props . pusher . username ,
input _in _focus : null
}
}
2018-06-28 08:12:03 +12:00
componentDidMount ( ) {
this . props . uiActions . setWindowTitle ( "Settings" ) ;
}
2018-06-15 08:56:17 +12:00
componentWillReceiveProps ( nextProps ) {
2017-08-05 22:25:25 +12:00
var changed = false
var state = this . state
2019-06-20 08:26:20 +12:00
if ( nextProps . pusher . username && nextProps . pusher . username != this . state . pusher _username && this . state . input _in _focus != 'pusher_username' ) {
2018-06-15 08:56:17 +12:00
state . pusher _username = nextProps . pusher . username
2017-08-05 22:25:25 +12:00
changed = true
}
if ( changed ) {
this . setState ( state )
}
}
resetAllSettings ( ) {
localStorage . clear ( ) ;
window . location = '#'
window . location . reload ( true )
return false ;
}
2017-11-27 16:38:33 +13:00
setConfig ( e ) {
this . setState ( { input _in _focus : null } ) ;
2017-08-05 22:25:25 +12:00
e . preventDefault ( ) ;
2017-11-27 16:38:33 +13:00
2018-06-10 10:02:31 +12:00
this . props . mopidyActions . set ( {
2017-11-27 16:38:33 +13:00
host : this . state . mopidy _host ,
2018-10-04 21:07:25 +13:00
port : this . state . mopidy _port
2017-11-27 16:38:33 +13:00
} ) ;
2017-08-05 22:25:25 +12:00
window . location . reload ( true ) ;
return false ;
}
2018-06-10 10:02:31 +12:00
handleBlur ( service , name , value ) {
this . setState ( { input _in _focus : null } ) ;
var data = { } ;
data [ name ] = value ;
this . props [ service + 'Actions' ] . set ( data ) ;
// Any per-field actions
switch ( name ) {
case 'library_albums_uri' :
this . props . mopidyActions . clearLibraryAlbums ( ) ;
break ;
case 'library_artists_uri' :
this . props . mopidyActions . clearLibraryArtists ( ) ;
break ;
}
2017-08-05 22:25:25 +12:00
}
renderApplyButton ( ) {
2017-11-27 16:38:33 +13:00
if ( this . props . mopidy . host == this . state . mopidy _host &&
2018-10-04 21:07:25 +13:00
this . props . mopidy . port == this . state . mopidy _port ) {
2017-11-27 16:38:33 +13:00
return null ;
}
2017-06-27 09:07:25 +12:00
return (
2017-08-05 22:25:25 +12:00
< div className = "field" >
< div className = "name" > < / d i v >
< div className = "input" >
2018-12-05 21:39:06 +13:00
< button type = "submit" className = "button button--secondary" > Apply and reload < / b u t t o n >
2017-08-05 22:25:25 +12:00
< / d i v >
2017-06-27 09:07:25 +12:00
< / d i v >
)
2017-02-21 08:35:24 +13:00
}
2017-11-13 16:52:53 +13:00
renderServerStatus ( ) {
var colour = 'grey' ;
2018-05-20 20:42:20 +12:00
var icon = 'help' ;
2017-11-13 16:52:53 +13:00
var status = 'Unknown' ;
2018-11-02 08:40:44 +13:00
var className = null ;
2017-11-13 16:52:53 +13:00
if ( this . props . mopidy . connecting || this . props . pusher . connecting ) {
2018-05-20 20:42:20 +12:00
icon = 'autorenew' ;
2018-11-02 08:40:44 +13:00
status = 'Connecting...' ;
className = 'icon--spin' ;
2017-11-13 16:52:53 +13:00
} else if ( ! this . props . mopidy . connected || ! this . props . pusher . connected ) {
colour = 'red' ;
icon = 'close' ;
status = 'Disconnected' ;
} else if ( this . props . mopidy . connected && this . props . pusher . connected ) {
colour = 'green' ;
icon = 'check' ;
status = 'Connected' ;
2017-08-04 09:19:19 +12:00
}
2017-08-06 12:20:43 +12:00
return (
2017-11-13 16:52:53 +13:00
< span className = { colour + '-text' } >
2019-04-23 07:48:52 +12:00
< Icon className = { className } name = { icon } / > { status }
2017-11-13 16:52:53 +13:00
< / s p a n >
) ;
}
2017-08-04 09:19:19 +12:00
render ( ) {
2017-08-05 22:25:25 +12:00
var options = (
< span >
2019-01-22 16:57:43 +13:00
< a className = "button button--default button--no-hover" onClick = { e => this . props . history . push ( '/settings/debug' ) } >
2018-05-19 11:15:10 +12:00
< Icon name = "code" / > Debug
2018-11-18 12:54:13 +13:00
< / a >
2018-12-10 21:27:22 +13:00
< a className = "button button--default button--no-hover" href = "https://github.com/jaedb/Iris/wiki" target = "_blank" >
2018-05-19 11:15:10 +12:00
< Icon name = "help" / > Help
2017-08-05 22:25:25 +12:00
< / a >
< / s p a n >
)
2018-04-16 21:58:38 +12:00
2017-08-04 09:19:19 +12:00
return (
< div className = "view settings-view" >
2018-08-27 08:21:41 +12:00
< Header options = { options } uiActions = { this . props . uiActions } >
2018-05-15 21:30:57 +12:00
< Icon name = "settings" type = "material" / >
Settings
< / H e a d e r >
2016-10-29 22:40:02 +13:00
2017-08-04 16:08:57 +12:00
< section className = "content-wrapper" >
2017-01-04 16:14:10 +13:00
2018-10-13 14:28:46 +13:00
< h4 className = "underline" > Server < a name = "server" > < / a > < / h 4 >
2017-11-04 14:03:59 +13:00
2017-11-13 16:52:53 +13:00
< div className = "field" >
< div className = "name" > Status < / d i v >
< div className = "input" >
< div className = "text" >
{ this . renderServerStatus ( ) }
< / d i v >
< / d i v >
2017-08-05 22:25:25 +12:00
< / d i v >
2019-02-12 20:20:25 +13:00
< label className = "field" >
2017-08-05 22:25:25 +12:00
< div className = "name" > Username < / d i v >
< div className = "input" >
2019-05-10 10:34:58 +12:00
< TextField
onChange = { value => this . props . pusherActions . setUsername ( value . replace ( /\W/g , '' ) ) }
2019-06-20 08:26:20 +12:00
value = { this . state . pusher _username }
/ >
2017-09-27 15:39:55 +13:00
< div className = "description" >
A non - unique string used to identify this client ( no special characters )
< / d i v >
2017-08-05 22:25:25 +12:00
< / d i v >
2019-02-12 20:20:25 +13:00
< / l a b e l >
2017-08-05 22:25:25 +12:00
2017-11-27 16:38:33 +13:00
< form onSubmit = { ( e ) => this . setConfig ( e ) } >
2019-02-12 20:20:25 +13:00
< label className = "field" >
2017-08-05 22:25:25 +12:00
< div className = "name" > Host < / d i v >
< div className = "input" >
< input
type = "text"
onChange = { e => this . setState ( { mopidy _host : e . target . value } ) }
onFocus = { e => this . setState ( { input _in _focus : 'mopidy_host' } ) }
onBlur = { e => this . setState ( { input _in _focus : null } ) }
value = { this . state . mopidy _host } / >
< / d i v >
2019-02-12 20:20:25 +13:00
< / l a b e l >
< label className = "field" >
2017-08-05 22:25:25 +12:00
< div className = "name" > Port < / d i v >
< div className = "input" >
< input
type = "text"
onChange = { e => this . setState ( { mopidy _port : e . target . value } ) }
onFocus = { e => this . setState ( { input _in _focus : 'mopidy_port' } ) }
onBlur = { e => this . setState ( { input _in _focus : null } ) }
value = { this . state . mopidy _port } / >
< / d i v >
2019-02-12 20:20:25 +13:00
< / l a b e l >
2017-08-05 22:25:25 +12:00
{ this . renderApplyButton ( ) }
2018-03-30 22:37:38 +13:00
< / f o r m >
2017-08-05 22:25:25 +12:00
2018-10-13 14:28:46 +13:00
< h4 className = "underline" > Services < a name = "services" > < / a > < / h 4 >
2019-01-17 22:13:18 +13:00
< Route path = "/settings/:service?" component = { Services } / >
2017-11-02 21:20:56 +13:00
2018-10-13 14:28:46 +13:00
< h4 className = "underline" > Interface < a name = "interface" > < / a > < / h 4 >
2017-08-05 22:25:25 +12:00
2018-08-24 16:10:41 +12:00
< div className = "field radio" >
< div className = "name" >
Theme
< / d i v >
< div className = "input" >
< label >
< input
type = "radio"
name = "theme"
value = "dark"
checked = { this . props . ui . theme == 'dark' }
onChange = { e => this . props . uiActions . set ( { theme : e . target . value } ) } / >
< span className = "label" > Dark < / s p a n >
< / l a b e l >
< label >
< input
type = "radio"
name = "theme"
value = "light"
checked = { this . props . ui . theme == 'light' }
onChange = { e => this . props . uiActions . set ( { theme : e . target . value } ) } / >
< span className = "label" > Light < / s p a n >
< / l a b e l >
< / d i v >
< / d i v >
2017-08-05 22:25:25 +12:00
< div className = "field checkbox" >
2018-09-18 21:38:37 +12:00
< div className = "name" > Behavior < / d i v >
2017-08-05 22:25:25 +12:00
< div className = "input" >
< label >
< input
type = "checkbox"
name = "log_actions"
checked = { this . props . ui . clear _tracklist _on _play }
onChange = { e => this . props . uiActions . set ( { clear _tracklist _on _play : ! this . props . ui . clear _tracklist _on _play } ) } / >
2018-09-21 11:58:54 +12:00
< span className = "label tooltip" >
2017-11-19 20:38:36 +13:00
Clear tracklist on play of URI ( s )
2018-09-21 11:58:54 +12:00
< span className = "tooltip__content" > Playing one or more URIs will clear the current play queue first < / s p a n >
2017-11-19 20:38:36 +13:00
< / s p a n >
< / l a b e l >
2018-06-29 15:00:23 +12:00
< label >
< input
type = "checkbox"
2019-05-10 10:34:58 +12:00
name = "hotkeys_enabled"
checked = { this . props . ui . hotkeys _enabled }
onChange = { e => this . props . uiActions . set ( { hotkeys _enabled : ! this . props . ui . hotkeys _enabled } ) } / >
2018-06-29 15:00:23 +12:00
< span className = "label" >
2019-05-10 10:34:58 +12:00
Enable hotkeys
2018-06-29 15:00:23 +12:00
< / s p a n >
< / l a b e l >
2019-02-08 16:05:43 +13:00
< label >
< input
type = "checkbox"
name = "smooth_scrolling_enabled"
checked = { this . props . ui . smooth _scrolling _enabled }
onChange = { e => this . props . uiActions . set ( { smooth _scrolling _enabled : ! this . props . ui . smooth _scrolling _enabled } ) } / >
< span className = "label" >
Enable smooth scrolling
< / s p a n >
< / l a b e l >
2019-08-18 16:51:22 +12:00
< label >
< input
type = "checkbox"
name = "playback_controls_touch_enabled"
checked = { this . props . ui . playback _controls _touch _enabled }
onChange = { e => this . props . uiActions . set ( { playback _controls _touch _enabled : ! this . props . ui . playback _controls _touch _enabled } ) } / >
< span className = "label tooltip" >
Enable touch events on play controls
< span className = "tooltip__content" > Allows left - and right - swipe to change tracks < / s p a n >
< / s p a n >
< / l a b e l >
2019-06-14 11:32:56 +12:00
< label >
< input
type = "checkbox"
name = "wide_scrollbar_enabled"
checked = { this . props . ui . wide _scrollbar _enabled }
onChange = { e => this . props . uiActions . set ( { wide _scrollbar _enabled : ! this . props . ui . wide _scrollbar _enabled } ) } / >
< span className = "label" >
Use wide scrollbars
< / s p a n >
< / l a b e l >
2017-08-05 22:25:25 +12:00
< / d i v >
< / d i v >
2018-06-11 08:15:55 +12:00
< div className = "field sources-priority" >
2018-09-18 21:38:37 +12:00
< div className = "name" >
2018-06-11 08:15:55 +12:00
Sources priority
< / d i v >
< div className = "input" >
< SourcesPriority
uri _schemes = { this . props . mopidy . uri _schemes ? this . props . mopidy . uri _schemes : [ ] }
uri _schemes _priority = { this . props . ui . uri _schemes _priority ? this . props . ui . uri _schemes _priority : [ ] }
uiActions = { this . props . uiActions }
/ >
2018-09-18 21:38:37 +12:00
< div className = "description" >
Drag - and - drop to prioritize search providers and results
< / d i v >
2018-06-11 08:15:55 +12:00
< / d i v >
< / d i v >
2018-09-18 21:38:37 +12:00
{ helpers . isHosted ( ) ? null : < div className = "field checkbox" >
< div className = "name" > Reporting < / d i v >
< div className = "input" >
< label >
< input
type = "checkbox"
name = "allow_reporting"
checked = { this . props . ui . allow _reporting }
onChange = { e => this . props . uiActions . set ( { allow _reporting : ! this . props . ui . allow _reporting } ) } / >
< span className = "label" >
Allow reporting of anonymous usage statistics
< / s p a n >
< / l a b e l >
2018-10-09 21:39:38 +13:00
< div className = "description" > This helps identify errors and potential features that make Iris better for everyone . See < a href = "https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target = "_blank" > privacy policy < / a > . < / d i v >
2018-09-18 21:38:37 +12:00
< / d i v >
< / d i v > }
2018-10-26 16:06:31 +13:00
< div className = "field commands-setup" id = "commands-setup" >
2018-10-09 21:39:38 +13:00
< div className = "name" >
Commands
< / d i v >
< div className = "input" >
2019-04-16 20:06:56 +12:00
< Commands
commands = { this . props . pusher . commands }
runCommand = { ( id , notify ) => this . props . pusherActions . runCommand ( id , notify ) }
onChange = { commands => this . props . pusherActions . setCommands ( commands ) }
/ >
2019-01-22 16:57:43 +13:00
< Link to = { '/edit-command' } className = "button button--default" > Add new < / L i n k >
2018-10-09 21:39:38 +13:00
< / d i v >
< / d i v >
2018-10-13 14:28:46 +13:00
< h4 className = "underline" > Advanced < a name = "advanced" > < / a > < / h 4 >
2018-09-18 21:38:37 +12:00
2018-06-10 10:02:31 +12:00
< div className = "field" >
< div className = "name" > Artist library URI < / d i v >
< div className = "input" >
< input
type = "text"
2018-10-16 21:21:36 +13:00
value = { this . state . mopidy _library _artists _uri }
2018-06-10 10:02:31 +12:00
onChange = { e => this . setState ( { mopidy _library _artists _uri : e . target . value } ) }
onBlur = { e => this . handleBlur ( 'mopidy' , 'library_artists_uri' , e . target . value ) }
/ >
< div className = "description" >
2018-10-16 21:21:36 +13:00
URI used for collecting library artists
2018-06-10 10:02:31 +12:00
< / d i v >
< / d i v >
< / d i v >
2019-02-12 20:20:25 +13:00
< label className = "field" >
2018-06-10 10:02:31 +12:00
< div className = "name" > Album library URI < / d i v >
< div className = "input" >
< input
type = "text"
2018-10-16 21:21:36 +13:00
value = { this . state . mopidy _library _albums _uri }
onChange = { e => this . setState ( { mopidy _library _albums _uri : e . target . value } ) }
onBlur = { e => this . handleBlur ( 'mopidy' , 'library_albums_uri' , e . target . value ) }
2018-06-10 10:02:31 +12:00
/ >
< div className = "description" >
2018-10-16 21:21:36 +13:00
URI used for collecting library albums
2018-06-10 10:02:31 +12:00
< / d i v >
< / d i v >
2019-02-12 20:20:25 +13:00
< / l a b e l >
2018-06-10 10:02:31 +12:00
2017-08-05 22:25:25 +12:00
< div className = "field pusher-connections" >
< div className = "name" > Connections < / d i v >
< div className = "input" >
2017-08-06 21:12:57 +12:00
< div className = "text" >
2017-08-05 22:25:25 +12:00
< PusherConnectionList / >
2017-08-06 21:12:57 +12:00
< / d i v >
2017-08-05 22:25:25 +12:00
< / d i v >
< / d i v >
2017-08-06 21:12:57 +12:00
< div className = "field" >
< div className = "name" > Version < / d i v >
< div className = "input" >
2018-04-16 21:58:38 +12:00
< span className = "text" >
2018-11-02 08:40:44 +13:00
{ this . props . pusher . version . current } installed { this . props . pusher . version . upgrade _available ? < span className = "flag dark" > < Icon name = "cloud_download" className = "blue-text" / > & nbsp ; Upgrade available < /span> : <span className="flag dark"><Icon name="check" className="green-text" / > & nbsp ; Up - to - date < / s p a n > }
2018-04-16 21:58:38 +12:00
< / s p a n >
2017-08-05 22:25:25 +12:00
< / d i v >
< / d i v >
2018-11-02 10:20:32 +13:00
< div className = "field" >
2018-12-10 21:27:22 +13:00
< button className = "button button--default" onClick = { e => this . props . pusherActions . localScan ( ) } > Run local scan < / b u t t o n >
2019-01-22 16:57:43 +13:00
< Link className = "button button--default" to = { "/share-configuration" } > Share configuration < / L i n k >
2018-11-02 10:20:32 +13:00
< / d i v >
2017-08-05 22:25:25 +12:00
< div className = "field" >
2018-12-07 11:31:29 +13:00
{ this . props . pusher . version . upgrade _available ? < button className = "button button--secondary" onClick = { e => this . props . pusherActions . upgrade ( ) } > Upgrade to { this . props . pusher . version . latest } < / b u t t o n > : n u l l }
2018-12-05 21:39:06 +13:00
< button className = { "button button--destructive" + ( this . props . mopidy . restarting ? ' button--working' : '' ) } onClick = { e => this . props . pusherActions . restart ( ) } > Restart server < / b u t t o n >
< ConfirmationButton className = "button--destructive" content = "Reset all settings" confirmingContent = "Are you sure?" onConfirm = { ( ) => this . resetAllSettings ( ) } / >
2017-08-05 22:25:25 +12:00
< / d i v >
2018-10-13 14:28:46 +13:00
< h4 className = "underline" > About < a name = "about" > < / a > < / h 4 >
2017-08-05 22:25:25 +12:00
< div className = "field" >
< div >
< em > < a href = "https://github.com/jaedb/Iris" target = "_blank" > Iris < / a > < / e m > i s a n o p e n - s o u r c e p r o j e c t b y < a h r e f = " h t t p s : / / g i t h u b . c o m / j a e d b " t a r g e t = " _ b l a n k " > J a m e s B a r n s l e y < / a > . I t i s p r o v i d e d f r e e a n d w i t h a b s o l u t e l y n o w a r r a n t y . I f y o u p a i d s o m e o n e f o r t h i s s o f t w a r e , p l e a s e l e t m e k n o w .
< / d i v >
< br / > < br / >
< div >
2018-12-10 21:27:22 +13:00
< a className = "button button--default" href = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=james%40barnsley%2enz&lc=NZ&item_name=James%20Barnsley¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted" target = "_blank" >
2018-05-29 08:06:46 +12:00
< Icon type = "fontawesome" name = "paypal" / > Donate
2017-08-05 22:25:25 +12:00
< / a >
2018-12-10 21:27:22 +13:00
< a className = "button button--default" href = "https://github.com/jaedb/Iris" target = "_blank" >
2018-05-29 08:06:46 +12:00
< Icon type = "fontawesome" name = "github" / > GitHub
2017-08-05 22:25:25 +12:00
< / a >
2018-12-10 21:27:22 +13:00
< a className = "button button--default" href = "http://creativecommons.org/licenses/by-nc/4.0/" target = "_blank" > < Icon type = "fontawesome" name = "creative-commons" / > & nbsp ; Licence < / a >
2017-08-05 22:25:25 +12:00
< / d i v >
< / d i v >
< / s e c t i o n >
2016-10-17 10:39:11 +13:00
< / d i v >
) ;
}
2017-08-05 22:25:25 +12:00
}
const mapStateToProps = ( state , ownProps ) => {
return state ;
}
const mapDispatchToProps = ( dispatch ) => {
return {
coreActions : bindActionCreators ( coreActions , dispatch ) ,
uiActions : bindActionCreators ( uiActions , dispatch ) ,
pusherActions : bindActionCreators ( pusherActions , dispatch ) ,
mopidyActions : bindActionCreators ( mopidyActions , dispatch ) ,
2017-11-03 09:06:41 +13:00
lastfmActions : bindActionCreators ( lastfmActions , dispatch ) ,
2017-08-05 22:25:25 +12:00
spotifyActions : bindActionCreators ( spotifyActions , dispatch )
}
}
export default connect ( mapStateToProps , mapDispatchToProps ) ( Settings )