UNPKG

@ledgerhq/live-common

Version:
90 lines 3.3 kB
import React, { createContext, useMemo, useCallback, useContext } from "react"; import differenceBy from "lodash/differenceBy"; import { fromPromise } from "xstate"; import { useMachine } from "@xstate/react"; import { localizeAnnouncements, filterAnnouncements } from "./logic"; import defaultFetchApi from "./api"; import { announcementMachine } from "./machine"; const AnnouncementsContext = createContext({ seenIds: [], allIds: [], cache: {}, isLoading: false, lastUpdateTime: undefined, error: undefined, updateCache: () => Promise.resolve(), setAsSeen: () => { }, }); export function useAnnouncements() { return useContext(AnnouncementsContext); } export const AnnouncementProvider = ({ children, context, handleLoad, handleSave, autoUpdateDelay, onNewAnnouncement, onAnnouncementRead, fetchApi = defaultFetchApi, }) => { const fetchData = useCallback(async (arg0) => { const { allIds, cache } = arg0.input; const rawAnnouncements = await fetchApi.fetchAnnouncements(); const localizedAnnouncements = localizeAnnouncements(rawAnnouncements, context); const announcements = filterAnnouncements(localizedAnnouncements, context); const oldAnnouncements = allIds.map((uuid) => cache[uuid]); const newAnnouncements = differenceBy(announcements, oldAnnouncements, announcement => announcement.uuid); if (onNewAnnouncement) { newAnnouncements.forEach(announcement => { onNewAnnouncement(announcement); }); } return { announcements, updateTime: Date.now(), }; }, [context, onNewAnnouncement, fetchApi]); const emitNewAnnouncement = useCallback(({ context }) => { if (onAnnouncementRead) { onAnnouncementRead(context.cache[context.seenId]); } }, [onAnnouncementRead]); const loadData = useCallback(async () => { const { announcements, lastUpdateTime, seenIds } = await handleLoad(); return { announcements, lastUpdateTime, seenIds, }; }, [handleLoad]); const saveData = useCallback(({ context }) => { const { cache, lastUpdateTime, seenIds, allIds } = context; const announcements = allIds.map((id) => cache[id]); handleSave({ announcements, seenIds, lastUpdateTime, }); }, [handleSave]); const [state, send] = useMachine(announcementMachine.provide({ actions: { saveData, emitNewAnnouncement, }, actors: { loadData: fromPromise(loadData), fetchData: fromPromise(fetchData), }, delays: { AUTO_UPDATE_DELAY: autoUpdateDelay, }, })); const api = useMemo(() => ({ updateCache: async () => { send({ type: "UPDATE_DATA", }); }, setAsSeen: (seenId) => { send({ type: "SET_AS_SEEN", seenId, }); }, }), [send]); const value = { ...state.context, ...api }; return (React.createElement(AnnouncementsContext.Provider, { value: value }, children)); }; //# sourceMappingURL=index.js.map