Skip to content

Instantly share code, notes, and snippets.

@leeovery
Last active August 1, 2020 16:55
Show Gist options
  • Save leeovery/59669ef1673f14a286561ca7c1f7e216 to your computer and use it in GitHub Desktop.
Save leeovery/59669ef1673f14a286561ca7c1f7e216 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const conversationMachine = Machine({
id: 'ConversationMachine',
initial: 'idle',
context: {
Yap: undefined,
User: undefined,
},
// either sending messages, receiving messages, or neither.
// can send and receive at same time.
type: 'parallel',
states: {
sending: {
initial: 'idle',
states: {
idle: {
on: { INIT_SENDING: 'sending' },
},
sending: {
on: {
SENDING_COMPLETE: 'sent',
SENDING_FAILED: 'failed',
},
},
sent: {
on: {
'': 'idle',
},
},
failed: {
on: {
// resend message?
// how does it know which message to send?
// use message ID or have machine for the lifecycle of each message
// when message sent and rendered the machine can be discarded.
// the parent machine can orchastrate this
}
}
},
},
receiving: {
initial: 'idle',
states: {
idle: {
on: { MESSAGE_RECEIVING: 'receiving' },
},
receiving: {
on: { MESSAGE_RECEIVED: 'received' },
},
received: {
on: {
'': 'idle',
},
},
},
},
},
});
const YapsMachine = Machine({
id: 'yap',
initial: 'unknown',
context: {
Yap: {
id: 123,
status: {
description: 'New'
}
},
User: {
id: 456,
},
},
states: {
unknown: {
id: 'unknown',
on: {
'': [
{ target: 'new.normal', cond: 'isNew' },
{ target: 'shown.success', cond: 'isShown' },
{ target: '#end' },
],
},
},
new: {
id: 'new',
initial: 'previous',
states: {
normal: {
on: {
'NEW.SHOW': [
{ target: '#shown', cond: 'canShow' },
{ target: 'noCredits' },
],
},
},
noCredits: {
entry() {
console.log('noCredits');
}
// agent tried to show listing but has no credits
// trigger purchase flow to upgrade or buy a bundle?
},
previous: {
type: 'history',
target: 'normal'
}
},
on: {
'NEW.REJECT': [
{ target: 'rejected', cond: 'canReject' },
{ target: '#new' }, // TODO - show error message
],
'NEW.SOLD': [
{ target: 'sold', cond: 'canSell' },
{ target: '#new' }, // TODO - show error message
],
},
},
shown: {
id: 'shown',
initial: 'pending',
states: {
pending: {
on: {
'SHOW.CONFIRM': 'loading',
'SHOW.CANCEL': '#new',
},
},
loading: {
invoke: {
id: 'showListing',
src: 'invokeShowYap',
onDone: {
target: 'success',
actions: ['assignYap', 'sendUpdate'],
},
onError: {
target: 'failure',
},
},
},
success: {
invoke: {
id: 'ConversationMachine',
src: 'invokeConversationMachine',
data: {
Yap: (context, event) => context.Yap,
User: (context, event) => context.User,
},
// onDone: ?
},
on: {
'SHOW.CLOSE': [
{ target: '#closed', cond: 'canClose' },
// { target: '#shown' }, // TODO - show error message
],
'SHOW.SOLD': [
{ target: '#sold', cond: 'canSell' },
// { target: '#new' }, // TODO - show error message
],
SEND_MESSAGE: {
actions: send('SEND_MESSAGE', {
to: 'ConversationMachine',
}),
},
},
},
failure: {},
},
},
closed: {
id: 'closed',
initial: 'pending',
states: {
pending: {
on: {
'CLOSE.CONFIRM': 'loading',
'CLOSE.CANCEL': '#unknown',
},
},
loading: {
invoke: {
id: 'closeYap',
src: 'invokeCloseYap',
onDone: {
target: 'success',
actions: ['assignYap', 'sendUpdate'],
},
onError: {
target: 'failure',
},
},
},
success: {
on: {
'': '#end',
}
},
failure: {
// ?
},
},
},
rejected: {
initial: 'pending',
states: {
pending: {
on: {
'REJECT.CONFIRM': 'loading',
'REJECT.CANCEL': '#new',
},
},
loading: {
invoke: {
id: 'rejectYap',
src: 'invokeRejectYap',
onDone: {
target: 'success',
actions: ['assignYap', 'sendUpdate'],
},
onError: {
target: 'failure',
},
},
},
success: {
on: {
'': '#end',
}
},
failure: {
// ?
},
},
},
sold: {
id: 'sold',
initial: 'pending',
states: {
pending: {
on: {
'SOLD.CONFIRM': 'loading',
'SOLD.CANCEL': '#unknown',
},
},
loading: {
invoke: {
id: 'sellYap',
src: 'invokeSellYap',
onDone: {
target: 'success',
actions: ['assignYap', 'sendUpdate'],
},
onError: {
target: 'failure',
},
},
},
success: {
on: {
'': '#end',
}
},
failure: {
// ?
},
},
},
end: {
id: 'end',
type: 'final'
}
},
}, {
actions: {
assignYap: assign({ Yap: (context, { data }) => data }),
sendUpdate: console.log('sendUpdate'),
},
guards: {
isNew: ({ Yap }) => true,
isShown: ({ Yap }) => false,
//
canReject: ({ Yap }) => true,
canSell: ({ Yap }) => true,
canClose: ({ Yap }) => false,
canShow: ({ Yap }) => true,
},
services: {
invokeShowYap: ({ Yap }) => Yap.show(),
invokeRejectYap: ({ Yap }) => Yap.reject(),
invokeSellYap: ({ Yap }) => Yap.sell(),
invokeCloseYap: ({ Yap }) => Yap.close(),
invokeConversationMachine: (context, event) => {
console.log('invokeConversationMachine');
return conversationMachine;
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment