Switch to webpack based extracting

This commit is contained in:
Jonas Dellinger
2022-05-10 23:38:10 +02:00
parent d9e9adead8
commit 2975cf8294
22 changed files with 8656 additions and 158 deletions

3
babel.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript',],
};

5
jest.config.js Normal file
View File

@@ -0,0 +1,5 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

8475
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,8 @@
"scripts": {
"build": "shx rm -rf dist && tsc -b",
"dev": "tsc -b -w",
"prepack": "npm run build"
"prepack": "npm run build",
"test": "jest"
},
"files": [
"/lib",
@@ -32,11 +33,14 @@
},
"homepage": "https://github.com/SteamDeckHomebrew/decky-frontend-lib#readme",
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/react": "16.14.0",
"import-sort-style-module": "^6.0.0",
"jest": "^27.5.1",
"prettier-plugin-import-sort": "^0.0.7",
"react": "16.14.0",
"react": "^16.14.0",
"shx": "^0.3.4",
"ts-jest": "^27.1.4",
"typescript": "^4.6.3"
},
"peerDependencies": {

View File

@@ -1,5 +0,0 @@
import { ReactNode } from 'react';
import { BackdropModule } from '../modules';
export const openBackdrop: (children: ReactNode) => void = BackdropModule.a;

View File

@@ -0,0 +1,16 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
interface ButtonProps {
label?: string;
description?: string;
layout?: 'below';
onClick?(e: MouseEvent): void;
disabled?: boolean;
bottomSeparator?: boolean;
}
export const Button = Object.values(CommonUIModule).find((mod: any) =>
mod?.render?.toString()?.includes('childrenContainerWidth:"min"'),
) as FC<ButtonProps>;

View File

@@ -1,46 +0,0 @@
import { FC, VFC } from 'react';
import { ControlsModule } from '../modules';
interface ButtonProps {
label?: string;
description?: string;
layout?: 'below';
onClick?(): void;
disabled?: boolean;
bottomSeparator?: boolean;
}
export const Button: FC<ButtonProps> = ControlsModule.d;
interface ToggleProps {
label?: string;
description?: string;
checked: boolean;
icon?: JSX.Element;
disabled?: boolean;
onChange?(checked: boolean): void;
}
export const Toggle: VFC<ToggleProps> = ControlsModule.jb;
interface NotchLabel {
notchIndex: number;
label: string;
value: number;
}
interface SliderProps {
label?: string;
value: number;
layout?: 'below';
icon?: JSX.Element;
min?: number;
max?: number;
step?: number;
notchCount?: number;
notchLabels?: NotchLabel[];
onChange?(value: number): void;
}
export const Slider: VFC<SliderProps> = ControlsModule.eb;

View File

@@ -1,20 +0,0 @@
import { FC, VFC } from 'react';
import { DialogModule } from '../modules';
export const Dialog: FC = DialogModule.a;
export const DialogTitle: FC = DialogModule.u;
export const DialogBody: FC = DialogModule.d;
export const DialogActions: FC = DialogModule.r;
interface DialogConfirmButtonsProps {
focusButton: 'primary';
strOKText: string;
onOK?(): void;
onCancel?(): void;
}
export const DialogConfirmButtons: VFC<DialogConfirmButtonsProps> = DialogModule.A;

View File

@@ -0,0 +1,40 @@
import { FC } from 'react';
import { findModuleChild } from '../webpack';
interface MenuProps {
label: string;
onCancel?(): void;
cancelText?: string;
}
export const Menu: FC<MenuProps> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.HideIfSubmenu && m[prop]?.prototype?.HideMenu) {
return m[prop];
}
}
});
interface MenuItemProps {
onSelected?(): void;
}
export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OnOKButton && m[prop]?.prototype?.OnMouseEnter) {
return m[prop];
}
}
});
/*
all().map(m => {
if (typeof m !== "object") return undefined;
for (let prop in m) { if (m[prop]?.prototype?.OK && m[prop]?.prototype?.Cancel && m[prop]?.prototype?.render) return m[prop]}
}).find(x => x)
*/

View File

@@ -1,17 +0,0 @@
import { FC } from 'react';
import { MenuModule } from '../modules';
interface SimpleMenuProps {
label: string;
onCancel?(): void;
cancelText?: string;
}
export const SimpleMenu: FC<SimpleMenuProps> = MenuModule.c;
interface MenuItemProps {
onSelected?(): void;
}
export const MenuItem: FC<MenuItemProps> = MenuModule.e;

View File

@@ -0,0 +1,12 @@
import { ReactNode } from 'react';
import { findModuleChild } from '../webpack';
export const showModal: (children: ReactNode, parent: EventTarget) => void = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (typeof m[prop] === 'function' && m[prop].toString().includes('stopPropagation))')) {
return m[prop];
}
}
});

