Merge branch 'master' of github.com:thecodingmachine/workadventure into develop

This commit is contained in:
David Négrier 2022-03-21 15:08:39 +01:00
commit c484d3ea84
71 changed files with 612 additions and 1027 deletions

View File

@ -55,7 +55,8 @@
"query-string": "^6.13.3", "query-string": "^6.13.3",
"redis": "^3.1.2", "redis": "^3.1.2",
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0", "uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
"uuidv4": "^6.0.7" "uuidv4": "^6.0.7",
"zod": "^3.12.0"
}, },
"devDependencies": { "devDependencies": {
"@types/busboy": "^0.2.3", "@types/busboy": "^0.2.3",

View File

@ -2258,3 +2258,8 @@ yn@3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
zod@^3.12.0:
version "3.14.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.14.2.tgz#0b4ed79085c471adce0e7f2c0a4fbb5ddc516ba2"
integrity sha512-iF+wrtzz7fQfkmn60PG6XFxaWBhYYKzp2i+nv24WbLUWb2JjymdkHlzBwP0erpc78WotwP5g9AAu7Sk8GWVVNw==

View File

@ -45,7 +45,7 @@ server {
rewrite ^/jwt /index.html break; rewrite ^/jwt /index.html break;
} }
location ~ ^/[@_]/ { location ~ ^/[@_*]/ {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
} }
} }

View File

@ -57,6 +57,7 @@
"simple-peer": "^9.11.0", "simple-peer": "^9.11.0",
"socket.io-client": "^2.3.0", "socket.io-client": "^2.3.0",
"standardized-audio-context": "^25.2.4", "standardized-audio-context": "^25.2.4",
"ts-deferred": "^1.0.4",
"ts-proto": "^1.96.0", "ts-proto": "^1.96.0",
"typesafe-i18n": "^2.59.0", "typesafe-i18n": "^2.59.0",
"uuidv4": "^6.2.10", "uuidv4": "^6.2.10",

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg2985" version="1.1" inkscape:version="0.48.4 r9939" width="485.33627" height="485.33627" sodipodi:docname="600px-France_road_sign_B1j.svg[1].png">
<metadata id="metadata2991">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs2989"/>
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1272" inkscape:window-height="745" id="namedview2987" showgrid="false" inkscape:snap-global="true" inkscape:snap-grids="true" inkscape:snap-bbox="true" inkscape:bbox-paths="true" inkscape:bbox-nodes="true" inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-midpoints="true" inkscape:object-paths="true" inkscape:snap-intersection-paths="true" inkscape:object-nodes="true" inkscape:snap-smooth-nodes="true" inkscape:snap-midpoints="true" inkscape:snap-object-midpoints="true" inkscape:snap-center="false" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" inkscape:zoom="0.59970176" inkscape:cx="390.56499" inkscape:cy="244.34365" inkscape:window-x="86" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:current-layer="layer1">
<inkscape:grid type="xygrid" id="grid2995" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true" originx="-57.33186px" originy="-57.33186px"/>
</sodipodi:namedview>
<g inkscape:groupmode="layer" id="layer1" inkscape:label="1" style="display:inline" transform="translate(-57.33186,-57.33186)">
<path sodipodi:type="arc" style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path2997" sodipodi:cx="300" sodipodi:cy="300" sodipodi:rx="240" sodipodi:ry="240" d="M 540,300 C 540,432.54834 432.54834,540 300,540 167.45166,540 60,432.54834 60,300 60,167.45166 167.45166,60 300,60 432.54834,60 540,167.45166 540,300 z" transform="matrix(1.0058783,0,0,1.0058783,-1.76349,-1.76349)"/>
<path sodipodi:type="arc" style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path4005" sodipodi:cx="304.75" sodipodi:cy="214.75" sodipodi:rx="44.75" sodipodi:ry="44.75" d="m 349.5,214.75 c 0,24.71474 -20.03526,44.75 -44.75,44.75 -24.71474,0 -44.75,-20.03526 -44.75,-44.75 0,-24.71474 20.03526,-44.75 44.75,-44.75 24.71474,0 44.75,20.03526 44.75,44.75 z" transform="matrix(5.1364411,0,0,5.1364411,-1265.3304,-803.05073)"/>
<rect style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="rect4001" width="345" height="80.599998" x="127.5" y="259.70001"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 188.149 188.149" style="enable-background:new 0 0 188.149 188.149;" xml:space="preserve">
<g>
<g>
<defs>
<circle id="SVGID_1_" cx="94.075" cy="94.075" r="94.074"/>
</defs>
<use xlink:href="#SVGID_1_" style="overflow:visible;fill:#4AC8EB;"/>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_2_);">
<path style="fill:#A57561;" d="M148.572,197.629v0.01H39.507v-0.01c0-15.124,6.147-28.809,16.09-38.679
c0.463-0.463,0.926-0.905,1.408-1.347c1.43-1.326,2.931-2.57,4.493-3.732c1.028-0.771,2.098-1.491,3.177-2.189
c1.08-0.699,2.19-1.357,3.331-1.975c0.021-0.021,0.042-0.021,0.042-0.021c0.441-0.247,0.873-0.493,1.306-0.761
c1.295-0.761,2.519-1.624,3.69-2.56c4.966-3.948,8.812-9.254,11.001-15.34v-0.011c1.306-3.629,2.016-7.546,2.016-11.639
l16.121,0.072c0,4.04,0.688,7.927,1.964,11.525c2.169,6.117,5.994,11.433,10.96,15.401c0.339,0.277,0.688,0.545,1.038,0.802
c0.483,0.36,0.977,0.71,1.47,1.039c0.37,0.246,0.751,0.493,1.132,0.72c0.421,0.257,0.853,0.514,1.285,0.75
c0.041,0.011,0.071,0.021,0.103,0.041c0.03,0.02,0.062,0.041,0.093,0.061c1.265,0.699,2.498,1.439,3.69,2.221
c0.401,0.258,0.802,0.524,1.192,0.803c0.515,0.37,1.039,0.74,1.543,1.131h0.021C139.966,163.875,148.572,179.729,148.572,197.629
z"/>
<path style="fill:#EB6D4A;" d="M148.572,197.629H39.507c0-15.124,6.147-28.809,16.09-38.679c0.463-0.463,0.926-0.905,1.408-1.347
c1.43-1.326,2.931-2.581,4.493-3.742c1.028-0.762,2.098-1.491,3.177-2.18c1.08-0.699,2.19-1.357,3.331-1.975
c0.021-0.021,0.042-0.021,0.042-0.021c0.441-0.247,0.873-0.493,1.306-0.761c1.295-0.761,2.519-1.624,3.69-2.56
c5.347,5.469,12.79,8.852,21.046,8.852c8.226,0,15.669-3.393,21.016-8.842c0.339,0.277,0.688,0.545,1.038,0.802
c0.483,0.36,0.977,0.71,1.47,1.039c0.37,0.246,0.751,0.493,1.132,0.72c0.421,0.267,0.853,0.514,1.285,0.75
c0.041,0.011,0.071,0.021,0.103,0.041c0.03,0.011,0.062,0.031,0.093,0.052c1.265,0.699,2.498,1.439,3.69,2.23
c0.401,0.258,0.802,0.524,1.192,0.803c0.515,0.37,1.039,0.74,1.543,1.131h0.021C139.966,163.875,148.572,179.729,148.572,197.629
z"/>
<path style="fill:#A57561;" d="M52.183,46.81v34.117c0,28.977,25.437,52.466,41.857,52.466c16.421,0,41.858-23.489,41.858-52.466
V46.81H52.183z"/>
<path style="fill:#141720;" d="M52.183,76.823L52.183,76.823c2.063,0,3.734-1.671,3.734-3.733V49.356h-3.734V76.823z"/>
<path style="fill:#141720;" d="M135.899,76.823L135.899,76.823V49.356h-3.733V73.09
C132.165,75.152,133.836,76.823,135.899,76.823z"/>
<path style="fill:#141720;" d="M135.893,48.33c0,4.884-0.328,6.061-3.734,5.801c-0.137-2.367-17.141-4.296-38.111-4.296
c-20.985,0-37.989,1.929-38.126,4.296c-3.406,0.26-3.734-0.917-3.734-5.801c0-0.479,0.014-0.984,0.027-1.519
c0.52-12.052,7.318-34.582,41.833-34.582c34.5,0,41.299,22.53,41.818,34.582C135.879,47.346,135.893,47.852,135.893,48.33z"/>
</g>
<path style="clip-path:url(#SVGID_2_);fill:#FFFFFF;" d="M115.106,146.119c-3.517,10.826-10.601,21.539-21.036,30.299
c-10.436-8.76-17.509-19.473-21.025-30.299c0.052,0.02,0.113,0.041,0.165,0.061c5.531,4.955,12.852,7.979,20.86,7.979
c8.009,0,15.319-3.013,20.851-7.968C114.982,146.17,115.044,146.14,115.106,146.119z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M512,84.85,427.15,0,256,171.15,84.85,0,0,84.85,171.15,256,0,427.15,84.85,512,256,340.85,427.15,512,512,427.15,340.85,256Z" transform="translate(0 0)"/></svg>

Before

Width:  |  Height:  |  Size: 319 B

View File

@ -1 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><defs><image width="12" height="14" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAOAQMAAAAhc2+vAAAAAXNSR0IB2cksfwAAAAZQTFRFAAAA////pdmf3QAAAAJ0Uk5TAP9bkSK1AAAAJUlEQVR4nGNgOMDAoMDw/wMDCDgwMDQwQIAASBgE/j8ACRswAACLjwYPIknTggAAAABJRU5ErkJggg=="/><image width="12" height="12" id="img2" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMAgMAAAArG7R0AAAAAXNSR0IB2cksfwAAAAlQTFRFAAAA/////wAAzV63nAAAAAN0Uk5TAP8BHlUJOgAAACJJREFUeJxjYGAQYGBgYGEIDQ0F0xA+BwMDEi80NASqigEAOD8CVqGVgwsAAAAASUVORK5CYII="/></defs><style></style><use href="#img1" x="2" y="1" /><use href="#img2" x="2" y="2" /></svg>

Before

Width:  |  Height:  |  Size: 717 B

View File

@ -1 +0,0 @@
<svg height="682pt" viewBox="-21 -47 682.66669 682" width="682pt" xmlns="http://www.w3.org/2000/svg"><path d="m640 86.65625v283.972656c0 48.511719-39.472656 87.988282-87.988281 87.988282h-279.152344l-185.183594 128.863281v-128.863281c-48.375-.164063-87.675781-39.574219-87.675781-87.988282v-283.972656c0-48.515625 39.472656-87.988281 87.988281-87.988281h464.023438c48.515625 0 87.988281 39.472656 87.988281 87.988281zm0 0" fill="#ffdb2d"/><path d="m640 86.65625v283.972656c0 48.511719-39.472656 87.988282-87.988281 87.988282h-232.109375v-459.949219h232.109375c48.515625 0 87.988281 39.472656 87.988281 87.988281zm0 0" fill="#ffaa20"/><g fill="#fff"><path d="m171.296875 131.167969h297.40625v37.5h-297.40625zm0 0"/><path d="m171.296875 211.167969h297.40625v37.5h-297.40625zm0 0"/><path d="m171.296875 291.167969h297.40625v37.5h-297.40625zm0 0"/></g><path d="m319.902344 131.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/><path d="m319.902344 211.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/><path d="m319.902344 291.167969h148.800781v37.5h-148.800781zm0 0" fill="#e1e1e3"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg id="i-fullscreen-exit" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" stroke="#FFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M4 12 L12 12 12 4 M20 4 L20 12 28 12 M4 20 L12 20 12 28 M28 20 L20 20 20 28" />
</svg>

Before

Width:  |  Height:  |  Size: 329 B

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg id="i-fullscreen" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M4 12 L4 4 12 4 M20 4 L28 4 28 12 M4 20 L4 28 12 28 M28 20 L28 28 20 28" />
</svg>

Before

