tabby-rdp 0.3.4 → 0.4.1
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 +66 -0
- package/README.md +27 -4
- package/dist/accountForm.js +90 -0
- package/dist/accountForm.js.map +1 -0
- package/dist/accounts.js +39 -0
- package/dist/accounts.js.map +1 -0
- package/dist/desktop.service.js +242 -19
- package/dist/desktop.service.js.map +1 -1
- package/dist/desktopForm.js +38 -2
- package/dist/desktopForm.js.map +1 -1
- package/dist/desktops.js +1 -0
- package/dist/desktops.js.map +1 -1
- package/dist/help.js +15 -1
- package/dist/help.js.map +1 -1
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/dist/keyboard.js +3 -3
- package/dist/keyboard.js.map +1 -1
- package/dist/rdcleanpath.js +1 -3
- package/dist/rdcleanpath.js.map +1 -1
- package/dist/rdpProfile.js +33 -5
- package/dist/rdpProfile.js.map +1 -1
- package/dist/settingsPage.js +574 -57
- package/dist/settingsPage.js.map +1 -1
- package/dist/signin.js +163 -21
- package/dist/signin.js.map +1 -1
- package/dist/ui.js +5 -2
- package/dist/ui.js.map +1 -1
- package/dist/updates.js +9 -0
- package/dist/updates.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
Fixes from a review of 0.4.0.
|
|
6
|
+
|
|
7
|
+
**Fixed**
|
|
8
|
+
- **Two desktops saving a password at the same moment** could lose one of them: Tabby's Vault rewrites its whole
|
|
9
|
+
contents per change. The plugin's Vault changes now go one after another.
|
|
10
|
+
- **A saved account took the desktop's old domain:** an account with a plain user name and no domain was signed in with
|
|
11
|
+
the domain the desktop had been given before, a field the form hides once an account is chosen. The account's domain
|
|
12
|
+
(also none) is what is used.
|
|
13
|
+
- **A profile group's account didn't reach profiles reached through an SSH profile** in that host's tab menu; it does
|
|
14
|
+
now, as it did when opening the profile itself.
|
|
15
|
+
- **"Ask for the account" on a new profile from the settings page** could be overridden by the "Remote desktops"
|
|
16
|
+
group's default, since the group was assigned after the editor closed. The profile is in the group before the editor
|
|
17
|
+
opens.
|
|
18
|
+
- **Removing an account** also clears a profile group default that named it, and says so when the password itself
|
|
19
|
+
couldn't be removed. A desktop whose account is gone asks for one, rather than signing in with a login of its own
|
|
20
|
+
saved earlier. A sign-in prompt left open while its account was removed or renamed no longer saves under it.
|
|
21
|
+
- **Editing an account's user name** keeps the old name when the old password couldn't be removed, so the two never
|
|
22
|
+
disagree; a password kept for an account's earlier user name isn't used for the new one. A new account whose password
|
|
23
|
+
couldn't be saved isn't added.
|
|
24
|
+
- **Hotkey collisions** are found among all of Tabby's bindings, per-profile and per-group hotkeys included, and named
|
|
25
|
+
by the profile or group; the note says only one of the two would act.
|
|
26
|
+
- The settings page checks the accounts' passwords one after another, and not at all once the keychain has stopped
|
|
27
|
+
answering, so a Linux keyring that doesn't answer can't hold every keychain worker.
|
|
28
|
+
- Cancelling or finishing **New account…** brings the user name fields back; the Vault lists a saved account's
|
|
29
|
+
password by the account's name, as intended.
|
|
30
|
+
|
|
31
|
+
## 0.4.0
|
|
32
|
+
|
|
33
|
+
**New**
|
|
34
|
+
- **Saved accounts** ([#11](https://github.com/meanaverage/tabby-rdp/issues/11)): a user name and domain under a
|
|
35
|
+
name, with the password kept once, for desktops that share an account. Chosen in a remote desktop profile's
|
|
36
|
+
**Account** field or in the form for a desktop behind an SSH host (**New account…** there adds one), or for a whole
|
|
37
|
+
profile group through the group's defaults. Listed, added, edited and removed in **Settings › Remote Desktop ›
|
|
38
|
+
Accounts**, which names the desktops using each account. A password a server refuses is asked for again and saved
|
|
39
|
+
for every desktop; **Sign in again…** asks anew.
|
|
40
|
+
- **Passwords in Tabby's Vault** when it is enabled, as Tabby keeps SSH passwords: encrypted, and carried by config
|
|
41
|
+
sync. The system keychain as before otherwise, and still read for what was saved before the Vault was turned on.
|
|
42
|
+
- **Configurable shortcuts** ([#15](https://github.com/meanaverage/tabby-rdp/issues/15)): view only, a screenshot,
|
|
43
|
+
Ctrl+Alt+Del, typing into all desktops of a tab, pasting to all of them, the connection status and Disconnect join
|
|
44
|
+
the desktop/console switch as Tabby hotkeys, set on the settings page in the look of Tabby's Hotkeys page (or
|
|
45
|
+
there). A key another hotkey already has is refused, and collisions made elsewhere are shown.
|
|
46
|
+
- **The settings page in tabs** — Getting started, Settings, Overlay, Desktops, Accounts, Troubleshooting — as
|
|
47
|
+
Tabby's Profiles & connections page is, with the settings grouped (Picture, Sound, Keyboard, SSH hosts, Updates)
|
|
48
|
+
and the detail behind ⓘ tooltips. The Desktops tab lists remote desktop profiles as well as desktops behind SSH
|
|
49
|
+
hosts, and adds, edits and removes both; profiles the plugin makes go into a "Remote desktops" group.
|
|
50
|
+
- **A clearer reason when a connection fails** before it is up ("10.3.0.5:3389 did not answer"), in place of
|
|
51
|
+
IronRDP's "general error (code 1)".
|
|
52
|
+
- The **name overlay preview** says which desktop resolution it stands for, and lets you pick one
|
|
53
|
+
([#16](https://github.com/meanaverage/tabby-rdp/issues/16)).
|
|
54
|
+
|
|
55
|
+
**Fixed**
|
|
56
|
+
- **The window could not be moved by its tab bar while a dialog was open**
|
|
57
|
+
([#19](https://github.com/meanaverage/tabby-rdp/issues/19)), the plugin's and Tabby's alike. Each dialog keeps a
|
|
58
|
+
strip the height of the tab bar draggable. Submitted to Tabby as well.
|
|
59
|
+
- **A stale update notice** in a Tabby left open across several releases
|
|
60
|
+
([#17](https://github.com/meanaverage/tabby-rdp/issues/17)): opening the settings page with an update known asks
|
|
61
|
+
npm again.
|
|
62
|
+
- Opening the settings page no longer prompts for the Vault passphrase.
|
|
63
|
+
|
|
64
|
+
**Docs**
|
|
65
|
+
- README: saved accounts, shortcuts, and where passwords are kept. Tabby's Vault page labels the plugin's secrets
|
|
66
|
+
generically until Tabby ships [#11765](https://github.com/Eugeny/tabby/pull/11765)
|
|
67
|
+
([#18](https://github.com/meanaverage/tabby-rdp/issues/18)).
|
|
68
|
+
|
|
3
69
|
## 0.3.4
|
|
4
70
|
|
|
5
71
|
**Fixed**
|
package/README.md
CHANGED
|
@@ -40,8 +40,8 @@ nothing is opened on the network, and nothing has to be installed on the remote
|
|
|
40
40
|
- **`desk`:** type `desk` in the console and the same shell, with its history and running programs, moves into a
|
|
41
41
|
terminal on the desktop.
|
|
42
42
|
|
|
43
|
-
Everything is in **Settings › Remote Desktop
|
|
44
|
-
the desktops and certificates the plugin keeps, and troubleshooting.
|
|
43
|
+
Everything is in **Settings › Remote Desktop**, in tabs: getting started and the shortcuts, the settings, the name
|
|
44
|
+
overlay, the desktops and certificates the plugin keeps, saved accounts, and troubleshooting.
|
|
45
45
|
|
|
46
46
|
The remote desktop itself is [IronRDP](https://github.com/Devolutions/IronRDP)'s web client, running inside Tabby.
|
|
47
47
|
Making it work with GNOME took fixes in IronRDP, which we contribute upstream ([below](#built-on-ironrdp)).
|
|
@@ -53,6 +53,7 @@ Making it work with GNOME took fixes in IronRDP, which we contribute upstream ([
|
|
|
53
53
|
- [Features](#features)
|
|
54
54
|
- [Windows and other desktops behind a host](#windows-and-other-desktops-behind-a-host)
|
|
55
55
|
- [Remote desktop profiles](#remote-desktop-profiles)
|
|
56
|
+
- [Saved accounts](#saved-accounts)
|
|
56
57
|
- [Several desktops in one tab](#several-desktops-in-one-tab)
|
|
57
58
|
- [VMs on a host](#vms-on-a-host)
|
|
58
59
|
- [desk: the console on the desktop](#desk-the-console-on-the-desktop)
|
|
@@ -120,7 +121,8 @@ connecting again.
|
|
|
120
121
|
| **Screenshots** | **Save a screenshot** in the desktop's menus saves the remote screen at its full resolution as a PNG in Downloads, and copies it to the clipboard. |
|
|
121
122
|
| **Connection status** | Optionally, a small line in the corner of the desktop with the throughput each way, frames per second, the SSH round trip, and how it is connected (desktop, host, resolution, graphics mode, sharpness). |
|
|
122
123
|
| **Reconnecting** | After sleep or a network change, the desktop reconnects by itself once the connection is back. |
|
|
123
|
-
| **Sign-in** | GNOME desktops need none: the plugin manages their credentials. Windows and xrdp desktops ask for the account once and can remember it in the system keychain; **Sign in again…** in the menu replaces it. |
|
|
124
|
+
| **Sign-in** | GNOME desktops need none: the plugin manages their credentials. Windows and xrdp desktops ask for the account once and can remember it, in Tabby's Vault when that is on and in the system keychain otherwise; **Sign in again…** in the menu replaces it. Desktops that share an account can use a [saved account](#saved-accounts), whose password is kept once. |
|
|
125
|
+
| **Shortcuts** | Switching between the desktop and the console, view only, a screenshot, Ctrl+Alt+Del, typing into or pasting to all desktops of a tab, the connection status and Disconnect each have a hotkey, set on the settings page or in Tabby's Hotkeys. They work while the desktop has the keyboard; a key another hotkey has is refused. |
|
|
124
126
|
| **Certificates** | GNOME desktops accept only the certificate the plugin made for them. Windows and xrdp desktops remember theirs on first use and ask before accepting a different one. |
|
|
125
127
|
|
|
126
128
|
<p align="center"><img src="docs/images/files.png" width="760" alt="A file copied on the remote desktop, offered for saving"></p>
|
|
@@ -217,6 +219,25 @@ A direct connection is a plain TCP connection from this computer, encrypted with
|
|
|
217
219
|
server's certificate is remembered on the first connection and checked on every later one, as for desktops behind a
|
|
218
220
|
host (above).
|
|
219
221
|
|
|
222
|
+
## Saved accounts
|
|
223
|
+
|
|
224
|
+
Several desktops often share one account: a domain admin, a lab user. A saved account keeps that user name (and
|
|
225
|
+
domain) under a name, with its password stored once, so when the password changes it is entered once for all of them.
|
|
226
|
+
|
|
227
|
+
**Settings › Remote Desktop › Accounts** lists them, with the desktops that use each one (click a name to open its
|
|
228
|
+
settings), and adds, edits and removes them. A desktop picks its account in its profile's **Account** field, or in the
|
|
229
|
+
form that adds a desktop behind an SSH host; **New account…** there adds one on the spot. A profile group's defaults
|
|
230
|
+
for **Remote desktop (RDP)** can pick an account for every profile in the group (**Profiles & connections**, the group's
|
|
231
|
+
menu), which is how to give a whole group of servers one sign-in.
|
|
232
|
+
|
|
233
|
+
Signing in with a saved account that has no password yet, or whose password a server refused, asks for it, and the
|
|
234
|
+
form saves what you enter as the account's new password for every desktop. A refused password is not dropped by
|
|
235
|
+
itself: one server refusing it doesn't make it wrong for the others. **Sign in again…** on such a desktop asks anew.
|
|
236
|
+
|
|
237
|
+
The accounts' names and user names are in Tabby's config (`remoteDesktop.accounts`); the passwords are in Tabby's
|
|
238
|
+
Vault when it is enabled (encrypted, and carried by Tabby's config sync), else in the system keychain. Removing an
|
|
239
|
+
account removes its password and sets its desktops back to asking.
|
|
240
|
+
|
|
220
241
|
## Several desktops in one tab
|
|
221
242
|
|
|
222
243
|
Split a tab (Tabby's **Split** in the tab's menu, or drag one tab onto another) and each pane can show a desktop: one
|
|
@@ -285,12 +306,14 @@ They are stored in Tabby's config under `remoteDesktop`:
|
|
|
285
306
|
| Microphone (`microphone`) | Off | Send your microphone while an app on the remote desktop records. Applies on the next connection. |
|
|
286
307
|
| Show connection status (`connectionStatus`) | Off | The indicator in the desktop's corner; fades when the pointer comes near. |
|
|
287
308
|
| Mac shortcuts (`macShortcuts`) | On | macOS. Off: ⌘ is the Windows key. |
|
|
309
|
+
| Shortcuts (`hotkeys.remote-desktop-*`) | ⌘⇧G / Ctrl+Shift+G for the switch; the rest unbound | Tabby's hotkeys: the switch between desktop and console, view only, screenshot, Ctrl+Alt+Del, type into all, paste to all, connection status, disconnect. Changed on the settings page (Getting started › Shortcuts) or in Settings › Hotkeys. |
|
|
310
|
+
| Saved accounts (`accounts`) | None | `[{ id, name, username, domain }]`; see [Saved accounts](#saved-accounts). The passwords are in the Vault (encrypted, part of the config) or the keychain, never in plaintext in the config. |
|
|
288
311
|
| Bring the console along with `desk` (`desk`) | Off | Installs `desk` and a login line on each machine you open a desktop on; applies on the next connection there. |
|
|
289
312
|
| Session backend (`sessionBackend`) | `native` | For `desk`: `native` (trd-pty) or `tmux`. Config file only. |
|
|
290
313
|
| Find virtual machines on SSH hosts (`discoverVMs`) | On | Lists a host's libvirt VMs with a desktop in its menu ([VMs on a host](#vms-on-a-host)). |
|
|
291
314
|
| Shut down VMs it started (`shutDownIdle`) | Never | 5, 15 or 60: minutes without a desktop open after which a VM the plugin started is shut down again ([VMs on a host](#vms-on-a-host)). |
|
|
292
315
|
| Tell me about new versions (`checkUpdates`) | On | Once a day, asks npm for the latest tabby-rdp (nothing else is sent), and says so in a note, the menus and the settings page when there's a newer one: Tabby itself shows plugin upgrades only on its Plugins page. |
|
|
293
|
-
| Desktop name overlay (`osd`) | When it helps | `show` (`auto`, `always`, `off`), `font`, `size`, `position`, `color` (empty: white) and `seconds`; the settings page previews it. |
|
|
316
|
+
| Desktop name overlay (`osd`) | When it helps | `show` (`auto`, `always`, `off`), `font`, `size`, `position`, `color` (empty: white) and `seconds`; the settings page previews it, at a resolution you pick. |
|
|
294
317
|
|
|
295
318
|
## Requirements
|
|
296
319
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.STYLE = exports.NEW_ACCOUNT = void 0;
|
|
4
|
+
exports.newAccountOption = newAccountOption;
|
|
5
|
+
exports.NEW_ACCOUNT = '__new__';
|
|
6
|
+
exports.STYLE = `
|
|
7
|
+
.trd-new-account { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; padding: 10px; border-radius: 6px;
|
|
8
|
+
border: 1px solid rgba(128, 128, 128, 0.35); }
|
|
9
|
+
.trd-new-account .trd-new-account-error { grid-column: 1 / -1; color: #f08080; font-size: 12px; }
|
|
10
|
+
.trd-new-account .trd-new-account-error:empty { display: none; }
|
|
11
|
+
.trd-new-account .trd-new-account-buttons { grid-column: 1 / -1; display: flex; gap: 8px; justify-content: flex-end; }
|
|
12
|
+
`;
|
|
13
|
+
/**
|
|
14
|
+
* Wires an account `<select>` that ends with "New account…": choosing it opens the form under the select; "Add" hands
|
|
15
|
+
* the fields to `save`, which returns the saved account, and the select then offers and shows it. `onChange` is told
|
|
16
|
+
* the chosen id ('' for none) whenever it changes, the new account included.
|
|
17
|
+
*/
|
|
18
|
+
function newAccountOption(select, label, save, onChange) {
|
|
19
|
+
select.append(new Option('New account…', exports.NEW_ACCOUNT));
|
|
20
|
+
let last = select.value;
|
|
21
|
+
let form = null;
|
|
22
|
+
const close = () => {
|
|
23
|
+
form?.remove();
|
|
24
|
+
form = null;
|
|
25
|
+
};
|
|
26
|
+
select.addEventListener('change', () => {
|
|
27
|
+
if (select.value !== exports.NEW_ACCOUNT) {
|
|
28
|
+
close();
|
|
29
|
+
last = select.value;
|
|
30
|
+
onChange(select.value);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (form) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
form = document.createElement('form');
|
|
37
|
+
form.className = 'trd-new-account';
|
|
38
|
+
form.autocomplete = 'off';
|
|
39
|
+
form.innerHTML = `
|
|
40
|
+
<input class="form-control form-control-sm" name="name" placeholder="Name, e.g. Domain A admin" spellcheck="false">
|
|
41
|
+
<input class="form-control form-control-sm" name="username" placeholder="User name, or DOMAIN\\user" spellcheck="false">
|
|
42
|
+
<input class="form-control form-control-sm" name="domain" placeholder="Domain (optional)" spellcheck="false">
|
|
43
|
+
<input class="form-control form-control-sm" name="password" type="password" autocomplete="new-password" placeholder="Password (optional; asked on the first connection)">
|
|
44
|
+
<div class="trd-new-account-error"></div>
|
|
45
|
+
<div class="trd-new-account-buttons">
|
|
46
|
+
<button type="button" class="btn btn-secondary btn-sm" name="cancel">Cancel</button>
|
|
47
|
+
<button type="submit" class="btn btn-primary btn-sm">Add account</button>
|
|
48
|
+
</div>`;
|
|
49
|
+
const field = (name) => form.querySelector(`[name="${name}"]`);
|
|
50
|
+
const error = form.querySelector('.trd-new-account-error');
|
|
51
|
+
// Keys typed in it are its own (the forms around it act on Enter and Escape).
|
|
52
|
+
form.addEventListener('keydown', event => {
|
|
53
|
+
event.stopPropagation();
|
|
54
|
+
if (event.key === 'Escape') {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
field('cancel').click();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
field('cancel').addEventListener('click', () => {
|
|
60
|
+
close();
|
|
61
|
+
select.value = last;
|
|
62
|
+
// As a choice made by hand: the form around it follows (its user name fields show again).
|
|
63
|
+
select.dispatchEvent(new Event('change'));
|
|
64
|
+
});
|
|
65
|
+
form.addEventListener('submit', async (event) => {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
event.stopPropagation();
|
|
68
|
+
const username = field('username').value.trim();
|
|
69
|
+
if (!username) {
|
|
70
|
+
error.textContent = 'Give it a user name.';
|
|
71
|
+
field('username').focus();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const account = await save({ name: field('name').value.trim(), username, domain: field('domain').value.trim(), password: field('password').value });
|
|
76
|
+
const option = new Option(label(account), account.id);
|
|
77
|
+
select.insertBefore(option, select.querySelector(`option[value="${exports.NEW_ACCOUNT}"]`));
|
|
78
|
+
close();
|
|
79
|
+
select.value = account.id;
|
|
80
|
+
select.dispatchEvent(new Event('change'));
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
error.textContent = `Couldn't save it: ${e?.message ?? e}`;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
select.insertAdjacentElement('afterend', form);
|
|
87
|
+
field('name').focus();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=accountForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountForm.js","sourceRoot":"","sources":["../src/accountForm.ts"],"names":[],"mappings":"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"}
|
package/dist/accounts.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.accountsOf = accountsOf;
|
|
4
|
+
exports.newAccountId = newAccountId;
|
|
5
|
+
exports.signInName = signInName;
|
|
6
|
+
exports.accountKey = accountKey;
|
|
7
|
+
/** The usable entries of `remoteDesktop.accounts` (hand-written ones may lack fields). */
|
|
8
|
+
function accountsOf(store) {
|
|
9
|
+
const list = Array.isArray(store?.accounts) ? store.accounts : [];
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
return list.flatMap((a) => {
|
|
12
|
+
const id = typeof a?.id === 'string' ? a.id.trim() : '';
|
|
13
|
+
const username = typeof a?.username === 'string' ? a.username.trim() : '';
|
|
14
|
+
if (!/^[A-Za-z0-9_-]+$/.test(id) || !username || seen.has(id)) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
seen.add(id);
|
|
18
|
+
const domain = typeof a.domain === 'string' && a.domain.trim() ? a.domain.trim() : undefined;
|
|
19
|
+
return [{ id, name: typeof a.name === 'string' && a.name.trim() ? a.name.trim() : signInName({ username, domain }), username, ...domain ? { domain } : {} }];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** A new account's id: nothing in it but that it is unused. */
|
|
23
|
+
function newAccountId(taken) {
|
|
24
|
+
for (;;) {
|
|
25
|
+
const id = Math.random().toString(36).slice(2, 10).padEnd(8, '0');
|
|
26
|
+
if (!taken.some(a => a.id === id)) {
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** What the account signs in as: DOMAIN\user, or the user name as typed when it names its domain itself. */
|
|
32
|
+
function signInName(account) {
|
|
33
|
+
return account.domain && !/[\\@]/.test(account.username) ? `${account.domain}\\${account.username}` : account.username;
|
|
34
|
+
}
|
|
35
|
+
/** Where the keychain keeps an account's password (next to the desktops' own entries, which are session keys). */
|
|
36
|
+
function accountKey(id) {
|
|
37
|
+
return `account#${id}`;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../src/accounts.ts"],"names":[],"mappings":";;AAoBA,gCAaC;AAGD,oCAOC;AAGD,gCAEC;AAGD,gCAEC;AAlCD,0FAA0F;AAC1F,SAAgB,UAAU,CAAE,KAAU;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IACjE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAM,EAAkB,EAAE;QAC3C,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACzE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAA;QACb,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QAC5F,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAChK,CAAC,CAAC,CAAA;AACN,CAAC;AAED,+DAA+D;AAC/D,SAAgB,YAAY,CAAE,KAAqB;IAC/C,SAAS,CAAC;QACN,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QACjE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAA;QACb,CAAC;IACL,CAAC;AACL,CAAC;AAED,4GAA4G;AAC5G,SAAgB,UAAU,CAAE,OAAkD;IAC1E,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAA;AAC1H,CAAC;AAED,kHAAkH;AAClH,SAAgB,UAAU,CAAE,EAAU;IAClC,OAAO,WAAW,EAAE,EAAE,CAAA;AAC1B,CAAC"}
|