View File

@@ -1,13 +0,0 @@
import { FC } from 'react';
import { PanelModule } from '../modules';
interface PanelSectionProps {
title?: string;
}
export const PanelSection: FC<PanelSectionProps> = PanelModule.a;
interface PanelSectionRowProps {}
export const PanelSectionRow: FC<PanelSectionRowProps> = PanelModule.b;

View File

@@ -0,0 +1,26 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
interface NotchLabel {
notchIndex: number;
label: string;
value: number;
}
interface SliderProps {
label?: string;
value: number;
layout?: 'below';
icon?: JSX.Element;
min?: number;
max?: number;
step?: number;
notchCount?: number;
notchLabels?: NotchLabel[];
onChange?(value: number): void;
}
export const Slider = Object.values(CommonUIModule).find((mod: any) =>
mod?.render?.toString()?.includes('SliderField,fallback'),
) as FC<SliderProps>;

View File

@@ -1,13 +0,0 @@
import { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
export const TabTitle: FC<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>> = ({
children,
className,
...props
}) => {
return (
<div className={`quickaccessmenu_Title_34nl5 ${className}`} {...props}>
{children}
</div>
);
};

View File

@@ -0,0 +1,16 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
interface ToggleProps {
label?: string;
description?: string;
checked: boolean;
icon?: JSX.Element;
disabled?: boolean;
onChange?(checked: boolean): void;
}
export const Toggle = Object.values(CommonUIModule).find((mod: any) =>
mod?.render?.toString()?.includes('ToggleField,fallback'),
) as FC<ToggleProps>;

View File

@@ -1,6 +1,5 @@
export * from './Backdrop';
export * from './Controls';
export * from './Dialogs';
export * from './Menus';
export * from './Panels';
export * from './Tabs';
export * from './Button';
export * from './Menu';
export * from './Modal';
export * from './Slider';
export * from './Toggle';

View File

@@ -1,8 +0,0 @@
import { NavigationModule } from '../modules';
interface Navigation {
NavigateToExternalWeb(url: string): void;
OpenQuickAccessMenu(key?: number): void;
}
export const Navigation: Navigation = NavigationModule.b;

View File

@@ -1 +0,0 @@
export * from './Navigation';

View File

@@ -1,3 +1,4 @@
// export * from './deck-libs';
export * from './deck-components';
export * from './deck-libs';
export * from './plugin';
export * from './webpack';

View File

@@ -1,10 +0,0 @@
import ModuleRaid from 'moduleraid';
const moduleraid = new ModuleRaid();
export const ControlsModule = moduleraid.modules['Mgs7'].exports;
export const NavigationModule = moduleraid.modules['sUK7'].exports;
export const DialogModule = moduleraid.modules['Mgs7'].exports;
export const BackdropModule = moduleraid.modules['TtDX'].exports;
export const MenuModule = moduleraid.modules['y+6m'].exports;
export const PanelModule = moduleraid.modules['jYUt'].exports;

View File

@@ -28,6 +28,9 @@ export interface ServerAPI {
type DefinePluginFn = (serverAPI: ServerAPI) => Plugin;
// TypeScript helper function
export const definePlugin = (fn: DefinePluginFn) => {
return fn;
export const definePlugin = (fn: DefinePluginFn): DefinePluginFn => {
return (...args) => {
// TODO: Maybe wrap this
return fn(...args);
};
};

59
src/webpack.ts Normal file
View File

@@ -0,0 +1,59 @@
declare global {
interface Window {
webpackJsonp: any;
}
}
// TODO
type Module = any;
type FilterFn = (module: any) => boolean;
type FindFn = (module: any) => any;
const wpRequire = window.webpackJsonp.push([
[],
{ get_require: (mod: any, _exports: any, wpRequire: any) => (mod.exports = wpRequire) },
[['get_require']],
]);
export const allModules: Module[] = Object.keys(wpRequire.c)
.map((x) => wpRequire.c[x].exports)
.filter((x) => x);
export const findModule = (filter: FilterFn) => {
for (const m of allModules) {
if (m.default && filter(m.default)) return m.default;
if (filter(m)) return m;
}
};
export const findModuleChild = (filter: FindFn) => {
for (const m of allModules) {
for (const mod of [m.default, m]) {
const filterRes = filter(mod);
if (filterRes) {
return filterRes;
} else {
continue;
}
}
}
};
export const findAllModules = (filter: FilterFn) => {
const out = [];
for (const m of allModules) {
if (m.default && filter(m.default)) out.push(m.default);
if (filter(m)) out.push(m);
}
return out;
};
export const CommonUIModule = allModules.find((m: Module) => {
if (typeof m !== 'object') return false;
for (let prop in m) {
if (m[prop]?.contextType?._currentValue && Object.keys(m).length > 60) return true;
}
return false;
});