diff --git a/package.json b/package.json index 8b7edce..9204c3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "overwolf-hooks", - "version": "4.1.5", + "version": "4.2.0", "description": "custom hooks to help use overwolf api with the new react hooks technology.", "author": "AlbericoD", "license": "MIT", diff --git a/src/hooks/useLauncherEventProvider/index.ts b/src/hooks/useLauncherEventProvider/index.ts new file mode 100644 index 0000000..2630ef6 --- /dev/null +++ b/src/hooks/useLauncherEventProvider/index.ts @@ -0,0 +1 @@ +export * from "./useLauncherEventProvider"; diff --git a/src/hooks/useLauncherEventProvider/useLauncherEventProvider.test.ts b/src/hooks/useLauncherEventProvider/useLauncherEventProvider.test.ts new file mode 100644 index 0000000..9d5efa1 --- /dev/null +++ b/src/hooks/useLauncherEventProvider/useLauncherEventProvider.test.ts @@ -0,0 +1,16 @@ +import { useLauncherEventProvider } from "./useLauncherEventProvider"; +import { renderHook } from "@testing-library/react"; + +describe("useGameEventProvider values", () => { + it("should return false when there are no required features", () => { + const { result } = renderHook(() => + useLauncherEventProvider( + -1, + { onInfoUpdates: () => {}, onNewEvents: () => {} }, + [] + ) + ); + const { started } = result.current; + expect(started).toBeFalsy(); + }); +}); diff --git a/src/hooks/useLauncherEventProvider/useLauncherEventProvider.ts b/src/hooks/useLauncherEventProvider/useLauncherEventProvider.ts new file mode 100644 index 0000000..7ab896e --- /dev/null +++ b/src/hooks/useLauncherEventProvider/useLauncherEventProvider.ts @@ -0,0 +1,136 @@ +import { useCallback, useState } from "react"; +import { sleep } from "../../lib/utils"; +import { log } from "../../lib/log"; + +interface UseLauncherEventProviderEventsDelegate { + onInfoUpdates( + info: any + ): void; + onNewEvents(events: any): void; +} +const getInfo = (launcherClassId: number): Promise> => { + return new Promise((resolve) => { + overwolf.games.launchers.events.getInfo(launcherClassId, (info) => resolve(info)); + }); +}; +export function useLauncherEventProvider( + launcherClassId: number, + delegate: UseLauncherEventProviderEventsDelegate, + requiredFeatures: Array, + featureRetries = 10, + displayLog = false +) { + const [started, setStarted] = useState(false); + + const onInfoUpdates = useCallback( + ( + info: UseLauncherEventProviderEventsDelegate["onInfoUpdates"]["arguments"] + ): void => { + delegate.onInfoUpdates(info); + if (displayLog) { + log( + JSON.stringify(info, null, 2), + "useLauncherEventProvider.ts", + "onInfoUpdates() -> delegate" + ); + } + }, + [delegate, displayLog] + ); + + const onNewEvents = useCallback( + ( + events: UseLauncherEventProviderEventsDelegate["onNewEvents"]["arguments"] + ): void => { + delegate.onNewEvents(events); + if (displayLog) { + log( + JSON.stringify(events, null, 2), + "useLauncherEventProvider.ts", + "onNewEvents() -> delegate" + ); + } + }, + [delegate, displayLog] + ); + + const unRegisterEvents = (): void => { + overwolf.games.launchers.events.onInfoUpdates.removeListener(onInfoUpdates); + overwolf.games.launchers.events.onNewEvents.removeListener(onNewEvents); + }; + const registerEvents = (): void => { + unRegisterEvents(); + overwolf.games.launchers.events.onInfoUpdates.addListener(onInfoUpdates); + overwolf.games.launchers.events.onNewEvents.addListener(onNewEvents); + }; + + const setRequiredFeatures = useCallback(async () => { + if (!requiredFeatures.length) return setStarted(false); + let tries: number = 1; + let result: overwolf.games.launchers.events.SetRequiredFeaturesResult = { + success: false, + supportedFeatures: [], + }; + + while (tries <= featureRetries) { + log( + `try ${tries} of ${featureRetries}`, + "useLauncherEventProvider.ts", + "setRequiredFeatures() -> callback -> try" + ); + result = await new Promise((resolve) => { + overwolf.games.launchers.events.setRequiredFeatures( + launcherClassId, + requiredFeatures, + (requiredResult) => resolve(requiredResult) + ); + }); + + if (result.success) { + log( + JSON.stringify(result, null, 2), + "useLauncherEventProvider.ts", + "setRequiredFeatures() -> callback -> success" + ); + const isSupported = + Array.isArray(result.supportedFeatures) && + result.supportedFeatures.length > 0; + + setStarted(isSupported); + return void 0; + } + + await sleep(3000); + tries++; + } + log( + JSON.stringify(result, null, 2), + "useLauncherEventProvider.ts", + "setRequiredFeatures() -> callback -> failure" + ); + + setStarted(false); + return void 0; + }, [requiredFeatures]); + + const start = useCallback(async (): Promise => { + if (started) return; + + registerEvents(); + + await setRequiredFeatures(); + + const { res, success } = await getInfo(launcherClassId); + + if (res && success) { + onInfoUpdates(res); + } + }, [setRequiredFeatures, onInfoUpdates, started, registerEvents]); + + const stop = useCallback((): void => { + setStarted(false); + unRegisterEvents(); + }, [unRegisterEvents]); + + return { started, start, stop } as const; +} diff --git a/src/index.ts b/src/index.ts index aa0aba8..1b47d81 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export * from "./hooks/useGameEventProvider/useGameEventProvider"; +export * from "./hooks/useLauncherEventProvider/useLauncherEventProvider"; export * from "./hooks/useRunningGame/useRunningGame"; export * from "./hooks/useWindow"; export * from "./hooks/useDrag/useDrag";