@domicile-desktop/component-library 0.0.0-alpha-56dd6c187f4e → 0.0.0-alpha-2fe5852c4a77
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/README.md +1 -1
- package/package.json +3 -3
- package/src/AppChooser/AppChooser.tsx +4 -4
- package/src/AppChooser/app-choices.ts +5 -4
- package/src/AppChooser/useDescribedChoices.ts +4 -4
- package/src/FilePicker/folders.ts +18 -11
- package/src/FilePicker/list-directory.ts +13 -9
- package/src/PortalDialogs/AccountDialog.tsx +2 -2
- package/src/PortalDialogs/AppChooserDialog.tsx +4 -4
- package/src/PortalDialogs/PortalDialogs.tsx +29 -18
- package/src/PortalDialogs/WallpaperDialog.tsx +2 -2
- package/src/useApps/useApps.ts +4 -4
- package/src/usePictureUrl/usePictureUrl.ts +5 -5
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Each export is `@domicile-desktop/component-library/<name>`.
|
|
|
52
52
|
| `ThemeProvider` | Light/dark theme state. Sets `data-theme` on `<html>`. |
|
|
53
53
|
| `ThemeSwitch` | Button that flips the theme. |
|
|
54
54
|
| `useApps` | Hook: names and icons of applications by app id, from their desktop entries. |
|
|
55
|
-
| `usePictureUrl` | Hook: a URL an `<img>` can show for a file read through
|
|
55
|
+
| `usePictureUrl` | Hook: a URL an `<img>` can show for a file read through `domicile.files`. |
|
|
56
56
|
| `usePortalWallpaper` | Hook: the pictures applications set through the Wallpaper portal, as paths. |
|
|
57
57
|
| `theme-core`, `theme-source`, `standalone-theme-source` | Theme types and sources. Use the standalone source where there is no compositor, such as Storybook. |
|
|
58
58
|
| `control-sizes` | `Size` type and `SIZES` array for sized controls. |
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@base-ui/react": "^1.8.0",
|
|
4
4
|
"@cprussin/option-result": "^2.0.1",
|
|
5
|
-
"@domicile-desktop/sdk": "0.0.0-alpha-
|
|
6
|
-
"@domicile-desktop/system-apps": "0.0.0-alpha-
|
|
5
|
+
"@domicile-desktop/sdk": "0.0.0-alpha-2fe5852c4a77",
|
|
6
|
+
"@domicile-desktop/system-apps": "0.0.0-alpha-2fe5852c4a77",
|
|
7
7
|
"@pandacss/dev": "^1.12.1",
|
|
8
8
|
"@phosphor-icons/react": "^2.1.10"
|
|
9
9
|
},
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"test:unit": "bun test"
|
|
118
118
|
},
|
|
119
119
|
"type": "module",
|
|
120
|
-
"version": "0.0.0-alpha-
|
|
120
|
+
"version": "0.0.0-alpha-2fe5852c4a77"
|
|
121
121
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AppsDesktop } from "@domicile-desktop/system-apps/apps-desktop";
|
|
2
2
|
import type { DescribedApp } from "@domicile-desktop/system-apps/describe-apps";
|
|
3
3
|
import { AppWindowIcon } from "@phosphor-icons/react/dist/ssr/AppWindow";
|
|
4
4
|
import { useId, useState } from "react";
|
|
@@ -35,7 +35,7 @@ type Props = {
|
|
|
35
35
|
opened: string;
|
|
36
36
|
screen: string | undefined;
|
|
37
37
|
/** Where the applications' desktop entries are read. */
|
|
38
|
-
|
|
38
|
+
domicile: AppsDesktop;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -54,10 +54,10 @@ export const AppChooser = ({
|
|
|
54
54
|
onChoose,
|
|
55
55
|
opened,
|
|
56
56
|
screen,
|
|
57
|
-
|
|
57
|
+
domicile,
|
|
58
58
|
}: Props) => {
|
|
59
59
|
const listId = useId();
|
|
60
|
-
const described = useDescribedChoices(
|
|
60
|
+
const described = useDescribedChoices(domicile, choices, contentType);
|
|
61
61
|
const [picked, setPicked] = useState<string | undefined>();
|
|
62
62
|
const apps = described?.apps ?? [];
|
|
63
63
|
const first =
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import type { Result } from "@cprussin/option-result";
|
|
5
5
|
import { Ok } from "@cprussin/option-result";
|
|
6
|
-
import type {
|
|
6
|
+
import type { SystemError } from "@domicile-desktop/sdk/system";
|
|
7
|
+
import type { AppsDesktop } from "@domicile-desktop/system-apps/apps-desktop";
|
|
7
8
|
import type { DescribedApp } from "@domicile-desktop/system-apps/describe-apps";
|
|
8
9
|
import { describeApps } from "@domicile-desktop/system-apps/describe-apps";
|
|
9
10
|
import { defaultApps } from "@domicile-desktop/system-apps/mime-apps";
|
|
@@ -20,15 +21,15 @@ export type DescribedChoices = {
|
|
|
20
21
|
* when it is `undefined`.
|
|
21
22
|
*/
|
|
22
23
|
export const describeChoices = async (
|
|
23
|
-
|
|
24
|
+
domicile: AppsDesktop,
|
|
24
25
|
choices: readonly string[],
|
|
25
26
|
contentType: string | undefined,
|
|
26
27
|
): Promise<Result<DescribedChoices, SystemError>> => {
|
|
27
28
|
const [apps, defaults] = await Promise.all([
|
|
28
|
-
describeApps(
|
|
29
|
+
describeApps(domicile, choices),
|
|
29
30
|
contentType === undefined
|
|
30
31
|
? Ok<string[], SystemError>([])
|
|
31
|
-
: defaultApps(
|
|
32
|
+
: defaultApps(domicile, contentType),
|
|
32
33
|
]);
|
|
33
34
|
return apps.andThen((found) =>
|
|
34
35
|
defaults.map((ids) => ({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AppsDesktop } from "@domicile-desktop/system-apps/apps-desktop";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
|
|
4
4
|
import type { DescribedChoices } from "./app-choices";
|
|
@@ -10,7 +10,7 @@ import { describeChoices } from "./app-choices";
|
|
|
10
10
|
* the choices have moved past.
|
|
11
11
|
*/
|
|
12
12
|
export const useDescribedChoices = (
|
|
13
|
-
|
|
13
|
+
domicile: AppsDesktop,
|
|
14
14
|
choices: readonly string[],
|
|
15
15
|
contentType: string | undefined,
|
|
16
16
|
): DescribedChoices | undefined => {
|
|
@@ -20,7 +20,7 @@ export const useDescribedChoices = (
|
|
|
20
20
|
|
|
21
21
|
useEffect(() => {
|
|
22
22
|
let current = true;
|
|
23
|
-
describeChoices(
|
|
23
|
+
describeChoices(domicile, key === "" ? [] : key.split("\n"), contentType)
|
|
24
24
|
.then((result) => {
|
|
25
25
|
result.match({
|
|
26
26
|
Err: (error) => {
|
|
@@ -42,7 +42,7 @@ export const useDescribedChoices = (
|
|
|
42
42
|
return () => {
|
|
43
43
|
current = false;
|
|
44
44
|
};
|
|
45
|
-
}, [
|
|
45
|
+
}, [domicile, key, contentType]);
|
|
46
46
|
|
|
47
47
|
return described;
|
|
48
48
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
// The folders `FilePicker` browses, and the
|
|
1
|
+
// The folders `FilePicker` browses, and the desktop's file calls behind them.
|
|
2
2
|
|
|
3
3
|
import type { Result } from "@cprussin/option-result";
|
|
4
|
-
import type {
|
|
4
|
+
import type { Files } from "@domicile-desktop/sdk/desktop/files";
|
|
5
|
+
import type { SystemError } from "@domicile-desktop/sdk/system";
|
|
5
6
|
|
|
6
7
|
import { listDirectory } from "./list-directory";
|
|
7
8
|
|
|
@@ -21,11 +22,17 @@ export type Folders = {
|
|
|
21
22
|
watch: (path: string, changed: () => void) => () => void;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
/** {@link
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
/** The calls {@link desktopFolders} makes. */
|
|
26
|
+
export type FolderFiles = Pick<
|
|
27
|
+
Files,
|
|
28
|
+
"createDir" | "readDir" | "stat" | "watch"
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
/** {@link Folders} through the desktop's files. */
|
|
32
|
+
export const desktopFolders = (files: FolderFiles): Folders => ({
|
|
33
|
+
create: (path) => files.createDir(path),
|
|
34
|
+
list: (path) => listDirectory(files, path),
|
|
35
|
+
watch: (path, changed) => watchDirectory(files, path, changed),
|
|
29
36
|
});
|
|
30
37
|
|
|
31
38
|
/**
|
|
@@ -34,7 +41,7 @@ export const systemFolders = (system: System): Folders => ({
|
|
|
34
41
|
* works, without live updates.
|
|
35
42
|
*/
|
|
36
43
|
const watchDirectory = (
|
|
37
|
-
|
|
44
|
+
files: FolderFiles,
|
|
38
45
|
path: string,
|
|
39
46
|
changed: () => void,
|
|
40
47
|
): (() => void) => {
|
|
@@ -42,7 +49,7 @@ const watchDirectory = (
|
|
|
42
49
|
stop: undefined,
|
|
43
50
|
stopped: false,
|
|
44
51
|
};
|
|
45
|
-
follow(
|
|
52
|
+
follow(files, path, watching, changed).catch((error: unknown) => {
|
|
46
53
|
// biome-ignore lint/suspicious/noConsole: reports a watch that broke
|
|
47
54
|
console.error("The file picker's directory watch broke", error);
|
|
48
55
|
});
|
|
@@ -56,12 +63,12 @@ type Watching = { stop: (() => void) | undefined; stopped: boolean };
|
|
|
56
63
|
|
|
57
64
|
/** Starts the watch, then calls `changed` for each item until it ends. */
|
|
58
65
|
const follow = async (
|
|
59
|
-
|
|
66
|
+
files: FolderFiles,
|
|
60
67
|
path: string,
|
|
61
68
|
watching: Watching,
|
|
62
69
|
changed: () => void,
|
|
63
70
|
): Promise<void> => {
|
|
64
|
-
const watch = (await
|
|
71
|
+
const watch = (await files.watch(path)).match({
|
|
65
72
|
Err: (error) => {
|
|
66
73
|
// biome-ignore lint/suspicious/noConsole: reports a watch that could not start
|
|
67
74
|
console.error("The file picker could not watch a directory", error);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
// A directory's entries for the file picker, read through the
|
|
1
|
+
// A directory's entries for the file picker, read through the desktop's files.
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { Files } from "@domicile-desktop/sdk/desktop/files";
|
|
4
|
+
import type { DirEntry } from "@domicile-desktop/sdk/system";
|
|
4
5
|
import { FileType } from "@domicile-desktop/sdk/system";
|
|
5
6
|
|
|
7
|
+
/** The calls a listing makes. */
|
|
8
|
+
export type ListedFiles = Pick<Files, "readDir" | "stat">;
|
|
9
|
+
|
|
6
10
|
/**
|
|
7
11
|
* The entries of the directory at absolute `path`, as `FileRequest.list`
|
|
8
12
|
* wants them: subdirectory names, and links to directories, end in `/`.
|
|
@@ -10,30 +14,30 @@ import { FileType } from "@domicile-desktop/sdk/system";
|
|
|
10
14
|
* read.
|
|
11
15
|
*/
|
|
12
16
|
export const listDirectory = async (
|
|
13
|
-
|
|
17
|
+
files: ListedFiles,
|
|
14
18
|
path: string,
|
|
15
19
|
): Promise<string[]> =>
|
|
16
|
-
(await
|
|
20
|
+
(await files.readDir(path)).match({
|
|
17
21
|
Err: (error) => {
|
|
18
22
|
throw new DOMException(error.message, "NotReadableError");
|
|
19
23
|
},
|
|
20
24
|
Ok: (entries) =>
|
|
21
|
-
Promise.all(entries.map((entry) => shownName(
|
|
25
|
+
Promise.all(entries.map((entry) => shownName(files, path, entry))),
|
|
22
26
|
});
|
|
23
27
|
|
|
24
28
|
const shownName = async (
|
|
25
|
-
|
|
29
|
+
files: ListedFiles,
|
|
26
30
|
directory: string,
|
|
27
31
|
{ fileType, name }: DirEntry,
|
|
28
32
|
): Promise<string> =>
|
|
29
|
-
(await isDirectory(
|
|
33
|
+
(await isDirectory(files, directory, name, fileType)) ? `${name}/` : name;
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Whether the entry is a directory, following a link. A dangling link counts
|
|
33
37
|
* as a file: the picker lists it, and picking it fails where it is read.
|
|
34
38
|
*/
|
|
35
39
|
const isDirectory = async (
|
|
36
|
-
|
|
40
|
+
files: ListedFiles,
|
|
37
41
|
directory: string,
|
|
38
42
|
name: string,
|
|
39
43
|
fileType: FileType,
|
|
@@ -43,7 +47,7 @@ const isDirectory = async (
|
|
|
43
47
|
return true;
|
|
44
48
|
}
|
|
45
49
|
case FileType.Symlink: {
|
|
46
|
-
const target = await
|
|
50
|
+
const target = await files.stat(childOf(directory, name));
|
|
47
51
|
return target.match({
|
|
48
52
|
Err: () => false,
|
|
49
53
|
Ok: (stat) => stat.fileType === FileType.Directory,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { Files } from "@domicile-desktop/sdk/desktop/files";
|
|
1
2
|
import type { AccountBody, PortalAnswer } from "@domicile-desktop/sdk/portal";
|
|
2
3
|
import { PortalAnswer as Answer } from "@domicile-desktop/sdk/portal";
|
|
3
|
-
import type { System } from "@domicile-desktop/sdk/system";
|
|
4
4
|
import { css } from "../../styled-system/css";
|
|
5
5
|
import { hstack } from "../../styled-system/patterns";
|
|
6
6
|
import { Button } from "../Button/Button";
|
|
@@ -13,7 +13,7 @@ type Props = {
|
|
|
13
13
|
asker: string;
|
|
14
14
|
body: AccountBody;
|
|
15
15
|
/** Reads the user's picture. */
|
|
16
|
-
files: Pick<
|
|
16
|
+
files: Pick<Files, "read">;
|
|
17
17
|
screen: string | undefined;
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
PortalAnswer,
|
|
4
4
|
} from "@domicile-desktop/sdk/portal";
|
|
5
5
|
import { PortalAnswer as Answer } from "@domicile-desktop/sdk/portal";
|
|
6
|
-
import type {
|
|
6
|
+
import type { AppsDesktop } from "@domicile-desktop/system-apps/apps-desktop";
|
|
7
7
|
import { AppChooser } from "../AppChooser/AppChooser";
|
|
8
8
|
|
|
9
9
|
type Props = {
|
|
@@ -13,7 +13,7 @@ type Props = {
|
|
|
13
13
|
body: AppChooserBody;
|
|
14
14
|
screen: string | undefined;
|
|
15
15
|
/** Where the applications' desktop entries are read. */
|
|
16
|
-
|
|
16
|
+
domicile: AppsDesktop;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
/** The AppChooser portal's {@link AppChooser}. Dismissing it cancels. */
|
|
@@ -22,13 +22,14 @@ export const AppChooserDialog = ({
|
|
|
22
22
|
asker,
|
|
23
23
|
body,
|
|
24
24
|
screen,
|
|
25
|
-
|
|
25
|
+
domicile,
|
|
26
26
|
}: Props) => (
|
|
27
27
|
<AppChooser
|
|
28
28
|
address={body.filename === undefined ? body.uri : undefined}
|
|
29
29
|
asker={asker}
|
|
30
30
|
choices={body.choices}
|
|
31
31
|
contentType={body.contentType}
|
|
32
|
+
domicile={domicile}
|
|
32
33
|
lastChoice={body.lastChoice}
|
|
33
34
|
onCancel={() => {
|
|
34
35
|
answer(Answer.Canceled());
|
|
@@ -38,7 +39,6 @@ export const AppChooserDialog = ({
|
|
|
38
39
|
}}
|
|
39
40
|
opened={openedOf(body)}
|
|
40
41
|
screen={screen}
|
|
41
|
-
system={system}
|
|
42
42
|
/>
|
|
43
43
|
);
|
|
44
44
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { CastClaim } from "@domicile-desktop/sdk/cast";
|
|
2
2
|
import { CastClaimKind } from "@domicile-desktop/sdk/cast";
|
|
3
|
+
import type { Capture } from "@domicile-desktop/sdk/desktop/capture";
|
|
4
|
+
import type { Dbus } from "@domicile-desktop/sdk/desktop/dbus";
|
|
5
|
+
import { desktop } from "@domicile-desktop/sdk/desktop/desktop";
|
|
6
|
+
import type { Files } from "@domicile-desktop/sdk/desktop/files";
|
|
7
|
+
import type { Processes } from "@domicile-desktop/sdk/desktop/processes";
|
|
3
8
|
import type {
|
|
4
9
|
DomicileBrowserWindow,
|
|
5
10
|
DomicileHost,
|
|
@@ -18,11 +23,9 @@ import {
|
|
|
18
23
|
watchCapturing,
|
|
19
24
|
watchPortalRequests,
|
|
20
25
|
} from "@domicile-desktop/sdk/portal";
|
|
21
|
-
import type { System, SystemHost } from "@domicile-desktop/sdk/system";
|
|
22
|
-
import { system } from "@domicile-desktop/sdk/system";
|
|
23
26
|
import { memo, useEffect, useMemo, useState } from "react";
|
|
24
27
|
import type { Folders } from "../FilePicker/folders";
|
|
25
|
-
import {
|
|
28
|
+
import { desktopFolders } from "../FilePicker/folders";
|
|
26
29
|
import type { App } from "../useApps/useApps";
|
|
27
30
|
import { useApps } from "../useApps/useApps";
|
|
28
31
|
import { AccessDialog } from "./AccessDialog";
|
|
@@ -44,12 +47,20 @@ import { UsbDialog } from "./UsbDialog";
|
|
|
44
47
|
import { useCastClaims } from "./useCastClaims";
|
|
45
48
|
import { WallpaperDialog } from "./WallpaperDialog";
|
|
46
49
|
|
|
50
|
+
/** What the dialogs read and draw through. */
|
|
51
|
+
export type DialogDesktop = {
|
|
52
|
+
readonly capture: Pick<Capture, "preview">;
|
|
53
|
+
readonly dbus: Pick<Dbus, "call">;
|
|
54
|
+
readonly files: Omit<Files, "search">;
|
|
55
|
+
readonly processes: Pick<Processes, "run" | "spawn">;
|
|
56
|
+
};
|
|
57
|
+
|
|
47
58
|
/** No shell chords; one array, so the default is stable across renders. */
|
|
48
59
|
const NONE: readonly string[] = [];
|
|
49
60
|
|
|
50
61
|
type Props = {
|
|
51
62
|
/** The desktop `Shell` is handed. */
|
|
52
|
-
host: GlobalShortcutsHost &
|
|
63
|
+
host: GlobalShortcutsHost & DomicileHost;
|
|
53
64
|
/**
|
|
54
65
|
* The display to show a dialog on when it has no parent window. Needs a
|
|
55
66
|
* `DisplayProvider`; without it, a dialog is centered on the whole page.
|
|
@@ -66,8 +77,8 @@ type Props = {
|
|
|
66
77
|
* boxes. See {@link drawnWindows}.
|
|
67
78
|
*/
|
|
68
79
|
shownWindows?: (() => readonly ShownWindow[]) | undefined;
|
|
69
|
-
/** How dialogs
|
|
70
|
-
|
|
80
|
+
/** How dialogs reach the desktop, for tests. */
|
|
81
|
+
desktopOf?: ((host: DomicileHost) => DialogDesktop) | undefined;
|
|
71
82
|
/**
|
|
72
83
|
* The display showing the `<app>` with this id, for a dialog modal over
|
|
73
84
|
* it. `undefined` uses `screen`.
|
|
@@ -94,13 +105,13 @@ export const PortalDialogs = memo(
|
|
|
94
105
|
screenOf,
|
|
95
106
|
shellChords = NONE,
|
|
96
107
|
shownWindows = drawnOnPage,
|
|
97
|
-
|
|
108
|
+
desktopOf = desktop,
|
|
98
109
|
}: Props) => {
|
|
99
110
|
const [requests, setRequests] = useState<readonly PortalRequest[]>([]);
|
|
100
|
-
const
|
|
101
|
-
const folders = useMemo(() =>
|
|
111
|
+
const domicile = useMemo(() => desktopOf(host), [desktopOf, host]);
|
|
112
|
+
const folders = useMemo(() => desktopFolders(domicile.files), [domicile]);
|
|
102
113
|
const [sessions, setSessions] = useState<readonly Capturing[]>([]);
|
|
103
|
-
const apps = useApps(
|
|
114
|
+
const apps = useApps(domicile, [
|
|
104
115
|
...requests.flatMap(appIds),
|
|
105
116
|
...sessions.map((session) => session.appId),
|
|
106
117
|
]);
|
|
@@ -149,13 +160,13 @@ export const PortalDialogs = memo(
|
|
|
149
160
|
asker={apps(shown.appId).name}
|
|
150
161
|
browserWindows={host.browserWindows ?? []}
|
|
151
162
|
claim={claims.get(shown.id)}
|
|
163
|
+
domicile={domicile}
|
|
152
164
|
folders={folders}
|
|
153
165
|
key={shown.id}
|
|
154
166
|
request={shown}
|
|
155
167
|
screen={screenFor(shown, screen, screenOf)}
|
|
156
168
|
shellChords={shellChords}
|
|
157
169
|
shownWindows={shownWindows}
|
|
158
|
-
system={files}
|
|
159
170
|
/>
|
|
160
171
|
))}
|
|
161
172
|
</>
|
|
@@ -178,7 +189,7 @@ const Dialog = ({
|
|
|
178
189
|
screen,
|
|
179
190
|
shellChords,
|
|
180
191
|
shownWindows,
|
|
181
|
-
|
|
192
|
+
domicile,
|
|
182
193
|
}: {
|
|
183
194
|
answer: (answer: PortalAnswer) => void;
|
|
184
195
|
apps: (appId: string) => App;
|
|
@@ -191,7 +202,7 @@ const Dialog = ({
|
|
|
191
202
|
screen: string | undefined;
|
|
192
203
|
shellChords: readonly string[];
|
|
193
204
|
shownWindows: () => readonly ShownWindow[];
|
|
194
|
-
|
|
205
|
+
domicile: DialogDesktop;
|
|
195
206
|
}) => {
|
|
196
207
|
switch (request.kind) {
|
|
197
208
|
case PortalKind.Access:
|
|
@@ -227,8 +238,8 @@ const Dialog = ({
|
|
|
227
238
|
answer={answer}
|
|
228
239
|
asker={asker}
|
|
229
240
|
body={request.body}
|
|
241
|
+
domicile={domicile}
|
|
230
242
|
screen={screen}
|
|
231
|
-
system={files}
|
|
232
243
|
/>
|
|
233
244
|
);
|
|
234
245
|
case PortalKind.FileChooser:
|
|
@@ -246,7 +257,7 @@ const Dialog = ({
|
|
|
246
257
|
answer={answer}
|
|
247
258
|
asker={asker}
|
|
248
259
|
body={request.body}
|
|
249
|
-
files={files}
|
|
260
|
+
files={domicile.files}
|
|
250
261
|
screen={screen}
|
|
251
262
|
/>
|
|
252
263
|
);
|
|
@@ -267,7 +278,7 @@ const Dialog = ({
|
|
|
267
278
|
answer={answer}
|
|
268
279
|
asker={asker}
|
|
269
280
|
body={request.body}
|
|
270
|
-
files={files}
|
|
281
|
+
files={domicile.files}
|
|
271
282
|
screen={screen}
|
|
272
283
|
/>
|
|
273
284
|
);
|
|
@@ -298,7 +309,7 @@ const Dialog = ({
|
|
|
298
309
|
body={request.body}
|
|
299
310
|
browserWindows={browserWindows}
|
|
300
311
|
castTo={claim?.kind === CastClaimKind.Pick ? claim.to : undefined}
|
|
301
|
-
previewWindow={
|
|
312
|
+
previewWindow={domicile.capture.preview}
|
|
302
313
|
screen={screen}
|
|
303
314
|
shownWindows={shownWindows}
|
|
304
315
|
/>
|
|
@@ -321,7 +332,7 @@ const Dialog = ({
|
|
|
321
332
|
asker={request.appId === SHELL_APP_ID ? undefined : asker}
|
|
322
333
|
body={request.body}
|
|
323
334
|
browserWindows={browserWindows}
|
|
324
|
-
previewWindow={
|
|
335
|
+
previewWindow={domicile.capture.preview}
|
|
325
336
|
screen={screen}
|
|
326
337
|
shownWindows={shownWindows}
|
|
327
338
|
/>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import type { Files } from "@domicile-desktop/sdk/desktop/files";
|
|
1
2
|
import type { PortalAnswer, WallpaperBody } from "@domicile-desktop/sdk/portal";
|
|
2
3
|
import {
|
|
3
4
|
PortalAnswer as Answer,
|
|
4
5
|
WallpaperTarget,
|
|
5
6
|
} from "@domicile-desktop/sdk/portal";
|
|
6
|
-
import type { System } from "@domicile-desktop/sdk/system";
|
|
7
7
|
import { css } from "../../styled-system/css";
|
|
8
8
|
import { Button } from "../Button/Button";
|
|
9
9
|
import { ModalDialog } from "../ModalDialog/ModalDialog";
|
|
@@ -14,7 +14,7 @@ type Props = {
|
|
|
14
14
|
/** Who asks, as the dialog names them. */
|
|
15
15
|
asker: string;
|
|
16
16
|
body: WallpaperBody;
|
|
17
|
-
files: Pick<
|
|
17
|
+
files: Pick<Files, "read">;
|
|
18
18
|
screen: string | undefined;
|
|
19
19
|
};
|
|
20
20
|
|
package/src/useApps/useApps.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { System } from "@domicile-desktop/sdk/system";
|
|
2
1
|
import { appIdName } from "@domicile-desktop/system-apps/app-id-name";
|
|
2
|
+
import type { AppsDesktop } from "@domicile-desktop/system-apps/apps-desktop";
|
|
3
3
|
import type { DescribedApp } from "@domicile-desktop/system-apps/describe-apps";
|
|
4
4
|
import { describeApps } from "@domicile-desktop/system-apps/describe-apps";
|
|
5
5
|
import { useCallback, useEffect, useState } from "react";
|
|
@@ -17,7 +17,7 @@ export type App = {
|
|
|
17
17
|
* yet, is named by its readable form; the empty id is "An application".
|
|
18
18
|
*/
|
|
19
19
|
export const useApps = (
|
|
20
|
-
|
|
20
|
+
domicile: AppsDesktop,
|
|
21
21
|
ids: readonly string[],
|
|
22
22
|
): ((appId: string) => App) => {
|
|
23
23
|
const [described, setDescribed] = useState<ReadonlyMap<string, DescribedApp>>(
|
|
@@ -31,7 +31,7 @@ export const useApps = (
|
|
|
31
31
|
return undefined;
|
|
32
32
|
} else {
|
|
33
33
|
let current = true;
|
|
34
|
-
describeApps(
|
|
34
|
+
describeApps(domicile, key.split("\n"))
|
|
35
35
|
.then((result) => {
|
|
36
36
|
result.match({
|
|
37
37
|
Err: (error) => {
|
|
@@ -54,7 +54,7 @@ export const useApps = (
|
|
|
54
54
|
current = false;
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
}, [
|
|
57
|
+
}, [domicile, key]);
|
|
58
58
|
|
|
59
59
|
return useCallback((appId) => app(described, appId), [described]);
|
|
60
60
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Files as FileCalls } from "@domicile-desktop/sdk/desktop/files";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
|
|
4
|
-
type Files = Pick<
|
|
4
|
+
type Files = Pick<FileCalls, "read">;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* A URL an `<img>` can show for the picture at `path`, read through
|
|
8
|
-
* `
|
|
7
|
+
* A URL an `<img>` can show for the picture at `path`, read through
|
|
8
|
+
* `domicile.files`. `undefined` for no path, until it is read, or when it cannot be
|
|
9
9
|
* read (logged). The URL is revoked when the path changes or on unmount.
|
|
10
10
|
*/
|
|
11
11
|
export const usePictureUrl = (
|
|
@@ -32,7 +32,7 @@ const showPicture = (
|
|
|
32
32
|
let made: string | undefined;
|
|
33
33
|
let current = true;
|
|
34
34
|
files
|
|
35
|
-
.
|
|
35
|
+
.read(path)
|
|
36
36
|
.then((read) => {
|
|
37
37
|
read.match({
|
|
38
38
|
Err: (error) => {
|