[WIP] Update
This commit is contained in:
@ -28,19 +28,24 @@
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@excalidraw/excalidraw": "^0.15.2",
|
||||
"@fontsource/roboto": "^5.0.5",
|
||||
"@mui/icons-material": "^5.14.1",
|
||||
"@mui/material": "^5.14.1",
|
||||
"@mui/styled-engine-sc": "^5.12.0",
|
||||
"dexie": "^3.2.4",
|
||||
"dexie-react-hooks": "^1.1.6",
|
||||
"i18next": "^23.2.11",
|
||||
"i18next-browser-languagedetector": "^7.1.0",
|
||||
"i18next-http-backend": "^2.2.1",
|
||||
"jotai": "^2.2.2",
|
||||
"just-diff": "^6.0.2",
|
||||
"just-diff-apply": "^5.5.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^13.0.2",
|
||||
"react-router-dom": "^6.14.2",
|
||||
"styled-components": "^6.0.4",
|
||||
"ts-pattern": "^5.0.4",
|
||||
|
292
pnpm-lock.yaml
generated
292
pnpm-lock.yaml
generated
@ -5,6 +5,12 @@ settings:
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@emotion/react':
|
||||
specifier: ^11.11.1
|
||||
version: 11.11.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.14)(react@18.2.0)
|
||||
'@excalidraw/excalidraw':
|
||||
specifier: ^0.15.2
|
||||
version: 0.15.2(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -16,16 +22,22 @@ dependencies:
|
||||
version: 5.14.1(@mui/material@5.14.1)(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/material':
|
||||
specifier: ^5.14.1
|
||||
version: 5.14.1(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mui/styled-engine-sc':
|
||||
specifier: ^5.12.0
|
||||
version: 5.12.0(styled-components@6.0.4)
|
||||
version: 5.14.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
|
||||
dexie:
|
||||
specifier: ^3.2.4
|
||||
version: 3.2.4
|
||||
dexie-react-hooks:
|
||||
specifier: ^1.1.6
|
||||
version: 1.1.6(@types/react@18.2.14)(dexie@3.2.4)(react@18.2.0)
|
||||
i18next:
|
||||
specifier: ^23.2.11
|
||||
version: 23.2.11
|
||||
i18next-browser-languagedetector:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
i18next-http-backend:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
jotai:
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2(react@18.2.0)
|
||||
@ -44,6 +56,9 @@ dependencies:
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
react-i18next:
|
||||
specifier: ^13.0.2
|
||||
version: 13.0.2(i18next@23.2.11)(react-dom@18.2.0)(react@18.2.0)
|
||||
react-router-dom:
|
||||
specifier: ^6.14.2
|
||||
version: 6.14.2(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -1456,6 +1471,22 @@ packages:
|
||||
to-fast-properties: 2.0.0
|
||||
dev: false
|
||||
|
||||
/@emotion/babel-plugin@11.11.0:
|
||||
resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==}
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.22.5
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/hash': 0.9.1
|
||||
'@emotion/memoize': 0.8.1
|
||||
'@emotion/serialize': 1.1.2
|
||||
babel-plugin-macros: 3.1.0
|
||||
convert-source-map: 1.9.0
|
||||
escape-string-regexp: 4.0.0
|
||||
find-root: 1.1.0
|
||||
source-map: 0.5.7
|
||||
stylis: 4.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/cache@11.11.0:
|
||||
resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==}
|
||||
dependencies:
|
||||
@ -1466,6 +1497,10 @@ packages:
|
||||
stylis: 4.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/hash@0.9.1:
|
||||
resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==}
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@1.2.1:
|
||||
resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==}
|
||||
dependencies:
|
||||
@ -1476,14 +1511,74 @@ packages:
|
||||
resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/react@11.11.1(@types/react@18.2.14)(react@18.2.0):
|
||||
resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/babel-plugin': 11.11.0
|
||||
'@emotion/cache': 11.11.0
|
||||
'@emotion/serialize': 1.1.2
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0)
|
||||
'@emotion/utils': 1.2.1
|
||||
'@emotion/weak-memoize': 0.3.1
|
||||
'@types/react': 18.2.14
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/serialize@1.1.2:
|
||||
resolution: {integrity: sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==}
|
||||
dependencies:
|
||||
'@emotion/hash': 0.9.1
|
||||
'@emotion/memoize': 0.8.1
|
||||
'@emotion/unitless': 0.8.1
|
||||
'@emotion/utils': 1.2.1
|
||||
csstype: 3.1.2
|
||||
dev: false
|
||||
|
||||
/@emotion/sheet@1.2.2:
|
||||
resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.14)(react@18.2.0):
|
||||
resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.0.0-rc.0
|
||||
'@types/react': '*'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/babel-plugin': 11.11.0
|
||||
'@emotion/is-prop-valid': 1.2.1
|
||||
'@emotion/react': 11.11.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@emotion/serialize': 1.1.2
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0)
|
||||
'@emotion/utils': 1.2.1
|
||||
'@types/react': 18.2.14
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/unitless@0.8.1:
|
||||
resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
|
||||
dev: false
|
||||
|
||||
/@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/utils@1.2.1:
|
||||
resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==}
|
||||
dev: false
|
||||
@ -1839,12 +1934,12 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@mui/material': 5.14.1(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mui/material': 5.14.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@types/react': 18.2.14
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mui/material@5.14.1(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0):
|
||||
/@mui/material@5.14.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-WtsgYuageTunLfxH3Ri+o1RuQTFImtRHxMcVNyD0Hhd2/znjW6KODNz0XfjvLRnNCAynBxZNiflcoIBW40h9PQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
@ -1862,9 +1957,11 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/react': 11.11.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/base': 5.0.0-beta.8(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mui/core-downloads-tracker': 5.14.1
|
||||
'@mui/system': 5.14.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/system': 5.14.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/types': 7.2.4(@types/react@18.2.14)
|
||||
'@mui/utils': 5.14.1(react@18.2.0)
|
||||
'@types/react': 18.2.14
|
||||
@ -1895,22 +1992,7 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mui/styled-engine-sc@5.12.0(styled-components@6.0.4):
|
||||
resolution: {integrity: sha512-3MgYoY2YG5tx0E5oKqvCv94oL0ABVBr+qpcyvciXW/v0wzPG6bXvuZV80GHYlJfasgnnRa1AbRWf5a9FcX8v6g==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@types/styled-components': ^5.1.14
|
||||
styled-components: ^5.3.1
|
||||
peerDependenciesMeta:
|
||||
'@types/styled-components':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
prop-types: 15.8.1
|
||||
styled-components: 6.0.4(react-dom@18.2.0)(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@mui/styled-engine@5.13.2(react@18.2.0):
|
||||
/@mui/styled-engine@5.13.2(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
@ -1925,12 +2007,14 @@ packages:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/cache': 11.11.0
|
||||
'@emotion/react': 11.11.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.14)(react@18.2.0)
|
||||
csstype: 3.1.2
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mui/system@5.14.1(@types/react@18.2.14)(react@18.2.0):
|
||||
/@mui/system@5.14.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.14)(react@18.2.0):
|
||||
resolution: {integrity: sha512-u+xlsU34Jdkgx1CxmBnIC4Y08uPdVX5iEd3S/1dggDFtOGp+Lj8xmKRJAQ8PJOOJLOh8pDwaZx4AwXikL4l1QA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
@ -1947,8 +2031,10 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@emotion/react': 11.11.1(@types/react@18.2.14)(react@18.2.0)
|
||||
'@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/private-theming': 5.13.7(@types/react@18.2.14)(react@18.2.0)
|
||||
'@mui/styled-engine': 5.13.2(react@18.2.0)
|
||||
'@mui/styled-engine': 5.13.2(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0)
|
||||
'@mui/types': 7.2.4(@types/react@18.2.14)
|
||||
'@mui/utils': 5.14.1(react@18.2.0)
|
||||
'@types/react': 18.2.14
|
||||
@ -2156,6 +2242,10 @@ packages:
|
||||
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
|
||||
dev: true
|
||||
|
||||
/@types/parse-json@4.0.0:
|
||||
resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
|
||||
dev: false
|
||||
|
||||
/@types/prop-types@15.7.5:
|
||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
||||
|
||||
@ -2449,6 +2539,15 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/babel-plugin-macros@3.1.0:
|
||||
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
cosmiconfig: 7.1.0
|
||||
resolve: 1.22.2
|
||||
dev: false
|
||||
|
||||
/babel-plugin-polyfill-corejs2@0.4.4(@babel/core@7.22.9):
|
||||
resolution: {integrity: sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==}
|
||||
peerDependencies:
|
||||
@ -2545,7 +2644,6 @@ packages:
|
||||
/callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/camelize@1.0.1:
|
||||
resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
|
||||
@ -2672,6 +2770,25 @@ packages:
|
||||
browserslist: 4.21.9
|
||||
dev: false
|
||||
|
||||
/cosmiconfig@7.1.0:
|
||||
resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
'@types/parse-json': 4.0.0
|
||||
import-fresh: 3.3.0
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
yaml: 1.10.2
|
||||
dev: false
|
||||
|
||||
/cross-fetch@3.1.6:
|
||||
resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==}
|
||||
dependencies:
|
||||
node-fetch: 2.6.12
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
dev: false
|
||||
|
||||
/cross-spawn@6.0.5:
|
||||
resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==}
|
||||
engines: {node: '>=4.8'}
|
||||
@ -2810,7 +2927,6 @@ packages:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
dev: true
|
||||
|
||||
/es-abstract@1.22.1:
|
||||
resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==}
|
||||
@ -2917,7 +3033,6 @@ packages:
|
||||
/escape-string-regexp@4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-react-hooks@4.6.0(eslint@8.44.0):
|
||||
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
|
||||
@ -3099,6 +3214,10 @@ packages:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
/find-root@1.1.0:
|
||||
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
|
||||
dev: false
|
||||
|
||||
/find-up@5.0.0:
|
||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
||||
engines: {node: '>=10'}
|
||||
@ -3333,10 +3452,22 @@ packages:
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
|
||||
/hoist-non-react-statics@3.3.2:
|
||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||
dependencies:
|
||||
react-is: 16.13.1
|
||||
dev: false
|
||||
|
||||
/hosted-git-info@2.8.9:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
dev: true
|
||||
|
||||
/html-parse-stringify@3.0.1:
|
||||
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
|
||||
dependencies:
|
||||
void-elements: 3.1.0
|
||||
dev: false
|
||||
|
||||
/http-cache-semantics@4.1.1:
|
||||
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
|
||||
dev: true
|
||||
@ -3360,6 +3491,26 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/i18next-browser-languagedetector@7.1.0:
|
||||
resolution: {integrity: sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
dev: false
|
||||
|
||||
/i18next-http-backend@2.2.1:
|
||||
resolution: {integrity: sha512-ZXIdn/8NJIBJ0X4hzXfc3STYxKrCKh1fYjji9HPyIpEJfvTvy8/ZlTl8RuTizzCPj2ZcWrfaecyOMKs6bQ7u5A==}
|
||||
dependencies:
|
||||
cross-fetch: 3.1.6
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
dev: false
|
||||
|
||||
/i18next@23.2.11:
|
||||
resolution: {integrity: sha512-MA4FsxOjyCaOZtRDB4yuwjCvqYEioD4G4LlXOn7SO3rnQUlxTufyLsOqfL9MKakeLRBkefe8bqcs0D6Z/xFk1w==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
dev: false
|
||||
|
||||
/ignore@5.2.4:
|
||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||
engines: {node: '>= 4'}
|
||||
@ -3371,7 +3522,6 @@ packages:
|
||||
dependencies:
|
||||
parent-module: 1.0.1
|
||||
resolve-from: 4.0.0
|
||||
dev: true
|
||||
|
||||
/imurmurhash@0.1.4:
|
||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||
@ -3415,7 +3565,6 @@ packages:
|
||||
|
||||
/is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
dev: true
|
||||
|
||||
/is-bigint@1.0.4:
|
||||
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
|
||||
@ -3593,6 +3742,10 @@ packages:
|
||||
resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
|
||||
dev: true
|
||||
|
||||
/json-parse-even-better-errors@2.3.1:
|
||||
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
|
||||
dev: false
|
||||
|
||||
/json-schema-traverse@0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
dev: true
|
||||
@ -3660,6 +3813,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: false
|
||||
|
||||
/lint-staged@13.2.3:
|
||||
resolution: {integrity: sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==}
|
||||
engines: {node: ^14.13.1 || >=16.0.0}
|
||||
@ -3854,6 +4011,18 @@ packages:
|
||||
tslib: 2.6.0
|
||||
dev: true
|
||||
|
||||
/node-fetch@2.6.12:
|
||||
resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
dev: false
|
||||
|
||||
/node-releases@2.0.13:
|
||||
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
|
||||
dev: false
|
||||
@ -3985,7 +4154,6 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
callsites: 3.1.0
|
||||
dev: true
|
||||
|
||||
/parse-json@4.0.0:
|
||||
resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
|
||||
@ -3995,6 +4163,16 @@ packages:
|
||||
json-parse-better-errors: 1.0.2
|
||||
dev: true
|
||||
|
||||
/parse-json@5.2.0:
|
||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.5
|
||||
error-ex: 1.3.2
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 1.2.4
|
||||
dev: false
|
||||
|
||||
/path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
@ -4032,7 +4210,6 @@ packages:
|
||||
/path-type@4.0.0:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/picocolors@1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
@ -4136,6 +4313,26 @@ packages:
|
||||
scheduler: 0.23.0
|
||||
dev: false
|
||||
|
||||
/react-i18next@13.0.2(i18next@23.2.11)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-NEVxC32v0oR4egwYM0QM0WE93AiJG5r0NTXTL8mhQfAhsMfDS2fSO6jpluyfsfypP988KzUQrAXncspcJ7+GHA==}
|
||||
peerDependencies:
|
||||
i18next: '>= 23.2.3'
|
||||
react: '>= 16.8.0'
|
||||
react-dom: '*'
|
||||
react-native: '*'
|
||||
peerDependenciesMeta:
|
||||
react-dom:
|
||||
optional: true
|
||||
react-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
html-parse-stringify: 3.0.1
|
||||
i18next: 23.2.11
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
dev: false
|
||||
@ -4261,7 +4458,6 @@ packages:
|
||||
/resolve-from@4.0.0:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/resolve@1.22.2:
|
||||
resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
|
||||
@ -4455,6 +4651,11 @@ packages:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/source-map@0.5.7:
|
||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/spdx-correct@3.2.0:
|
||||
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
|
||||
dependencies:
|
||||
@ -4664,6 +4865,10 @@ packages:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
||||
/tr46@0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
dev: false
|
||||
|
||||
/ts-pattern@5.0.4:
|
||||
resolution: {integrity: sha512-D5iVliqugv2C9541W2CNXFYNEZxr4TiHuLPuf49tKEdQFp/8y8fR0v1RExUvXkiWozKCwE7zv07C6EKxf0lKuQ==}
|
||||
dev: false
|
||||
@ -4882,6 +5087,22 @@ packages:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/void-elements@3.1.0:
|
||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
dev: false
|
||||
|
||||
/whatwg-url@5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
dev: false
|
||||
|
||||
/which-boxed-primitive@1.0.2:
|
||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||
dependencies:
|
||||
@ -4947,6 +5168,11 @@ packages:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
||||
/yaml@1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/yaml@2.3.1:
|
||||
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
@ -3,7 +3,7 @@ import ExcalidrawContainer from './Excalidraw/Container';
|
||||
import { useCallback, useState } from 'react';
|
||||
import Sidebar, { SidebarVariant } from './Excalidraw/Sidebar';
|
||||
import RightTopUI from './Excalidraw/RightTopUI';
|
||||
import MainMenu from './Excalidraw/MainMenu';
|
||||
import MainMenuBase from './Excalidraw/MainMenu';
|
||||
|
||||
export const ExcalidrawMain = () => {
|
||||
const [excalidrawAPI, setExcalidrawAPI] = useState<ExcalidrawImperativeAPI>();
|
||||
@ -32,7 +32,7 @@ export const ExcalidrawMain = () => {
|
||||
return <Sidebar variant={sidebarVariant} variantProps={{ onClose }} />;
|
||||
}}
|
||||
>
|
||||
<MainMenu />
|
||||
<MainMenuBase />
|
||||
</ExcalidrawContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { MainMenuLink, MainMenuProvider } from '@/Components/Utilities';
|
||||
import { MainMenu as MainMenuBase } from '@excalidraw/excalidraw';
|
||||
|
||||
const MainMenu = () => {
|
||||
return (
|
||||
<MainMenuProvider>
|
||||
<MainMenuBase>
|
||||
<MainMenuBase.DefaultItems.ToggleTheme />
|
||||
<MainMenuBase.DefaultItems.Export />
|
||||
<MainMenuBase.DefaultItems.SaveAsImage />
|
||||
<MainMenuLink href="/license">License</MainMenuLink>
|
||||
</MainMenuProvider>
|
||||
<MainMenuBase.ItemLink href="/license">License</MainMenuBase.ItemLink>
|
||||
</MainMenuBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ExcalidrawImperativeAPI } from '@excalidraw/excalidraw/types/types';
|
||||
import { FC, useCallback } from 'react';
|
||||
import { ToggleButton, ToggleButtonGroup } from '@/Components/Utilities';
|
||||
import { ToggleButton, ToggleButtonGroup } from '@mui/material';
|
||||
import { SidebarVariant, SidebarVariantSchema } from './Sidebar';
|
||||
import { z } from 'zod';
|
||||
import { LiveCollaborationTrigger } from '@excalidraw/excalidraw';
|
||||
@ -33,7 +33,7 @@ const RightTopUI: FC<RightTopUIProps> = (props) => {
|
||||
<>
|
||||
<LiveCollaborationTrigger
|
||||
isCollaborating={false}
|
||||
onSelect={() => console.log('nyya')}
|
||||
onSelect={() => devlog.log('nyya')}
|
||||
/>
|
||||
<ToggleButtonGroup
|
||||
exclusive
|
||||
|
@ -1,22 +1,23 @@
|
||||
import { SidebarProvider } from '@/Components/Utilities';
|
||||
import { Sidebar } from '@excalidraw/excalidraw';
|
||||
import { FC } from 'react';
|
||||
import { z } from 'zod';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
export const SidebarBasePropsSchema = z.object({
|
||||
onClose: z.function().returns(z.void()),
|
||||
onClose: z.function().args().returns(z.void()),
|
||||
});
|
||||
|
||||
export type SidebarBaseProps = z.infer<typeof SidebarBasePropsSchema> & {
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
const SidebarProviderBase: FC<SidebarBaseProps> = (props) => {
|
||||
const SidebarBase: FC<SidebarBaseProps> = (props) => {
|
||||
return (
|
||||
<SidebarProvider dockable={true} onClose={props.onClose}>
|
||||
{props.children}
|
||||
</SidebarProvider>
|
||||
<Sidebar dockable={true} onClose={props.onClose}>
|
||||
<Box sx={{ p: 2 }}>{props.children}</Box>
|
||||
</Sidebar>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarProviderBase;
|
||||
export default SidebarBase;
|
||||
|
@ -1,16 +1,11 @@
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { Button, SidebarHeader } from '@/Components/Utilities';
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Sidebar } from '@excalidraw/excalidraw';
|
||||
import { z } from 'zod';
|
||||
import SidebarProviderBase, { SidebarBasePropsSchema } from './Base';
|
||||
import { startCollaboration } from '@/webrtc/collaboration';
|
||||
import {
|
||||
SignalingData,
|
||||
decodeSignalingData,
|
||||
encodeSignalingData,
|
||||
} from '@/webrtc/utilities';
|
||||
import { Input, Link } from '@mui/material';
|
||||
import { fromUrl, toUrl } from '@/utilities/url';
|
||||
import SidebarBase, { SidebarBasePropsSchema } from './Base';
|
||||
import { Button, Input, Link } from '@mui/material';
|
||||
import { copyToClipboard } from '@/utilities/clipboard';
|
||||
import { useAtom } from 'jotai';
|
||||
import { PeerConfigurationAtom, PeerConnectionAtom } from '@/atoms/webrtc';
|
||||
|
||||
export type CollaborationSidebarProps = z.infer<
|
||||
typeof CollaborationSidebarPropsSchema
|
||||
@ -21,14 +16,18 @@ export const CollaborationSidebarPropsSchema = z
|
||||
.merge(SidebarBasePropsSchema);
|
||||
|
||||
const CollaborationSidebar: FC<CollaborationSidebarProps> = (props) => {
|
||||
const signalingDataCallback = useCallback((data: SignalingData) => {
|
||||
const encodedData = encodeSignalingData(data);
|
||||
const url = toUrl({ signalingData: encodedData });
|
||||
const [peerConnection, setPeerConnection] = useAtom(PeerConnectionAtom);
|
||||
|
||||
setCollaborationUrl(url);
|
||||
const [peerConfiguration] = useAtom(PeerConfigurationAtom);
|
||||
|
||||
console.log(data);
|
||||
}, []);
|
||||
const initializePeerConnection = useCallback(() => {
|
||||
if (peerConnection) {
|
||||
devlog.warn('Peer connection already initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
setPeerConnection(new RTCPeerConnection(peerConfiguration));
|
||||
}, [peerConfiguration, peerConnection, setPeerConnection]);
|
||||
|
||||
const [collaborationUrl, setCollaborationUrl] = useState<URL | null>(null);
|
||||
const [isCollaborationStarted, setIsCollaborationStarted] = useState(false);
|
||||
@ -36,58 +35,35 @@ const CollaborationSidebar: FC<CollaborationSidebarProps> = (props) => {
|
||||
useState<URL | null>(null);
|
||||
|
||||
const onMessage = useCallback((event: MessageEvent) => {
|
||||
console.log(event);
|
||||
devlog.log(event);
|
||||
}, []);
|
||||
|
||||
const startCollaborationWrapper = useCallback(async () => {
|
||||
console.log('start collaboration');
|
||||
const copyCollaborationUrl = useCallback(
|
||||
() => copyToClipboard(collaborationUrl?.toString(), undefined),
|
||||
[collaborationUrl]
|
||||
);
|
||||
|
||||
const signalingData = providedCollaborationUrl
|
||||
? decodeSignalingData(fromUrl(providedCollaborationUrl).signalingData!)
|
||||
: undefined;
|
||||
|
||||
console.log(signalingData);
|
||||
|
||||
await startCollaboration(signalingData, signalingDataCallback, {
|
||||
onMessage,
|
||||
});
|
||||
}, [signalingDataCallback, onMessage, providedCollaborationUrl]);
|
||||
|
||||
const copyCollaborationUrl = useCallback(async () => {
|
||||
console.log('copy collaboration url');
|
||||
console.log(collaborationUrl?.toString());
|
||||
await copyToClipboard(collaborationUrl ? collaborationUrl?.toString() : '');
|
||||
}, [collaborationUrl]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isCollaborationStarted || providedCollaborationUrl) {
|
||||
startCollaborationWrapper().catch((error) => console.error(error));
|
||||
// TODO: Check this !!
|
||||
const offerWerapper = useCallback(async () => {
|
||||
if (!peerConnection) {
|
||||
devlog.error('Peer connection not initialized');
|
||||
return;
|
||||
}
|
||||
}, [
|
||||
isCollaborationStarted,
|
||||
startCollaborationWrapper,
|
||||
providedCollaborationUrl,
|
||||
]);
|
||||
|
||||
const offer = await peerConnection.createOffer();
|
||||
await peerConnection.setLocalDescription(offer);
|
||||
|
||||
devlog.log(offer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SidebarProviderBase onClose={props.onClose}>
|
||||
<SidebarHeader>Collaboration</SidebarHeader>
|
||||
<Button onClick={() => setIsCollaborationStarted(true)}>
|
||||
Start Collaboration
|
||||
<SidebarBase onClose={props.onClose}>
|
||||
<Sidebar.Header>Collaboration</Sidebar.Header>
|
||||
<Button onClick={initializePeerConnection}>
|
||||
Initialize a local peer.
|
||||
</Button>
|
||||
<Link>{collaborationUrl?.toString()}</Link>
|
||||
<Button
|
||||
onClick={() => {
|
||||
copyCollaborationUrl().catch((e) => console.error(e));
|
||||
}}
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
<Input
|
||||
value={providedCollaborationUrl ?? ''}
|
||||
onChange={(e) => setProvidedCollaborationUrl(new URL(e.target.value))}
|
||||
></Input>
|
||||
</SidebarProviderBase>
|
||||
<Button> Create a new collaboration session. (offer)</Button>
|
||||
</SidebarBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { FC } from 'react';
|
||||
import { Button, SidebarHeader } from '@/Components/Utilities';
|
||||
import { Sidebar } from '@excalidraw/excalidraw';
|
||||
import { z } from 'zod';
|
||||
import SidebarProviderBase, { SidebarBasePropsSchema } from './Base';
|
||||
import SidebarBase, { SidebarBasePropsSchema } from './Base';
|
||||
import { Switch, FormControlLabel, FormGroup } from '@mui/material';
|
||||
import { useAtom } from 'jotai';
|
||||
import { LoggerStateAtom } from '@/atoms/debug';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export type GeneralSidebarProps = z.infer<typeof GeneralSidebarPropsSchema>;
|
||||
|
||||
@ -10,11 +14,24 @@ export const GeneralSidebarPropsSchema = z
|
||||
.merge(SidebarBasePropsSchema);
|
||||
|
||||
const GeneralSidebar: FC<GeneralSidebarProps> = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const [loggerState, setLoggerState] = useAtom(LoggerStateAtom);
|
||||
|
||||
return (
|
||||
<SidebarProviderBase onClose={props.onClose}>
|
||||
<SidebarHeader>General Settings</SidebarHeader>
|
||||
<Button>Button</Button>
|
||||
</SidebarProviderBase>
|
||||
<SidebarBase onClose={props.onClose}>
|
||||
<Sidebar.Header>{t('general-settings')}</Sidebar.Header>
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={loggerState}
|
||||
onChange={(e) => setLoggerState?.(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label={t('toggle-debug-mode')}
|
||||
/>
|
||||
</FormGroup>
|
||||
</SidebarBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Button as ButtonBase,
|
||||
ToggleButtonGroup as ToggleButtonGroupBase,
|
||||
ToggleButton as ToggleButtonBase,
|
||||
} from '@mui/material';
|
||||
import { MainMenu, Sidebar } from '@excalidraw/excalidraw';
|
||||
|
||||
export const SidebarProvider = styled(Sidebar)``;
|
||||
export const SidebarHeader = styled(Sidebar.Header)``;
|
||||
|
||||
export const MainMenuProvider = styled(MainMenu)``;
|
||||
export const MainMenuLink = styled(MainMenu.ItemLink)``;
|
||||
|
||||
export const Button = styled(ButtonBase)``;
|
||||
|
||||
export const ToggleButtonGroup = styled(ToggleButtonGroupBase)``;
|
||||
|
||||
export const ToggleButton = styled(ToggleButtonBase)``;
|
3
src/atoms/debug.ts
Normal file
3
src/atoms/debug.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
export const LoggerStateAtom = atom(import.meta.env.DEV);
|
3
src/atoms/ui.ts
Normal file
3
src/atoms/ui.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
export const LangCodeAtom = atom('en');
|
10
src/atoms/webrtc.ts
Normal file
10
src/atoms/webrtc.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { DefaultPeerConfiguration } from '@/webrtc/connection';
|
||||
import { atom } from 'jotai';
|
||||
|
||||
export const PeerConnectionAtom = atom<RTCPeerConnection | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export const PeerConfigurationAtom = atom<RTCConfiguration>(
|
||||
DefaultPeerConfiguration
|
||||
);
|
8
src/globals.ts
Normal file
8
src/globals.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import type { DevLog } from '@/types/devlog';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
devlog: DevLog;
|
||||
}
|
||||
let devlog: DevLog;
|
||||
}
|
36
src/i18n.ts
Normal file
36
src/i18n.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import Backend from 'i18next-http-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
import en from '@/i18n/en/translation.json';
|
||||
import ja_JP from '@/i18n/ja_JP/translation.json';
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
returnEmptyString: false,
|
||||
debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
|
||||
resources: {
|
||||
en: {
|
||||
translation: en,
|
||||
},
|
||||
ja_JP: {
|
||||
translation: ja_JP,
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
devlog.error(e);
|
||||
});
|
||||
|
||||
export default i18n;
|
4
src/i18n/en/translation.json
Normal file
4
src/i18n/en/translation.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"toggle-debug-mode": "Toggle Debug Mode",
|
||||
"general-settings": "General Settings"
|
||||
}
|
1
src/i18n/ja_JP/translation.json
Normal file
1
src/i18n/ja_JP/translation.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -1,11 +1,18 @@
|
||||
import '@/globals';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
import router from './routes';
|
||||
import DevLogProvider from '@/utilities/DevLogProvider';
|
||||
|
||||
import '@/i18n';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<RouterProvider router={router} />
|
||||
<DevLogProvider>
|
||||
<RouterProvider router={router} />
|
||||
</DevLogProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
8
src/types/devlog.ts
Normal file
8
src/types/devlog.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export type Logger = <T>(...args: T[]) => void;
|
||||
|
||||
export type DevLog = {
|
||||
info: Logger;
|
||||
log: Logger;
|
||||
error: Logger;
|
||||
warn: Logger;
|
||||
};
|
65
src/types/language.ts
Normal file
65
src/types/language.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { languages } from '@excalidraw/excalidraw';
|
||||
import { Language } from '@excalidraw/excalidraw/types/i18n';
|
||||
|
||||
// Reference:
|
||||
// https://github.com/excalidraw/excalidraw/blob/e57dc405fa575a330110699ee762dce5918e9e04/src/i18n.ts#L20
|
||||
const LangCodes = [
|
||||
'en',
|
||||
'ar-SA',
|
||||
'bg-BG',
|
||||
'ca-ES',
|
||||
'cs-CZ',
|
||||
'de-DE',
|
||||
'el-GR',
|
||||
'es-ES',
|
||||
'eu-ES',
|
||||
'fa-IR',
|
||||
'fi-FI',
|
||||
'fr-FR',
|
||||
'gl-ES',
|
||||
'he-IL',
|
||||
'hi-IN',
|
||||
'hu-HU',
|
||||
'id-ID',
|
||||
'it-IT',
|
||||
'ja-JP',
|
||||
'kab-KA',
|
||||
'kk-KZ',
|
||||
'ko-KR',
|
||||
'ku-TR',
|
||||
'lt-LT',
|
||||
'lv-LV',
|
||||
'my-MM',
|
||||
'nb-NO',
|
||||
'nl-NL',
|
||||
'nn-NO',
|
||||
'oc-FR',
|
||||
'pa-IN',
|
||||
'pl-PL',
|
||||
'pt-BR',
|
||||
'pt-PT',
|
||||
'ro-RO',
|
||||
'ru-RU',
|
||||
'sk-SK',
|
||||
'sv-SE',
|
||||
'sl-SI',
|
||||
'tr-TR',
|
||||
'uk-UA',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
'vi-VN',
|
||||
'mr-IN',
|
||||
] as const;
|
||||
|
||||
export type LangCode = (typeof LangCodes)[number];
|
||||
|
||||
export type Languages = {
|
||||
[key in LangCode]: Language;
|
||||
}[];
|
||||
|
||||
export const Languages = languages
|
||||
.map((lang) => (LangCodes.includes(lang.code as LangCode) ? lang : undefined))
|
||||
.filter((item) => item !== undefined)
|
||||
.map((langCode) => ({
|
||||
langCode: languages.find((lang) => lang.code === langCode?.code),
|
||||
}));
|
30
src/types/utilities.ts
Normal file
30
src/types/utilities.ts
Normal file
@ -0,0 +1,30 @@
|
||||
export type Result<T, E> = Ok<T> | Err<E>;
|
||||
|
||||
export type Ok<T> = {
|
||||
v: T;
|
||||
};
|
||||
|
||||
export type Err<E> = {
|
||||
e: E;
|
||||
};
|
||||
|
||||
export const ok = <T>(v: T): Ok<T> => ({ v });
|
||||
|
||||
export const err = <E>(e: E): Err<E> => ({ e });
|
||||
|
||||
export const isOk = <T, E>(r: Result<T, E>): r is Ok<T> => 'v' in r;
|
||||
|
||||
export const isErr = <T, E>(r: Result<T, E>): r is Err<E> => 'e' in r;
|
||||
|
||||
export const unwrap = <T, E>(r: Result<T, E>): T => {
|
||||
if (isOk(r)) return r.v;
|
||||
throw r.e;
|
||||
};
|
||||
|
||||
export const re = <T, E>(r: Result<T, E>) => ({
|
||||
ok: ok(r),
|
||||
err: err(r),
|
||||
isOk: isOk(r),
|
||||
isErr: isErr(r),
|
||||
unwrap: unwrap(r),
|
||||
});
|
55
src/utilities/DevLogProvider.tsx
Normal file
55
src/utilities/DevLogProvider.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { LoggerStateAtom } from '@/atoms/debug';
|
||||
import { useAtom } from 'jotai';
|
||||
import { FC, ReactNode, useCallback, useEffect } from 'react';
|
||||
import type { Logger } from '@/types/devlog';
|
||||
|
||||
export type DevLogProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const DevLogProvider: FC<DevLogProviderProps> = (props) => {
|
||||
const [loggerState] = useAtom(LoggerStateAtom);
|
||||
|
||||
const info: Logger = useCallback(
|
||||
(...args) => {
|
||||
loggerState && console.info(args);
|
||||
},
|
||||
[loggerState]
|
||||
);
|
||||
|
||||
const log: Logger = useCallback(
|
||||
(...args) => {
|
||||
loggerState && console.log(args);
|
||||
},
|
||||
[loggerState]
|
||||
);
|
||||
|
||||
const error: Logger = useCallback(
|
||||
(...args) => {
|
||||
loggerState && console.error(args);
|
||||
},
|
||||
[loggerState]
|
||||
);
|
||||
|
||||
const warn: Logger = useCallback(
|
||||
(...args) => {
|
||||
loggerState && console.warn(args);
|
||||
},
|
||||
[loggerState]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.devlog = {
|
||||
info,
|
||||
log,
|
||||
error,
|
||||
warn,
|
||||
};
|
||||
|
||||
devlog = window.devlog;
|
||||
}, [info, log, error, warn]);
|
||||
|
||||
return <>{props.children}</>;
|
||||
};
|
||||
|
||||
export default DevLogProvider;
|
@ -1,3 +1,23 @@
|
||||
export const copyToClipboard = async (text: string) => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
export const copyToClipboard = (
|
||||
text: string | undefined | null,
|
||||
callback: (() => void) | undefined
|
||||
) => {
|
||||
if (!text) {
|
||||
devlog.log('no text to copy');
|
||||
return;
|
||||
}
|
||||
|
||||
devlog.log('copy collaboration url');
|
||||
devlog.log(text);
|
||||
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.catch((err: DOMException) => {
|
||||
devlog.error(`Could not copy text why: ${err.toString()}`);
|
||||
});
|
||||
};
|
||||
|
@ -1,28 +0,0 @@
|
||||
import establishConnection from './connection';
|
||||
import type { Connection, DataChannelCallbacks } from './connection';
|
||||
import type { SignalingData } from './utilities';
|
||||
|
||||
export type SignalingDataCallback = (signalingData: SignalingData) => void;
|
||||
|
||||
export type OnAnswerCallback = (answer: RTCSessionDescription) => void;
|
||||
export type OnOfferCallback = (offer: RTCSessionDescription) => void;
|
||||
|
||||
export const startCollaboration = async (
|
||||
signalingData: SignalingData | undefined,
|
||||
onSignalingData: SignalingDataCallback,
|
||||
dataChannelCallbacks: DataChannelCallbacks
|
||||
): Promise<void> => {
|
||||
let connection: Connection = {
|
||||
connectionState: 'noConnection',
|
||||
dataChannelCallbacks,
|
||||
signalingData,
|
||||
};
|
||||
|
||||
while (connection?.connectionState !== 'established') {
|
||||
connection = await establishConnection(connection);
|
||||
|
||||
if (connection.signalingData) {
|
||||
onSignalingData(connection.signalingData);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,96 +1,10 @@
|
||||
import { match } from 'ts-pattern';
|
||||
import { SignalingDataType, SignalingData } from './utilities';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const PeerConfiguration: RTCConfiguration = {
|
||||
export const DefaultPeerConfiguration: RTCConfiguration = {
|
||||
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
|
||||
};
|
||||
|
||||
export const EstablishingConnectionStateSchema = z.enum([
|
||||
'noConnection',
|
||||
'waiting',
|
||||
'established',
|
||||
]);
|
||||
|
||||
export type EstablishingConnectionState = z.infer<
|
||||
typeof EstablishingConnectionStateSchema
|
||||
>;
|
||||
|
||||
export type Connection = {
|
||||
connectionState: EstablishingConnectionState;
|
||||
signalingData?: SignalingData;
|
||||
dataChannelCallbacks?: DataChannelCallbacks;
|
||||
};
|
||||
|
||||
export const establishConnection = async ({
|
||||
connectionState,
|
||||
signalingData,
|
||||
dataChannelCallbacks,
|
||||
}: Connection): Promise<Connection> => {
|
||||
const peerConnection = createPeerConnection();
|
||||
|
||||
return await match(connectionState)
|
||||
.with('noConnection', async () => {
|
||||
const _signalingData = await createOffer(peerConnection);
|
||||
|
||||
return {
|
||||
connectionState: 'waiting',
|
||||
signalingData: _signalingData,
|
||||
dataChannelCallbacks,
|
||||
} as Connection;
|
||||
})
|
||||
.with('waiting', async () => {
|
||||
if (!dataChannelCallbacks) {
|
||||
throw new Error('Data channel callbacks are not set');
|
||||
}
|
||||
if (!signalingData) {
|
||||
throw new Error('Signaling data is not set');
|
||||
}
|
||||
|
||||
await peerConnection.setRemoteDescription(signalingData.sdp);
|
||||
|
||||
const connection: Connection = await match(signalingData.type)
|
||||
.with('offer', async () => {
|
||||
const answer = await createAnswer(peerConnection);
|
||||
return {
|
||||
connectionState: 'waiting',
|
||||
signalingData: answer,
|
||||
dataChannelCallbacks,
|
||||
} as Connection;
|
||||
})
|
||||
.with('answer', () => {
|
||||
return {
|
||||
connectionState: 'established',
|
||||
signalingData: undefined,
|
||||
dataChannelCallbacks,
|
||||
} as Connection;
|
||||
})
|
||||
.exhaustive();
|
||||
|
||||
dataChannelHandler(
|
||||
signalingData.type,
|
||||
peerConnection,
|
||||
dataChannelCallbacks
|
||||
);
|
||||
|
||||
return connection;
|
||||
})
|
||||
.with('established', () => {
|
||||
throw new Error(
|
||||
"Connection can't be established because it is already established"
|
||||
);
|
||||
})
|
||||
.exhaustive();
|
||||
};
|
||||
|
||||
export default establishConnection;
|
||||
|
||||
export const createPeerConnection = () => {
|
||||
const configuration = PeerConfiguration;
|
||||
|
||||
return new RTCPeerConnection(configuration);
|
||||
};
|
||||
|
||||
export const createOffer = async (peerConnection: RTCPeerConnection) => {
|
||||
const offer = await peerConnection.createOffer();
|
||||
await peerConnection.setLocalDescription(offer);
|
||||
@ -103,7 +17,7 @@ export const createOffer = async (peerConnection: RTCPeerConnection) => {
|
||||
|
||||
return signalingData;
|
||||
} else {
|
||||
throw new Error('Local description is not set');
|
||||
devlog.error('Local description is not set');
|
||||
}
|
||||
};
|
||||
|
||||
@ -143,6 +57,6 @@ export const createAnswer = async (peerConnection: RTCPeerConnection) => {
|
||||
|
||||
return signalingData;
|
||||
} else {
|
||||
throw new Error('Local description is not set');
|
||||
devlog.error('Local description is not set');
|
||||
}
|
||||
};
|
||||
|
@ -4,10 +4,9 @@ import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@mui/styled-engine': '@mui/styled-engine-sc',
|
||||
},
|
||||
define: {
|
||||
devlog: 'window.devlog',
|
||||
'process.env': {},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
|
Reference in New Issue
Block a user