mirror of
https://github.com/SteamDeckHomebrew/decky-frontend-lib.git
synced 2026-05-21 10:29:00 +02:00
Compare commits
20 Commits
v3.15.0
...
aa/menu-ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6e399fa46 | ||
|
|
e48c7bbadd | ||
|
|
727fcc8186 | ||
|
|
dc196d53f5 | ||
|
|
f0379e5d19 | ||
|
|
fd94842647 | ||
|
|
ef6be8c6ec | ||
|
|
767dc2fcee | ||
|
|
52305987c5 | ||
|
|
6f14da152a | ||
|
|
bb291b211c | ||
|
|
88f245d476 | ||
|
|
5bc78df918 | ||
|
|
c586afb97d | ||
|
|
d9150c2556 | ||
|
|
cd0635e94f | ||
|
|
443c7850d7 | ||
|
|
d24136ecb6 | ||
|
|
55507446cc | ||
|
|
925ea8c3ce |
63
CHANGELOG.md
63
CHANGELOG.md
@@ -1,3 +1,66 @@
|
|||||||
|
## [3.18.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.3...v3.18.4) (2022-12-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **modals:** fix ModalRoot again ([fd94842](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fd94842647e51dd9a104e170e0c5ee2bebce12d6))
|
||||||
|
|
||||||
|
## [3.18.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.2...v3.18.3) (2022-12-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Router:** update Router interface to SteamOS3.4 and add Navigation ([#52](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/52)) ([f0379e5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/f0379e5d19279863b571e66918bc9107efedb612))
|
||||||
|
|
||||||
|
## [3.18.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.1...v3.18.2) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **useQuickAccessVisible:** remove invalid prop access ([#66](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/66)) ([767dc2f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/767dc2fcee97d8b6c2d331ae29704d9b469de51a))
|
||||||
|
|
||||||
|
## [3.18.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.0...v3.18.1) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **findSP:** fallback to last active context ([#53](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/53)) ([6f14da1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/6f14da152acc4757b814844f1b77bf83dd98d77e))
|
||||||
|
|
||||||
|
# [3.18.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.17.0...v3.18.0) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **DialogCheckbox:** Add DialogCheckbox component ([#58](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/58)) ([88f245d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/88f245d476a6477e9fc0cd35e9b675961ecbc26c))
|
||||||
|
|
||||||
|
# [3.17.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.2...v3.17.0) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **ControlsList:** Add ControlsList component ([#61](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/61)) ([c586afb](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c586afb97d59928ecb703b5a254ed1b9405e2c7e))
|
||||||
|
|
||||||
|
## [3.16.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.1...v3.16.2) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Marquee:** replace default export with named export ([cd0635e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cd0635e94f98499f9f5fc24a7fd4b93efe7dfc38))
|
||||||
|
|
||||||
|
## [3.16.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.0...v3.16.1) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **FooterLegend:** change description types to ReactNode ([#62](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/62)) ([d24136e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d24136ecb6b0c5239b68723e8f92a4822aa7b590))
|
||||||
|
|
||||||
|
# [3.16.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.15.0...v3.16.0) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Marquee:** Add Marquee component ([#63](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/63)) ([925ea8c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/925ea8c3ceaaf6ff2f79b8808908a9b144a4fcff))
|
||||||
|
|
||||||
# [3.15.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.14.0...v3.15.0) (2022-12-11)
|
# [3.15.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.14.0...v3.15.0) (2022-12-11)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "decky-frontend-lib",
|
"name": "decky-frontend-lib",
|
||||||
"version": "3.15.0",
|
"version": "3.18.4",
|
||||||
"description": "A library for building decky plugins",
|
"description": "A library for building decky plugins",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ declare global {
|
|||||||
|
|
||||||
function getQuickAccessWindow(): Window | null {
|
function getQuickAccessWindow(): Window | null {
|
||||||
try {
|
try {
|
||||||
const navTrees = FocusNavController?.m_ActiveContext?.m_rgGamepadNavigationTrees || FocusNavController?.m_rgGamepadNavigationTrees;
|
const context = FocusNavController?.m_ActiveContext || FocusNavController?.m_LastActiveContext;
|
||||||
|
const navTrees = context?.m_rgGamepadNavigationTrees || FocusNavController?.m_rgGamepadNavigationTrees;
|
||||||
return navTrees?.find((tree: any) => tree?.id === "QuickAccess-NA")?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
|
return navTrees?.find((tree: any) => tree?.id === "QuickAccess-NA")?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
17
src/deck-components/ControlsList.tsx
Normal file
17
src/deck-components/ControlsList.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { findModuleChild } from '../webpack';
|
||||||
|
import { FC } from 'react';
|
||||||
|
|
||||||
|
export interface ControlsListProps {
|
||||||
|
alignItems?: 'left' | 'right' | 'center';
|
||||||
|
spacing?: 'standard' | 'extra';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ControlsList: FC<ControlsListProps> = findModuleChild((m) => {
|
||||||
|
if (typeof m !== 'object') return;
|
||||||
|
for (const prop in m) {
|
||||||
|
if (m[prop]?.toString && m[prop].toString().includes('().ControlsListChild') && m[prop].toString().includes('().ControlsListOuterPanel')) {
|
||||||
|
return m[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
});
|
||||||
33
src/deck-components/DialogCheckbox.tsx
Normal file
33
src/deck-components/DialogCheckbox.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { FC, ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { findModule } from '../webpack';
|
||||||
|
import { DialogCommonProps } from './Dialog';
|
||||||
|
import { FooterLegendProps } from './FooterLegend';
|
||||||
|
|
||||||
|
export interface DialogCheckboxProps extends DialogCommonProps, FooterLegendProps {
|
||||||
|
onChange?(checked: boolean): void;
|
||||||
|
label?: ReactNode;
|
||||||
|
description?: ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
|
tooltip?: string;
|
||||||
|
color?: string;
|
||||||
|
highlightColor?: string;
|
||||||
|
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||||
|
controlled?: boolean;
|
||||||
|
checked?: boolean;
|
||||||
|
onClick?(evt: Event): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DialogCheckbox = Object.values(findModule((m: any) => {
|
||||||
|
if (typeof m !== 'object') return false;
|
||||||
|
for (const prop in m) {
|
||||||
|
if (m[prop]?.prototype?.GetPanelElementProps) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})).find((m: any) =>
|
||||||
|
m.contextType &&
|
||||||
|
m.prototype?.render.toString().includes('fallback:') &&
|
||||||
|
m?.prototype?.SetChecked &&
|
||||||
|
m?.prototype?.Toggle &&
|
||||||
|
m?.prototype?.GetPanelElementProps
|
||||||
|
) as FC<DialogCheckboxProps>;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
export enum GamepadButton {
|
export enum GamepadButton {
|
||||||
INVALID,
|
INVALID,
|
||||||
OK,
|
OK,
|
||||||
@@ -42,16 +44,16 @@ export interface GamepadEventDetail {
|
|||||||
source: number;
|
source: number;
|
||||||
}
|
}
|
||||||
export declare type ActionDescriptionMap = {
|
export declare type ActionDescriptionMap = {
|
||||||
[key in GamepadButton]?: string
|
[key in GamepadButton]?: ReactNode
|
||||||
}
|
}
|
||||||
export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
|
export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
|
||||||
export interface FooterLegendProps {
|
export interface FooterLegendProps {
|
||||||
actionDescriptionMap?: ActionDescriptionMap;
|
actionDescriptionMap?: ActionDescriptionMap;
|
||||||
onOKActionDescription?: string;
|
onOKActionDescription?: ReactNode;
|
||||||
onCancelActionDescription?: string;
|
onCancelActionDescription?: ReactNode;
|
||||||
onSecondaryActionDescription?: string;
|
onSecondaryActionDescription?: ReactNode;
|
||||||
onOptionsActionDescription?: string;
|
onOptionsActionDescription?: ReactNode;
|
||||||
onMenuActionDescription?: string;
|
onMenuActionDescription?: ReactNode;
|
||||||
onButtonDown?: (evt: GamepadEvent) => void;
|
onButtonDown?: (evt: GamepadEvent) => void;
|
||||||
onButtonUp?: (evt: GamepadEvent) => void;
|
onButtonUp?: (evt: GamepadEvent) => void;
|
||||||
onOKButton?: (evt: GamepadEvent) => void;
|
onOKButton?: (evt: GamepadEvent) => void;
|
||||||
|
|||||||
26
src/deck-components/Marquee.tsx
Normal file
26
src/deck-components/Marquee.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { CSSProperties, FC, ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { findModuleChild } from '../webpack';
|
||||||
|
|
||||||
|
export interface MarqueeProps {
|
||||||
|
play?: boolean;
|
||||||
|
direction?: 'left' | 'right';
|
||||||
|
speed?: number;
|
||||||
|
delay?: number;
|
||||||
|
fadeLength?: number;
|
||||||
|
center?: boolean;
|
||||||
|
resetOnPause?: boolean;
|
||||||
|
style?: CSSProperties;
|
||||||
|
className?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Marquee: FC<MarqueeProps> = findModuleChild((m) => {
|
||||||
|
if (typeof m !== 'object') return;
|
||||||
|
for (const prop in m) {
|
||||||
|
if (m[prop]?.toString && m[prop].toString().includes('.Marquee') && m[prop].toString().includes('--fade-length')) {
|
||||||
|
return m[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
});
|
||||||
@@ -38,7 +38,7 @@ const showModalRaw:
|
|||||||
unknown1?: unknown,
|
unknown1?: unknown,
|
||||||
hideActions?: { bHideActions?: boolean },
|
hideActions?: { bHideActions?: boolean },
|
||||||
modalManager?: unknown,
|
modalManager?: unknown,
|
||||||
) => Promise<ShowModalResult>)
|
) => ShowModalResult)
|
||||||
| void = findModuleChild((m) => {
|
| void = findModuleChild((m) => {
|
||||||
if (typeof m !== 'object') return undefined;
|
if (typeof m !== 'object') return undefined;
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
@@ -52,16 +52,15 @@ const showModalRaw:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const oldShowModalRaw:
|
const oldShowModalRaw: ((modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => ShowModalResult) | void =
|
||||||
| ((modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => Promise<ShowModalResult>)
|
findModuleChild((m) => {
|
||||||
| void = findModuleChild((m) => {
|
if (typeof m !== 'object') return undefined;
|
||||||
if (typeof m !== 'object') return undefined;
|
for (let prop in m) {
|
||||||
for (let prop in m) {
|
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
|
||||||
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
|
return m[prop];
|
||||||
return m[prop];
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
export const showModal = (
|
export const showModal = (
|
||||||
modal: ReactNode,
|
modal: ReactNode,
|
||||||
@@ -70,7 +69,7 @@ export const showModal = (
|
|||||||
strTitle: 'Decky Dialog',
|
strTitle: 'Decky Dialog',
|
||||||
bHideMainWindowForPopouts: false,
|
bHideMainWindowForPopouts: false,
|
||||||
},
|
},
|
||||||
): Promise<ShowModalResult> => {
|
): ShowModalResult => {
|
||||||
if (showModalRaw) {
|
if (showModalRaw) {
|
||||||
return showModalRaw(modal, parent || findSP(), props.strTitle, props, undefined, {
|
return showModalRaw(modal, parent || findSP(), props.strTitle, props, undefined, {
|
||||||
bHideActions: props.bHideActionIcons,
|
bHideActions: props.bHideActionIcons,
|
||||||
@@ -118,13 +117,13 @@ export const ConfirmModal = findModuleChild((m) => {
|
|||||||
}
|
}
|
||||||
}) as FC<ConfirmModalProps>;
|
}) as FC<ConfirmModalProps>;
|
||||||
|
|
||||||
// new
|
// new as of december 2022 on beta
|
||||||
export const ModalRoot = (Object.values(
|
export const ModalRoot = (Object.values(
|
||||||
findModule((m: any) => {
|
findModule((m: any) => {
|
||||||
if (typeof m !== 'object') return false;
|
if (typeof m !== 'object') return false;
|
||||||
|
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
if (m[prop]?.toString()?.includes('"ModalManager","DialogWrapper"')) {
|
if (m[prop]?.m_mapModalManager) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,6 +131,20 @@ export const ModalRoot = (Object.values(
|
|||||||
return false;
|
return false;
|
||||||
}) || {},
|
}) || {},
|
||||||
)?.find((x: any) => x?.type?.toString()?.includes('((function(){')) ||
|
)?.find((x: any) => x?.type?.toString()?.includes('((function(){')) ||
|
||||||
|
// before december 2022 beta
|
||||||
|
Object.values(
|
||||||
|
findModule((m: any) => {
|
||||||
|
if (typeof m !== 'object') return false;
|
||||||
|
|
||||||
|
for (let prop in m) {
|
||||||
|
if (m[prop]?.toString()?.includes('"ModalManager","DialogWrapper"')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}) || {},
|
||||||
|
)?.find((x: any) => x?.type?.toString()?.includes('((function(){')) ||
|
||||||
// old
|
// old
|
||||||
findModuleChild((m) => {
|
findModuleChild((m) => {
|
||||||
if (typeof m !== 'object') return undefined;
|
if (typeof m !== 'object') return undefined;
|
||||||
|
|||||||
@@ -63,28 +63,38 @@ export type AppOverview = {
|
|||||||
sort_as: string;
|
sort_as: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Router {
|
export interface MenuStore {
|
||||||
CloseSideMenus(): void;
|
|
||||||
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
|
||||||
GetQuickAccessTab(): QuickAccessTab;
|
|
||||||
Navigate(path: string): void;
|
|
||||||
NavigateBackOrOpenMenu(): void;
|
|
||||||
NavigateToAppProperties(): void;
|
|
||||||
NavigateToBugForum(): void;
|
|
||||||
NavigateToExternalWeb(url: string): void;
|
|
||||||
NavigateToHelp(): void;
|
|
||||||
NavigateToInvites(): void;
|
|
||||||
NavigateToRunningApp(replace?: boolean): void;
|
|
||||||
NavigateToStorage(): void;
|
|
||||||
NavigateToStore(): void;
|
|
||||||
NavigateToStoreApp(appId: number | string): void;
|
|
||||||
NavigateToStoreFreeToPlay(): void;
|
|
||||||
NavigateToStoreManual(): void;
|
|
||||||
NavigateToStoreNewReleases(): void;
|
|
||||||
NavigateToStoreOnSale(): void;
|
|
||||||
ToggleSideMenu(sideMenu: SideMenu): void;
|
|
||||||
CloseSideMenus(): void;
|
|
||||||
OpenSideMenu(sideMenu: SideMenu): void;
|
OpenSideMenu(sideMenu: SideMenu): void;
|
||||||
|
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
||||||
|
OpenMainMenu(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WindowRouter {
|
||||||
|
BrowserWindow: Window;
|
||||||
|
MenuStore: MenuStore;
|
||||||
|
Navigate(path: string): void;
|
||||||
|
NavigateToChat(): void;
|
||||||
|
NavigateToSteamWeb(url: string): void;
|
||||||
|
NavigateBack(): void;
|
||||||
|
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WindowStore {
|
||||||
|
GamepadUIMainWindowInstance?: WindowRouter; // Current
|
||||||
|
SteamUIWindows: WindowRouter[];
|
||||||
|
OverlayWindows: WindowRouter[]; // Used by desktop GamepadUI
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Router {
|
||||||
|
WindowStore?: WindowStore;
|
||||||
|
CloseSideMenus(): void;
|
||||||
|
Navigate(path: string): void;
|
||||||
|
NavigateToAppProperties(): void;
|
||||||
|
NavigateToExternalWeb(url: string): void;
|
||||||
|
NavigateToInvites(): void;
|
||||||
|
NavigateToChat(): void;
|
||||||
|
NavigateToLibraryTab(): void;
|
||||||
|
NavigateToLayoutPreview(e: unknown): void;
|
||||||
OpenPowerMenu(unknown?: any): void;
|
OpenPowerMenu(unknown?: any): void;
|
||||||
get RunningApps(): AppOverview[];
|
get RunningApps(): AppOverview[];
|
||||||
get MainRunningApp(): AppOverview | undefined;
|
get MainRunningApp(): AppOverview | undefined;
|
||||||
@@ -96,3 +106,51 @@ export const Router = findModuleChild((m: Module) => {
|
|||||||
if (m[prop]?.Navigate && m[prop]?.NavigationManager) return m[prop];
|
if (m[prop]?.Navigate && m[prop]?.NavigationManager) return m[prop];
|
||||||
}
|
}
|
||||||
}) as Router;
|
}) as Router;
|
||||||
|
|
||||||
|
export interface Navigation {
|
||||||
|
Navigate(path: string): void;
|
||||||
|
NavigateBack(): void;
|
||||||
|
NavigateToAppProperties(): void;
|
||||||
|
NavigateToExternalWeb(url: string): void;
|
||||||
|
NavigateToInvites(): void;
|
||||||
|
NavigateToChat(): void;
|
||||||
|
NavigateToLibraryTab(): void;
|
||||||
|
NavigateToLayoutPreview(e: unknown): void;
|
||||||
|
NavigateToSteamWeb(url: string): void;
|
||||||
|
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||||
|
OpenSideMenu(sideMenu: SideMenu): void;
|
||||||
|
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
||||||
|
OpenMainMenu(): void;
|
||||||
|
OpenPowerMenu(unknown?: any): void;
|
||||||
|
CloseSideMenus(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Navigation = {
|
||||||
|
Navigate: Router.Navigate.bind(Router),
|
||||||
|
NavigateBack: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateBack.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
|
),
|
||||||
|
NavigateToAppProperties: Router.NavigateToAppProperties.bind(Router),
|
||||||
|
NavigateToExternalWeb: Router.NavigateToExternalWeb.bind(Router),
|
||||||
|
NavigateToInvites: Router.NavigateToInvites.bind(Router),
|
||||||
|
NavigateToChat: Router.NavigateToChat.bind(Router),
|
||||||
|
NavigateToLibraryTab: Router.NavigateToLibraryTab.bind(Router),
|
||||||
|
NavigateToLayoutPreview: Router.NavigateToLayoutPreview.bind(Router),
|
||||||
|
NavigateToSteamWeb: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToSteamWeb.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
|
),
|
||||||
|
NavigateToWebRoute: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToWebRoute.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
|
),
|
||||||
|
OpenSideMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenSideMenu.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
|
),
|
||||||
|
OpenQuickAccessMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenQuickAccessMenu.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
|
),
|
||||||
|
OpenMainMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenMainMenu.bind(
|
||||||
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
|
),
|
||||||
|
CloseSideMenus: Router.CloseSideMenus.bind(Router),
|
||||||
|
OpenPowerMenu: Router.OpenPowerMenu.bind(Router),
|
||||||
|
} as Navigation;
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
export * from './Button';
|
export * from './Button';
|
||||||
export * from './ButtonItem';
|
export * from './ButtonItem';
|
||||||
export * from './Carousel';
|
export * from './Carousel';
|
||||||
|
export * from './ControlsList';
|
||||||
export * from './Dialog';
|
export * from './Dialog';
|
||||||
|
export * from './DialogCheckbox';
|
||||||
export * from './Dropdown';
|
export * from './Dropdown';
|
||||||
export * from './Field';
|
export * from './Field';
|
||||||
export * from './Focusable';
|
export * from './Focusable';
|
||||||
export * from './FocusRing';
|
export * from './FocusRing';
|
||||||
export * from './FooterLegend';
|
export * from './FooterLegend';
|
||||||
|
export * from './Marquee';
|
||||||
export * from './Menu';
|
export * from './Menu';
|
||||||
export * from './Modal';
|
export * from './Modal';
|
||||||
export * from './Panel';
|
export * from './Panel';
|
||||||
|
|||||||
@@ -21,6 +21,52 @@ interface ServerResponseError {
|
|||||||
|
|
||||||
export type ServerResponse<TRes> = ServerResponseSuccess<TRes> | ServerResponseError;
|
export type ServerResponse<TRes> = ServerResponseSuccess<TRes> | ServerResponseError;
|
||||||
|
|
||||||
|
export interface MainMenuItem {
|
||||||
|
/** Called when clicking this menu item, useful if you do not want to navigate to a route.
|
||||||
|
* For navigating to a route, use route instead. */
|
||||||
|
action?: () => void;
|
||||||
|
/** The route this menu item navigates to @example "/steamweb" */
|
||||||
|
route?: string;
|
||||||
|
/** Props for the route this item navigates to. Currently only used for /steamweb to determine what webpack to navigate to @example {url: 'https://store.steampowered.com/'} */
|
||||||
|
routeState?: any;
|
||||||
|
/** Label for this menu item, @example "Store" */
|
||||||
|
label: ReactNode;
|
||||||
|
/** Runs when this item is selected. Defaults to setting the focused app to null.
|
||||||
|
* If you override this you must also call the original to retain proper behaivour */
|
||||||
|
onFocus?: () => void;
|
||||||
|
/** Icon of this menu item, you probably want a react SVG node */
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomMainMenuItem extends MainMenuItem {
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MainMenuItemReactNode {
|
||||||
|
props: MainMenuItem;
|
||||||
|
type: ComponentType;
|
||||||
|
key: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OverlayReactNode {
|
||||||
|
props: MainMenuItem;
|
||||||
|
type: ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ItemPatch = (item: MainMenuItemReactNode) => MainMenuItemReactNode;
|
||||||
|
export type OverlayPatch = (overlay: OverlayReactNode) => OverlayReactNode;
|
||||||
|
|
||||||
|
export interface MenuHook {
|
||||||
|
addItem(item: CustomMainMenuItem): CustomMainMenuItem;
|
||||||
|
addPatch(path: string, patch: ItemPatch): ItemPatch;
|
||||||
|
addOverlayPatch(patch: OverlayPatch): OverlayPatch;
|
||||||
|
addOverlayComponent(component: ReactNode): ReactNode;
|
||||||
|
removePatch(path: string, patch: ItemPatch): void;
|
||||||
|
removeOverlayPatch(patch: OverlayPatch): void;
|
||||||
|
removeOverlayComponent(component: ReactNode): void;
|
||||||
|
removeItem(item: CustomMainMenuItem): void;
|
||||||
|
}
|
||||||
|
|
||||||
export type RoutePatch = (route: RouteProps) => RouteProps;
|
export type RoutePatch = (route: RouteProps) => RouteProps;
|
||||||
|
|
||||||
export interface RouterHook {
|
export interface RouterHook {
|
||||||
@@ -59,6 +105,7 @@ export interface FilePickerRes {
|
|||||||
|
|
||||||
export interface ServerAPI {
|
export interface ServerAPI {
|
||||||
routerHook: RouterHook;
|
routerHook: RouterHook;
|
||||||
|
menuHook: MenuHook;
|
||||||
toaster: Toaster;
|
toaster: Toaster;
|
||||||
openFilePicker(startPath: string, includeFiles?: boolean, regex?: RegExp): Promise<FilePickerRes>;
|
openFilePicker(startPath: string, includeFiles?: boolean, regex?: RegExp): Promise<FilePickerRes>;
|
||||||
callPluginMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
callPluginMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export function findSP(): Window {
|
|||||||
// old (SP as host)
|
// old (SP as host)
|
||||||
if (document.title == 'SP') return window;
|
if (document.title == 'SP') return window;
|
||||||
// new (SP as popup)
|
// new (SP as popup)
|
||||||
return FocusNavController.m_ActiveContext.m_rgGamepadNavigationTrees.find((x: any) => x.m_ID == 'root_1_').Root
|
const context = FocusNavController.m_ActiveContext || FocusNavController.m_LastActiveContext;
|
||||||
|
return context.m_rgGamepadNavigationTrees.find((x: any) => x.m_ID == 'root_1_').Root
|
||||||
.Element.ownerDocument.defaultView;
|
.Element.ownerDocument.defaultView;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user