@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
90 lines • 3.3 kB
JavaScript
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