@applicaster/zapp-react-native-ui-components
Version:
Applicaster Zapp React Native ui components for the Quick Brick App
137 lines (112 loc) • 3.51 kB
text/typescript
import { findPluginByIdentifier } from "@applicaster/zapp-react-native-utils/pluginUtils";
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
import { loggerLiveImageManager } from "../../../VideoLive/loggerHelper";
const { log_debug, log_error } = loggerLiveImageManager;
export type PreloadHookConfig = ZappPreloadPlugins & {
configuration: any;
};
function runHookWithCallback(
invoke: (
payload: any,
callback: (result: hookCallbackArgs) => void,
abortCallback: () => void
) => void,
payload: any
): Promise<{ payload: any; aborted: boolean }> {
return new Promise((resolve, reject) => {
const abortCallback = () => {
resolve({ payload, aborted: true });
};
try {
invoke(
payload,
({
success,
error,
payload: resultPayload,
abort,
}: hookCallbackArgs) => {
if (error) {
reject(error);
} else if (!success || abort) {
resolve({ payload: resultPayload ?? payload, aborted: true });
} else {
resolve({ payload: resultPayload ?? payload, aborted: false });
}
},
abortCallback
);
} catch (error) {
log_error(`Error running preload hook: ${error.message}`, { error });
reject(error);
}
});
}
// TODO: Move this function to a more generic place,
// as it can be used by other components that want to run preload hooks
// and add test coverage for it
export async function executePreloadHooks({
preloadHooks,
entry,
}: {
preloadHooks: PreloadHookConfig[];
entry: ZappEntry;
}): Promise<ZappEntry | null> {
if (!preloadHooks?.length) {
return entry;
}
const sortedHooks = [...preloadHooks].sort(
(a, b) => (a.weight || 0) - (b.weight || 0)
);
const hookNames = sortedHooks.map((hook) => hook.identifier).join(", ");
log_debug(
`Preload hook sequence: ${hookNames}, entry: ${entry.id} - ${entry.title}`
);
let payload: any = entry;
let needsAbort = false;
const plugins = appStore.get("plugins");
for (const hookConfig of sortedHooks) {
const plugin = findPluginByIdentifier(hookConfig.identifier, plugins, true);
if (!plugin?.module) {
log_debug(
`Preload hook plugin not found: ${hookConfig.identifier}, skipping`
);
continue;
}
const { module: hookModule } = plugin;
if (hookModule.skipHook?.(payload)) {
log_debug(`Skipping hook: ${hookConfig.identifier}`);
continue;
}
if (hookModule.runInBackground) {
log_debug(
`Running background hook: ${hookConfig.identifier}, entry: ${payload?.id} - ${payload?.title}`
);
const result = await runHookWithCallback(
(item, callback, abortCallback) =>
hookModule
.runInBackground(item, callback, hookConfig, abortCallback)
?.catch?.((error: Error) => {
log_error(
`Error running background preload hook: ${hookConfig.identifier}, error: ${error.message}`,
{ error }
);
callback({ success: false, payload: item, error });
}),
payload
);
payload = result.payload;
needsAbort = result.aborted;
}
if (needsAbort) {
log_debug(
`Preload hook requested abort: ${hookConfig.identifier}, stopping chain`
);
break;
}
}
if (needsAbort) {
return null;
}
return payload;
}