Width:  |  Height:  |  Size: 322 B

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 451.7 512" style="enable-background:new 0 0 451.7 512;" xml:space="preserve">
<path d="M436.9,212.6L237.2,12.9c-11.7-11.7-30.7-11.7-42.4,0s-11.7,30.7,0,42.4L394.5,255c11.5,11.9,30.5,12.2,42.4,0.7
c11.9-11.5,12.2-30.5,0.7-42.4C437.4,213.1,437.2,212.8,436.9,212.6z"/>
<path d="M179.5,83.1l-1.5,7.5c-10.4,53-36,103.4-70.6,144.3l109,108.3c40.7-34.9,90.2-61.5,143.1-72.3l7.5-1.5L179.5,83.1z"/>
<path d="M87.4,257l-74.2,74.2c-17.6,17.6-17.6,46.1,0,63.6c0,0,0,0,0,0l42.4,42.4c17.6,17.6,46.1,17.6,63.6,0c0,0,0,0,0,0l74.2-74.2
L87.4,257z M98,373.7c-6.1,5.6-15.6,5.3-21.2-0.8c-5.4-5.8-5.4-14.7,0-20.5l21.2-21.2c6-5.8,15.5-5.6,21.2,0.4
c5.6,5.8,5.6,15,0,20.8L98,373.7z"/>
<path d="M256.1,445.3l20.4-20.4c17.6-17.6,17.6-46.1,0-63.6l-15.1-15.2c-8.4,5.7-16.4,11.7-24.2,18.3l18.1,18.1
c5.8,5.9,5.8,15.3,0,21.2l-20.7,20.8l-30.5-29.5l-42.4,42.4l68.1,65.9c11.7,11.7,30.7,11.7,42.4,0c11.7-11.7,11.7-30.7,0-42.4l0,0
L256.1,445.3z"/>
<path d="M316.7,0c-8.3,0-15,6.7-15,15v30c0,8.3,6.7,15,15,15c8.3,0,15-6.7,15-15V15C331.7,6.7,325,0,316.7,0z"/>
<path d="M436.7,120h-30c-8.3,0-15,6.7-15,15s6.7,15,15,15h30c8.3,0,15-6.7,15-15S445,120,436.7,120z"/>
<path d="M417.3,34.4c-5.9-5.9-15.4-5.9-21.2,0l-30,30c-6,5.8-6.1,15.3-0.4,21.2c5.8,6,15.3,6.1,21.2,0.4c0.1-0.1,0.2-0.2,0.4-0.4
l30-30C423.2,49.7,423.2,40.2,417.3,34.4z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 377.87"><defs><style>.cls-1{fill:#ffda01;}</style></defs><path class="cls-1" d="M494.6,67.07H17.4A17.4,17.4,0,0,0,0,84.46V343.84a17.4,17.4,0,0,0,17.4,17.39H494.6A17.4,17.4,0,0,0,512,343.84V84.46a17.4,17.4,0,0,0-17.4-17.39Z" transform="translate(0 -67.07)"/><path class="cls-1" d="M355.42,414.75H296.35V391.42h-80.7v23.33H156.58a15.1,15.1,0,1,0,0,30.19H355.42a15.1,15.1,0,1,0,0-30.19Z" transform="translate(0 -67.07)"/></svg>

Before

Width:  |  Height:  |  Size: 512 B

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<g>
<path class="st0" d="M163.2,351.1c-2.4-23.4-1.1-46.7,3.9-69.2c2.6-11-2.1-23.8-9.4-29.6l-36.8-39.7C142.5,160,170,126.2,216.8,95
l45.1,27.2c9,7.3,21.3,9.1,32,4.4c21.2-9.5,43.7-15.4,67.2-17.7c16.9-1.7,29.3-16.8,27.6-33.7L381.5,5
c-1.7-16.9-16.8-29.3-33.7-27.6C154-2.8,12.4,170.8,32.1,364.5c1.7,16.9,16.8,29.3,33.7,27.6l69.9-7.1
C152.5,383.1,164.9,368,163.2,351.1z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 804 B

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 384 384" style="enable-background:new 0 0 384 384;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<g>
<path class="st0" d="M32.6,256.8c17.3-15.9,36.8-28.8,57.8-38.3c10.4-4.5,17.8-15.9,18.1-25.3l9.8-53.2
c55-14.2,98.5-12.3,151.6,6.5l5.2,52.4c-0.5,11.6,5.4,22.5,15.6,28.3c20.3,11.3,38.5,25.8,54.4,43.2c11.5,12.5,31,13.4,43.5,1.9
l51.9-47.7c12.5-11.5,13.4-31,1.9-43.5c-131.8-143.5-355.6-153-499-21.3c-12.5,11.5-13.4,31-1.9,43.5l47.5,51.8
C0.6,267.4,20.1,268.3,32.6,256.8z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 810 B

View File

@ -1 +0,0 @@
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56.48 56.48"><defs><style>.cls-1{fill:#e76e54;}.cls-2{fill:#fff;}</style></defs><path class="cls-1" d="M39.94,512H16.54L0,495.46v-23.4l16.54-16.54h23.4l16.54,16.54v23.4Z" transform="translate(0 -455.52)"/><path class="cls-2" d="M33.54,485.52H23l-1.77-21.18H35.3Z" transform="translate(0 -455.52)"/><path class="cls-2" d="M23,492.58H33.54v10.59H23Z" transform="translate(0 -455.52)"/></svg>

Before

Width:  |  Height:  |  Size: 477 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path d="M481.508,210.336L68.414,38.926c-17.403-7.222-37.064-4.045-51.309,8.287C2.86,59.547-3.098,78.551,1.558,96.808
L38.327,241h180.026c8.284,0,15.001,6.716,15.001,15.001c0,8.284-6.716,15.001-15.001,15.001H38.327L1.558,415.193
c-4.656,18.258,1.301,37.262,15.547,49.595c14.274,12.357,33.937,15.495,51.31,8.287l413.094-171.409
C500.317,293.862,512,276.364,512,256.001C512,235.638,500.317,218.139,481.508,210.336z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 985 B

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 441.78"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M481.51,210.34,68.41,38.93A49.44,49.44,0,0,0,1.56,96.81L38.33,241h180a15,15,0,1,1,0,30h-180L1.56,415.19a49.43,49.43,0,0,0,66.86,57.88l413.09-171.4a49.44,49.44,0,0,0,0-91.33Z" transform="translate(0 -35.11)"/></svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 441.78"><defs><style>.cls-1{fill:#ffda01;}</style></defs><path class="cls-1" d="M481.51,210.34,68.41,38.93A49.44,49.44,0,0,0,1.56,96.81L38.33,241h180a15,15,0,1,1,0,30h-180L1.56,415.19a49.43,49.43,0,0,0,66.86,57.88l413.09-171.4a49.44,49.44,0,0,0,0-91.33Z" transform="translate(0 -35.11)"/></svg>

Before

Width:  |  Height:  |  Size: 382 B

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path d="M453.6,237.3c-1.5-18.8-5.6-37-12.3-54.5l46.1-37l-75-93.6L366.5,89c-15.8-10.7-33-18.9-51.1-24.6V6.1h-120v58.7
c-19,6.1-36.8,15-53.2,26.5l-46.3-36L22.3,150l47.2,36.6c-6.3,17.5-10,35.8-11.2,54.5L0,255l27.9,116.7l41-9.8
c20.2-20.2,38.4-38.4,62.4-62.4C99.4,213,163.5,120.6,256.1,120.6c73.4,0,132.9,59.5,132.9,132.9c0,90.7-89,154.7-174.8,126.2
c-6.9,6.9-77.9,77.9-88.9,88.9l79.1,37.3l26.3-55.8c18.2,2.3,36.3,2.1,54.1-0.5l26.9,55.1L419.6,452l-26.9-54.9
c13.3-12.7,24.7-27,34.1-42.8l59,13.2L512,250.4L453.6,237.3z"/>
</g>
</g>
<g>
<g>
<path d="M336,219.4l-7.6-19.1L282.6,246L262,225.4l45.8-45.8l-19.1-7.6c-74.9-29.8-144.2,52.2-104.9,120.7
C82.6,393.9,169.1,307.5,47.6,429c-17,17,18.4,52.5,35.4,35.4c70.6-70.6,2-2,137.5-137.5C289.6,360.5,364.5,291,336,219.4z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.81"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M453.58,237.31a195.46,195.46,0,0,0-12.33-54.5l46.14-37-75-93.62L366.55,89a196.1,196.1,0,0,0-51.12-24.58V6.1h-120V64.75a195.85,195.85,0,0,0-53.23,26.53l-46.34-36L22.3,150l47.16,36.64a196.64,196.64,0,0,0-11.19,54.46L0,255,27.91,371.68l41-9.81,62.4-62.39C99.44,213,163.49,120.57,256.09,120.57A133,133,0,0,1,389,253.51c0,90.69-89,154.71-174.78,126.22l-88.88,88.89,79.1,37.28,26.31-55.81a199.26,199.26,0,0,0,54.12-.45l27,55.07L419.6,452l-26.88-54.93a197.42,197.42,0,0,0,34.06-42.84l59,13.22,26.2-117Z" transform="translate(0 -6.1)"/><path class="cls-1" d="M336,219.37l-7.61-19.14L282.55,246,262,225.44l45.79-45.78L288.63,172c-74.92-29.8-144.18,52.17-104.87,120.7C82.63,393.88,169.06,307.46,47.55,429,30.51,446,66,481.44,83,464.4c70.58-70.59,2-2,137.48-137.47C289.61,360.46,364.47,291,336,219.37Z" transform="translate(0 -6.1)"/></svg>

Before

Width:  |  Height:  |  Size: 994 B

View File

@ -1 +0,0 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.81"><defs><style>.cls-1{fill:#ffda01;}</style></defs><path class="cls-1" d="M453.58,237.31a195.46,195.46,0,0,0-12.33-54.5l46.14-37-75-93.62L366.55,89a196.1,196.1,0,0,0-51.12-24.58V6.1h-120V64.75a195.85,195.85,0,0,0-53.23,26.53l-46.34-36L22.3,150l47.16,36.64a196.64,196.64,0,0,0-11.19,54.46L0,255,27.91,371.68l41-9.81,62.4-62.39C99.44,213,163.49,120.57,256.09,120.57A133,133,0,0,1,389,253.51c0,90.69-89,154.71-174.78,126.22l-88.88,88.89,79.1,37.28,26.31-55.81a199.26,199.26,0,0,0,54.12-.45l27,55.07L419.6,452l-26.88-54.93a197.42,197.42,0,0,0,34.06-42.84l59,13.22,26.2-117Z" transform="translate(0 -6.1)"/><path class="cls-1" d="M336,219.37l-7.61-19.14L282.55,246,262,225.44l45.79-45.78L288.63,172c-74.92-29.8-144.18,52.17-104.87,120.7C82.63,393.88,169.06,307.46,47.55,429,30.51,446,66,481.44,83,464.4c70.58-70.59,2-2,137.48-137.47C289.61,360.46,364.47,291,336,219.37Z" transform="translate(0 -6.1)"/></svg>

