Source: lib/machine/onlineStatus.js

import { createMachine } from "@/import/xstate";
import GeneralSyncHelper from "@/shared/helper/sync/general";
import { distinctUntilChanged, map } from "rxjs/operators";

/**
 * @param {number} showOnlineAgainMessageInSeconds Default: 30. Amount of seconds that the "you're back online" message is shown.
 * @return {object} Xstate state machine.
 */
export const createOnlineStatusMachine = (showOnlineAgainMessageInSeconds = 30) => {
  const events = GeneralSyncHelper.isUserOnline$.pipe(
    map((bool) => (bool ? "ONLINE" : "OFFLINE")),
    distinctUntilChanged()
  );
  return createMachine({
    id: "OnlineStatus",
    initial: "init",
    predictableActionArguments: true,
    invoke: {
      src: () => events,
    },
    on: {
      ONLINE: ".online",
      OFFLINE: ".offline",
    },
    states: {
      init: {
        on: {
          ONLINE: "#steady",
          OFFLINE: "#offline",
        },
      },
      offline: {
        id: "offline",
      },
      online: {
        id: "online",
        initial: "notify",
        on: {
          USER_NOTIFIED: {
            target: ".steady",
          },
        },
        states: {
          notify: {
            invoke: {
              src: () => (cb) => {
                const interval = setTimeout(() => {
                  cb("USER_NOTIFIED");
                }, 1000 * showOnlineAgainMessageInSeconds);

                return () => {
                  clearTimeout(interval);
                };
              },
            },
          },
          steady: {
            id: "steady",
          },
        },
      },
    },
  });
};