From 15f12ed45e394e74921cfb91d793388c70e98d87 Mon Sep 17 00:00:00 2001 From: magnetenstad Date: Tue, 30 Jan 2024 04:47:29 +0100 Subject: [PATCH] Broadcast game --- package-lock.json | 389 +++++++++++--------------------- package.json | 4 +- src/stores/game.ts | 2 + src/stores/online.ts | 67 ++++-- src/views/GameView.vue | 19 +- src/views/SpectateLobbyView.vue | 12 +- src/views/SpectateView.vue | 8 +- 7 files changed, 216 insertions(+), 285 deletions(-) diff --git a/package-lock.json b/package-lock.json index 568d275..768f084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "dependencies": { "@formkit/auto-animate": "^0.8.0", - "@supabase/supabase-js": "^2.36.0", + "@supabase/supabase-js": "^2.39.3", "@types/node": "^20.7.1", "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", @@ -17,7 +17,7 @@ "mobile-drag-drop": "^3.0.0-rc.0", "nanoid": "^5.0.1", "pinia": "^2.1.6", - "vue": "^3.3.4", + "vue": "^3.4.15", "vue-router": "^4.2.5" }, "devDependencies": { @@ -30,9 +30,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -445,17 +445,17 @@ } }, "node_modules/@supabase/gotrue-js": { - "version": "2.54.0", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.54.0.tgz", - "integrity": "sha512-JjtbchtPbpgK0O8NIMIvKLk7HHv0kd23L3UO5a398nczCcBkI0IvmbPtbS4Xs5AUIuJ+JHtV6siOZR1ha5EzQw==", + "version": "2.62.2", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.62.2.tgz", + "integrity": "sha512-AP6e6W9rQXFTEJ7sTTNYQrNf0LCcnt1hUW+RIgUK+Uh3jbWvcIST7wAlYyNZiMlS9+PYyymWQ+Ykz/rOYSO0+A==", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/node-fetch": { - "version": "2.6.14", - "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.14.tgz", - "integrity": "sha512-w/Tsd22e/5fAeoxqQ4P2MX6EyF+iM6rc9kmlMVFkHuG0rAltt2TLhFbDJfemnHbtvnazWaRfy5KnFU/SYT37dQ==", + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -464,41 +464,42 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.8.4.tgz", - "integrity": "sha512-ELjpvhb04wILUiJz9zIsTSwaz9LQNlX+Ig5/LgXQ7k68qQI6NqHVn+ISRNt53DngUIyOnLHjeqqIRHBZ7zpgGA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.9.2.tgz", + "integrity": "sha512-I6yHo8CC9cxhOo6DouDMy9uOfW7hjdsnCxZiaJuIVZm1dBGTFiQPgfMa9zXCamEWzNyWRjZvupAUuX+tqcl5Sw==", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/realtime-js": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.7.4.tgz", - "integrity": "sha512-FzSzs1k9ruh/uds5AJ95Nc3beiMCCIhougExJ3O98CX1LMLAKUKFy5FivKLvcNhXnNfUEL0XUfGMb4UH2J7alg==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.9.3.tgz", + "integrity": "sha512-lAp50s2n3FhGJFq+wTSXLNIDPw5Y0Wxrgt44eM5nLSA3jZNUUP3Oq2Ccd1CbZdVntPCWLZvJaU//pAd2NE+QnQ==", "dependencies": { + "@supabase/node-fetch": "^2.6.14", "@types/phoenix": "^1.5.4", - "@types/websocket": "^1.0.3", - "websocket": "^1.0.34" + "@types/ws": "^8.5.10", + "ws": "^8.14.2" } }, "node_modules/@supabase/storage-js": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.4.tgz", - "integrity": "sha512-yspHD19I9uQUgfTh0J94+/r/g6hnhdQmw6Y7OWqr/EbnL6uvicGV1i1UDkkmeUHqfF9Mbt2sLtuxRycYyKv2ew==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.5.tgz", + "integrity": "sha512-OpLoDRjFwClwc2cjTJZG8XviTiQH4Ik8sCiMK5v7et0MDu2QlXjCAW3ljxJB5+z/KazdMOTnySi+hysxWUPu3w==", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/supabase-js": { - "version": "2.36.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.36.0.tgz", - "integrity": "sha512-K9ze4BpQrOZsmYUvF2j9FfIkTfxR4K8GJx6F6DTOfJ8fZg4JSNjfzlGvhCVDwiV4w1NRrmEQ/F89THNt3eXXhg==", + "version": "2.39.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.39.3.tgz", + "integrity": "sha512-NoltJSaJNKDJNutO5sJPAAi5RIWrn1z2XH+ig1+cHDojT6BTN7TvZPNa3Kq3gFQWfO5H1N9El/bCTZJ3iFW2kQ==", "dependencies": { "@supabase/functions-js": "^2.1.5", - "@supabase/gotrue-js": "^2.54.0", + "@supabase/gotrue-js": "^2.60.0", "@supabase/node-fetch": "^2.6.14", - "@supabase/postgrest-js": "^1.8.4", - "@supabase/realtime-js": "^2.7.4", + "@supabase/postgrest-js": "^1.9.0", + "@supabase/realtime-js": "^2.9.3", "@supabase/storage-js": "^2.5.4" } }, @@ -529,14 +530,14 @@ "integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==" }, "node_modules/@types/phoenix": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.2.tgz", - "integrity": "sha512-I3mm7x5XIi+5NsIY3nfreY+H4PmQdyBwJ84SiUSOxSg1axwEPNmkKWYVm56y+emDpPPUL3cPzrLcgRWSd9gI7g==" + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.4.tgz", + "integrity": "sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==" }, - "node_modules/@types/websocket": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.7.tgz", - "integrity": "sha512-62Omr8U0PO+hgjLCpPnMsmjh2/FRwIGOktZHyYAUzooEJotwkXHMp7vCacdYi8haxBNOiw9bc2HIHI+b/MPNjA==", + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { "@types/node": "*" } @@ -650,49 +651,49 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", - "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz", + "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==", "dependencies": { - "@babel/parser": "^7.21.3", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.6", + "@vue/shared": "3.4.15", + "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", - "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz", + "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==", "dependencies": { - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-core": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", - "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", - "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/compiler-dom": "3.3.4", - "@vue/compiler-ssr": "3.3.4", - "@vue/reactivity-transform": "3.3.4", - "@vue/shared": "3.3.4", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz", + "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==", + "dependencies": { + "@babel/parser": "^7.23.6", + "@vue/compiler-core": "3.4.15", + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15", "estree-walker": "^2.0.2", - "magic-string": "^0.30.0", - "postcss": "^8.1.10", + "magic-string": "^0.30.5", + "postcss": "^8.4.33", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", - "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz", + "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==", "dependencies": { - "@vue/compiler-dom": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-dom": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/devtools-api": { @@ -725,60 +726,48 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", - "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz", + "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==", "dependencies": { - "@vue/shared": "3.3.4" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", - "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", - "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.0" + "@vue/shared": "3.4.15" } }, "node_modules/@vue/runtime-core": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", - "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz", + "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==", "dependencies": { - "@vue/reactivity": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/reactivity": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/runtime-dom": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", - "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz", + "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==", "dependencies": { - "@vue/runtime-core": "3.3.4", - "@vue/shared": "3.3.4", - "csstype": "^3.1.1" + "@vue/runtime-core": "3.4.15", + "@vue/shared": "3.4.15", + "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", - "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz", + "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==", "dependencies": { - "@vue/compiler-ssr": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15" }, "peerDependencies": { - "vue": "3.3.4" + "vue": "3.4.15" } }, "node_modules/@vue/shared": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", - "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz", + "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==" }, "node_modules/@vue/typescript": { "version": "1.8.15", @@ -918,18 +907,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/bufferutil": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", - "integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -1008,18 +985,9 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", @@ -1051,14 +1019,6 @@ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -1094,37 +1054,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/esbuild": { @@ -1221,19 +1159,6 @@ "node": ">=0.10.0" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - }, "node_modules/fetch-blob": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", @@ -1479,11 +1404,6 @@ "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", "dev": true }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -1533,9 +1453,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -1621,11 +1541,6 @@ "resolved": "https://registry.npmjs.org/mobile-drag-drop/-/mobile-drag-drop-3.0.0-rc.0.tgz", "integrity": "sha512-f8wIDTbBYLBW/+5sei1cqUE+StyDpf/LP+FRZELlVX6tmOOmELk84r3wh1z3woxCB9G5octhF06K5COvFjGgqg==" }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/muggle-string": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", @@ -1658,11 +1573,6 @@ "node": ">= 0.4.0" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -1700,16 +1610,6 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/npm-normalize-package-bin": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", @@ -2235,11 +2135,6 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -2249,14 +2144,6 @@ "node": ">=4" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -2285,18 +2172,6 @@ "node": ">= 4.0.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/vite": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", @@ -2499,15 +2374,23 @@ "dev": true }, "node_modules/vue": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", - "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz", + "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==", "dependencies": { - "@vue/compiler-dom": "3.3.4", - "@vue/compiler-sfc": "3.3.4", - "@vue/runtime-dom": "3.3.4", - "@vue/server-renderer": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-sfc": "3.4.15", + "@vue/runtime-dom": "3.4.15", + "@vue/server-renderer": "3.4.15", + "@vue/shared": "3.4.15" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/vue-router": { @@ -2565,22 +2448,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "node_modules/websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -2619,12 +2486,24 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=0.10.32" + "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/yallist": { diff --git a/package.json b/package.json index e962938..86679c4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@formkit/auto-animate": "^0.8.0", - "@supabase/supabase-js": "^2.36.0", + "@supabase/supabase-js": "^2.39.3", "@types/node": "^20.7.1", "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", @@ -20,7 +20,7 @@ "mobile-drag-drop": "^3.0.0-rc.0", "nanoid": "^5.0.1", "pinia": "^2.1.6", - "vue": "^3.3.4", + "vue": "^3.4.15", "vue-router": "^4.2.5" }, "devDependencies": { diff --git a/src/stores/game.ts b/src/stores/game.ts index b14fc18..86968f2 100644 --- a/src/stores/game.ts +++ b/src/stores/game.ts @@ -12,6 +12,7 @@ import { } from '@/types/game' import { acceptHMRUpdate, defineStore } from 'pinia' import { useEloStore } from './elo' +import { useOnlineStore } from './online' import { upsertLegStatistics, useStatsStore } from './stats' import { useUsersStore } from './users' @@ -49,6 +50,7 @@ export const useGameStore = defineStore('game', { this.gameState = this.getController().getGameState() if (this.game) { this.game.result = this.gameState.rank + useOnlineStore().sendGame(this.game) } this.tryPlayWalkOn() return this.gameState diff --git a/src/stores/online.ts b/src/stores/online.ts index a1c1165..035850e 100644 --- a/src/stores/online.ts +++ b/src/stores/online.ts @@ -1,4 +1,6 @@ import { supabase } from '@/supabase' +import { Game } from '@/types/game' +import { RealtimeChannel } from '@supabase/supabase-js' import { acceptHMRUpdate, defineStore } from 'pinia' type OnlinePresence = { @@ -8,38 +10,69 @@ type OnlinePresence = { } export const useOnlineStore = defineStore('online', { - state: () => { - const room = supabase.channel('online') - - return { - room, - presences: [] as OnlinePresence[], - spectating: null as string | null, - presence: {} as Partial, - } - }, + state: () => ({ + presences: [] as OnlinePresence[], + spectating: null as string | null, + spectatingGame: null as Game | null, + presence: { + inGame: false, + date: new Date(), + } as Partial, + room: null as RealtimeChannel | null, + inChannel: null as RealtimeChannel | null, + outChannel: null as RealtimeChannel | null, + }), actions: { - initRoom(userId: string) { + async initRoom(userId: string) { + await supabase.removeAllChannels() + + this.room = supabase.channel('online') this.room .on('presence', { event: 'sync' }, () => { - const state = this.room.presenceState() + const state = this.room?.presenceState() // @ts-ignore this.presences = Object.values(state).flat() }) .subscribe(async (status) => { - if (status !== 'SUBSCRIBED') { - return - } - + if (status !== 'SUBSCRIBED') return this.sendUpdate({ userId }) }) + + this.outChannel = supabase.channel(`game-${userId}`).subscribe() }, async sendUpdate(presence: Partial) { this.presence = { ...this.presence, ...presence } if (!this.presence.userId) return - await this.room.track(this.presence) + await this.room?.track(presence) + }, + + async startSpectating(userId: string) { + this.spectating = userId + await this.inChannel?.unsubscribe() + this.inChannel = supabase + .channel(`game-${this.spectating}`) + .on('broadcast', { event: 'game' }, (game) => { + // @ts-ignore + this.spectatingGame = game as Game + }) + .subscribe() + }, + + async stopSpectating() { + await this.inChannel?.unsubscribe() + this.inChannel = null + this.spectating = null + this.spectatingGame = null + }, + + sendGame(game: Game) { + this.outChannel?.send({ + type: 'broadcast', + event: 'game', + payload: game, + }) }, }, diff --git a/src/views/GameView.vue b/src/views/GameView.vue index 20ccf77..90cf869 100644 --- a/src/views/GameView.vue +++ b/src/views/GameView.vue @@ -105,6 +105,7 @@ import Youtube from '@/components/Youtube.vue' import { speak } from '@/functions/speak' import { getGameDisplayName, getInputComponent } from '@/games/games' import { router } from '@/router' +import { useAuthStore } from '@/stores/auth' import { useEloStore } from '@/stores/elo' import { useGameStore } from '@/stores/game' import { useLoadingStore } from '@/stores/loading' @@ -120,6 +121,7 @@ const gameStore = useGameStore() const usersStore = useUsersStore() const loadingStore = useLoadingStore() const onlineStore = useOnlineStore() +const authStore = useAuthStore() const eloDeltas = ref<{ userId: string; eloDelta: number }[]>([]) @@ -149,14 +151,23 @@ const displayVisit = computed(() => { return { visit: visit ?? [null, null, null], isPrev: false } }) -onMounted(() => { +onMounted(async () => { if (!gameStore.game) { quit() } - onlineStore.sendUpdate({ inGame: true }) + await onlineStore.sendUpdate({ + inGame: true, + userId: authStore.auth?.id, + date: new Date(), + }) }) -onUnmounted(() => { - onlineStore.sendUpdate({ inGame: false }) + +onUnmounted(async () => { + await onlineStore.sendUpdate({ + inGame: false, + userId: authStore.auth?.id, + date: new Date(), + }) }) const quit = () => { diff --git a/src/views/SpectateLobbyView.vue b/src/views/SpectateLobbyView.vue index 96a182d..476a264 100644 --- a/src/views/SpectateLobbyView.vue +++ b/src/views/SpectateLobbyView.vue @@ -5,12 +5,7 @@ @@ -23,4 +18,9 @@ import { useOnlineStore } from '@/stores/online' import { useUsersStore } from '@/stores/users' const onlineStore = useOnlineStore() + +const spectate = async (userId: string) => { + await onlineStore.startSpectating(userId) + router.push({ name: 'spectate' }) +} diff --git a/src/views/SpectateView.vue b/src/views/SpectateView.vue index 76233f0..b27c6bc 100644 --- a/src/views/SpectateView.vue +++ b/src/views/SpectateView.vue @@ -8,6 +8,8 @@

{{ name }} is in game.

{{ name }} is not in game.

+ + {{ onlineStore.spectatingGame }} @@ -15,7 +17,7 @@ import { router } from '@/router' import { useOnlineStore } from '@/stores/online' import { useUsersStore } from '@/stores/users' -import { computed, watch } from 'vue' +import { computed, onUnmounted, watch } from 'vue' const onlineStore = useOnlineStore() @@ -32,4 +34,8 @@ watch( }, { immediate: true } ) + +onUnmounted(() => { + onlineStore.stopSpectating() +})