Before

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -9,6 +9,8 @@
import { iframeStates } from "../../WebRtc/CoWebsiteManager"; import { iframeStates } from "../../WebRtc/CoWebsiteManager";
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager"; import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
import uploadFile from "../images/jitsi.png";
export let index: number; export let index: number;
export let coWebsite: CoWebsite; export let coWebsite: CoWebsite;
export let vertical: boolean; export let vertical: boolean;
@ -21,7 +23,7 @@
onMount(() => { onMount(() => {
icon.src = isJitsi icon.src = isJitsi
? "/resources/logos/jitsi.png" ? uploadFile
: `${ICON_URL}/icon?url=${coWebsite.getUrl().hostname}&size=64..96..256&fallback_icon_color=14304c`; : `${ICON_URL}/icon?url=${coWebsite.getUrl().hostname}&size=64..96..256&fallback_icon_color=14304c`;
icon.alt = coWebsite.getUrl().hostname; icon.alt = coWebsite.getUrl().hostname;
icon.onload = () => { icon.onload = () => {
@ -350,9 +352,14 @@
color: white; color: white;
padding: 4px; padding: 4px;
border-radius: 4px; border-radius: 4px;
p { p {
margin-bottom: 0; margin-bottom: 0;
} }
&.hide {
display: none;
}
} }
} }
</style> </style>

View File

@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import { fly } from "svelte/transition"; import { fly } from "svelte/transition";
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore"; import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
import firefoxImg from "./images/help-setting-camera-permission-firefox.png";
import chromeImg from "./images/help-setting-camera-permission-chrome.png";
import { getNavigatorType, isAndroid as isAndroidFct, NavigatorType } from "../../WebRtc/DeviceUtils"; import { getNavigatorType, isAndroid as isAndroidFct, NavigatorType } from "../../WebRtc/DeviceUtils";
import LL from "../../i18n/i18n-svelte"; import LL from "../../i18n/i18n-svelte";
@ -33,9 +31,9 @@
<p class="err"> <p class="err">
{$LL.camera.help.firefoxContent()} {$LL.camera.help.firefoxContent()}
</p> </p>
<img src={firefoxImg} alt="" /> <img src={$LL.camera.help.screen.firefox()} alt="" />
{:else if isChrome && !isAndroid} {:else if isChrome && !isAndroid}
<img src={chromeImg} alt="" /> <img src={$LL.camera.help.screen.chrome()} alt="" />
{/if} {/if}
</p> </p>
</section> </section>

View File

@ -3,6 +3,7 @@
import { LoginScene, LoginSceneName } from "../../Phaser/Login/LoginScene"; import { LoginScene, LoginSceneName } from "../../Phaser/Login/LoginScene";
import { DISPLAY_TERMS_OF_USE, MAX_USERNAME_LENGTH } from "../../Enum/EnvironmentVariable"; import { DISPLAY_TERMS_OF_USE, MAX_USERNAME_LENGTH } from "../../Enum/EnvironmentVariable";
import logoImg from "../images/logo.png"; import logoImg from "../images/logo.png";
import poweredByWorkAdventureImg from "../images/Powered_By_WorkAdventure_Big.png";
import { gameManager } from "../../Phaser/Game/GameManager"; import { gameManager } from "../../Phaser/Game/GameManager";
import LL from "../../i18n/i18n-svelte"; import LL from "../../i18n/i18n-svelte";
@ -13,6 +14,8 @@
let name = gameManager.getPlayerName() || ""; let name = gameManager.getPlayerName() || "";
let startValidating = false; let startValidating = false;
let logo = gameManager.currentStartedRoom.loginSceneLogo ?? logoImg;
function submit() { function submit() {
startValidating = true; startValidating = true;
@ -25,7 +28,7 @@
<form class="loginScene" on:submit|preventDefault={submit}> <form class="loginScene" on:submit|preventDefault={submit}>
<section class="text-center"> <section class="text-center">
<img src={logoImg} alt="WorkAdventure logo" /> <img src={logo} alt="" />
</section> </section>
<section class="text-center"> <section class="text-center">
<h2>{$LL.login.input.name.placeholder()}</h2> <h2>{$LL.login.input.name.placeholder()}</h2>
@ -60,6 +63,11 @@
<section class="action"> <section class="action">
<button type="submit" class="nes-btn is-primary loginSceneFormSubmit">{$LL.login.continue()}</button> <button type="submit" class="nes-btn is-primary loginSceneFormSubmit">{$LL.login.continue()}</button>
</section> </section>
{#if logo !== logoImg}
<section class="text-center powered-by">
<img src={poweredByWorkAdventureImg} alt="Powered by WorkAdventure" />
</section>
{/if}
</form> </form>
<style lang="scss"> <style lang="scss">
@ -132,6 +140,11 @@
width: 100%; width: 100%;
margin: 20px 0; margin: 20px 0;
} }
&.powered-by {
position: fixed;
bottom: 0;
}
} }
} }
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -31,6 +31,8 @@ export class Room {
private _group: string | null = null; private _group: string | null = null;
private _expireOn: Date | undefined; private _expireOn: Date | undefined;
private _canReport: boolean = false; private _canReport: boolean = false;
private _loadingLogo: string | undefined;
private _loginSceneLogo: string | undefined;
private constructor(private roomUrl: URL) { private constructor(private roomUrl: URL) {
this.id = roomUrl.pathname; this.id = roomUrl.pathname;
@ -126,6 +128,8 @@ export class Room {
this._expireOn = new Date(data.expireOn); this._expireOn = new Date(data.expireOn);
} }
this._canReport = data.canReport ?? false; this._canReport = data.canReport ?? false;
this._loadingLogo = data.loadingLogo ?? undefined;
this._loginSceneLogo = data.loginSceneLogo ?? undefined;
return new MapDetail(data.mapUrl); return new MapDetail(data.mapUrl);
} else { } else {
throw new Error("Data received by the /map endpoint of the Pusher is not in a valid format."); throw new Error("Data received by the /map endpoint of the Pusher is not in a valid format.");
@ -233,4 +237,12 @@ export class Room {
get canReport(): boolean { get canReport(): boolean {
return this._canReport; return this._canReport;
} }
get loadingLogo(): string | undefined {
return this._loadingLogo;
}
get loginSceneLogo(): string | undefined {
return this._loginSceneLogo;
}
} }

View File

@ -349,7 +349,9 @@ export class RoomConnection implements RoomConnection {
break; break;
} }
} }
if (this.closed) { if (this.closed) {
this.closeConnection();
break; break;
} }

View File

@ -1,10 +1,12 @@
import ImageFrameConfig = Phaser.Types.Loader.FileTypes.ImageFrameConfig; import ImageFrameConfig = Phaser.Types.Loader.FileTypes.ImageFrameConfig;
import { DirtyScene } from "../Game/DirtyScene"; import { DirtyScene } from "../Game/DirtyScene";
import { gameManager } from "../Game/GameManager";
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
import CancelablePromise from "cancelable-promise";
import Image = Phaser.GameObjects.Image;
import Texture = Phaser.Textures.Texture;
const LogoNameIndex: string = "logoLoading";
const TextName: string = "Loading..."; const TextName: string = "Loading...";
const LogoResource: string = "static/images/logo.png";
const LogoFrame: ImageFrameConfig = { frameWidth: 310, frameHeight: 60 };
const loadingBarHeight: number = 16; const loadingBarHeight: number = 16;
const padding: number = 5; const padding: number = 5;
@ -14,9 +16,15 @@ export class Loader {
private progress!: Phaser.GameObjects.Graphics; private progress!: Phaser.GameObjects.Graphics;
private progressAmount: number = 0; private progressAmount: number = 0;
private logo: Phaser.GameObjects.Image | undefined; private logo: Phaser.GameObjects.Image | undefined;
private logoPoweredBy: Phaser.GameObjects.Image | undefined;
private poweredByLogo: Phaser.GameObjects.Image | undefined;
private loadingText: Phaser.GameObjects.Text | null = null; private loadingText: Phaser.GameObjects.Text | null = null;
private logoNameIndex!: string;
private superLoad: SuperLoaderPlugin;
public constructor(private scene: Phaser.Scene) {} public constructor(private scene: Phaser.Scene) {
this.superLoad = new SuperLoaderPlugin(scene);
}
public addLoader(): void { public addLoader(): void {
// If there is nothing to load, do not display the loader. // If there is nothing to load, do not display the loader.
@ -24,43 +32,53 @@ export class Loader {
return; return;
} }
const logoResource = gameManager.currentStartedRoom.loadingLogo ?? "static/images/logo.png";
this.logoNameIndex = "logoLoading" + logoResource;
const loadingBarWidth: number = Math.floor(this.scene.game.renderer.width / 3); const loadingBarWidth: number = Math.floor(this.scene.game.renderer.width / 3);
const promiseLoadLogoTexture = new Promise<Phaser.GameObjects.Image>((res) => { //add loading if logo image until logo image is ready
if (this.scene.load.textureManager.exists(LogoNameIndex)) {
return res(
(this.logo = this.scene.add.image(
this.scene.game.renderer.width / 2,
this.scene.game.renderer.height / 2 - 150,
LogoNameIndex
))
);
} else {
//add loading if logo image is not ready
this.loadingText = this.scene.add.text( this.loadingText = this.scene.add.text(
this.scene.game.renderer.width / 2, this.scene.game.renderer.width / 2,
this.scene.game.renderer.height / 2 - 50, this.scene.game.renderer.height / 2 - 50,
TextName TextName
); );
}
this.scene.load.spritesheet(LogoNameIndex, LogoResource, LogoFrame); const logoPromise = this.superLoad.image(this.logoNameIndex, logoResource);
this.scene.load.once(`filecomplete-spritesheet-${LogoNameIndex}`, () => { logoPromise
if (this.loadingText) { .then((texture) => {
this.loadingText.destroy(); this.logo = this.scene.add.image(
}
return res(
(this.logo = this.scene.add.image(
this.scene.game.renderer.width / 2, this.scene.game.renderer.width / 2,
this.scene.game.renderer.height / 2 - 150, this.scene.game.renderer.height / 2 - 150,
LogoNameIndex texture
))
); );
});
}); this.loadingText?.destroy();
})
.catch((e) => console.warn("Could not load logo: ", logoResource, e));
let poweredByLogoPromise: CancelablePromise<Texture> | undefined;
if (gameManager.currentStartedRoom.loadingLogo) {
poweredByLogoPromise = this.superLoad.image(
"poweredByLogo",
"static/images/Powered_By_WorkAdventure_Small.png"
);
poweredByLogoPromise
.then((texture) => {
this.poweredByLogo = this.scene.add.image(
this.scene.game.renderer.width / 2,
this.scene.game.renderer.height - 50,
texture
);
})
.catch((e) =>
console.warn('Could not load image "static/images/Powered_By_WorkAdventure_Small.png"', e)
);
}
this.progressContainer = this.scene.add.graphics(); this.progressContainer = this.scene.add.graphics();
this.progress = this.scene.add.graphics();
this.progressContainer.fillStyle(0x444444, 0.8); this.progressContainer.fillStyle(0x444444, 0.8);
this.progress = this.scene.add.graphics();
this.resize(); this.resize();
@ -68,26 +86,35 @@ export class Loader {
this.progressAmount = value; this.progressAmount = value;
this.drawProgress(); this.drawProgress();
}); });
const resizeFunction = this.resize.bind(this);
this.scene.scale.on(Phaser.Scale.Events.RESIZE, resizeFunction);
this.scene.load.on("complete", () => { this.scene.load.on("complete", () => {
if (this.loadingText) { if (this.loadingText) {
this.loadingText.destroy(); this.loadingText.destroy();
} }
promiseLoadLogoTexture logoPromise.cancel();
.then((resLoadingImage: Phaser.GameObjects.Image) => { poweredByLogoPromise?.cancel();
resLoadingImage.destroy();
}) this.logo?.destroy();
.catch((e) => console.error(e)); this.poweredByLogo?.destroy();
this.progress.destroy(); this.progress.destroy();
this.progressContainer.destroy(); this.progressContainer.destroy();
if (this.scene instanceof DirtyScene) { if (this.scene instanceof DirtyScene) {
this.scene.markDirty(); this.scene.markDirty();
} }
this.scene.scale.off(Phaser.Scale.Events.RESIZE, resizeFunction);
}); });
} }
public removeLoader(): void { public removeLoader(): void {
if (this.scene.load.textureManager.exists(LogoNameIndex)) { if (this.scene.load.textureManager.exists(this.logoNameIndex)) {
this.scene.load.textureManager.remove(LogoNameIndex); this.scene.load.textureManager.remove(this.logoNameIndex);
}
if (this.scene.load.textureManager.exists("poweredByLogo")) {
this.scene.load.textureManager.remove("poweredByLogo");
} }
} }
@ -114,6 +141,11 @@ export class Loader {
this.logo.x = this.scene.game.renderer.width / 2; this.logo.x = this.scene.game.renderer.width / 2;
this.logo.y = this.scene.game.renderer.height / 2 - 150; this.logo.y = this.scene.game.renderer.height / 2 - 150;
} }
if (this.poweredByLogo) {
this.poweredByLogo.x = this.scene.game.renderer.width / 2;
this.poweredByLogo.y = this.scene.game.renderer.height - 40;
}
} }
private drawProgress() { private drawProgress() {

View File

@ -57,8 +57,8 @@ export class SoundMeter {
this.context = context; this.context = context;
this.analyser = this.context.createAnalyser(); this.analyser = this.context.createAnalyser();
this.analyser.fftSize = 2048; this.analyser.fftSize = 256;
const bufferLength = this.analyser.fftSize; const bufferLength = this.analyser.frequencyBinCount;
this.dataArray = new Uint8Array(bufferLength); this.dataArray = new Uint8Array(bufferLength);
} }

View File

@ -18,6 +18,7 @@ import { createColorStore } from "../../Stores/OutlineColorStore";
import type { OutlineableInterface } from "../Game/OutlineableInterface"; import type { OutlineableInterface } from "../Game/OutlineableInterface";
import type CancelablePromise from "cancelable-promise"; import type CancelablePromise from "cancelable-promise";
import { TalkIcon } from "../Components/TalkIcon"; import { TalkIcon } from "../Components/TalkIcon";
import { Deferred } from "ts-deferred";
const playerNameY = -25; const playerNameY = -25;
@ -50,6 +51,11 @@ export abstract class Character extends Container implements OutlineableInterfac
private readonly outlineColorStoreUnsubscribe: Unsubscriber; private readonly outlineColorStoreUnsubscribe: Unsubscriber;
private texturePromise: CancelablePromise<string[] | void> | undefined; private texturePromise: CancelablePromise<string[] | void> | undefined;
/**
* A deferred promise that resolves when the texture of the character is actually displayed.
*/
private textureLoadedDeferred = new Deferred<void>();
constructor( constructor(
scene: GameScene, scene: GameScene,
x: number, x: number,
@ -78,12 +84,13 @@ export abstract class Character extends Container implements OutlineableInterfac
this.addTextures(textures, frame); this.addTextures(textures, frame);
this.invisible = false; this.invisible = false;
this.playAnimation(direction, moving); this.playAnimation(direction, moving);
this.textureLoadedDeferred.resolve();
return this.getSnapshot().then((htmlImageElementSrc) => { return this.getSnapshot().then((htmlImageElementSrc) => {
this._pictureStore.set(htmlImageElementSrc); this._pictureStore.set(htmlImageElementSrc);
}); });
}) })
.catch(() => { .catch(() => {
return lazyLoadPlayerCharacterTextures(scene.load, [ return lazyLoadPlayerCharacterTextures(scene.superLoad, [
{ {
id: "color_22", id: "color_22",
img: "resources/customisation/character_color/character_color21.png", img: "resources/customisation/character_color/character_color21.png",
@ -92,10 +99,19 @@ export abstract class Character extends Container implements OutlineableInterfac
id: "eyes_23", id: "eyes_23",
img: "resources/customisation/character_eyes/character_eyes23.png", img: "resources/customisation/character_eyes/character_eyes23.png",
}, },
]).then((textures) => { ])
.then((textures) => {
this.addTextures(textures, frame); this.addTextures(textures, frame);
this.invisible = false; this.invisible = false;
this.playAnimation(direction, moving); this.playAnimation(direction, moving);
this.textureLoadedDeferred.resolve();
return this.getSnapshot().then((htmlImageElementSrc) => {
this._pictureStore.set(htmlImageElementSrc);
});
})
.catch((e) => {
this.textureLoadedDeferred.reject(e);
throw e;
}); });
}) })
.finally(() => { .finally(() => {
@ -517,4 +533,13 @@ export abstract class Character extends Container implements OutlineableInterfac
public characterFarAwayOutline(): void { public characterFarAwayOutline(): void {
this.outlineColorStore.characterFarAway(); this.outlineColorStore.characterFarAway();
} }
/**
* Returns a promise that resolves as soon as a texture is displayed for the user.
* The promise will return when the required texture is loaded OR when the fallback texture is loaded (in case
* the required texture could not be loaded).
*/
public getTextureLoadedPromise(): PromiseLike<void> {
return this.textureLoadedDeferred.promise;
}
} }

View File

@ -1,5 +1,7 @@
//The list of all the player textures, both the default models and the partial textures used for customization //The list of all the player textures, both the default models and the partial textures used for customization
import { WokaList, WokaPartType } from "../../Messages/JsonMessages/PlayerTextures";
export interface BodyResourceDescriptionListInterface { export interface BodyResourceDescriptionListInterface {
[key: string]: BodyResourceDescriptionInterface; [key: string]: BodyResourceDescriptionInterface;
} }
@ -33,24 +35,6 @@ export enum PlayerTexturesKey {
Woka = "woka", Woka = "woka",
} }
type PlayerTexturesMetadata = Record<PlayerTexturesKey, PlayerTexturesCategory>;
interface PlayerTexturesCategory {
collections: PlayerTexturesCollection[];
required?: boolean;
}
interface PlayerTexturesCollection {
name: string;
textures: PlayerTexturesRecord[];
}
interface PlayerTexturesRecord {
id: string;
name: string;
url: string;
}
export class PlayerTextures { export class PlayerTextures {
private PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {}; private PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {};
private COLOR_RESOURCES: BodyResourceDescriptionListInterface = {}; private COLOR_RESOURCES: BodyResourceDescriptionListInterface = {};
@ -61,7 +45,7 @@ export class PlayerTextures {
private ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {}; private ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {};
private LAYERS: BodyResourceDescriptionListInterface[] = []; private LAYERS: BodyResourceDescriptionListInterface[] = [];
public loadPlayerTexturesMetadata(metadata: PlayerTexturesMetadata): void { public loadPlayerTexturesMetadata(metadata: WokaList): void {
this.mapTexturesMetadataIntoResources(metadata); this.mapTexturesMetadataIntoResources(metadata);
} }
@ -88,7 +72,7 @@ export class PlayerTextures {
return this.LAYERS; return this.LAYERS;
} }
private mapTexturesMetadataIntoResources(metadata: PlayerTexturesMetadata): void { private mapTexturesMetadataIntoResources(metadata: WokaList): void {
this.PLAYER_RESOURCES = this.getMappedResources(metadata.woka); this.PLAYER_RESOURCES = this.getMappedResources(metadata.woka);
this.COLOR_RESOURCES = this.getMappedResources(metadata.body); this.COLOR_RESOURCES = this.getMappedResources(metadata.body);
this.EYES_RESOURCES = this.getMappedResources(metadata.eyes); this.EYES_RESOURCES = this.getMappedResources(metadata.eyes);
@ -107,7 +91,7 @@ export class PlayerTextures {
]; ];
} }
private getMappedResources(category: PlayerTexturesCategory): BodyResourceDescriptionListInterface { private getMappedResources(category: WokaPartType): BodyResourceDescriptionListInterface {
const resources: BodyResourceDescriptionListInterface = {}; const resources: BodyResourceDescriptionListInterface = {};
if (!category) { if (!category) {
return {}; return {};

View File

@ -2,6 +2,8 @@ import LoaderPlugin = Phaser.Loader.LoaderPlugin;
import type { CharacterTexture } from "../../Connexion/LocalUser"; import type { CharacterTexture } from "../../Connexion/LocalUser";
import { BodyResourceDescriptionInterface, mapLayerToLevel, PlayerTextures, PlayerTexturesKey } from "./PlayerTextures"; import { BodyResourceDescriptionInterface, mapLayerToLevel, PlayerTextures, PlayerTexturesKey } from "./PlayerTextures";
import CancelablePromise from "cancelable-promise"; import CancelablePromise from "cancelable-promise";
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
import Texture = Phaser.Textures.Texture;
export interface FrameConfig { export interface FrameConfig {
frameWidth: number; frameWidth: number;
@ -35,81 +37,33 @@ export const loadAllDefaultModels = (
}; };
export const loadWokaTexture = ( export const loadWokaTexture = (
loaderPlugin: LoaderPlugin, superLoaderPlugin: SuperLoaderPlugin,
texture: BodyResourceDescriptionInterface texture: BodyResourceDescriptionInterface
): CancelablePromise<BodyResourceDescriptionInterface> => { ): CancelablePromise<Texture> => {
return createLoadingPromise(loaderPlugin, texture, { return superLoaderPlugin.spritesheet(texture.id, texture.img, {
frameWidth: 32, frameWidth: 32,
frameHeight: 32, frameHeight: 32,
}); });
}; };
export const lazyLoadPlayerCharacterTextures = ( export const lazyLoadPlayerCharacterTextures = (
loadPlugin: LoaderPlugin, superLoaderPlugin: SuperLoaderPlugin,
textures: BodyResourceDescriptionInterface[] textures: BodyResourceDescriptionInterface[]
): CancelablePromise<string[]> => { ): CancelablePromise<string[]> => {
const promisesList: CancelablePromise<unknown>[] = []; const promisesList: CancelablePromise<Texture>[] = [];
textures.forEach((texture) => { for (const texture of textures) {
try {
//TODO refactor
if (!loadPlugin.textureManager.exists(texture.id)) {
promisesList.push( promisesList.push(
createLoadingPromise(loadPlugin, texture, { superLoaderPlugin.spritesheet(texture.id, texture.img, {
frameWidth: 32, frameWidth: 32,
frameHeight: 32, frameHeight: 32,
}) })
); );
} }
} catch (err) { const returnPromise: CancelablePromise<Texture[]> = CancelablePromise.all(promisesList);
console.error(err);
}
});
let returnPromise: CancelablePromise<Array<string | BodyResourceDescriptionInterface>>;
if (promisesList.length > 0) {
loadPlugin.start();
returnPromise = CancelablePromise.all(promisesList).then(() => textures);
} else {
returnPromise = CancelablePromise.resolve(textures);
}
//If the loading fail, we render the default model instead. return returnPromise.then(() =>
return returnPromise.then((keys) => textures.map((key) => {
keys.map((key) => { return key.id;
return typeof key !== "string" ? key.id : key;
}) })
); );
}; };
export const createLoadingPromise = (
loadPlugin: LoaderPlugin,
playerResourceDescriptor: BodyResourceDescriptionInterface,
frameConfig: FrameConfig
) => {
return new CancelablePromise<BodyResourceDescriptionInterface>((res, rej, cancel) => {
if (loadPlugin.textureManager.exists(playerResourceDescriptor.id)) {
return res(playerResourceDescriptor);
}
cancel(() => {
loadPlugin.off("loaderror");
loadPlugin.off("filecomplete-spritesheet-" + playerResourceDescriptor.id);
return;
});
loadPlugin.spritesheet(playerResourceDescriptor.id, playerResourceDescriptor.img, frameConfig);
const errorCallback = (file: { src: string }) => {
if (file.src !== playerResourceDescriptor.img) return;
console.error("failed loading player resource: ", playerResourceDescriptor);
rej(playerResourceDescriptor);
loadPlugin.off("filecomplete-spritesheet-" + playerResourceDescriptor.id, successCallback);
loadPlugin.off("loaderror", errorCallback);
};
const successCallback = () => {
loadPlugin.off("loaderror", errorCallback);
res(playerResourceDescriptor);
};
loadPlugin.once("filecomplete-spritesheet-" + playerResourceDescriptor.id, successCallback);
loadPlugin.on("loaderror", errorCallback);
});
};

View File

@ -19,7 +19,7 @@ export class GameManager {
private companion: string | null; private companion: string | null;
private startRoom!: Room; private startRoom!: Room;
private cameraSetup?: { video: unknown; audio: unknown }; private cameraSetup?: { video: unknown; audio: unknown };
currentGameSceneName: string | null = null; private currentGameSceneName: string | null = null;
// Note: this scenePlugin is the scenePlugin of the EntryScene. We should always provide a key in methods called on this scenePlugin. // Note: this scenePlugin is the scenePlugin of the EntryScene. We should always provide a key in methods called on this scenePlugin.
private scenePlugin!: Phaser.Scenes.ScenePlugin; private scenePlugin!: Phaser.Scenes.ScenePlugin;

View File

@ -18,7 +18,7 @@ import { soundManager } from "./SoundManager";
import { SharedVariablesManager } from "./SharedVariablesManager"; import { SharedVariablesManager } from "./SharedVariablesManager";
import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager"; import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
import { lazyLoadPlayerCharacterTextures, loadWokaTexture } from "../Entity/PlayerTexturesLoadingManager"; import { lazyLoadPlayerCharacterTextures } from "../Entity/PlayerTexturesLoadingManager";
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager"; import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
import { iframeListener } from "../../Api/IframeListener"; import { iframeListener } from "../../Api/IframeListener";
import { DEBUG_MODE, JITSI_URL, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable"; import { DEBUG_MODE, JITSI_URL, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable";
@ -99,6 +99,8 @@ import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite";
import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite"; import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite";
import type { VideoPeer } from "../../WebRtc/VideoPeer"; import type { VideoPeer } from "../../WebRtc/VideoPeer";
import CancelablePromise from "cancelable-promise"; import CancelablePromise from "cancelable-promise";
import { Deferred } from "ts-deferred";
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
export interface GameSceneInitInterface { export interface GameSceneInitInterface {
initPosition: PointInterface | null; initPosition: PointInterface | null;
reconnecting: boolean; reconnecting: boolean;
@ -164,13 +166,9 @@ export class GameScene extends DirtyScene {
private playersPositionInterpolator = new PlayersPositionInterpolator(); private playersPositionInterpolator = new PlayersPositionInterpolator();
public connection: RoomConnection | undefined; public connection: RoomConnection | undefined;
private simplePeer!: SimplePeer; private simplePeer!: SimplePeer;
private connectionAnswerPromise: Promise<RoomJoinedMessageInterface>; private connectionAnswerPromiseDeferred: Deferred<RoomJoinedMessageInterface>;
private connectionAnswerPromiseResolve!: (
value: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>
) => void;
// A promise that will resolve when the "create" method is called (signaling loading is ended) // A promise that will resolve when the "create" method is called (signaling loading is ended)
private createPromise: Promise<void>; private createPromiseDeferred: Deferred<void>;
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
private iframeSubscriptionList!: Array<Subscription>; private iframeSubscriptionList!: Array<Subscription>;
private peerStoreUnsubscribe!: Unsubscriber; private peerStoreUnsubscribe!: Unsubscriber;
private emoteUnsubscribe!: Unsubscriber; private emoteUnsubscribe!: Unsubscriber;
@ -220,6 +218,7 @@ export class GameScene extends DirtyScene {
private loader: Loader; private loader: Loader;
private lastCameraEvent: WasCameraUpdatedEvent | undefined; private lastCameraEvent: WasCameraUpdatedEvent | undefined;
private firstCameraUpdateSent: boolean = false; private firstCameraUpdateSent: boolean = false;
public readonly superLoad: SuperLoaderPlugin;
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) { constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
super({ super({
@ -232,13 +231,10 @@ export class GameScene extends DirtyScene {
this.MapUrlFile = MapUrlFile; this.MapUrlFile = MapUrlFile;
this.roomUrl = room.key; this.roomUrl = room.key;
this.createPromise = new Promise<void>((resolve, reject): void => { this.createPromiseDeferred = new Deferred<void>();
this.createPromiseResolve = resolve; this.connectionAnswerPromiseDeferred = new Deferred<RoomJoinedMessageInterface>();
});
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
this.connectionAnswerPromiseResolve = resolve;
});
this.loader = new Loader(this); this.loader = new Loader(this);
this.superLoad = new SuperLoaderPlugin(this);
} }
//hook preload scene //hook preload scene
@ -408,11 +404,11 @@ export class GameScene extends DirtyScene {
this.load.on("complete", () => { this.load.on("complete", () => {
// FIXME: the factory might fail because the resources might not be loaded yet... // FIXME: the factory might fail because the resources might not be loaded yet...
// We would need to add a loader ended event in addition to the createPromise // We would need to add a loader ended event in addition to the createPromise
this.createPromise this.createPromiseDeferred.promise
.then(async () => { .then(async () => {
itemFactory.create(this); itemFactory.create(this);
const roomJoinedAnswer = await this.connectionAnswerPromise; const roomJoinedAnswer = await this.connectionAnswerPromiseDeferred.promise;
for (const object of objectsOfType) { for (const object of objectsOfType) {
// TODO: we should pass here a factory to create sprites (maybe?) // TODO: we should pass here a factory to create sprites (maybe?)
@ -609,7 +605,7 @@ export class GameScene extends DirtyScene {
} }
} }
this.createPromiseResolve(); this.createPromiseDeferred.resolve();
// Now, let's load the script, if any // Now, let's load the script, if any
const scripts = this.getScriptUrls(this.mapFile); const scripts = this.getScriptUrls(this.mapFile);
const disableModuleMode = this.getProperty(this.mapFile, GameMapProperties.SCRIPT_DISABLE_MODULE_SUPPORT) as const disableModuleMode = this.getProperty(this.mapFile, GameMapProperties.SCRIPT_DISABLE_MODULE_SUPPORT) as
@ -712,7 +708,11 @@ export class GameScene extends DirtyScene {
} }
}); });
Promise.all([this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises]) Promise.all([
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
...scriptPromises,
this.CurrentPlayer.getTextureLoadedPromise() as Promise<unknown>,
])
.then(() => { .then(() => {
this.scene.wake(); this.scene.wake();
}) })
@ -749,7 +749,7 @@ export class GameScene extends DirtyScene {
.then((onConnect: OnConnectInterface) => { .then((onConnect: OnConnectInterface) => {
this.connection = onConnect.connection; this.connection = onConnect.connection;
lazyLoadPlayerCharacterTextures(this.load, onConnect.room.characterLayers) lazyLoadPlayerCharacterTextures(this.superLoad, onConnect.room.characterLayers)
.then((layers) => { .then((layers) => {
this.currentPlayerTexturesResolve(layers); this.currentPlayerTexturesResolve(layers);
}) })
@ -878,7 +878,7 @@ export class GameScene extends DirtyScene {
); );
//this.initUsersPosition(roomJoinedMessage.users); //this.initUsersPosition(roomJoinedMessage.users);
this.connectionAnswerPromiseResolve(onConnect.room); this.connectionAnswerPromiseDeferred.resolve(onConnect.room);
// Analyze tags to find if we are admin. If yes, show console. // Analyze tags to find if we are admin. If yes, show console.
if (this.scene.isSleeping()) { if (this.scene.isSleeping()) {
@ -1293,7 +1293,7 @@ ${escapedMessage}
iframeListener.registerAnswerer("getState", async () => { iframeListener.registerAnswerer("getState", async () => {
// The sharedVariablesManager is not instantiated before the connection is established. So we need to wait // The sharedVariablesManager is not instantiated before the connection is established. So we need to wait
// for the connection to send back the answer. // for the connection to send back the answer.
await this.connectionAnswerPromise; await this.connectionAnswerPromiseDeferred.promise;
return { return {
mapUrl: this.MapUrlFile, mapUrl: this.MapUrlFile,
startLayerName: this.startPositionCalculator.startLayerName, startLayerName: this.startPositionCalculator.startLayerName,
@ -1316,7 +1316,7 @@ ${escapedMessage}
}) })
); );
iframeListener.registerAnswerer("loadTileset", (eventTileset) => { iframeListener.registerAnswerer("loadTileset", (eventTileset) => {
return this.connectionAnswerPromise.then(() => { return this.connectionAnswerPromiseDeferred.promise.then(() => {
const jsonTilesetDir = eventTileset.url.substr(0, eventTileset.url.lastIndexOf("/")); const jsonTilesetDir = eventTileset.url.substr(0, eventTileset.url.lastIndexOf("/"));
//Initialise the firstgid to 1 because if there is no tileset in the tilemap, the firstgid will be 1 //Initialise the firstgid to 1 because if there is no tileset in the tilemap, the firstgid will be 1
let newFirstgid = 1; let newFirstgid = 1;
@ -1917,7 +1917,7 @@ ${escapedMessage}
return; return;
} }
const texturesPromise = lazyLoadPlayerCharacterTextures(this.load, addPlayerData.characterLayers); const texturesPromise = lazyLoadPlayerCharacterTextures(this.superLoad, addPlayerData.characterLayers);
const player = new RemotePlayer( const player = new RemotePlayer(
addPlayerData.userId, addPlayerData.userId,
addPlayerData.userUuid, addPlayerData.userUuid,
@ -2088,8 +2088,6 @@ ${escapedMessage}
right: camera.scrollX + camera.width, right: camera.scrollX + camera.width,
bottom: camera.scrollY + camera.height, bottom: camera.scrollY + camera.height,
}); });
this.loader.resize();
} }
private getObjectLayerData(objectName: string): ITiledMapObject | undefined { private getObjectLayerData(objectName: string): ITiledMapObject | undefined {

View File

@ -3,39 +3,16 @@ import { BodyResourceDescriptionInterface, PlayerTexturesKey } from "../Entity/P
import { loadWokaTexture } from "../Entity/PlayerTexturesLoadingManager"; import { loadWokaTexture } from "../Entity/PlayerTexturesLoadingManager";
import type CancelablePromise from "cancelable-promise"; import type CancelablePromise from "cancelable-promise";
import { PlayerTextures } from "../Entity/PlayerTextures"; import { PlayerTextures } from "../Entity/PlayerTextures";
import Texture = Phaser.Textures.Texture;
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
export abstract class AbstractCharacterScene extends ResizableScene { export abstract class AbstractCharacterScene extends ResizableScene {
protected playerTextures: PlayerTextures; protected playerTextures: PlayerTextures;
protected superLoad: SuperLoaderPlugin;
constructor(params: { key: string }) { constructor(params: { key: string }) {
super(params); super(params);
this.playerTextures = new PlayerTextures(); this.playerTextures = new PlayerTextures();
} this.superLoad = new SuperLoaderPlugin(this);
loadCustomSceneSelectCharacters(): Promise<BodyResourceDescriptionInterface[]> {
const textures = this.playerTextures.getTexturesResources(PlayerTexturesKey.Woka);
const promises: CancelablePromise<BodyResourceDescriptionInterface>[] = [];
if (textures) {
for (const texture of Object.values(textures)) {
if (texture.level === -1) {
continue;
}
promises.push(loadWokaTexture(this.load, texture));
}
}
return Promise.all(promises);
}
loadSelectSceneCharacters(): Promise<BodyResourceDescriptionInterface[]> {
const promises: CancelablePromise<BodyResourceDescriptionInterface>[] = [];
for (const textures of this.playerTextures.getLayers()) {
for (const texture of Object.values(textures)) {
if (texture.level !== -1) {
continue;
}
promises.push(loadWokaTexture(this.load, texture));
}
}
return Promise.all(promises);
} }
} }

View File

@ -16,6 +16,7 @@ import { get } from "svelte/store";
import { analyticsClient } from "../../Administration/AnalyticsClient"; import { analyticsClient } from "../../Administration/AnalyticsClient";
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils"; import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
import { PUSHER_URL } from "../../Enum/EnvironmentVariable"; import { PUSHER_URL } from "../../Enum/EnvironmentVariable";
import { wokaList } from "../../Messages/JsonMessages/PlayerTextures";
export const CustomizeSceneName = "CustomizeScene"; export const CustomizeSceneName = "CustomizeScene";
@ -41,12 +42,12 @@ export class CustomizeScene extends AbstractCharacterScene {
} }
preload() { preload() {
const wokaMetadataKey = "woka-list"; const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href;
this.cache.json.remove(wokaMetadataKey); this.cache.json.remove(wokaMetadataKey);
// FIXME: window.location.href is wrong. We need the URL of the main room (so we need to apply any redirect before!) this.superLoad
this.load.json( .json(
wokaMetadataKey, wokaMetadataKey,
`${PUSHER_URL}/woka/list?roomUrl=` + encodeURIComponent(window.location.href), `${PUSHER_URL}/woka/list?roomUrl=` + encodeURIComponent(gameManager.currentStartedRoom.href),
undefined, undefined,
{ {
responseType: "text", responseType: "text",
@ -54,32 +55,17 @@ export class CustomizeScene extends AbstractCharacterScene {
Authorization: localUserStore.getAuthToken() ?? "", Authorization: localUserStore.getAuthToken() ?? "",
}, },
withCredentials: true, withCredentials: true,
} },
); (key, type, data) => {
this.load.once(`filecomplete-json-${wokaMetadataKey}`, () => { this.playerTextures.loadPlayerTexturesMetadata(wokaList.parse(data));
this.playerTextures.loadPlayerTexturesMetadata(this.cache.json.get(wokaMetadataKey));
this.loadCustomSceneSelectCharacters()
.then((bodyResourceDescriptions) => {
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
if (
bodyResourceDescription.level == undefined ||
bodyResourceDescription.level < 0 ||
bodyResourceDescription.level > 5
) {
throw new Error("Texture level is null");
}
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
});
this.lazyloadingAttempt = true;
})
.catch((e) => console.error(e));
this.layers = loadAllLayers(this.load, this.playerTextures); this.layers = loadAllLayers(this.load, this.playerTextures);
this.lazyloadingAttempt = false; this.lazyloadingAttempt = false;
}
)
.catch((e) => console.error(e));
//this function must stay at the end of preload function //this function must stay at the end of preload function
this.loader.addLoader(); this.loader.addLoader();
});
} }
create() { create() {

View File

@ -16,6 +16,7 @@ import { analyticsClient } from "../../Administration/AnalyticsClient";
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils"; import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
import { PUSHER_URL } from "../../Enum/EnvironmentVariable"; import { PUSHER_URL } from "../../Enum/EnvironmentVariable";
import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore"; import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore";
import { wokaList } from "../../Messages/JsonMessages/PlayerTextures";
//todo: put this constants in a dedicated file //todo: put this constants in a dedicated file
export const SelectCharacterSceneName = "SelectCharacterScene"; export const SelectCharacterSceneName = "SelectCharacterScene";
@ -44,13 +45,13 @@ export class SelectCharacterScene extends AbstractCharacterScene {
} }
preload() { preload() {
const wokaMetadataKey = "woka-list"; const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href;
this.cache.json.remove(wokaMetadataKey); this.cache.json.remove(wokaMetadataKey);
// FIXME: window.location.href is wrong. We need the URL of the main room (so we need to apply any redirect before!) this.superLoad
this.load.json( .json(
wokaMetadataKey, wokaMetadataKey,
`${PUSHER_URL}/woka/list?roomUrl=` + encodeURIComponent(window.location.href), `${PUSHER_URL}/woka/list?roomUrl=` + encodeURIComponent(gameManager.currentStartedRoom.href),
undefined, undefined,
{ {
responseType: "text", responseType: "text",
@ -58,24 +59,17 @@ export class SelectCharacterScene extends AbstractCharacterScene {
Authorization: localUserStore.getAuthToken() ?? "", Authorization: localUserStore.getAuthToken() ?? "",
}, },
withCredentials: true, withCredentials: true,
} },
); (key, type, data) => {
this.load.once(`filecomplete-json-${wokaMetadataKey}`, () => { this.playerTextures.loadPlayerTexturesMetadata(wokaList.parse(data));
this.playerTextures.loadPlayerTexturesMetadata(this.cache.json.get(wokaMetadataKey));
this.loadSelectSceneCharacters()
.then((bodyResourceDescriptions) => {
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
this.playerModels.push(bodyResourceDescription);
});
this.lazyloadingAttempt = true;
})
.catch((e) => console.error(e));
this.playerModels = loadAllDefaultModels(this.load, this.playerTextures); this.playerModels = loadAllDefaultModels(this.load, this.playerTextures);
this.lazyloadingAttempt = false; this.lazyloadingAttempt = false;
}
)
.catch((e) => console.error(e));
//this function must stay at the end of preload function //this function must stay at the end of preload function
this.loader.addLoader(); this.loader.addLoader();
});
} }
create() { create() {

View File

@ -0,0 +1,176 @@
import CancelablePromise from "cancelable-promise";
import { Scene } from "phaser";
import Texture = Phaser.Textures.Texture;
/**
* A wrapper around Phaser LoaderPlugin. Each method returns a (cancelable) Promise that resolves as soon as
* the file is loaded.
*
* As a bonus, if the scene is destroyed BEFORE the promise resolves, the promise is canceled automatically.
* So there is no risk of trying to add a resource on a closed scene.
*/
export class SuperLoaderPlugin {
constructor(private scene: Scene) {}
public spritesheet(
key: string,
url: string,
frameConfig?: Phaser.Types.Loader.FileTypes.ImageFrameConfig,
xhrSettings?: Phaser.Types.Loader.XHRSettingsObject
) {
return this.loadResource<Texture>(
() => {
this.scene.load.spritesheet(key, url, frameConfig, xhrSettings);
},
key,
url,
() => {
if (this.scene.load.textureManager.exists(key)) {
return this.scene.load.textureManager.get(key);
}
return undefined;
},
"spritesheet"
);
}
public image(key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {
return this.loadResource<Texture>(
() => {
this.scene.load.image(key, url, xhrSettings);
},
key,
url,
() => {
if (this.scene.load.textureManager.exists(key)) {
return this.scene.load.textureManager.get(key);
}
return undefined;
},
"image"
);
}
/**
* @param key
* @param url
* @param dataKey
* @param xhrSettings
* @param immediateCallback The function returns a promise BUT the "then" promise will be triggered after the current Javascript thread finishes. In case of Phaser loader, this can be a problem if you want to add additional resources to the loader in the callback. The "immediateCallback" triggers directly in the
*/
public json(
key: string,
url: string,
dataKey?: string,
xhrSettings?: Phaser.Types.Loader.XHRSettingsObject,
immediateCallback?: (key: string, type: string, data: unknown) => void
) {
return this.loadResource<unknown>(
() => {
this.scene.load.json(key, url, dataKey, xhrSettings);
},
key,
url,
() => {
if (this.scene.load.cacheManager.json.exists(key)) {
return this.scene.load.cacheManager.json.get(key);
}
return undefined;
},
"json",
immediateCallback
);
}
/**
* @param callback The function that calls the loader to load a resource
* @param key The key of the resource to be loaded
* @param fromCache A function that checks in the cache if the resource is already available
* @param type The type of resource loaded
* @param immediateCallback The function returns a promise BUT the "then" promise will be triggered after the current Javascript thread finishes. In case of Phaser loader, this can be a problem if you want to add additional resources to the loader in the callback. The "immediateCallback" triggers directly in the
* @private
*/
private loadResource<T>(
callback: () => void,
key: string,
url: string,
fromCache: () => T | undefined,
type: string,
immediateCallback?: (key: string, type: string, data: unknown) => void
): CancelablePromise<T> {
// If for some reason, the "url" is empty, let's reject the promise.
if (!url) {
console.error("Tried to load an empty " + type + ". URL is missing.");
return CancelablePromise.reject(Error("Failed loading " + type + ": URL is empty"));
}
return new CancelablePromise<T>((res, rej, cancel) => {
if (this.scene.scene.settings.status === Phaser.Scenes.DESTROYED) {
rej(new Error("Trying to load a " + type + " in a Scene that is already destroyed."));
}
const resource = fromCache();
if (resource !== undefined) {
return res(resource);
}
let destroySceneEventRegistered = false;
const unloadCallbacks = () => {
this.scene.load.off("filecomplete-" + type + "-" + key, successCallback);
this.scene.load.off("loaderror", errorCallback);
if (destroySceneEventRegistered) {
this.scene.events.off(Phaser.Scenes.Events.DESTROY, unloadCallbacks);
}
};
const errorCallback = (file: { src: string }) => {
if (file.src !== url) return;
console.error("Failed loading " + type + ": ", url);
rej(new Error('Failed loading "+type+": "' + url + '"'));
unloadCallbacks();
};
const successCallback = (key: string, type: string, data: unknown) => {
this.scene.load.off("loaderror", errorCallback);
this.scene.events.off(Phaser.Scenes.Events.DESTROY, unloadCallbacks);
const resource = fromCache();
if (!resource) {
return rej(new Error("Newly loaded resource not available in cache"));
}
res(resource);
// The "then" callbacks registered on the promise are not executed immediately when "res" is called.
// Instead, they are called after the current JS thread finishes.
// In some cases, we want the callbacks to execute right now. In particular if we load a map / json file
// that contains references to other files that needs to be loaded.
if (immediateCallback) {
immediateCallback(key, type, data);
}
console.log("Resolve done for ", url);
};
cancel(() => {
unloadCallbacks();
});
callback();
this.scene.load.once("filecomplete-" + type + "-" + key, successCallback);
this.scene.load.on("loaderror", errorCallback);
if (this.scene.scene.settings.status > Phaser.Scenes.LOADING) {
// When the scene is destroyed, let's remove our callbacks.
// We only need to register this destroy event is the scene is not in loading state (otherwise, Phaser
// will take care of that for us).
destroySceneEventRegistered = true;
this.scene.events.once(Phaser.Scenes.Events.DESTROY, unloadCallbacks);
// Let's start the loader if we are no more in the scene loading state
this.scene.load.start();
// Due to a bug, if the loader is already started, additional items are not added.... unless we
// explicitly call the "update" method.
this.scene.load.update();
}
});
}
}

View File

@ -545,8 +545,12 @@ export const obtainedMediaConstraintStore = derived<Readable<MediaStreamConstrai
export const localVolumeStore = readable<number | undefined>(undefined, (set) => { export const localVolumeStore = readable<number | undefined>(undefined, (set) => {
let timeout: ReturnType<typeof setTimeout>; let timeout: ReturnType<typeof setTimeout>;
let soundMeter: SoundMeter;
const unsubscribe = localStreamStore.subscribe((localStreamStoreValue) => { const unsubscribe = localStreamStore.subscribe((localStreamStoreValue) => {
clearInterval(timeout); clearInterval(timeout);
if (soundMeter) {
soundMeter.stop();
}
if (localStreamStoreValue.type === "error") { if (localStreamStoreValue.type === "error") {
set(undefined); set(undefined);
return; return;
@ -557,7 +561,7 @@ export const localVolumeStore = readable<number | undefined>(undefined, (set) =>
set(undefined); set(undefined);
return; return;
} }
const soundMeter = new SoundMeter(mediaStream); soundMeter = new SoundMeter(mediaStream);
let error = false; let error = false;
timeout = setInterval(() => { timeout = setInterval(() => {
@ -575,6 +579,9 @@ export const localVolumeStore = readable<number | undefined>(undefined, (set) =>
return () => { return () => {
unsubscribe(); unsubscribe();
clearInterval(timeout); clearInterval(timeout);
if (soundMeter) {
soundMeter.stop();
}
}; };
}); });

View File

@ -619,7 +619,10 @@ class CoWebsiteManager {
setTimeout(() => { setTimeout(() => {
this.fire(); this.fire();
}, animationTime); }, animationTime);
} else if (!highlightedEmbed) { } else if (
!highlightedEmbed &&
this.getCoWebsites().find((searchCoWebsite) => searchCoWebsite.getId() === coWebsite.getId())
) {
highlightedEmbedScreen.toggleHighlight({ highlightedEmbedScreen.toggleHighlight({
type: "cowebsite", type: "cowebsite",
embed: coWebsite, embed: coWebsite,

View File

@ -197,7 +197,10 @@ class JitsiFactory {
options.onload = () => doResolve(); //we want for the iframe to be loaded before triggering animations. options.onload = () => doResolve(); //we want for the iframe to be loaded before triggering animations.
this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options); this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options);
this.jitsiApi.executeCommand("displayName", playerName);
this.jitsiApi.addListener("videoConferenceJoined", () => {
this.jitsiApi?.executeCommand("displayName", playerName);
});
this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback); this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback);
this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback); this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback);

View File

@ -74,12 +74,17 @@ export class VideoPeer extends Peer {
this.volumeStore = readable<number | undefined>(undefined, (set) => { this.volumeStore = readable<number | undefined>(undefined, (set) => {
let timeout: ReturnType<typeof setTimeout>; let timeout: ReturnType<typeof setTimeout>;
let soundMeter: SoundMeter;
const unsubscribe = this.streamStore.subscribe((mediaStream) => { const unsubscribe = this.streamStore.subscribe((mediaStream) => {
clearInterval(timeout);
if (soundMeter) {
soundMeter.stop();
}
if (mediaStream === null || mediaStream.getAudioTracks().length <= 0) { if (mediaStream === null || mediaStream.getAudioTracks().length <= 0) {
set(undefined); set(undefined);
return; return;
} }
const soundMeter = new SoundMeter(mediaStream); soundMeter = new SoundMeter(mediaStream);
let error = false; let error = false;
timeout = setInterval(() => { timeout = setInterval(() => {
@ -97,6 +102,9 @@ export class VideoPeer extends Peer {
return () => { return () => {
unsubscribe(); unsubscribe();
clearInterval(timeout); clearInterval(timeout);
if (soundMeter) {
soundMeter.stop();
}
}; };
}); });

View File

@ -13,6 +13,10 @@ const camera: NonNullable<Translation["camera"]> = {
'Bitte klicke auf "Diese Entscheidungen speichern" Schaltfläche um erneute Nachfragen nach der Freigabe in Firefox zu verhindern.', 'Bitte klicke auf "Diese Entscheidungen speichern" Schaltfläche um erneute Nachfragen nach der Freigabe in Firefox zu verhindern.',
refresh: "Aktualisieren", refresh: "Aktualisieren",
continue: "Ohne Kamera fortfahren", continue: "Ohne Kamera fortfahren",
screen: {
firefox: "/resources/help-setting-camera-permission/de-DE-chrome.png",
chrome: "/resources/help-setting-camera-permission/de-DE-chrome.png",
},
}, },
my: { my: {
silentZone: "Stiller Bereich", silentZone: "Stiller Bereich",

View File

@ -13,6 +13,10 @@ const camera: BaseTranslation = {
'Please click the "Remember this decision" checkbox, if you don\'t want Firefox to keep asking you the authorization.', 'Please click the "Remember this decision" checkbox, if you don\'t want Firefox to keep asking you the authorization.',
refresh: "Refresh", refresh: "Refresh",
continue: "Continue without webcam", continue: "Continue without webcam",
screen: {
firefox: "/resources/help-setting-camera-permission/en-US-firefox.png",
chrome: "/resources/help-setting-camera-permission/en-US-firefox.png",
},
}, },
my: { my: {
silentZone: "Silent zone", silentZone: "Silent zone",

View File

@ -13,6 +13,10 @@ const camera: NonNullable<Translation["camera"]> = {
'Veuillez cocher la case "Se souvenir de cette décision" si vous ne voulez pas que Firefox vous demande sans cesse l\'autorisation.', 'Veuillez cocher la case "Se souvenir de cette décision" si vous ne voulez pas que Firefox vous demande sans cesse l\'autorisation.',
refresh: "Rafraîchir", refresh: "Rafraîchir",
continue: "Continuer sans webcam", continue: "Continuer sans webcam",
screen: {
firefox: "/resources/help-setting-camera-permission/fr-FR-chrome.png",
chrome: "/resources/help-setting-camera-permission/fr-FR-chrome.png",
},
}, },
my: { my: {
silentZone: "Zone silencieuse", silentZone: "Zone silencieuse",

View File

@ -2,7 +2,7 @@ import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte"; import { svelte } from "@sveltejs/vite-plugin-svelte";
import { envConfig } from "@geprog/vite-plugin-env-config"; import { envConfig } from "@geprog/vite-plugin-env-config";
import sveltePreprocess from "svelte-preprocess"; import sveltePreprocess from "svelte-preprocess";
import pluginRewriteAll from 'vite-plugin-rewrite-all'; import pluginRewriteAll from "vite-plugin-rewrite-all";
export default defineConfig({ export default defineConfig({
server: { server: {
@ -10,7 +10,10 @@ export default defineConfig({
hmr: { hmr: {
// workaround for development in docker // workaround for development in docker
clientPort: 80, clientPort: 80,
} },
},
build: {
sourcemap: true,
}, },
plugins: [ plugins: [
svelte({ svelte({

View File

@ -2900,6 +2900,11 @@ to-regex-range@^5.0.1:
dependencies: dependencies:
is-number "^7.0.0" is-number "^7.0.0"
ts-deferred@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/ts-deferred/-/ts-deferred-1.0.4.tgz#58145ebaeef5b8f2a290b8cec3d060839f9489c7"
integrity sha1-WBReuu71uPKikLjOw9Bgg5+Uicc=
ts-node@^10.4.0: ts-node@^10.4.0:
version "10.4.0" version "10.4.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7"

View File

@ -22,6 +22,10 @@ export const isMapDetailsData = new tg.IsInterface()
expireOn: tg.isString, expireOn: tg.isString,
// Whether the "report" feature is enabled or not on this room // Whether the "report" feature is enabled or not on this room
canReport: tg.isBoolean, canReport: tg.isBoolean,
// The URL of the logo image on the loading screen
loadingLogo: tg.isNullable(tg.isString),
// The URL of the logo image on "LoginScene"
loginSceneLogo: tg.isNullable(tg.isString),
}) })
.get(); .get();

View File

@ -21,7 +21,8 @@
"generic-type-guard": "^3.5.0", "generic-type-guard": "^3.5.0",
"google-protobuf": "^3.13.0", "google-protobuf": "^3.13.0",
"grpc": "^1.24.4", "grpc": "^1.24.4",
"ts-proto": "^1.96.0" "ts-proto": "^1.96.0",
"zod": "^3.12.0"
}, },
"devDependencies": { "devDependencies": {
"@types/google-protobuf": "^3.7.4", "@types/google-protobuf": "^3.7.4",

View File

@ -4645,3 +4645,8 @@ year@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0"
integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A= integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A=
zod@^3.12.0:
version "3.14.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.14.2.tgz#0b4ed79085c471adce0e7f2c0a4fbb5ddc516ba2"
integrity sha512-iF+wrtzz7fQfkmn60PG6XFxaWBhYYKzp2i+nv24WbLUWb2JjymdkHlzBwP0erpc78WotwP5g9AAu7Sk8GWVVNw==

View File

@ -37,7 +37,7 @@ import { InvalidTokenError } from "../Controller/InvalidTokenError";
import HyperExpress from "hyper-express"; import HyperExpress from "hyper-express";
import { localWokaService } from "../Services/LocalWokaService"; import { localWokaService } from "../Services/LocalWokaService";
import { WebSocket } from "uWebSockets.js"; import { WebSocket } from "uWebSockets.js";
import { WokaDetail } from "../Enum/PlayerTextures"; import { WokaDetail } from "../Messages/JsonMessages/PlayerTextures";
/** /**
* The object passed between the "open" and the "upgrade" methods when opening a websocket * The object passed between the "open" and the "upgrade" methods when opening a websocket

View File

@ -88,6 +88,14 @@ export class MapController extends BaseHttpController {
* type: boolean|undefined * type: boolean|undefined
* description: Whether the "report" feature is enabled or not on this room * description: Whether the "report" feature is enabled or not on this room
* example: true * example: true
* loadingLogo:
* type: string
* description: The URL of the image to be used on the loading page
* example: https://example.com/logo.png
* loginSceneLogo:
* type: string
* description: The URL of the image to be used on the LoginScene
* example: https://example.com/logo_login.png
* *
*/ */
this.app.get("/map", (req, res) => { this.app.get("/map", (req, res) => {

View File

@ -92,10 +92,12 @@ export class PositionDispatcher {
public removeViewport(socket: ExSocketInterface): void { public removeViewport(socket: ExSocketInterface): void {
// Also, let's stop listening on viewports // Also, let's stop listening on viewports
if (socket.listenedZones) {
for (const zone of socket.listenedZones) { for (const zone of socket.listenedZones) {
this.stopListening(zone, socket); this.stopListening(zone, socket);
} }
} }
}
public isEmpty(): boolean { public isEmpty(): boolean {
return Object.keys(this.zones).length === 0; return Object.keys(this.zones).length === 0;

View File

@ -11,7 +11,7 @@ import {
import { ClientDuplexStream } from "grpc"; import { ClientDuplexStream } from "grpc";
import { Zone } from "_Model/Zone"; import { Zone } from "_Model/Zone";
import { compressors } from "hyper-express"; import { compressors } from "hyper-express";
import { WokaDetail } from "_Enum/PlayerTextures"; import { WokaDetail } from "../../Messages/JsonMessages/PlayerTextures";
export type BackConnection = ClientDuplexStream<PusherToBackMessage, ServerToClientMessage>; export type BackConnection = ClientDuplexStream<PusherToBackMessage, ServerToClientMessage>;

View File

@ -9,7 +9,7 @@ import { ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
import Direction = PositionMessage.Direction; import Direction = PositionMessage.Direction;
import { ItemEventMessageInterface } from "_Model/Websocket/ItemEventMessage"; import { ItemEventMessageInterface } from "_Model/Websocket/ItemEventMessage";
import { PositionInterface } from "_Model/PositionInterface"; import { PositionInterface } from "_Model/PositionInterface";
import { WokaDetail } from "_Enum/PlayerTextures"; import { WokaDetail } from "../../Messages/JsonMessages/PlayerTextures";
export class ProtobufUtils { export class ProtobufUtils {
public static toPositionMessage(point: PointInterface): PositionMessage { public static toPositionMessage(point: PointInterface): PositionMessage {

View File

@ -1,11 +1,11 @@
import { ADMIN_API_TOKEN, ADMIN_API_URL, ADMIN_URL, OPID_PROFILE_SCREEN_PROVIDER } from "../Enum/EnvironmentVariable"; import { ADMIN_API_TOKEN, ADMIN_API_URL, ADMIN_URL, OPID_PROFILE_SCREEN_PROVIDER } from "../Enum/EnvironmentVariable";
import Axios, { AxiosResponse } from "axios"; import Axios, { AxiosResponse } from "axios";
import { MapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; import { isMapDetailsData, MapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
import { RoomRedirect } from "../Messages/JsonMessages/RoomRedirect"; import { isRoomRedirect, RoomRedirect } from "../Messages/JsonMessages/RoomRedirect";
import { AdminApiData, isAdminApiData } from "../Messages/JsonMessages/AdminApiData"; import { AdminApiData, isAdminApiData } from "../Messages/JsonMessages/AdminApiData";
import * as tg from "generic-type-guard"; import * as tg from "generic-type-guard";
import { isNumber } from "generic-type-guard"; import { isNumber } from "generic-type-guard";
import { isWokaDetail } from "../Enum/PlayerTextures"; import { isWokaDetail } from "../Messages/JsonMessages/PlayerTextures";
import qs from "qs"; import qs from "qs";
export interface AdminBannedData { export interface AdminBannedData {
@ -46,10 +46,16 @@ class AdminApi {
userId, userId,
}; };
const res = await Axios.get(ADMIN_API_URL + "/api/map", { const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/map", {
headers: { Authorization: `${ADMIN_API_TOKEN}` }, headers: { Authorization: `${ADMIN_API_TOKEN}` },
params, params,
}); });
if (!isMapDetailsData(res.data) && !isRoomRedirect(res.data)) {
throw new Error(
"Invalid answer received from the admin for the /api/map endpoint. Received: " +
JSON.stringify(res.data)
);
}
return res.data; return res.data;
} }

View File

@ -1,6 +1,6 @@
import axios, { AxiosResponse } from "axios"; import axios, { AxiosResponse } from "axios";
import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable"; import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable";
import { wokaList, WokaList } from "../Enum/PlayerTextures"; import { wokaList, WokaList } from "../Messages/JsonMessages/PlayerTextures";
import { WokaServiceInterface } from "./WokaServiceInterface"; import { WokaServiceInterface } from "./WokaServiceInterface";
class AdminWokaService implements WokaServiceInterface { class AdminWokaService implements WokaServiceInterface {

View File

@ -1,4 +1,4 @@
import { WokaDetail, WokaDetailsResult, WokaList, wokaPartNames } from "../Enum/PlayerTextures"; import { WokaDetail, WokaDetailsResult, WokaList, wokaPartNames } from "../Messages/JsonMessages/PlayerTextures";
import { WokaServiceInterface } from "./WokaServiceInterface"; import { WokaServiceInterface } from "./WokaServiceInterface";
class LocalWokaService implements WokaServiceInterface { class LocalWokaService implements WokaServiceInterface {

View File

@ -1,4 +1,4 @@
import { WokaDetailsResult, WokaList } from "../Enum/PlayerTextures"; import { WokaList } from "../Messages/JsonMessages/PlayerTextures";
export interface WokaServiceInterface { export interface WokaServiceInterface {
/** /**

617
tests/package-lock.json generated
View File

@ -5,7 +5,7 @@
"packages": { "packages": {
"": { "": {
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.19.1", "@playwright/test": "^1.20.0",
"@types/dockerode": "^3.3.0", "@types/dockerode": "^3.3.0",
"axios": "^0.24.0", "axios": "^0.24.0",
"dockerode": "^3.3.1", "dockerode": "^3.3.1",
@ -565,21 +565,6 @@
"@babel/core": "^7.0.0-0" "@babel/core": "^7.0.0-0"
} }
}, },
"node_modules/@babel/plugin-syntax-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
"integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.16.7"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-syntax-logical-assignment-operators": { "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4", "version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
@ -700,25 +685,6 @@
"@babel/core": "^7.0.0-0" "@babel/core": "^7.0.0-0"
} }
}, },
"node_modules/@babel/plugin-transform-react-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz",
"integrity": "sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-module-imports": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-jsx": "^7.16.7",
"@babel/types": "^7.16.7"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-typescript": { "node_modules/@babel/plugin-transform-typescript": {
"version": "7.16.8", "version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz",
@ -888,13 +854,14 @@
} }
}, },
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.19.1", "version": "1.20.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.19.1.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.20.0.tgz",
"integrity": "sha512-NGWqJWP4N2HFyXlOSDwQSfgmige94p9KQvml62fJ5wg4sknfkyw+CnFeLUze8qvnGlS0PbVISMRV5JOE8EdxjQ==", "integrity": "sha512-UpI5HTcgNLckR0kqXqwNvbcIXtRaDxk+hnO0OBwPSjfbBjRfRgAJ2ClA/b30C5E3UW5dJa17zhsy2qrk66l5cg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "7.16.7", "@babel/code-frame": "7.16.7",
"@babel/core": "7.16.12", "@babel/core": "7.16.12",
"@babel/helper-plugin-utils": "7.16.7",
"@babel/plugin-proposal-class-properties": "7.16.7", "@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-proposal-dynamic-import": "7.16.7", "@babel/plugin-proposal-dynamic-import": "7.16.7",
"@babel/plugin-proposal-export-namespace-from": "7.16.7", "@babel/plugin-proposal-export-namespace-from": "7.16.7",
@ -909,24 +876,19 @@
"@babel/plugin-syntax-object-rest-spread": "7.8.3", "@babel/plugin-syntax-object-rest-spread": "7.8.3",
"@babel/plugin-syntax-optional-catch-binding": "7.8.3", "@babel/plugin-syntax-optional-catch-binding": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.16.8", "@babel/plugin-transform-modules-commonjs": "7.16.8",
"@babel/plugin-transform-react-jsx": "7.16.7",
"@babel/preset-typescript": "7.16.7", "@babel/preset-typescript": "7.16.7",
"babel-plugin-module-resolver": "4.1.0",
"colors": "1.4.0", "colors": "1.4.0",
"commander": "8.3.0", "commander": "8.3.0",
"debug": "4.3.3", "debug": "4.3.3",
"expect": "27.2.5", "expect": "27.2.5",
"jest-matcher-utils": "27.2.5", "jest-matcher-utils": "27.2.5",
"jpeg-js": "0.4.3",
"json5": "2.2.0", "json5": "2.2.0",
"mime": "3.0.0", "mime": "3.0.0",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"ms": "2.1.3", "ms": "2.1.3",
"open": "8.4.0", "open": "8.4.0",
"pirates": "4.0.4", "pirates": "4.0.4",
"pixelmatch": "5.2.1", "playwright-core": "1.20.0",
"playwright-core": "1.19.1",
"pngjs": "6.0.0",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"source-map-support": "0.4.18", "source-map-support": "0.4.18",
"stack-utils": "2.0.5", "stack-utils": "2.0.5",
@ -939,48 +901,12 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@playwright/test/node_modules/mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/@playwright/test/node_modules/ms": { "node_modules/@playwright/test/node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true "dev": true
}, },
"node_modules/@playwright/test/node_modules/pngjs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
"integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
"dev": true,
"engines": {
"node": ">=12.13.0"
}
},
"node_modules/@playwright/test/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@playwright/test/node_modules/source-map-support": { "node_modules/@playwright/test/node_modules/source-map-support": {
"version": "0.4.18", "version": "0.4.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
@ -1141,22 +1067,6 @@
"object.assign": "^4.1.0" "object.assign": "^4.1.0"
} }
}, },
"node_modules/babel-plugin-module-resolver": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz",
"integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==",
"dev": true,
"dependencies": {
"find-babel-config": "^1.2.0",
"glob": "^7.1.6",
"pkg-up": "^3.1.0",
"reselect": "^4.0.0",
"resolve": "^1.13.1"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1617,40 +1527,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/find-babel-config": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz",
"integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==",
"dev": true,
"dependencies": {
"json5": "^0.5.1",
"path-exists": "^3.0.0"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/find-babel-config/node_modules/json5": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true,
"bin": {
"json5": "lib/cli.js"
}
},
"node_modules/find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"dependencies": {
"locate-path": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.14.8", "version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
@ -1850,18 +1726,6 @@
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true "dev": true
}, },
"node_modules/is-core-module": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-docker": { "node_modules/is-docker": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
@ -2221,19 +2085,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"dependencies": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.4", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@ -2247,6 +2098,18 @@
"node": ">=8.6" "node": ">=8.6"
} }
}, },
"node_modules/mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@ -2343,51 +2206,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"dependencies": {
"p-limit": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/path-is-absolute": { "node_modules/path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -2406,12 +2224,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/pend": { "node_modules/pend": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@ -2466,30 +2278,20 @@
"node": ">=8.0.0" "node": ">=8.0.0"
} }
}, },
"node_modules/pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"dev": true,
"dependencies": {
"find-up": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.19.1", "version": "1.20.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.19.1.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.20.0.tgz",
"integrity": "sha512-+ByjhWX39PlINVRXr4ef9Kle85mk5QzA2WLioCoMQc3bSUtZpLV1mbeUDtRp/bvFw6YDIEyptj4QvzzRTXN3vg==", "integrity": "sha512-d25IRcdooS278Cijlp8J8A5fLQZ+/aY3dKRJvgX5yjXA69N0huIUdnh3xXSgn+LsQ9DCNmB7Ngof3eY630jgdA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"colors": "1.4.0",
"commander": "8.3.0", "commander": "8.3.0",
"debug": "4.3.3", "debug": "4.3.3",
"extract-zip": "2.0.1", "extract-zip": "2.0.1",
"https-proxy-agent": "5.0.0", "https-proxy-agent": "5.0.0",
"jpeg-js": "0.4.3", "jpeg-js": "0.4.3",
"mime": "3.0.0", "mime": "3.0.0",
"pixelmatch": "5.2.1",
"pngjs": "6.0.0", "pngjs": "6.0.0",
"progress": "2.0.3", "progress": "2.0.3",
"proper-lockfile": "4.1.2", "proper-lockfile": "4.1.2",
@ -2508,19 +2310,7 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/playwright-core/node_modules/mime": { "node_modules/pngjs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/playwright-core/node_modules/pngjs": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
"integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
@ -2529,42 +2319,6 @@
"node": ">=12.13.0" "node": ">=12.13.0"
} }
}, },
"node_modules/playwright-core/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/playwright-core/node_modules/ws": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
"dev": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/pretty-format": { "node_modules/pretty-format": {
"version": "27.5.1", "version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
@ -2656,29 +2410,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/reselect": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==",
"dev": true
},
"node_modules/resolve": {
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
"integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
"dev": true,
"dependencies": {
"is-core-module": "^2.8.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/retry": { "node_modules/retry": {
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
@ -2688,6 +2419,21 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/safe-buffer": { "node_modules/safe-buffer": {
"version": "5.2.1", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@ -2736,9 +2482,9 @@
} }
}, },
"node_modules/signal-exit": { "node_modules/signal-exit": {
"version": "3.0.6", "version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true "dev": true
}, },
"node_modules/slash": { "node_modules/slash": {
@ -2863,18 +2609,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/tar-fs": { "node_modules/tar-fs": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
@ -2957,6 +2691,27 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true "dev": true
}, },
"node_modules/ws": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
"dev": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yauzl": { "node_modules/yauzl": {
"version": "2.10.0", "version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
@ -3375,15 +3130,6 @@
"@babel/helper-plugin-utils": "^7.8.0" "@babel/helper-plugin-utils": "^7.8.0"
} }
}, },
"@babel/plugin-syntax-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
"integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-syntax-logical-assignment-operators": { "@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4", "version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
@ -3468,19 +3214,6 @@
"babel-plugin-dynamic-import-node": "^2.3.3" "babel-plugin-dynamic-import-node": "^2.3.3"
} }
}, },
"@babel/plugin-transform-react-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz",
"integrity": "sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-module-imports": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-jsx": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/plugin-transform-typescript": { "@babel/plugin-transform-typescript": {
"version": "7.16.8", "version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz",
@ -3607,13 +3340,14 @@
} }
}, },
"@playwright/test": { "@playwright/test": {
"version": "1.19.1", "version": "1.20.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.19.1.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.20.0.tgz",
"integrity": "sha512-NGWqJWP4N2HFyXlOSDwQSfgmige94p9KQvml62fJ5wg4sknfkyw+CnFeLUze8qvnGlS0PbVISMRV5JOE8EdxjQ==", "integrity": "sha512-UpI5HTcgNLckR0kqXqwNvbcIXtRaDxk+hnO0OBwPSjfbBjRfRgAJ2ClA/b30C5E3UW5dJa17zhsy2qrk66l5cg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "7.16.7", "@babel/code-frame": "7.16.7",
"@babel/core": "7.16.12", "@babel/core": "7.16.12",
"@babel/helper-plugin-utils": "7.16.7",
"@babel/plugin-proposal-class-properties": "7.16.7", "@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-proposal-dynamic-import": "7.16.7", "@babel/plugin-proposal-dynamic-import": "7.16.7",
"@babel/plugin-proposal-export-namespace-from": "7.16.7", "@babel/plugin-proposal-export-namespace-from": "7.16.7",
@ -3628,57 +3362,31 @@
"@babel/plugin-syntax-object-rest-spread": "7.8.3", "@babel/plugin-syntax-object-rest-spread": "7.8.3",
"@babel/plugin-syntax-optional-catch-binding": "7.8.3", "@babel/plugin-syntax-optional-catch-binding": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.16.8", "@babel/plugin-transform-modules-commonjs": "7.16.8",
"@babel/plugin-transform-react-jsx": "7.16.7",
"@babel/preset-typescript": "7.16.7", "@babel/preset-typescript": "7.16.7",
"babel-plugin-module-resolver": "4.1.0",
"colors": "1.4.0", "colors": "1.4.0",
"commander": "8.3.0", "commander": "8.3.0",
"debug": "4.3.3", "debug": "4.3.3",
"expect": "27.2.5", "expect": "27.2.5",
"jest-matcher-utils": "27.2.5", "jest-matcher-utils": "27.2.5",
"jpeg-js": "0.4.3",
"json5": "2.2.0", "json5": "2.2.0",
"mime": "3.0.0", "mime": "3.0.0",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"ms": "2.1.3", "ms": "2.1.3",
"open": "8.4.0", "open": "8.4.0",
"pirates": "4.0.4", "pirates": "4.0.4",
"pixelmatch": "5.2.1", "playwright-core": "1.20.0",
"playwright-core": "1.19.1",
"pngjs": "6.0.0",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"source-map-support": "0.4.18", "source-map-support": "0.4.18",
"stack-utils": "2.0.5", "stack-utils": "2.0.5",
"yazl": "2.5.1" "yazl": "2.5.1"
}, },
"dependencies": { "dependencies": {
"mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true
},
"ms": { "ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true "dev": true
}, },
"pngjs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
"integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
"dev": true
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"source-map-support": { "source-map-support": {
"version": "0.4.18", "version": "0.4.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
@ -3835,19 +3543,6 @@
"object.assign": "^4.1.0" "object.assign": "^4.1.0"
} }
}, },
"babel-plugin-module-resolver": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz",
"integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==",
"dev": true,
"requires": {
"find-babel-config": "^1.2.0",
"glob": "^7.1.6",
"pkg-up": "^3.1.0",
"reselect": "^4.0.0",
"resolve": "^1.13.1"
}
},
"balanced-match": { "balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -4187,33 +3882,6 @@
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
} }
}, },
"find-babel-config": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz",
"integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==",
"dev": true,
"requires": {
"json5": "^0.5.1",
"path-exists": "^3.0.0"
},
"dependencies": {
"json5": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
}
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"follow-redirects": { "follow-redirects": {
"version": "1.14.8", "version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
@ -4349,15 +4017,6 @@
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true "dev": true
}, },
"is-core-module": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"requires": {
"has": "^1.0.3"
}
},
"is-docker": { "is-docker": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
@ -4618,16 +4277,6 @@
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
}, },
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"micromatch": { "micromatch": {
"version": "4.0.4", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
@ -4638,6 +4287,12 @@
"picomatch": "^2.2.3" "picomatch": "^2.2.3"
} }
}, },
"mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true
},
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@ -4716,36 +4371,6 @@
"is-wsl": "^2.2.0" "is-wsl": "^2.2.0"
} }
}, },
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -4758,12 +4383,6 @@
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true "dev": true
}, },
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"pend": { "pend": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@ -4805,27 +4424,20 @@
} }
} }
}, },
"pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"dev": true,
"requires": {
"find-up": "^3.0.0"
}
},
"playwright-core": { "playwright-core": {
"version": "1.19.1", "version": "1.20.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.19.1.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.20.0.tgz",
"integrity": "sha512-+ByjhWX39PlINVRXr4ef9Kle85mk5QzA2WLioCoMQc3bSUtZpLV1mbeUDtRp/bvFw6YDIEyptj4QvzzRTXN3vg==", "integrity": "sha512-d25IRcdooS278Cijlp8J8A5fLQZ+/aY3dKRJvgX5yjXA69N0huIUdnh3xXSgn+LsQ9DCNmB7Ngof3eY630jgdA==",
"dev": true, "dev": true,
"requires": { "requires": {
"colors": "1.4.0",
"commander": "8.3.0", "commander": "8.3.0",
"debug": "4.3.3", "debug": "4.3.3",
"extract-zip": "2.0.1", "extract-zip": "2.0.1",
"https-proxy-agent": "5.0.0", "https-proxy-agent": "5.0.0",
"jpeg-js": "0.4.3", "jpeg-js": "0.4.3",
"mime": "3.0.0", "mime": "3.0.0",
"pixelmatch": "5.2.1",
"pngjs": "6.0.0", "pngjs": "6.0.0",
"progress": "2.0.3", "progress": "2.0.3",
"proper-lockfile": "4.1.2", "proper-lockfile": "4.1.2",
@ -4836,13 +4448,7 @@
"ws": "8.4.2", "ws": "8.4.2",
"yauzl": "2.10.0", "yauzl": "2.10.0",
"yazl": "2.5.1" "yazl": "2.5.1"
}, }
"dependencies": {
"mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true
}, },
"pngjs": { "pngjs": {
"version": "6.0.0", "version": "6.0.0",
@ -4850,24 +4456,6 @@
"integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
"dev": true "dev": true
}, },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"ws": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
"dev": true,
"requires": {}
}
}
},
"pretty-format": { "pretty-format": {
"version": "27.5.1", "version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
@ -4943,29 +4531,21 @@
"util-deprecate": "^1.0.1" "util-deprecate": "^1.0.1"
} }
}, },
"reselect": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==",
"dev": true
},
"resolve": {
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
"integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
"dev": true,
"requires": {
"is-core-module": "^2.8.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
},
"retry": { "retry": {
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
"dev": true "dev": true
}, },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": { "safe-buffer": {
"version": "5.2.1", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@ -4994,9 +4574,9 @@
"dev": true "dev": true
}, },
"signal-exit": { "signal-exit": {
"version": "3.0.6", "version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true "dev": true
}, },
"slash": { "slash": {
@ -5091,12 +4671,6 @@
"has-flag": "^3.0.0" "has-flag": "^3.0.0"
} }
}, },
"supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true
},
"tar-fs": { "tar-fs": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
@ -5164,6 +4738,13 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true "dev": true
}, },
"ws": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
"dev": true,
"requires": {}
},
"yauzl": { "yauzl": {
"version": "2.10.0", "version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",

View File

@ -1,6 +1,6 @@
{ {
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.19.1", "@playwright/test": "^1.20.0",
"@types/dockerode": "^3.3.0", "@types/dockerode": "^3.3.0",
"axios": "^0.24.0", "axios": "^0.24.0",
"dockerode": "^3.3.1", "dockerode": "^3.3.1",