Skip to content

Instantly share code, notes, and snippets.

@farskid
Last active September 12, 2019 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save farskid/d62d569e4ce76f56769aa7ffed95a200 to your computer and use it in GitHub Desktop.
Save farskid/d62d569e4ce76f56769aa7ffed95a200 to your computer and use it in GitHub Desktop.
HSLZone logic using Finite state machines and Reactive statecharts
const zoneMachine = Machine(
{
id: "zoneMachine",
initial: "preparing",
context: { error: undefined, zone: undefined },
states: {
preparing: {
invoke: {
src: "detectLocationSupport",
id: "detectLocationSupport",
onDone: {
target: "ready"
},
onError: {
target: "error"
}
}
},
ready: {
initial: "zone_idle",
states: {
zone_idle: {
on: {
DETECT_ZONE: {
target: "zone_pending"
}
}
},
zone_pending: {
invoke: {
id: "detectZone",
src: "detectZone",
onDone: {
target: "zone_available",
actions: ["setZone"]
},
onError: {
target: "zone_error",
actions: ["setError"]
}
}
},
zone_available: {
initial: "not_watching",
on: {
REFRESH: {
target: "zone_pending"
},
LOCATION_CHANGED: {
target: ".history",
actions: ["setZone", "sendNotif"]
}
},
states: {
history: {
type: "history",
history: "deep"
},
not_watching: {
on: {
WATCH_LOCATION: {
target: "watching"
}
}
},
watching: {
invoke: {
id: "watchLocation",
src: "watchLocationService"
}
}
}
},
zone_error: {
on: {
DETECT_ZONE: {
target: "zone_pending"
}
}
}
}
},
error: {
type: "final"
}
}
},
{
services: {
detectLocationSupport: () => {
return new Promise((resolve, reject) => {
const isSupported = Math.random() > 0.5;
if (isSupported) {
resolve(true);
} else {
reject(false);
}
});
},
detectZone: () => {
return new Promise((resolve, reject) => {
setTimeout(() => {resolve()}, 1000);
});
},
watchLocationService: (ctx, e) => (callback, onEvent) => {
const watchId = setInterval(() => {
callback({
type: "LOCATION_CHANGED",
data: newZone
});
new Notification(`changed zone ${newZone}`);
}, 2000);
return () => {
clearInterval(watchId);
};
}
},
actions: {
setZone: assign({
zone: (_, e) => e.data
}),
setError: assign({
error: (_, e) => e.data
}),
sendNotif: (ctx, e) => {
if ("Notification" in window) {
if (Notification.permission === "default") {
Notification.requestPermission()
.then(permission => {
if (permission === "granted") {
new Notification(`Your zone changed to ${e.data}`);
}
})
.catch(err => {});
} else if (Notification.permission === "granted") {
new Notification(`Your zone changed to ${e.data}`);
}
}
}
}
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment