Last active
January 11, 2021 16:23
-
-
Save HipsterBrown/df4cd7efdb35b1305ec8f8c803e6f273 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Available variables: | |
| // - Machine | |
| // - interpret | |
| // - assign | |
| // - send | |
| // - sendParent | |
| // - spawn | |
| // - raise | |
| // - actions | |
| // - XState (all XState exports) | |
| const gameMachine = Machine({ | |
| id: 'complexMachine', | |
| initial: 'awaitingPermissions', | |
| context: { | |
| audioInputDevices: [], | |
| audioOutputDevices: [], | |
| videoInputDevices: [], | |
| isJoiningMuted: false, | |
| }, | |
| states: { | |
| awaitingPermissions: { | |
| initial: 'makingInitialCheck', | |
| on: { | |
| REPORT_NO_PERMISSION_TO_VIEW: 'youDoNotHavePermissionToViewThisPage', | |
| }, | |
| states: { | |
| makingInitialCheck: { | |
| always: [ | |
| { | |
| cond: 'checkIfUserIsTryingToAccessViaPin', | |
| target: 'isTryingToAccessViaPin', | |
| }, | |
| { | |
| cond: 'isLoggedInAsAUser', | |
| target: 'isLoggedInAsAUser', | |
| }, | |
| { | |
| target: 'errored', | |
| }, | |
| ], | |
| }, | |
| errored: { | |
| onEntry: send('REPORT_NO_PERMISSION_TO_VIEW'), | |
| }, | |
| isLoggedInAsAUser: { | |
| entry: 'startDataStream', | |
| on: { | |
| RECEIVE_DATA: [ | |
| { | |
| cond: 'isNotTheHostOfTheViewing', | |
| target: 'errored', | |
| }, | |
| { actions: 'assignDataToContext', target: 'complete' }, | |
| ], | |
| }, | |
| }, | |
| isTryingToAccessViaPin: { | |
| initial: 'checkingForSessionIdInLocalStorage', | |
| states: { | |
| checkingForSessionIdInLocalStorage: { | |
| invoke: { | |
| src: 'checkForSessionId', | |
| onDone: [ | |
| { | |
| actions: [ | |
| assign((context, event) => { | |
| return { | |
| anonymousSessionId: event.data, | |
| }; | |
| }), | |
| ], | |
| cond: (context) => Boolean(context.anonymousSessionId), | |
| target: 'checksComplete', | |
| }, | |
| { | |
| target: 'checkingUserPin', | |
| }, | |
| ], | |
| }, | |
| }, | |
| checkingUserPin: { | |
| invoke: { | |
| src: 'checkUserPin', | |
| onDone: { | |
| target: 'checksComplete', | |
| actions: [ | |
| 'saveSessionIdToLocalStorage', | |
| assign((context, event) => ({ | |
| anonymousSessionId: event.data, | |
| })), | |
| ], | |
| }, | |
| onError: { | |
| target: 'errored', | |
| }, | |
| }, | |
| }, | |
| errored: { | |
| onEntry: send('REPORT_NO_PERMISSION_TO_VIEW'), | |
| }, | |
| checksComplete: { | |
| type: 'final', | |
| }, | |
| }, | |
| onDone: 'awaitingFirstPacketOfData', | |
| }, | |
| awaitingFirstPacketOfData: { | |
| onEntry: 'startDataStream', | |
| on: { | |
| RECEIVE_DATA: [ | |
| { | |
| cond: 'dataHasErrored', | |
| target: 'errored', | |
| }, | |
| { | |
| cond: 'isTheHostOfTheViewing', | |
| actions: ['clearAnonymousSessionId', 'assignDataToContext'], | |
| target: 'complete', | |
| }, | |
| { | |
| cond: 'hasAccessToTheViewing', | |
| actions: 'assignDataToContext', | |
| target: 'complete', | |
| }, | |
| { | |
| target: 'errored', | |
| }, | |
| ], | |
| }, | |
| }, | |
| complete: { | |
| type: 'final', | |
| }, | |
| }, | |
| onDone: [ | |
| { | |
| cond: 'hasNotLoggedInBefore', | |
| target: 'creatingUserViewing', | |
| }, | |
| { target: 'processingData' }, | |
| ], | |
| }, | |
| processingData: { | |
| always: [ | |
| { | |
| cond: 'hasNoAccessToTheViewing', | |
| target: 'youDoNotHavePermissionToViewThisPage', | |
| }, | |
| { | |
| cond: 'viewingHasEnded', | |
| target: 'viewingHasEnded', | |
| }, | |
| { | |
| cond: 'isHost', | |
| target: 'inViewing', | |
| }, | |
| { | |
| cond: 'thereAreTooManyPeopleInTheViewing', | |
| target: 'waitingForSomeoneElseToLeave', | |
| }, | |
| { | |
| cond: 'hostIsNotHere', | |
| actions: ['reportThatViewersAreWaiting'], | |
| target: 'inViewerWaitingArea', | |
| }, | |
| { | |
| target: 'inViewerWaitingArea', | |
| }, | |
| ], | |
| }, | |
| creatingUserViewing: { | |
| invoke: { | |
| src: 'createUserViewing', | |
| onError: 'youDoNotHavePermissionToViewThisPage', | |
| onDone: 'processingData', | |
| }, | |
| }, | |
| waitingForSomeoneElseToLeave: { | |
| initial: 'waiting', | |
| onDone: 'inViewing', | |
| states: { | |
| waiting: { | |
| on: { | |
| RECEIVE_DATA: { | |
| cond: 'userThatIsWaitingCanJoin', | |
| target: 'canJoin', | |
| }, | |
| }, | |
| }, | |
| canJoin: { | |
| on: { | |
| JOIN_VIEWING: 'joining', | |
| }, | |
| }, | |
| joining: { | |
| type: 'final', | |
| }, | |
| }, | |
| }, | |
| inViewerWaitingArea: { | |
| initial: 'waiting', | |
| on: { | |
| RECEIVE_DATA: { | |
| actions: 'assignDataToContext', | |
| }, | |
| }, | |
| states: { | |
| waiting: { | |
| on: { | |
| REPORT_VIEWING_STARTED: 'meetingIsReady', | |
| }, | |
| }, | |
| meetingIsReady: { | |
| on: { | |
| JOIN_VIEWING: 'readyToJoin', | |
| }, | |
| }, | |
| readyToJoin: { | |
| type: 'final', | |
| }, | |
| }, | |
| onDone: 'inViewing', | |
| }, | |
| youDoNotHavePermissionToViewThisPage: { type: 'final' }, | |
| viewingHasEnded: { | |
| type: 'final', | |
| }, | |
| askingHostViewingEndingOptions: { | |
| on: { | |
| SEND_FOLLOWUP_EMAIL_TO_ATTENDEES: { | |
| actions: [ | |
| 'goToScheduledViewingsPage', | |
| 'reportShouldSendFollowupToAttendees', | |
| 'showToastSayingFollowupEmailHasSent', | |
| ], | |
| }, | |
| REFUSE_SEND_FOLLOWUP_EMAIL_TO_ATTENDEES: { | |
| actions: 'goToScheduledViewingsPage', | |
| }, | |
| }, | |
| }, | |
| attendeeHasLeftViewing: { | |
| type: 'final', | |
| }, | |
| inViewing: { | |
| type: 'parallel', | |
| activities: ['updateViewingWithMyPresence'], | |
| on: { | |
| RECEIVE_DATA: [ | |
| { | |
| cond: 'hasTheViewingEnded', | |
| target: 'viewingHasEnded', | |
| }, | |
| { | |
| actions: 'assignDataToContext', | |
| }, | |
| ], | |
| END_CALL: [ | |
| { | |
| cond: 'isHost', | |
| actions: ['endViewing', 'endCallInTwilio'], | |
| target: 'askingHostViewingEndingOptions', | |
| }, | |
| { | |
| target: 'attendeeHasLeftViewing', | |
| actions: ['endCallInTwilio'], | |
| }, | |
| ], | |
| GIVE_CONTROL_BACK_TO_HOST: { | |
| actions: 'giveControlToHost', | |
| cond: 'isNotHost', | |
| }, | |
| GIVE_CONTROL_TO_VIEWER: { | |
| actions: 'giveControlToViewer', | |
| cond: 'isHost', | |
| }, | |
| RETRIEVE_CONTROL_AS_HOST: { | |
| cond: 'isHost', | |
| actions: 'giveControlToHost', | |
| }, | |
| REQUEST_CONTROL_AS_VIEWER: [ | |
| { | |
| cond: 'isHost', | |
| actions: 'giveControlToHost', | |
| }, | |
| { | |
| cond: 'isAnonymousViewer', | |
| actions: 'requestControlAsAnonymousViewer', | |
| }, | |
| { | |
| cond: 'isLoggedInUser', | |
| actions: 'requestControlAsLoggedInUser', | |
| }, | |
| ], | |
| SEND_MESSAGE: [ | |
| { | |
| cond: 'isAnonymousViewer', | |
| actions: 'sendMessageAsAnonymousViewer', | |
| }, | |
| { | |
| cond: 'isLoggedInUser', | |
| actions: 'sendMessageAsLoggedInUser', | |
| }, | |
| ], | |
| }, | |
| states: { | |
| changePropertyModal: { | |
| initial: 'closed', | |
| states: { | |
| open: { | |
| on: { | |
| CLOSE_PROPERTY_MODAL: 'closed', | |
| UPDATE_PROPERTY: [ | |
| { | |
| cond: 'canUpdateTheProperty', | |
| actions: 'updateViewingProperty', | |
| }, | |
| { | |
| actions: 'showToastThatUserIsNotAllowedToUpdateTheProperty', | |
| }, | |
| ], | |
| }, | |
| }, | |
| closed: { | |
| on: { | |
| OPEN_PROPERTY_MODAL: 'open', | |
| }, | |
| }, | |
| }, | |
| }, | |
| excessViewerWarning: { | |
| initial: 'hasNotWarned', | |
| states: { | |
| hasNotWarned: { | |
| on: {}, | |
| }, | |
| hasWarned: {}, | |
| }, | |
| }, | |
| chatTabs: { | |
| initial: 'callTab', | |
| states: { | |
| chatTab: { | |
| on: { | |
| PRESS_CALL_TAB: 'callTab', | |
| }, | |
| }, | |
| callTab: { | |
| initial: 'noNotificationBadge', | |
| states: { | |
| noNotificationBadge: { | |
| on: { | |
| RECEIVE_NEW_MESSAGES: 'showNotificationBadge', | |
| }, | |
| }, | |
| showNotificationBadge: {}, | |
| }, | |
| on: { | |
| PRESS_CHAT_TAB: 'chatTab', | |
| }, | |
| }, | |
| }, | |
| }, | |
| mobileChatTabs: { | |
| initial: 'noTabOpen', | |
| states: { | |
| noTabOpen: { | |
| initial: 'noNotificationBadge', | |
| id: 'mobileChatTabsNoTabOpen', | |
| on: { | |
| PRESS_CHAT_TAB: 'chatTabOpen', | |
| }, | |
| states: { | |
| noNotificationBadge: { | |
| on: { | |
| RECEIVE_NEW_MESSAGES: 'showNotificationBadge', | |
| PRESS_CALL_TAB: | |
| '#mobileChatTabsCallTabOpen.noNotificationBadge', | |
| }, | |
| }, | |
| showNotificationBadge: { | |
| on: { | |
| PRESS_CALL_TAB: | |
| '#mobileChatTabsCallTabOpen.showNotificationBadge', | |
| }, | |
| }, | |
| }, | |
| }, | |
| chatTabOpen: { | |
| on: { | |
| PRESS_CHAT_TAB: 'noTabOpen', | |
| PRESS_CALL_TAB: 'callTabOpen', | |
| }, | |
| }, | |
| callTabOpen: { | |
| initial: 'noNotificationBadge', | |
| id: 'mobileChatTabsCallTabOpen', | |
| on: { | |
| PRESS_CHAT_TAB: 'chatTabOpen', | |
| }, | |
| states: { | |
| noNotificationBadge: { | |
| on: { | |
| RECEIVE_NEW_MESSAGES: 'showNotificationBadge', | |
| PRESS_CALL_TAB: | |
| '#mobileChatTabsNoTabOpen.noNotificationBadge', | |
| }, | |
| }, | |
| showNotificationBadge: { | |
| on: { | |
| PRESS_CALL_TAB: | |
| '#mobileChatTabsNoTabOpen.showNotificationBadge', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| callStatus: { | |
| initial: 'requestingTwilioAudioOptions', | |
| states: { | |
| notInCall: { | |
| on: { | |
| JOIN_CALL: 'requestingTwilioAudioOptions', | |
| }, | |
| onEntry: 'reportHasNotJoinedCall', | |
| }, | |
| requestingTwilioAudioOptions: { | |
| invoke: { | |
| src: 'requestTwilioAudioOptions', | |
| onError: 'callErrored', | |
| onDone: [ | |
| { | |
| target: 'showingInitialCallOptionsModal', | |
| actions: 'assignOptionsToState', | |
| }, | |
| ], | |
| }, | |
| }, | |
| showingInitialCallOptionsModal: { | |
| on: { | |
| BEGIN_CALL: [ | |
| { | |
| target: 'beginningCall', | |
| }, | |
| ], | |
| BEGIN_CALL_MUTED: [ | |
| { | |
| target: 'beginningCall', | |
| actions: assign((context) => { | |
| return { | |
| ...context, | |
| isJoiningMuted: true, | |
| }; | |
| }), | |
| }, | |
| ], | |
| CHOOSE_DEVICE: { | |
| actions: 'assignDeviceToContext', | |
| }, | |
| REFUSE_TO_JOIN_CALL: 'notInCall', | |
| }, | |
| }, | |
| beginningCall: { | |
| invoke: { | |
| src: 'joiningTwilioCall', | |
| onDone: { | |
| target: 'inCall', | |
| }, | |
| onError: 'callErrored', | |
| }, | |
| }, | |
| inCall: { | |
| type: 'parallel', | |
| onEntry: 'reportHasJoinedCall', | |
| states: { | |
| callOptionsModal: { | |
| initial: 'closed', | |
| states: { | |
| closed: { | |
| on: { | |
| OPEN_CALL_OPTIONS_MODAL: 'open', | |
| }, | |
| }, | |
| open: { | |
| on: { | |
| CLOSE_CALL_OPTIONS_MODAL: 'closed', | |
| CHOOSE_DEVICE: { | |
| actions: [ | |
| 'assignDeviceToContext', | |
| 'tellTwilioThatIChoseANewDevice', | |
| ], | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| video: { | |
| initial: 'checking', | |
| states: { | |
| checking: { | |
| always: [ | |
| { | |
| cond: 'choseNoVideo', | |
| target: 'noVideo', | |
| }, | |
| { | |
| cond: 'isHost', | |
| target: 'video', | |
| }, | |
| { | |
| target: 'noVideo', | |
| }, | |
| ], | |
| }, | |
| noVideo: { | |
| onEntry: ['reportHostIsNotSharingVideo'], | |
| on: { | |
| TURN_ON_VIDEO: { | |
| cond: 'isHost', | |
| target: 'showingVideoOptions', | |
| }, | |
| }, | |
| }, | |
| showingVideoOptions: { | |
| on: { | |
| CHOOSE_DEVICE: { | |
| actions: 'assignDeviceToContext', | |
| }, | |
| CONFIRM_VIDEO_OPTION: { | |
| cond: 'hasSelectedAVideoInputDevice', | |
| target: 'video', | |
| actions: ['turnOnVideoOnTwilio'], | |
| }, | |
| CANCEL_VIDEO_OPTIONS_MODAL: 'noVideo', | |
| }, | |
| }, | |
| video: { | |
| onEntry: ['reportHostIsSharingVideo'], | |
| onExit: ['reportHostIsNotSharingVideo'], | |
| on: { | |
| HIDE_VIDEO: { | |
| target: 'noVideo', | |
| actions: 'turnOffVideoOnTwilio', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| microphone: { | |
| initial: 'checking', | |
| states: { | |
| checking: { | |
| always: [ | |
| { | |
| cond: 'choseMicrophoneMuted', | |
| target: 'muted', | |
| }, | |
| { | |
| target: 'unmuted', | |
| }, | |
| ], | |
| }, | |
| muted: { | |
| onEntry: 'ensureMicrophoneMuted', | |
| on: { | |
| TOGGLE_MUTE: 'unmuted', | |
| UNMUTE: 'unmuted', | |
| }, | |
| }, | |
| unmuted: { | |
| onEntry: 'ensureMicrophoneUnmuted', | |
| on: { | |
| TOGGLE_MUTE: 'muted', | |
| MUTE: 'muted', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| callErrored: { | |
| onEntry: 'reportHasNotJoinedCall', | |
| type: 'final', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment