diff --git a/Makefile b/Makefile index d93789640e1f..badd506e0eb1 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,10 @@ deploy-init: cp $(LIBJITSIMEET_DIR)/models/RTC/Encoder.onnx \ $(LIBJITSIMEET_DIR)/models/RTC/Decoder.onnx \ $(DEPLOY_DIR)/models - cp -r $(ONNX_DIR)/dist \ - $(DEPLOY_DIR) + mkdir -p $(DEPLOY_DIR)/dist + cp $(ONNX_DIR)/dist/ort-wasm-simd-threaded.mjs \ + $(ONNX_DIR)/dist/ort-wasm-simd-threaded.wasm \ + $(DEPLOY_DIR)/dist deploy-appbundle: cp $(BUILD_DIR)/*.min.js $(DEPLOY_DIR) diff --git a/conference.js b/conference.js index e627d2ba21bf..ce03f84c03ed 100644 --- a/conference.js +++ b/conference.js @@ -163,6 +163,7 @@ import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise' import { handleToggleVideoMuted } from './react/features/toolbox/actions.any'; import { transcriberJoined, transcriberLeft } from './react/features/transcribing/actions'; import { muteLocal } from './react/features/video-menu/actions.any'; +import { setTileView } from './react/features/video-layout/actions.any'; const logger = Logger.getLogger('app:conference-web'); let room; @@ -1882,6 +1883,7 @@ export default { APP.UI.initConference(); dispatch(conferenceJoined(room)); + dispatch(setTileView(true)); const participantCount = room?.getParticipants()?.length; if (participantCount === 0) { dispatch(toggleE2EE(true)); diff --git a/config.js b/config.js index 999cacb2d1f3..4ae4c041597f 100644 --- a/config.js +++ b/config.js @@ -340,6 +340,13 @@ var config = { // How many participants while in the tile view mode, before the receiving video quality is reduced from HD to SD. // Use -1 to disable. // maxFullResolutionParticipants: 2, + maxFullResolutionParticipants: -1, + videoQuality: { + minHeightForQualityLvl: { + 240: 'standard', + 720: 'high', + }, + }, // w3c spec-compliant video constraints to use for video capture. Currently // used by browsers that return true from lib-jitsi-meet's diff --git a/modules/UI/videolayout/LargeVideoManager.js b/modules/UI/videolayout/LargeVideoManager.js index 6804a4a10de7..9850e2bb7eb1 100644 --- a/modules/UI/videolayout/LargeVideoManager.js +++ b/modules/UI/videolayout/LargeVideoManager.js @@ -543,6 +543,9 @@ export default class LargeVideoManager { * Updates the src of the dominant speaker avatar */ updateAvatar() { + if (!this._dominantSpeakerAvatarContainer) { + return; + } if (!this._avatarRoot) { this._avatarRoot = createRoot(this._dominantSpeakerAvatarContainer); } diff --git a/package.json b/package.json index 0d1eedbcf07e..4820e5353e66 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "js-md5": "0.6.1", "js-sha512": "0.8.0", "jwt-decode": "2.2.0", - "lib-meet": "https://github.com/internxt/lib-meet/releases/download/v.1.0.2/lib-meet-1.0.2.tgz", + "lib-meet": "https://github.com/internxt/lib-meet/releases/download/v.1.0.3/lib-meet-1.0.3.tgz", "lodash-es": "4.18.1", "moment": "2.29.4", "moment-duration-format": "2.2.2", diff --git a/react/features/base/meet/views/Conference/components/VideoGallery.tsx b/react/features/base/meet/views/Conference/components/VideoGallery.tsx index 6c8c96f3fd90..646563479ffe 100644 --- a/react/features/base/meet/views/Conference/components/VideoGallery.tsx +++ b/react/features/base/meet/views/Conference/components/VideoGallery.tsx @@ -1,5 +1,6 @@ -import React from "react"; -import { useAspectRatio } from "../../../general/hooks/useAspectRatio"; +import React, { useEffect, useRef } from "react"; +import { useDispatch } from "react-redux"; +import { setMeasuredTileViewThumbnailSize } from "../../../../../filmstrip/actions.web"; import { VideoParticipantType } from "../types"; import VideoParticipant from "./VideoParticipant"; @@ -10,8 +11,10 @@ export interface VideoGalleryProps { } const VideoGallery = ({ participants, flipX, translate }: VideoGalleryProps) => { + const dispatch = useDispatch(); + const gridRef = useRef(null); + const maxSeen = useRef(0); const participantsNumber = participants.length; - const { containerStyle } = useAspectRatio(); const hasOneParticipant = participantsNumber === 1; const sortedParticipants = [...participants].sort((a, b) => { @@ -22,41 +25,73 @@ const VideoGallery = ({ participants, flipX, translate }: VideoGalleryProps) => return a.name.localeCompare(b.name); }); - const getParticipantClasses = () => { - let widthClass = ""; - let heightClass = ""; - + const getLayout = () => { if (hasOneParticipant) { - return "relative aspect-square sm:aspect-video h-full max-w-full"; + return { aspect: "sm:aspect-video", width: "h-full max-w-full" }; } else if (participantsNumber === 2) { - widthClass = "w-[calc(50%-5px)]"; - heightClass = "sm:max-h-[75%]"; - } else if (participantsNumber === 3) { - widthClass = "w-[calc(33.333%-5px)] sm:w-[calc(33%-10px)]"; - heightClass = "sm:max-h-[36%]"; - } else if (participantsNumber === 4) { - widthClass = "w-[calc(50%-5px)]"; - heightClass = "sm:max-h-[36%]"; - } else if (participantsNumber > 4 && participantsNumber < 10) { - widthClass = "w-[calc(50%-5px)] sm:w-[calc(33.333%-7px)]"; - heightClass = "sm:max-h-[24%]"; - } else { - widthClass = "w-[calc(50%-5px)] sm:w-[calc(25%-7px)]"; - heightClass = "sm:max-h-[18%]"; + // 2 cols x 1 row + return { aspect: "sm:aspect-[32/9]", width: "w-[calc(50%-5px)]" }; + } else if (participantsNumber <= 4) { + // 2 cols x 2 rows -> 3 participants wrap to 2 on top, 1 centered below + return { aspect: "sm:aspect-video", width: "w-[calc(50%-5px)]" }; + } else if (participantsNumber <= 6) { + // 3 cols x 2 rows + return { aspect: "sm:aspect-[8/3]", width: "w-[calc(50%-5px)] sm:w-[calc(33.333%-7px)]" }; + } else if (participantsNumber <= 9) { + // 3 cols x 3 rows + return { aspect: "sm:aspect-video", width: "w-[calc(50%-5px)] sm:w-[calc(33.333%-7px)]" }; } + // 10 (room max capacity) -> 4 cols x 3 rows, last row has 2 centered + return { aspect: "sm:aspect-[64/27]", width: "w-[calc(50%-5px)] sm:w-[calc(25%-8px)]" }; + }; - const mobileHeightClass = participantsNumber > 4 ? "max-h-[120px]" : ""; + const { aspect, width } = getLayout(); + const mobileHeightClass = participantsNumber > 4 ? "max-h-[120px] sm:max-h-none" : ""; + const participantClasses = `relative ${width} ${mobileHeightClass} aspect-square sm:aspect-video`; - return `relative ${widthClass} ${heightClass} ${mobileHeightClass} aspect-square sm:aspect-video`; - }; + useEffect(() => { + const grid = gridRef.current; + + if (!grid || participantsNumber === 0) { + return; + } + + const measure = () => { + const tile = grid.firstElementChild; + + if (!tile) { + return; + } + + const { height, width: tileWidth } = tile.getBoundingClientRect(); + + const dpr = window.devicePixelRatio || 1; + + if (height > 0 && tileWidth > 0 && height * dpr > maxSeen.current) { + maxSeen.current = height * dpr; + dispatch(setMeasuredTileViewThumbnailSize( + Math.round(height * dpr), + Math.round(tileWidth * dpr) + )); + } + }; + + const observer = new ResizeObserver(measure); + + observer.observe(grid); + measure(); + + return () => observer.disconnect(); + }, [ dispatch, participantsNumber ]); return (
diff --git a/react/features/base/meet/views/Conference/containers/ConferenceControlsWrapper.tsx b/react/features/base/meet/views/Conference/containers/ConferenceControlsWrapper.tsx index 36b2f7795a61..380b4490e781 100644 --- a/react/features/base/meet/views/Conference/containers/ConferenceControlsWrapper.tsx +++ b/react/features/base/meet/views/Conference/containers/ConferenceControlsWrapper.tsx @@ -80,7 +80,7 @@ const ConferenceControls = ({ inviteUrl={_inviteUrl} />
-
+
{ isVisible={this.state.isBannerVisible} onClose={() => this.setState({ isBannerVisible: false })} /> -
+
{/* */}
diff --git a/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx b/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx index 0e2db7858722..187b1a8a0306 100644 --- a/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx +++ b/react/features/base/meet/views/Conference/containers/VideoGalleryWrapper.tsx @@ -8,7 +8,6 @@ import { startScreenShareFlow } from "../../../../../screen-share/actions.web"; import { isScreenVideoShared } from "../../../../../screen-share/functions"; import { getCurrentConference } from "../../../../conference/functions"; import { translate } from "../../../../i18n/functions"; -import { useAspectRatio } from "../../../general/hooks/useAspectRatio"; import { useParticipantAvatar } from "../../PreMeeting/hooks/useParticipantAvatar"; import VideoGallery from "../components/VideoGallery"; import VideoParticipant from "../components/VideoParticipant"; @@ -29,7 +28,6 @@ interface GalleryVideoWrapperProps extends WithTranslation, OwnProps, MappedStat } const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProps) => { - const { containerStyle } = useAspectRatio(); const participantsScrollRef = useRef(null); const [canScrollUp, setCanScrollUp] = useState(false); const [canScrollDown, setCanScrollDown] = useState(false); @@ -41,7 +39,6 @@ const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProp const flipX = useSelector((state: IReduxState) => state["features/base/settings"].localFlipX); const isLocalSharing = useSelector((state: IReduxState) => isScreenVideoShared(state)); - const contStyle = videoMode === "gallery" ? containerStyle : {}; const hasScreenShare = screenShareParticipants.length > 0; const sharingParticipant = screenShareParticipants[0]; @@ -85,7 +82,7 @@ const GalleryVideoWrapper = ({ videoMode, t, dispatch }: GalleryVideoWrapperProp }, [participants]); return ( -
+
{/* Screen Sharing Notification */} diff --git a/react/features/chat/components/web/Chat.tsx b/react/features/chat/components/web/Chat.tsx index 861307b8313b..547b8b7d7038 100644 --- a/react/features/chat/components/web/Chat.tsx +++ b/react/features/chat/components/web/Chat.tsx @@ -170,6 +170,11 @@ const useStyles = makeStyles<{ userSelect: 'text', WebkitUserSelect: 'text', }, + + '&::selection': { + backgroundColor: '#FFFFFF', + color: '#000000' + }, "@keyframes chatSlideIn": { "0%": { diff --git a/react/features/conference/components/web/Conference.tsx b/react/features/conference/components/web/Conference.tsx index 9dc597fe91d1..c1f21f298dc6 100644 --- a/react/features/conference/components/web/Conference.tsx +++ b/react/features/conference/components/web/Conference.tsx @@ -303,7 +303,7 @@ class Conference extends AbstractConference {
-
+
{/* */}
diff --git a/react/features/e2ee/middleware.ts b/react/features/e2ee/middleware.ts index 8722718c29dc..299139fc9205 100644 --- a/react/features/e2ee/middleware.ts +++ b/react/features/e2ee/middleware.ts @@ -183,9 +183,7 @@ StateListenerRegistry.register( const handlers = new Map(); const sasAvailableHandler = (sas: object) => { - if (ConfigService.instance.isDevelopment()) { - dispatch(openDialog('ParticipantVerificationDialog', ParticipantVerificationSASDialog, { sas })); - } + dispatch(openDialog('ParticipantVerificationDialog', ParticipantVerificationSASDialog, { sas })); }; handlers.set(JitsiConferenceEvents.E2EE_SAS_AVAILABLE, sasAvailableHandler); conference.on(JitsiConferenceEvents.E2EE_SAS_AVAILABLE, sasAvailableHandler); diff --git a/react/features/filmstrip/actions.web.ts b/react/features/filmstrip/actions.web.ts index 64cb793807ce..d9927417ee81 100644 --- a/react/features/filmstrip/actions.web.ts +++ b/react/features/filmstrip/actions.web.ts @@ -110,6 +110,9 @@ export function setTileViewDimensions() { numberOfParticipants, desiredNumberOfVisibleTiles: numberOfVisibleTiles }); + const measured = state['features/filmstrip'].tileViewDimensions?.measured + ? state['features/filmstrip'].tileViewDimensions?.thumbnailSize + : null; const thumbnailsTotalHeight = (rows ?? 1) * (TILE_VERTICAL_MARGIN + (height ?? 0)); const availableHeight = clientHeight - TILE_VIEW_GRID_VERTICAL_MARGIN; const hasScroll = availableHeight < thumbnailsTotalHeight; @@ -127,9 +130,10 @@ export function setTileViewDimensions() { rows }, thumbnailSize: { - height, - width + height: measured?.height ?? height, + width: measured?.width ?? width }, + measured: state['features/filmstrip'].tileViewDimensions?.measured ?? false, filmstripHeight, filmstripWidth, hasScroll @@ -138,6 +142,32 @@ export function setTileViewDimensions() { }; } +/** + * Overrides the tile thumbnail size with one measured from the rendered grid. + * setTileViewDimensions() derives it from the legacy filmstrip geometry, which + * this UI does not render, so it under-reports and the receiver constraints end + * up lower than the tiles actually are. + */ +export function setMeasuredTileViewThumbnailSize(height: number, width: number) { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { + const { tileViewDimensions } = getState()['features/filmstrip']; + + if (tileViewDimensions?.thumbnailSize?.height === height + && tileViewDimensions?.thumbnailSize?.width === width) { + return; + } + + dispatch({ + type: SET_TILE_VIEW_DIMENSIONS, + dimensions: { + ...tileViewDimensions, + measured: true, + thumbnailSize: { height, width } + } + }); + }; +} + /** * Sets the dimensions of the thumbnails in vertical view. * diff --git a/react/features/filmstrip/reducer.ts b/react/features/filmstrip/reducer.ts index 349c0d46a8c5..1071f5a94bd1 100644 --- a/react/features/filmstrip/reducer.ts +++ b/react/features/filmstrip/reducer.ts @@ -212,6 +212,7 @@ interface IFilmstripDimensions { rows: number; }; hasScroll?: boolean; + measured?: boolean; thumbnailSize?: IDimensions; } diff --git a/webpack.config.js b/webpack.config.js index cb6a627e930a..a30d399905e8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -77,6 +77,10 @@ function devServerProxyBypass({ path, headers }) { return "/index.html"; } + if (tpath === "/config.js" || tpath === "/interface_config.js") { + return tpath; + } + if ( tpath.startsWith("/css/") || tpath.startsWith("/doc/") || diff --git a/yarn.lock b/yarn.lock index dca85ce90622..1ba8080291ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3137,9 +3137,9 @@ eslint-scope "5.1.1" "@noble/ciphers@^2.0.1": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-2.2.0.tgz#84fb45ac9332925d643b80f89ceb0ea2f21dba95" - integrity sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-2.4.0.tgz#04cf9e0f1cd3d521e8e5ca92dc0c02238180f676" + integrity sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw== "@noble/curves@~2.0.0": version "2.0.1" @@ -3159,9 +3159,9 @@ integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== "@noble/hashes@^2.0.1": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.2.0.tgz#22da1d16a469954fce877055d559900a6c73b63b" - integrity sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg== + version "2.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.4.0.tgz#e6a3e98edbed3c8659b28bb8f9b18ca02ec8ea4b" + integrity sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA== "@noble/post-quantum@^0.5.2": version "0.5.4" @@ -3300,9 +3300,9 @@ integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== "@protobufjs/utf8@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.1.tgz#eaee5900122c110a3dbcb728c0597014a2621774" - integrity sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg== + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.2.tgz#78d476333d85d5b1c792e257bca74ba080da49a4" + integrity sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug== "@puppeteer/browsers@^2.2.0": version "2.11.0" @@ -5564,9 +5564,9 @@ undici-types "~7.16.0" "@types/node@>=13.7.0": - version "26.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-26.0.0.tgz#d4aece9e9412e9f2008d59bc2d74f5279316b665" - integrity sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA== + version "26.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-26.4.0.tgz#4c4ca071c42241fe602741d02999f16b4e64c468" + integrity sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ== dependencies: undici-types "~8.3.0" @@ -12482,9 +12482,9 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -"lib-meet@https://github.com/internxt/lib-meet/releases/download/v.1.0.2/lib-meet-1.0.2.tgz": - version "1.0.2" - resolved "https://github.com/internxt/lib-meet/releases/download/v.1.0.2/lib-meet-1.0.2.tgz#5195bc96930c0a3fedc9eee52151f2ad5f6d3a4a" +"lib-meet@https://github.com/internxt/lib-meet/releases/download/v.1.0.3/lib-meet-1.0.3.tgz": + version "1.0.3" + resolved "https://github.com/internxt/lib-meet/releases/download/v.1.0.3/lib-meet-1.0.3.tgz#8188f845d75011396e6fb98c854f52b2285a947f" dependencies: "@hexagon/base64" "^2.0.4" "@jitsi/js-utils" "6.3.2" @@ -12501,7 +12501,7 @@ levn@^0.4.1: emoji-regex "10.4.0" jwt-decode "4.0.0" lodash-es "4.18.1" - onnxruntime-web "=1.23.0" + onnxruntime-web "1.29.0" sdp-transform "2.3.0" strophe.js "https://github.com/jitsi/strophejs/releases/download/v1.5-jitsi-3/strophe.js-1.5.0.tgz" uuid "14.0.0" @@ -14171,20 +14171,20 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -onnxruntime-common@1.23.0: - version "1.23.0" - resolved "https://registry.yarnpkg.com/onnxruntime-common/-/onnxruntime-common-1.23.0.tgz#ab254b0725fc837597000e705f885db523d6c37e" - integrity sha512-Auz8S9D7vpF8ok7fzTobvD1XdQDftRf/S7pHmjeCr3Xdymi4z1C7zx4vnT6nnUjbpelZdGwda0BmWHCCTMKUTg== +onnxruntime-common@1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/onnxruntime-common/-/onnxruntime-common-1.29.0.tgz#e489ef9cb17074b5d38b829fa43679b8dcd155b7" + integrity sha512-/F63/e2VJoaVXGGNu6S5QH7jivBThGO95OzAVXXQ8hTta/b1QxI8udHa6cI3+3mAb5WWIIaMMwfZw01oivjJ1g== -onnxruntime-web@=1.23.0: - version "1.23.0" - resolved "https://registry.yarnpkg.com/onnxruntime-web/-/onnxruntime-web-1.23.0.tgz#7e3dd04df7e6d659f7acf1cab6caa706898344e0" - integrity sha512-w0bvC2RwDxphOUFF8jFGZ/dYw+duaX20jM6V4BIZJPCfK4QuCpB/pVREV+hjYbT3x4hyfa2ZbTaWx4e1Vot0fQ== +onnxruntime-web@1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/onnxruntime-web/-/onnxruntime-web-1.29.0.tgz#b5a1670237b4670c40e2468c465af9144fd81aaf" + integrity sha512-LuQlpX6MFLJZu756erwUeb1mNfoJGbs1kzDwJGNlf5RvfYMdqhcY3vNpDPK40CUV2HoWTkIj+uS0o36GFHjeYw== dependencies: flatbuffers "^25.1.24" guid-typescript "^1.0.9" long "^5.2.3" - onnxruntime-common "1.23.0" + onnxruntime-common "1.29.0" platform "^1.3.6" protobufjs "^7.2.4" @@ -14852,9 +14852,9 @@ proto-list@~1.2.1: integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== protobufjs@^7.2.4: - version "7.6.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.6.4.tgz#8bb000300026efd63eb7951d26e5dbb38f5658f2" - integrity sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw== + version "7.6.6" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.6.6.tgz#7a3923e8e32b0ee2ff689f8eed6e455c090ac67e" + integrity sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2"