Cancellable processes

This commit is contained in:
James Barnsley
2017-04-06 09:01:53 +12:00
parent f292e512dc
commit 27272dcd0f
7 changed files with 74 additions and 29 deletions

View File

@ -11,9 +11,6 @@ export default class Notifications extends React.Component{
renderNotifications(){
if (!this.props.notifications || this.props.notifications.length <= 0) return null
// we only care about the last notification
var notification = this.props.notifications[this.props.notifications.length-1]
return (
<span>
{
@ -26,14 +23,6 @@ export default class Notifications extends React.Component{
</div>
)
case 'process':
return (
<div className="process notification" key={notification.key}>
<FontAwesome name="close" className="close-button" onClick={ e => this.props.uiActions.cancelProcess(notification.key) } />
{ notification.content }
</div>
)
default:
return (
<div className={notification.type+" notification"} key={notification.key}>
@ -48,6 +37,37 @@ export default class Notifications extends React.Component{
)
}
renderProcesses(){
if (!this.props.processes || this.props.processes.length <= 0) return null
var processes = this.props.processes
var items = []
for (var key in processes){
if (processes.hasOwnProperty(key)){
if (processes[key].cancelling){
items.push(
<div className="process notification cancelling" key={key}>
Cancelling
</div>
)
} else {
items.push(
<div className="process notification" key={key}>
<FontAwesome name="close" className="close-button" onClick={ e => this.props.uiActions.cancelProcess(key) } />
{ processes[key].content }
</div>
)
}
}
}
return (
<span>
{items}
</span>
)
}
// do we want the loading of everything to be displayed?
// not likely...
renderLoader(){
@ -79,6 +99,7 @@ export default class Notifications extends React.Component{
return (
<div className="notifications">
{this.renderNotifications()}
{this.renderProcesses()}
</div>
)
}

View File

@ -239,12 +239,19 @@ const MopidyMiddleware = (function(){
let process_batch = function(){
// process is not active, so abort
if (!store.getState().ui.processes || !store.getState().ui.processes[action.uri]){
// process is not running
if (store.getState().ui.processes && store.getState().ui.processes[action.type]){
if (store.getState().ui.processes[action.type].cancelling){
// recognise as cancelled
store.dispatch(uiActions.stopProcess(action.type))
return false
}
} else {
return false
}
store.dispatch(uiActions.createNotification('Adding '+remaining_uris.length+' URI(s)', 'loading', action.type))
// update our process details
store.dispatch(uiActions.startProcess(action.type, 'Adding '+remaining_uris.length+' URI(s)'))
var params = {uris: remaining_uris.splice(0,5)}
if (action.next && current_track_index > -1){
@ -279,14 +286,13 @@ const MopidyMiddleware = (function(){
// all done
} else {
store.dispatch(uiActions.removeNotification(action.type))
store.dispatch(uiActions.stopProcess(action.type))
}
})
}
// start processing
store.dispatch(uiActions.startProcess(action.type))
store.dispatch(uiActions.startProcess(action.type, 'Adding '+remaining_uris.length+' URI(s)'))
process_batch()
break

View File

@ -262,10 +262,11 @@ export function stopLoading(key){
}
}
export function startProcess(key){
export function startProcess(key,content){
return {
type: 'START_PROCESS',
key: key
key: key,
content: content
}
}

View File

@ -268,15 +268,13 @@ const UIMiddleware = (function(){
case 'CREATE_NOTIFICATION':
// start a timeout to remove this (non loading) notification
if (action.notification.type != 'process'){
var timeout = setTimeout(
function(){
store.dispatch(uiActions.removeNotification(action.notification.key))
},
(action.notification.type == 'shortcut' ? 1000 : 3000)
)
}
// start a timeout to remove this notification
var timeout = setTimeout(
function(){
store.dispatch(uiActions.removeNotification(action.notification.key))
},
(action.notification.type == 'shortcut' ? 1000 : 3000)
)
next(action)
break

View File

@ -745,7 +745,23 @@ export default function reducer(ui = {}, action){
case 'START_PROCESS':
var processes = Object.assign({}, (ui.processes ? ui.processes : []))
processes[action.key] = 'active'
processes[action.key] = {
key: action.key,
content: action.content
}
return Object.assign({}, ui, {processes: processes})
case 'CANCEL_PROCESS':
var processes = Object.assign({}, (ui.processes ? ui.processes : {}))
if (processes[action.key]){
processes[action.key] = Object.assign(
{},
processes[action.key],
{
cancelling: true
}
)
}
return Object.assign({}, ui, {processes: processes})
case 'STOP_PROCESS':

View File

@ -158,6 +158,7 @@ class App extends React.Component{
<Notifications
uiActions={this.props.uiActions}
notifications={this.props.notifications}
processes={this.props.processes}
load_queue={this.props.load_queue} />
{this.props.debug_info ? <DebugInfo /> : null}
</div>
@ -174,6 +175,7 @@ class App extends React.Component{
const mapStateToProps = (state, ownProps) => {
return {
notifications: (state.ui.notifications ? state.ui.notifications : []),
processes: (state.ui.processes ? state.ui.processes : {}),
load_queue: (state.ui.load_queue ? state.ui.load_queue : {}),
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorized,

View File

@ -104,7 +104,8 @@ class Debug extends React.Component{
<div className="name"></div>
<div className="input">
<a className="button secondary" onClick={e => this.props.uiActions.createNotification('Test notification')}>Create notification</a>
<a className="button secondary" onClick={e => this.props.uiActions.createNotification('Process running','process')}>Create process</a>
<a className="button secondary" onClick={e => this.props.uiActions.startProcess('test_process', 'Test process')}>Start process</a>
<a className="button secondary" onClick={e => this.props.uiActions.stopProcess('test_process')}>Stop process</a>
</div>
</div>
</form>