@metamask-previews/client-controller 0.0.0-preview-a196307b6
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.
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/ClientController-method-action-types.cjs +7 -0
- package/dist/ClientController-method-action-types.cjs.map +1 -0
- package/dist/ClientController-method-action-types.d.cts +23 -0
- package/dist/ClientController-method-action-types.d.cts.map +1 -0
- package/dist/ClientController-method-action-types.d.mts +23 -0
- package/dist/ClientController-method-action-types.d.mts.map +1 -0
- package/dist/ClientController-method-action-types.mjs +6 -0
- package/dist/ClientController-method-action-types.mjs.map +1 -0
- package/dist/ClientController.cjs +117 -0
- package/dist/ClientController.cjs.map +1 -0
- package/dist/ClientController.d.cts +135 -0
- package/dist/ClientController.d.cts.map +1 -0
- package/dist/ClientController.d.mts +135 -0
- package/dist/ClientController.d.mts.map +1 -0
- package/dist/ClientController.mjs +112 -0
- package/dist/ClientController.mjs.map +1 -0
- package/dist/index.cjs +9 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/dist/selectors.cjs +18 -0
- package/dist/selectors.cjs.map +1 -0
- package/dist/selectors.d.cts +9 -0
- package/dist/selectors.d.cts.map +1 -0
- package/dist/selectors.d.mts +9 -0
- package/dist/selectors.d.mts.map +1 -0
- package/dist/selectors.mjs +15 -0
- package/dist/selectors.mjs.map +1 -0
- package/package.json +73 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of `@metamask/client-controller` ([#7808](https://github.com/MetaMask/core/pull/7808))
|
|
13
|
+
- `ClientController` for managing client (UI) open/closed state
|
|
14
|
+
- `ClientController:setUiOpen` messenger action for platform code to call
|
|
15
|
+
- `ClientController:stateChange` event for controllers to subscribe to lifecycle changes
|
|
16
|
+
- `isUiOpen` state property (not persisted - always starts as `false`)
|
|
17
|
+
- `clientControllerSelectors.selectIsUiOpen` selector for derived state access
|
|
18
|
+
- Full TypeScript support with exported types
|
|
19
|
+
|
|
20
|
+
[Unreleased]: https://github.com/MetaMask/core/
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MetaMask
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# `@metamask/client-controller`
|
|
2
|
+
|
|
3
|
+
Client-level state for MetaMask (e.g. whether a UI window is open). Provides a centralized way for controllers to respond to application lifecycle changes.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @metamask/client-controller
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
or
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @metamask/client-controller
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Basic Setup
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Messenger } from '@metamask/messenger';
|
|
23
|
+
import {
|
|
24
|
+
ClientController,
|
|
25
|
+
ClientControllerActions,
|
|
26
|
+
ClientControllerEvents,
|
|
27
|
+
} from '@metamask/client-controller';
|
|
28
|
+
|
|
29
|
+
const rootMessenger = new Messenger<
|
|
30
|
+
'Root',
|
|
31
|
+
ClientControllerActions,
|
|
32
|
+
ClientControllerEvents
|
|
33
|
+
>({ namespace: 'Root' });
|
|
34
|
+
|
|
35
|
+
const controllerMessenger = new Messenger({
|
|
36
|
+
namespace: 'ClientController',
|
|
37
|
+
parent: rootMessenger,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const clientController = new ClientController({
|
|
41
|
+
messenger: controllerMessenger,
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Platform Integration
|
|
46
|
+
|
|
47
|
+
Platform code calls `ClientController:setUiOpen` when the UI is opened or
|
|
48
|
+
closed:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
onUiOpened() {
|
|
52
|
+
controllerMessenger.call('ClientController:setUiOpen', true);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onUiClosed() {
|
|
56
|
+
controllerMessenger.call('ClientController:setUiOpen', false);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Consumer controller and using with other lifecycle state (e.g. Keyring unlock/lock)
|
|
61
|
+
|
|
62
|
+
Use `ClientController:stateChange` only for behavior that **must** run when the
|
|
63
|
+
UI is open or closed (e.g., pausing/resuming a critical background task). **Use
|
|
64
|
+
the selector** when subscribing so the handler receives a single derived value
|
|
65
|
+
(e.g. `isUiOpen`), and **prefer pause/resume** over stop/start for polling.
|
|
66
|
+
|
|
67
|
+
UI open/close alone is usually not enough to decide when to start or stop work.
|
|
68
|
+
Combine `ClientController:stateChange` with other lifecycle events, such as
|
|
69
|
+
**KeyringController:unlock** / **KeyringController:lock** (or any controller that
|
|
70
|
+
expresses "ready for background work"). Only start subscriptions, polling, or
|
|
71
|
+
network requests when **both** the UI is open and the keyring (or equivalent) is
|
|
72
|
+
unlocked; stop or pause when the UI closes **or** the keyring locks.
|
|
73
|
+
|
|
74
|
+
#### Important: Usage guidelines and warnings
|
|
75
|
+
|
|
76
|
+
**Do not subscribe to updates for all kinds of data as soon as the client
|
|
77
|
+
opens.** When MetaMask opens, the current screen may not need every type of
|
|
78
|
+
data. Starting subscriptions, polling, or network requests for everything when
|
|
79
|
+
`isUiOpen` becomes true can lead to unnecessary network traffic and battery
|
|
80
|
+
use, requests before onboarding is complete (a recurring source of issues), and
|
|
81
|
+
poor performance as more features are added.
|
|
82
|
+
|
|
83
|
+
**Use this controller responsibly:**
|
|
84
|
+
|
|
85
|
+
- Start only the subscriptions, polling, or requests that are **needed for the
|
|
86
|
+
current screen or flow**
|
|
87
|
+
- Do **not** start network-dependent or heavy behavior solely because
|
|
88
|
+
`ClientController:stateChange` reported `isUiOpen: true`
|
|
89
|
+
- Consider **deferring** non-critical updates until the user has completed
|
|
90
|
+
onboarding or reached a screen that needs that data
|
|
91
|
+
- Prefer starting and stopping per feature or per screen (e.g., when a
|
|
92
|
+
component mounts that needs the data) rather than globally when the client
|
|
93
|
+
opens
|
|
94
|
+
- **Combine with Keyring unlock/lock:** Only start work when it is appropriate
|
|
95
|
+
for both UI open state and wallet state (e.g. client open **and** keyring
|
|
96
|
+
unlocked)
|
|
97
|
+
- **Prefer pause/resume over stop/start for polling** so you can resume without
|
|
98
|
+
full re-initialization. Use the selector when subscribing (see example
|
|
99
|
+
below).
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { clientControllerSelectors } from '@metamask/client-controller';
|
|
103
|
+
|
|
104
|
+
class SomeDataController extends BaseController {
|
|
105
|
+
#uiOpen = false;
|
|
106
|
+
#keyringUnlocked = false;
|
|
107
|
+
|
|
108
|
+
constructor({ messenger }) {
|
|
109
|
+
super({ messenger, ... });
|
|
110
|
+
|
|
111
|
+
messenger.subscribe(
|
|
112
|
+
'ClientController:stateChange',
|
|
113
|
+
(isUiOpen) => {
|
|
114
|
+
this.#uiOpen = isUiOpen;
|
|
115
|
+
this.updateActive();
|
|
116
|
+
},
|
|
117
|
+
clientControllerSelectors.selectIsUiOpen,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
messenger.subscribe('KeyringController:unlock', () => {
|
|
121
|
+
this.#keyringUnlocked = true;
|
|
122
|
+
this.updateActive();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
messenger.subscribe('KeyringController:lock', () => {
|
|
126
|
+
this.#keyringUnlocked = false;
|
|
127
|
+
this.updateActive();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
updateActive() {
|
|
132
|
+
const shouldRun = this.#uiOpen && this.#keyringUnlocked;
|
|
133
|
+
if (shouldRun) {
|
|
134
|
+
this.resume();
|
|
135
|
+
} else {
|
|
136
|
+
this.pause();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Note: `stateChange` emits `[state, patches]`; the selector receives the full
|
|
143
|
+
payload and returns the value passed to the handler (here, `isUiOpen`).
|
|
144
|
+
|
|
145
|
+
## API Reference
|
|
146
|
+
|
|
147
|
+
### State
|
|
148
|
+
|
|
149
|
+
| Property | Type | Description |
|
|
150
|
+
| ---------- | --------- | ------------------------------------------ |
|
|
151
|
+
| `isUiOpen` | `boolean` | Whether the client (UI) is currently open. |
|
|
152
|
+
|
|
153
|
+
State is not persisted. It always starts as `false`.
|
|
154
|
+
|
|
155
|
+
### Actions
|
|
156
|
+
|
|
157
|
+
| Action | Parameters | Description |
|
|
158
|
+
| ---------------------------- | --------------- | ---------------------------- |
|
|
159
|
+
| `ClientController:getState` | none | Returns current state. |
|
|
160
|
+
| `ClientController:setUiOpen` | `open: boolean` | Sets whether the UI is open. |
|
|
161
|
+
|
|
162
|
+
### Events
|
|
163
|
+
|
|
164
|
+
| Event | Payload | Description |
|
|
165
|
+
| ------------------------------ | ------------------ | ---------------------------- |
|
|
166
|
+
| `ClientController:stateChange` | `[state, patches]` | Standard state change event. |
|
|
167
|
+
|
|
168
|
+
### Selectors
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { clientControllerSelectors } from '@metamask/client-controller';
|
|
172
|
+
|
|
173
|
+
const state = messenger.call('ClientController:getState');
|
|
174
|
+
const isOpen = clientControllerSelectors.selectIsUiOpen(state);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Contributing
|
|
178
|
+
|
|
179
|
+
This package is part of a monorepo. Instructions for contributing can be found
|
|
180
|
+
in the [monorepo README](https://github.com/MetaMask/core#readme).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController-method-action-types.cjs","sourceRoot":"","sources":["../src/ClientController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { ClientController } from './ClientController';\n\n/**\n * Updates state with whether the MetaMask UI is open.\n *\n * This method should be called when the user has opened the first window or\n * screen containing the MetaMask UI, or closed the last window or screen\n * containing the MetaMask UI.\n *\n * @param open - Whether the MetaMask UI is open.\n */\nexport type ClientControllerSetUiOpenAction = {\n type: `ClientController:setUiOpen`;\n handler: ClientController['setUiOpen'];\n};\n\n/**\n * Union of all ClientController action types.\n */\nexport type ClientControllerMethodActions = ClientControllerSetUiOpenAction;\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
+
* Do not edit manually.
|
|
4
|
+
*/
|
|
5
|
+
import type { ClientController } from "./ClientController.cjs";
|
|
6
|
+
/**
|
|
7
|
+
* Updates state with whether the MetaMask UI is open.
|
|
8
|
+
*
|
|
9
|
+
* This method should be called when the user has opened the first window or
|
|
10
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
11
|
+
* containing the MetaMask UI.
|
|
12
|
+
*
|
|
13
|
+
* @param open - Whether the MetaMask UI is open.
|
|
14
|
+
*/
|
|
15
|
+
export type ClientControllerSetUiOpenAction = {
|
|
16
|
+
type: `ClientController:setUiOpen`;
|
|
17
|
+
handler: ClientController['setUiOpen'];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Union of all ClientController action types.
|
|
21
|
+
*/
|
|
22
|
+
export type ClientControllerMethodActions = ClientControllerSetUiOpenAction;
|
|
23
|
+
//# sourceMappingURL=ClientController-method-action-types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController-method-action-types.d.cts","sourceRoot":"","sources":["../src/ClientController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA2B;AAE3D;;;;;;;;GAQG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,4BAA4B,CAAC;IACnC,OAAO,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
+
* Do not edit manually.
|
|
4
|
+
*/
|
|
5
|
+
import type { ClientController } from "./ClientController.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Updates state with whether the MetaMask UI is open.
|
|
8
|
+
*
|
|
9
|
+
* This method should be called when the user has opened the first window or
|
|
10
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
11
|
+
* containing the MetaMask UI.
|
|
12
|
+
*
|
|
13
|
+
* @param open - Whether the MetaMask UI is open.
|
|
14
|
+
*/
|
|
15
|
+
export type ClientControllerSetUiOpenAction = {
|
|
16
|
+
type: `ClientController:setUiOpen`;
|
|
17
|
+
handler: ClientController['setUiOpen'];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Union of all ClientController action types.
|
|
21
|
+
*/
|
|
22
|
+
export type ClientControllerMethodActions = ClientControllerSetUiOpenAction;
|
|
23
|
+
//# sourceMappingURL=ClientController-method-action-types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController-method-action-types.d.mts","sourceRoot":"","sources":["../src/ClientController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA2B;AAE3D;;;;;;;;GAQG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,4BAA4B,CAAC;IACnC,OAAO,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,+BAA+B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController-method-action-types.mjs","sourceRoot":"","sources":["../src/ClientController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { ClientController } from './ClientController';\n\n/**\n * Updates state with whether the MetaMask UI is open.\n *\n * This method should be called when the user has opened the first window or\n * screen containing the MetaMask UI, or closed the last window or screen\n * containing the MetaMask UI.\n *\n * @param open - Whether the MetaMask UI is open.\n */\nexport type ClientControllerSetUiOpenAction = {\n type: `ClientController:setUiOpen`;\n handler: ClientController['setUiOpen'];\n};\n\n/**\n * Union of all ClientController action types.\n */\nexport type ClientControllerMethodActions = ClientControllerSetUiOpenAction;\n"]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClientController = exports.getDefaultClientControllerState = exports.controllerName = void 0;
|
|
4
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
5
|
+
// === GENERAL ===
|
|
6
|
+
/**
|
|
7
|
+
* The name of the {@link ClientController}.
|
|
8
|
+
*/
|
|
9
|
+
exports.controllerName = 'ClientController';
|
|
10
|
+
/**
|
|
11
|
+
* Constructs the default {@link ClientController} state.
|
|
12
|
+
*
|
|
13
|
+
* @returns The default {@link ClientController} state.
|
|
14
|
+
*/
|
|
15
|
+
function getDefaultClientControllerState() {
|
|
16
|
+
return {
|
|
17
|
+
isUiOpen: false,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
exports.getDefaultClientControllerState = getDefaultClientControllerState;
|
|
21
|
+
/**
|
|
22
|
+
* The metadata for each property in {@link ClientControllerState}.
|
|
23
|
+
*/
|
|
24
|
+
const controllerMetadata = {
|
|
25
|
+
isUiOpen: {
|
|
26
|
+
includeInDebugSnapshot: true,
|
|
27
|
+
includeInStateLogs: true,
|
|
28
|
+
persist: false,
|
|
29
|
+
usedInUi: false,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
// === MESSENGER ===
|
|
33
|
+
const MESSENGER_EXPOSED_METHODS = ['setUiOpen'];
|
|
34
|
+
/**
|
|
35
|
+
* `ClientController` manages the application lifecycle state.
|
|
36
|
+
*
|
|
37
|
+
* This controller tracks whether the MetaMask UI is open and publishes state
|
|
38
|
+
* change events that other controllers can subscribe to for adjusting their behavior.
|
|
39
|
+
*
|
|
40
|
+
* **Use cases:**
|
|
41
|
+
* - Polling controllers can pause when the UI closes, resume when it opens
|
|
42
|
+
* - WebSocket connections can disconnect when closed, reconnect when opened
|
|
43
|
+
* - Real-time subscriptions can pause when not visible
|
|
44
|
+
*
|
|
45
|
+
* **Platform Integration:**
|
|
46
|
+
* Platform code should call `ClientController:setUiOpen` via messenger.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // In MetamaskController or platform code
|
|
51
|
+
* onUiOpened() {
|
|
52
|
+
* // ...
|
|
53
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', true);
|
|
54
|
+
* }
|
|
55
|
+
*
|
|
56
|
+
* onUiClosed() {
|
|
57
|
+
* // ...
|
|
58
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', false);
|
|
59
|
+
* }
|
|
60
|
+
*
|
|
61
|
+
* // Consumer controller subscribing to state changes
|
|
62
|
+
* class MyController extends BaseController {
|
|
63
|
+
* constructor({ messenger }) {
|
|
64
|
+
* super({ messenger, ... });
|
|
65
|
+
*
|
|
66
|
+
* messenger.subscribe(
|
|
67
|
+
* 'ClientController:stateChange',
|
|
68
|
+
* (isClientOpen) => {
|
|
69
|
+
* if (isClientOpen) {
|
|
70
|
+
* this.resumePolling();
|
|
71
|
+
* } else {
|
|
72
|
+
* this.pausePolling();
|
|
73
|
+
* }
|
|
74
|
+
* },
|
|
75
|
+
* clientControllerSelectors.selectIsUiOpen,
|
|
76
|
+
* );
|
|
77
|
+
* }
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
class ClientController extends base_controller_1.BaseController {
|
|
82
|
+
/**
|
|
83
|
+
* Constructs a new {@link ClientController}.
|
|
84
|
+
*
|
|
85
|
+
* @param options - The constructor options.
|
|
86
|
+
* @param options.messenger - The messenger suited for this controller.
|
|
87
|
+
* @param options.state - The initial state to set on this controller.
|
|
88
|
+
*/
|
|
89
|
+
constructor({ messenger, state = {} }) {
|
|
90
|
+
super({
|
|
91
|
+
messenger,
|
|
92
|
+
metadata: controllerMetadata,
|
|
93
|
+
name: exports.controllerName,
|
|
94
|
+
state: {
|
|
95
|
+
...getDefaultClientControllerState(),
|
|
96
|
+
...state,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Updates state with whether the MetaMask UI is open.
|
|
103
|
+
*
|
|
104
|
+
* This method should be called when the user has opened the first window or
|
|
105
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
106
|
+
* containing the MetaMask UI.
|
|
107
|
+
*
|
|
108
|
+
* @param open - Whether the MetaMask UI is open.
|
|
109
|
+
*/
|
|
110
|
+
setUiOpen(open) {
|
|
111
|
+
this.update((state) => {
|
|
112
|
+
state.isUiOpen = open;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.ClientController = ClientController;
|
|
117
|
+
//# sourceMappingURL=ClientController.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController.cjs","sourceRoot":"","sources":["../src/ClientController.ts"],"names":[],"mappings":";;;AAKA,+DAA2D;AAK3D,kBAAkB;AAElB;;GAEG;AACU,QAAA,cAAc,GAAG,kBAAkB,CAAC;AAgBjD;;;;GAIG;AACH,SAAgB,+BAA+B;IAC7C,OAAO;QACL,QAAQ,EAAE,KAAK;KAChB,CAAC;AACJ,CAAC;AAJD,0EAIC;AAED;;GAEG;AACH,MAAM,kBAAkB,GAAG;IACzB,QAAQ,EAAE;QACR,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,IAAI;QACxB,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,KAAK;KAChB;CAC6C,CAAC;AAEjD,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,WAAW,CAAU,CAAC;AAiEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAa,gBAAiB,SAAQ,gCAIrC;IACC;;;;;;OAMG;IACH,YAAY,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAA2B;QAC5D,KAAK,CAAC;YACJ,SAAS;YACT,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,sBAAc;YACpB,KAAK,EAAE;gBACL,GAAG,+BAA+B,EAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,4BAA4B,CACzC,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAa;QACrB,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA3CD,4CA2CC","sourcesContent":["import type {\n StateMetadata,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { ClientControllerMethodActions } from './ClientController-method-action-types';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ClientController}.\n */\nexport const controllerName = 'ClientController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link ClientController}.\n */\nexport type ClientControllerState = {\n /**\n * Whether the user has opened at least one window or screen\n * containing the MetaMask UI. These windows or screens may or\n * may not be in an inactive state.\n */\n isUiOpen: boolean;\n};\n\n/**\n * Constructs the default {@link ClientController} state.\n *\n * @returns The default {@link ClientController} state.\n */\nexport function getDefaultClientControllerState(): ClientControllerState {\n return {\n isUiOpen: false,\n };\n}\n\n/**\n * The metadata for each property in {@link ClientControllerState}.\n */\nconst controllerMetadata = {\n isUiOpen: {\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n persist: false,\n usedInUi: false,\n },\n} satisfies StateMetadata<ClientControllerState>;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['setUiOpen'] as const;\n\n/**\n * Retrieves the state of the {@link ClientController}.\n */\nexport type ClientControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ClientControllerState\n>;\n\n/**\n * Actions that {@link ClientController} exposes.\n */\nexport type ClientControllerActions =\n | ClientControllerGetStateAction\n | ClientControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ClientController} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Published when the state of {@link ClientController} changes.\n */\nexport type ClientControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ClientControllerState\n>;\n\n/**\n * Events that {@link ClientController} exposes.\n */\nexport type ClientControllerEvents = ClientControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ClientController} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger for {@link ClientController}.\n */\nexport type ClientControllerMessenger = Messenger<\n typeof controllerName,\n ClientControllerActions | AllowedActions,\n ClientControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options for constructing a {@link ClientController}.\n */\nexport type ClientControllerOptions = {\n /**\n * The messenger suited for this controller.\n */\n messenger: ClientControllerMessenger;\n /**\n * The initial state to set on this controller.\n */\n state?: Partial<ClientControllerState>;\n};\n\n/**\n * `ClientController` manages the application lifecycle state.\n *\n * This controller tracks whether the MetaMask UI is open and publishes state\n * change events that other controllers can subscribe to for adjusting their behavior.\n *\n * **Use cases:**\n * - Polling controllers can pause when the UI closes, resume when it opens\n * - WebSocket connections can disconnect when closed, reconnect when opened\n * - Real-time subscriptions can pause when not visible\n *\n * **Platform Integration:**\n * Platform code should call `ClientController:setUiOpen` via messenger.\n *\n * @example\n * ```typescript\n * // In MetamaskController or platform code\n * onUiOpened() {\n * // ...\n * this.controllerMessenger.call('ClientController:setUiOpen', true);\n * }\n *\n * onUiClosed() {\n * // ...\n * this.controllerMessenger.call('ClientController:setUiOpen', false);\n * }\n *\n * // Consumer controller subscribing to state changes\n * class MyController extends BaseController {\n * constructor({ messenger }) {\n * super({ messenger, ... });\n *\n * messenger.subscribe(\n * 'ClientController:stateChange',\n * (isClientOpen) => {\n * if (isClientOpen) {\n * this.resumePolling();\n * } else {\n * this.pausePolling();\n * }\n * },\n * clientControllerSelectors.selectIsUiOpen,\n * );\n * }\n * }\n * ```\n */\nexport class ClientController extends BaseController<\n typeof controllerName,\n ClientControllerState,\n ClientControllerMessenger\n> {\n /**\n * Constructs a new {@link ClientController}.\n *\n * @param options - The constructor options.\n * @param options.messenger - The messenger suited for this controller.\n * @param options.state - The initial state to set on this controller.\n */\n constructor({ messenger, state = {} }: ClientControllerOptions) {\n super({\n messenger,\n metadata: controllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultClientControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Updates state with whether the MetaMask UI is open.\n *\n * This method should be called when the user has opened the first window or\n * screen containing the MetaMask UI, or closed the last window or screen\n * containing the MetaMask UI.\n *\n * @param open - Whether the MetaMask UI is open.\n */\n setUiOpen(open: boolean): void {\n this.update((state) => {\n state.isUiOpen = open;\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import { BaseController } from "@metamask/base-controller";
|
|
3
|
+
import type { Messenger } from "@metamask/messenger";
|
|
4
|
+
import type { ClientControllerMethodActions } from "./ClientController-method-action-types.cjs";
|
|
5
|
+
/**
|
|
6
|
+
* The name of the {@link ClientController}.
|
|
7
|
+
*/
|
|
8
|
+
export declare const controllerName = "ClientController";
|
|
9
|
+
/**
|
|
10
|
+
* Describes the shape of the state object for {@link ClientController}.
|
|
11
|
+
*/
|
|
12
|
+
export type ClientControllerState = {
|
|
13
|
+
/**
|
|
14
|
+
* Whether the user has opened at least one window or screen
|
|
15
|
+
* containing the MetaMask UI. These windows or screens may or
|
|
16
|
+
* may not be in an inactive state.
|
|
17
|
+
*/
|
|
18
|
+
isUiOpen: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Constructs the default {@link ClientController} state.
|
|
22
|
+
*
|
|
23
|
+
* @returns The default {@link ClientController} state.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getDefaultClientControllerState(): ClientControllerState;
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves the state of the {@link ClientController}.
|
|
28
|
+
*/
|
|
29
|
+
export type ClientControllerGetStateAction = ControllerGetStateAction<typeof controllerName, ClientControllerState>;
|
|
30
|
+
/**
|
|
31
|
+
* Actions that {@link ClientController} exposes.
|
|
32
|
+
*/
|
|
33
|
+
export type ClientControllerActions = ClientControllerGetStateAction | ClientControllerMethodActions;
|
|
34
|
+
/**
|
|
35
|
+
* Actions from other messengers that {@link ClientController} calls.
|
|
36
|
+
*/
|
|
37
|
+
type AllowedActions = never;
|
|
38
|
+
/**
|
|
39
|
+
* Published when the state of {@link ClientController} changes.
|
|
40
|
+
*/
|
|
41
|
+
export type ClientControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, ClientControllerState>;
|
|
42
|
+
/**
|
|
43
|
+
* Events that {@link ClientController} exposes.
|
|
44
|
+
*/
|
|
45
|
+
export type ClientControllerEvents = ClientControllerStateChangeEvent;
|
|
46
|
+
/**
|
|
47
|
+
* Events from other messengers that {@link ClientController} subscribes to.
|
|
48
|
+
*/
|
|
49
|
+
type AllowedEvents = never;
|
|
50
|
+
/**
|
|
51
|
+
* The messenger for {@link ClientController}.
|
|
52
|
+
*/
|
|
53
|
+
export type ClientControllerMessenger = Messenger<typeof controllerName, ClientControllerActions | AllowedActions, ClientControllerEvents | AllowedEvents>;
|
|
54
|
+
/**
|
|
55
|
+
* The options for constructing a {@link ClientController}.
|
|
56
|
+
*/
|
|
57
|
+
export type ClientControllerOptions = {
|
|
58
|
+
/**
|
|
59
|
+
* The messenger suited for this controller.
|
|
60
|
+
*/
|
|
61
|
+
messenger: ClientControllerMessenger;
|
|
62
|
+
/**
|
|
63
|
+
* The initial state to set on this controller.
|
|
64
|
+
*/
|
|
65
|
+
state?: Partial<ClientControllerState>;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* `ClientController` manages the application lifecycle state.
|
|
69
|
+
*
|
|
70
|
+
* This controller tracks whether the MetaMask UI is open and publishes state
|
|
71
|
+
* change events that other controllers can subscribe to for adjusting their behavior.
|
|
72
|
+
*
|
|
73
|
+
* **Use cases:**
|
|
74
|
+
* - Polling controllers can pause when the UI closes, resume when it opens
|
|
75
|
+
* - WebSocket connections can disconnect when closed, reconnect when opened
|
|
76
|
+
* - Real-time subscriptions can pause when not visible
|
|
77
|
+
*
|
|
78
|
+
* **Platform Integration:**
|
|
79
|
+
* Platform code should call `ClientController:setUiOpen` via messenger.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // In MetamaskController or platform code
|
|
84
|
+
* onUiOpened() {
|
|
85
|
+
* // ...
|
|
86
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', true);
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* onUiClosed() {
|
|
90
|
+
* // ...
|
|
91
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', false);
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* // Consumer controller subscribing to state changes
|
|
95
|
+
* class MyController extends BaseController {
|
|
96
|
+
* constructor({ messenger }) {
|
|
97
|
+
* super({ messenger, ... });
|
|
98
|
+
*
|
|
99
|
+
* messenger.subscribe(
|
|
100
|
+
* 'ClientController:stateChange',
|
|
101
|
+
* (isClientOpen) => {
|
|
102
|
+
* if (isClientOpen) {
|
|
103
|
+
* this.resumePolling();
|
|
104
|
+
* } else {
|
|
105
|
+
* this.pausePolling();
|
|
106
|
+
* }
|
|
107
|
+
* },
|
|
108
|
+
* clientControllerSelectors.selectIsUiOpen,
|
|
109
|
+
* );
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare class ClientController extends BaseController<typeof controllerName, ClientControllerState, ClientControllerMessenger> {
|
|
115
|
+
/**
|
|
116
|
+
* Constructs a new {@link ClientController}.
|
|
117
|
+
*
|
|
118
|
+
* @param options - The constructor options.
|
|
119
|
+
* @param options.messenger - The messenger suited for this controller.
|
|
120
|
+
* @param options.state - The initial state to set on this controller.
|
|
121
|
+
*/
|
|
122
|
+
constructor({ messenger, state }: ClientControllerOptions);
|
|
123
|
+
/**
|
|
124
|
+
* Updates state with whether the MetaMask UI is open.
|
|
125
|
+
*
|
|
126
|
+
* This method should be called when the user has opened the first window or
|
|
127
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
128
|
+
* containing the MetaMask UI.
|
|
129
|
+
*
|
|
130
|
+
* @param open - Whether the MetaMask UI is open.
|
|
131
|
+
*/
|
|
132
|
+
setUiOpen(open: boolean): void;
|
|
133
|
+
}
|
|
134
|
+
export {};
|
|
135
|
+
//# sourceMappingURL=ClientController.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController.d.cts","sourceRoot":"","sources":["../src/ClientController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,6BAA6B,EAAE,mDAA+C;AAI5F;;GAEG;AACH,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAIjD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAIvE;AAkBD;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,6BAA6B,CAAC;AAElC;;GAEG;AACH,KAAK,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAEtE;;GAEG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,GAAG,cAAc,EACxC,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAIF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,SAAS,EAAE,yBAAyB,CAAC;IACrC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;IACC;;;;;;OAMG;gBACS,EAAE,SAAS,EAAE,KAAU,EAAE,EAAE,uBAAuB;IAiB9D;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CAK/B"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent } from "@metamask/base-controller";
|
|
2
|
+
import { BaseController } from "@metamask/base-controller";
|
|
3
|
+
import type { Messenger } from "@metamask/messenger";
|
|
4
|
+
import type { ClientControllerMethodActions } from "./ClientController-method-action-types.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* The name of the {@link ClientController}.
|
|
7
|
+
*/
|
|
8
|
+
export declare const controllerName = "ClientController";
|
|
9
|
+
/**
|
|
10
|
+
* Describes the shape of the state object for {@link ClientController}.
|
|
11
|
+
*/
|
|
12
|
+
export type ClientControllerState = {
|
|
13
|
+
/**
|
|
14
|
+
* Whether the user has opened at least one window or screen
|
|
15
|
+
* containing the MetaMask UI. These windows or screens may or
|
|
16
|
+
* may not be in an inactive state.
|
|
17
|
+
*/
|
|
18
|
+
isUiOpen: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Constructs the default {@link ClientController} state.
|
|
22
|
+
*
|
|
23
|
+
* @returns The default {@link ClientController} state.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getDefaultClientControllerState(): ClientControllerState;
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves the state of the {@link ClientController}.
|
|
28
|
+
*/
|
|
29
|
+
export type ClientControllerGetStateAction = ControllerGetStateAction<typeof controllerName, ClientControllerState>;
|
|
30
|
+
/**
|
|
31
|
+
* Actions that {@link ClientController} exposes.
|
|
32
|
+
*/
|
|
33
|
+
export type ClientControllerActions = ClientControllerGetStateAction | ClientControllerMethodActions;
|
|
34
|
+
/**
|
|
35
|
+
* Actions from other messengers that {@link ClientController} calls.
|
|
36
|
+
*/
|
|
37
|
+
type AllowedActions = never;
|
|
38
|
+
/**
|
|
39
|
+
* Published when the state of {@link ClientController} changes.
|
|
40
|
+
*/
|
|
41
|
+
export type ClientControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, ClientControllerState>;
|
|
42
|
+
/**
|
|
43
|
+
* Events that {@link ClientController} exposes.
|
|
44
|
+
*/
|
|
45
|
+
export type ClientControllerEvents = ClientControllerStateChangeEvent;
|
|
46
|
+
/**
|
|
47
|
+
* Events from other messengers that {@link ClientController} subscribes to.
|
|
48
|
+
*/
|
|
49
|
+
type AllowedEvents = never;
|
|
50
|
+
/**
|
|
51
|
+
* The messenger for {@link ClientController}.
|
|
52
|
+
*/
|
|
53
|
+
export type ClientControllerMessenger = Messenger<typeof controllerName, ClientControllerActions | AllowedActions, ClientControllerEvents | AllowedEvents>;
|
|
54
|
+
/**
|
|
55
|
+
* The options for constructing a {@link ClientController}.
|
|
56
|
+
*/
|
|
57
|
+
export type ClientControllerOptions = {
|
|
58
|
+
/**
|
|
59
|
+
* The messenger suited for this controller.
|
|
60
|
+
*/
|
|
61
|
+
messenger: ClientControllerMessenger;
|
|
62
|
+
/**
|
|
63
|
+
* The initial state to set on this controller.
|
|
64
|
+
*/
|
|
65
|
+
state?: Partial<ClientControllerState>;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* `ClientController` manages the application lifecycle state.
|
|
69
|
+
*
|
|
70
|
+
* This controller tracks whether the MetaMask UI is open and publishes state
|
|
71
|
+
* change events that other controllers can subscribe to for adjusting their behavior.
|
|
72
|
+
*
|
|
73
|
+
* **Use cases:**
|
|
74
|
+
* - Polling controllers can pause when the UI closes, resume when it opens
|
|
75
|
+
* - WebSocket connections can disconnect when closed, reconnect when opened
|
|
76
|
+
* - Real-time subscriptions can pause when not visible
|
|
77
|
+
*
|
|
78
|
+
* **Platform Integration:**
|
|
79
|
+
* Platform code should call `ClientController:setUiOpen` via messenger.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // In MetamaskController or platform code
|
|
84
|
+
* onUiOpened() {
|
|
85
|
+
* // ...
|
|
86
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', true);
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* onUiClosed() {
|
|
90
|
+
* // ...
|
|
91
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', false);
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* // Consumer controller subscribing to state changes
|
|
95
|
+
* class MyController extends BaseController {
|
|
96
|
+
* constructor({ messenger }) {
|
|
97
|
+
* super({ messenger, ... });
|
|
98
|
+
*
|
|
99
|
+
* messenger.subscribe(
|
|
100
|
+
* 'ClientController:stateChange',
|
|
101
|
+
* (isClientOpen) => {
|
|
102
|
+
* if (isClientOpen) {
|
|
103
|
+
* this.resumePolling();
|
|
104
|
+
* } else {
|
|
105
|
+
* this.pausePolling();
|
|
106
|
+
* }
|
|
107
|
+
* },
|
|
108
|
+
* clientControllerSelectors.selectIsUiOpen,
|
|
109
|
+
* );
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare class ClientController extends BaseController<typeof controllerName, ClientControllerState, ClientControllerMessenger> {
|
|
115
|
+
/**
|
|
116
|
+
* Constructs a new {@link ClientController}.
|
|
117
|
+
*
|
|
118
|
+
* @param options - The constructor options.
|
|
119
|
+
* @param options.messenger - The messenger suited for this controller.
|
|
120
|
+
* @param options.state - The initial state to set on this controller.
|
|
121
|
+
*/
|
|
122
|
+
constructor({ messenger, state }: ClientControllerOptions);
|
|
123
|
+
/**
|
|
124
|
+
* Updates state with whether the MetaMask UI is open.
|
|
125
|
+
*
|
|
126
|
+
* This method should be called when the user has opened the first window or
|
|
127
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
128
|
+
* containing the MetaMask UI.
|
|
129
|
+
*
|
|
130
|
+
* @param open - Whether the MetaMask UI is open.
|
|
131
|
+
*/
|
|
132
|
+
setUiOpen(open: boolean): void;
|
|
133
|
+
}
|
|
134
|
+
export {};
|
|
135
|
+
//# sourceMappingURL=ClientController.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController.d.mts","sourceRoot":"","sources":["../src/ClientController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,6BAA6B,EAAE,mDAA+C;AAI5F;;GAEG;AACH,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAIjD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAIvE;AAkBD;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,6BAA6B,CAAC;AAElC;;GAEG;AACH,KAAK,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,cAAc,EACrB,qBAAqB,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAEtE;;GAEG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,cAAc,EACrB,uBAAuB,GAAG,cAAc,EACxC,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAIF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,SAAS,EAAE,yBAAyB,CAAC;IACrC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,cAAc,EACrB,qBAAqB,EACrB,yBAAyB,CAC1B;IACC;;;;;;OAMG;gBACS,EAAE,SAAS,EAAE,KAAU,EAAE,EAAE,uBAAuB;IAiB9D;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CAK/B"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { BaseController } from "@metamask/base-controller";
|
|
2
|
+
// === GENERAL ===
|
|
3
|
+
/**
|
|
4
|
+
* The name of the {@link ClientController}.
|
|
5
|
+
*/
|
|
6
|
+
export const controllerName = 'ClientController';
|
|
7
|
+
/**
|
|
8
|
+
* Constructs the default {@link ClientController} state.
|
|
9
|
+
*
|
|
10
|
+
* @returns The default {@link ClientController} state.
|
|
11
|
+
*/
|
|
12
|
+
export function getDefaultClientControllerState() {
|
|
13
|
+
return {
|
|
14
|
+
isUiOpen: false,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The metadata for each property in {@link ClientControllerState}.
|
|
19
|
+
*/
|
|
20
|
+
const controllerMetadata = {
|
|
21
|
+
isUiOpen: {
|
|
22
|
+
includeInDebugSnapshot: true,
|
|
23
|
+
includeInStateLogs: true,
|
|
24
|
+
persist: false,
|
|
25
|
+
usedInUi: false,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
// === MESSENGER ===
|
|
29
|
+
const MESSENGER_EXPOSED_METHODS = ['setUiOpen'];
|
|
30
|
+
/**
|
|
31
|
+
* `ClientController` manages the application lifecycle state.
|
|
32
|
+
*
|
|
33
|
+
* This controller tracks whether the MetaMask UI is open and publishes state
|
|
34
|
+
* change events that other controllers can subscribe to for adjusting their behavior.
|
|
35
|
+
*
|
|
36
|
+
* **Use cases:**
|
|
37
|
+
* - Polling controllers can pause when the UI closes, resume when it opens
|
|
38
|
+
* - WebSocket connections can disconnect when closed, reconnect when opened
|
|
39
|
+
* - Real-time subscriptions can pause when not visible
|
|
40
|
+
*
|
|
41
|
+
* **Platform Integration:**
|
|
42
|
+
* Platform code should call `ClientController:setUiOpen` via messenger.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // In MetamaskController or platform code
|
|
47
|
+
* onUiOpened() {
|
|
48
|
+
* // ...
|
|
49
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', true);
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* onUiClosed() {
|
|
53
|
+
* // ...
|
|
54
|
+
* this.controllerMessenger.call('ClientController:setUiOpen', false);
|
|
55
|
+
* }
|
|
56
|
+
*
|
|
57
|
+
* // Consumer controller subscribing to state changes
|
|
58
|
+
* class MyController extends BaseController {
|
|
59
|
+
* constructor({ messenger }) {
|
|
60
|
+
* super({ messenger, ... });
|
|
61
|
+
*
|
|
62
|
+
* messenger.subscribe(
|
|
63
|
+
* 'ClientController:stateChange',
|
|
64
|
+
* (isClientOpen) => {
|
|
65
|
+
* if (isClientOpen) {
|
|
66
|
+
* this.resumePolling();
|
|
67
|
+
* } else {
|
|
68
|
+
* this.pausePolling();
|
|
69
|
+
* }
|
|
70
|
+
* },
|
|
71
|
+
* clientControllerSelectors.selectIsUiOpen,
|
|
72
|
+
* );
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export class ClientController extends BaseController {
|
|
78
|
+
/**
|
|
79
|
+
* Constructs a new {@link ClientController}.
|
|
80
|
+
*
|
|
81
|
+
* @param options - The constructor options.
|
|
82
|
+
* @param options.messenger - The messenger suited for this controller.
|
|
83
|
+
* @param options.state - The initial state to set on this controller.
|
|
84
|
+
*/
|
|
85
|
+
constructor({ messenger, state = {} }) {
|
|
86
|
+
super({
|
|
87
|
+
messenger,
|
|
88
|
+
metadata: controllerMetadata,
|
|
89
|
+
name: controllerName,
|
|
90
|
+
state: {
|
|
91
|
+
...getDefaultClientControllerState(),
|
|
92
|
+
...state,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Updates state with whether the MetaMask UI is open.
|
|
99
|
+
*
|
|
100
|
+
* This method should be called when the user has opened the first window or
|
|
101
|
+
* screen containing the MetaMask UI, or closed the last window or screen
|
|
102
|
+
* containing the MetaMask UI.
|
|
103
|
+
*
|
|
104
|
+
* @param open - Whether the MetaMask UI is open.
|
|
105
|
+
*/
|
|
106
|
+
setUiOpen(open) {
|
|
107
|
+
this.update((state) => {
|
|
108
|
+
state.isUiOpen = open;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=ClientController.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientController.mjs","sourceRoot":"","sources":["../src/ClientController.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAK3D,kBAAkB;AAElB;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAgBjD;;;;GAIG;AACH,MAAM,UAAU,+BAA+B;IAC7C,OAAO;QACL,QAAQ,EAAE,KAAK;KAChB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,kBAAkB,GAAG;IACzB,QAAQ,EAAE;QACR,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,IAAI;QACxB,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,KAAK;KAChB;CAC6C,CAAC;AAEjD,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,WAAW,CAAU,CAAC;AAiEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,OAAO,gBAAiB,SAAQ,cAIrC;IACC;;;;;;OAMG;IACH,YAAY,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAA2B;QAC5D,KAAK,CAAC;YACJ,SAAS;YACT,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE;gBACL,GAAG,+BAA+B,EAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,4BAA4B,CACzC,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAa;QACrB,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import type {\n StateMetadata,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { ClientControllerMethodActions } from './ClientController-method-action-types';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ClientController}.\n */\nexport const controllerName = 'ClientController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link ClientController}.\n */\nexport type ClientControllerState = {\n /**\n * Whether the user has opened at least one window or screen\n * containing the MetaMask UI. These windows or screens may or\n * may not be in an inactive state.\n */\n isUiOpen: boolean;\n};\n\n/**\n * Constructs the default {@link ClientController} state.\n *\n * @returns The default {@link ClientController} state.\n */\nexport function getDefaultClientControllerState(): ClientControllerState {\n return {\n isUiOpen: false,\n };\n}\n\n/**\n * The metadata for each property in {@link ClientControllerState}.\n */\nconst controllerMetadata = {\n isUiOpen: {\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n persist: false,\n usedInUi: false,\n },\n} satisfies StateMetadata<ClientControllerState>;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['setUiOpen'] as const;\n\n/**\n * Retrieves the state of the {@link ClientController}.\n */\nexport type ClientControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ClientControllerState\n>;\n\n/**\n * Actions that {@link ClientController} exposes.\n */\nexport type ClientControllerActions =\n | ClientControllerGetStateAction\n | ClientControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ClientController} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Published when the state of {@link ClientController} changes.\n */\nexport type ClientControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ClientControllerState\n>;\n\n/**\n * Events that {@link ClientController} exposes.\n */\nexport type ClientControllerEvents = ClientControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ClientController} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger for {@link ClientController}.\n */\nexport type ClientControllerMessenger = Messenger<\n typeof controllerName,\n ClientControllerActions | AllowedActions,\n ClientControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options for constructing a {@link ClientController}.\n */\nexport type ClientControllerOptions = {\n /**\n * The messenger suited for this controller.\n */\n messenger: ClientControllerMessenger;\n /**\n * The initial state to set on this controller.\n */\n state?: Partial<ClientControllerState>;\n};\n\n/**\n * `ClientController` manages the application lifecycle state.\n *\n * This controller tracks whether the MetaMask UI is open and publishes state\n * change events that other controllers can subscribe to for adjusting their behavior.\n *\n * **Use cases:**\n * - Polling controllers can pause when the UI closes, resume when it opens\n * - WebSocket connections can disconnect when closed, reconnect when opened\n * - Real-time subscriptions can pause when not visible\n *\n * **Platform Integration:**\n * Platform code should call `ClientController:setUiOpen` via messenger.\n *\n * @example\n * ```typescript\n * // In MetamaskController or platform code\n * onUiOpened() {\n * // ...\n * this.controllerMessenger.call('ClientController:setUiOpen', true);\n * }\n *\n * onUiClosed() {\n * // ...\n * this.controllerMessenger.call('ClientController:setUiOpen', false);\n * }\n *\n * // Consumer controller subscribing to state changes\n * class MyController extends BaseController {\n * constructor({ messenger }) {\n * super({ messenger, ... });\n *\n * messenger.subscribe(\n * 'ClientController:stateChange',\n * (isClientOpen) => {\n * if (isClientOpen) {\n * this.resumePolling();\n * } else {\n * this.pausePolling();\n * }\n * },\n * clientControllerSelectors.selectIsUiOpen,\n * );\n * }\n * }\n * ```\n */\nexport class ClientController extends BaseController<\n typeof controllerName,\n ClientControllerState,\n ClientControllerMessenger\n> {\n /**\n * Constructs a new {@link ClientController}.\n *\n * @param options - The constructor options.\n * @param options.messenger - The messenger suited for this controller.\n * @param options.state - The initial state to set on this controller.\n */\n constructor({ messenger, state = {} }: ClientControllerOptions) {\n super({\n messenger,\n metadata: controllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultClientControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Updates state with whether the MetaMask UI is open.\n *\n * This method should be called when the user has opened the first window or\n * screen containing the MetaMask UI, or closed the last window or screen\n * containing the MetaMask UI.\n *\n * @param open - Whether the MetaMask UI is open.\n */\n setUiOpen(open: boolean): void {\n this.update((state) => {\n state.isUiOpen = open;\n });\n }\n}\n"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientControllerSelectors = exports.getDefaultClientControllerState = exports.ClientController = void 0;
|
|
4
|
+
var ClientController_1 = require("./ClientController.cjs");
|
|
5
|
+
Object.defineProperty(exports, "ClientController", { enumerable: true, get: function () { return ClientController_1.ClientController; } });
|
|
6
|
+
Object.defineProperty(exports, "getDefaultClientControllerState", { enumerable: true, get: function () { return ClientController_1.getDefaultClientControllerState; } });
|
|
7
|
+
var selectors_1 = require("./selectors.cjs");
|
|
8
|
+
Object.defineProperty(exports, "clientControllerSelectors", { enumerable: true, get: function () { return selectors_1.clientControllerSelectors; } });
|
|
9
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2DAG4B;AAF1B,oHAAA,gBAAgB,OAAA;AAChB,mIAAA,+BAA+B,OAAA;AAEjC,6CAAwD;AAA/C,sHAAA,yBAAyB,OAAA","sourcesContent":["export {\n ClientController,\n getDefaultClientControllerState,\n} from './ClientController';\nexport { clientControllerSelectors } from './selectors';\n\nexport type {\n ClientControllerState,\n ClientControllerOptions,\n ClientControllerGetStateAction,\n ClientControllerActions,\n ClientControllerStateChangeEvent,\n ClientControllerEvents,\n ClientControllerMessenger,\n} from './ClientController';\nexport type { ClientControllerSetUiOpenAction } from './ClientController-method-action-types';\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ClientController, getDefaultClientControllerState, } from "./ClientController.cjs";
|
|
2
|
+
export { clientControllerSelectors } from "./selectors.cjs";
|
|
3
|
+
export type { ClientControllerState, ClientControllerOptions, ClientControllerGetStateAction, ClientControllerActions, ClientControllerStateChangeEvent, ClientControllerEvents, ClientControllerMessenger, } from "./ClientController.cjs";
|
|
4
|
+
export type { ClientControllerSetUiOpenAction } from "./ClientController-method-action-types.cjs";
|
|
5
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;AAC5B,OAAO,EAAE,yBAAyB,EAAE,wBAAoB;AAExD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,sBAAsB,EACtB,yBAAyB,GAC1B,+BAA2B;AAC5B,YAAY,EAAE,+BAA+B,EAAE,mDAA+C"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ClientController, getDefaultClientControllerState, } from "./ClientController.mjs";
|
|
2
|
+
export { clientControllerSelectors } from "./selectors.mjs";
|
|
3
|
+
export type { ClientControllerState, ClientControllerOptions, ClientControllerGetStateAction, ClientControllerActions, ClientControllerStateChangeEvent, ClientControllerEvents, ClientControllerMessenger, } from "./ClientController.mjs";
|
|
4
|
+
export type { ClientControllerSetUiOpenAction } from "./ClientController-method-action-types.mjs";
|
|
5
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;AAC5B,OAAO,EAAE,yBAAyB,EAAE,wBAAoB;AAExD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,sBAAsB,EACtB,yBAAyB,GAC1B,+BAA2B;AAC5B,YAAY,EAAE,+BAA+B,EAAE,mDAA+C"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,EAChC,+BAA2B;AAC5B,OAAO,EAAE,yBAAyB,EAAE,wBAAoB","sourcesContent":["export {\n ClientController,\n getDefaultClientControllerState,\n} from './ClientController';\nexport { clientControllerSelectors } from './selectors';\n\nexport type {\n ClientControllerState,\n ClientControllerOptions,\n ClientControllerGetStateAction,\n ClientControllerActions,\n ClientControllerStateChangeEvent,\n ClientControllerEvents,\n ClientControllerMessenger,\n} from './ClientController';\nexport type { ClientControllerSetUiOpenAction } from './ClientController-method-action-types';\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientControllerSelectors = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Selects whether the UI is currently open.
|
|
6
|
+
*
|
|
7
|
+
* @param state - The ClientController state.
|
|
8
|
+
* @returns True if the UI is open.
|
|
9
|
+
*/
|
|
10
|
+
const selectIsUiOpen = (state) => state.isUiOpen;
|
|
11
|
+
/**
|
|
12
|
+
* Selectors for the ClientController state.
|
|
13
|
+
* These can be used with Redux or directly with controller state.
|
|
14
|
+
*/
|
|
15
|
+
exports.clientControllerSelectors = {
|
|
16
|
+
selectIsUiOpen,
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=selectors.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.cjs","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,KAA4B,EAAW,EAAE,CAC/D,KAAK,CAAC,QAAQ,CAAC;AAEjB;;;GAGG;AACU,QAAA,yBAAyB,GAAG;IACvC,cAAc;CACf,CAAC","sourcesContent":["import type { ClientControllerState } from './ClientController';\n\n/**\n * Selects whether the UI is currently open.\n *\n * @param state - The ClientController state.\n * @returns True if the UI is open.\n */\nconst selectIsUiOpen = (state: ClientControllerState): boolean =>\n state.isUiOpen;\n\n/**\n * Selectors for the ClientController state.\n * These can be used with Redux or directly with controller state.\n */\nexport const clientControllerSelectors = {\n selectIsUiOpen,\n};\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientControllerState } from "./ClientController.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Selectors for the ClientController state.
|
|
4
|
+
* These can be used with Redux or directly with controller state.
|
|
5
|
+
*/
|
|
6
|
+
export declare const clientControllerSelectors: {
|
|
7
|
+
selectIsUiOpen: (state: ClientControllerState) => boolean;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=selectors.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.cts","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,+BAA2B;AAWhE;;;GAGG;AACH,eAAO,MAAM,yBAAyB;4BAPP,qBAAqB,KAAG,OAAO;CAS7D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientControllerState } from "./ClientController.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Selectors for the ClientController state.
|
|
4
|
+
* These can be used with Redux or directly with controller state.
|
|
5
|
+
*/
|
|
6
|
+
export declare const clientControllerSelectors: {
|
|
7
|
+
selectIsUiOpen: (state: ClientControllerState) => boolean;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=selectors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.mts","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,+BAA2B;AAWhE;;;GAGG;AACH,eAAO,MAAM,yBAAyB;4BAPP,qBAAqB,KAAG,OAAO;CAS7D,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Selects whether the UI is currently open.
|
|
3
|
+
*
|
|
4
|
+
* @param state - The ClientController state.
|
|
5
|
+
* @returns True if the UI is open.
|
|
6
|
+
*/
|
|
7
|
+
const selectIsUiOpen = (state) => state.isUiOpen;
|
|
8
|
+
/**
|
|
9
|
+
* Selectors for the ClientController state.
|
|
10
|
+
* These can be used with Redux or directly with controller state.
|
|
11
|
+
*/
|
|
12
|
+
export const clientControllerSelectors = {
|
|
13
|
+
selectIsUiOpen,
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=selectors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.mjs","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,KAA4B,EAAW,EAAE,CAC/D,KAAK,CAAC,QAAQ,CAAC;AAEjB;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,cAAc;CACf,CAAC","sourcesContent":["import type { ClientControllerState } from './ClientController';\n\n/**\n * Selects whether the UI is currently open.\n *\n * @param state - The ClientController state.\n * @returns True if the UI is open.\n */\nconst selectIsUiOpen = (state: ClientControllerState): boolean =>\n state.isUiOpen;\n\n/**\n * Selectors for the ClientController state.\n * These can be used with Redux or directly with controller state.\n */\nexport const clientControllerSelectors = {\n selectIsUiOpen,\n};\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@metamask-previews/client-controller",
|
|
3
|
+
"version": "0.0.0-preview-a196307b6",
|
|
4
|
+
"description": "Client-level state for MetaMask (e.g. whether a UI window is open)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"MetaMask",
|
|
7
|
+
"Ethereum"
|
|
8
|
+
],
|
|
9
|
+
"homepage": "https://github.com/MetaMask/core/tree/main/packages/client-controller#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/MetaMask/core/issues"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/MetaMask/core.git"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"default": "./dist/index.mjs"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/index.d.cts",
|
|
27
|
+
"default": "./dist/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"main": "./dist/index.cjs",
|
|
33
|
+
"types": "./dist/index.d.cts",
|
|
34
|
+
"files": [
|
|
35
|
+
"dist/"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
|
|
39
|
+
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
|
|
40
|
+
"build:docs": "typedoc",
|
|
41
|
+
"changelog:update": "../../scripts/update-changelog.sh @metamask/client-controller",
|
|
42
|
+
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/client-controller",
|
|
43
|
+
"publish:preview": "yarn npm publish --tag preview",
|
|
44
|
+
"since-latest-release": "../../scripts/since-latest-release.sh",
|
|
45
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
|
|
46
|
+
"test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
|
|
47
|
+
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
|
48
|
+
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@metamask/base-controller": "^9.0.0",
|
|
52
|
+
"@metamask/messenger": "^0.3.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@metamask/auto-changelog": "^3.4.4",
|
|
56
|
+
"@ts-bridge/cli": "^0.6.4",
|
|
57
|
+
"@types/jest": "^29.5.14",
|
|
58
|
+
"deepmerge": "^4.2.2",
|
|
59
|
+
"jest": "^29.7.0",
|
|
60
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
61
|
+
"ts-jest": "^29.2.5",
|
|
62
|
+
"typedoc": "^0.25.13",
|
|
63
|
+
"typedoc-plugin-missing-exports": "^2.0.0",
|
|
64
|
+
"typescript": "~5.3.3"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": "^18.18 || >=20"
|
|
68
|
+
},
|
|
69
|
+
"publishConfig": {
|
|
70
|
+
"access": "public",
|
|
71
|
+
"registry": "https://registry.npmjs.org/"
|
|
72
|
+
}
|
|
73
|
+
}
|