use custom chat
This commit is contained in:
parent
c50b2319b0
commit
5b1c6d2deb
244
package-lock.json
generated
244
package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@dcl/crypto": "^3.4.3",
|
||||
"@dcl/protocol": "^1.0.0-5810343446.commit-4ee6d08",
|
||||
"@dcl/schemas": "^7.4.1",
|
||||
"@dcl/social-rpc-client": "^0.0.0-20230725183127.commit-e0fdbae",
|
||||
"@dcl/ui-env": "^1.4.0",
|
||||
@ -30,7 +31,8 @@
|
||||
"react-virtualized-auto-sizer": "^1.0.20",
|
||||
"react-window": "^1.8.9",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-saga": "^1.2.3"
|
||||
"redux-saga": "^1.2.3",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcl/eslint-config": "1.1.7",
|
||||
@ -1258,6 +1260,17 @@
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/@coinbase/wallet-sdk/node_modules/rxjs": {
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||
"dependencies": {
|
||||
"tslib": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
@ -1342,6 +1355,14 @@
|
||||
"multiformats": "^9.6.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/protocol": {
|
||||
"version": "1.0.0-5810343446.commit-4ee6d08",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-5810343446.commit-4ee6d08.tgz",
|
||||
"integrity": "sha512-9vhbn+IfdOn1qnJa7PE6kLsmT2G0pYoUXi2ydEelStEQw6Rkvfhc564mAx1zz+xLz7ZSE+9gWit90zroHNvavw==",
|
||||
"dependencies": {
|
||||
"@dcl/ts-proto": "1.154.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/rpc": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/rpc/-/rpc-1.1.2.tgz",
|
||||
@ -1415,6 +1436,65 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/ts-proto": {
|
||||
"version": "1.154.0",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/ts-proto/-/ts-proto-1.154.0.tgz",
|
||||
"integrity": "sha512-2S5AKMMPVZrVfa/1WRy4/h0niikcbu3Yf6dCoudh7ScG7BsyKAPC3CMg6IJKHzrmWS593UZClq7YJof6Vt4O+w==",
|
||||
"dependencies": {
|
||||
"@types/object-hash": "^3.0.2",
|
||||
"case-anything": "^2.1.10",
|
||||
"dataloader": "^1.4.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"protobufjs": "^7.2.4",
|
||||
"ts-poet": "^6.4.1",
|
||||
"ts-proto-descriptors": "^1.15.0"
|
||||
},
|
||||
"bin": {
|
||||
"protoc-gen-dcl_ts_proto": "protoc-gen-dcl_ts_proto"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/ts-proto/node_modules/@types/node": {
|
||||
"version": "20.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz",
|
||||
"integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ=="
|
||||
},
|
||||
"node_modules/@dcl/ts-proto/node_modules/long": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||
},
|
||||
"node_modules/@dcl/ts-proto/node_modules/protobufjs": {
|
||||
"version": "7.2.4",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz",
|
||||
"integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.2",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@protobufjs/codegen": "^2.0.4",
|
||||
"@protobufjs/eventemitter": "^1.1.0",
|
||||
"@protobufjs/fetch": "^1.1.0",
|
||||
"@protobufjs/float": "^1.0.2",
|
||||
"@protobufjs/inquire": "^1.1.0",
|
||||
"@protobufjs/path": "^1.1.2",
|
||||
"@protobufjs/pool": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.0",
|
||||
"@types/node": ">=13.7.0",
|
||||
"long": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/ts-proto/node_modules/ts-proto-descriptors": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.15.0.tgz",
|
||||
"integrity": "sha512-TYyJ7+H+7Jsqawdv+mfsEpZPTIj9siDHS6EMCzG/z3b/PZiphsX+mWtqFfFVe5/N0Th6V3elK9lQqjnrgTOfrg==",
|
||||
"dependencies": {
|
||||
"long": "^5.2.3",
|
||||
"protobufjs": "^7.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcl/ui-env": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/ui-env/-/ui-env-1.4.0.tgz",
|
||||
@ -3413,19 +3493,6 @@
|
||||
"livekit-client": "^1.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@livekit/components-core/node_modules/rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@livekit/components-core/node_modules/tslib": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
||||
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
|
||||
},
|
||||
"node_modules/@livekit/components-react": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@livekit/components-react/-/components-react-1.0.8.tgz",
|
||||
@ -4860,6 +4927,11 @@
|
||||
"form-data": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/object-hash": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-3.0.2.tgz",
|
||||
"integrity": "sha512-tfyXl1JPCf2hzIDK29gO7qGqJjThKBzg/Cn3bA68R9NmWdOx+f7k5mm4to/n43BHspCwcoUC6FU4NpUoK/h9bQ=="
|
||||
},
|
||||
"node_modules/@types/pbkdf2": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
|
||||
@ -7999,6 +8071,11 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/dataloader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
@ -15406,6 +15483,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-hash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
@ -17335,16 +17420,18 @@
|
||||
"integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA=="
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"dependencies": {
|
||||
"tslib": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=2.0.0"
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs/node_modules/tslib": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
||||
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@ -20629,6 +20716,14 @@
|
||||
"version": "10.16.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.16.0.tgz",
|
||||
"integrity": "sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA=="
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -20717,6 +20812,14 @@
|
||||
"multiformats": "^9.6.3"
|
||||
}
|
||||
},
|
||||
"@dcl/protocol": {
|
||||
"version": "1.0.0-5810343446.commit-4ee6d08",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-5810343446.commit-4ee6d08.tgz",
|
||||
"integrity": "sha512-9vhbn+IfdOn1qnJa7PE6kLsmT2G0pYoUXi2ydEelStEQw6Rkvfhc564mAx1zz+xLz7ZSE+9gWit90zroHNvavw==",
|
||||
"requires": {
|
||||
"@dcl/ts-proto": "1.154.0"
|
||||
}
|
||||
},
|
||||
"@dcl/rpc": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/rpc/-/rpc-1.1.2.tgz",
|
||||
@ -20774,6 +20877,60 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dcl/ts-proto": {
|
||||
"version": "1.154.0",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/ts-proto/-/ts-proto-1.154.0.tgz",
|
||||
"integrity": "sha512-2S5AKMMPVZrVfa/1WRy4/h0niikcbu3Yf6dCoudh7ScG7BsyKAPC3CMg6IJKHzrmWS593UZClq7YJof6Vt4O+w==",
|
||||
"requires": {
|
||||
"@types/object-hash": "^3.0.2",
|
||||
"case-anything": "^2.1.10",
|
||||
"dataloader": "^1.4.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"protobufjs": "^7.2.4",
|
||||
"ts-poet": "^6.4.1",
|
||||
"ts-proto-descriptors": "^1.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "20.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz",
|
||||
"integrity": "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ=="
|
||||
},
|
||||
"long": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||
},
|
||||
"protobufjs": {
|
||||
"version": "7.2.4",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz",
|
||||
"integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==",
|
||||
"requires": {
|
||||
"@protobufjs/aspromise": "^1.1.2",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@protobufjs/codegen": "^2.0.4",
|
||||
"@protobufjs/eventemitter": "^1.1.0",
|
||||
"@protobufjs/fetch": "^1.1.0",
|
||||
"@protobufjs/float": "^1.0.2",
|
||||
"@protobufjs/inquire": "^1.1.0",
|
||||
"@protobufjs/path": "^1.1.2",
|
||||
"@protobufjs/pool": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.0",
|
||||
"@types/node": ">=13.7.0",
|
||||
"long": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"ts-proto-descriptors": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.15.0.tgz",
|
||||
"integrity": "sha512-TYyJ7+H+7Jsqawdv+mfsEpZPTIj9siDHS6EMCzG/z3b/PZiphsX+mWtqFfFVe5/N0Th6V3elK9lQqjnrgTOfrg==",
|
||||
"requires": {
|
||||
"long": "^5.2.3",
|
||||
"protobufjs": "^7.2.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dcl/ui-env": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@dcl/ui-env/-/ui-env-1.4.0.tgz",
|
||||
@ -22089,21 +22246,6 @@
|
||||
"global-tld-list": "^0.0.1139",
|
||||
"loglevel": "^1.8.1",
|
||||
"rxjs": "^7.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
||||
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@livekit/components-react": {
|
||||
@ -23283,6 +23425,11 @@
|
||||
"form-data": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"@types/object-hash": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-3.0.2.tgz",
|
||||
"integrity": "sha512-tfyXl1JPCf2hzIDK29gO7qGqJjThKBzg/Cn3bA68R9NmWdOx+f7k5mm4to/n43BHspCwcoUC6FU4NpUoK/h9bQ=="
|
||||
},
|
||||
"@types/pbkdf2": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
|
||||
@ -25809,6 +25956,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataloader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
|
||||
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
@ -31519,6 +31671,11 @@
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
},
|
||||
"object-hash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
@ -32927,11 +33084,18 @@
|
||||
"integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA=="
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
||||
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@dcl/crypto": "^3.4.3",
|
||||
"@dcl/protocol": "^1.0.0-5810343446.commit-4ee6d08",
|
||||
"@dcl/schemas": "^7.4.1",
|
||||
"@dcl/social-rpc-client": "^0.0.0-20230725183127.commit-e0fdbae",
|
||||
"@dcl/ui-env": "^1.4.0",
|
||||
@ -38,7 +39,8 @@
|
||||
"react-virtualized-auto-sizer": "^1.0.20",
|
||||
"react-window": "^1.8.9",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-saga": "^1.2.3"
|
||||
"redux-saga": "^1.2.3",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcl/eslint-config": "1.1.7",
|
||||
|
||||
129
src/components/VideoConference/Chat/Chat.tsx
Normal file
129
src/components/VideoConference/Chat/Chat.tsx
Normal file
@ -0,0 +1,129 @@
|
||||
import type { ChatMessage, ReceivedChatMessage } from '@livekit/components-core'
|
||||
import { ChatEntry, MessageFormatter, useMaybeLayoutContext, useRoomContext } from '@livekit/components-react'
|
||||
import * as React from 'react'
|
||||
import { cloneSingleChild, setupChat, useObservableState } from './utils'
|
||||
|
||||
export type { ChatMessage, ReceivedChatMessage }
|
||||
|
||||
export interface ChatProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
messageFormatter?: MessageFormatter
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function useChat() {
|
||||
const room = useRoomContext()
|
||||
const [setup, setSetup] = React.useState<ReturnType<typeof setupChat>>()
|
||||
const isSending = useObservableState(setup?.isSendingObservable, false)
|
||||
const chatMessages = useObservableState(setup?.messageObservable, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
const setupChatReturn = setupChat(room)
|
||||
setSetup(setupChatReturn)
|
||||
return setupChatReturn.destroy
|
||||
}, [room])
|
||||
|
||||
return { send: setup?.send, chatMessages, isSending }
|
||||
}
|
||||
|
||||
/**
|
||||
* The Chat component adds a basis chat functionality to the LiveKit room. The messages are distributed to all participants
|
||||
* in the room. Only users who are in the room at the time of dispatch will receive the message.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <LiveKitRoom>
|
||||
* <Chat />
|
||||
* </LiveKitRoom>
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export default function Chat({ messageFormatter, ...props }: ChatProps) {
|
||||
const inputRef = React.useRef<HTMLInputElement>(null)
|
||||
const ulRef = React.useRef<HTMLUListElement>(null)
|
||||
|
||||
const { send, chatMessages, isSending } = useChat()
|
||||
|
||||
const layoutContext = useMaybeLayoutContext()
|
||||
const lastReadMsgAt = React.useRef<ChatMessage['timestamp']>(0)
|
||||
|
||||
async function handleSubmit(event: React.FormEvent) {
|
||||
event.preventDefault()
|
||||
if (inputRef.current && inputRef.current.value.trim() !== '') {
|
||||
if (send) {
|
||||
await send(inputRef.current.value)
|
||||
inputRef.current.value = ''
|
||||
inputRef.current.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (ulRef) {
|
||||
ulRef.current?.scrollTo({ top: ulRef.current.scrollHeight })
|
||||
}
|
||||
}, [ulRef, chatMessages])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!layoutContext || chatMessages.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
layoutContext.widget.state?.showChat &&
|
||||
chatMessages.length > 0 &&
|
||||
lastReadMsgAt.current !== chatMessages[chatMessages.length - 1]?.timestamp
|
||||
) {
|
||||
lastReadMsgAt.current = chatMessages[chatMessages.length - 1]?.timestamp
|
||||
return
|
||||
}
|
||||
|
||||
const unreadMessageCount = chatMessages.filter(msg => !lastReadMsgAt.current || msg.timestamp > lastReadMsgAt.current).length
|
||||
|
||||
const { widget } = layoutContext
|
||||
if (unreadMessageCount > 0 && widget.state?.unreadMessages !== unreadMessageCount) {
|
||||
widget.dispatch?.({ msg: 'unread_msg', count: unreadMessageCount })
|
||||
}
|
||||
}, [chatMessages, layoutContext?.widget])
|
||||
|
||||
return (
|
||||
<div {...props} className="lk-chat">
|
||||
<ul className="lk-list lk-chat-messages" ref={ulRef}>
|
||||
{props.children
|
||||
? chatMessages.map((msg, idx) =>
|
||||
cloneSingleChild(props.children, {
|
||||
entry: msg,
|
||||
key: idx,
|
||||
messageFormatter
|
||||
})
|
||||
)
|
||||
: chatMessages.map((msg, idx, allMsg) => {
|
||||
const hideName = idx >= 1 && allMsg[idx - 1].from === msg.from
|
||||
// If the time delta between two messages is bigger than 60s show timestamp.
|
||||
const hideTimestamp = idx >= 1 && msg.timestamp - allMsg[idx - 1].timestamp < 60_000
|
||||
|
||||
return (
|
||||
<ChatEntry
|
||||
key={idx}
|
||||
hideName={hideName}
|
||||
hideTimestamp={hideName === false ? false : hideTimestamp} // If we show the name always show the timestamp as well.
|
||||
entry={msg}
|
||||
messageFormatter={messageFormatter}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
<form className="lk-chat-form" onSubmit={handleSubmit}>
|
||||
<input
|
||||
className="lk-form-control lk-chat-form-input"
|
||||
disabled={isSending}
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
placeholder="Enter a message..."
|
||||
/>
|
||||
<button type="submit" className="lk-button lk-chat-form-button" disabled={isSending}>
|
||||
Send
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
2
src/components/VideoConference/Chat/index.ts
Normal file
2
src/components/VideoConference/Chat/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import Chat from './Chat'
|
||||
export default Chat
|
||||
97
src/components/VideoConference/Chat/utils.ts
Normal file
97
src/components/VideoConference/Chat/utils.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { DataTopic, sendMessage, setupDataMessageHandler } from '@livekit/components-core'
|
||||
import { ReceivedChatMessage } from '@livekit/components-react'
|
||||
import { DataPacket_Kind, Participant, Room } from 'livekit-client'
|
||||
import * as React from 'react'
|
||||
import { BehaviorSubject, Subject, takeUntil, map, scan, filter } from 'rxjs'
|
||||
import type { Observable } from 'rxjs'
|
||||
import { Packet } from '@dcl/protocol/out-js/decentraland/kernel/comms/rfc4/comms.gen'
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function useObservableState<T>(observable: Observable<T> | undefined, startWith: T) {
|
||||
const [state, setState] = React.useState<T>(startWith)
|
||||
React.useEffect(() => {
|
||||
// observable state doesn't run in SSR
|
||||
if (typeof window === 'undefined' || !observable) return
|
||||
const subscription = observable.subscribe(setState)
|
||||
return () => subscription.unsubscribe()
|
||||
}, [observable])
|
||||
return state
|
||||
}
|
||||
|
||||
export function cloneSingleChild(children: React.ReactNode | React.ReactNode[], props?: Record<string, any>, key?: any) {
|
||||
return React.Children.map(children, child => {
|
||||
// Checking isValidElement is the safe way and avoids a typescript
|
||||
// error too.
|
||||
if (React.isValidElement(child) && React.Children.only(children)) {
|
||||
return React.cloneElement(child, { ...props, key })
|
||||
}
|
||||
return child
|
||||
})
|
||||
}
|
||||
|
||||
export function setupChat(room: Room) {
|
||||
const onDestroyObservable = new Subject<void>()
|
||||
const messageSubject = new Subject<{
|
||||
payload: Uint8Array
|
||||
topic: string | undefined
|
||||
from: Participant | undefined
|
||||
}>()
|
||||
|
||||
/** Subscribe to all messages send over the wire. */
|
||||
const { messageObservable } = setupDataMessageHandler(room)
|
||||
messageObservable.pipe(takeUntil(onDestroyObservable)).subscribe(messageSubject)
|
||||
|
||||
/** Build up the message array over time. */
|
||||
const messagesObservable = messageSubject.pipe(
|
||||
map(msg => {
|
||||
const packet = Packet.decode(msg.payload)
|
||||
return { packet, msg }
|
||||
}),
|
||||
filter(({ packet }) => packet.message?.$case === 'chat'),
|
||||
map(({ packet, msg }) => {
|
||||
if (packet.message?.$case === 'chat') {
|
||||
const { timestamp, message } = packet.message.chat
|
||||
return { from: msg.from, timestamp, message }
|
||||
}
|
||||
throw new Error('Found msg without chat')
|
||||
}),
|
||||
scan<ReceivedChatMessage, ReceivedChatMessage[]>((acc, value) => [...acc, value], []),
|
||||
takeUntil(onDestroyObservable)
|
||||
)
|
||||
|
||||
const isSending$ = new BehaviorSubject<boolean>(false)
|
||||
|
||||
const send = async (message: string) => {
|
||||
const encodedMsg = Packet.encode({
|
||||
message: {
|
||||
$case: 'chat',
|
||||
chat: {
|
||||
timestamp: Date.now(),
|
||||
message: message
|
||||
}
|
||||
}
|
||||
}).finish()
|
||||
isSending$.next(true)
|
||||
try {
|
||||
await sendMessage(room.localParticipant, encodedMsg, undefined, {
|
||||
kind: DataPacket_Kind.RELIABLE
|
||||
})
|
||||
messageSubject.next({
|
||||
payload: encodedMsg,
|
||||
topic: DataTopic.CHAT,
|
||||
from: room.localParticipant
|
||||
})
|
||||
} finally {
|
||||
isSending$.next(false)
|
||||
}
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
onDestroyObservable.next()
|
||||
onDestroyObservable.complete()
|
||||
}
|
||||
|
||||
return { messageObservable: messagesObservable, isSendingObservable: isSending$, send, destroy }
|
||||
}
|
||||
@ -2,7 +2,6 @@ import * as React from 'react'
|
||||
import { isEqualTrackRef, isTrackReference, log, isWeb } from '@livekit/components-core'
|
||||
import {
|
||||
CarouselView,
|
||||
Chat,
|
||||
ConnectionStateToast,
|
||||
ControlBar,
|
||||
FocusLayout,
|
||||
@ -14,11 +13,34 @@ import {
|
||||
useCreateLayoutContext,
|
||||
// useParticipants,
|
||||
usePinnedTracks,
|
||||
useTracks
|
||||
useTracks,
|
||||
MessageEncoder,
|
||||
MessageDecoder
|
||||
} from '@livekit/components-react'
|
||||
import { RoomEvent, Track } from 'livekit-client'
|
||||
import ParticipantTile from './ParticipantTile'
|
||||
import type { TrackReferenceOrPlaceholder, WidgetState } from '@livekit/components-core'
|
||||
import { ChatMessage } from '@livekit/components-react'
|
||||
import { Packet } from '@dcl/protocol/out-js/decentraland/kernel/comms/rfc4/comms.gen'
|
||||
import Chat from './Chat'
|
||||
|
||||
const messageDecoder: MessageDecoder = (message: Uint8Array) => {
|
||||
const packet = Packet.decode(message)
|
||||
if (packet.message && packet.message.$case === 'chat') {
|
||||
const { timestamp, message } = packet.message.chat
|
||||
return { timestamp, message }
|
||||
} else if (packet.message?.$case === 'position') {
|
||||
}
|
||||
|
||||
return {
|
||||
message: 'Error',
|
||||
timestamp: 0
|
||||
}
|
||||
}
|
||||
|
||||
const messageEncoder: MessageEncoder = (message: ChatMessage) => {
|
||||
return new Uint8Array()
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -44,7 +66,7 @@ export interface VideoConferenceProps extends React.HTMLAttributes<HTMLDivElemen
|
||||
* @public
|
||||
*/
|
||||
export function VideoConference({ chatMessageFormatter, ...props }: VideoConferenceProps) {
|
||||
const [widgetState, setWidgetState] = React.useState<WidgetState>({ showChat: false })
|
||||
const [widgetState, setWidgetState] = React.useState<WidgetState>({ showChat: false, unreadMessages: 0 })
|
||||
const lastAutoFocusedScreenShareTrack = React.useRef<TrackReferenceOrPlaceholder | null>(null)
|
||||
|
||||
const tracks = useTracks(
|
||||
@ -115,7 +137,12 @@ export function VideoConference({ chatMessageFormatter, ...props }: VideoConfere
|
||||
)}
|
||||
<ControlBar controls={{ chat: true }} />
|
||||
</div>
|
||||
<Chat style={{ display: widgetState.showChat ? 'flex' : 'none' }} messageFormatter={chatMessageFormatter} />
|
||||
<Chat
|
||||
style={{ display: widgetState.showChat ? 'flex' : 'none' }}
|
||||
messageFormatter={chatMessageFormatter}
|
||||
messageEncoder={messageEncoder}
|
||||
messageDecoder={messageDecoder}
|
||||
/>
|
||||
</LayoutContextProvider>
|
||||
)}
|
||||
<RoomAudioRenderer />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user