@peers-app/peers-ui 0.7.40 → 0.8.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/dist/command-palette/command-palette.d.ts +2 -2
- package/dist/command-palette/command-palette.js +3 -7
- package/dist/components/group-switcher.d.ts +2 -1
- package/dist/components/group-switcher.js +7 -6
- package/dist/globals.d.ts +1 -1
- package/dist/screens/contacts/contact-list.js +4 -1
- package/dist/screens/contacts/index.d.ts +2 -0
- package/dist/screens/contacts/index.js +2 -0
- package/dist/screens/contacts/user-connect.d.ts +2 -0
- package/dist/screens/contacts/user-connect.js +312 -0
- package/dist/screens/network-viewer/device-details-modal.js +44 -0
- package/dist/screens/network-viewer/group-details-modal.js +80 -2
- package/dist/screens/network-viewer/network-viewer.js +36 -16
- package/dist/screens/settings/settings-page.js +13 -7
- package/dist/screens/setup-user.js +8 -6
- package/dist/system-apps/index.d.ts +1 -0
- package/dist/system-apps/index.js +10 -1
- package/dist/system-apps/mobile-settings.app.d.ts +2 -0
- package/dist/system-apps/mobile-settings.app.js +8 -0
- package/dist/tabs-layout/tabs-layout.js +60 -38
- package/dist/tabs-layout/tabs-state.d.ts +10 -4
- package/dist/tabs-layout/tabs-state.js +41 -4
- package/dist/ui-router/ui-loader.js +45 -12
- package/package.json +3 -3
- package/src/command-palette/command-palette.ts +4 -8
- package/src/components/group-switcher.tsx +12 -8
- package/src/screens/contacts/contact-list.tsx +4 -0
- package/src/screens/contacts/index.ts +3 -1
- package/src/screens/contacts/user-connect.tsx +452 -0
- package/src/screens/network-viewer/device-details-modal.tsx +55 -0
- package/src/screens/network-viewer/group-details-modal.tsx +144 -1
- package/src/screens/network-viewer/network-viewer.tsx +36 -29
- package/src/screens/settings/settings-page.tsx +17 -9
- package/src/screens/setup-user.tsx +9 -6
- package/src/system-apps/index.ts +9 -0
- package/src/system-apps/mobile-settings.app.ts +8 -0
- package/src/tabs-layout/tabs-layout.tsx +108 -82
- package/src/tabs-layout/tabs-state.ts +54 -5
- package/src/ui-router/ui-loader.tsx +50 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { groupDeviceVar, groupUserVar, IAppNav, IPackage, newid } from "@peers-app/peers-sdk";
|
|
1
|
+
import { groupDeviceVar, groupUserVar, IAppNav, IPackage, newid, observable, Observable } from "@peers-app/peers-sdk";
|
|
2
2
|
import { _mainContentPath } from "../globals";
|
|
3
3
|
import { systemPackage } from "../system-apps";
|
|
4
4
|
import { allPackages } from "../ui-router/routes-loader";
|
|
@@ -19,19 +19,68 @@ export const launcherApp: TabState = {
|
|
|
19
19
|
iconClassName: 'bi-grid-3x3-gap',
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
//
|
|
23
|
-
|
|
22
|
+
// Persistent vars for storage (write-only, no subscription to avoid oscillation)
|
|
23
|
+
const _persistentActiveTabs = groupDeviceVar<TabState[]>('activeTabs', {
|
|
24
24
|
defaultValue: [launcherApp],
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
const _persistentActiveTabId = groupDeviceVar<string>('activeTabId', {
|
|
28
28
|
defaultValue: 'launcher',
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
const _persistentRecentlyUsedApps = groupUserVar<string[]>('recentlyUsedApps', {
|
|
32
32
|
defaultValue: [],
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
// In-memory observables for UI state (loaded once, then write-through to persistent vars)
|
|
36
|
+
export const activeTabs: Observable<TabState[]> & { loadingPromise: Promise<void> } = (() => {
|
|
37
|
+
const obs = observable<TabState[]>([launcherApp]);
|
|
38
|
+
|
|
39
|
+
// Write-through to persistent var on change
|
|
40
|
+
obs.subscribe(value => {
|
|
41
|
+
_persistentActiveTabs(value);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Load initial value once
|
|
45
|
+
const loadingPromise = _persistentActiveTabs.loadingPromise.then(() => {
|
|
46
|
+
obs(_persistentActiveTabs());
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return Object.assign(obs, { loadingPromise });
|
|
50
|
+
})();
|
|
51
|
+
|
|
52
|
+
export const activeTabId: Observable<string> & { loadingPromise: Promise<void> } = (() => {
|
|
53
|
+
const obs = observable<string>('launcher');
|
|
54
|
+
|
|
55
|
+
// Write-through to persistent var on change
|
|
56
|
+
obs.subscribe(value => {
|
|
57
|
+
_persistentActiveTabId(value);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Load initial value once
|
|
61
|
+
const loadingPromise = _persistentActiveTabId.loadingPromise.then(() => {
|
|
62
|
+
obs(_persistentActiveTabId());
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return Object.assign(obs, { loadingPromise });
|
|
66
|
+
})();
|
|
67
|
+
|
|
68
|
+
export const recentlyUsedApps: Observable<string[]> & { loadingPromise: Promise<void> } = (() => {
|
|
69
|
+
const obs = observable<string[]>([]);
|
|
70
|
+
|
|
71
|
+
// Write-through to persistent var on change
|
|
72
|
+
obs.subscribe(value => {
|
|
73
|
+
_persistentRecentlyUsedApps(value);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Load initial value once
|
|
77
|
+
const loadingPromise = _persistentRecentlyUsedApps.loadingPromise.then(() => {
|
|
78
|
+
obs(_persistentRecentlyUsedApps());
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return Object.assign(obs, { loadingPromise });
|
|
82
|
+
})();
|
|
83
|
+
|
|
35
84
|
export const initializedTabs = new Set<string>();
|
|
36
85
|
|
|
37
86
|
export function goToTabPath(path: string) {
|
|
@@ -221,26 +221,65 @@ const UILoader = (args: { peersUIId: string, props: Record<string, any> }) => {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
const uiLoadingPromises: Record<string, Promise<any>> = {};
|
|
224
|
+
|
|
225
|
+
// Check if we're running in a React Native WebView (has injectUIBundle available)
|
|
226
|
+
const isReactNativeWebView = typeof (window as any).ReactNativeWebView !== 'undefined';
|
|
227
|
+
|
|
224
228
|
function loadUIBundle(pkg: IPackage, forceRefresh?: boolean) {
|
|
225
229
|
// Dynamically import the bundle
|
|
226
230
|
let importPromise: Promise<any> = uiLoadingPromises[pkg.packageId];
|
|
227
231
|
if (!importPromise || forceRefresh) {
|
|
232
|
+
const sTime = Date.now();
|
|
228
233
|
console.log(`loading ui bundle for ${pkg.name}`);
|
|
229
234
|
importPromise = new Promise<void>(async (resolve, reject) => {
|
|
230
235
|
try {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
236
|
+
if (!pkg.uiBundleFileId) {
|
|
237
|
+
resolve();
|
|
238
|
+
return;
|
|
234
239
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
240
|
+
|
|
241
|
+
// Use fast injection path for React Native WebView
|
|
242
|
+
if (isReactNativeWebView && rpcServerCalls.injectUIBundle) {
|
|
243
|
+
// Set up listeners for bundle load completion
|
|
244
|
+
const _window = window as any;
|
|
245
|
+
_window.__peersUIs = _window.__peersUIs || {};
|
|
246
|
+
|
|
247
|
+
const loadPromise = new Promise<void>((resolveLoad, rejectLoad) => {
|
|
248
|
+
const fileId = pkg.uiBundleFileId!;
|
|
249
|
+
|
|
250
|
+
_window.__peersUIBundleLoaded = (loadedFileId: string) => {
|
|
251
|
+
if (loadedFileId === fileId) {
|
|
252
|
+
// Copy loaded UIs to our local registry
|
|
253
|
+
Object.keys(_window.__peersUIs || {}).forEach(peersUIId => {
|
|
254
|
+
peersUIs[peersUIId] = _window.__peersUIs[peersUIId];
|
|
255
|
+
});
|
|
256
|
+
resolveLoad();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
_window.__peersUIBundleError = (errorFileId: string, errorMsg: string) => {
|
|
261
|
+
if (errorFileId === fileId) {
|
|
262
|
+
rejectLoad(new Error(errorMsg));
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await rpcServerCalls.injectUIBundle(pkg.uiBundleFileId);
|
|
268
|
+
await loadPromise;
|
|
269
|
+
console.log(`finished loading ui bundle for ${pkg.name}: ${(Date.now() - sTime).toFixed(0)}ms`);
|
|
270
|
+
} else {
|
|
271
|
+
// Fallback: use postMessage-based getFileContents (slower for large bundles)
|
|
272
|
+
let bundleCode = await rpcServerCalls.getFileContents(pkg.uiBundleFileId);
|
|
273
|
+
if (bundleCode) {
|
|
274
|
+
const exportUIs = (peerUIs: IPeersPackageUIs) => {
|
|
275
|
+
peerUIs?.uis?.forEach(ui => {
|
|
276
|
+
peersUIs[ui.peersUIId] = ui;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const bundleFunction = new Function('exportUIs', bundleCode);
|
|
280
|
+
await bundleFunction(exportUIs);
|
|
241
281
|
}
|
|
242
|
-
|
|
243
|
-
await bundleFunction(exportUIs);
|
|
282
|
+
console.log(`finished loading ui bundle for ${pkg.name}: ${(Date.now() - sTime).toFixed(0)}ms, ${(bundleCode.length/1000).toFixed(0)} KB`);
|
|
244
283
|
}
|
|
245
284
|
resolve();
|
|
246
285
|
} catch (err) {
|