@peers-app/peers-ui 0.29.1 → 0.29.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ export * from "./use-file-url";
1
2
  export * from "./use-observable";
2
3
  export * from "./use-observable-state";
3
4
  export * from "./use-on-screen";
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  // `use-host-contract` stays internal: its screens import it by path.
18
+ __exportStar(require("./use-file-url"), exports);
18
19
  __exportStar(require("./use-observable"), exports);
19
20
  __exportStar(require("./use-observable-state"), exports);
20
21
  __exportStar(require("./use-on-screen"), exports);
@@ -0,0 +1,23 @@
1
+ /** What {@link useFileUrl} returns. */
2
+ export interface IUseFileUrlResult {
3
+ /** An object URL for the file, such as an `<img src>`. Undefined until it's read. */
4
+ url: string | undefined;
5
+ /** True while the file is being read. */
6
+ loading: boolean;
7
+ /** Why the file couldn't be read: not found, or not on any connected device. */
8
+ error: Error | undefined;
9
+ }
10
+ /**
11
+ * Read a file saved with System Files and give a URL for it, for an image or a download link.
12
+ *
13
+ * ```tsx
14
+ * const avatar = useFileUrl(member.imageFileId);
15
+ * {avatar.url ? <img src={avatar.url} alt="" /> : <Initials />}
16
+ * ```
17
+ *
18
+ * Reads through `hostContract(SystemFiles)` in the screen's data context, the active group.
19
+ * The URL is revoked when the file id changes or the component unmounts, so don't keep it.
20
+ *
21
+ * @param fileId - The file's id; nothing is read while it's undefined.
22
+ */
23
+ export declare function useFileUrl(fileId: string | undefined): IUseFileUrlResult;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFileUrl = useFileUrl;
4
+ const peers_sdk_1 = require("@peers-app/peers-sdk");
5
+ const react_1 = require("react");
6
+ /**
7
+ * Read a file saved with System Files and give a URL for it, for an image or a download link.
8
+ *
9
+ * ```tsx
10
+ * const avatar = useFileUrl(member.imageFileId);
11
+ * {avatar.url ? <img src={avatar.url} alt="" /> : <Initials />}
12
+ * ```
13
+ *
14
+ * Reads through `hostContract(SystemFiles)` in the screen's data context, the active group.
15
+ * The URL is revoked when the file id changes or the component unmounts, so don't keep it.
16
+ *
17
+ * @param fileId - The file's id; nothing is read while it's undefined.
18
+ */
19
+ function useFileUrl(fileId) {
20
+ const [state, setState] = (0, react_1.useState)({
21
+ url: undefined,
22
+ loading: !!fileId,
23
+ error: undefined,
24
+ });
25
+ (0, react_1.useEffect)(() => {
26
+ if (!fileId) {
27
+ setState({ url: undefined, loading: false, error: undefined });
28
+ return;
29
+ }
30
+ let ended = false;
31
+ let url;
32
+ setState({ url: undefined, loading: true, error: undefined });
33
+ const files = (0, peers_sdk_1.hostContract)(peers_sdk_1.SystemFiles);
34
+ (0, peers_sdk_1.readWholeFile)((input) => files.tools.read(input), fileId).then(({ bytes, mimeType }) => {
35
+ if (ended)
36
+ return;
37
+ url = URL.createObjectURL(new Blob([bytes], mimeType ? { type: mimeType } : undefined));
38
+ setState({ url, loading: false, error: undefined });
39
+ }, (error) => {
40
+ if (ended)
41
+ return;
42
+ const reason = error instanceof Error ? error : new Error(String(error));
43
+ setState({ url: undefined, loading: false, error: reason });
44
+ });
45
+ return () => {
46
+ ended = true;
47
+ if (url)
48
+ URL.revokeObjectURL(url);
49
+ };
50
+ }, [fileId]);
51
+ return state;
52
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Read a package's UI or routes bundle as text, through System Files in the context its
3
+ * version is installed in.
4
+ *
5
+ * @param dataContextId - Context of the selected package version.
6
+ * @param fileId - The bundle's file id.
7
+ */
8
+ export declare function readBundleText(dataContextId: string, fileId: string): Promise<string>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readBundleText = readBundleText;
4
+ const peers_sdk_1 = require("@peers-app/peers-sdk");
5
+ const clients = new Map();
6
+ /** System Files on the local host, scoped to one data context; one client per context. */
7
+ function filesIn(dataContextId) {
8
+ let client = clients.get(dataContextId);
9
+ if (!client) {
10
+ client = (0, peers_sdk_1.hostContract)(peers_sdk_1.SystemFiles, { dataContextId: async () => dataContextId });
11
+ clients.set(dataContextId, client);
12
+ }
13
+ return client;
14
+ }
15
+ // Keep a leading BOM, as Buffer's UTF-8 decoding did, so bundle integrity hashes still match.
16
+ const decoder = new TextDecoder("utf-8", { ignoreBOM: true });
17
+ /**
18
+ * Read a package's UI or routes bundle as text, through System Files in the context its
19
+ * version is installed in.
20
+ *
21
+ * @param dataContextId - Context of the selected package version.
22
+ * @param fileId - The bundle's file id.
23
+ */
24
+ async function readBundleText(dataContextId, fileId) {
25
+ const files = filesIn(dataContextId);
26
+ const { bytes } = await (0, peers_sdk_1.readWholeFile)((input) => files.tools.read(input), fileId);
27
+ return decoder.decode(bytes);
28
+ }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadAllRoutes = exports.allPackages = void 0;
4
4
  const peers_sdk_1 = require("@peers-app/peers-sdk");
5
5
  require("../ui-defaults");
6
+ const bundle_files_1 = require("./bundle-files");
6
7
  const runnable_version_1 = require("./runnable-version");
7
8
  /** Packages with authorized navigation metadata available in the current context. */
8
9
  exports.allPackages = (0, peers_sdk_1.observable)([]);
@@ -102,8 +103,8 @@ function loadRoutesBundle(pkg, forceRefresh) {
102
103
  const selected = await (0, runnable_version_1.resolveRunnableVersion)(pkg);
103
104
  const routesBundleFileId = selected?.pv.routesBundleFileId;
104
105
  let bundleCode = "";
105
- if (routesBundleFileId) {
106
- bundleCode = await peers_sdk_1.rpcServerCalls.getFileContents(routesBundleFileId);
106
+ if (selected && routesBundleFileId) {
107
+ bundleCode = await (0, bundle_files_1.readBundleText)(selected.dataContext.dataContextId, routesBundleFileId);
107
108
  }
108
109
  if (bundleCode) {
109
110
  if (selected?.dataContext.groupId)
@@ -43,6 +43,7 @@ const loading_indicator_1 = require("../components/loading-indicator");
43
43
  const globals_1 = require("../globals");
44
44
  const hooks_1 = require("../hooks");
45
45
  require("../ui-defaults");
46
+ const bundle_files_1 = require("./bundle-files");
46
47
  const routes_loader_1 = require("./routes-loader");
47
48
  const runnable_version_1 = require("./runnable-version");
48
49
  const peersUIs = {};
@@ -194,7 +195,7 @@ function loadUIBundle(pkg, forceRefresh) {
194
195
  if (!selected || !uiBundleFileId) {
195
196
  return;
196
197
  }
197
- const bundleCode = await peers_sdk_1.rpcServerCalls.getFileContents(uiBundleFileId);
198
+ const bundleCode = await (0, bundle_files_1.readBundleText)(selected.dataContext.dataContextId, uiBundleFileId);
198
199
  if (bundleCode) {
199
200
  if (selected.dataContext.groupId)
200
201
  (0, peers_sdk_1.assertPackageBundleIntegrity)(selected.pv, "ui", bundleCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-ui",
3
- "version": "0.29.1",
3
+ "version": "0.29.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-ui.git"
@@ -36,7 +36,7 @@
36
36
  "lint:fix": "biome check --write ."
37
37
  },
38
38
  "peerDependencies": {
39
- "@peers-app/peers-sdk": "^0.29.1",
39
+ "@peers-app/peers-sdk": "^0.29.2",
40
40
  "bootstrap": "^5.3.3",
41
41
  "react": "^18.0.0",
42
42
  "react-dom": "^18.0.0"
@@ -47,7 +47,7 @@
47
47
  "@babel/preset-react": "^7.24.1",
48
48
  "@babel/preset-typescript": "^7.27.1",
49
49
  "@biomejs/biome": "2.3.11",
50
- "@peers-app/peers-sdk": "0.29.1",
50
+ "@peers-app/peers-sdk": "0.29.2",
51
51
  "@testing-library/dom": "^10.4.0",
52
52
  "@testing-library/jest-dom": "^6.6.3",
53
53
  "@testing-library/react": "^16.3.0",