Skip to content

Instantly share code, notes, and snippets.

@dsngo
Last active September 23, 2020 11:13
Show Gist options
  • Save dsngo/529fb60af32fd808640dcf4ad76d57dc to your computer and use it in GitHub Desktop.
Save dsngo/529fb60af32fd808640dcf4ad76d57dc to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const preCheck = () => new Promise((res,rej)=>res("OK"))
// const preCheck = () => new Promise()
const services = {
authPin: (ctx, e) => {
return new Promise((res, rej) => {
e.payload == "RESOLVE" ? res("RESOLVED") : rej(e.payload);
});
},
authorizing: (ctx, e) => {
return new Promise((res, rej) => {
switch (e.payload) {
case "PIN_SUCCESS":
return res("PIN_SUCCESS");
case "ID_SUCCESS":
return res("ID_SUCCESS");
default:
return rej(e.payload);
}
});
},
initAppStream: (ctx, e) => {
return new Promise((res, rej) => {
e.payload == "RESOLVE" ? res("RESOLVED") : rej(e.payload);
});
},
reconnectAPI: (ctx, e) => {
return new Promise((res, rej) => {
e.payload == "RESOLVE" ? res("RESOLVED") : rej(e.payload);
});
},
getInitTime: (ctx, e) => {
return new Promise((res, rej) => {
e.payload == "RESOLVE" ? res("RESOLVED") : rej(e.payload);
});
},
};
const actionsDef = {
toggleAgree: assign({ agreed: (ctx) => !ctx.agreed }),
showLoad: assign({ loading: true }),
hideLoad: assign({ loading: false }),
resetRetry: assign({ retry: 0 }),
incrRetry: assign({ retry: (ctx) => ctx.retry + 1 }),
doneChk: assign({
mic: true,
video: true,
speaker: true,
network: true,
}),
rejCtx: assign({
mic: (_, e) => e.data != "AudioError",
video: (_, e) => e.data != "VideoError",
network: (_, e) => e.data != "NetworkError",
}),
rejPIN: assign({ pinErrMsg: "Invalid PIN" }),
assignErrMsg: assign({ pinErrMsg: (_, e) => e.data }),
clearErrMsg: assign({ pinErrMsg: "" }),
authorizedPIN: assign({ loginStatus: true }),
setInitTime: assign({ initTime: (ctx, e) => e?.payload || ctx.initTime }),
toggleMedia: assign((_, e) => {}),
assignContext: assign((_, e) => ({ [e.key]: e.value })),
};
const guards = {
validRetry: (context, _, { cond }) => {
return context.retry <= cond.maxRetry;
},
isAgreed: (ctx) => ctx.agreed,
invalidPermission: (_, e) => e?.data == "NotAllowedError",
invalidBrowser: (_, e) => e?.data == "BrowserNotSupported",
invalidTime: (_, e) => e?.payload == "MS_110",
pinSuccess: (_, e) => e?.data == "PIN_SUCCESS",
idSuccess: (_, e) => e?.data == "ID_SUCCESS",
rMR610: (_, e) => e?.payload == "MR_610",
rMR620: (_, e) => e?.payload == "MR_620",
rMR630: (_, e) => e?.payload == "MR_630",
rME200: (_, e) => e?.payload == "ME_200",
};
const delays = {
INIT_DEFAULT: (_, e) => (e?.payload == undefined ? 6e5 : Number(e.playload)),
WAIT_TIME: 3000,
};
const appMachine = Machine(
{
id: "rjs-visitor",
initial: "interview",
context: {
loading: false,
agreed: false,
pinErrMsg: "",
mic: true,
video: true,
speaker: true,
network: true,
loginStatus: false,
retry: 0,
initTime: 33e4,
},
states: {
testing: {},
landing: {
id: "landing",
initial: "mr_100",
states: {
mr_100: {
on: { NEXT: { target: "mr_200", cond: "isAgreed" } },
exit: "toggleAgree",
},
mr_200: {
on: { NEXT: { target: "checking", cond: "isAgreed" } },
exit: "toggleAgree",
},
checking: {
id: "checking",
invoke: {
id: "preCheck",
src: preCheck,
onDone: { target: "#verify", actions: "doneChk" },
onError: [
{
target: "mr_130",
cond: "invalidBrowser",
},
{
target: "mr_110",
cond: "invalidPermission",
},
{
target: "mr_120",
actions: "rejCtx",
},
],
},
entry: "showLoad",
exit: "hideLoad",
},
mr_110: {},
mr_120: {},
mr_130: {},
},
on: {
RESET: ".mr_100",
TOGGLE: { actions: "toggleAgree" },
},
},
verify: {
id: "verify",
initial: "idle",
states: {
idle: {
id: "idle",
initial: "mr_300",
states: {
mr_300: {},
mr_400: { on: { BACK: "mr_300", ALT: "mr_410" } },
mr_410: { on: { BACK: "mr_400" } },
hist: { type: "history" },
},
on: {
CLEAR_MSG: { actions: "clearErrMsg" },
TEST: { actions: assign({ pinErrMsg: "test" }) },
AUTHORIZE: "authorize",
SETTING: "#setting",
},
},
authorize: {
entry: "showLoad",
exit: "hideLoad",
invoke: {
id: "authorize",
src: "authorizing",
onDone: [
{ target: "idle.mr_400", cond: "pinSuccess" },
{ target: "mr_500", cond: "idSuccess" },
],
onError: { target: "idle.hist", actions: "assignErrMsg" },
},
},
setting: {
id: "setting",
initial: "mr_600",
states: {
mr_600: {
on: {
NEXT: [
{
target: "mr_610",
cond: "rMR610",
},
{
target: "mr_620",
cond: "rMR620",
},
{
target: "mr_630",
cond: "rMR630",
},
],
},
},
mr_610: {},
mr_620: {},
mr_630: {},
},
on: { BACK: ".mr_600" },
},
mr_500: { on: { BACK: "idle.hist", NEXT: "#interview" } },
},
on: { RESET: ".idle" },
},
interview: {
id: "interview",
on: { RESET: "#verify" },
invoke: {
id: "getInitTime",
src: "getInitTime",
onDone: { actions: "setInitTime" },
},
initial: "ms_prepare",
states: {
ms_prepare: {
initial: "ms_100",
states: {
ms_100: {
on: { NEXT: "ms_200", INVALID: "ms_110" },
},
ms_110: {
after: {
WAIT_TIME: { actions: send("RESET") },
},
},
ms_200: {
after: {
WAIT_TIME: "ms_300",
},
},
ms_300: {
on: {
NEXT: "#interviewing",
},
},
},
},
interviewing: {
id: "interviewing",
states: {
start: {},
reconnecting: {
entry: ["showLoad", "incrRetry"],
exit: ["hideLoad", "resetRetry"],
on: {
DONE: "start",
ERR: [
{
target: "reconnecting",
cond: { type: "validRetry", maxRetry: 20 },
},
{ actions: send("RESET") },
],
},
},
end: {
initial: "routing",
states: {
routing: {
on: {
"": [
{ target: "me_200", cond: "rME200" },
{ target: "me_100" },
],
},
},
me_100: { type: "final" },
me_200: { type: "final" },
},
},
},
on: {
TOGGLE: { actions: "toggleMedia" },
END: ".end",
ERR: ".reconnecting",
},
},
},
},
},
on: {
ASSIGN: { actions: "assignContext" },
},
},
{ delays, services, actions: actionsDef, guards }
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment