@camera.ui/browser 0.0.190 → 0.0.192
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/index.d.ts +2 -1
- package/dist/index.js +106 -65
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -883,7 +883,7 @@ export declare interface ReactiveContactSensor extends ReactiveSensor<ContactSen
|
|
|
883
883
|
getProperty(property: string): unknown;
|
|
884
884
|
}
|
|
885
885
|
|
|
886
|
-
export declare interface ReactiveCoreManager extends Omit<CoreManager, 'connectToPlugin' | 'signRequest' | 'onEvent'> {
|
|
886
|
+
export declare interface ReactiveCoreManager extends Omit<CoreManager, 'connectToPlugin' | 'signRequest' | 'onEvent' | 'assistantAsk' | 'assistantAccess'> {
|
|
887
887
|
}
|
|
888
888
|
|
|
889
889
|
export declare interface ReactiveDeviceManager {
|
|
@@ -1078,6 +1078,7 @@ export declare interface ReactiveSmokeSensor extends ReactiveSensor<SmokeSensorP
|
|
|
1078
1078
|
|
|
1079
1079
|
export declare interface ReactiveStorage {
|
|
1080
1080
|
readonly proxy: Promisify<StorageRPC>;
|
|
1081
|
+
readonly client: RPCClient;
|
|
1081
1082
|
readonly config: ShallowRef<SchemaConfig | undefined>;
|
|
1082
1083
|
readonly isLoading: Ref<boolean>;
|
|
1083
1084
|
readonly error: Ref<Error | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -430,9 +430,7 @@ function fetchSnapshotShared(deviceManager, id, forceFresh = false) {
|
|
|
430
430
|
const device = await acquireCameraDevice(deviceManager, id);
|
|
431
431
|
try {
|
|
432
432
|
if (!device) return void 0;
|
|
433
|
-
|
|
434
|
-
if (result) setSnapshot(id, result);
|
|
435
|
-
return result ?? void 0;
|
|
433
|
+
return await device.fetchSnapshot(void 0, forceFresh ? true : void 0) ?? void 0;
|
|
436
434
|
} finally {
|
|
437
435
|
if (device) releaseCameraDevice(id);
|
|
438
436
|
}
|
|
@@ -445,28 +443,32 @@ function hookReconnectRefresh(cameraUi, deviceManager) {
|
|
|
445
443
|
if (reconnectHooked) return;
|
|
446
444
|
reconnectHooked = true;
|
|
447
445
|
cameraUi.on("reconnected", () => {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
446
|
+
setTimeout(() => {
|
|
447
|
+
let delay = 0;
|
|
448
|
+
for (const id of subscribers.keys()) {
|
|
449
|
+
if ((subscribers.get(id)?.size ?? 0) === 0) continue;
|
|
450
|
+
const cameraId = id;
|
|
451
|
+
setTimeout(() => {
|
|
452
|
+
if ((subscribers.get(cameraId)?.size ?? 0) === 0) return;
|
|
453
|
+
fetchSnapshotShared(deviceManager, cameraId).catch(() => void 0);
|
|
454
|
+
}, delay);
|
|
455
|
+
delay += 150;
|
|
456
|
+
}
|
|
457
|
+
}, 0);
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
function deferRevoke(url) {
|
|
461
461
|
setTimeout(() => URL.revokeObjectURL(url), REVOKE_DELAY_MS);
|
|
462
462
|
}
|
|
463
463
|
function setSnapshot(cameraId, data, fetchedAt) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
464
|
+
if (snapshotCache.get(cameraId) !== data) {
|
|
465
|
+
const oldUrl = urlCache.get(cameraId);
|
|
466
|
+
if (oldUrl) {
|
|
467
|
+
deferRevoke(oldUrl);
|
|
468
|
+
urlCache.delete(cameraId);
|
|
469
|
+
}
|
|
470
|
+
snapshotCache.set(cameraId, data);
|
|
468
471
|
}
|
|
469
|
-
snapshotCache.set(cameraId, data);
|
|
470
472
|
if (fetchedAt !== void 0) timestampCache.set(cameraId, fetchedAt);
|
|
471
473
|
notify(cameraId);
|
|
472
474
|
}
|
|
@@ -1808,7 +1810,7 @@ async function resolvePluginId(rpcRef, pluginName) {
|
|
|
1808
1810
|
}
|
|
1809
1811
|
//#endregion
|
|
1810
1812
|
//#region src/composables/useStorage.ts
|
|
1811
|
-
function createReactiveStorage(proxy) {
|
|
1813
|
+
function createReactiveStorage(proxy, client) {
|
|
1812
1814
|
const config = shallowRef();
|
|
1813
1815
|
const isLoading = ref(false);
|
|
1814
1816
|
const error = ref();
|
|
@@ -1872,6 +1874,7 @@ function createReactiveStorage(proxy) {
|
|
|
1872
1874
|
}
|
|
1873
1875
|
return {
|
|
1874
1876
|
proxy,
|
|
1877
|
+
client,
|
|
1875
1878
|
config,
|
|
1876
1879
|
isLoading,
|
|
1877
1880
|
error,
|
|
@@ -1891,10 +1894,10 @@ function getCameraStorageKey(pluginId, cameraId) {
|
|
|
1891
1894
|
function getSensorStorageKey(pluginId, sensorId) {
|
|
1892
1895
|
return `plugin:${pluginId}:sensor:${sensorId}`;
|
|
1893
1896
|
}
|
|
1894
|
-
function acquireStorage(key, createProxy) {
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1897
|
+
function acquireStorage(key, client, createProxy) {
|
|
1898
|
+
const cached = storageCache.get(key);
|
|
1899
|
+
if (cached && cached.client !== client) storageCache.forceRelease(key);
|
|
1900
|
+
return storageCache.acquire(key, () => createReactiveStorage(createProxy(), client));
|
|
1898
1901
|
}
|
|
1899
1902
|
function releaseStorage(key) {
|
|
1900
1903
|
storageCache.release(key);
|
|
@@ -1918,10 +1921,23 @@ function cleanupStorage(state, isConnected, config) {
|
|
|
1918
1921
|
state.cachedStorage = void 0;
|
|
1919
1922
|
config.value = void 0;
|
|
1920
1923
|
}
|
|
1924
|
+
function bindStorage(state, storageKey, client, config, createProxy) {
|
|
1925
|
+
if (state.currentStorageKey === storageKey && state.cachedStorage?.client === client) return;
|
|
1926
|
+
if (state.currentStorageKey && state.currentStorageKey !== storageKey) {
|
|
1927
|
+
releaseStorage(state.currentStorageKey);
|
|
1928
|
+
config.value = void 0;
|
|
1929
|
+
}
|
|
1930
|
+
state.currentStorageKey = storageKey;
|
|
1931
|
+
state.cachedStorage = acquireStorage(storageKey, client, createProxy);
|
|
1932
|
+
}
|
|
1921
1933
|
var GET_CONFIG_RETRY_DELAYS = [
|
|
1922
1934
|
2e3,
|
|
1923
1935
|
5e3,
|
|
1924
1936
|
1e4,
|
|
1937
|
+
15e3,
|
|
1938
|
+
15e3,
|
|
1939
|
+
15e3,
|
|
1940
|
+
15e3,
|
|
1925
1941
|
15e3
|
|
1926
1942
|
];
|
|
1927
1943
|
function sleep(ms) {
|
|
@@ -2017,7 +2033,8 @@ function createStorageOperations(state, config, isLoading, error) {
|
|
|
2017
2033
|
};
|
|
2018
2034
|
}
|
|
2019
2035
|
function usePluginStorage(pluginName) {
|
|
2020
|
-
const
|
|
2036
|
+
const cameraUi = useCameraUi();
|
|
2037
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2021
2038
|
const config = shallowRef();
|
|
2022
2039
|
const _isLoading = ref(false);
|
|
2023
2040
|
const initialSetupDone = ref(false);
|
|
@@ -2026,16 +2043,14 @@ function usePluginStorage(pluginName) {
|
|
|
2026
2043
|
const state = createStorageState();
|
|
2027
2044
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2028
2045
|
async function connect(name) {
|
|
2029
|
-
|
|
2046
|
+
const client = rpc.value;
|
|
2047
|
+
if (!client || !clientConnected.value) return false;
|
|
2030
2048
|
try {
|
|
2031
2049
|
const pluginId = await resolvePluginId(rpc, name);
|
|
2032
2050
|
if (!pluginId) throw new Error(`Plugin "${name}" not found`);
|
|
2033
|
-
|
|
2034
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2035
|
-
state.currentStorageKey = storageKey;
|
|
2036
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2051
|
+
bindStorage(state, getPluginStorageKey(pluginId), client, config, () => {
|
|
2037
2052
|
const namespaces = NamespaceManager.pluginNamespaces(pluginId);
|
|
2038
|
-
return
|
|
2053
|
+
return client.createProxy(namespaces.pluginStorageRpc);
|
|
2039
2054
|
});
|
|
2040
2055
|
isConnected.value = true;
|
|
2041
2056
|
return true;
|
|
@@ -2053,14 +2068,20 @@ function usePluginStorage(pluginName) {
|
|
|
2053
2068
|
}
|
|
2054
2069
|
return operations.getConfig();
|
|
2055
2070
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2071
|
+
async function sync() {
|
|
2072
|
+
const name = toValue(pluginName);
|
|
2073
|
+
if (clientConnected.value && name) {
|
|
2058
2074
|
await connect(name);
|
|
2059
2075
|
operations.getConfig();
|
|
2060
2076
|
} else cleanupStorage(state, isConnected, config);
|
|
2061
2077
|
initialSetupDone.value = true;
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2078
|
+
}
|
|
2079
|
+
watch([clientConnected, () => toValue(pluginName)], sync, { immediate: true });
|
|
2080
|
+
cameraUi.on("reconnected", sync);
|
|
2081
|
+
tryOnScopeDispose(() => {
|
|
2082
|
+
cameraUi.off("reconnected", sync);
|
|
2083
|
+
cleanupStorage(state, isConnected, config);
|
|
2084
|
+
});
|
|
2064
2085
|
return {
|
|
2065
2086
|
config,
|
|
2066
2087
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
|
@@ -2073,7 +2094,8 @@ function usePluginStorage(pluginName) {
|
|
|
2073
2094
|
};
|
|
2074
2095
|
}
|
|
2075
2096
|
function useCameraStorage(camera, pluginName) {
|
|
2076
|
-
const
|
|
2097
|
+
const cameraUi = useCameraUi();
|
|
2098
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2077
2099
|
const config = shallowRef();
|
|
2078
2100
|
const _isLoading = ref(false);
|
|
2079
2101
|
const initialSetupDone = ref(false);
|
|
@@ -2082,16 +2104,14 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2082
2104
|
const state = createStorageState();
|
|
2083
2105
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2084
2106
|
async function connect(cameraId, name) {
|
|
2085
|
-
|
|
2107
|
+
const client = rpc.value;
|
|
2108
|
+
if (!client || !clientConnected.value) return false;
|
|
2086
2109
|
try {
|
|
2087
2110
|
const pluginId = await resolvePluginId(rpc, name);
|
|
2088
2111
|
if (!pluginId) throw new Error(`Plugin "${name}" not found`);
|
|
2089
|
-
|
|
2090
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2091
|
-
state.currentStorageKey = storageKey;
|
|
2092
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2112
|
+
bindStorage(state, getCameraStorageKey(pluginId, cameraId), client, config, () => {
|
|
2093
2113
|
const namespaces = NamespaceManager.pluginCameraNamespaces(pluginId, cameraId);
|
|
2094
|
-
return
|
|
2114
|
+
return client.createProxy(namespaces.cameraStorageRpc);
|
|
2095
2115
|
});
|
|
2096
2116
|
isConnected.value = true;
|
|
2097
2117
|
return true;
|
|
@@ -2110,18 +2130,25 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2110
2130
|
}
|
|
2111
2131
|
return operations.getConfig();
|
|
2112
2132
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
(
|
|
2117
|
-
], async ([connected, cameraId, name]) => {
|
|
2118
|
-
if (connected && cameraId && name) {
|
|
2133
|
+
async function sync() {
|
|
2134
|
+
const cameraId = extractCameraId(toValue(camera));
|
|
2135
|
+
const name = toValue(pluginName);
|
|
2136
|
+
if (clientConnected.value && cameraId && name) {
|
|
2119
2137
|
await connect(cameraId, name);
|
|
2120
2138
|
operations.getConfig();
|
|
2121
2139
|
} else cleanupStorage(state, isConnected, config);
|
|
2122
2140
|
initialSetupDone.value = true;
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2141
|
+
}
|
|
2142
|
+
watch([
|
|
2143
|
+
clientConnected,
|
|
2144
|
+
() => extractCameraId(toValue(camera)),
|
|
2145
|
+
() => toValue(pluginName)
|
|
2146
|
+
], sync, { immediate: true });
|
|
2147
|
+
cameraUi.on("reconnected", sync);
|
|
2148
|
+
tryOnScopeDispose(() => {
|
|
2149
|
+
cameraUi.off("reconnected", sync);
|
|
2150
|
+
cleanupStorage(state, isConnected, config);
|
|
2151
|
+
});
|
|
2125
2152
|
return {
|
|
2126
2153
|
config,
|
|
2127
2154
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
|
@@ -2134,7 +2161,8 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2134
2161
|
};
|
|
2135
2162
|
}
|
|
2136
2163
|
function useSensorStorage(sensorId, pluginId) {
|
|
2137
|
-
const
|
|
2164
|
+
const cameraUi = useCameraUi();
|
|
2165
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2138
2166
|
const config = shallowRef();
|
|
2139
2167
|
const _isLoading = ref(false);
|
|
2140
2168
|
const initialSetupDone = ref(false);
|
|
@@ -2143,14 +2171,12 @@ function useSensorStorage(sensorId, pluginId) {
|
|
|
2143
2171
|
const state = createStorageState();
|
|
2144
2172
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2145
2173
|
function connect(senId, plugId) {
|
|
2146
|
-
|
|
2174
|
+
const client = rpc.value;
|
|
2175
|
+
if (!client || !clientConnected.value) return false;
|
|
2147
2176
|
try {
|
|
2148
|
-
|
|
2149
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2150
|
-
state.currentStorageKey = storageKey;
|
|
2151
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2177
|
+
bindStorage(state, getSensorStorageKey(plugId, senId), client, config, () => {
|
|
2152
2178
|
const namespaces = NamespaceManager.pluginSensorNamespaces(plugId, senId);
|
|
2153
|
-
return
|
|
2179
|
+
return client.createProxy(namespaces.sensorStorageRpc);
|
|
2154
2180
|
});
|
|
2155
2181
|
isConnected.value = true;
|
|
2156
2182
|
return true;
|
|
@@ -2169,18 +2195,25 @@ function useSensorStorage(sensorId, pluginId) {
|
|
|
2169
2195
|
}
|
|
2170
2196
|
return operations.getConfig();
|
|
2171
2197
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
(
|
|
2176
|
-
], ([connected, senId, plugId]) => {
|
|
2177
|
-
if (connected && senId && plugId) {
|
|
2198
|
+
function sync() {
|
|
2199
|
+
const senId = toValue(sensorId);
|
|
2200
|
+
const plugId = toValue(pluginId);
|
|
2201
|
+
if (clientConnected.value && senId && plugId) {
|
|
2178
2202
|
connect(senId, plugId);
|
|
2179
2203
|
operations.getConfig();
|
|
2180
2204
|
} else cleanupStorage(state, isConnected, config);
|
|
2181
2205
|
initialSetupDone.value = true;
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2206
|
+
}
|
|
2207
|
+
watch([
|
|
2208
|
+
clientConnected,
|
|
2209
|
+
() => toValue(sensorId),
|
|
2210
|
+
() => toValue(pluginId)
|
|
2211
|
+
], sync, { immediate: true });
|
|
2212
|
+
cameraUi.on("reconnected", sync);
|
|
2213
|
+
tryOnScopeDispose(() => {
|
|
2214
|
+
cameraUi.off("reconnected", sync);
|
|
2215
|
+
cleanupStorage(state, isConnected, config);
|
|
2216
|
+
});
|
|
2184
2217
|
return {
|
|
2185
2218
|
config,
|
|
2186
2219
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
|
@@ -3018,6 +3051,7 @@ async function processWebRTCMessage(handler, msg) {
|
|
|
3018
3051
|
//#endregion
|
|
3019
3052
|
//#region src/streaming/streamConnection.ts
|
|
3020
3053
|
var log = new Logger("StreamConnection");
|
|
3054
|
+
var MSE_AUDIO_CODEC = /mp4a|opus|flac|mp3/i;
|
|
3021
3055
|
function isVideoInPictureInPicture(video) {
|
|
3022
3056
|
if (!video) return false;
|
|
3023
3057
|
if (typeof document !== "undefined" && "pictureInPictureElement" in document && document.pictureInPictureElement === video) return true;
|
|
@@ -3597,6 +3631,9 @@ var StreamConnection = class {
|
|
|
3597
3631
|
this.markSourceUndecodable();
|
|
3598
3632
|
this.restart();
|
|
3599
3633
|
}
|
|
3634
|
+
noteDeliveredAudio(delivered) {
|
|
3635
|
+
if (delivered && !this.hasAudio.value) this.hasAudio.value = true;
|
|
3636
|
+
}
|
|
3600
3637
|
async probeStream() {
|
|
3601
3638
|
const cam = this.camera.value;
|
|
3602
3639
|
const source = this.source.value;
|
|
@@ -3681,7 +3718,10 @@ var StreamConnection = class {
|
|
|
3681
3718
|
else if (this.backchannelHandler) processWebRTCMessage(this.backchannelHandler, msg);
|
|
3682
3719
|
break;
|
|
3683
3720
|
case "mse":
|
|
3684
|
-
if (this.mseHandler && typeof msg.value === "string")
|
|
3721
|
+
if (this.mseHandler && typeof msg.value === "string") {
|
|
3722
|
+
this.noteDeliveredAudio(MSE_AUDIO_CODEC.test(msg.value));
|
|
3723
|
+
this.mseHandler.initializeBuffer(msg.value);
|
|
3724
|
+
}
|
|
3685
3725
|
break;
|
|
3686
3726
|
case "error": if (this.requestedMode.value !== "auto") {
|
|
3687
3727
|
this.error.value = new Error(msg.value);
|
|
@@ -3717,6 +3757,7 @@ var StreamConnection = class {
|
|
|
3717
3757
|
this.handleWebRTCFailed();
|
|
3718
3758
|
return;
|
|
3719
3759
|
}
|
|
3760
|
+
this.noteDeliveredAudio(stream.getAudioTracks().length > 0);
|
|
3720
3761
|
this.activeMode.value = this.requestedMode.value === "auto" ? "webrtc" : this.requestedMode.value;
|
|
3721
3762
|
this.lastMediaStream = stream;
|
|
3722
3763
|
video.srcObject = stream;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camera.ui/browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.192",
|
|
4
4
|
"description": "camera.ui browser client",
|
|
5
5
|
"author": "seydx (https://github.com/cameraui/clients)",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"unplugin-dts": "^1.1.0",
|
|
64
64
|
"updates": "^18.1.0",
|
|
65
65
|
"vite": "^8.3.0",
|
|
66
|
-
"vitest": "^5.0.
|
|
66
|
+
"vitest": "^5.0.1",
|
|
67
67
|
"vue": "^3.5.42",
|
|
68
68
|
"vue-tsc": "^3.3.11"
|
|
69
69
|
},
|