Introduce shelter inspired api/flux
This shows a good example of adding to the Bunny APIs
This commit is contained in:
parent
9fc5326c71
commit
4ffebc8671
8 changed files with 71 additions and 4 deletions
|
|
@ -4,6 +4,7 @@
|
|||
@bunny from BunnyObject {
|
||||
api {
|
||||
commands
|
||||
flux
|
||||
native {
|
||||
fs
|
||||
modules
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bunny-types",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.6",
|
||||
"description": "Types for Bunny, a mod for Discord's mobile apps",
|
||||
"author": "pylixonly",
|
||||
"publishConfig": {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { initCorePlugins } from "@core/plugins";
|
|||
import initSettings from "@core/ui/settings";
|
||||
import { patchAssets } from "@lib/api/assets";
|
||||
import { patchCommands } from "@lib/api/commands";
|
||||
import { injectFluxInterceptor } from "@lib/api/flux";
|
||||
import { isThemeSupported } from "@lib/api/native/loader";
|
||||
import { patchLogHook } from "@lib/debug";
|
||||
import { initPlugins } from "@lib/managers/plugins";
|
||||
|
|
@ -23,6 +24,7 @@ export default async () => {
|
|||
|
||||
// Load everything in parallel
|
||||
const unloads = await Promise.all([
|
||||
injectFluxInterceptor(),
|
||||
patchLogHook(),
|
||||
patchAssets(),
|
||||
patchCommands(),
|
||||
|
|
|
|||
42
src/lib/api/flux/index.ts
Normal file
42
src/lib/api/flux/index.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// shelter-mod inspired
|
||||
import { FluxDispatcher } from "@lib/metro/common";
|
||||
|
||||
const blockedSym = Symbol.for("bunny.flux.blocked");
|
||||
const modifiedSym = Symbol.for("bunny.flux.modified");
|
||||
|
||||
export const dispatcher = FluxDispatcher;
|
||||
|
||||
type Intercept = (payload: Record<string, any> & { type: string; }) => any;
|
||||
let intercepts: Intercept[] = [];
|
||||
|
||||
export function injectFluxInterceptor() {
|
||||
const cb = (payload: any) => {
|
||||
for (const intercept of intercepts) {
|
||||
const res = intercept(payload);
|
||||
|
||||
// nullish -> nothing, falsy -> block, object -> modify
|
||||
if (res == null) {
|
||||
continue;
|
||||
} else if (!res) {
|
||||
payload[blockedSym] = true;
|
||||
} else if (typeof res === "object") {
|
||||
Object.assign(payload, res);
|
||||
payload[modifiedSym] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return blockedSym in payload;
|
||||
};
|
||||
|
||||
(dispatcher._interceptors ??= []).unshift(cb);
|
||||
|
||||
return () => dispatcher._interceptors &&= dispatcher._interceptors.filter(v => v !== cb);
|
||||
}
|
||||
|
||||
export function intercept(cb: Intercept) {
|
||||
intercepts.push(cb);
|
||||
|
||||
return () => {
|
||||
intercepts = intercepts.filter(i => i !== cb);
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
export * as assets from "./assets";
|
||||
export * as commands from "./commands";
|
||||
export * as flux from "./flux";
|
||||
export * as native from "./native";
|
||||
export * as patcher from "./patcher";
|
||||
export * as storage from "./storage";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { find, findByProps } from "@metro/filters";
|
||||
import { Dispatcher } from "@metro/types";
|
||||
|
||||
const colorModule = findByProps("colors", "unsafe_rawColors");
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ export const NavigationNative = findByProps("NavigationContainer");
|
|||
|
||||
// Flux
|
||||
export const Flux = findByProps("connectStores");
|
||||
export const FluxDispatcher = findByProps("_currentDispatchActionType");
|
||||
export const FluxDispatcher = findByProps("_currentDispatchActionType") as Dispatcher;
|
||||
|
||||
// React
|
||||
export const React = window.React = findByProps("createElement") as typeof import("react");
|
||||
|
|
|
|||
19
src/lib/metro/types.ts
Normal file
19
src/lib/metro/types.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
export interface Dispatcher {
|
||||
_actionHandlers: unknown;
|
||||
_interceptors?: ((payload: any) => void | boolean)[];
|
||||
_currentDispatchActionType: undefined | string;
|
||||
_processingWaitQueue: boolean;
|
||||
_subscriptions: Record<string, Set<(payload: any) => void>>;
|
||||
_waitQueue: unknown[];
|
||||
|
||||
addDependencies(node1: any, node2: any): void;
|
||||
dispatch(payload: any): Promise<void>;
|
||||
flushWaitQueue(): void;
|
||||
isDispatching(): boolean;
|
||||
register(name: string, actionHandler: Record<string, (e: any) => void>, storeDidChange: (e: any) => boolean): string;
|
||||
setInterceptor(interceptor?: (payload: any) => void | boolean): void;
|
||||
subscribe(actionType: string, callback: (payload: any) => void): () => void;
|
||||
unsubscribe(actionType: string, callback: (payload: any) => void): () => void;
|
||||
wait(cb: () => void): void;
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ export type BunnyObject = ReturnType<typeof _bunnyObject>;
|
|||
const _bunnyObject = () => ({ // this function is never used, only exists for typings
|
||||
api: {
|
||||
...api,
|
||||
flux: utils.without({ ...api.flux }, "injectFluxInterceptor"),
|
||||
commands: { ...api.commands },
|
||||
native: {
|
||||
...api.native,
|
||||
|
|
@ -59,7 +60,7 @@ const _bunnyObject = () => ({ // this function is never used, only exists for ty
|
|||
assets: { ...api.assets },
|
||||
patcher: utils.without({
|
||||
...patcher,
|
||||
unpatchAll: () => {}
|
||||
unpatchAll: () => { }
|
||||
}, "unpatchAll")
|
||||
},
|
||||
managers: {
|
||||
|
|
@ -101,5 +102,5 @@ const _bunnyObject = () => ({ // this function is never used, only exists for ty
|
|||
},
|
||||
debug: { ...debug },
|
||||
version: debug.versionHash,
|
||||
unload: () => {},
|
||||
unload: () => { },
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue