@decky/ui 4.4.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,10 @@
1
+ import { ModuleID } from './webpack';
1
2
  export interface ClassModule {
2
3
  [name: string]: string;
3
4
  }
5
+ export declare const classModuleMap: Map<ModuleID, ClassModule>;
4
6
  export declare const classMap: ClassModule[];
5
- export declare function findClass(name: string): string | void;
7
+ export declare function findClass(id: string, name: string): string | void;
8
+ export declare function findClassByName(name: string): string | void;
6
9
  export declare function findClassModule(filter: (module: any) => boolean): ClassModule | void;
7
10
  export declare function unminifyClass(minifiedClass: string): string | void;
@@ -1,5 +1,5 @@
1
- import { findAllModules } from './webpack';
2
- export const classMap = findAllModules((m) => {
1
+ import { createModuleMapping } from './webpack';
2
+ export const classModuleMap = createModuleMapping((m) => {
3
3
  if (typeof m == 'object' && !m.__esModule) {
4
4
  const keys = Object.keys(m);
5
5
  if (keys.length == 1 && m.version)
@@ -10,14 +10,18 @@ export const classMap = findAllModules((m) => {
10
10
  }
11
11
  return false;
12
12
  });
13
- export function findClass(name) {
14
- return classMap.find((m) => m?.[name])?.[name];
13
+ export const classMap = [...classModuleMap.values()];
14
+ export function findClass(id, name) {
15
+ return classModuleMap.get(id)?.[name];
16
+ }
17
+ export function findClassByName(name) {
18
+ return classMap.find((m) => m[name])?.[name];
15
19
  }
16
20
  export function findClassModule(filter) {
17
21
  return classMap.find((m) => filter(m));
18
22
  }
19
23
  export function unminifyClass(minifiedClass) {
20
- for (let m of classMap) {
24
+ for (let m of classModuleMap.values()) {
21
25
  for (let className of Object.keys(m)) {
22
26
  if (m[className] == minifiedClass)
23
27
  return className;
package/dist/webpack.d.ts CHANGED
@@ -3,18 +3,20 @@ declare global {
3
3
  webpackChunksteamui: any;
4
4
  }
5
5
  }
6
+ export type ModuleID = string;
6
7
  export type Module = any;
7
8
  export type Export = any;
8
9
  type FilterFn = (module: any) => boolean;
9
10
  type ExportFilterFn = (moduleExport: any, exportName?: any) => boolean;
10
11
  type FindFn = (module: any) => any;
11
- export declare let modules: any;
12
+ export declare let modules: Map<string, any>;
12
13
  export declare const findModule: (filter: FilterFn) => any;
13
- export declare const findModuleDetailsByExport: (filter: ExportFilterFn, minExports?: number) => [module: Module | undefined, moduleExport: any, exportName: any];
14
+ export declare const findModuleDetailsByExport: (filter: ExportFilterFn, minExports?: number) => [module: Module | undefined, moduleExport: any, exportName: any, moduleID: string | undefined];
14
15
  export declare const findModuleByExport: (filter: ExportFilterFn, minExports?: number) => any;
15
16
  export declare const findModuleExport: (filter: ExportFilterFn, minExports?: number) => any;
16
17
  export declare const findModuleChild: (filter: FindFn) => any;
17
18
  export declare const findAllModules: (filter: FilterFn) => any[];
19
+ export declare const createModuleMapping: (filter: FilterFn) => Map<string, any>;
18
20
  export declare const CommonUIModule: any;
19
21
  export declare const IconsModule: any;
20
22
  export declare const ReactRouter: any;
package/dist/webpack.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import Logger from './logger';
2
2
  const logger = new Logger('Webpack');
3
- export let modules = [];
3
+ export let modules = new Map();
4
4
  function initModuleCache() {
5
5
  const startTime = performance.now();
6
6
  logger.group('Webpack Module Init');
7
- const id = Math.random();
7
+ const id = Symbol("@decky/ui");
8
8
  let webpackRequire;
9
9
  window.webpackChunksteamui.push([
10
10
  [id],
@@ -14,22 +14,22 @@ function initModuleCache() {
14
14
  },
15
15
  ]);
16
16
  logger.log('Initializing all modules. Errors here likely do not matter, as they are usually just failing module side effects.');
17
- for (let i of Object.keys(webpackRequire.m)) {
17
+ for (let id of Object.keys(webpackRequire.m)) {
18
18
  try {
19
- const module = webpackRequire(i);
19
+ const module = webpackRequire(id);
20
20
  if (module) {
21
- modules.push(module);
21
+ modules.set(id, module);
22
22
  }
23
23
  }
24
24
  catch (e) {
25
- logger.debug('Ignoring require error for module', i, e);
25
+ logger.debug('Ignoring require error for module', id, e);
26
26
  }
27
27
  }
28
28
  logger.groupEnd(`Modules initialized in ${performance.now() - startTime}ms...`);
29
29
  }
30
30
  initModuleCache();
31
31
  export const findModule = (filter) => {
32
- for (const m of modules) {
32
+ for (const m of modules.values()) {
33
33
  if (m.default && filter(m.default))
34
34
  return m.default;
35
35
  if (filter(m))
@@ -37,7 +37,7 @@ export const findModule = (filter) => {
37
37
  }
38
38
  };
39
39
  export const findModuleDetailsByExport = (filter, minExports) => {
40
- for (const m of modules) {
40
+ for (const [id, m] of modules) {
41
41
  if (!m)
42
42
  continue;
43
43
  for (const mod of [m.default, m]) {
@@ -49,7 +49,7 @@ export const findModuleDetailsByExport = (filter, minExports) => {
49
49
  if (mod?.[exportName]) {
50
50
  const filterRes = filter(mod[exportName], exportName);
51
51
  if (filterRes) {
52
- return [mod, mod[exportName], exportName];
52
+ return [mod, mod[exportName], exportName, id];
53
53
  }
54
54
  else {
55
55
  continue;
@@ -58,7 +58,7 @@ export const findModuleDetailsByExport = (filter, minExports) => {
58
58
  }
59
59
  }
60
60
  }
61
- return [undefined, undefined, undefined];
61
+ return [undefined, undefined, undefined, undefined];
62
62
  };
63
63
  export const findModuleByExport = (filter, minExports) => {
64
64
  return findModuleDetailsByExport(filter, minExports)?.[0];
@@ -67,7 +67,7 @@ export const findModuleExport = (filter, minExports) => {
67
67
  return findModuleDetailsByExport(filter, minExports)?.[1];
68
68
  };
69
69
  export const findModuleChild = (filter) => {
70
- for (const m of modules) {
70
+ for (const m of modules.values()) {
71
71
  for (const mod of [m.default, m]) {
72
72
  const filterRes = filter(mod);
73
73
  if (filterRes) {
@@ -81,7 +81,7 @@ export const findModuleChild = (filter) => {
81
81
  };
82
82
  export const findAllModules = (filter) => {
83
83
  const out = [];
84
- for (const m of modules) {
84
+ for (const m of modules.values()) {
85
85
  if (m.default && filter(m.default))
86
86
  out.push(m.default);
87
87
  if (filter(m))
@@ -89,7 +89,17 @@ export const findAllModules = (filter) => {
89
89
  }
90
90
  return out;
91
91
  };
92
- export const CommonUIModule = modules.find((m) => {
92
+ export const createModuleMapping = (filter) => {
93
+ const mapping = new Map();
94
+ for (const [id, m] of modules) {
95
+ if (m.default && filter(m.default))
96
+ mapping.set(id, m.default);
97
+ if (filter(m))
98
+ mapping.set(id, m);
99
+ }
100
+ return mapping;
101
+ };
102
+ export const CommonUIModule = findModule((m) => {
93
103
  if (typeof m !== 'object')
94
104
  return false;
95
105
  for (let prop in m) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decky/ui",
3
- "version": "4.4.0",
3
+ "version": "4.6.0",
4
4
  "description": "A library for interacting with the Steam frontend in Decky plugins and elsewhere.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,10 +1,10 @@
1
- import { Module, findAllModules } from './webpack';
1
+ import { Module, ModuleID, createModuleMapping } from './webpack';
2
2
 
3
3
  export interface ClassModule {
4
4
  [name: string]: string;
5
5
  }
6
6
 
7
- export const classMap: ClassModule[] = findAllModules((m: Module) => {
7
+ export const classModuleMap: Map<ModuleID, ClassModule> = createModuleMapping((m: Module) => {
8
8
  if (typeof m == 'object' && !m.__esModule) {
9
9
  const keys = Object.keys(m);
10
10
  // special case some libraries
@@ -17,8 +17,14 @@ export const classMap: ClassModule[] = findAllModules((m: Module) => {
17
17
  return false;
18
18
  });
19
19
 
20
- export function findClass(name: string): string | void {
21
- return classMap.find((m) => m?.[name])?.[name];
20
+ export const classMap = [...classModuleMap.values()];
21
+
22
+ export function findClass(id: string, name: string): string | void {
23
+ return classModuleMap.get(id)?.[name];
24
+ }
25
+
26
+ export function findClassByName(name: string): string | void {
27
+ return classMap.find((m) => m[name])?.[name];
22
28
  }
23
29
 
24
30
  export function findClassModule(filter: (module: any) => boolean): ClassModule | void {
@@ -26,7 +32,7 @@ export function findClassModule(filter: (module: any) => boolean): ClassModule |
26
32
  }
27
33
 
28
34
  export function unminifyClass(minifiedClass: string): string | void {
29
- for (let m of classMap) {
35
+ for (let m of classModuleMap.values()) {
30
36
  for (let className of Object.keys(m)) {
31
37
  if (m[className] == minifiedClass) return className;
32
38
  }
@@ -11,12 +11,14 @@ function getQuickAccessWindow(): Window | null {
11
11
 
12
12
  /**
13
13
  * Returns state indicating the visibility of quick access menu.
14
+ *
15
+ * @deprecated moved to @decky/api
14
16
  *
15
17
  * @returns `true` if quick access menu is visible and `false` otherwise.
16
18
  *
17
19
  * @example
18
20
  * import { FC, useEffect } from "react";
19
- * import { useQuickAccessVisible } from "decky-frontend-lib";
21
+ * import { useQuickAccessVisible } from "@decky/ui";
20
22
  *
21
23
  * export const PluginPanelView: FC<{}> = ({ }) => {
22
24
  * const isVisible = useQuickAccessVisible();
package/src/webpack.ts CHANGED
@@ -9,20 +9,21 @@ declare global {
9
9
  const logger = new Logger('Webpack');
10
10
 
11
11
  // In most case an object with getters for each property. Look for the first call to r.d in the module, usually near or at the top.
12
+ export type ModuleID = string; // number string
12
13
  export type Module = any;
13
14
  export type Export = any;
14
15
  type FilterFn = (module: any) => boolean;
15
16
  type ExportFilterFn = (moduleExport: any, exportName?: any) => boolean;
16
17
  type FindFn = (module: any) => any;
17
18
 
18
- export let modules: any = [];
19
+ export let modules = new Map<ModuleID, Module>();
19
20
 
20
21
  function initModuleCache() {
21
22
  const startTime = performance.now();
22
23
  logger.group('Webpack Module Init');
23
24
  // Webpack 5, currently on beta
24
25
  // Generate a fake module ID
25
- const id = Math.random(); // really should be an int and not a float but who cares
26
+ const id = Symbol("@decky/ui");
26
27
  let webpackRequire!: ((id: any) => Module) & { m: object };
27
28
  // Insert our module in a new chunk.
28
29
  // The module will then be called with webpack's internal require function as its first argument
@@ -39,14 +40,14 @@ function initModuleCache() {
39
40
  );
40
41
 
41
42
  // Loop over every module ID
42
- for (let i of Object.keys(webpackRequire.m)) {
43
+ for (let id of Object.keys(webpackRequire.m)) {
43
44
  try {
44
- const module = webpackRequire(i);
45
+ const module = webpackRequire(id);
45
46
  if (module) {
46
- modules.push(module);
47
+ modules.set(id, module);
47
48
  }
48
49
  } catch (e) {
49
- logger.debug('Ignoring require error for module', i, e);
50
+ logger.debug('Ignoring require error for module', id, e);
50
51
  }
51
52
  }
52
53
 
@@ -56,7 +57,7 @@ function initModuleCache() {
56
57
  initModuleCache();
57
58
 
58
59
  export const findModule = (filter: FilterFn) => {
59
- for (const m of modules) {
60
+ for (const m of modules.values()) {
60
61
  if (m.default && filter(m.default)) return m.default;
61
62
  if (filter(m)) return m;
62
63
  }
@@ -65,8 +66,8 @@ export const findModule = (filter: FilterFn) => {
65
66
  export const findModuleDetailsByExport = (
66
67
  filter: ExportFilterFn,
67
68
  minExports?: number,
68
- ): [module: Module | undefined, moduleExport: any, exportName: any] => {
69
- for (const m of modules) {
69
+ ): [module: Module | undefined, moduleExport: any, exportName: any, moduleID: string | undefined] => {
70
+ for (const [id, m] of modules) {
70
71
  if (!m) continue;
71
72
  for (const mod of [m.default, m]) {
72
73
  if (typeof mod !== 'object') continue;
@@ -75,7 +76,7 @@ export const findModuleDetailsByExport = (
75
76
  if (mod?.[exportName]) {
76
77
  const filterRes = filter(mod[exportName], exportName);
77
78
  if (filterRes) {
78
- return [mod, mod[exportName], exportName];
79
+ return [mod, mod[exportName], exportName, id];
79
80
  } else {
80
81
  continue;
81
82
  }
@@ -83,7 +84,7 @@ export const findModuleDetailsByExport = (
83
84
  }
84
85
  }
85
86
  }
86
- return [undefined, undefined, undefined];
87
+ return [undefined, undefined, undefined, undefined];
87
88
  };
88
89
 
89
90
  export const findModuleByExport = (filter: ExportFilterFn, minExports?: number) => {
@@ -98,7 +99,7 @@ export const findModuleExport = (filter: ExportFilterFn, minExports?: number) =>
98
99
  * @deprecated use findModuleExport instead
99
100
  */
100
101
  export const findModuleChild = (filter: FindFn) => {
101
- for (const m of modules) {
102
+ for (const m of modules.values()) {
102
103
  for (const mod of [m.default, m]) {
103
104
  const filterRes = filter(mod);
104
105
  if (filterRes) {
@@ -110,10 +111,13 @@ export const findModuleChild = (filter: FindFn) => {
110
111
  }
111
112
  };
112
113
 
114
+ /**
115
+ * @deprecated use createModuleMapping instead
116
+ */
113
117
  export const findAllModules = (filter: FilterFn) => {
114
118
  const out = [];
115
119
 
116
- for (const m of modules) {
120
+ for (const m of modules.values()) {
117
121
  if (m.default && filter(m.default)) out.push(m.default);
118
122
  if (filter(m)) out.push(m);
119
123
  }
@@ -121,7 +125,18 @@ export const findAllModules = (filter: FilterFn) => {
121
125
  return out;
122
126
  };
123
127
 
124
- export const CommonUIModule = modules.find((m: Module) => {
128
+ export const createModuleMapping = (filter: FilterFn) => {
129
+ const mapping = new Map<ModuleID, Module>();
130
+
131
+ for (const [id, m] of modules) {
132
+ if (m.default && filter(m.default)) mapping.set(id, m.default);
133
+ if (filter(m)) mapping.set(id, m);
134
+ }
135
+
136
+ return mapping;
137
+ };
138
+
139
+ export const CommonUIModule = findModule((m: Module) => {
125
140
  if (typeof m !== 'object') return false;
126
141
  for (let prop in m) {
127
142
  if (m[prop]?.contextType?._currentValue && Object.keys(m).length > 60) return true;