diff --git a/README.md b/README.md index b37bd21..cbd8b5b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ Oxford debate (pl. _[debata oksfordzka](https://pl.wikipedia.org/wiki/Debata_oks - Debate clock adjustable to rules of any tournament, - Generator of motions used in past tournaments with filtering by type and language, - Usable logos of tournaments that used Debate Tools, -- Submitting custom logos. +- Submitting custom logos, +- Sharing debate configurations via links. ## Origin @@ -34,7 +35,7 @@ Debate Tools were first used and tested in ZSK Poznań, during the 2023/2024 edi ## License -Copyright © 2023-2024 Jakub Mańczak & Mateusz Dobrzyński +Copyright © 2023-2025 Jakub Mańczak & Mateusz Dobrzyński Unless stated otherwise in `LEGAL.md` regarding specific files, Debate Tools are distributed under [AGPL-3.0-only](LICENSE). diff --git a/package-lock.json b/package-lock.json index 7a05ae4..2d3cc28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@jest/globals": "^29.7.0", "@types/jest": "^29.5.12", "flag-icons": "^7.2.2", + "fs": "^0.0.1-security", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "24.1.0", @@ -24,7 +25,7 @@ "use-sound": "^4.0.1" }, "devDependencies": { - "@playwright/test": "^1.45.1", + "@playwright/test": "^1.51.0", "@testing-library/dom": "^10.1.0", "@testing-library/react": "^16.0.0", "@types/node": "^20", @@ -1328,9 +1329,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", - "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.24.tgz", + "integrity": "sha512-LAm0Is2KHTNT6IT16lxT+suD0u+VVfYNQqM+EJTKuFRRuY2z+zj01kueWXPCxbMBDt0B5vONYzabHGUNbZYAhA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1343,12 +1344,13 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz", - "integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.24.tgz", + "integrity": "sha512-7Tdi13aojnAZGpapVU6meVSpNzgrFwZ8joDcNS8cJVNuP3zqqrLqeory9Xec5TJZR/stsGJdfwo8KeyloT3+rQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1358,12 +1360,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", - "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.24.tgz", + "integrity": "sha512-lXR2WQqUtu69l5JMdTwSvQUkdqAhEWOqJEYUQ21QczQsAlNOW2kWZCucA6b3EXmPbcvmHB1kSZDua/713d52xg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1373,12 +1376,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", - "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.24.tgz", + "integrity": "sha512-nxvJgWOpSNmzidYvvGDfXwxkijb6hL9+cjZx1PVG6urr2h2jUqBALkKjT7kpfurRWicK6hFOvarmaWsINT1hnA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -1388,12 +1392,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", - "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.24.tgz", + "integrity": "sha512-PaBgOPhqa4Abxa3y/P92F3kklNPsiFjcjldQGT7kFmiY5nuFn8ClBEoX8GIpqU1ODP2y8P6hio6vTomx2Vy0UQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -1403,9 +1408,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", - "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.24.tgz", + "integrity": "sha512-vEbyadiRI7GOr94hd2AB15LFVgcJZQWu7Cdi9cWjCMeCiUsHWA0U5BkGPuoYRnTxTn0HacuMb9NeAmStfBCLoQ==", "cpu": [ "x64" ], @@ -1419,12 +1424,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", - "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.24.tgz", + "integrity": "sha512-df0FC9ptaYsd8nQCINCzFtDWtko8PNRTAU0/+d7hy47E0oC17tI54U/0NdGk7l/76jz1J377dvRjmt6IUdkpzQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -1434,12 +1440,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", - "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.24.tgz", + "integrity": "sha512-ZEntbLjeYAJ286eAqbxpZHhDFYpYjArotQ+/TW9j7UROh0DUmX7wYDGtsTPpfCV8V+UoqHBPU7q9D4nDNH014Q==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1449,12 +1456,13 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", - "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.24.tgz", + "integrity": "sha512-9KuS+XUXM3T6v7leeWU0erpJ6NsFIwiTFD5nzNg8J5uo/DMIPvCp3L1Ao5HjbHX0gkWPB1VrKoo/Il4F0cGK2Q==", "cpu": [ "ia32" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1464,12 +1472,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", - "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.24.tgz", + "integrity": "sha512-cXcJ2+x0fXQ2CntaE00d7uUH+u1Bfp/E0HsNQH79YiLaZE5Rbm7dZzyAYccn3uICM7mw+DxoMqEfGXZtF4Fgaw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1524,13 +1533,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz", - "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.0.tgz", + "integrity": "sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.45.1" + "playwright": "1.51.0" }, "bin": { "playwright": "cli.js" @@ -2655,9 +2664,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001579", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", - "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "version": "1.0.30001703", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz", + "integrity": "sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==", "funding": [ { "type": "opencollective", @@ -2671,7 +2680,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", @@ -2913,9 +2923,10 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3934,9 +3945,10 @@ "dev": true }, "node_modules/fast-loops": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz", - "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==", + "license": "MIT" }, "node_modules/fast-shallow-equal": { "version": "1.0.0", @@ -4083,11 +4095,31 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -6483,11 +6515,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -6589,15 +6622,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6611,12 +6645,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/next": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz", - "integrity": "sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==", + "version": "14.2.24", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.24.tgz", + "integrity": "sha512-En8VEexSJ0Py2FfVnRRh8gtERwDRaJGNvsvad47ShkC2Yi8AXQPXEA2vKoDJlGFSj5WE5SyF21zNi4M5gyi+SQ==", "license": "MIT", "dependencies": { - "@next/env": "14.2.4", + "@next/env": "14.2.24", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -6631,15 +6665,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.4", - "@next/swc-darwin-x64": "14.2.4", - "@next/swc-linux-arm64-gnu": "14.2.4", - "@next/swc-linux-arm64-musl": "14.2.4", - "@next/swc-linux-x64-gnu": "14.2.4", - "@next/swc-linux-x64-musl": "14.2.4", - "@next/swc-win32-arm64-msvc": "14.2.4", - "@next/swc-win32-ia32-msvc": "14.2.4", - "@next/swc-win32-x64-msvc": "14.2.4" + "@next/swc-darwin-arm64": "14.2.24", + "@next/swc-darwin-x64": "14.2.24", + "@next/swc-linux-arm64-gnu": "14.2.24", + "@next/swc-linux-arm64-musl": "14.2.24", + "@next/swc-linux-x64-gnu": "14.2.24", + "@next/swc-linux-x64-musl": "14.2.24", + "@next/swc-win32-arm64-msvc": "14.2.24", + "@next/swc-win32-ia32-msvc": "14.2.24", + "@next/swc-win32-x64-msvc": "14.2.24" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -7132,13 +7166,13 @@ } }, "node_modules/playwright": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", - "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.0.tgz", + "integrity": "sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.1" + "playwright-core": "1.51.0" }, "bin": { "playwright": "cli.js" @@ -7151,9 +7185,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz", - "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.0.tgz", + "integrity": "sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -7163,21 +7197,6 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", diff --git a/package.json b/package.json index 993a59c..fa55ab0 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@jest/globals": "^29.7.0", "@types/jest": "^29.5.12", "flag-icons": "^7.2.2", + "fs": "^0.0.1-security", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "24.1.0", @@ -26,7 +27,7 @@ "use-sound": "^4.0.1" }, "devDependencies": { - "@playwright/test": "^1.45.1", + "@playwright/test": "^1.51.0", "@testing-library/dom": "^10.1.0", "@testing-library/react": "^16.0.0", "@types/node": "^20", @@ -38,5 +39,10 @@ "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" + }, + "browser": { + "fs": false, + "path": false, + "os": false } } diff --git a/playwright.config.ts b/playwright.config.ts index be844e1..2c001df 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -35,9 +35,11 @@ export default defineConfig({ projects: [ { name: "chromium", - use: { ...devices["Desktop Chrome"] }, + use: { + ...devices["Desktop Chrome"], + permissions: ["clipboard-read", "clipboard-write"], + }, }, - { name: "firefox", use: { ...devices["Desktop Firefox"] }, diff --git a/src/app/oxford-debate/page.tsx b/src/app/oxford-debate/page.tsx index 5e7ffe5..a09949f 100644 --- a/src/app/oxford-debate/page.tsx +++ b/src/app/oxford-debate/page.tsx @@ -156,7 +156,9 @@ export default function OxfordDebate() { {/* debate finished */} {stage === 8 && (
-

{debateFinishedEnthusiastic}

+

+ {debateFinishedEnthusiastic} +

{"🎉"}

)} diff --git a/src/app/oxford-debate/setup/page.tsx b/src/app/oxford-debate/setup/page.tsx index 71f062a..6820f5f 100644 --- a/src/app/oxford-debate/setup/page.tsx +++ b/src/app/oxford-debate/setup/page.tsx @@ -10,16 +10,26 @@ import { IconPlayCircle } from "@/components/icons/PlayCircle"; import { IconX } from "@/components/icons/X"; import { DebateContext } from "@/contexts/DebateContext"; import { useLang } from "@/lib/useLang"; -import { displayImageType, displayImageTypeArray } from "@/types/debate"; -import { useContext, useEffect, useState } from "react"; +import { + debateConf, + defaultDebateConf, + displayImageType, + displayImageTypeArray, +} from "@/types/debate"; +import { useContext, useEffect, useRef, useState } from "react"; import { defaultSoundPack, soundPackName, soundPackNamesArray, soundPacks, + ztmPoznańSoundPack, } from "@/types/soundPack"; import { convertImageToBase64 } from "@/lib/imageToBase64"; import { DebatecoreFooter } from "@/components/DebatecoreFooter"; +import { IconClipboard } from "@/components/icons/Clipboard"; +import { useEffectOnce } from "react-use"; +import { toast, Toaster } from "sonner"; +import Link from "next/link"; export default function OxfordDebateSetup() { const debateContext = useContext(DebateContext); @@ -31,6 +41,8 @@ export default function OxfordDebateSetup() { const soundPackDefault = useLang("defaultSoundsOption"); const [customClockImageSelected, setCustomClockImageSelected] = useState(false); + const initializedRef = useRef(false); + const debateCopiedMessage = useLang("debateCopiedSuccess"); const getDisplayNameOfClockImage = (clockImageName: string) => { switch (clockImageName) { @@ -68,10 +80,137 @@ export default function OxfordDebateSetup() { } else { setCustomClockImageSelected(false); } + initializedRef.current = true; + }, [setCustomClockImageSelected, debateContext.conf.clockImageName]); + + const parseUrlParams = () => { + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const conf: debateConf = { + motion: urlParams.get("motion") || defaultDebateConf.motion, + proTeam: urlParams.get("proTeam") || defaultDebateConf.proTeam, + oppTeam: urlParams.get("oppTeam") || defaultDebateConf.oppTeam, + speechTime: + parseInt(urlParams.get("speechTime") || "") || + defaultDebateConf.speechTime, + adVocemTime: + parseInt(urlParams.get("adVocemTime") || "") || + defaultDebateConf.adVocemTime, + endProtectedTime: + parseInt(urlParams.get("endProtectedTime") || "") || + defaultDebateConf.endProtectedTime, + startProtectedTime: + parseInt(urlParams.get("startProtectedTime") || "") || + defaultDebateConf.startProtectedTime, + beepOnSpeechEnd: getBooleanParamValue("beepOnSpeechEnd", urlParams), + beepProtectedTime: getBooleanParamValue("beepProtectedTime", urlParams), + visualizeProtectedTimes: false, + clockImageName: parseClockImageName( + urlParams.get("clockImageName"), + urlParams.get("customClockImageLink") + ), + customClockImageBase64: "", + customClockImageLink: urlParams.get("customClockImageLink") || "", + soundPack: getSoundPack(urlParams), + }; + return conf; + }; + + useEffectOnce(() => { + let confFromParams = parseUrlParams(); + if ( + debateContext.conf == defaultDebateConf && + confFromParams != defaultDebateConf + ) { + debateContext.setConf(confFromParams); + } }); + function getBooleanParamValue( + param: "beepOnSpeechEnd" | "beepProtectedTime", + urlParams: URLSearchParams + ): boolean { + const paramValue = parseAsBoolean(urlParams.get(param)); + if (paramValue != undefined) { + return paramValue; + } else if (param == "beepOnSpeechEnd") { + return defaultDebateConf.beepOnSpeechEnd; + } else if (param == "beepProtectedTime") { + return defaultDebateConf.beepProtectedTime; + } else { + throw Error("Invalid boolean param"); + } + } + + function parseAsBoolean(value: string | null): boolean | undefined { + if (value == "true") { + return true; + } else if (value == "false") { + return false; + } else { + return undefined; + } + } + + function getSoundPack(urlParams: URLSearchParams) { + const soundPack = urlParams.get("soundPack"); + if (soundPack == undefined) { + return defaultSoundPack; + } + if (decodeURI(soundPack) == "ZTM Poznań") { + return ztmPoznańSoundPack; + } else { + return defaultSoundPack; + } + } + + function parseClockImageName( + name: string | null, + clockImageLink: string | null + ): displayImageType { + if (displayImageTypeArray.includes(name as any)) { + return name as displayImageType; + } else if (!displayImageTypeArray.includes(name as any) && clockImageLink) { + return "custom"; + } else return "null"; + } + + function copyDebateConfigurationLink() { + const currentDebateConf = debateContext.conf; + const params = []; + let param: keyof debateConf; + for (param in currentDebateConf) { + if ( + currentDebateConf[param] != defaultDebateConf[param] && + param != "soundPack" + ) { + params.push(`${param}=${currentDebateConf[param]}`); + } + } + let link = `${ + location.protocol + "//" + location.host + location.pathname + }`; + if (params.length == 0) { + navigator.clipboard.writeText(link); + } else { + link += "?"; + params.forEach((param) => { + link += `&${param}`; + }); + if ( + currentDebateConf.soundPack.name != defaultDebateConf.soundPack.name + ) { + link += `&soundPack=${currentDebateConf.soundPack.name}`; + } + navigator.clipboard.writeText(encodeURI(link)); + console.log(link); + } + toast.success(debateCopiedMessage); + } + return (
+

{useLang("oxfordDebateConfiguration")} @@ -199,6 +338,13 @@ export default function OxfordDebateSetup() {
+ + copyDebateConfigurationLink()} + text={useLang("copyDebateConfiguration")} + icon={IconClipboard} + /> + { const [clockImageLoaded, setClockImageLoaded] = useState(false); const loadingText = useLang("loading"); + function getImageSource() { + if ( + currentDebateConf.clockImageName == "custom" && + currentDebateConf.customClockImageBase64 != "" + ) { + return `data:image/png;base64, ${currentDebateConf.customClockImageBase64}`; + } else if ( + currentDebateConf.clockImageName == "custom" && + currentDebateConf.customClockImageLink != "" + ) { + return currentDebateConf.customClockImageLink; + } else { + return ""; + } + } + return (
{ /> )} {clockImageName === "custom" && - currentDebateConf.customClockImageBase64 != "" && ( + currentDebateConf.customClockImageBase64 != "" && + currentDebateConf.customClockImageLink == "" && ( Custom logo setClockImageLoaded(true)} + data-loaded={clockImageLoaded} + /> + )} + {clockImageName === "custom" && + currentDebateConf.customClockImageLink != "" && ( + Custom logo {
{useLang("disclaimer")} - {" © 2023-2024 Jakub Mańczak & Mateusz Dobrzyński"} + {" © 2023-2025 Jakub Mańczak & Mateusz Dobrzyński"}
); diff --git a/src/components/TimeInput.tsx b/src/components/TimeInput.tsx index 84e1b5a..6a6d783 100644 --- a/src/components/TimeInput.tsx +++ b/src/components/TimeInput.tsx @@ -29,7 +29,7 @@ const TimeInput = (props: {
{minutesCount} - {` ${minutesGrammaticalNumber}`} + {` ${minutesGrammaticalNumber}`}