mirror of
https://github.com/SteamDeckHomebrew/decky-frontend-lib.git
synced 2026-05-18 09:00:13 +02:00
Switch to webpack based extracting
This commit is contained in:
3
babel.config.js
Normal file
3
babel.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript',],
|
||||
};
|
||||
5
jest.config.js
Normal file
5
jest.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
};
|
||||
8475
package-lock.json
generated
8475
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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": {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { BackdropModule } from '../modules';
|
||||
|
||||
export const openBackdrop: (children: ReactNode) => void = BackdropModule.a;
|
||||
16
src/deck-components/Button.tsx
Normal file
16
src/deck-components/Button.tsx
Normal 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>;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
40
src/deck-components/Menu.tsx
Normal file
40
src/deck-components/Menu.tsx
Normal 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)
|
||||
*/
|
||||
@@ -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;
|
||||
12
src/deck-components/Modal.tsx
Normal file
12
src/deck-components/Modal.tsx
Normal 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];
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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;
|
||||
26
src/deck-components/Slider.tsx
Normal file
26
src/deck-components/Slider.tsx
Normal 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>;
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
16
src/deck-components/Toggle.tsx
Normal file
16
src/deck-components/Toggle.tsx
Normal 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>;
|
||||
@@ -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';
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { NavigationModule } from '../modules';
|
||||
|
||||
interface Navigation {
|
||||
NavigateToExternalWeb(url: string): void;
|
||||
OpenQuickAccessMenu(key?: number): void;
|
||||
}
|
||||
|
||||
export const Navigation: Navigation = NavigationModule.b;
|
||||
@@ -1 +0,0 @@
|
||||
export * from './Navigation';
|
||||
@@ -1,3 +1,4 @@
|
||||
// export * from './deck-libs';
|
||||
export * from './deck-components';
|
||||
export * from './deck-libs';
|
||||
export * from './plugin';
|
||||
export * from './webpack';
|
||||
|
||||
@@ -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;
|
||||
@@ -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
59
src/webpack.ts
Normal 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;
|
||||
});
|
||||
Reference in New Issue
Block a user