From 20bc80728ca3e693d0168fd47d3381aceccf9394 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:20:52 +0900 Subject: [PATCH 001/190] chore(deps): update [misskey-js] update dependencies (#15692) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- packages/misskey-js/generator/package.json | 6 +- packages/misskey-js/package.json | 10 +- pnpm-lock.yaml | 615 ++++++++++++++++----- 3 files changed, 488 insertions(+), 143 deletions(-) diff --git a/packages/misskey-js/generator/package.json b/packages/misskey-js/generator/package.json index f3c926bcdf..290b01ee50 100644 --- a/packages/misskey-js/generator/package.json +++ b/packages/misskey-js/generator/package.json @@ -8,9 +8,9 @@ }, "devDependencies": { "@readme/openapi-parser": "2.7.0", - "@types/node": "22.13.9", - "@typescript-eslint/eslint-plugin": "8.26.0", - "@typescript-eslint/parser": "8.26.0", + "@types/node": "22.13.15", + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", "openapi-types": "12.1.3", "openapi-typescript": "6.7.6", "ts-case-convert": "2.1.0", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 094c0e0856..2cef692184 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -35,12 +35,12 @@ "directory": "packages/misskey-js" }, "devDependencies": { - "@microsoft/api-extractor": "7.51.1", + "@microsoft/api-extractor": "7.52.2", "@swc/jest": "0.2.37", "@types/jest": "29.5.14", - "@types/node": "22.13.9", - "@typescript-eslint/eslint-plugin": "8.26.0", - "@typescript-eslint/parser": "8.26.0", + "@types/node": "22.13.15", + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", "jest": "29.7.0", "jest-fetch-mock": "3.0.3", "jest-websocket-mock": "2.5.0", @@ -50,7 +50,7 @@ "execa": "8.0.1", "tsd": "0.31.2", "typescript": "5.8.2", - "esbuild": "0.25.0", + "esbuild": "0.25.2", "glob": "11.0.1" }, "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7c3a6d462..146021fbf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1309,8 +1309,8 @@ importers: version: 4.4.0 devDependencies: '@microsoft/api-extractor': - specifier: 7.51.1 - version: 7.51.1(@types/node@22.13.9) + specifier: 7.52.2 + version: 7.52.2(@types/node@22.13.15) '@swc/jest': specifier: 0.2.37 version: 0.2.37(@swc/core@1.11.11) @@ -1318,17 +1318,17 @@ importers: specifier: 29.5.14 version: 29.5.14 '@types/node': - specifier: 22.13.9 - version: 22.13.9 + specifier: 22.13.15 + version: 22.13.15 '@typescript-eslint/eslint-plugin': - specifier: 8.26.0 - version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2) + specifier: 8.29.0 + version: 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2) '@typescript-eslint/parser': - specifier: 8.26.0 - version: 8.26.0(eslint@9.22.0)(typescript@5.8.2) + specifier: 8.29.0 + version: 8.29.0(eslint@9.22.0)(typescript@5.8.2) esbuild: - specifier: 0.25.0 - version: 0.25.0 + specifier: 0.25.2 + version: 0.25.2 execa: specifier: 8.0.1 version: 8.0.1 @@ -1337,7 +1337,7 @@ importers: version: 11.0.1 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@22.13.9) + version: 29.7.0(@types/node@22.13.15) jest-fetch-mock: specifier: 3.0.3 version: 3.0.3(encoding@0.1.13) @@ -1366,14 +1366,14 @@ importers: specifier: 2.7.0 version: 2.7.0(openapi-types@12.1.3) '@types/node': - specifier: 22.13.9 - version: 22.13.9 + specifier: 22.13.15 + version: 22.13.15 '@typescript-eslint/eslint-plugin': - specifier: 8.26.0 - version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2) + specifier: 8.29.0 + version: 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2) '@typescript-eslint/parser': - specifier: 8.26.0 - version: 8.26.0(eslint@9.22.0)(typescript@5.8.2) + specifier: 8.29.0 + version: 8.29.0(eslint@9.22.0)(typescript@5.8.2) openapi-types: specifier: 12.1.3 version: 12.1.3 @@ -1968,6 +1968,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.0': resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} engines: {node: '>=18'} @@ -1980,6 +1986,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.0': resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} engines: {node: '>=18'} @@ -1992,6 +2004,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.0': resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} engines: {node: '>=18'} @@ -2004,6 +2022,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.0': resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} engines: {node: '>=18'} @@ -2016,6 +2040,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.0': resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} engines: {node: '>=18'} @@ -2028,6 +2058,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.0': resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} engines: {node: '>=18'} @@ -2040,6 +2076,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.0': resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} engines: {node: '>=18'} @@ -2052,6 +2094,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.0': resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} engines: {node: '>=18'} @@ -2064,6 +2112,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.0': resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} engines: {node: '>=18'} @@ -2076,6 +2130,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.0': resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} engines: {node: '>=18'} @@ -2088,6 +2148,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.0': resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} engines: {node: '>=18'} @@ -2100,6 +2166,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.0': resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} engines: {node: '>=18'} @@ -2112,6 +2184,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.0': resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} engines: {node: '>=18'} @@ -2124,6 +2202,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.0': resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} engines: {node: '>=18'} @@ -2136,6 +2220,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.0': resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} engines: {node: '>=18'} @@ -2148,6 +2238,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.0': resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} engines: {node: '>=18'} @@ -2160,6 +2256,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.0': resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} engines: {node: '>=18'} @@ -2172,6 +2274,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.0': resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} engines: {node: '>=18'} @@ -2184,6 +2292,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.0': resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} engines: {node: '>=18'} @@ -2196,6 +2310,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.0': resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} engines: {node: '>=18'} @@ -2208,6 +2328,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.25.0': resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} engines: {node: '>=18'} @@ -2220,6 +2346,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.0': resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} engines: {node: '>=18'} @@ -2232,6 +2364,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.0': resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} engines: {node: '>=18'} @@ -2244,6 +2382,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.0': resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} engines: {node: '>=18'} @@ -2256,6 +2400,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2685,11 +2835,11 @@ packages: '@types/react': '>=16' react: '>=16' - '@microsoft/api-extractor-model@7.30.3': - resolution: {integrity: sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==} + '@microsoft/api-extractor-model@7.30.5': + resolution: {integrity: sha512-0ic4rcbcDZHz833RaTZWTGu+NpNgrxVNjVaor0ZDUymfDFzjA/Uuk8hYziIUIOEOSTfmIQqyzVwlzxZxPe7tOA==} - '@microsoft/api-extractor@7.51.1': - resolution: {integrity: sha512-VoFvIeYXme8QctXDkixy1KIn750kZaFy2snAEOB3nhDFfbBcJNEcvBrpCIQIV09MqI4g9egKUkg+/12WMRC77w==} + '@microsoft/api-extractor@7.52.2': + resolution: {integrity: sha512-RX37V5uhBBPUvrrcmIxuQ8TPsohvr6zxo7SsLPOzBYcH9nbjbvtdXrts4cxHCXGOin9JR5ar37qfxtCOuEBTHA==} hasBin: true '@microsoft/tsdoc-config@0.17.1': @@ -3380,8 +3530,8 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/node-core-library@5.11.0': - resolution: {integrity: sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==} + '@rushstack/node-core-library@5.13.0': + resolution: {integrity: sha512-IGVhy+JgUacAdCGXKUrRhwHMTzqhWwZUI+qEPcdzsb80heOw0QPbhhoVsoiMF7Klp8eYsp7hzpScMXmOa3Uhfg==} peerDependencies: '@types/node': '*' peerDependenciesMeta: @@ -3391,16 +3541,16 @@ packages: '@rushstack/rig-package@0.5.3': resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==} - '@rushstack/terminal@0.15.0': - resolution: {integrity: sha512-vXQPRQ+vJJn4GVqxkwRe+UGgzNxdV8xuJZY2zem46Y0p3tlahucH9/hPmLGj2i9dQnUBFiRnoM9/KW7PYw8F4Q==} + '@rushstack/terminal@0.15.2': + resolution: {integrity: sha512-7Hmc0ysK5077R/IkLS9hYu0QuNafm+TbZbtYVzCMbeOdMjaRboLKrhryjwZSRJGJzu+TV1ON7qZHeqf58XfLpA==} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/ts-command-line@4.23.5': - resolution: {integrity: sha512-jg70HfoK44KfSP3MTiL5rxsZH7X1ktX3cZs9Sl8eDu1/LxJSbPsh0MOFRC710lIuYYSgxWjI5AjbCBAl7u3RxA==} + '@rushstack/ts-command-line@4.23.7': + resolution: {integrity: sha512-Gr9cB7DGe6uz5vq2wdr89WbVDKz0UeuFEn5H2CfWDe7JvjFFaiV15gi6mqDBTbHhHCWS7w8mF1h3BnIfUndqdA==} '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -4341,8 +4491,8 @@ packages: '@types/node@22.13.11': resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==} - '@types/node@22.13.9': - resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} + '@types/node@22.13.15': + resolution: {integrity: sha512-imAbQEEbVni6i6h6Bd5xkCRwLqFc8hihCsi2GbtDoAtUcAFQ6Zs4pFXTZUUbroTkXdImczWM9AI8eZUuybXE3w==} '@types/nodemailer@6.4.17': resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} @@ -4513,6 +4663,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.29.0': + resolution: {integrity: sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.26.0': resolution: {integrity: sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4527,6 +4685,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.29.0': + resolution: {integrity: sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/scope-manager@8.26.0': resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4535,6 +4700,10 @@ packages: resolution: {integrity: sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.29.0': + resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.26.0': resolution: {integrity: sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4549,6 +4718,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.29.0': + resolution: {integrity: sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/types@8.26.0': resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4557,6 +4733,10 @@ packages: resolution: {integrity: sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.29.0': + resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.26.0': resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4569,6 +4749,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.29.0': + resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.26.0': resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4583,6 +4769,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.29.0': + resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/visitor-keys@8.26.0': resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4591,6 +4784,10 @@ packages: resolution: {integrity: sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.29.0': + resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -6171,6 +6368,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -10339,11 +10541,6 @@ packages: typeorm-aurora-data-api-driver: optional: true - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.8.2: resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} @@ -11896,150 +12093,225 @@ snapshots: '@esbuild/aix-ppc64@0.25.1': optional: true + '@esbuild/aix-ppc64@0.25.2': + optional: true + '@esbuild/android-arm64@0.25.0': optional: true '@esbuild/android-arm64@0.25.1': optional: true + '@esbuild/android-arm64@0.25.2': + optional: true + '@esbuild/android-arm@0.25.0': optional: true '@esbuild/android-arm@0.25.1': optional: true + '@esbuild/android-arm@0.25.2': + optional: true + '@esbuild/android-x64@0.25.0': optional: true '@esbuild/android-x64@0.25.1': optional: true + '@esbuild/android-x64@0.25.2': + optional: true + '@esbuild/darwin-arm64@0.25.0': optional: true '@esbuild/darwin-arm64@0.25.1': optional: true + '@esbuild/darwin-arm64@0.25.2': + optional: true + '@esbuild/darwin-x64@0.25.0': optional: true '@esbuild/darwin-x64@0.25.1': optional: true + '@esbuild/darwin-x64@0.25.2': + optional: true + '@esbuild/freebsd-arm64@0.25.0': optional: true '@esbuild/freebsd-arm64@0.25.1': optional: true + '@esbuild/freebsd-arm64@0.25.2': + optional: true + '@esbuild/freebsd-x64@0.25.0': optional: true '@esbuild/freebsd-x64@0.25.1': optional: true + '@esbuild/freebsd-x64@0.25.2': + optional: true + '@esbuild/linux-arm64@0.25.0': optional: true '@esbuild/linux-arm64@0.25.1': optional: true + '@esbuild/linux-arm64@0.25.2': + optional: true + '@esbuild/linux-arm@0.25.0': optional: true '@esbuild/linux-arm@0.25.1': optional: true + '@esbuild/linux-arm@0.25.2': + optional: true + '@esbuild/linux-ia32@0.25.0': optional: true '@esbuild/linux-ia32@0.25.1': optional: true + '@esbuild/linux-ia32@0.25.2': + optional: true + '@esbuild/linux-loong64@0.25.0': optional: true '@esbuild/linux-loong64@0.25.1': optional: true + '@esbuild/linux-loong64@0.25.2': + optional: true + '@esbuild/linux-mips64el@0.25.0': optional: true '@esbuild/linux-mips64el@0.25.1': optional: true + '@esbuild/linux-mips64el@0.25.2': + optional: true + '@esbuild/linux-ppc64@0.25.0': optional: true '@esbuild/linux-ppc64@0.25.1': optional: true + '@esbuild/linux-ppc64@0.25.2': + optional: true + '@esbuild/linux-riscv64@0.25.0': optional: true '@esbuild/linux-riscv64@0.25.1': optional: true + '@esbuild/linux-riscv64@0.25.2': + optional: true + '@esbuild/linux-s390x@0.25.0': optional: true '@esbuild/linux-s390x@0.25.1': optional: true + '@esbuild/linux-s390x@0.25.2': + optional: true + '@esbuild/linux-x64@0.25.0': optional: true '@esbuild/linux-x64@0.25.1': optional: true + '@esbuild/linux-x64@0.25.2': + optional: true + '@esbuild/netbsd-arm64@0.25.0': optional: true '@esbuild/netbsd-arm64@0.25.1': optional: true + '@esbuild/netbsd-arm64@0.25.2': + optional: true + '@esbuild/netbsd-x64@0.25.0': optional: true '@esbuild/netbsd-x64@0.25.1': optional: true + '@esbuild/netbsd-x64@0.25.2': + optional: true + '@esbuild/openbsd-arm64@0.25.0': optional: true '@esbuild/openbsd-arm64@0.25.1': optional: true + '@esbuild/openbsd-arm64@0.25.2': + optional: true + '@esbuild/openbsd-x64@0.25.0': optional: true '@esbuild/openbsd-x64@0.25.1': optional: true + '@esbuild/openbsd-x64@0.25.2': + optional: true + '@esbuild/sunos-x64@0.25.0': optional: true '@esbuild/sunos-x64@0.25.1': optional: true + '@esbuild/sunos-x64@0.25.2': + optional: true + '@esbuild/win32-arm64@0.25.0': optional: true '@esbuild/win32-arm64@0.25.1': optional: true + '@esbuild/win32-arm64@0.25.2': + optional: true + '@esbuild/win32-ia32@0.25.0': optional: true '@esbuild/win32-ia32@0.25.1': optional: true + '@esbuild/win32-ia32@0.25.2': + optional: true + '@esbuild/win32-x64@0.25.0': optional: true '@esbuild/win32-x64@0.25.1': optional: true + '@esbuild/win32-x64@0.25.2': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@9.22.0)': dependencies: eslint: 9.22.0 @@ -12357,7 +12629,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -12370,14 +12642,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.7.1 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.13.11) + jest-config: 29.7.0(@types/node@22.13.15) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -12406,7 +12678,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -12424,7 +12696,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.13.11 + '@types/node': 22.13.15 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -12446,7 +12718,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -12516,7 +12788,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/yargs': 17.0.19 chalk: 4.1.2 @@ -12589,29 +12861,29 @@ snapshots: '@types/react': 18.0.28 react: 19.0.0 - '@microsoft/api-extractor-model@7.30.3(@types/node@22.13.9)': + '@microsoft/api-extractor-model@7.30.5(@types/node@22.13.15)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.9) + '@rushstack/node-core-library': 5.13.0(@types/node@22.13.15) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.51.1(@types/node@22.13.9)': + '@microsoft/api-extractor@7.52.2(@types/node@22.13.15)': dependencies: - '@microsoft/api-extractor-model': 7.30.3(@types/node@22.13.9) + '@microsoft/api-extractor-model': 7.30.5(@types/node@22.13.15) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.9) + '@rushstack/node-core-library': 5.13.0(@types/node@22.13.15) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.0(@types/node@22.13.9) - '@rushstack/ts-command-line': 4.23.5(@types/node@22.13.9) + '@rushstack/terminal': 0.15.2(@types/node@22.13.15) + '@rushstack/ts-command-line': 4.23.7(@types/node@22.13.15) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 semver: 7.5.4 source-map: 0.6.1 - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - '@types/node' @@ -13321,7 +13593,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.11.0(@types/node@22.13.9)': + '@rushstack/node-core-library@5.13.0(@types/node@22.13.15)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -13332,23 +13604,23 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 22.13.9 + '@types/node': 22.13.15 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.0(@types/node@22.13.9)': + '@rushstack/terminal@0.15.2(@types/node@22.13.15)': dependencies: - '@rushstack/node-core-library': 5.11.0(@types/node@22.13.9) + '@rushstack/node-core-library': 5.13.0(@types/node@22.13.15) supports-color: 8.1.1 optionalDependencies: - '@types/node': 22.13.9 + '@types/node': 22.13.15 - '@rushstack/ts-command-line@4.23.5(@types/node@22.13.9)': + '@rushstack/ts-command-line@4.23.7(@types/node@22.13.15)': dependencies: - '@rushstack/terminal': 0.15.0(@types/node@22.13.9) + '@rushstack/terminal': 0.15.2(@types/node@22.13.15) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.1 @@ -14028,8 +14300,8 @@ snapshots: '@storybook/theming': 8.6.7(storybook@8.6.7(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)) better-opn: 3.0.2 browser-assert: 1.2.1 - esbuild: 0.25.1 - esbuild-register: 3.5.0(esbuild@0.25.1) + esbuild: 0.25.2 + esbuild-register: 3.5.0(esbuild@0.25.2) jsdoc-type-pratt-parser: 4.1.0 process: 0.11.10 recast: 0.23.6 @@ -14420,7 +14692,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/archiver@6.0.3': dependencies: @@ -14456,7 +14728,7 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.35 - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/braces@3.0.1': {} @@ -14470,11 +14742,11 @@ snapshots: '@types/connect@3.4.35': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/connect@3.4.36': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/content-disposition@0.5.8': {} @@ -14499,7 +14771,7 @@ snapshots: '@types/express-serve-static-core@4.17.33': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 @@ -14512,11 +14784,11 @@ snapshots: '@types/fluent-ffmpeg@2.1.27': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/graceful-fs@4.1.6': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/hammerjs@2.0.46': {} @@ -14530,7 +14802,7 @@ snapshots: '@types/http-link-header@1.0.7': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/istanbul-lib-coverage@2.0.4': {} @@ -14551,7 +14823,7 @@ snapshots: '@types/jsdom@21.1.7': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/tough-cookie': 4.0.2 parse5: 7.2.1 @@ -14587,11 +14859,11 @@ snapshots: '@types/mysql@2.15.26': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/node-fetch@2.6.11': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 form-data: 4.0.2 '@types/node@22.13.10': @@ -14602,13 +14874,13 @@ snapshots: dependencies: undici-types: 6.20.0 - '@types/node@22.13.9': + '@types/node@22.13.15': dependencies: undici-types: 6.20.0 '@types/nodemailer@6.4.17': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/normalize-package-data@2.4.1': {} @@ -14619,11 +14891,11 @@ snapshots: '@types/oauth2orize@1.11.5': dependencies: '@types/express': 4.17.17 - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/oauth@0.9.6': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/offscreencanvas@2019.3.0': {} @@ -14635,13 +14907,13 @@ snapshots: '@types/pg@8.11.11': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 pg-protocol: 1.7.0 pg-types: 4.0.1 '@types/pg@8.6.1': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 pg-protocol: 1.7.1 pg-types: 2.2.0 @@ -14653,7 +14925,7 @@ snapshots: '@types/qrcode@1.5.5': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/qs@6.9.7': {} @@ -14671,7 +14943,7 @@ snapshots: '@types/readdir-glob@1.1.1': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/rename@1.0.7': {} @@ -14692,7 +14964,7 @@ snapshots: '@types/serve-static@1.15.1': dependencies: '@types/mime': 3.0.1 - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/serviceworker@0.0.74': {} @@ -14716,7 +14988,7 @@ snapshots: '@types/tedious@4.0.14': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 '@types/throttle-debounce@5.0.2': {} @@ -14734,15 +15006,15 @@ snapshots: '@types/vary@1.1.3': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/web-push@3.6.4': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/ws@8.18.0': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.15 '@types/yargs-parser@21.0.0': {} @@ -14752,7 +15024,7 @@ snapshots: '@types/yauzl@2.10.0': dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 optional: true '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2)': @@ -14789,6 +15061,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.29.0(eslint@9.22.0)(typescript@5.8.2) + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/type-utils': 8.29.0(eslint@9.22.0)(typescript@5.8.2) + '@typescript-eslint/utils': 8.29.0(eslint@9.22.0)(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.29.0 + eslint: 9.22.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.26.0(eslint@9.22.0)(typescript@5.8.2)': dependencies: '@typescript-eslint/scope-manager': 8.26.0 @@ -14813,6 +15102,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.29.0(eslint@9.22.0)(typescript@5.8.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.29.0 + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.22.0 + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.26.0': dependencies: '@typescript-eslint/types': 8.26.0 @@ -14823,6 +15124,11 @@ snapshots: '@typescript-eslint/types': 8.27.0 '@typescript-eslint/visitor-keys': 8.27.0 + '@typescript-eslint/scope-manager@8.29.0': + dependencies: + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/visitor-keys': 8.29.0 + '@typescript-eslint/type-utils@8.26.0(eslint@9.22.0)(typescript@5.8.2)': dependencies: '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) @@ -14845,10 +15151,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.29.0(eslint@9.22.0)(typescript@5.8.2)': + dependencies: + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) + '@typescript-eslint/utils': 8.29.0(eslint@9.22.0)(typescript@5.8.2) + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.22.0 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@8.26.0': {} '@typescript-eslint/types@8.27.0': {} + '@typescript-eslint/types@8.29.0': {} + '@typescript-eslint/typescript-estree@8.26.0(typescript@5.8.2)': dependencies: '@typescript-eslint/types': 8.26.0 @@ -14877,6 +15196,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.29.0(typescript@5.8.2)': + dependencies: + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/visitor-keys': 8.29.0 + debug: 4.4.0(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.26.0(eslint@9.22.0)(typescript@5.8.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.22.0) @@ -14899,6 +15232,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.29.0(eslint@9.22.0)(typescript@5.8.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.22.0) + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2) + eslint: 9.22.0 + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@8.26.0': dependencies: '@typescript-eslint/types': 8.26.0 @@ -14909,6 +15253,11 @@ snapshots: '@typescript-eslint/types': 8.27.0 eslint-visitor-keys: 4.2.0 + '@typescript-eslint/visitor-keys@8.29.0': + dependencies: + '@typescript-eslint/types': 8.29.0 + eslint-visitor-keys: 4.2.0 + '@ungap/structured-clone@1.2.0': {} '@vitejs/plugin-vue@5.2.3(vite@6.2.4(@types/node@22.13.11)(sass@1.86.0)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))': @@ -16169,13 +16518,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@22.13.9): + create-jest@29.7.0(@types/node@22.13.15): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.13.9) + jest-config: 29.7.0(@types/node@22.13.15) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -16878,10 +17227,10 @@ snapshots: es6-promise: 4.2.8 optional: true - esbuild-register@3.5.0(esbuild@0.25.1): + esbuild-register@3.5.0(esbuild@0.25.2): dependencies: debug: 4.4.0(supports-color@8.1.1) - esbuild: 0.25.1 + esbuild: 0.25.2 transitivePeerDependencies: - supports-color @@ -16941,6 +17290,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.1 '@esbuild/win32-x64': 0.25.1 + esbuild@0.25.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 + escalade@3.1.1: {} escalade@3.2.0: {} @@ -18382,7 +18759,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 co: 4.6.0 dedent: 1.3.0 @@ -18421,16 +18798,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@22.13.9): + jest-cli@29.7.0(@types/node@22.13.15): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.13.9) + create-jest: 29.7.0(@types/node@22.13.15) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@22.13.9) + jest-config: 29.7.0(@types/node@22.13.15) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -18470,7 +18847,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.13.11): + jest-config@29.7.0(@types/node@22.13.15): dependencies: '@babel/core': 7.23.5 '@jest/test-sequencer': 29.7.0 @@ -18495,37 +18872,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.13.11 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-config@29.7.0(@types/node@22.13.9): - dependencies: - '@babel/core': 7.23.5 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.23.5) - chalk: 4.1.2 - ci-info: 3.7.1 - deepmerge: 4.2.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.13.9 + '@types/node': 22.13.15 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -18554,7 +18901,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -18571,7 +18918,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.6 - '@types/node': 22.13.11 + '@types/node': 22.13.15 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -18610,7 +18957,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.13.10 + '@types/node': 22.13.15 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -18645,7 +18992,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -18673,7 +19020,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 @@ -18719,7 +19066,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 chalk: 4.1.2 ci-info: 3.7.1 graceful-fs: 4.2.11 @@ -18738,7 +19085,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.13.11 + '@types/node': 22.13.15 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -18752,7 +19099,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.13.11 + '@types/node': 22.13.15 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -18769,12 +19116,12 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@22.13.9): + jest@29.7.0(@types/node@22.13.15): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@22.13.9) + jest-cli: 29.7.0(@types/node@22.13.15) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -21942,8 +22289,6 @@ snapshots: transitivePeerDependencies: - supports-color - typescript@5.7.3: {} - typescript@5.8.2: {} uid2@0.0.4: {} From 70133a88f2d7cda6ab39e44fe08780086072ff4a Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:52:59 +0900 Subject: [PATCH 002/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/MkThemePreview.vue | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/MkThemePreview.vue b/packages/frontend/src/components/MkThemePreview.vue index fb5e2b6571..013ab9d6a4 100644 --- a/packages/frontend/src/components/MkThemePreview.vue +++ b/packages/frontend/src/components/MkThemePreview.vue @@ -12,11 +12,13 @@ SPDX-License-Identifier: AGPL-3.0-only - - - - - + + + + + + + @@ -53,14 +55,23 @@ const themeVariables = ref<{ bg: string; panel: string; fg: string; + mention: string; + hashtag: string; + link: string; divider: string; accent: string; accentedBg: string; navBg: string; + success: string; + warn: string; + error: string; }>({ bg: 'var(--MI_THEME-bg)', panel: 'var(--MI_THEME-panel)', fg: 'var(--MI_THEME-fg)', + mention: 'var(--MI_THEME-mention)', + hashtag: 'var(--MI_THEME-hashtag)', + link: 'var(--MI_THEME-link)', divider: 'var(--MI_THEME-divider)', accent: 'var(--MI_THEME-accent)', accentedBg: 'var(--MI_THEME-accentedBg)', @@ -86,6 +97,9 @@ watch(() => props.theme, (theme) => { bg: compiled.bg ?? 'var(--MI_THEME-bg)', panel: compiled.panel ?? 'var(--MI_THEME-panel)', fg: compiled.fg ?? 'var(--MI_THEME-fg)', + mention: compiled.mention ?? 'var(--MI_THEME-mention)', + hashtag: compiled.hashtag ?? 'var(--MI_THEME-hashtag)', + link: compiled.link ?? 'var(--MI_THEME-link)', divider: compiled.divider ?? 'var(--MI_THEME-divider)', accent: compiled.accent ?? 'var(--MI_THEME-accent)', accentedBg: compiled.accentedBg ?? 'var(--MI_THEME-accentedBg)', From f4f9832f8bf7d8bb1b95055f8da049931119412d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 1 Apr 2025 17:13:58 +0900 Subject: [PATCH 003/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 26 ++++--------------- locales/ja-JP.yml | 14 ++++------ packages/frontend-shared/themes/_dark.json5 | 1 - packages/frontend-shared/themes/_light.json5 | 1 - packages/frontend-shared/themes/d-astro.json5 | 1 - packages/frontend-shared/themes/d-u0.json5 | 1 - packages/frontend-shared/themes/l-u0.json5 | 1 - packages/frontend-shared/themes/l-vivid.json5 | 1 - .../src/ui/_common_/navbar-for-mobile.vue | 2 +- .../frontend/src/ui/_common_/navbar-h.vue | 2 +- packages/frontend/src/ui/_common_/navbar.vue | 2 +- 11 files changed, 13 insertions(+), 39 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 4d3e4e73ce..2c64a6d373 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -8235,23 +8235,19 @@ export interface Locale extends ILocale { */ "header": string; /** - * サイドバーの背景 + * ナビゲーションバーの背景 */ "navBg": string; /** - * サイドバーの文字 + * ナビゲーションバーの文字 */ "navFg": string; /** - * サイドバー文字(ホバー) - */ - "navHoverFg": string; - /** - * サイドバー文字(アクティブ) + * ナビゲーションバー文字(アクティブ) */ "navActive": string; /** - * サイドバーのインジケーター + * ナビゲーションバーのインジケーター */ "navIndicator": string; /** @@ -8271,7 +8267,7 @@ export interface Locale extends ILocale { */ "mentionMe": string; /** - * Renote + * リノート */ "renote": string; /** @@ -8334,10 +8330,6 @@ export interface Locale extends ILocale { * ドライブフォルダーの背景 */ "driveFolderBg": string; - /** - * 壁紙のオーバーレイ - */ - "wallpaperOverlay": string; /** * バッジ */ @@ -8346,14 +8338,6 @@ export interface Locale extends ILocale { * チャットの背景 */ "messageBg": string; - /** - * アクセント (暗め) - */ - "accentDarken": string; - /** - * アクセント (明るめ) - */ - "accentLighten": string; /** * 強調された文字 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 639b094a81..322506965c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2161,16 +2161,15 @@ _theme: panel: "パネル" shadow: "影" header: "ヘッダー" - navBg: "サイドバーの背景" - navFg: "サイドバーの文字" - navHoverFg: "サイドバー文字(ホバー)" - navActive: "サイドバー文字(アクティブ)" - navIndicator: "サイドバーのインジケーター" + navBg: "ナビゲーションバーの背景" + navFg: "ナビゲーションバーの文字" + navActive: "ナビゲーションバー文字(アクティブ)" + navIndicator: "ナビゲーションバーのインジケーター" link: "リンク" hashtag: "ハッシュタグ" mention: "メンション" mentionMe: "あなた宛てメンション" - renote: "Renote" + renote: "リノート" modalBg: "モーダルの背景" divider: "分割線" scrollbarHandle: "スクロールバーの取っ手" @@ -2186,11 +2185,8 @@ _theme: buttonHoverBg: "ボタンの背景 (ホバー)" inputBorder: "入力ボックスの縁取り" driveFolderBg: "ドライブフォルダーの背景" - wallpaperOverlay: "壁紙のオーバーレイ" badge: "バッジ" messageBg: "チャットの背景" - accentDarken: "アクセント (暗め)" - accentLighten: "アクセント (明るめ)" fgHighlighted: "強調された文字" _sfx: diff --git a/packages/frontend-shared/themes/_dark.json5 b/packages/frontend-shared/themes/_dark.json5 index d960e627ef..cefc5edb72 100644 --- a/packages/frontend-shared/themes/_dark.json5 +++ b/packages/frontend-shared/themes/_dark.json5 @@ -34,7 +34,6 @@ header: ':alpha<0.7<@panel', navBg: '@panel', navFg: '@fg', - navHoverFg: ':lighten<17<@fg', navActive: '@accent', navIndicator: '@indicator', link: '#44a4c1', diff --git a/packages/frontend-shared/themes/_light.json5 b/packages/frontend-shared/themes/_light.json5 index 90912df3e3..25e6e5ab7f 100644 --- a/packages/frontend-shared/themes/_light.json5 +++ b/packages/frontend-shared/themes/_light.json5 @@ -34,7 +34,6 @@ header: ':alpha<0.7<@panel', navBg: '@panel', navFg: '@fg', - navHoverFg: ':darken<17<@fg', navActive: '@accent', navIndicator: '@indicator', link: '#44a4c1', diff --git a/packages/frontend-shared/themes/d-astro.json5 b/packages/frontend-shared/themes/d-astro.json5 index c2792d2e9f..48839241bd 100644 --- a/packages/frontend-shared/themes/d-astro.json5 +++ b/packages/frontend-shared/themes/d-astro.json5 @@ -31,7 +31,6 @@ navActive: '@accent', infoWarnBg: '#42321c', infoWarnFg: '#ffbd3e', - navHoverFg: ':lighten<17<@fg', dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', inputBorderHover: 'rgba(255, 255, 255, 0.2)', diff --git a/packages/frontend-shared/themes/d-u0.json5 b/packages/frontend-shared/themes/d-u0.json5 index e1bda175dd..ddce06649c 100644 --- a/packages/frontend-shared/themes/d-u0.json5 +++ b/packages/frontend-shared/themes/d-u0.json5 @@ -42,7 +42,6 @@ fgOnWhite: '@accent', infoWarnBg: '#42321c', infoWarnFg: '#ffbd3e', - navHoverFg: ':lighten<17<@fg', codeBoolean: '#c59eff', dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', diff --git a/packages/frontend-shared/themes/l-u0.json5 b/packages/frontend-shared/themes/l-u0.json5 index c76ae3a9c6..d8e403c961 100644 --- a/packages/frontend-shared/themes/l-u0.json5 +++ b/packages/frontend-shared/themes/l-u0.json5 @@ -43,7 +43,6 @@ fgOnWhite: '@accent', infoWarnBg: '#42321c', infoWarnFg: '#ffbd3e', - navHoverFg: ':lighten<17<@fg', codeBoolean: '#c59eff', dateLabelFg: '@fg', inputBorder: 'rgba(255, 255, 255, 0.1)', diff --git a/packages/frontend-shared/themes/l-vivid.json5 b/packages/frontend-shared/themes/l-vivid.json5 index dbd725e35f..d69f024a6b 100644 --- a/packages/frontend-shared/themes/l-vivid.json5 +++ b/packages/frontend-shared/themes/l-vivid.json5 @@ -34,7 +34,6 @@ navActive: '@accent', infoWarnBg: '#fff0db', infoWarnFg: '#8f6e31', - navHoverFg: ':darken<17<@fg', dateLabelFg: '@fg', inputBorder: 'rgba(0, 0, 0, 0.1)', inputBorderHover: 'rgba(0, 0, 0, 0.2)', diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 6acfde5b89..b5098563bd 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -221,7 +221,7 @@ function more() { &:hover { text-decoration: none; - color: var(--MI_THEME-navHoverFg); + color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17))); } &.active { diff --git a/packages/frontend/src/ui/_common_/navbar-h.vue b/packages/frontend/src/ui/_common_/navbar-h.vue index c93935dd26..13fc592e70 100644 --- a/packages/frontend/src/ui/_common_/navbar-h.vue +++ b/packages/frontend/src/ui/_common_/navbar-h.vue @@ -149,7 +149,7 @@ onMounted(() => { &:hover { text-decoration: none; - color: var(--MI_THEME-navHoverFg); + color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17))); } &.active { diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index fbb604ba8e..faab2704a7 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -456,7 +456,7 @@ function menuEdit() { &:hover { text-decoration: none; - color: var(--MI_THEME-navHoverFg); + color: light-dark(hsl(from var(--MI_THEME-navFg) h s calc(l - 17)), hsl(from var(--MI_THEME-navFg) h s calc(l + 17))); } &.active { From 4f206eea9fd5746470f548a1e067e4546c34f950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 1 Apr 2025 17:15:22 +0900 Subject: [PATCH 004/190] =?UTF-8?q?refactor(frontend):=20intl-string?= =?UTF-8?q?=E3=81=AE=E5=87=A6=E7=90=86=E3=81=AE=E3=83=91=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=9E=E3=83=B3=E3=82=B9=E5=90=91=E4=B8=8A=20(#1573?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(frontend): intl-stringの処理のパフォーマンス向上 * :v: --- packages/frontend/src/utility/intl-string.ts | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/utility/intl-string.ts b/packages/frontend/src/utility/intl-string.ts index a5b5bbb592..4bc51e2cb0 100644 --- a/packages/frontend/src/utility/intl-string.ts +++ b/packages/frontend/src/utility/intl-string.ts @@ -9,9 +9,9 @@ import type { toHiragana as toHiraganaType } from 'wanakana'; let toHiragana: typeof toHiraganaType = (str?: string) => str ?? ''; let isWanakanaLoaded = false; -/** +/** * ローマ字変換のセットアップ(日本語以外の環境で読み込まないのでlazy-loading) - * + * * ここの比較系関数を使う際は事前に呼び出す必要がある */ export async function initIntlString(forceWanakana = false) { @@ -82,16 +82,17 @@ export function normalizeStringWithHiragana(str: string) { /** aとbが同じかどうか */ export function compareStringEquals(a: string, b: string) { - return ( - normalizeString(a) === normalizeString(b) || - normalizeStringWithHiragana(a) === normalizeStringWithHiragana(b) - ); + if (a === b) return true; // まったく同じ場合はtrue。なお、ノーマライズ前後で文字数が変化することがあるため、文字数が違うからといってfalseにはできない + if (normalizeString(a) === normalizeString(b)) return true; + if (normalizeStringWithHiragana(a) === normalizeStringWithHiragana(b)) return true; + return false; } /** baseにqueryが含まれているかどうか */ export function compareStringIncludes(base: string, query: string) { - return ( - normalizeString(base).includes(normalizeString(query)) || - normalizeStringWithHiragana(base).includes(normalizeStringWithHiragana(query)) - ); + if (base === query) return true; // まったく同じ場合は含まれていると考えてよいのでtrue + if (base.includes(query)) return true; + if (normalizeString(base).includes(normalizeString(query))) return true; + if (normalizeStringWithHiragana(base).includes(normalizeStringWithHiragana(query))) return true; + return false; } From bd8162c2bddf9403cc2ac4712b320e6a6834c4de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 1 Apr 2025 08:19:26 +0000 Subject: [PATCH 005/190] Bump version to 2025.4.0-beta.0 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2f9dd2b120..633a0a0293 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.0-alpha.0", + "version": "2025.4.0-beta.0", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 2cef692184..ed73416e45 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.0-alpha.0", + "version": "2025.4.0-beta.0", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From a5f9eba974849fa2fcbad4814d509b04c963ef23 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:09:25 +0900 Subject: [PATCH 006/190] =?UTF-8?q?enhance(frontend):=20=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=BC=E3=83=AB=E3=81=97=E3=81=9F=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=9E=E3=82=92=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9?= =?UTF-8?q?=E9=96=93=E3=81=A7=E5=90=8C=E6=9C=9F=E3=81=A7=E3=81=8D=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + .../frontend/src/pages/settings/theme.vue | 20 +++++++++++++++++++ .../utility/autogen/settings-search-index.ts | 5 +++++ 4 files changed, 30 insertions(+) diff --git a/locales/index.d.ts b/locales/index.d.ts index 2c64a6d373..177c9685a1 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5662,6 +5662,10 @@ export interface Locale extends ILocale { * オフのとき */ "ifOff": string; + /** + * デバイス間でインストールしたテーマを同期 + */ + "enableSyncThemesBetweenDevices": string; "_chat": { /** * 送信者の名前を表示 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 322506965c..483ece655d 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1416,6 +1416,7 @@ _settings: showNavbarSubButtons: "ナビゲーションバーに副ボタンを表示" ifOn: "オンのとき" ifOff: "オフのとき" + enableSyncThemesBetweenDevices: "デバイス間でインストールしたテーマを同期" _chat: showSenderName: "送信者の名前を表示" diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue index d149849afc..adc93ff7a7 100644 --- a/packages/frontend/src/pages/settings/theme.vue +++ b/packages/frontend/src/pages/settings/theme.vue @@ -181,6 +181,12 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + +
{{ i18n.ts._theme.manage }} @@ -264,6 +270,20 @@ watch(syncDeviceDarkMode, () => { } }); +const themesSyncEnabled = ref(prefer.isSyncEnabled('themes')); + +function changeThemesSyncEnabled(value: boolean) { + if (value) { + prefer.enableSync('themes').then((res) => { + if (res == null) return; + if (res.enabled) themesSyncEnabled.value = true; + }); + } else { + prefer.disableSync('themes'); + themesSyncEnabled.value = false; + } +} + const headerActions = computed(() => []); const headerTabs = computed(() => []); diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts index 08ab0d8811..7f800d2b70 100644 --- a/packages/frontend/src/utility/autogen/settings-search-index.ts +++ b/packages/frontend/src/utility/autogen/settings-search-index.ts @@ -37,6 +37,11 @@ export const searchIndexes: SearchIndexItem[] = [ label: i18n.ts.themeForDarkMode, keywords: ['dark', 'theme'], }, + { + id: 'jwW5HULqA', + label: i18n.ts._settings.enableSyncThemesBetweenDevices, + keywords: ['sync', 'themes', 'devices'], + }, ], label: i18n.ts.theme, keywords: ['theme'], From 3ec5bf114b06b620074c307072824d3e078b4946 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:25:53 +0900 Subject: [PATCH 007/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/pages/settings/deck.vue | 2 +- packages/frontend/src/pages/settings/emoji-palette.vue | 2 +- packages/frontend/src/pages/settings/theme.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/pages/settings/deck.vue b/packages/frontend/src/pages/settings/deck.vue index f4bce8a5dd..39055268d4 100644 --- a/packages/frontend/src/pages/settings/deck.vue +++ b/packages/frontend/src/pages/settings/deck.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- + diff --git a/packages/frontend/src/pages/settings/emoji-palette.vue b/packages/frontend/src/pages/settings/emoji-palette.vue index 398228e226..f86c40412a 100644 --- a/packages/frontend/src/pages/settings/emoji-palette.vue +++ b/packages/frontend/src/pages/settings/emoji-palette.vue @@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue index adc93ff7a7..ad641d37db 100644 --- a/packages/frontend/src/pages/settings/theme.vue +++ b/packages/frontend/src/pages/settings/theme.vue @@ -183,7 +183,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + From 55d835ad51dd4e114d367b3711ce0025a15fe26f Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 2 Apr 2025 10:37:16 +0900 Subject: [PATCH 008/190] =?UTF-8?q?Fix:=20=E9=80=9A=E7=9F=A5=E3=81=AE?= =?UTF-8?q?=E3=83=9A=E3=83=BC=E3=82=B8=E3=83=8D=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=81=A7=EF=BC=92=E3=81=A4=E4=BB=A5=E4=B8=8A=E8=AA=AD?= =?UTF-8?q?=E3=81=BF=E8=BE=BC=E3=82=81=E3=81=AA=E3=81=8F=E3=81=AA=E3=82=8B?= =?UTF-8?q?=E3=81=93=E3=81=A8=E3=81=8C=E3=81=82=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20(#15277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: notifications-groupedのinclude/exclude typesに:groupedを指定できてしまう問題 * refactor: 通知の取得処理を Notification Service に移動 * feat: add function to parse additional part of id * fix: 通知のページネーションが正しく動かない問題 Redisにのページネーションで使用する時間及びidとRedis上のものが混同されていたので、Misskeyが生成するものに寄せました。 * pnpm run build-misskey-js-with-types * chore: XADDをretryするように * fix: notifications-groupedでxrevrangeしているのを消し忘れていた --- packages/backend/src/core/IdService.ts | 26 +++- .../backend/src/core/NotificationService.ts | 121 +++++++++++++++--- packages/backend/src/misc/bigint.ts | 40 ++++++ packages/backend/src/misc/id/aid.ts | 7 + packages/backend/src/misc/id/aidx.ts | 8 ++ packages/backend/src/misc/id/meid.ts | 9 ++ packages/backend/src/misc/id/meidg.ts | 9 ++ packages/backend/src/misc/id/object-id.ts | 9 ++ packages/backend/src/misc/id/ulid.ts | 20 ++- .../api/endpoints/i/notifications-grouped.ts | 38 +++--- .../server/api/endpoints/i/notifications.ts | 53 +------- packages/misskey-js/src/autogen/types.ts | 4 +- 12 files changed, 248 insertions(+), 96 deletions(-) create mode 100644 packages/backend/src/misc/bigint.ts diff --git a/packages/backend/src/core/IdService.ts b/packages/backend/src/core/IdService.ts index 10df6ef266..223a8de678 100644 --- a/packages/backend/src/core/IdService.ts +++ b/packages/backend/src/core/IdService.ts @@ -7,13 +7,13 @@ import { Inject, Injectable } from '@nestjs/common'; import { ulid } from 'ulid'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import { genAid, isSafeAidT, parseAid } from '@/misc/id/aid.js'; -import { genAidx, isSafeAidxT, parseAidx } from '@/misc/id/aidx.js'; -import { genMeid, isSafeMeidT, parseMeid } from '@/misc/id/meid.js'; -import { genMeidg, isSafeMeidgT, parseMeidg } from '@/misc/id/meidg.js'; -import { genObjectId, isSafeObjectIdT, parseObjectId } from '@/misc/id/object-id.js'; +import { genAid, isSafeAidT, parseAid, parseAidFull } from '@/misc/id/aid.js'; +import { genAidx, isSafeAidxT, parseAidx, parseAidxFull } from '@/misc/id/aidx.js'; +import { genMeid, isSafeMeidT, parseMeid, parseMeidFull } from '@/misc/id/meid.js'; +import { genMeidg, isSafeMeidgT, parseMeidg, parseMeidgFull } from '@/misc/id/meidg.js'; +import { genObjectId, isSafeObjectIdT, parseObjectId, parseObjectIdFull } from '@/misc/id/object-id.js'; import { bindThis } from '@/decorators.js'; -import { parseUlid } from '@/misc/id/ulid.js'; +import { parseUlid, parseUlidFull } from '@/misc/id/ulid.js'; @Injectable() export class IdService { @@ -70,4 +70,18 @@ export class IdService { default: throw new Error('unrecognized id generation method'); } } + + // Note: additional is at most 64 bits + @bindThis + public parseFull(id: string): { date: number; additional: bigint; } { + switch (this.method) { + case 'aid': return parseAidFull(id); + case 'aidx': return parseAidxFull(id); + case 'objectid': return parseObjectIdFull(id); + case 'meid': return parseMeidFull(id); + case 'meidg': return parseMeidgFull(id); + case 'ulid': return parseUlidFull(id); + default: throw new Error('unrecognized id generation method'); + } + } } diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts index 68ad92f396..eeade4569b 100644 --- a/packages/backend/src/core/NotificationService.ts +++ b/packages/backend/src/core/NotificationService.ts @@ -7,6 +7,7 @@ import { setTimeout } from 'node:timers/promises'; import * as Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { In } from 'typeorm'; +import { ReplyError } from 'ioredis'; import { DI } from '@/di-symbols.js'; import type { UsersRepository } from '@/models/_.js'; import type { MiUser } from '@/models/User.js'; @@ -19,7 +20,7 @@ import { IdService } from '@/core/IdService.js'; import { CacheService } from '@/core/CacheService.js'; import type { Config } from '@/config.js'; import { UserListService } from '@/core/UserListService.js'; -import type { FilterUnionByProperty } from '@/types.js'; +import { FilterUnionByProperty, groupedNotificationTypes, obsoleteNotificationTypes } from '@/types.js'; import { trackPromise } from '@/misc/promise-tracker.js'; @Injectable() @@ -145,21 +146,36 @@ export class NotificationService implements OnApplicationShutdown { } } - const notification = { - id: this.idService.gen(), - createdAt: new Date(), - type: type, - ...(notifierId ? { - notifierId, - } : {}), - ...data, - } as any as FilterUnionByProperty; + const createdAt = new Date(); + let notification: FilterUnionByProperty; + let redisId: string; - const redisIdPromise = this.redisClient.xadd( - `notificationTimeline:${notifieeId}`, - 'MAXLEN', '~', this.config.perUserNotificationsMaxCount.toString(), - '*', - 'data', JSON.stringify(notification)); + do { + notification = { + id: this.idService.gen(), + createdAt, + type: type, + ...(notifierId ? { + notifierId, + } : {}), + ...data, + } as unknown as FilterUnionByProperty; + + try { + redisId = (await this.redisClient.xadd( + `notificationTimeline:${notifieeId}`, + 'MAXLEN', '~', this.config.perUserNotificationsMaxCount.toString(), + this.toXListId(notification.id), + 'data', JSON.stringify(notification)))!; + } catch (e) { + // The ID specified in XADD is equal or smaller than the target stream top item で失敗することがあるのでリトライ + if (e instanceof ReplyError) continue; + throw e; + } + + break; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + } while (true); const packed = await this.notificationEntityService.pack(notification, notifieeId, {}); @@ -173,7 +189,7 @@ export class NotificationService implements OnApplicationShutdown { const interval = notification.type === 'test' ? 0 : 2000; setTimeout(interval, 'unread notification', { signal: this.#shutdownController.signal }).then(async () => { const latestReadNotificationId = await this.redisClient.get(`latestReadNotification:${notifieeId}`); - if (latestReadNotificationId && (latestReadNotificationId >= (await redisIdPromise)!)) return; + if (latestReadNotificationId && (latestReadNotificationId >= redisId)) return; this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed); this.pushNotificationService.pushNotification(notifieeId, 'notification', packed); @@ -228,6 +244,79 @@ export class NotificationService implements OnApplicationShutdown { this.#shutdownController.abort(); } + private toXListId(id: string): string { + const { date, additional } = this.idService.parseFull(id); + return date.toString() + '-' + additional.toString(); + } + + @bindThis + public async getNotifications( + userId: MiUser['id'], + { + sinceId, + untilId, + limit = 20, + includeTypes, + excludeTypes, + }: { + sinceId?: string, + untilId?: string, + limit?: number, + // any extra types are allowed, those are no-op + includeTypes?: (MiNotification['type'] | string)[], + excludeTypes?: (MiNotification['type'] | string)[], + }, + ): Promise { + let sinceTime = sinceId ? this.toXListId(sinceId) : null; + let untilTime = untilId ? this.toXListId(untilId) : null; + + let notifications: MiNotification[]; + for (;;) { + let notificationsRes: [id: string, fields: string[]][]; + + // sinceidのみの場合は古い順、そうでない場合は新しい順。 QueryService.makePaginationQueryも参照 + if (sinceTime && !untilTime) { + notificationsRes = await this.redisClient.xrange( + `notificationTimeline:${userId}`, + '(' + sinceTime, + '+', + 'COUNT', limit); + } else { + notificationsRes = await this.redisClient.xrevrange( + `notificationTimeline:${userId}`, + untilTime ? '(' + untilTime : '+', + sinceTime ? '(' + sinceTime : '-', + 'COUNT', limit); + } + + if (notificationsRes.length === 0) { + return []; + } + + notifications = notificationsRes.map(x => JSON.parse(x[1][1])) as MiNotification[]; + + if (includeTypes && includeTypes.length > 0) { + notifications = notifications.filter(notification => includeTypes.includes(notification.type)); + } else if (excludeTypes && excludeTypes.length > 0) { + notifications = notifications.filter(notification => !excludeTypes.includes(notification.type)); + } + + if (notifications.length !== 0) { + // 通知が1件以上ある場合は返す + break; + } + + // フィルタしたことで通知が0件になった場合、次のページを取得する + if (sinceId && !untilId) { + sinceTime = notificationsRes[notificationsRes.length - 1][0]; + } else { + untilTime = notificationsRes[notificationsRes.length - 1][0]; + } + } + + return notifications; + } + @bindThis public onApplicationShutdown(signal?: string | undefined): void { this.dispose(); diff --git a/packages/backend/src/misc/bigint.ts b/packages/backend/src/misc/bigint.ts new file mode 100644 index 0000000000..efa1527ec9 --- /dev/null +++ b/packages/backend/src/misc/bigint.ts @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +function parseBigIntChunked(str: string, base: number, chunkSize: number, powerOfChunkSize: bigint): bigint { + const chunks = []; + while (str.length > 0) { + chunks.unshift(str.slice(-chunkSize)); + str = str.slice(0, -chunkSize); + } + let result = 0n; + for (const chunk of chunks) { + result *= powerOfChunkSize; + const int = parseInt(chunk, base); + if (Number.isNaN(int)) { + throw new Error('Invalid base36 string'); + } + result += BigInt(int); + } + return result; +} + +export function parseBigInt36(str: string): bigint { + // log_36(Number.MAX_SAFE_INTEGER) => 10.251599391715352 + // so we process 10 chars at once + return parseBigIntChunked(str, 36, 10, 36n ** 10n); +} + +export function parseBigInt16(str: string): bigint { + // log_16(Number.MAX_SAFE_INTEGER) => 13.25 + // so we process 13 chars at once + return parseBigIntChunked(str, 16, 13, 16n ** 13n); +} + +export function parseBigInt32(str: string): bigint { + // log_32(Number.MAX_SAFE_INTEGER) => 10.6 + // so we process 10 chars at once + return parseBigIntChunked(str, 32, 10, 32n ** 10n); +} diff --git a/packages/backend/src/misc/id/aid.ts b/packages/backend/src/misc/id/aid.ts index 60ba788e44..c0e8478db5 100644 --- a/packages/backend/src/misc/id/aid.ts +++ b/packages/backend/src/misc/id/aid.ts @@ -7,6 +7,7 @@ // 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さ2の[ノイズ文字列] import * as crypto from 'node:crypto'; +import { parseBigInt36 } from '@/misc/bigint.js'; export const aidRegExp = /^[0-9a-z]{10}$/; @@ -35,6 +36,12 @@ export function parseAid(id: string): { date: Date; } { return { date: new Date(time) }; } +export function parseAidFull(id: string): { date: number; additional: bigint; } { + const date = parseInt(id.slice(0, 8), 36) + TIME2000; + const additional = parseBigInt36(id.slice(8, 10)); + return { date, additional }; +} + export function isSafeAidT(t: number): boolean { return t > TIME2000; } diff --git a/packages/backend/src/misc/id/aidx.ts b/packages/backend/src/misc/id/aidx.ts index 1b087e70af..006673a6d0 100644 --- a/packages/backend/src/misc/id/aidx.ts +++ b/packages/backend/src/misc/id/aidx.ts @@ -9,6 +9,7 @@ // https://misskey.m544.net/notes/71899acdcc9859ec5708ac24 import { customAlphabet } from 'nanoid'; +import { parseBigInt36 } from '@/misc/bigint.js'; export const aidxRegExp = /^[0-9a-z]{16}$/; @@ -16,6 +17,7 @@ const TIME2000 = 946684800000; const TIME_LENGTH = 8; const NODE_LENGTH = 4; const NOISE_LENGTH = 4; +const AIDX_LENGTH = TIME_LENGTH + NODE_LENGTH + NOISE_LENGTH; const nodeId = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', NODE_LENGTH)(); let counter = 0; @@ -42,6 +44,12 @@ export function parseAidx(id: string): { date: Date; } { return { date: new Date(time) }; } +export function parseAidxFull(id: string): { date: number; additional: bigint; } { + const date = parseInt(id.slice(0, TIME_LENGTH), 36) + TIME2000; + const additional = parseBigInt36(id.slice(TIME_LENGTH, AIDX_LENGTH)); + return { date, additional }; +} + export function isSafeAidxT(t: number): boolean { return t > TIME2000; } diff --git a/packages/backend/src/misc/id/meid.ts b/packages/backend/src/misc/id/meid.ts index dfab48a369..563e07ed8f 100644 --- a/packages/backend/src/misc/id/meid.ts +++ b/packages/backend/src/misc/id/meid.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { parseBigInt16 } from '@/misc/bigint.js'; + const CHARS = '0123456789abcdef'; // same as object-id @@ -39,6 +41,13 @@ export function parseMeid(id: string): { date: Date; } { }; } +export function parseMeidFull(id: string): { date: number; additional: bigint; } { + return { + date: parseInt(id.slice(0, 12), 16) - 0x800000000000, + additional: parseBigInt16(id.slice(12, 24)), + }; +} + export function isSafeMeidT(t: number): boolean { return t > 0; } diff --git a/packages/backend/src/misc/id/meidg.ts b/packages/backend/src/misc/id/meidg.ts index b9c0cc3dda..b825807114 100644 --- a/packages/backend/src/misc/id/meidg.ts +++ b/packages/backend/src/misc/id/meidg.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { parseBigInt16 } from '@/misc/bigint.js'; + const CHARS = '0123456789abcdef'; // 4bit Fixed hex value 'g' @@ -39,6 +41,13 @@ export function parseMeidg(id: string): { date: Date; } { }; } +export function parseMeidgFull(id: string): { date: number; additional: bigint; } { + return { + date: parseInt(id.slice(1, 12), 16), + additional: parseBigInt16(id.slice(12, 24)), + }; +} + export function isSafeMeidgT(t: number): boolean { return t > 0; } diff --git a/packages/backend/src/misc/id/object-id.ts b/packages/backend/src/misc/id/object-id.ts index 243f92bbac..68409c7a61 100644 --- a/packages/backend/src/misc/id/object-id.ts +++ b/packages/backend/src/misc/id/object-id.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { parseBigInt16 } from '@/misc/bigint.js'; + const CHARS = '0123456789abcdef'; // same as meid @@ -39,6 +41,13 @@ export function parseObjectId(id: string): { date: Date; } { }; } +export function parseObjectIdFull(id: string): { date: number; additional: bigint; } { + return { + date: parseInt(id.slice(0, 8), 16) * 1000, + additional: parseBigInt16(id.slice(8, 24)), + }; +} + export function isSafeObjectIdT(t: number): boolean { return t > 0; } diff --git a/packages/backend/src/misc/id/ulid.ts b/packages/backend/src/misc/id/ulid.ts index fc3654d6d2..8b81702d19 100644 --- a/packages/backend/src/misc/id/ulid.ts +++ b/packages/backend/src/misc/id/ulid.ts @@ -5,15 +5,27 @@ // Crockford's Base32 // https://github.com/ulid/spec#encoding +import { parseBigInt32 } from '@/misc/bigint.js'; + const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/; -export function parseUlid(id: string): { date: Date; } { - const timestamp = id.slice(0, 10); +function parseBase32(timestamp: string) { let time = 0; - for (let i = 0; i < 10; i++) { + for (let i = 0; i < timestamp.length; i++) { time = time * 32 + CHARS.indexOf(timestamp[i]); } - return { date: new Date(time) }; + return time; +} + +export function parseUlid(id: string): { date: Date; } { + return { date: new Date(parseBase32(id.slice(0, 10))) }; +} + +export function parseUlidFull(id: string): { date: number; additional: bigint; } { + return { + date: parseBase32(id.slice(0, 10)), + additional: parseBigInt32(id.slice(10, 26)), + }; } diff --git a/packages/backend/src/server/api/endpoints/i/notifications-grouped.ts b/packages/backend/src/server/api/endpoints/i/notifications-grouped.ts index 88d7f51c26..b9c41b057d 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications-grouped.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications-grouped.ts @@ -7,7 +7,12 @@ import { In } from 'typeorm'; import * as Redis from 'ioredis'; import { Inject, Injectable } from '@nestjs/common'; import type { NotesRepository } from '@/models/_.js'; -import { obsoleteNotificationTypes, groupedNotificationTypes, FilterUnionByProperty } from '@/types.js'; +import { + obsoleteNotificationTypes, + groupedNotificationTypes, + FilterUnionByProperty, + notificationTypes, +} from '@/types.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { NotificationEntityService } from '@/core/entities/NotificationEntityService.js'; import { NotificationService } from '@/core/NotificationService.js'; @@ -47,10 +52,10 @@ export const paramDef = { markAsRead: { type: 'boolean', default: true }, // 後方互換のため、廃止された通知タイプも受け付ける includeTypes: { type: 'array', items: { - type: 'string', enum: [...groupedNotificationTypes, ...obsoleteNotificationTypes], + type: 'string', enum: [...notificationTypes, ...obsoleteNotificationTypes], } }, excludeTypes: { type: 'array', items: { - type: 'string', enum: [...groupedNotificationTypes, ...obsoleteNotificationTypes], + type: 'string', enum: [...notificationTypes, ...obsoleteNotificationTypes], } }, }, required: [], @@ -74,31 +79,20 @@ export default class extends Endpoint { // eslint- return []; } // excludeTypes に全指定されている場合はクエリしない - if (groupedNotificationTypes.every(type => ps.excludeTypes?.includes(type))) { + if (notificationTypes.every(type => ps.excludeTypes?.includes(type))) { return []; } const includeTypes = ps.includeTypes && ps.includeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof groupedNotificationTypes[number][]; const excludeTypes = ps.excludeTypes && ps.excludeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof groupedNotificationTypes[number][]; - const limit = (ps.limit + EXTRA_LIMIT) + (ps.untilId ? 1 : 0) + (ps.sinceId ? 1 : 0); // untilIdに指定したものも含まれるため+1 - const notificationsRes = await this.redisClient.xrevrange( - `notificationTimeline:${me.id}`, - ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+', - ps.sinceId ? this.idService.parse(ps.sinceId).date.getTime() : '-', - 'COUNT', limit); - - if (notificationsRes.length === 0) { - return []; - } - - let notifications = notificationsRes.map(x => JSON.parse(x[1][1])).filter(x => x.id !== ps.untilId && x !== ps.sinceId) as MiNotification[]; - - if (includeTypes && includeTypes.length > 0) { - notifications = notifications.filter(notification => includeTypes.includes(notification.type)); - } else if (excludeTypes && excludeTypes.length > 0) { - notifications = notifications.filter(notification => !excludeTypes.includes(notification.type)); - } + const notifications = await this.notificationService.getNotifications(me.id, { + sinceId: ps.sinceId, + untilId: ps.untilId, + limit: ps.limit, + includeTypes, + excludeTypes, + }); if (notifications.length === 0) { return []; diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts index be8d0cfb34..f5a48b2f69 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications.ts @@ -82,52 +82,13 @@ export default class extends Endpoint { // eslint- const includeTypes = ps.includeTypes && ps.includeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][]; const excludeTypes = ps.excludeTypes && ps.excludeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][]; - let sinceTime = ps.sinceId ? this.idService.parse(ps.sinceId).date.getTime().toString() : null; - let untilTime = ps.untilId ? this.idService.parse(ps.untilId).date.getTime().toString() : null; - - let notifications: MiNotification[]; - for (;;) { - let notificationsRes: [id: string, fields: string[]][]; - - // sinceidのみの場合は古い順、そうでない場合は新しい順。 QueryService.makePaginationQueryも参照 - if (sinceTime && !untilTime) { - notificationsRes = await this.redisClient.xrange( - `notificationTimeline:${me.id}`, - '(' + sinceTime, - '+', - 'COUNT', ps.limit); - } else { - notificationsRes = await this.redisClient.xrevrange( - `notificationTimeline:${me.id}`, - untilTime ? '(' + untilTime : '+', - sinceTime ? '(' + sinceTime : '-', - 'COUNT', ps.limit); - } - - if (notificationsRes.length === 0) { - return []; - } - - notifications = notificationsRes.map(x => JSON.parse(x[1][1])) as MiNotification[]; - - if (includeTypes && includeTypes.length > 0) { - notifications = notifications.filter(notification => includeTypes.includes(notification.type)); - } else if (excludeTypes && excludeTypes.length > 0) { - notifications = notifications.filter(notification => !excludeTypes.includes(notification.type)); - } - - if (notifications.length !== 0) { - // 通知が1件以上ある場合は返す - break; - } - - // フィルタしたことで通知が0件になった場合、次のページを取得する - if (ps.sinceId && !ps.untilId) { - sinceTime = notificationsRes[notificationsRes.length - 1][0]; - } else { - untilTime = notificationsRes[notificationsRes.length - 1][0]; - } - } + const notifications = await this.notificationService.getNotifications(me.id, { + sinceId: ps.sinceId, + untilId: ps.untilId, + limit: ps.limit, + includeTypes, + excludeTypes, + }); // Mark all as read if (ps.markAsRead) { diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 57c4824424..d46df2423a 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -21732,8 +21732,8 @@ export type operations = { untilId?: string; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; From d44fd87b69aab9569bd80b34f567bba67eee2fff Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:37:48 +0900 Subject: [PATCH 009/190] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc4636120..4dd40a331e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Enhance: セキュリティを強化するため、ジョブキューのダッシュボード(bull-board)統合が削除されました。 - Misskeyネイティブでダッシュボードを実装予定です - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように +- Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 ### Client - Feat: 設定の管理が強化されました From 2e0c80bc21f68a3b61dfb50bfd9e3d2fe332fb9d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 2 Apr 2025 01:47:33 +0000 Subject: [PATCH 010/190] Bump version to 2025.4.0-beta.1 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 633a0a0293..2611ddb695 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.0-beta.0", + "version": "2025.4.0-beta.1", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index ed73416e45..33a7070cc6 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.0-beta.0", + "version": "2025.4.0-beta.1", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From 102578712bbed1d4588bf5c2b1996a4655d16de8 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 2 Apr 2025 10:48:57 +0900 Subject: [PATCH 011/190] =?UTF-8?q?fix:=20iPad=E3=81=A7deck=20ui=E3=81=A7?= =?UTF-8?q?=E3=83=9E=E3=82=A6=E3=82=B9=E3=83=9B=E3=82=A4=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=A7=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=84=20(#15244)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: ipadでdeck uiでスクロールできない * docs(changelog): iPadOSでdeck uiをマウスカーソルによってスクロールできない問題を修正 * chore: remove pointermove listener * lint: use window.document * chore: use passive pointerdown event --- CHANGELOG.md | 1 + packages/frontend/src/ui/deck.vue | 18 ++++++++++++++---- packages/frontend/src/ui/deck/column.vue | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd40a331e..9a2da274e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ - Fix: テーマ切り替え時に一部の色が変わらない問題を修正 - NOTE: 構造上クラシックUIを新しいデザインシステムに移行することが困難なため、クラシックUIが削除されました - デッキUIでカラムを中央寄せにし、メインカラムの左右にウィジェットカラムを配置し、ナビゲーションバーを上部に表示することである程度クラシックUIを再現できます +- Fix: iPadOSでdeck uiをマウスカーソルによってスクロールできない問題を修正 ### Server - Enhance 全体的なパフォーマンス向上 diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index ef4a6fc03c..bf39c07229 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -12,15 +12,15 @@ SPDX-License-Identifier: AGPL-3.0-only -
-
+ +
{ isMobile.value = window.innerWidth <= 500; }); -const snapScroll = deviceKind === 'smartphone' || deviceKind === 'tablet'; +// ポインターイベント非対応用に初期値はUAから出す +const snapScroll = ref(deviceKind === 'smartphone' || deviceKind === 'tablet'); const withWallpaper = prefer.s['deck.wallpaper'] != null; const drawerMenuShowing = ref(false); const gap = prefer.r['deck.columnGap']; @@ -219,7 +220,16 @@ const onContextmenu = (ev) => { }], ev); }; +// タッチでスクロールしてるときはスナップスクロールを有効にする +function pointerEvent(ev: PointerEvent) { + snapScroll.value = ev.pointerType === 'touch'; +} + +window.document.addEventListener('pointerdown', pointerEvent, { passive: true }); + function onWheel(ev: WheelEvent) { + // WheelEvent はマウスからしか発火しないのでスナップスクロールは無効化する + snapScroll.value = false; if (ev.deltaX === 0 && columnsEl.value != null) { columnsEl.value.scrollLeft += ev.deltaY; } diff --git a/packages/frontend/src/ui/deck/column.vue b/packages/frontend/src/ui/deck/column.vue index 497a04610e..3d359b05c2 100644 --- a/packages/frontend/src/ui/deck/column.vue +++ b/packages/frontend/src/ui/deck/column.vue @@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only @dragstart="onDragstart" @dragend="onDragend" @contextmenu.prevent.stop="onContextmenu" - @wheel="emit('headerWheel', $event)" + @wheel.passive="emit('headerWheel', $event)" > From d0a98f6e6c7596e9649671d7cc88ac14252aa594 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 13:04:03 +0900 Subject: [PATCH 012/190] fix(frontend): Fix #15744 --- packages/frontend/src/components/MkTutorialDialog.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/frontend/src/components/MkTutorialDialog.vue b/packages/frontend/src/components/MkTutorialDialog.vue index 3e91baada4..92f71b01af 100644 --- a/packages/frontend/src/components/MkTutorialDialog.vue +++ b/packages/frontend/src/components/MkTutorialDialog.vue @@ -249,6 +249,7 @@ async function close(skip: boolean) { .pageFooter { position: sticky; + z-index: 1; bottom: 0; left: 0; flex-shrink: 0; From 0bf49818c4477b3bed53017a77885153395662b0 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Wed, 2 Apr 2025 15:44:04 +0900 Subject: [PATCH 013/190] enhance: implement `sentryForFrontend` (#15433) Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- .config/cypress-devcontainer.yml | 5 ++ .config/docker_example.yml | 5 ++ .config/example.yml | 5 ++ .devcontainer/devcontainer.yml | 5 ++ CHANGELOG.md | 3 + chart/files/default.yml | 5 ++ packages/backend/package.json | 1 + packages/backend/src/config.ts | 17 ++++- .../src/core/entities/MetaEntityService.ts | 1 + .../backend/src/models/json-schema/meta.ts | 32 ++++++++ packages/frontend/package.json | 1 + packages/frontend/src/boot/common.ts | 37 +++++++++- packages/misskey-js/src/autogen/types.ts | 15 ++++ pnpm-lock.yaml | 74 +++++++++++++++++++ 14 files changed, 202 insertions(+), 4 deletions(-) diff --git a/.config/cypress-devcontainer.yml b/.config/cypress-devcontainer.yml index e75e32a17a..a028e2685e 100644 --- a/.config/cypress-devcontainer.yml +++ b/.config/cypress-devcontainer.yml @@ -165,6 +165,11 @@ id: 'aidx' # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' #sentryForFrontend: +# vueIntegration: +# tracingOptions: +# trackComponents: true +# browserTracingIntegration: +# replayIntegration: # options: # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' diff --git a/.config/docker_example.yml b/.config/docker_example.yml index 1ffed00cc7..4be1352bd7 100644 --- a/.config/docker_example.yml +++ b/.config/docker_example.yml @@ -177,6 +177,11 @@ id: 'aidx' # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' #sentryForFrontend: +# vueIntegration: +# tracingOptions: +# trackComponents: true +# browserTracingIntegration: +# replayIntegration: # options: # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' diff --git a/.config/example.yml b/.config/example.yml index 71427c84bc..d4584215c9 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -259,6 +259,11 @@ id: 'aidx' # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' #sentryForFrontend: +# vueIntegration: +# tracingOptions: +# trackComponents: true +# browserTracingIntegration: +# replayIntegration: # options: # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' diff --git a/.devcontainer/devcontainer.yml b/.devcontainer/devcontainer.yml index 3eb4fc2879..6d904e87b9 100644 --- a/.devcontainer/devcontainer.yml +++ b/.devcontainer/devcontainer.yml @@ -152,6 +152,11 @@ id: 'aidx' # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' #sentryForFrontend: +# vueIntegration: +# tracingOptions: +# trackComponents: true +# browserTracingIntegration: +# replayIntegration: # options: # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2da274e4..2cd0fbd8e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ - メッセージにはリアクションも可能です - Enhance: セキュリティを強化するため、ジョブキューのダッシュボード(bull-board)統合が削除されました。 - Misskeyネイティブでダッシュボードを実装予定です +- Enhance: フロントエンドのエラートラッキングができるように + - `.config/default.yml`中の項目`sentryForFrontend`を適宜設定してください。 + - 外部サービスであるSentryへエラー情報が送信されます。ご利用の地域の法令に従い、適切なプライバシーポリシーを策定の上で運用してください。 - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように - Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 diff --git a/chart/files/default.yml b/chart/files/default.yml index 4d17131c25..06f762aafa 100644 --- a/chart/files/default.yml +++ b/chart/files/default.yml @@ -173,6 +173,11 @@ id: "aidx" # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' #sentryForFrontend: +# vueIntegration: +# tracingOptions: +# trackComponents: true +# browserTracingIntegration: +# replayIntegration: # options: # dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' diff --git a/packages/backend/package.json b/packages/backend/package.json index bcaa6357ce..d7705b2b9e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -186,6 +186,7 @@ "devDependencies": { "@jest/globals": "29.7.0", "@nestjs/platform-express": "10.4.15", + "@sentry/vue": "9.8.0", "@simplewebauthn/types": "12.0.0", "@swc/jest": "0.2.37", "@types/accepts": "1.3.7", diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 32ea700748..646fa07911 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -7,7 +7,8 @@ import * as fs from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, resolve } from 'node:path'; import * as yaml from 'js-yaml'; -import * as Sentry from '@sentry/node'; +import type * as Sentry from '@sentry/node'; +import type * as SentryVue from '@sentry/vue'; import type { RedisOptions } from 'ioredis'; type RedisOptionsSource = Partial & { @@ -62,7 +63,12 @@ type Source = { scope?: 'local' | 'global' | string[]; }; sentryForBackend?: { options: Partial; enableNodeProfiling: boolean; }; - sentryForFrontend?: { options: Partial }; + sentryForFrontend?: { + options: Partial & { dsn: string }; + vueIntegration?: SentryVue.VueIntegrationOptions | null; + browserTracingIntegration?: Parameters[0] | null; + replayIntegration?: Parameters[0] | null; + }; publishTarballInsteadOfProvideRepositoryUrl?: boolean; @@ -198,7 +204,12 @@ export type Config = { redisForTimelines: RedisOptions & RedisOptionsSource; redisForReactions: RedisOptions & RedisOptionsSource; sentryForBackend: { options: Partial; enableNodeProfiling: boolean; } | undefined; - sentryForFrontend: { options: Partial } | undefined; + sentryForFrontend: { + options: Partial & { dsn: string }; + vueIntegration?: SentryVue.VueIntegrationOptions | null; + browserTracingIntegration?: Parameters[0] | null; + replayIntegration?: Parameters[0] | null; + } | undefined; perChannelMaxNoteCacheCount: number; perUserNotificationsMaxCount: number; deactivateAntennaThreshold: number; diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 08717bd066..02783dc450 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -127,6 +127,7 @@ export class MetaEntityService { policies: { ...DEFAULT_POLICIES, ...instance.policies }, + sentryForFrontend: this.config.sentryForFrontend ?? null, mediaProxy: this.config.mediaProxy, enableUrlPreview: instance.urlPreviewEnabled, noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts index 1e25c355ca..2cd7620af0 100644 --- a/packages/backend/src/models/json-schema/meta.ts +++ b/packages/backend/src/models/json-schema/meta.ts @@ -211,6 +211,38 @@ export const packedMetaLiteSchema = { type: 'boolean', optional: false, nullable: false, }, + sentryForFrontend: { + type: 'object', + optional: false, nullable: true, + properties: { + options: { + type: 'object', + optional: false, nullable: false, + properties: { + dsn: { + type: 'string', + optional: false, nullable: false, + }, + }, + additionalProperties: true, + }, + vueIntegration: { + type: 'object', + optional: true, nullable: true, + additionalProperties: true, + }, + browserTracingIntegration: { + type: 'object', + optional: true, nullable: true, + additionalProperties: true, + }, + replayIntegration: { + type: 'object', + optional: true, nullable: true, + additionalProperties: true, + }, + }, + }, mediaProxy: { type: 'string', optional: false, nullable: false, diff --git a/packages/frontend/package.json b/packages/frontend/package.json index fe0abb173b..01dcf09d47 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -25,6 +25,7 @@ "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "6.0.2", "@rollup/pluginutils": "5.1.4", + "@sentry/vue": "9.8.0", "@syuilo/aiscript": "0.19.0", "@tabler/icons-webfont": "3.31.0", "@twemoji/parser": "15.1.1", diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index 7a88b938dd..c8098b6cf8 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -5,7 +5,7 @@ import { computed, watch, version as vueVersion } from 'vue'; import { compareVersions } from 'compare-versions'; -import { version, lang, updateLocale, locale } from '@@/js/config.js'; +import { version, lang, updateLocale, locale, apiUrl } from '@@/js/config.js'; import defaultLightTheme from '@@/themes/l-light.json5'; import defaultDarkTheme from '@@/themes/d-green-lime.json5'; import type { App } from 'vue'; @@ -291,6 +291,41 @@ export async function common(createVue: () => Promise>) { return root; })(); + if (instance.sentryForFrontend) { + const Sentry = await import('@sentry/vue'); + Sentry.init({ + app, + integrations: [ + ...(instance.sentryForFrontend.vueIntegration !== undefined ? [ + Sentry.vueIntegration(instance.sentryForFrontend.vueIntegration ?? undefined), + ] : []), + ...(instance.sentryForFrontend.browserTracingIntegration !== undefined ? [ + Sentry.browserTracingIntegration(instance.sentryForFrontend.browserTracingIntegration ?? undefined), + ] : []), + ...(instance.sentryForFrontend.replayIntegration !== undefined ? [ + Sentry.replayIntegration(instance.sentryForFrontend.replayIntegration ?? undefined), + ] : []), + ], + + // Set tracesSampleRate to 1.0 to capture 100% + tracesSampleRate: 1.0, + + // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled + ...(instance.sentryForFrontend.browserTracingIntegration !== undefined ? { + tracePropagationTargets: [apiUrl], + } : {}), + + // Capture Replay for 10% of all sessions, + // plus for 100% of sessions with an error + ...(instance.sentryForFrontend.replayIntegration !== undefined ? { + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, + } : {}), + + ...instance.sentryForFrontend.options, + }); + } + app.mount(rootEl); // boot.jsのやつを解除 diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index d46df2423a..ef4be07072 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5309,6 +5309,21 @@ export type components = { enableEmail: boolean; enableServiceWorker: boolean; translatorAvailable: boolean; + sentryForFrontend: ({ + options: { + dsn: string; + [key: string]: unknown; + }; + vueIntegration?: { + [key: string]: unknown; + } | null; + browserTracingIntegration?: { + [key: string]: unknown; + } | null; + replayIntegration?: { + [key: string]: unknown; + } | null; + }) | null; mediaProxy: string; enableUrlPreview: boolean; backgroundImageUrl: string | null; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 146021fbf1..46416c0332 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -444,6 +444,9 @@ importers: '@nestjs/platform-express': specifier: 10.4.15 version: 10.4.15(@nestjs/common@11.0.12(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.0.12) + '@sentry/vue': + specifier: 9.8.0 + version: 9.8.0(vue@3.5.13(typescript@5.8.2)) '@simplewebauthn/types': specifier: 12.0.0 version: 12.0.0 @@ -709,6 +712,9 @@ importers: '@rollup/pluginutils': specifier: 5.1.4 version: 5.1.4(rollup@4.36.0) + '@sentry/vue': + specifier: 9.8.0 + version: 9.8.0(vue@3.5.13(typescript@5.8.2)) '@syuilo/aiscript': specifier: 0.19.0 version: 0.19.0 @@ -3555,10 +3561,34 @@ packages: '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@sentry-internal/browser-utils@9.8.0': + resolution: {integrity: sha512-7aQDeU9ogMLKnEBFM/vvgMMgZDkfMhoZCtX8kq65gn33L4X2B8sI5oyUj2QJtXaRSsiUjbdCaquDLqZBCaLQHA==} + engines: {node: '>=18'} + + '@sentry-internal/feedback@9.8.0': + resolution: {integrity: sha512-xWiCJkD8ROuy2pnojuRLcLI6sezK399gasA5ZL4MCXdkryqZYs55Ef2Ofj4z0RdUc8gMUb81+LTqwbmbfTqNlQ==} + engines: {node: '>=18'} + + '@sentry-internal/replay-canvas@9.8.0': + resolution: {integrity: sha512-/6ELOnyCOItvqv2Os29JhE8ydDds3xibMQ+FomsSkClQdC4bbc/L74nm/fdXVpJkMswtjksiTwZo1nYTS3JsIw==} + engines: {node: '>=18'} + + '@sentry-internal/replay@9.8.0': + resolution: {integrity: sha512-YJhhNnrsufYVIX9s5lNSFFQrBJjUtn5AxvrcnN0fvLymNg3Y73GOUpFmhTxyELjQneKiOViClxjoWSVAN7sqQA==} + engines: {node: '>=18'} + + '@sentry/browser@9.8.0': + resolution: {integrity: sha512-iFM4PGLc6qCb0GaHnA5Uy09k25RXVSepAgS574cm1CH7II1wrRjTozKnPKROW89WDMuxoTOL7Tk7qPGCyWmA4g==} + engines: {node: '>=18'} + '@sentry/core@8.55.0': resolution: {integrity: sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==} engines: {node: '>=14.18'} + '@sentry/core@9.8.0': + resolution: {integrity: sha512-EnN2yLWCbWjooWBPzwlXdZoJG/Bqn3ymbuXX++DUJuBGjSmtixQeTf/hKeVzj4zbib3BbbYsNBasRVjq8Rk5ng==} + engines: {node: '>=18'} + '@sentry/node@8.55.0': resolution: {integrity: sha512-h10LJLDTRAzYgay60Oy7moMookqqSZSviCWkkmHZyaDn+4WURnPp5SKhhfrzPRQcXKrweiOwDSHBgn1tweDssg==} engines: {node: '>=14.18'} @@ -3579,6 +3609,16 @@ packages: engines: {node: '>=14.18'} hasBin: true + '@sentry/vue@9.8.0': + resolution: {integrity: sha512-E+27lL+aU8HjDo3DD3TlgStTIxBZHVqz6jZcL0/tig/JldpFRetO77terRHNfSVlPc0m3aNXuARu7G438f7ZlQ==} + engines: {node: '>=18'} + peerDependencies: + pinia: 2.x || 3.x + vue: 2.x || 3.x + peerDependenciesMeta: + pinia: + optional: true + '@shikijs/core@3.2.1': resolution: {integrity: sha512-FhsdxMWYu/C11sFisEp7FMGBtX/OSSbnXZDMBhGuUDBNTdsoZlMSgQv5f90rwvzWAdWIW6VobD+G3IrazxA6dQ==} @@ -13629,8 +13669,36 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} + '@sentry-internal/browser-utils@9.8.0': + dependencies: + '@sentry/core': 9.8.0 + + '@sentry-internal/feedback@9.8.0': + dependencies: + '@sentry/core': 9.8.0 + + '@sentry-internal/replay-canvas@9.8.0': + dependencies: + '@sentry-internal/replay': 9.8.0 + '@sentry/core': 9.8.0 + + '@sentry-internal/replay@9.8.0': + dependencies: + '@sentry-internal/browser-utils': 9.8.0 + '@sentry/core': 9.8.0 + + '@sentry/browser@9.8.0': + dependencies: + '@sentry-internal/browser-utils': 9.8.0 + '@sentry-internal/feedback': 9.8.0 + '@sentry-internal/replay': 9.8.0 + '@sentry-internal/replay-canvas': 9.8.0 + '@sentry/core': 9.8.0 + '@sentry/core@8.55.0': {} + '@sentry/core@9.8.0': {} + '@sentry/node@8.55.0': dependencies: '@opentelemetry/api': 1.9.0 @@ -13690,6 +13758,12 @@ snapshots: transitivePeerDependencies: - supports-color + '@sentry/vue@9.8.0(vue@3.5.13(typescript@5.8.2))': + dependencies: + '@sentry/browser': 9.8.0 + '@sentry/core': 9.8.0 + vue: 3.5.13(typescript@5.8.2) + '@shikijs/core@3.2.1': dependencies: '@shikijs/types': 3.2.1 From 98eadd709364a11f039a8d45a2498ec6c8226c46 Mon Sep 17 00:00:00 2001 From: "Nanashi." Date: Wed, 2 Apr 2025 16:01:24 +0900 Subject: [PATCH 014/190] =?UTF-8?q?feat:=20=E3=82=A2=E3=83=B3=E3=83=86?= =?UTF-8?q?=E3=83=8A=E3=81=A7=E3=82=BB=E3=83=B3=E3=82=B7=E3=83=86=E3=82=A3?= =?UTF-8?q?=E3=83=96=E3=81=AA=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=88=E3=82=92?= =?UTF-8?q?=E9=99=A4=E5=A4=96=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=20(#15346)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(db): マイグレーションを追加 * feat(backend): カラムの定義を追加 * wip * feat: フラグを設定出来るように * feat: /notesエンドポイントを対応 * feat: websocketを対応 * test: テストを追加 * docs: CHANGELOGを更新 * docs: CHANGELOGの追加場所を修正 * chore: api.jsonを更新 * docs(CHANGELOG): General欄に移動 * docs: フォーマットを揃える * chore: クエリを削除 * revert: 英訳を消す * chore: note.channelを追加するところを変える * docs: CHANGELOGを更新する * docs(CHANGELOG): 2025.3.2に移動 * chore: changelogを下に移動 * ci: CI再実行用の空コミット --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + locales/index.d.ts | 4 ++ locales/ja-JP.yml | 1 + ...3-addAntennaHideNotesInSensitiveChannel.js | 16 ++++++++ packages/backend/src/core/AntennaService.ts | 2 + .../backend/src/core/NoteCreateService.ts | 5 ++- .../src/core/entities/AntennaEntityService.ts | 1 + packages/backend/src/models/Antenna.ts | 5 +++ .../backend/src/models/json-schema/antenna.ts | 5 +++ .../server/api/endpoints/antennas/create.ts | 2 + .../server/api/endpoints/antennas/notes.ts | 3 ++ .../server/api/endpoints/antennas/update.ts | 2 + packages/backend/test/e2e/antennas.ts | 39 +++++++++++++++++++ .../src/components/MkAntennaEditor.vue | 4 ++ packages/misskey-js/src/autogen/types.ts | 4 ++ 15 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 packages/backend/migration/1736230492103-addAntennaHideNotesInSensitiveChannel.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd0fbd8e9..32df3e3d91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - 外部サービスであるSentryへエラー情報が送信されます。ご利用の地域の法令に従い、適切なプライバシーポリシーを策定の上で運用してください。 - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように - Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 +- Enhance: アンテナでセンシティブなチャンネルのノートを除外できるように `#14177` ### Client - Feat: 設定の管理が強化されました diff --git a/locales/index.d.ts b/locales/index.d.ts index 177c9685a1..4741d37cc6 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1714,6 +1714,10 @@ export interface Locale extends ILocale { * ファイルが添付されたノートのみ */ "withFileAntenna": string; + /** + * センシティブなチャンネルのノートを非表示 + */ + "hideNotesInSensitiveChannel": string; /** * ブラウザへのプッシュ通知を有効にする */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 483ece655d..8b19ed9e48 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -424,6 +424,7 @@ antennaExcludeBots: "Botアカウントを除外" antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" notifyAntenna: "新しいノートを通知する" withFileAntenna: "ファイルが添付されたノートのみ" +hideNotesInSensitiveChannel: "センシティブなチャンネルのノートを非表示" enableServiceworker: "ブラウザへのプッシュ通知を有効にする" antennaUsersDescription: "ユーザー名を改行で区切って指定します" caseSensitive: "大文字小文字を区別する" diff --git a/packages/backend/migration/1736230492103-addAntennaHideNotesInSensitiveChannel.js b/packages/backend/migration/1736230492103-addAntennaHideNotesInSensitiveChannel.js new file mode 100644 index 0000000000..74225de96a --- /dev/null +++ b/packages/backend/migration/1736230492103-addAntennaHideNotesInSensitiveChannel.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AddAntennaHideNotesInSensitiveChannel1736230492103 { + name = 'AddAntennaHideNotesInSensitiveChannel1736230492103' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "antenna" ADD "hideNotesInSensitiveChannel" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "hideNotesInSensitiveChannel"`); + } +} diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index e827ffa68c..5ad5bcf72a 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -114,6 +114,8 @@ export class AntennaService implements OnApplicationShutdown { if (note.visibility === 'specified') return false; if (note.visibility === 'followers') return false; + if (antenna.hideNotesInSensitiveChannel && note.channel?.isSensitive) return false; + if (antenna.excludeBots && noteUser.isBot) return false; if (antenna.localOnly && noteUser.host != null) return false; diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 8f416f398c..1ddb2b173d 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -532,7 +532,10 @@ export class NoteCreateService implements OnApplicationShutdown { this.pushToTl(note, user); - this.antennaService.addNoteToAntennas(note, user); + this.antennaService.addNoteToAntennas({ + ...note, + channel: data.channel ?? null, + }, user); if (data.reply) { this.saveReply(data.reply, note); diff --git a/packages/backend/src/core/entities/AntennaEntityService.ts b/packages/backend/src/core/entities/AntennaEntityService.ts index e770028af3..e81c1e8db4 100644 --- a/packages/backend/src/core/entities/AntennaEntityService.ts +++ b/packages/backend/src/core/entities/AntennaEntityService.ts @@ -41,6 +41,7 @@ export class AntennaEntityService { excludeBots: antenna.excludeBots, withReplies: antenna.withReplies, withFile: antenna.withFile, + hideNotesInSensitiveChannel: antenna.hideNotesInSensitiveChannel, isActive: antenna.isActive, hasUnreadNote: false, // TODO notify: false, // 後方互換性のため diff --git a/packages/backend/src/models/Antenna.ts b/packages/backend/src/models/Antenna.ts index 33e6f48189..0d92c5cade 100644 --- a/packages/backend/src/models/Antenna.ts +++ b/packages/backend/src/models/Antenna.ts @@ -100,4 +100,9 @@ export class MiAntenna { default: false, }) public localOnly: boolean; + + @Column('boolean', { + default: false, + }) + public hideNotesInSensitiveChannel: boolean; } diff --git a/packages/backend/src/models/json-schema/antenna.ts b/packages/backend/src/models/json-schema/antenna.ts index b5b9a5b42c..2bdaca80d0 100644 --- a/packages/backend/src/models/json-schema/antenna.ts +++ b/packages/backend/src/models/json-schema/antenna.ts @@ -100,5 +100,10 @@ export const packedAntennaSchema = { optional: false, nullable: false, default: false, }, + hideNotesInSensitiveChannel: { + type: 'boolean', + optional: false, nullable: false, + default: false, + }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index e0c8ddcc84..9b34b52b16 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -73,6 +73,7 @@ export const paramDef = { excludeBots: { type: 'boolean' }, withReplies: { type: 'boolean' }, withFile: { type: 'boolean' }, + hideNotesInSensitiveChannel: { type: 'boolean' }, }, required: ['name', 'src', 'keywords', 'excludeKeywords', 'users', 'caseSensitive', 'withReplies', 'withFile'], } as const; @@ -133,6 +134,7 @@ export default class extends Endpoint { // eslint- excludeBots: ps.excludeBots, withReplies: ps.withReplies, withFile: ps.withFile, + hideNotesInSensitiveChannel: ps.hideNotesInSensitiveChannel, }); this.globalEventService.publishInternalEvent('antennaCreated', antenna); diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 4b8543c2d1..a44eb6720b 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -108,6 +108,9 @@ export default class extends Endpoint { // eslint- .leftJoinAndSelect('reply.user', 'replyUser') .leftJoinAndSelect('renote.user', 'renoteUser'); + // NOTE: センシティブ除外の設定はこのエンドポイントでは無視する。 + // https://github.com/misskey-dev/misskey/pull/15346#discussion_r1929950255 + this.queryService.generateVisibilityQuery(query, me); this.queryService.generateMutedUserQueryForNotes(query, me); this.queryService.generateBlockedUserQueryForNotes(query, me); diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts index 10f26b1912..c5ddefebf7 100644 --- a/packages/backend/src/server/api/endpoints/antennas/update.ts +++ b/packages/backend/src/server/api/endpoints/antennas/update.ts @@ -72,6 +72,7 @@ export const paramDef = { excludeBots: { type: 'boolean' }, withReplies: { type: 'boolean' }, withFile: { type: 'boolean' }, + hideNotesInSensitiveChannel: { type: 'boolean' }, }, required: ['antennaId'], } as const; @@ -129,6 +130,7 @@ export default class extends Endpoint { // eslint- excludeBots: ps.excludeBots, withReplies: ps.withReplies, withFile: ps.withFile, + hideNotesInSensitiveChannel: ps.hideNotesInSensitiveChannel, isActive: true, lastUsedAt: new Date(), }); diff --git a/packages/backend/test/e2e/antennas.ts b/packages/backend/test/e2e/antennas.ts index a544db955a..eb9583ee01 100644 --- a/packages/backend/test/e2e/antennas.ts +++ b/packages/backend/test/e2e/antennas.ts @@ -146,6 +146,7 @@ describe('アンテナ', () => { caseSensitive: false, createdAt: new Date(response.createdAt).toISOString(), excludeKeywords: [['']], + hideNotesInSensitiveChannel: false, hasUnreadNote: false, isActive: true, keywords: [['keyword']], @@ -217,6 +218,8 @@ describe('アンテナ', () => { { parameters: () => ({ withReplies: true }) }, { parameters: () => ({ withFile: false }) }, { parameters: () => ({ withFile: true }) }, + { parameters: () => ({ hideNotesInSensitiveChannel: false }) }, + { parameters: () => ({ hideNotesInSensitiveChannel: true }) }, ]; test.each(antennaParamPattern)('を作成できること($#)', async ({ parameters }) => { const response = await successfulApiCall({ @@ -626,6 +629,42 @@ describe('アンテナ', () => { assert.deepStrictEqual(response, expected); }); + test('が取得できること(センシティブチャンネルのノートを除く)', async () => { + const keyword = 'キーワード'; + const antenna = await successfulApiCall({ + endpoint: 'antennas/create', + parameters: { ...defaultParam, keywords: [[keyword]], hideNotesInSensitiveChannel: true }, + user: alice, + }); + const nonSensitiveChannel = await successfulApiCall({ + endpoint: 'channels/create', + parameters: { name: 'test', isSensitive: false }, + user: alice, + }); + const sensitiveChannel = await successfulApiCall({ + endpoint: 'channels/create', + parameters: { name: 'test', isSensitive: true }, + user: alice, + }); + + const noteInLocal = await post(bob, { text: `test ${keyword}` }); + const noteInNonSensitiveChannel = await post(bob, { text: `test ${keyword}`, channelId: nonSensitiveChannel.id }); + await post(bob, { text: `test ${keyword}`, channelId: sensitiveChannel.id }); + + const response = await successfulApiCall({ + endpoint: 'antennas/notes', + parameters: { antennaId: antenna.id }, + user: alice, + }); + // 最後に投稿したものが先頭に来る。 + const expected = [ + noteInNonSensitiveChannel, + noteInLocal, + ]; + assert.deepStrictEqual(response, expected); + }); + + test.skip('が取得でき、日付指定のPaginationに一貫性があること', async () => { }); test.each([ { label: 'ID指定', offsetBy: 'id' }, diff --git a/packages/frontend/src/components/MkAntennaEditor.vue b/packages/frontend/src/components/MkAntennaEditor.vue index ac71618ee2..e1c8200b73 100644 --- a/packages/frontend/src/components/MkAntennaEditor.vue +++ b/packages/frontend/src/components/MkAntennaEditor.vue @@ -39,6 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.localOnly }} {{ i18n.ts.caseSensitive }} {{ i18n.ts.withFileAntenna }} + {{ i18n.ts.hideNotesInSensitiveChannel }}
@@ -86,6 +87,7 @@ const initialAntenna = deepMerge(props.antenna ?? {}, { caseSensitive: false, localOnly: false, withFile: false, + hideNotesInSensitiveChannel: false, isActive: true, hasUnreadNote: false, notify: false, @@ -108,6 +110,7 @@ const localOnly = ref(initialAntenna.localOnly); const excludeBots = ref(initialAntenna.excludeBots); const withReplies = ref(initialAntenna.withReplies); const withFile = ref(initialAntenna.withFile); +const hideNotesInSensitiveChannel = ref(initialAntenna.hideNotesInSensitiveChannel); const userLists = ref(null); watch(() => src.value, async () => { @@ -124,6 +127,7 @@ async function saveAntenna() { excludeBots: excludeBots.value, withReplies: withReplies.value, withFile: withFile.value, + hideNotesInSensitiveChannel: hideNotesInSensitiveChannel.value, caseSensitive: caseSensitive.value, localOnly: localOnly.value, users: users.value.trim().split('\n').map(x => x.trim()), diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index ef4be07072..037b09660c 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4898,6 +4898,8 @@ export type components = { hasUnreadNote: boolean; /** @default false */ notify: boolean; + /** @default false */ + hideNotesInSensitiveChannel: boolean; }; Clip: { /** @@ -11305,6 +11307,7 @@ export type operations = { excludeBots?: boolean; withReplies: boolean; withFile: boolean; + hideNotesInSensitiveChannel?: boolean; }; }; }; @@ -11586,6 +11589,7 @@ export type operations = { excludeBots?: boolean; withReplies?: boolean; withFile?: boolean; + hideNotesInSensitiveChannel?: boolean; }; }; }; From 3a16af4b4b6881f880bf5d04ebd40404f4e87c62 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:01:48 +0900 Subject: [PATCH 015/190] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32df3e3d91..9f54948619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,8 @@ - `.config/default.yml`中の項目`sentryForFrontend`を適宜設定してください。 - 外部サービスであるSentryへエラー情報が送信されます。ご利用の地域の法令に従い、適切なプライバシーポリシーを策定の上で運用してください。 - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように -- Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 - Enhance: アンテナでセンシティブなチャンネルのノートを除外できるように `#14177` +- Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 ### Client - Feat: 設定の管理が強化されました From e1dc1e51110516a86a13fb4006660c19fb130399 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 19:16:16 +0900 Subject: [PATCH 016/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend-shared/themes/d-astro.json5 | 6 +++--- packages/frontend-shared/themes/d-botanical.json5 | 3 +++ packages/frontend-shared/themes/d-persimmon.json5 | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/frontend-shared/themes/d-astro.json5 b/packages/frontend-shared/themes/d-astro.json5 index 48839241bd..5e721534d3 100644 --- a/packages/frontend-shared/themes/d-astro.json5 +++ b/packages/frontend-shared/themes/d-astro.json5 @@ -7,9 +7,9 @@ bg: '#232125', fg: '#efdab9', link: '#78b0a0', - warn: '#ecb637', + warn: '#ffd152', badge: '#31b1ce', - error: '#ec4137', + error: '#ff6652', focus: ':alpha<0.3<@accent', navBg: '@panel', navFg: '@fg', @@ -24,7 +24,7 @@ hashtag: '#ff9156', mention: '#ffd152', modalBg: 'rgba(0, 0, 0, 0.5)', - success: '#86b300', + success: '#78b07f', indicator: '@accent', mentionMe: '#fb5d38', messageBg: '@bg', diff --git a/packages/frontend-shared/themes/d-botanical.json5 b/packages/frontend-shared/themes/d-botanical.json5 index 62208d2378..507880aab1 100644 --- a/packages/frontend-shared/themes/d-botanical.json5 +++ b/packages/frontend-shared/themes/d-botanical.json5 @@ -22,5 +22,8 @@ mentionMe: 'rgb(212, 210, 76)', hashtag: '#5bcbb0', link: '@accent', + success: '@accent', + warn: 'rgb(255, 213, 82)', + error: 'rgb(255, 105, 82)', }, } diff --git a/packages/frontend-shared/themes/d-persimmon.json5 b/packages/frontend-shared/themes/d-persimmon.json5 index 0ab6523dd7..538e3b7e70 100644 --- a/packages/frontend-shared/themes/d-persimmon.json5 +++ b/packages/frontend-shared/themes/d-persimmon.json5 @@ -22,5 +22,8 @@ mentionMe: '#de6161', hashtag: '#68bad0', link: '#a1c758', + error: '#ce5441', + warn: '#d0b868', + success: '#a1c758', }, } From d07552424c388b608882b42abb222058d0d6795a Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 2 Apr 2025 19:48:32 +0900 Subject: [PATCH 017/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/frontend/src/pages/clip.vue | 2 +- packages/frontend/src/pages/tag.vue | 2 +- packages/frontend/src/utility/get-note-menu.ts | 4 ++-- packages/frontend/src/utility/get-user-menu.ts | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 4741d37cc6..9ef4886cb5 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5378,6 +5378,10 @@ export interface Locale extends ILocale { * 上 */ "top": string; + /** + * 埋め込み + */ + "embed": string; "_chat": { /** * まだメッセージはありません diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 8b19ed9e48..947b7b4fa5 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1340,6 +1340,7 @@ compress: "圧縮" right: "右" bottom: "下" top: "上" +embed: "埋め込み" _chat: noMessagesYet: "まだメッセージはありません" diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue index 8fe65217fb..a2fb02462e 100644 --- a/packages/frontend/src/pages/clip.vue +++ b/packages/frontend/src/pages/clip.vue @@ -150,7 +150,7 @@ const headerActions = computed(() => clip.value && isOwned.value ? [{ }, }, { icon: 'ti ti-code', - text: i18n.ts.genEmbedCode, + text: i18n.ts.embed, action: () => { genEmbedCode('clips', clip.value!.id); }, diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue index 4afef6f4d7..f67777be4e 100644 --- a/packages/frontend/src/pages/tag.vue +++ b/packages/frontend/src/pages/tag.vue @@ -56,7 +56,7 @@ const headerActions = computed(() => [{ label: i18n.ts.more, handler: (ev: MouseEvent) => { os.popupMenu([{ - text: i18n.ts.genEmbedCode, + text: i18n.ts.embed, icon: 'ti ti-code', action: () => { genEmbedCode('tags', props.tag); diff --git a/packages/frontend/src/utility/get-note-menu.ts b/packages/frontend/src/utility/get-note-menu.ts index 9e1ae7e9ac..dd8bdf43d7 100644 --- a/packages/frontend/src/utility/get-note-menu.ts +++ b/packages/frontend/src/utility/get-note-menu.ts @@ -331,7 +331,7 @@ export function getNoteMenu(props: { }, }); } else { - menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode)); + menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.embed)); } if (isSupportShare()) { @@ -489,7 +489,7 @@ export function getNoteMenu(props: { }, }); } else { - menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.genEmbedCode)); + menuItems.push(getNoteEmbedCodeMenu(appearNote, i18n.ts.embed)); } } diff --git a/packages/frontend/src/utility/get-user-menu.ts b/packages/frontend/src/utility/get-user-menu.ts index 10429c8ff1..8cf9f31d3e 100644 --- a/packages/frontend/src/utility/get-user-menu.ts +++ b/packages/frontend/src/utility/get-user-menu.ts @@ -198,7 +198,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router } else { menuItems.push({ icon: 'ti ti-code', - text: i18n.ts.genEmbedCode, + text: i18n.ts.embed, type: 'parent', children: [{ text: i18n.ts.noteOfThisUser, From 1a3866c4f67fb5a745a7966220286680b810d23b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:15:16 +0900 Subject: [PATCH 018/190] =?UTF-8?q?fix(backend/chat):=20=E8=87=AA=E5=88=86?= =?UTF-8?q?=E3=81=8C=E4=BD=9C=E3=81=A3=E3=81=9F=E3=83=81=E3=83=A3=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=83=AB=E3=83=BC=E3=83=A0=E3=81=AB=E4=BB=96=E4=BA=BA?= =?UTF-8?q?=E3=81=8C=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E9=80=81=E3=81=A3=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AB=E6=9C=AA?= =?UTF-8?q?=E8=AA=AD=E3=81=AB=E3=81=AA=E3=82=89=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #15748 --- packages/backend/src/core/ChatService.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index df1c384b54..6194f624b1 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -211,9 +211,15 @@ export class ChatService { file?: MiDriveFile | null; uri?: string | null; }): Promise> { - const memberships = await this.chatRoomMembershipsRepository.findBy({ roomId: toRoom.id }); + const memberships = (await this.chatRoomMembershipsRepository.findBy({ roomId: toRoom.id })).map(m => ({ + userId: m.userId, + isMuted: m.isMuted, + })).concat({ // ownerはmembershipレコードを作らないため + userId: toRoom.ownerId, + isMuted: false, + }); - if (toRoom.ownerId !== fromUser.id && !memberships.some(member => member.userId === fromUser.id)) { + if (!memberships.some(member => member.userId === fromUser.id)) { throw new Error('you are not a member of the room'); } From 455be80b4f7ff04a71d1773b2ec058adb3af3e69 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:32:55 +0900 Subject: [PATCH 019/190] =?UTF-8?q?fix(backend):=20=E9=9D=9E=E3=83=AD?= =?UTF-8?q?=E3=82=B0=E3=82=A4=E3=83=B3=E3=81=A7=E3=82=BF=E3=82=A4=E3=83=A0?= =?UTF-8?q?=E3=83=A9=E3=82=A4=E3=83=B3=E3=81=AE=E3=82=B9=E3=83=88=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=81=AB=E6=8E=A5=E7=B6=9A=E3=81=97=E3=81=9F?= =?UTF-8?q?=E9=9A=9B=E3=80=81=E8=A1=A8=E7=A4=BA=E3=81=AB=E3=83=AD=E3=82=B0?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E5=BF=85=E9=A0=88=E3=81=AE=E3=83=8E=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=8C=E6=B5=81=E3=82=8C=E3=82=8B=E5=A0=B4=E5=90=88?= =?UTF-8?q?=E3=81=8C=E3=81=82=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../backend/src/server/api/stream/channels/global-timeline.ts | 1 + .../backend/src/server/api/stream/channels/local-timeline.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f54948619..9da5e9bb2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ - Fix: ActivityPubリクエストURLチェック実装は仕様に従っていないのを修正 - Fix: 連合無しモードでも外部から照会可能だった問題を修正 - Fix: テスト用WebHookのペイロードの`emojis`パラメータが実際のものと異なる問題を修正 +- Fix: 非ログインでタイムラインのストリームに接続した際、表示にログイン必須のノートが流れる場合がある問題を修正 ## 2025.3.1 diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index ed56fe0d40..4f64ce6866 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -50,6 +50,7 @@ class GlobalTimelineChannel extends Channel { if (note.visibility !== 'public') return; if (note.channelId != null) return; + if (note.user.requireSigninToViewContents && this.user == null) return; if (isRenotePacked(note) && !isQuotePacked(note) && !this.withRenotes) return; diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 491029f5de..c3cf78a24a 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -53,6 +53,7 @@ class LocalTimelineChannel extends Channel { if (note.user.host !== null) return; if (note.visibility !== 'public') return; if (note.channelId != null) return; + if (note.user.requireSigninToViewContents && this.user == null) return; // 関係ない返信は除外 if (note.reply && this.user && !this.following[note.userId]?.withReplies && !this.withReplies) { From d7365eb12659f0d681ec645aaedd5d962aed8b9b Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Thu, 3 Apr 2025 12:54:08 +0900 Subject: [PATCH 020/190] fix(storybook): update obsolete method for preferences (#15750) --- packages/frontend/.storybook/preview.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts index 269bc4fb9a..fb855c1410 100644 --- a/packages/frontend/.storybook/preview.ts +++ b/packages/frontend/.storybook/preview.ts @@ -83,7 +83,7 @@ queueMicrotask(() => { widgets(app); misskeyOS = os; if (isChromatic()) { - prefer.set('animation', false); + prefer.commit('animation', false); } }); }); From 1779a23e25e5ba3fad076272d6757ea4d1a3cf16 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:31:13 +0900 Subject: [PATCH 021/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend-shared/themes/l-botanical.json5 | 8 ++++---- packages/frontend-shared/themes/l-coffee.json5 | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/frontend-shared/themes/l-botanical.json5 b/packages/frontend-shared/themes/l-botanical.json5 index 17e9ca246f..4ad539e8a0 100644 --- a/packages/frontend-shared/themes/l-botanical.json5 +++ b/packages/frontend-shared/themes/l-botanical.json5 @@ -13,18 +13,18 @@ fgHighlighted: '#6bc9a0', fgOnWhite: '@accent', divider: '#cfcfcf', - panel: '@X14', + panel: '#ebe7e5', panelHeaderBg: '@panel', panelHeaderDivider: '@divider', header: ':alpha<0.7<@panel', - navBg: '@X14', + navBg: '#ebe7e5', renote: '#229e92', mention: '#da6d35', mentionMe: '#d44c4c', hashtag: '#4cb8d4', link: '@accent', buttonGradateB: ':hue<-70<@accent', - success: '#86b300', - X14: '#ebe7e5' + success: '@accent', + error: '#da5635', }, } diff --git a/packages/frontend-shared/themes/l-coffee.json5 b/packages/frontend-shared/themes/l-coffee.json5 index b64cc73583..df3a12a37b 100644 --- a/packages/frontend-shared/themes/l-coffee.json5 +++ b/packages/frontend-shared/themes/l-coffee.json5 @@ -18,5 +18,8 @@ mention: '@accent', mentionMe: 'rgb(170, 149, 98)', hashtag: '@accent', + error: '#db9184', + warn: '#dbc184', + success: '#a3c975', }, } From 7cecaa5c54797b6b089b2e58a8f7bd08540f3eac Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 3 Apr 2025 14:32:42 +0900 Subject: [PATCH 022/190] perf(frontend): avoid main thread scroll repaint --- packages/frontend/src/components/MkContainer.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/frontend/src/components/MkContainer.vue b/packages/frontend/src/components/MkContainer.vue index 39ca39aad7..29165d7b71 100644 --- a/packages/frontend/src/components/MkContainer.vue +++ b/packages/frontend/src/components/MkContainer.vue @@ -215,6 +215,14 @@ onUnmounted(() => { .content { --MI-stickyTop: 0px; + /* + 理屈は知らないけど、ここでbackgroundを設定しておかないと + スクロールコンテナーが少なくともChromeにおいて + main thread scrolling になってしまい、パフォーマンスが(多分)落ちる。 + backgroundが透明だと裏側を描画しないといけなくなるとかそういう理由かもしれない + */ + background: var(--MI_THEME-panel); + &.omitted { position: relative; max-height: var(--maxHeight); From e07bb1dcbce6eaa2bfe157a6c9f1361dbf9aa280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:28:10 +0900 Subject: [PATCH 023/190] =?UTF-8?q?fix:=20=E3=83=81=E3=83=A3=E3=83=83?= =?UTF-8?q?=E3=83=88=E5=91=A8=E3=82=8A=E3=81=AE=E4=BF=AE=E6=AD=A3=20(#1574?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(misskey-js): チャットのChannel型定義を追加 * fix(backend); canChatで塞いでいない書き込み系のAPIを塞ぐ * fix(frontend): チャット周りのフロントエンド型修正 * lint fix * fix broken lockfile * fix * refactor * wip * wip * wip * clean up --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- packages/backend/src/core/ChatService.ts | 4 +- .../src/core/entities/ChatEntityService.ts | 8 +- packages/backend/src/misc/json-schema.ts | 4 +- .../src/models/json-schema/chat-message.ts | 112 +++++++++++++++++- .../endpoints/chat/messages/create-to-room.ts | 2 +- .../endpoints/chat/messages/create-to-user.ts | 2 +- .../api/endpoints/chat/messages/delete.ts | 1 + .../api/endpoints/chat/messages/react.ts | 1 + .../endpoints/chat/messages/room-timeline.ts | 2 +- .../api/endpoints/chat/messages/unreact.ts | 1 + .../endpoints/chat/messages/user-timeline.ts | 2 +- packages/frontend/src/pages/chat/XMessage.vue | 62 +++++----- .../frontend/src/pages/chat/home.home.vue | 4 +- .../src/pages/chat/home.invitations.vue | 9 +- .../src/pages/chat/home.joiningRooms.vue | 15 +-- .../src/pages/chat/home.ownedRooms.vue | 10 +- packages/frontend/src/pages/chat/home.vue | 2 +- packages/frontend/src/pages/chat/message.vue | 10 +- .../frontend/src/pages/chat/room.form.vue | 21 +++- .../frontend/src/pages/chat/room.info.vue | 5 +- .../frontend/src/pages/chat/room.members.vue | 5 +- .../frontend/src/pages/chat/room.search.vue | 3 +- packages/frontend/src/pages/chat/room.vue | 97 +++++++++------ .../frontend/src/use/use-mutation-observer.ts | 4 +- packages/misskey-js/etc/misskey-js.api.md | 60 +++++++++- packages/misskey-js/src/autogen/models.ts | 2 + packages/misskey-js/src/autogen/types.ts | 42 +++++-- packages/misskey-js/src/streaming.types.ts | 51 +++++++- pnpm-lock.yaml | 65 +++++++--- 29 files changed, 453 insertions(+), 153 deletions(-) diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index 6194f624b1..3984cefc80 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -99,7 +99,7 @@ export class ChatService { text?: string | null; file?: MiDriveFile | null; uri?: string | null; - }): Promise> { + }): Promise> { if (fromUser.id === toUser.id) { throw new Error('yourself'); } @@ -210,7 +210,7 @@ export class ChatService { text?: string | null; file?: MiDriveFile | null; uri?: string | null; - }): Promise> { + }): Promise> { const memberships = (await this.chatRoomMembershipsRepository.findBy({ roomId: toRoom.id })).map(m => ({ userId: m.userId, isMuted: m.isMuted, diff --git a/packages/backend/src/core/entities/ChatEntityService.ts b/packages/backend/src/core/entities/ChatEntityService.ts index 099a9e3ad2..da112d5444 100644 --- a/packages/backend/src/core/entities/ChatEntityService.ts +++ b/packages/backend/src/core/entities/ChatEntityService.ts @@ -128,7 +128,7 @@ export class ChatEntityService { packedFiles: Map | null>; }; }, - ): Promise> { + ): Promise> { const packedFiles = options?._hint_?.packedFiles; const message = typeof src === 'object' ? src : await this.chatMessagesRepository.findOneByOrFail({ id: src }); @@ -147,7 +147,7 @@ export class ChatEntityService { createdAt: this.idService.parse(message.id).date.toISOString(), text: message.text, fromUserId: message.fromUserId, - toUserId: message.toUserId, + toUserId: message.toUserId!, fileId: message.fileId, file: message.fileId ? (packedFiles?.get(message.fileId) ?? await this.driveFileEntityService.pack(message.file ?? message.fileId)) : null, reactions, @@ -177,7 +177,7 @@ export class ChatEntityService { packedUsers: Map>; }; }, - ): Promise> { + ): Promise> { const packedFiles = options?._hint_?.packedFiles; const packedUsers = options?._hint_?.packedUsers; @@ -199,7 +199,7 @@ export class ChatEntityService { text: message.text, fromUserId: message.fromUserId, fromUser: packedUsers?.get(message.fromUserId) ?? await this.userEntityService.pack(message.fromUser ?? message.fromUserId), - toRoomId: message.toRoomId, + toRoomId: message.toRoomId!, fileId: message.fileId, file: message.fileId ? (packedFiles?.get(message.fileId) ?? await this.driveFileEntityService.pack(message.file ?? message.fileId)) : null, reactions, diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index bc9308ca9b..27aa3d89de 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -63,7 +63,7 @@ import { } from '@/models/json-schema/meta.js'; import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js'; import { packedAbuseReportNotificationRecipientSchema } from '@/models/json-schema/abuse-report-notification-recipient.js'; -import { packedChatMessageSchema, packedChatMessageLiteSchema } from '@/models/json-schema/chat-message.js'; +import { packedChatMessageSchema, packedChatMessageLiteSchema, packedChatMessageLiteForRoomSchema, packedChatMessageLiteFor1on1Schema } from '@/models/json-schema/chat-message.js'; import { packedChatRoomSchema } from '@/models/json-schema/chat-room.js'; import { packedChatRoomInvitationSchema } from '@/models/json-schema/chat-room-invitation.js'; import { packedChatRoomMembershipSchema } from '@/models/json-schema/chat-room-membership.js'; @@ -126,6 +126,8 @@ export const refs = { AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema, ChatMessage: packedChatMessageSchema, ChatMessageLite: packedChatMessageLiteSchema, + ChatMessageLiteFor1on1: packedChatMessageLiteFor1on1Schema, + ChatMessageLiteForRoom: packedChatMessageLiteForRoomSchema, ChatRoom: packedChatRoomSchema, ChatRoomInvitation: packedChatRoomInvitationSchema, ChatRoomMembership: packedChatRoomMembershipSchema, diff --git a/packages/backend/src/models/json-schema/chat-message.ts b/packages/backend/src/models/json-schema/chat-message.ts index 44b7298702..3b5e85ab69 100644 --- a/packages/backend/src/models/json-schema/chat-message.ts +++ b/packages/backend/src/models/json-schema/chat-message.ts @@ -72,7 +72,7 @@ export const packedChatMessageSchema = { }, user: { type: 'object', - optional: true, nullable: true, + optional: false, nullable: false, ref: 'UserLite', }, }, @@ -144,3 +144,113 @@ export const packedChatMessageLiteSchema = { }, }, } as const; + +export const packedChatMessageLiteFor1on1Schema = { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + }, + createdAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: false, + }, + fromUserId: { + type: 'string', + optional: false, nullable: false, + }, + toUserId: { + type: 'string', + optional: false, nullable: false, + }, + text: { + type: 'string', + optional: true, nullable: true, + }, + fileId: { + type: 'string', + optional: true, nullable: true, + }, + file: { + type: 'object', + optional: true, nullable: true, + ref: 'DriveFile', + }, + reactions: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + properties: { + reaction: { + type: 'string', + optional: false, nullable: false, + }, + }, + }, + }, + }, +} as const; + +export const packedChatMessageLiteForRoomSchema = { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + }, + createdAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: false, + }, + fromUserId: { + type: 'string', + optional: false, nullable: false, + }, + fromUser: { + type: 'object', + optional: false, nullable: false, + ref: 'UserLite', + }, + toRoomId: { + type: 'string', + optional: false, nullable: false, + }, + text: { + type: 'string', + optional: true, nullable: true, + }, + fileId: { + type: 'string', + optional: true, nullable: true, + }, + file: { + type: 'object', + optional: true, nullable: true, + ref: 'DriveFile', + }, + reactions: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + properties: { + reaction: { + type: 'string', + optional: false, nullable: false, + }, + user: { + type: 'object', + optional: false, nullable: false, + ref: 'UserLite', + }, + }, + }, + }, + }, +} as const; diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts index 1f334d5750..a988dc60b9 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts @@ -30,7 +30,7 @@ export const meta = { res: { type: 'object', optional: false, nullable: false, - ref: 'ChatMessageLite', + ref: 'ChatMessageLiteForRoom', }, errors: { diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts index 6b77a026fb..bbaab8a6c3 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts @@ -30,7 +30,7 @@ export const meta = { res: { type: 'object', optional: false, nullable: false, - ref: 'ChatMessageLite', + ref: 'ChatMessageLiteFor1on1', }, errors: { diff --git a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts index 959599ddcf..25fc774d4f 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts @@ -13,6 +13,7 @@ export const meta = { tags: ['chat'], requireCredential: true, + requiredRolePolicy: 'canChat', kind: 'write:chat', diff --git a/packages/backend/src/server/api/endpoints/chat/messages/react.ts b/packages/backend/src/server/api/endpoints/chat/messages/react.ts index 561e36ed19..0145e380be 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/react.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/react.ts @@ -13,6 +13,7 @@ export const meta = { tags: ['chat'], requireCredential: true, + requiredRolePolicy: 'canChat', kind: 'write:chat', diff --git a/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts b/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts index 7aef35db04..b6d3356196 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts @@ -23,7 +23,7 @@ export const meta = { items: { type: 'object', optional: false, nullable: false, - ref: 'ChatMessageLite', + ref: 'ChatMessageLiteForRoom', }, }, diff --git a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts index 4eb25259fb..b97bad8a9c 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts @@ -13,6 +13,7 @@ export const meta = { tags: ['chat'], requireCredential: true, + requiredRolePolicy: 'canChat', kind: 'write:chat', diff --git a/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts b/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts index 9d308d79b0..a35f121bb1 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts @@ -24,7 +24,7 @@ export const meta = { items: { type: 'object', optional: false, nullable: false, - ref: 'ChatMessageLite', + ref: 'ChatMessageLiteFor1on1', }, }, diff --git a/packages/frontend/src/pages/chat/XMessage.vue b/packages/frontend/src/pages/chat/XMessage.vue index 33741b1845..eb8b0d79ee 100644 --- a/packages/frontend/src/pages/chat/XMessage.vue +++ b/packages/frontend/src/pages/chat/XMessage.vue @@ -5,33 +5,28 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/utility/timeline-date-separate.ts b/packages/frontend/src/utility/timeline-date-separate.ts new file mode 100644 index 0000000000..f9876a20ff --- /dev/null +++ b/packages/frontend/src/utility/timeline-date-separate.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { computed } from 'vue'; +import type { Ref } from 'vue'; + +function getDateText(dateInstance: Date) { + const date = dateInstance.getDate(); + const month = dateInstance.getMonth() + 1; + return `${month.toString()}/${date.toString()}`; +} + +export type DateSeparetedTimelineItem = { + id: string; + type: 'item'; + data: T; +} | { + id: string; + type: 'date'; + prev: Date; + prevText: string; + next: Date; + nextText: string; +}; + +export function makeDateSeparatedTimelineComputedRef(items: Ref) { + return computed[]>(() => { + const tl: DateSeparetedTimelineItem[] = []; + for (let i = 0; i < items.value.length; i++) { + const item = items.value[i]; + + const date = new Date(item.createdAt); + const nextDate = items.value[i + 1] ? new Date(items.value[i + 1].createdAt) : null; + + tl.push({ + id: item.id, + type: 'item', + data: item, + }); + + if ( + i !== items.value.length - 1 && + nextDate != null && ( + date.getFullYear() !== nextDate.getFullYear() || + date.getMonth() !== nextDate.getMonth() || + date.getDate() !== nextDate.getDate() + ) + ) { + tl.push({ + id: `date-${item.id}`, + type: 'date', + prev: date, + prevText: getDateText(date), + next: nextDate, + nextText: getDateText(nextDate), + }); + } + } + return tl; + }); +} From 440a4a4d8bf6b9e11d25218af65348f9a0cab176 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:42:25 +0900 Subject: [PATCH 026/190] refactor(frontend): refactor MkDateSeparatedList --- .../frontend/src/components/MkDateSeparatedList.vue | 13 +++---------- .../frontend/src/utility/timeline-date-separate.ts | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/components/MkDateSeparatedList.vue b/packages/frontend/src/components/MkDateSeparatedList.vue index ec6fcdc311..1cf6f0b744 100644 --- a/packages/frontend/src/components/MkDateSeparatedList.vue +++ b/packages/frontend/src/components/MkDateSeparatedList.vue @@ -3,16 +3,18 @@ SPDX-FileCopyrightText: syuilo and misskey-project SPDX-License-Identifier: AGPL-3.0-only --> + + + + diff --git a/packages/frontend/src/components/index.ts b/packages/frontend/src/components/index.ts index 6c6903c3a4..34cf598b84 100644 --- a/packages/frontend/src/components/index.ts +++ b/packages/frontend/src/components/index.ts @@ -30,6 +30,7 @@ import PageWithAnimBg from './global/PageWithAnimBg.vue'; import SearchMarker from './global/SearchMarker.vue'; import SearchLabel from './global/SearchLabel.vue'; import SearchKeyword from './global/SearchKeyword.vue'; +import SearchIcon from './global/SearchIcon.vue'; import type { App } from 'vue'; @@ -67,6 +68,7 @@ export const components = { SearchMarker: SearchMarker, SearchLabel: SearchLabel, SearchKeyword: SearchKeyword, + SearchIcon: SearchIcon, }; declare module '@vue/runtime-core' { @@ -98,5 +100,6 @@ declare module '@vue/runtime-core' { SearchMarker: typeof SearchMarker; SearchLabel: typeof SearchLabel; SearchKeyword: typeof SearchKeyword; + SearchIcon: typeof SearchIcon; } } diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index 58fcb0c5e0..d97ea6e459 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -58,7 +58,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -81,7 +81,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -100,7 +100,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue index 86ae8af213..647fed10e3 100644 --- a/packages/frontend/src/pages/settings/preferences.vue +++ b/packages/frontend/src/pages/settings/preferences.vue @@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -279,7 +279,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -341,7 +341,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -382,7 +382,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -421,7 +421,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -531,7 +531,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
@@ -567,7 +567,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
{{ i18n.ts.reloadRequiredToApplySettings }} @@ -601,7 +601,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
From 154b89f07a67909f2dae360c0d63f2e125808366 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:16:08 +0900 Subject: [PATCH 046/190] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/ui/deck.vue | 8 ++++---- packages/frontend/src/ui/universal.vue | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index bf39c07229..422b00e9c2 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
Date: Mon, 7 Apr 2025 08:17:46 +0000 Subject: [PATCH 047/190] Bump version to 2025.4.0-rc.2 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5b45b999f3..879bf1d029 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.0-rc.1", + "version": "2025.4.0-rc.2", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 7e92981230..7ab4cb8914 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.0-rc.1", + "version": "2025.4.0-rc.2", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From 6c27ab12ebcf0dba20055f4cf79d923f79c6da76 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:30:44 +0900 Subject: [PATCH 048/190] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 434a18442a..2f1e08f2c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - 再度ログインすればサーバーのバックアップから設定データを復元可能です - エクスポートした設定データを他のサーバーでインポートして適用すること(設定の持ち運び)が可能になりました - 設定情報の移行は自動で行われますが、何らかの理由で失敗した場合、設定→その他→旧設定情報を移行 で再試行可能です + - 過去に作成されたバックアップデータとは現在互換性がありませんのでご注意ください - Feat: 画面を重ねて表示するオプションを実装(実験的) - 設定 → その他 → 実験的機能 → Enable stacking router view - Enhance: プラグインの管理が強化されました From 9d3f3264fdd059f47537da48fd125cdd2f4bad1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Mon, 7 Apr 2025 19:09:11 +0900 Subject: [PATCH 049/190] =?UTF-8?q?enhance:=20=E3=83=81=E3=83=A3=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=81=AE=E9=96=B2=E8=A6=A7=E3=82=92=E7=84=A1=E5=8A=B9?= =?UTF-8?q?=E5=8C=96=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=20(#15765)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance: チャットの閲覧を無効化できるように * fix * fix * fix * readonlyの説明を追加 * enhance: チャットが無効な場合はチャット関連の設定も隠すように * fix * refactor: ChatServiceからApiに関するドメイン知識を排除 --- locales/index.d.ts | 10 ++- locales/ja-JP.yml | 4 +- packages/backend/src/core/ChatService.ts | 36 +++++++- packages/backend/src/core/RoleService.ts | 12 ++- .../src/core/entities/UserEntityService.ts | 2 +- .../backend/src/models/json-schema/role.ts | 5 +- .../src/server/api/endpoints/chat/history.ts | 2 + .../endpoints/chat/messages/create-to-room.ts | 3 +- .../endpoints/chat/messages/create-to-user.ts | 3 +- .../api/endpoints/chat/messages/delete.ts | 3 +- .../api/endpoints/chat/messages/react.ts | 3 +- .../endpoints/chat/messages/room-timeline.ts | 2 + .../api/endpoints/chat/messages/search.ts | 2 + .../api/endpoints/chat/messages/show.ts | 2 + .../api/endpoints/chat/messages/unreact.ts | 3 +- .../endpoints/chat/messages/user-timeline.ts | 2 + .../server/api/endpoints/chat/rooms/create.ts | 3 +- .../server/api/endpoints/chat/rooms/delete.ts | 2 + .../chat/rooms/invitations/create.ts | 3 +- .../chat/rooms/invitations/ignore.ts | 2 + .../endpoints/chat/rooms/invitations/inbox.ts | 2 + .../chat/rooms/invitations/outbox.ts | 2 + .../server/api/endpoints/chat/rooms/join.ts | 2 + .../api/endpoints/chat/rooms/joining.ts | 2 + .../server/api/endpoints/chat/rooms/leave.ts | 2 + .../api/endpoints/chat/rooms/members.ts | 2 + .../server/api/endpoints/chat/rooms/mute.ts | 2 + .../server/api/endpoints/chat/rooms/owned.ts | 2 + .../server/api/endpoints/chat/rooms/show.ts | 2 + .../server/api/endpoints/chat/rooms/update.ts | 2 + packages/frontend-shared/js/const.ts | 2 +- packages/frontend/src/navbar.ts | 1 + .../frontend/src/pages/admin/roles.editor.vue | 21 +++-- packages/frontend/src/pages/admin/roles.vue | 14 +-- packages/frontend/src/pages/chat/XMessage.vue | 10 +-- .../frontend/src/pages/chat/home.home.vue | 4 +- packages/frontend/src/pages/chat/room.vue | 90 ++++++++++--------- .../src/pages/settings/preferences.vue | 75 ++++++++-------- .../frontend/src/pages/settings/privacy.vue | 33 ++++--- packages/frontend/src/router.definition.ts | 12 ++- .../frontend/src/utility/get-user-menu.ts | 2 +- packages/misskey-js/src/autogen/types.ts | 3 +- 42 files changed, 255 insertions(+), 136 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index c157cb2a1f..4341828481 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5386,6 +5386,10 @@ export interface Locale extends ILocale { * 設定を移行しています。しばらくお待ちください... (後ほど、設定→その他→旧設定情報を移行 で手動で移行することもできます) */ "settingsMigrating": string; + /** + * 読み取り専用 + */ + "readonly": string; "_chat": { /** * まだメッセージはありません @@ -5500,6 +5504,10 @@ export interface Locale extends ILocale { * このサーバー、またはこのアカウントでチャットは有効化されていません。 */ "chatNotAvailableForThisAccountOrServer": string; + /** + * このサーバー、またはこのアカウントでチャットは読み取り専用となっています。新たに書き込んだり、チャットルームを作成・参加したりすることはできません。 + */ + "chatIsReadOnlyForThisAccountOrServer": string; /** * 相手のアカウントでチャット機能が使えない状態になっています。 */ @@ -7531,7 +7539,7 @@ export interface Locale extends ILocale { /** * チャットを許可 */ - "canChat": string; + "chatAvailability": string; }; "_condition": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b0084dc440..0d34bbc1ca 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1342,6 +1342,7 @@ bottom: "下" top: "上" embed: "埋め込み" settingsMigrating: "設定を移行しています。しばらくお待ちください... (後ほど、設定→その他→旧設定情報を移行 で手動で移行することもできます)" +readonly: "読み取り専用" _chat: noMessagesYet: "まだメッセージはありません" @@ -1372,6 +1373,7 @@ _chat: muteThisRoom: "このルームをミュート" deleteRoom: "ルームを削除" chatNotAvailableForThisAccountOrServer: "このサーバー、またはこのアカウントでチャットは有効化されていません。" + chatIsReadOnlyForThisAccountOrServer: "このサーバー、またはこのアカウントでチャットは読み取り専用となっています。新たに書き込んだり、チャットルームを作成・参加したりすることはできません。" chatNotAvailableInOtherAccount: "相手のアカウントでチャット機能が使えない状態になっています。" cannotChatWithTheUser: "このユーザーとのチャットを開始できません" cannotChatWithTheUser_description: "チャットが使えない状態になっているか、相手がチャットを開放していません。" @@ -1950,7 +1952,7 @@ _role: canImportFollowing: "フォローのインポートを許可" canImportMuting: "ミュートのインポートを許可" canImportUserLists: "リストのインポートを許可" - canChat: "チャットを許可" + chatAvailability: "チャットを許可" _condition: roleAssignedTo: "マニュアルロールにアサイン済み" isLocal: "ローカルユーザー" diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index 3984cefc80..b0e8cfb61c 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -94,6 +94,40 @@ export class ChatService { ) { } + @bindThis + public async getChatAvailability(userId: MiUser['id']): Promise<{ read: boolean; write: boolean; }> { + const policies = await this.roleService.getUserPolicies(userId); + + switch (policies.chatAvailability) { + case 'available': + return { + read: true, + write: true, + }; + case 'readonly': + return { + read: true, + write: false, + }; + case 'unavailable': + return { + read: false, + write: false, + }; + default: + throw new Error('invalid chat availability (unreachable)'); + } + } + + /** getChatAvailabilityの糖衣。主にAPI呼び出し時に走らせて、権限的に問題ない場合はそのまま続行する */ + @bindThis + public async checkChatAvailability(userId: MiUser['id'], permission: 'read' | 'write') { + const policy = await this.getChatAvailability(userId); + if (policy[permission] === false) { + throw new Error('ROLE_PERMISSION_DENIED'); + } + } + @bindThis public async createMessageToUser(fromUser: { id: MiUser['id']; host: MiUser['host']; }, toUser: MiUser, params: { text?: string | null; @@ -140,7 +174,7 @@ export class ChatService { } } - if (!(await this.roleService.getUserPolicies(toUser.id)).canChat) { + if (!(await this.getChatAvailability(toUser.id)).write) { throw new Error('recipient is cannot chat (policy)'); } diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 0a2659ee32..601959cc96 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -63,7 +63,7 @@ export type RolePolicies = { canImportFollowing: boolean; canImportMuting: boolean; canImportUserLists: boolean; - canChat: boolean; + chatAvailability: 'available' | 'readonly' | 'unavailable'; }; export const DEFAULT_POLICIES: RolePolicies = { @@ -98,7 +98,7 @@ export const DEFAULT_POLICIES: RolePolicies = { canImportFollowing: true, canImportMuting: true, canImportUserLists: true, - canChat: true, + chatAvailability: 'available', }; @Injectable() @@ -370,6 +370,12 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { return aggregate(policies.map(policy => policy.useDefault ? basePolicies[name] : policy.value)); } + function aggregateChatAvailability(vs: RolePolicies['chatAvailability'][]) { + if (vs.some(v => v === 'available')) return 'available'; + if (vs.some(v => v === 'readonly')) return 'readonly'; + return 'unavailable'; + } + return { gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)), ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)), @@ -402,7 +408,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { canImportFollowing: calc('canImportFollowing', vs => vs.some(v => v === true)), canImportMuting: calc('canImportMuting', vs => vs.some(v => v === true)), canImportUserLists: calc('canImportUserLists', vs => vs.some(v => v === true)), - canChat: calc('canChat', vs => vs.some(v => v === true)), + chatAvailability: calc('chatAvailability', aggregateChatAvailability), }; } diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index ad8052711c..e252ff509e 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -557,7 +557,7 @@ export class UserEntityService implements OnModuleInit { followersVisibility: profile!.followersVisibility, followingVisibility: profile!.followingVisibility, chatScope: user.chatScope, - canChat: this.roleService.getUserPolicies(user.id).then(r => r.canChat), + canChat: this.roleService.getUserPolicies(user.id).then(r => r.chatAvailability === 'available'), roles: this.roleService.getUserRoles(user.id).then(roles => roles.filter(role => role.isPublic).sort((a, b) => b.displayOrder - a.displayOrder).map(role => ({ id: role.id, name: role.name, diff --git a/packages/backend/src/models/json-schema/role.ts b/packages/backend/src/models/json-schema/role.ts index 6f63dcef2e..1cfcb830e0 100644 --- a/packages/backend/src/models/json-schema/role.ts +++ b/packages/backend/src/models/json-schema/role.ts @@ -292,9 +292,10 @@ export const packedRolePoliciesSchema = { type: 'boolean', optional: false, nullable: false, }, - canChat: { - type: 'boolean', + chatAvailability: { + type: 'string', optional: false, nullable: false, + enum: ['available', 'readonly', 'unavailable'], }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/chat/history.ts b/packages/backend/src/server/api/endpoints/chat/history.ts index 7553a751e0..fdd9055106 100644 --- a/packages/backend/src/server/api/endpoints/chat/history.ts +++ b/packages/backend/src/server/api/endpoints/chat/history.ts @@ -46,6 +46,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const history = ps.room ? await this.chatService.roomHistory(me.id, ps.limit) : await this.chatService.userHistory(me.id, ps.limit); const packedMessages = await this.chatEntityService.packMessagesDetailed(history, me); diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts index a988dc60b9..ad2b82e219 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts @@ -16,7 +16,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', prohibitMoved: true, @@ -74,6 +73,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const room = await this.chatService.findRoomById(ps.toRoomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts index bbaab8a6c3..fa34a7d558 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts @@ -16,7 +16,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', prohibitMoved: true, @@ -86,6 +85,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + let file = null; if (ps.fileId != null) { file = await this.driveFilesRepository.findOneBy({ diff --git a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts index 25fc774d4f..63b75fb6a7 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts @@ -13,7 +13,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', kind: 'write:chat', @@ -43,6 +42,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const message = await this.chatService.findMyMessageById(me.id, ps.messageId); if (message == null) { throw new ApiError(meta.errors.noSuchMessage); diff --git a/packages/backend/src/server/api/endpoints/chat/messages/react.ts b/packages/backend/src/server/api/endpoints/chat/messages/react.ts index 0145e380be..5f61e7e992 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/react.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/react.ts @@ -13,7 +13,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', kind: 'write:chat', @@ -44,6 +43,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.react(ps.messageId, me.id, ps.reaction); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts b/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts index b6d3356196..c0e344b889 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/room-timeline.ts @@ -54,6 +54,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const room = await this.chatService.findRoomById(ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/messages/search.ts b/packages/backend/src/server/api/endpoints/chat/messages/search.ts index 4c989e5ca9..682597f76d 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/search.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/search.ts @@ -54,6 +54,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + if (ps.roomId != null) { const room = await this.chatService.findRoomById(ps.roomId); if (room == null) { diff --git a/packages/backend/src/server/api/endpoints/chat/messages/show.ts b/packages/backend/src/server/api/endpoints/chat/messages/show.ts index 371f7a7071..9a2bbb8742 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/show.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/show.ts @@ -50,6 +50,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const message = await this.chatService.findMessageById(ps.messageId); if (message == null) { throw new ApiError(meta.errors.noSuchMessage); diff --git a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts index b97bad8a9c..6784bb6ecf 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts @@ -13,7 +13,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', kind: 'write:chat', @@ -44,6 +43,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.unreact(ps.messageId, me.id, ps.reaction); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts b/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts index a35f121bb1..a057e2e088 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/user-timeline.ts @@ -56,6 +56,8 @@ export default class extends Endpoint { // eslint- private getterService: GetterService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const other = await this.getterService.getUser(ps.userId).catch(err => { if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); throw err; diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/create.ts b/packages/backend/src/server/api/endpoints/chat/rooms/create.ts index fa4cc8ceb4..68a53f0886 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/create.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/create.ts @@ -15,7 +15,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', prohibitMoved: true, @@ -52,6 +51,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const room = await this.chatService.createRoom(me, { name: ps.name, description: ps.description ?? '', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts b/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts index 1d77a06dd8..82a8e1f30d 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts @@ -42,6 +42,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const room = await this.chatService.findRoomById(ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/create.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/create.ts index 5da4a1a772..b1f049f2b9 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/create.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/create.ts @@ -15,7 +15,6 @@ export const meta = { tags: ['chat'], requireCredential: true, - requiredRolePolicy: 'canChat', prohibitMoved: true, @@ -57,6 +56,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const room = await this.chatService.findMyRoomById(me.id, ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts index 8c017f7d01..b8a228089b 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts @@ -42,6 +42,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.ignoreRoomInvitation(me.id, ps.roomId); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/inbox.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/inbox.ts index 07337480fc..8a02d1c704 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/inbox.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/inbox.ts @@ -47,6 +47,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const invitations = await this.chatService.getReceivedRoomInvitationsWithPagination(me.id, ps.limit, ps.sinceId, ps.untilId); return this.chatEntityService.packRoomInvitations(invitations, me); }); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts index 12d496e94b..0702ba086c 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts @@ -55,6 +55,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const room = await this.chatService.findMyRoomById(me.id, ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/join.ts b/packages/backend/src/server/api/endpoints/chat/rooms/join.ts index dbd4d1ea5a..d561f9e03f 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/join.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/join.ts @@ -42,6 +42,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.joinToRoom(me.id, ps.roomId); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/joining.ts b/packages/backend/src/server/api/endpoints/chat/rooms/joining.ts index c4c6253236..ba9242c762 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/joining.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/joining.ts @@ -47,6 +47,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const memberships = await this.chatService.getMyMemberships(me.id, ps.limit, ps.sinceId, ps.untilId); return this.chatEntityService.packRoomMemberships(memberships, me, { diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts b/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts index 724ad61f7e..a3ad0c2d6f 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts @@ -42,6 +42,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.leaveRoom(me.id, ps.roomId); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/members.ts b/packages/backend/src/server/api/endpoints/chat/rooms/members.ts index 407bfe74f1..f5ffa21d32 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/members.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/members.ts @@ -54,6 +54,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const room = await this.chatService.findRoomById(ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts b/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts index 5208b8a253..11cbe7b8b9 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts @@ -43,6 +43,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + await this.chatService.muteRoom(me.id, ps.roomId, ps.mute); }); } diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/owned.ts b/packages/backend/src/server/api/endpoints/chat/rooms/owned.ts index 6516120bca..accf7e1bee 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/owned.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/owned.ts @@ -47,6 +47,8 @@ export default class extends Endpoint { // eslint- private chatService: ChatService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const rooms = await this.chatService.getOwnedRoomsWithPagination(me.id, ps.limit, ps.sinceId, ps.untilId); return this.chatEntityService.packRooms(rooms, me); }); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/show.ts b/packages/backend/src/server/api/endpoints/chat/rooms/show.ts index 547618ee7d..50da210d81 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/show.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/show.ts @@ -47,6 +47,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'read'); + const room = await this.chatService.findRoomById(ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/update.ts b/packages/backend/src/server/api/endpoints/chat/rooms/update.ts index 6f2a9c10b5..0cd62cb040 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/update.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/update.ts @@ -49,6 +49,8 @@ export default class extends Endpoint { // eslint- private chatEntityService: ChatEntityService, ) { super(meta, paramDef, async (ps, me) => { + await this.chatService.checkChatAvailability(me.id, 'write'); + const room = await this.chatService.findMyRoomById(me.id, ps.roomId); if (room == null) { throw new ApiError(meta.errors.noSuchRoom); diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index fa60476b69..de65c3db97 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -108,7 +108,7 @@ export const ROLE_POLICIES = [ 'canImportFollowing', 'canImportMuting', 'canImportUserLists', - 'canChat', + 'chatAvailability', ] as const; export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg'; diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts index 185d9e81b7..c0fe0f2b85 100644 --- a/packages/frontend/src/navbar.ts +++ b/packages/frontend/src/navbar.ts @@ -114,6 +114,7 @@ export const navbarItemDef = reactive({ title: i18n.ts.chat, icon: 'ti ti-messages', to: '/chat', + show: computed(() => $i != null && $i.policies.chatAvailability !== 'unavailable'), indicated: computed(() => $i != null && $i.hasUnreadChatMessages), }, achievements: { diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 73119940c1..930a63f5a9 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -165,21 +165,24 @@ SPDX-License-Identifier: AGPL-3.0-only
- - + +
- + - + - - + + + + +
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index df4efd1271..7c950957cf 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -51,12 +51,15 @@ SPDX-License-Identifier: AGPL-3.0-only
- - - - + + + + - + + + + @@ -295,6 +298,7 @@ import MkInput from '@/components/MkInput.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import MkButton from '@/components/MkButton.vue'; +import MkSelect from '@/components/MkSelect.vue'; import MkRange from '@/components/MkRange.vue'; import MkRolePreview from '@/components/MkRolePreview.vue'; import * as os from '@/os.js'; diff --git a/packages/frontend/src/pages/chat/XMessage.vue b/packages/frontend/src/pages/chat/XMessage.vue index eb8b0d79ee..def6ec7d14 100644 --- a/packages/frontend/src/pages/chat/XMessage.vue +++ b/packages/frontend/src/pages/chat/XMessage.vue @@ -85,7 +85,7 @@ const isMe = computed(() => props.message.fromUserId === $i.id); const urls = computed(() => props.message.text ? extractUrlFromMfm(mfm.parse(props.message.text)) : []); provide(DI.mfmEmojiReactCallback, (reaction) => { - if (!$i.policies.canChat) return; + if ($i.policies.chatAvailability !== 'available') return; sound.playMisskeySfx('reaction'); misskeyApi('chat/messages/react', { @@ -95,7 +95,7 @@ provide(DI.mfmEmojiReactCallback, (reaction) => { }); function react(ev: MouseEvent) { - if (!$i.policies.canChat) return; + if ($i.policies.chatAvailability !== 'available') return; const targetEl = getHTMLElementOrNull(ev.currentTarget ?? ev.target); if (!targetEl) return; @@ -110,7 +110,7 @@ function react(ev: MouseEvent) { } function onReactionClick(record: Misskey.entities.ChatMessage['reactions'][0]) { - if (!$i.policies.canChat) return; + if ($i.policies.chatAvailability !== 'available') return; if (record.user.id === $i.id) { misskeyApi('chat/messages/unreact', { @@ -138,7 +138,7 @@ function onContextmenu(ev: MouseEvent) { function showMenu(ev: MouseEvent, contextmenu = false) { const menu: MenuItem[] = []; - if (!isMe.value && $i.policies.canChat) { + if (!isMe.value && $i.policies.chatAvailability === 'available') { menu.push({ text: i18n.ts.reaction, icon: 'ti ti-mood-plus', @@ -164,7 +164,7 @@ function showMenu(ev: MouseEvent, contextmenu = false) { type: 'divider', }); - if (isMe.value && $i.policies.canChat) { + if (isMe.value && $i.policies.chatAvailability === 'available') { menu.push({ text: i18n.ts.delete, icon: 'ti ti-trash', diff --git a/packages/frontend/src/pages/chat/home.home.vue b/packages/frontend/src/pages/chat/home.home.vue index 17f0e0fbcd..a8ed891de0 100644 --- a/packages/frontend/src/pages/chat/home.home.vue +++ b/packages/frontend/src/pages/chat/home.home.vue @@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -85,7 +32,6 @@ import { instanceName } from '@@/js/config.js'; import { isLink } from '@@/js/is-link.js'; import XCommon from './_common_/common.vue'; import type { PageMetadata } from '@/page.js'; -import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue'; import XPreferenceRestore from '@/ui/_common_/PreferenceRestore.vue'; import * as os from '@/os.js'; @@ -178,50 +124,6 @@ const onContextmenu = (ev) => { $ui-font-size: 1em; // TODO: どこかに集約したい $widgets-hide-threshold: 1090px; -.transition_menuDrawerBg_enterActive, -.transition_menuDrawerBg_leaveActive { - opacity: 1; - transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.transition_menuDrawerBg_enterFrom, -.transition_menuDrawerBg_leaveTo { - opacity: 0; -} - -.transition_menuDrawer_enterActive, -.transition_menuDrawer_leaveActive { - opacity: 1; - transform: translateX(0); - transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.transition_menuDrawer_enterFrom, -.transition_menuDrawer_leaveTo { - opacity: 0; - transform: translateX(-240px); -} - -.transition_widgetsDrawerBg_enterActive, -.transition_widgetsDrawerBg_leaveActive { - opacity: 1; - transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.transition_widgetsDrawerBg_enterFrom, -.transition_widgetsDrawerBg_leaveTo { - opacity: 0; -} - -.transition_widgetsDrawer_enterActive, -.transition_widgetsDrawer_leaveActive { - opacity: 1; - transform: translateX(0); - transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.transition_widgetsDrawer_enterFrom, -.transition_widgetsDrawer_leaveTo { - opacity: 0; - transform: translateX(-240px); -} - .root { height: 100dvh; overflow: clip; @@ -248,24 +150,6 @@ $widgets-hide-threshold: 1090px; min-height: 0; } -.menuDrawerBg { - z-index: 1001; -} - -.menuDrawer { - position: fixed; - top: 0; - left: 0; - z-index: 1001; - height: 100dvh; - width: 240px; - box-sizing: border-box; - contain: strict; - overflow: auto; - overscroll-behavior: contain; - background: var(--MI_THEME-navBg); -} - .statusbars { position: sticky; top: 0; @@ -285,34 +169,4 @@ $widgets-hide-threshold: 1090px; display: none; } } - -.widgetsDrawerBg { - z-index: 1001; -} - -.widgetsDrawer { - position: fixed; - top: 0; - left: 0; - z-index: 1001; - width: 310px; - height: 100dvh; - padding: var(--MI-margin) var(--MI-margin) calc(var(--MI-margin) + env(safe-area-inset-bottom, 0px)) !important; - box-sizing: border-box; - overflow: auto; - overscroll-behavior: contain; - background: var(--MI_THEME-bg); -} - -.widgetsCloseButton { - padding: 8px; - display: block; - margin: 0 auto; -} - -@media (min-width: 370px) { - .widgetsCloseButton { - display: none; - } -} From ce721a8066225fd8a7fd32ebffb2eb550c8e9364 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:19:44 +0900 Subject: [PATCH 054/190] New Crowdin updates (#15773) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (German) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (English) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Simplified) --- locales/ca-ES.yml | 4 +- locales/de-DE.yml | 1 - locales/en-US.yml | 1 - locales/it-IT.yml | 1 - locales/ko-KR.yml | 217 +++++++++++++++++++++++----------------------- locales/zh-CN.yml | 5 +- locales/zh-TW.yml | 6 +- 7 files changed, 121 insertions(+), 114 deletions(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 9a1733128b..05de3b49d9 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1342,6 +1342,7 @@ bottom: "A baix " top: "A dalt " embed: "Incrustar" settingsMigrating: "Estem fent la migració de la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard i manualment anant a Preferències → Altres configuracions → Migrar configuració antiga)" +readonly: "Només lectura" _chat: noMessagesYet: "Encara no tens missatges " newMessage: "Missatge nou" @@ -1371,6 +1372,7 @@ _chat: muteThisRoom: "Silenciar aquesta sala" deleteRoom: "Esborrar la sala" chatNotAvailableForThisAccountOrServer: "El xat no està disponible per aquest servidor o aquest compte." + chatIsReadOnlyForThisAccountOrServer: "El xat és només de lectura en aquest servidor o compte. No es poden escriure nous missatges ni crear o unir-se a sales de xat." chatNotAvailableInOtherAccount: "La funció de xat es troba desactivada al compte de l'altre usuari." cannotChatWithTheUser: "No pots xatejar amb aquest usuari" cannotChatWithTheUser_description: "El xat està desactivat o l'altra part encara no l'ha obert." @@ -1931,7 +1933,7 @@ _role: canImportFollowing: "Autoritza la importació de seguidors" canImportMuting: "Autoritza la importació de silenciats" canImportUserLists: "Autoritza la importació de llistes d'usuaris " - canChat: "Pot xatejar" + chatAvailability: "Es permet xatejar" _condition: roleAssignedTo: "Assignat a rols manuals" isLocal: "Usuari local" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 1676fb16b8..3e081a605e 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1930,7 +1930,6 @@ _role: canImportFollowing: "Importieren von Gefolgten zulassen" canImportMuting: "Importieren von Stummgeschalteten zulassen" canImportUserLists: "Importieren von Listen erlauben" - canChat: "Chatten erlauben" _condition: roleAssignedTo: "Manuellen Rollen zugewiesen" isLocal: "Lokaler Benutzer" diff --git a/locales/en-US.yml b/locales/en-US.yml index 63fa07ec68..74aa479162 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1930,7 +1930,6 @@ _role: canImportFollowing: "Allow importing following" canImportMuting: "Allow importing muting" canImportUserLists: "Allow importing lists" - canChat: "Allow Chat" _condition: roleAssignedTo: "Assigned to manual roles" isLocal: "Local user" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 7215070334..5f74398770 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1930,7 +1930,6 @@ _role: canImportFollowing: "Può importare Following" canImportMuting: "Può importare Silenziati" canImportUserLists: "Può importare liste di Profili" - canChat: "Chat consentita" _condition: roleAssignedTo: "Assegnato a ruoli manualmente" isLocal: "Profilo locale" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 4204c40309..beb5bc05d5 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -64,8 +64,8 @@ copyNoteId: "노트 ID 복사" copyFileId: "파일 ID 복사" copyFolderId: "폴더 ID 복사" copyProfileUrl: "프로필 URL 복사" -searchUser: "사용자 검색" -searchThisUsersNotes: "사용자의 노트 검색" +searchUser: "유저 검색" +searchThisUsersNotes: "유저의 노트를 검색" reply: "답글" loadMore: "더 보기" showMore: "더 보기" @@ -267,7 +267,7 @@ publishing: "배포 중" notResponding: "응답 없음" instanceFollowing: "서버의 팔로잉" instanceFollowers: "서버의 팔로워" -instanceUsers: "서버의 사용자" +instanceUsers: "서버의 유저" changePassword: "비밀번호 변경" security: "보안" retypedNotMatch: "입력이 일치하지 않습니다." @@ -385,12 +385,12 @@ disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리 registration: "등록" invite: "초대" driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량" -driveCapacityPerRemoteAccount: "원격 사용자별 드라이브 용량" +driveCapacityPerRemoteAccount: "리모트 유저별 드라이브 용량" inMb: "메가바이트 단위" bannerUrl: "배너 이미지 URL" backgroundImageUrl: "배경 이미지 URL" basicInfo: "기본 정보" -pinnedUsers: "고정한 사용자" +pinnedUsers: "고정한 유저" pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다." pinnedPages: "고정한 페이지" pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다." @@ -436,11 +436,11 @@ silence: "사일런스" silenceConfirm: "이 계정을 사일런스로 설정하시겠습니까?" unsilence: "사일런스 해제" unsilenceConfirm: "이 계정의 사일런스를 해제하시겠습니까?" -popularUsers: "인기 사용자" -recentlyUpdatedUsers: "최근에 활동한 사용자" -recentlyRegisteredUsers: "최근에 가입한 사용자" -recentlyDiscoveredUsers: "최근에 발견한 사용자" -exploreUsersCount: "{count}명의 사용자가 있습니다" +popularUsers: "인기 유저" +recentlyUpdatedUsers: "최근에 활동한 유저" +recentlyRegisteredUsers: "최근에 가입한 유저" +recentlyDiscoveredUsers: "최근에 발견한 유저" +exploreUsersCount: "{count}명의 유저가 있습니다" exploreFediverse: "연합우주를 탐색" popularTags: "인기 태그" userList: "리스트" @@ -508,7 +508,7 @@ strongPassword: "강한 비밀번호" passwordMatched: "일치합니다" passwordNotMatched: "일치하지 않습니다" signinWith: "{x}로 로그인" -signinFailed: "로그인할 수 없습니다. 사용자 이름과 비밀번호를 확인해 주십시오." +signinFailed: "로그인할 수 없습니다. 유저 이름과 비밀번호를 확인해 주십시오." or: "혹은" language: "언어" uiLanguage: "UI 표시 언어" @@ -607,7 +607,7 @@ uiInspectorDescription: "메모리에 있는 UI 컴포넌트의 인스턴트 목 output: "출력" script: "스크립트" disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음" -updateRemoteUser: "원격 사용자 정보 갱신" +updateRemoteUser: "리모트 유저 정보 갱신" unsetUserAvatar: "아바타 제거" unsetUserAvatarConfirm: "아바타를 제거할까요?" unsetUserBanner: "배너 제거" @@ -616,7 +616,7 @@ deleteAllFiles: "모든 파일 삭제" deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?" removeAllFollowing: "모든 팔로잉 해제" removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요." -userSuspended: "이 사용자는 정지되었습니다." +userSuspended: "이 유저는 정지되었습니다." userSilenced: "이 계정은 사일런스된 상태입니다." yourAccountSuspendedTitle: "계정이 정지되었습니다" yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오." @@ -677,7 +677,7 @@ emailAddress: "메일 주소" smtpConfig: "SMTP 서버 설정" smtpHost: "호스트" smtpPort: "포트" -smtpUser: "사용자 이름" +smtpUser: "유저 이름" smtpPass: "비밀번호" emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다." smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용" @@ -763,7 +763,7 @@ no: "아니오" driveFilesCount: "드라이브에 있는 파일 수" driveUsage: "드라이브 사용량" noCrawle: "검색엔진의 인덱싱 거부" -noCrawleDescription: "검색엔진에 사용자 페이지, 노트, 페이지 등의 콘텐츠를 인덱싱되지 않게 합니다." +noCrawleDescription: "검색엔진에 유저 페이지, 노트, 페이지 등의 콘텐츠를 인덱싱되지 않게 합니다." lockedAccountInfo: "팔로우를 승인으로 승인받더라도 노트의 공개 범위를 '팔로워'로 하지 않는 한 누구나 당신의 노트를 볼 수 있습니다." alwaysMarkSensitive: "미디어를 항상 열람 주의로 설정" loadRawImages: "첨부한 이미지의 썸네일을 원본화질로 표시" @@ -795,7 +795,7 @@ needReloadToApply: "변경 사항은 새로고침하면 적용됩니다." showTitlebar: "타이틀 바를 표시하기" clearCache: "캐시 비우기" onlineUsersCount: "{n}명이 접속 중" -nUsers: "{n} 사용자" +nUsers: "{n} 유저" nNotes: "{n} 노트" sendErrorReports: "오류 보고서 보내기" sendErrorReportsDescription: "이 설정을 활성화하면, 문제가 발생했을 때 오류에 대한 상세 정보를 Misskey에 보내어 더 나은 소프트웨어를 만드는 데에 도움을 줄 수 있습니다." @@ -841,7 +841,7 @@ addDescription: "설명 추가" userPagePinTip: "각 노트의 메뉴에서 「프로필에 고정」을 선택하는 것으로, 여기에 노트를 표시해 둘 수 있어요." notSpecifiedMentionWarning: "수신자가 선택되지 않은 멘션이 있어요" info: "정보" -userInfo: "사용자 정보" +userInfo: "유저 정보" unknown: "알 수 없음" onlineStatus: "온라인 상태" hideOnlineStatus: "온라인 상태 숨기기" @@ -857,7 +857,7 @@ switchAccount: "계정 바꾸기" enabled: "활성화" disabled: "비활성화" quickAction: "빠른 동작" -user: "사용자" +user: "유저" administration: "관리" accounts: "계정" switch: "전환" @@ -898,7 +898,7 @@ whatIsNew: "패치 정보 보기" translate: "번역" translatedFrom: "{x}에서 번역" accountDeletionInProgress: "계정 삭제 작업을 진행하고 있습니다" -usernameInfo: "서버상에서 계정을 식별하기 위한 이름. 알파벳(a~z, A~Z), 숫자(0~9) 및 언더바(_)를 사용할 수 있습니다. 사용자명은 나중에 변경할 수 없습니다." +usernameInfo: "서버상에서 계정을 식별하기 위한 이름. 알파벳(a~z, A~Z), 숫자(0~9) 및 언더바(_)를 사용할 수 있습니다. 유저명은 나중에 변경할 수 없습니다." aiChanMode: "아이 모드" devMode: "개발자 모드" keepCw: "CW 유지하기" @@ -1032,7 +1032,7 @@ correspondingSourceIsAvailable: "소스 코드는 {anchor}에서 받아보실 roles: "역할" role: "역할" noRole: "역할이 없습니다" -normalUser: "일반 사용자" +normalUser: "일반 유저" undefined: "정의되지 않음" assign: "할당" unassign: "할당 취소" @@ -1106,7 +1106,7 @@ audio: "소리" audioFiles: "소리" dataSaver: "데이터 절약 모드" accountMigration: "계정 이동" -accountMoved: "이 사용자는 다음 계정으로 이사했습니다:" +accountMoved: "이 유저는 다음 계정으로 이사했습니다:" accountMovedShort: "이사한 계정입니다" operationForbidden: "사용할 수 없습니다" forceShowAds: "광고를 항상 표시" @@ -1127,8 +1127,8 @@ serverRules: "서버 규칙" pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오." pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오." continue: "계속" -preservedUsernames: "예약한 사용자 이름" -preservedUsernamesDescription: "예약할 사용자명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 사용자명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다." +preservedUsernames: "예약한 유저명" +preservedUsernamesDescription: "예약할 유저명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 유저명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다." createNoteFromTheFile: "이 파일로 노트를 작성" archive: "아카이브" archived: "아카이브 됨" @@ -1142,7 +1142,7 @@ youFollowing: "팔로잉" preventAiLearning: "기계학습(생성형 AI)으로의 사용을 거부" preventAiLearningDescription: "외부의 문장 생성 AI나 이미지 생성 AI에 대해 제출한 노트나 이미지 등의 콘텐츠를 학습의 대상으로 사용하지 않도록 요구합니다. 다만, 이 요구사항을 지킬 의무는 없기 때문에 학습을 완전히 방지하는 것은 아닙니다." options: "옵션" -specifyUser: "사용자 지정" +specifyUser: "유저 지정" lookupConfirm: "조회 할까요?" openTagPageConfirm: "해시태그의 페이지를 열까요?" specifyHost: "호스트 지정" @@ -1297,8 +1297,8 @@ passkeyVerificationSucceededButPasswordlessLoginDisabled: "입력된 패스키 messageToFollower: "팔로워에게 보낼 메시지" target: "대상" testCaptchaWarning: "CAPTCHA를 테스트하기 위한 기능입니다. 실제 환경에서는 사용하지 마세요." -prohibitedWordsForNameOfUser: "금지 단어 (사용자 이름)" -prohibitedWordsForNameOfUserDescription: "이 목록에 포함되는 키워드가 사용자 이름에 있는 경우, 일반 사용자는 이름을 바꿀 수 없습니다. 모더레이터 권한을 가진 사용자는 제한 대상에서 제외됩니다." +prohibitedWordsForNameOfUser: "금지 단어 (유저명)" +prohibitedWordsForNameOfUserDescription: "이 목록에 포함되는 키워드가 유저명에 있는 경우, 일반 유저는 이름을 바꿀 수 없습니다. 모더레이터 권한을 가진 유저는 제한 대상에서 제외됩니다." yourNameContainsProhibitedWords: "바꾸려는 이름에 금지된 키워드가 포함되어 있습니다." yourNameContainsProhibitedWordsDescription: "이름에 금지된 키워드가 있습니다. 이름을 사용해야 하는 경우, 서버 관리자에 문의하세요." thisContentsAreMarkedAsSigninRequiredByAuthor: "게시자에 의해 로그인해야 볼 수 있도록 설정되어 있습니다." @@ -1341,15 +1341,17 @@ right: "오른쪽" bottom: "아래" top: "위" embed: "임베드" +settingsMigrating: "설정을 이전하는 중입니다. 잠시 기다려주십시오... (나중에 '환경설정 → 기타 → 기존 설정 정보를 이전'에서 수동으로 이전할 수도 있습니다)" +readonly: "읽기 전용" _chat: noMessagesYet: "아직 메시지가 없습니다" newMessage: "새로운 메시지" individualChat: "개인 대화" - individualChat_description: "특정 사용자와 일대일 채팅을 할 수 있습니다." + individualChat_description: "특정 유저와 일대일 채팅을 할 수 있습니다." roomChat: "룸 채팅" - roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 사용자와도 상대방이 수락하면 채팅을 할 수 있습니다." + roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 유저와도 상대방이 수락하면 채팅을 할 수 있습니다." createRoom: "룸을 생성" - inviteUserToChat: "사용자를 초대하여 채팅을 시작하세요" + inviteUserToChat: "유저를 초대하여 채팅을 시작하세요" yourRooms: "생성한 룸" joiningRooms: "참가 중인 룸" invitations: "초대" @@ -1357,7 +1359,7 @@ _chat: history: "이력" noHistory: "기록이 없습니다" noRooms: "룸이 없습니다" - inviteUser: "사용자를 초대" + inviteUser: "유저를 초대" sentInvitations: "초대를 보내기" join: "참여" ignore: "무시" @@ -1370,21 +1372,22 @@ _chat: muteThisRoom: "이 룸을 뮤트" deleteRoom: "룸을 삭제" chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다." + chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅방을 만들거나 참가할 수 없습니다." chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다." - cannotChatWithTheUser: "이 사용자와 채팅을 시작할 수 없습니다" + cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다" cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다." chatWithThisUser: "채팅하기" - thisUserAllowsChatOnlyFromFollowers: "이 사용자는 팔로워만 채팅을 할 수 있습니다." - thisUserAllowsChatOnlyFromFollowing: "이 사용자는 이 사용자가 팔로우하는 사용자만 채팅을 허용합니다." - thisUserAllowsChatOnlyFromMutualFollowing: "이 사용자는 상호 팔로우하는 사용자만 채팅을 허용합니다." - thisUserNotAllowedChatAnyone: "이 사용자는 다른 사람의 채팅을 받지 않습니다." + thisUserAllowsChatOnlyFromFollowers: "이 유저는 팔로워만 채팅을 할 수 있습니다." + thisUserAllowsChatOnlyFromFollowing: "이 유저는 이 유저가 팔로우하는 유저만 채팅을 허용합니다." + thisUserAllowsChatOnlyFromMutualFollowing: "이 유저는 상호 팔로우하는 유저만 채팅을 허용합니다." + thisUserNotAllowedChatAnyone: "이 유저는 다른 사람의 채팅을 받지 않습니다." chatAllowedUsers: "채팅을 허용한 상대" chatAllowedUsers_note: "내가 채팅 메시지를 보낸 상대와는 이 설정과 상관없이 채팅이 가능합니다." _chatAllowedUsers: everyone: "누구나" followers: "자신의 팔로워만" - following: "자신이 팔로우한 사용자만" - mutual: "상호 팔로우한 사용자만" + following: "자신이 팔로우한 유저만" + mutual: "상호 팔로우한 유저만" none: "아무도 허락하지 않기" _emojiPalette: palettes: "팔레트" @@ -1410,7 +1413,7 @@ _settings: soundsBanner: "클라이언트에서 재생할 소리에 대한 설정을 합니다." timelineAndNote: "타임라인과 노트" makeEveryTextElementsSelectable: "모든 텍스트 요소를 선택할 수 있도록 함" - makeEveryTextElementsSelectable_description: "활성화 시, 일부 동작에서 사용자의 접근성이 나빠질 수도 있습니다." + makeEveryTextElementsSelectable_description: "활성화 시, 일부 동작에서 유저의 접근성이 나빠질 수도 있습니다." useStickyIcons: "아이콘이 스크롤을 따라가도록 하기" showNavbarSubButtons: "내비게이션 바에 보조 버튼 표시" ifOn: "켜져 있을 때" @@ -1436,12 +1439,12 @@ _accountSettings: requireSigninToViewContents: "콘텐츠 열람을 위해 로그인을 필수로 설정하기" requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다." requireSigninToViewContentsDescription2: "URL 미리보기(OGP), 웹페이지에 삽입, 노트 인용을 지원하지 않는 서버에서 볼 수 없게 됩니다." - requireSigninToViewContentsDescription3: "원격 서버에 연합된 콘텐츠에는 이러한 제한이 적용되지 않을 수 있습니다." + requireSigninToViewContentsDescription3: "리모트 서버에 연합된 콘텐츠에는 이러한 제한이 적용되지 않을 수 있습니다." makeNotesFollowersOnlyBefore: "과거 노트는 팔로워만 볼 수 있도록 설정하기" makeNotesFollowersOnlyBeforeDescription: "이 기능이 활성화되어 있는 동안, 설정된 날짜 및 시간보다 과거 또는 설정된 시간이 지난 노트는 팔로워만 볼 수 있게 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다." makeNotesHiddenBefore: "과거 노트 비공개로 전환하기" makeNotesHiddenBeforeDescription: "이 기능이 활성화되어 있는 동안 설정한 날짜 및 시간보다 과거 또는 설정한 시간이 지난 노트는 본인만 볼 수 있게(비공개로 전환) 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다." - mayNotEffectForFederatedNotes: "원격 서버에 연합된 노트에는 효과가 없을 수도 있습니다." + mayNotEffectForFederatedNotes: "리모트 서버에 연합된 노트에는 효과가 없을 수도 있습니다." mayNotEffectSomeSituations: "여기서 설정하는 제한은 모더레이션이나 리모트 서버에서 볼 때 등 일부 환경에서는 적용되지 않을 수도 있습니다." notesHavePassedSpecifiedPeriod: "지정한 시간이 경과된 노트" notesOlderThanSpecifiedDateAndTime: "지정된 날짜 및 시간 이전의 노트" @@ -1482,11 +1485,11 @@ _announcement: needConfirmationToRead: "읽음으로 표시하기 전에 확인하기" needConfirmationToReadDescription: "활성화하면 이 공지사항을 읽음으로 표시하기 전에 확인 알림창을 띄웁니다. '모두 읽음'의 대상에서도 제외됩니다." end: "공지에서 내리기" - tooManyActiveAnnouncementDescription: "공지사항이 너무 많을 경우, 사용자 경험에 영향을 끼칠 가능성이 있습니다. 오래된 공지사항은 아카이브하시는 것을 권장드립니다." + tooManyActiveAnnouncementDescription: "공지사항이 너무 많을 경우, 유저 경험에 영향을 끼칠 가능성이 있습니다. 오래된 공지사항은 아카이브하시는 것을 권장드립니다." readConfirmTitle: "읽음으로 표시합니까?" readConfirmText: "〈{title}〉의 내용을 읽음으로 표시합니다." shouldNotBeUsedToPresentPermanentInfo: "신규 유저의 이용 경험에 악영향을 끼칠 수 있으므로, 일시적인 알림 수단으로만 사용하고 고정된 정보에는 사용을 지양하는 것을 추천합니다." - dialogAnnouncementUxWarn: "다이얼로그 형태의 알림이 동시에 2개 이상 존재하는 경우, 사용자 경험에 악영향을 끼칠 수 있으므로 신중히 결정하십시오." + dialogAnnouncementUxWarn: "다이얼로그 형태의 알림이 동시에 2개 이상 존재하는 경우, 유저 경험에 악영향을 끼칠 수 있으므로 신중히 결정하십시오." silence: "조용히 알림" silenceDescription: "활성화하면 공지사항에 대한 알림이 가지 않게 되며, 확인 버튼을 누를 필요가 없게 됩니다." _initialAccountSetting: @@ -1728,40 +1731,40 @@ _achievements: flavor: "냐냐냐냐냐냐아아아아앙!" _following1: title: "첫 팔로우" - description: "사용자를 처음으로 팔로우했습니다" + description: "유저를 처음으로 팔로우했습니다" _following10: title: "팔로우, 팔로우" - description: "10명의 사용자를 팔로우했습니다" + description: "10명의 유저를 팔로우했습니다" _following50: title: "친구 잔뜩" - description: "50명의 사용자를 팔로우했습니다" + description: "50명의 유저를 팔로우했습니다" _following100: title: "주소록 한 권으론 부족해" - description: "100명의 사용자를 팔로우했습니다" + description: "100명의 유저를 팔로우했습니다" _following300: title: "친구가 넘쳐나" - description: "300명의 사용자를 팔로우했습니다" + description: "300명의 유저를 팔로우했습니다" _followers1: title: "첫 팔로워" - description: "사용자가 처음으로 팔로잉했습니다" + description: "유저가 처음으로 팔로잉했습니다" _followers10: title: "팔로우 미!" - description: "10명의 사용자가 팔로우했습니다" + description: "10명의 유저가 팔로우했습니다" _followers50: title: "이곳저곳" - description: "50명의 사용자가 팔로우했습니다" + description: "50명의 유저가 팔로우했습니다" _followers100: title: "인기왕" - description: "100명의 사용자가 팔로우했습니다" + description: "100명의 유저가 팔로우했습니다" _followers300: title: "줄 좀 서봐요" - description: "100명의 사용자가 팔로우했습니다" + description: "100명의 유저가 팔로우했습니다" _followers500: title: "기지국" - description: "500명의 사용자가 팔로우했습니다" + description: "500명의 유저가 팔로우했습니다" _followers1000: title: "유명인사" - description: "1,000명의 사용자가 팔로우했습니다" + description: "1,000명의 유저가 팔로우했습니다" _collectAchievements30: title: "도전 과제 콜렉터" description: "30개의 도전과제를 획득했습니다" @@ -1867,7 +1870,7 @@ _role: permission: "역할 권한" descriptionOfPermission: "조정자는 기본적인 조정 작업을 진행할 수 있습니다.\n관리자는 서버의 모든 설정을 변경할 수 있습니다." assignTarget: "할당 대상" - descriptionOfAssignTarget: "수동을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n조건부를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다." + descriptionOfAssignTarget: "수동을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n조건부를 선택하면 조건을 설정해 일치하는 유저를 자동으로 포함되게 할 수 있습니다." manual: "수동" manualRoles: "수동 역할" conditional: "조건부" @@ -1875,7 +1878,7 @@ _role: condition: "조건" isConditionalRole: "조건부 역할입니다." isPublic: "역할 공개" - descriptionOfIsPublic: "역할에 할당된 사용자를 누구나 볼 수 있습니다. 또한 사용자 프로필에 이 역할이 표시됩니다." + descriptionOfIsPublic: "역할에 할당된 유저를 누구나 볼 수 있습니다. 또한 유저 프로필에 이 역할이 표시됩니다." options: "옵션" policies: "정책" baseRole: "기본 역할" @@ -1888,10 +1891,10 @@ _role: descriptionOfIsExplorable: "활성화하면 역할 타임라인을 공개합니다. 비활성화 시 타임라인이 공개되지 않습니다." displayOrder: "표시 순서" descriptionOfDisplayOrder: "값이 클 수록 UI에서 먼저 표시됩니다." - preserveAssignmentOnMoveAccount: "마이그레이션 대상 계정에도 할당 상태 전달" - preserveAssignmentOnMoveAccount_description: "켜면 이 역할이 부여된 계정이 마이그레이션될 때 마이그레이션 대상 계정에도 이 역할이 승계됩니다." + preserveAssignmentOnMoveAccount: "이전 대상 계정에도 할당 상태 전달" + preserveAssignmentOnMoveAccount_description: "켜면 이 역할이 부여된 계정이 이전될 때 마이그레이션 대상 계정에도 이 역할이 승계됩니다." canEditMembersByModerator: "모더레이터의 역할 수정 허용" - descriptionOfCanEditMembersByModerator: "이 옵션을 켜면 모더레이터도 이 역할에 사용자를 할당하거나 삭제할 수 있습니다. 꺼져 있으면 관리자만 할당이 가능합니다." + descriptionOfCanEditMembersByModerator: "이 옵션을 켜면 모더레이터도 이 역할에 유저를 할당하거나 삭제할 수 있습니다. 꺼져 있으면 관리자만 할당이 가능합니다." priority: "우선순위" _priority: low: "낮음" @@ -1917,8 +1920,8 @@ _role: webhookMax: "만들 수 있는 Webhook 수" clipMax: "만들 수 있는 클립 수" noteEachClipsMax: "클립에 넣을 수 있는 노트 수" - userListMax: "만들 수 있는 사용자 리스트 수" - userEachUserListsMax: "사용자 리스트에 넣을 수 있는 사용자 수" + userListMax: "만들 수 있는 유저 리스트 수" + userEachUserListsMax: "유저 리스트에 넣을 수 있는 유저 수" rateLimitFactor: "요청 빈도 제한" descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다." canHideAds: "광고 숨기기" @@ -1930,24 +1933,24 @@ _role: canImportFollowing: "팔로우 가져오기 허용" canImportMuting: "뮤트 목록 가져오기 허용" canImportUserLists: "리스트 목록 가져오기 허용" - canChat: "채팅을 허락" + chatAvailability: "채팅을 허락" _condition: roleAssignedTo: "수동 역할에 이미 할당됨" - isLocal: "로컬 사용자" - isRemote: "원격 사용자" - isCat: "고양이 사용자" - isBot: "봇 사용자" - isSuspended: "정지된 사용자" - isLocked: "잠금 계정 사용자" - isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 사용자" + isLocal: "로컬 유저" + isRemote: "리모트 유저" + isCat: "고양이 유저" + isBot: "봇 유저" + isSuspended: "정지된 유저" + isLocked: "잠금 계정 유저" + isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 유저" createdLessThan: "가입한 지 다음 일수 이내인 유저" createdMoreThan: "가입한 지 다음 일수 이상인 유저" followersLessThanOrEq: "팔로워 수가 다음 이하인 유저" - followersMoreThanOrEq: "팔로워 수가 다음보다 많은 사용자" + followersMoreThanOrEq: "팔로워 수가 다음보다 많은 유저" followingLessThanOrEq: "팔로잉 수가 다음 이하인 유저" - followingMoreThanOrEq: "팔로잉 수가 다음보다 많은 사용자" + followingMoreThanOrEq: "팔로잉 수가 다음보다 많은 유저" notesLessThanOrEq: "노트 수가 다음 이하인 유저" - notesMoreThanOrEq: "노트 수가 다음보다 많은 사용자" + notesMoreThanOrEq: "노트 수가 다음보다 많은 유저" and: "다음을 모두 만족" or: "다음을 하나라도 만족" not: "다음을 만족하지 않음" @@ -1989,7 +1992,7 @@ _ad: adsSettings: "광고 표시 설정" notesPerOneAd: "실시간으로 갱신되는 타임라인에서 광고를 노출시키는 간격 (노트 당)" setZeroToDisable: "0으로 지정하면 실시간 타임라인에서의 광고를 비활성화합니다" - adsTooClose: "광고의 표시 간격이 매우 작아, 사용자 경험에 부정적인 영향을 미칠 수 있습니다." + adsTooClose: "광고의 표시 간격이 매우 작아, 유저 경험에 부정적인 영향을 미칠 수 있습니다." _forgotPassword: enterEmail: "여기에 계정에 등록한 메일 주소를 입력해 주세요. 입력한 메일 주소로 비밀번호 재설정 링크를 발송합니다." ifNoEmail: "메일 주소를 등록하지 않은 경우, 관리자에 문의해 주십시오." @@ -2244,7 +2247,7 @@ _permissions: "write:pages": "페이지를 수정합니다" "read:page-likes": "페이지의 좋아요를 확인합니다" "write:page-likes": "페이지에 좋아요를 추가하거나 취소합니다" - "read:user-groups": "사용자 그룹 보기" + "read:user-groups": "유저 그룹 보기" "write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다" "read:channels": "채널을 보기" "write:channels": "채널을 추가하거나 삭제합니다" @@ -2256,23 +2259,23 @@ _permissions: "write:flash": "Play를 조작합니다" "read:flash-likes": "Play의 좋아요를 봅니다" "write:flash-likes": "Play의 좋아요를 조작합니다" - "read:admin:abuse-user-reports": "사용자 신고 보기" - "write:admin:delete-account": "사용자 계정 삭제하기" - "write:admin:delete-all-files-of-a-user": "모든 사용자 파일 삭제하기" + "read:admin:abuse-user-reports": "유저 신고 보기" + "write:admin:delete-account": "유저 계정 삭제하기" + "write:admin:delete-all-files-of-a-user": "모든 유저 파일 삭제하기" "read:admin:index-stats": "데이터베이스 색인 정보 보기" "read:admin:table-stats": "데이터베이스 테이블 정보 보기" - "read:admin:user-ips": "사용자 IP 주소 보기" + "read:admin:user-ips": "유저 IP 주소 보기" "read:admin:meta": "인스턴스 메타데이터 보기" - "write:admin:reset-password": "사용자 비밀번호 재설정하기" - "write:admin:resolve-abuse-user-report": "사용자 신고 처리하기" + "write:admin:reset-password": "유저 비밀번호 재설정하기" + "write:admin:resolve-abuse-user-report": "유저 신고 처리하기" "write:admin:send-email": "이메일 보내기" "read:admin:server-info": "서버 정보 보기" "read:admin:show-moderation-log": "조정 기록 보기" - "read:admin:show-user": "사용자 개인정보 보기" - "write:admin:suspend-user": "사용자 정지하기" - "write:admin:unset-user-avatar": "사용자 아바타 삭제하기" - "write:admin:unset-user-banner": "사용자 배너 삭제하기" - "write:admin:unsuspend-user": "사용자 정지 해제하기" + "read:admin:show-user": "유저 개인정보 보기" + "write:admin:suspend-user": "유저 정지하기" + "write:admin:unset-user-avatar": "유저 아바타 삭제하기" + "write:admin:unset-user-banner": "유저 배너 삭제하기" + "write:admin:unsuspend-user": "유저 정지 해제하기" "write:admin:meta": "인스턴스 메타데이터 수정하기" "write:admin:user-note": "조정 기록 수정하기" "write:admin:roles": "역할 수정하기" @@ -2286,15 +2289,15 @@ _permissions: "write:admin:avatar-decorations": "아바타 꾸미기 수정하기" "read:admin:avatar-decorations": "아바타 꾸미기 보기" "write:admin:federation": "연합 정보 수정하기" - "write:admin:account": "사용자 계정 수정하기" - "read:admin:account": "사용자 정보 보기" + "write:admin:account": "유저 계정 수정하기" + "read:admin:account": "유저 정보 보기" "write:admin:emoji": "이모지 수정하기" "read:admin:emoji": "이모지 보기" "write:admin:queue": "작업 대기열 수정하기" "read:admin:queue": "작업 대기열 정보 보기" "write:admin:promo": "홍보 기록 수정하기" - "write:admin:drive": "사용자 드라이브 수정하기" - "read:admin:drive": "사용자 드라이브 정보 보기" + "write:admin:drive": "유저 드라이브 수정하기" + "read:admin:drive": "유저 드라이브 정보 보기" "read:admin:stream": "관리자용 Websocket API 사용하기" "write:admin:ad": "광고 수정하기" "read:admin:ad": "광고 보기" @@ -2316,7 +2319,7 @@ _auth: callback: "앱으로 돌아갑니다" accepted: "접근 권한이 부여되었습니다." denied: "접근이 거부되었습니다" - scopeUser: "다음 사용자로 활동하고 있습니다." + scopeUser: "다음 유저로 활동하고 있습니다." pleaseLogin: "어플리케이션의 접근을 허가하려면 로그인하십시오." byClickingYouWillBeRedirectedToThisUrl: "접근을 허용하면 자동으로 다음 URL로 이동합니다." _antennaSources: @@ -2353,7 +2356,7 @@ _widgets: postForm: "글 입력란" slideshow: "슬라이드 쇼" button: "버튼" - onlineUsers: "온라인 사용자" + onlineUsers: "온라인 유저" jobQueue: "작업 대기열" serverMetric: "서버 통계" aiscript: "AiScript 콘솔" @@ -2363,7 +2366,7 @@ _widgets: _userList: chooseList: "리스트 선택" clicker: "클리커" - birthdayFollowings: "오늘이 생일인 사용자" + birthdayFollowings: "오늘이 생일인 유저" _cw: hide: "숨기기" show: "더 보기" @@ -2415,7 +2418,7 @@ _postForm: f: "작성해주시길 기다리고 있어요..." _profile: name: "이름" - username: "사용자 이름" + username: "유저명" description: "자기소개" youCanIncludeHashtags: "해시 태그를 포함할 수 있습니다." metadata: "추가 정보" @@ -2446,7 +2449,7 @@ _charts: apRequest: "요청" usersIncDec: "유저 수 증감" usersTotal: "유저 수 합계" - activeUsers: "활동 사용자 수" + activeUsers: "활동 유저 수" notesIncDec: "노트 수 증감" localNotesIncDec: "로컬 노트 수 증감" remoteNotesIncDec: "리모트 노트 수 증감" @@ -2457,8 +2460,8 @@ _charts: storageUsageTotal: "스토리지 사용량 합계" _instanceCharts: requests: "요청" - users: "사용자 수 차이" - usersTotal: "누적 사용자 수" + users: "유저 수 차이" + usersTotal: "누적 유저 수" notes: "노트 수 증감" notesTotal: "누적 노트 수" ff: "팔로잉/팔로워 증감" @@ -2572,18 +2575,18 @@ _notification: createTokenDescription: "만약 기억이 나지 않는다면 '{text}'를 통해 액세스 토큰을 삭제해 주세요." _types: all: "전부" - note: "사용자의 새 글" + note: "유저의 새 글" follow: "팔로잉" mention: "멘션" reply: "답글" renote: "리노트" quote: "인용" - reaction: "반응" + reaction: "리액션" pollEnded: "투표가 종료됨" receiveFollowRequest: "팔로우 요청을 받았을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때" - roleAssigned: "역할이 부여 됨" - chatRoomInvitationReceived: "채팅 룸에 초대받았습니다" + roleAssigned: "역할이 부여됨" + chatRoomInvitationReceived: "채팅 룸에 초대받음" achievementEarned: "도전 과제 획득" exportCompleted: "추출을 성공함" login: "로그인" @@ -2671,10 +2674,10 @@ _abuseReport: mail: "이메일" webhook: "Webhook" _captions: - mail: "모더레이터 권한을 가진 사용자의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)" + mail: "모더레이터 권한을 가진 유저의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)" webhook: "지정한 SystemWebhook에 알림을 보냅니다 (신고를 받은 때와 해결했을 때에 송신)" keywords: "키워드" - notifiedUser: "알릴 사용자" + notifiedUser: "알릴 유저" notifiedWebhook: "사용할 Webhook" deleteConfirm: "수신자를 삭제하시겠습니까?" _moderationLogTypes: @@ -2693,11 +2696,11 @@ _moderationLogTypes: deleteDriveFile: "파일 삭제" deleteNote: "노트 삭제" createGlobalAnnouncement: "전역 공지사항 생성" - createUserAnnouncement: "사용자 공지사항 만들기" + createUserAnnouncement: "유저에게 공지사항 만들기" updateGlobalAnnouncement: "모든 공지사항 수정" - updateUserAnnouncement: "사용자 공지사항 수정" + updateUserAnnouncement: "유저의 공지사항 수정" deleteGlobalAnnouncement: "모든 공지사항 삭제" - deleteUserAnnouncement: "사용자 공지사항 삭제" + deleteUserAnnouncement: "유저의 공지사항 삭제" resetPassword: "비밀번호 재설정" suspendRemoteInstance: "리모트 서버를 정지" unsuspendRemoteInstance: "리모트 서버의 정지를 해제" @@ -2939,7 +2942,7 @@ _embedCodeGen: _selfXssPrevention: warning: "경고" title: "“이 화면에 뭔가를 붙여넣어라\"는 것은 모두 사기입니다." - description1: "여기에 무언가를 붙여넣으면 악의적인 사용자에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다." + description1: "여기에 무언가를 붙여넣으면 악의적인 유저에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다." description2: "붙여 넣으려는 항목이 무엇인지 정확히 이해하지 못하는 경우, %c지금 바로 작업을 중단하고 이 창을 닫으십시오." description3: "자세한 내용은 여기를 확인해 주세요. {link}" _followRequest: @@ -2990,7 +2993,7 @@ _search: searchScopeAll: "전체" searchScopeLocal: "로컬" searchScopeServer: "서버 지정" - searchScopeUser: "사용자 지정" + searchScopeUser: "유저 지정" pleaseEnterServerHost: "서버의 호스트를 입력해 주세요." pleaseSelectUser: "유저를 선택해주세요" serverHostPlaceholder: "예: misskey.example.com" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 57a78471db..9e05860d24 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -1341,6 +1341,8 @@ right: "右" bottom: "下" top: "上" embed: "嵌入" +settingsMigrating: "正在迁移设置,请稍候。(之后也可以在设置 → 其它 → 迁移旧设置来手动迁移)" +readonly: "只读" _chat: noMessagesYet: "还没有消息" newMessage: "新消息" @@ -1370,6 +1372,7 @@ _chat: muteThisRoom: "静音此房间" deleteRoom: "删除房间" chatNotAvailableForThisAccountOrServer: "此服务器或者账户还未开启聊天功能。" + chatIsReadOnlyForThisAccountOrServer: "此服务器或者账户内的聊天为只读。无法发布新信息或创建及加入群聊。" chatNotAvailableInOtherAccount: "对方账户目前处于无法使用聊天的状态。" cannotChatWithTheUser: "无法与此用户聊天" cannotChatWithTheUser_description: "可能现在无法使用聊天,或者对方未开启聊天。" @@ -1929,7 +1932,7 @@ _role: canImportFollowing: "允许导入关注列表" canImportMuting: "允许导入隐藏列表" canImportUserLists: "允许导入用户列表" - canChat: "允许聊天" + chatAvailability: "允许聊天" _condition: roleAssignedTo: "已分配给手动角色" isLocal: "是本地用户" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 4a57debf77..a5c275b2e3 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1342,6 +1342,7 @@ bottom: "下" top: "上" embed: "嵌入" settingsMigrating: "正在移轉設定。請稍候……(之後也可以到「設定 → 其他 → 舊設定資訊移轉」中手動進行移轉)" +readonly: "唯讀" _chat: noMessagesYet: "尚無訊息" newMessage: "新訊息" @@ -1371,6 +1372,7 @@ _chat: muteThisRoom: "此聊天室已靜音" deleteRoom: "刪除聊天室" chatNotAvailableForThisAccountOrServer: "這個伺服器或這個帳號的聊天功能尚未啟用。" + chatIsReadOnlyForThisAccountOrServer: "在此伺服器或此帳戶上的聊天是唯讀的。您無法發布新訊息、建立或加入聊天室。" chatNotAvailableInOtherAccount: "對方的帳號無法使用聊天功能。" cannotChatWithTheUser: "無法與此使用者聊天" cannotChatWithTheUser_description: "聊天功能目前無法使用,或對方尚未開放聊天功能。" @@ -1436,7 +1438,7 @@ _preferencesBackup: _accountSettings: requireSigninToViewContents: "須登入以顯示內容" requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。" - requireSigninToViewContentsDescription2: "來自不支援 URL 預覽 (OGP)、 網頁嵌入和引用貼文的伺服器,也將停止顯示。" + requireSigninToViewContentsDescription2: "針對您貼文的 URL 預覽 (OGP) 與網頁嵌入功能將會無法使用。而不支援引用貼文的伺服器,也將停止顯示。" requireSigninToViewContentsDescription3: "這些限制可能不適用於被聯邦發送至遠端伺服器的內容。" makeNotesFollowersOnlyBefore: "讓過去的貼文僅對追隨者顯示" makeNotesFollowersOnlyBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對追隨者顯示。 如果您再次停用它,貼文的公開狀態也會恢復原狀。" @@ -1931,7 +1933,7 @@ _role: canImportFollowing: "允許匯入追隨名單" canImportMuting: "允許匯入靜音名單" canImportUserLists: "允許匯入清單" - canChat: "允許聊天" + chatAvailability: "允許聊天" _condition: roleAssignedTo: "手動指派角色完成" isLocal: "本地使用者" From 3374a587a144f02bf29bd7d704c28f45f506e412 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:28:17 +0900 Subject: [PATCH 055/190] refactor --- packages/frontend/src/components/MkPageWindow.vue | 4 ++-- packages/frontend/src/components/global/MkSpacer.vue | 3 ++- packages/frontend/src/components/global/SearchMarker.vue | 4 ++-- packages/frontend/src/di.ts | 2 ++ packages/frontend/src/ui/deck/column.vue | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue index 5cb00c5292..32c2e48b01 100644 --- a/packages/frontend/src/components/MkPageWindow.vue +++ b/packages/frontend/src/components/MkPageWindow.vue @@ -117,7 +117,7 @@ windowRouter.addListener('change', ctx => { windowRouter.init(); provide(DI.router, windowRouter); -provide('inAppSearchMarkerId', searchMarkerId); +provide(DI.inAppSearchMarkerId, searchMarkerId); provideMetadataReceiver((metadataGetter) => { const info = metadataGetter(); pageMetadata.value = info; @@ -125,7 +125,7 @@ provideMetadataReceiver((metadataGetter) => { provideReactiveMetadata(pageMetadata); provide('shouldOmitHeaderTitle', true); provide('shouldHeaderThin', true); -provide('forceSpacerMin', true); +provide(DI.forceSpacerMin, true); const contextmenu = computed(() => ([{ icon: 'ti ti-player-eject', diff --git a/packages/frontend/src/components/global/MkSpacer.vue b/packages/frontend/src/components/global/MkSpacer.vue index 6080bad9cd..c3bc37cb92 100644 --- a/packages/frontend/src/components/global/MkSpacer.vue +++ b/packages/frontend/src/components/global/MkSpacer.vue @@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/deck.ts b/packages/frontend/src/deck.ts index 9df56c52df..c108a365b6 100644 --- a/packages/frontend/src/deck.ts +++ b/packages/frontend/src/deck.ts @@ -38,6 +38,7 @@ export const columnTypes = [ 'mentions', 'direct', 'roleTimeline', + 'chat', ] as const; export type ColumnType = typeof columnTypes[number]; diff --git a/packages/frontend/src/pages/chat/home.home.vue b/packages/frontend/src/pages/chat/home.home.vue index a8ed891de0..a0853fb0c9 100644 --- a/packages/frontend/src/pages/chat/home.home.vue +++ b/packages/frontend/src/pages/chat/home.home.vue @@ -34,34 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only -
- - - -
-
- {{ item.message.toRoom.name }} - -
-
- - - -
-
{{ i18n.ts.you }}:{{ item.message.text }}
-
-
-
-
-
{{ i18n.ts._chat.noHistory }}
-
- +
@@ -81,20 +54,12 @@ import { updateCurrentAccountPartial } from '@/accounts.js'; import MkInput from '@/components/MkInput.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkInfo from '@/components/MkInfo.vue'; +import MkChatHistories from '@/components/MkChatHistories.vue'; const $i = ensureSignin(); const router = useRouter(); -const initializing = ref(true); -const fetching = ref(false); -const history = ref<{ - id: string; - message: Misskey.entities.ChatMessage; - other: Misskey.entities.ChatMessage['fromUser'] | Misskey.entities.ChatMessage['toUser'] | null; - isMe: boolean; -}[]>([]); - const searchQuery = ref(''); const searched = ref(false); const searchResults = ref([]); @@ -148,57 +113,8 @@ async function search() { searched.value = true; } -async function fetchHistory() { - if (fetching.value) return; - - fetching.value = true; - - const [userMessages, roomMessages] = await Promise.all([ - misskeyApi('chat/history', { room: false }), - misskeyApi('chat/history', { room: true }), - ]); - - history.value = [...userMessages, ...roomMessages] - .toSorted((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) - .map(m => ({ - id: m.id, - message: m, - other: (!('room' in m) || m.room == null) ? (m.fromUserId === $i.id ? m.toUser : m.fromUser) : null, - isMe: m.fromUserId === $i.id, - })); - - fetching.value = false; - initializing.value = false; - - updateCurrentAccountPartial({ hasUnreadChatMessages: false }); -} - -let isActivated = true; - -onActivated(() => { - isActivated = true; -}); - -onDeactivated(() => { - isActivated = false; -}); - -useInterval(() => { - // TODO: DOM的にバックグラウンドになっていないかどうかも考慮する - if (!window.document.hidden && isActivated) { - fetchHistory(); - } -}, 1000 * 10, { - immediate: false, - afterMounted: true, -}); - -onActivated(() => { - fetchHistory(); -}); - onMounted(() => { - fetchHistory(); + updateCurrentAccountPartial({ hasUnreadChatMessages: false }); }); @@ -207,77 +123,6 @@ onMounted(() => { margin: 0 auto; } -.message { - position: relative; - display: flex; - padding: 16px 24px; - - &.isRead, - &.isMe { - opacity: 0.8; - } - - &:not(.isMe):not(.isRead) { - &::before { - content: ''; - position: absolute; - top: 8px; - right: 8px; - width: 8px; - height: 8px; - border-radius: 100%; - background-color: var(--MI_THEME-accent); - } - } -} - -.messageAvatar { - width: 50px; - height: 50px; - margin: 0 16px 0 0; -} - -.messageBody { - flex: 1; - min-width: 0; -} - -.messageHeader { - display: flex; - align-items: center; - margin-bottom: 2px; - white-space: nowrap; - overflow: clip; -} - -.messageHeaderName { - margin: 0; - padding: 0; - overflow: hidden; - text-overflow: ellipsis; - font-size: 1em; - font-weight: bold; -} - -.messageHeaderUsername { - margin: 0 8px; -} - -.messageHeaderTime { - margin-left: auto; -} - -.messageBodyText { - overflow: hidden; - overflow-wrap: break-word; - font-size: 1.1em; -} - -.youSaid { - font-weight: bold; - margin-right: 0.5em; -} - .searchResultItem { padding: 12px; border: solid 1px var(--MI_THEME-divider); diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 96961d951f..7556f513c2 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -97,6 +97,7 @@ import XWidgetsColumn from '@/ui/deck/widgets-column.vue'; import XMentionsColumn from '@/ui/deck/mentions-column.vue'; import XDirectColumn from '@/ui/deck/direct-column.vue'; import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue'; +import XChatColumn from '@/ui/deck/chat-column.vue'; import { mainRouter } from '@/router.js'; import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js'; @@ -114,6 +115,7 @@ const columnComponents = { mentions: XMentionsColumn, direct: XDirectColumn, roleTimeline: XRoleTimelineColumn, + chat: XChatColumn, }; mainRouter.navHook = (path, flag): boolean => { diff --git a/packages/frontend/src/ui/deck/chat-column.vue b/packages/frontend/src/ui/deck/chat-column.vue new file mode 100644 index 0000000000..791af2e44c --- /dev/null +++ b/packages/frontend/src/ui/deck/chat-column.vue @@ -0,0 +1,27 @@ + + + + + From 525b6a76773a25c7bb48761082fa93732567b138 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:37:29 +0900 Subject: [PATCH 094/190] feat(frontend): chat widget --- CHANGELOG.md | 1 + locales/index.d.ts | 4 ++ locales/ja-JP.yml | 1 + packages/frontend/src/widgets/WidgetChat.vue | 52 ++++++++++++++++++++ packages/frontend/src/widgets/index.ts | 2 + 5 files changed, 60 insertions(+) create mode 100644 packages/frontend/src/widgets/WidgetChat.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 90952614c9..38563da555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - ### Client +- Feat: チャットウィジェットを追加 - Feat: デッキにチャットカラムを追加 - Fix: ログアウトした際に処理が終了しない問題を修正 - Fix: 自動バックアップが設定されている環境でログアウト直前に設定をバックアップするように diff --git a/locales/index.d.ts b/locales/index.d.ts index 5885e04847..97e66be6d7 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9207,6 +9207,10 @@ export interface Locale extends ILocale { * 今日誕生日のユーザー */ "birthdayFollowings": string; + /** + * チャット + */ + "chat": string; }; "_cw": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 4a334c2b41..1801c8e15b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2421,6 +2421,7 @@ _widgets: chooseList: "リストを選択" clicker: "クリッカー" birthdayFollowings: "今日誕生日のユーザー" + chat: "チャット" _cw: hide: "隠す" diff --git a/packages/frontend/src/widgets/WidgetChat.vue b/packages/frontend/src/widgets/WidgetChat.vue new file mode 100644 index 0000000000..43b2a6e522 --- /dev/null +++ b/packages/frontend/src/widgets/WidgetChat.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/packages/frontend/src/widgets/index.ts b/packages/frontend/src/widgets/index.ts index ea17d484c5..aea810d1ea 100644 --- a/packages/frontend/src/widgets/index.ts +++ b/packages/frontend/src/widgets/index.ts @@ -35,6 +35,7 @@ export default function(app: App) { app.component('WidgetUserList', defineAsyncComponent(() => import('./WidgetUserList.vue'))); app.component('WidgetClicker', defineAsyncComponent(() => import('./WidgetClicker.vue'))); app.component('WidgetBirthdayFollowings', defineAsyncComponent(() => import('./WidgetBirthdayFollowings.vue'))); + app.component('WidgetChat', defineAsyncComponent(() => import('./WidgetChat.vue'))); } // 連合関連のウィジェット(連合無効時に隠す) @@ -70,6 +71,7 @@ export const widgets = [ 'userList', 'clicker', 'birthdayFollowings', + 'chat', ...federationWidgets, ]; From 6bd45a27b13c4c00d627ad056bc7b57047b9493d Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 15 Apr 2025 16:09:04 +0900 Subject: [PATCH 095/190] =?UTF-8?q?fix:=20=E3=83=95=E3=82=A9=E3=83=AB?= =?UTF-8?q?=E3=83=80=E3=82=92=E9=96=8B=E3=81=84=E3=81=9F=E7=8A=B6=E6=85=8B?= =?UTF-8?q?=E3=81=A7=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC=E3=81=8B=E3=82=89?= =?UTF-8?q?=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC=E3=83=89=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=82=82=E3=83=AB=E3=83=BC=E3=83=88=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AB=E3=83=80=E3=81=AB=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20(#15836)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: フォルダを開いた状態でメニューからアップロードしてもルートフォルダにアップロードされる問題 * docs(changelog): Fix: フォルダを開いた状態でメニューからアップロードしてもルートフォルダにアップロードされる問題を修正 #15836 --- CHANGELOG.md | 1 + packages/frontend/src/components/MkDrive.vue | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38563da555..3214ef936f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Feat: デッキにチャットカラムを追加 - Fix: ログアウトした際に処理が終了しない問題を修正 - Fix: 自動バックアップが設定されている環境でログアウト直前に設定をバックアップするように +- Fix: フォルダを開いた状態でメニューからアップロードしてもルートフォルダにアップロードされる問題を修正 #15836 ### Server - Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index c212167c8f..6270ac8314 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -626,13 +626,13 @@ function getMenu() { text: i18n.ts.upload + ' (' + i18n.ts.compress + ')', icon: 'ti ti-upload', action: () => { - chooseFileFromPc(true, { keepOriginal: false }); + chooseFileFromPc(true, { uploadFolder: folder.value?.id, keepOriginal: false }); }, }, { text: i18n.ts.upload, icon: 'ti ti-upload', action: () => { - chooseFileFromPc(true, { keepOriginal: true }); + chooseFileFromPc(true, { uploadFolder: folder.value?.id, keepOriginal: true }); }, }, { text: i18n.ts.fromUrl, From d5fe6e36aecd2551fb2f3b80af4d1c42e0010fc7 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 15 Apr 2025 16:10:17 +0900 Subject: [PATCH 096/190] =?UTF-8?q?fix:=20avatarId=20=E3=81=8C=20null=20?= =?UTF-8?q?=E3=81=AE=E3=81=A8=E3=81=8D=E3=81=AB=E3=82=82=20avatarUrl=20?= =?UTF-8?q?=E3=81=8C=20non=20null=20=E6=8B=85=E3=81=A3=E3=81=A6=E3=82=8B?= =?UTF-8?q?=E3=81=93=E3=81=A8=E3=81=8C=E3=81=82=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20(#15833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/WebhookTestService.ts | 8 ++++---- packages/backend/src/core/entities/UserEntityService.ts | 8 ++++---- packages/backend/src/models/User.ts | 4 ++++ packages/backend/src/server/ServerService.ts | 2 +- packages/backend/src/server/web/ClientServerService.ts | 2 +- packages/backend/src/server/web/FeedService.ts | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts index 222153fd2a..9cf985b688 100644 --- a/packages/backend/src/core/WebhookTestService.ts +++ b/packages/backend/src/core/WebhookTestService.ts @@ -411,8 +411,8 @@ export class WebhookTestService { name: user.name, username: user.username, host: user.host, - avatarUrl: user.avatarUrl, - avatarBlurhash: user.avatarBlurhash, + avatarUrl: user.avatarId == null ? null : user.avatarUrl, + avatarBlurhash: user.avatarId == null ? null : user.avatarBlurhash, avatarDecorations: user.avatarDecorations.map(it => ({ id: it.id, angle: it.angle, @@ -441,8 +441,8 @@ export class WebhookTestService { createdAt: new Date().toISOString(), updatedAt: user.updatedAt?.toISOString() ?? null, lastFetchedAt: user.lastFetchedAt?.toISOString() ?? null, - bannerUrl: user.bannerUrl, - bannerBlurhash: user.bannerBlurhash, + bannerUrl: user.bannerId == null ? null : user.bannerUrl, + bannerBlurhash: user.bannerId == null ? null : user.bannerBlurhash, isLocked: user.isLocked, isSilenced: false, isSuspended: user.isSuspended, diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index e252ff509e..d4769d24d4 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -486,8 +486,8 @@ export class UserEntityService implements OnModuleInit { name: user.name, username: user.username, host: user.host, - avatarUrl: user.avatarUrl ?? this.getIdenticonUrl(user), - avatarBlurhash: user.avatarBlurhash, + avatarUrl: (user.avatarId == null ? null : user.avatarUrl) ?? this.getIdenticonUrl(user), + avatarBlurhash: (user.avatarId == null ? null : user.avatarBlurhash), avatarDecorations: user.avatarDecorations.length > 0 ? this.avatarDecorationService.getAll().then(decorations => user.avatarDecorations.filter(ud => decorations.some(d => d.id === ud.id)).map(ud => ({ id: ud.id, angle: ud.angle || undefined, @@ -533,8 +533,8 @@ export class UserEntityService implements OnModuleInit { createdAt: this.idService.parse(user.id).date.toISOString(), updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null, - bannerUrl: user.bannerUrl, - bannerBlurhash: user.bannerBlurhash, + bannerUrl: user.bannerId == null ? null : user.bannerUrl, + bannerBlurhash: user.bannerId == null ? null : user.bannerBlurhash, isLocked: user.isLocked, isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote), isSuspended: user.isSuspended, diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index bc652cea62..baf4eefdf1 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -118,21 +118,25 @@ export class MiUser { @JoinColumn() public banner: MiDriveFile | null; + // avatarId が null になったとしてもこれが null でない可能性があるため、このフィールドを使うときは avatarId の non-null チェックをすること @Column('varchar', { length: 512, nullable: true, }) public avatarUrl: string | null; + // bannerId が null になったとしてもこれが null でない可能性があるため、このフィールドを使うときは bannerId の non-null チェックをすること @Column('varchar', { length: 512, nullable: true, }) public bannerUrl: string | null; + // avatarId が null になったとしてもこれが null でない可能性があるため、このフィールドを使うときは avatarId の non-null チェックをすること @Column('varchar', { length: 128, nullable: true, }) public avatarBlurhash: string | null; + // bannerId が null になったとしてもこれが null でない可能性があるため、このフィールドを使うときは bannerId の non-null チェックをすること @Column('varchar', { length: 128, nullable: true, }) diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index b899053287..355d7ca08e 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -221,7 +221,7 @@ export class ServerService implements OnApplicationShutdown { reply.header('Cache-Control', 'public, max-age=86400'); if (user) { - reply.redirect(user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user)); + reply.redirect((user.avatarId == null ? null : user.avatarUrl) ?? this.userEntityService.getIdenticonUrl(user)); } else { reply.redirect('/static-assets/user-unknown.png'); } diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 927970e2e2..30a911088e 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -534,7 +534,7 @@ export class ClientServerService { return await reply.view('user', { user, profile, me, - avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), + avatarUrl: _user.avatarUrl, sub: request.params.sub, ...await this.generateCommonPugData(this.meta), clientCtx: htmlSafeJsonStringify({ diff --git a/packages/backend/src/server/web/FeedService.ts b/packages/backend/src/server/web/FeedService.ts index 9d810ddc84..eae7645321 100644 --- a/packages/backend/src/server/web/FeedService.ts +++ b/packages/backend/src/server/web/FeedService.ts @@ -65,7 +65,7 @@ export class FeedService { generator: 'Misskey', description: `${user.notesCount} Notes, ${profile.followingVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.followersVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`, link: author.link, - image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), + image: (user.avatarId == null ? null : user.avatarUrl) ?? this.userEntityService.getIdenticonUrl(user), feedLinks: { json: `${author.link}.json`, atom: `${author.link}.atom`, From f454e820bd5f1698a25fde38277ce37adbd277dc Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 15 Apr 2025 16:14:52 +0900 Subject: [PATCH 097/190] feat: render quote note with `quote-inline` class for ap compatibility (#15818) --- packages/backend/src/core/MfmService.ts | 10 +++++++-- .../src/core/activitypub/ApMfmService.ts | 10 ++++----- .../src/core/activitypub/ApRendererService.ts | 22 +++++++++++++++---- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 00208927e2..28d980f718 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -6,7 +6,7 @@ import { URL } from 'node:url'; import { Inject, Injectable } from '@nestjs/common'; import * as parse5 from 'parse5'; -import { Window, XMLSerializer } from 'happy-dom'; +import { type Document, type HTMLParagraphElement, Window, XMLSerializer } from 'happy-dom'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { intersperse } from '@/misc/prelude/array.js'; @@ -23,6 +23,8 @@ type ChildNode = DefaultTreeAdapterMap['childNode']; const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; +export type Appender = (document: Document, body: HTMLParagraphElement) => void; + @Injectable() export class MfmService { constructor( @@ -267,7 +269,7 @@ export class MfmService { } @bindThis - public toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = []) { + public toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = [], additionalAppenders: Appender[] = []) { if (nodes == null) { return null; } @@ -492,6 +494,10 @@ export class MfmService { appendChildren(nodes, body); + for (const additionalAppender of additionalAppenders) { + additionalAppender(doc, body); + } + // Remove the unnecessary namespace const serialized = new XMLSerializer().serializeToString(body).replace(/^\s*

/, '

'); diff --git a/packages/backend/src/core/activitypub/ApMfmService.ts b/packages/backend/src/core/activitypub/ApMfmService.ts index 4036d2794a..f4c07e472c 100644 --- a/packages/backend/src/core/activitypub/ApMfmService.ts +++ b/packages/backend/src/core/activitypub/ApMfmService.ts @@ -5,7 +5,7 @@ import { Injectable } from '@nestjs/common'; import * as mfm from 'mfm-js'; -import { MfmService } from '@/core/MfmService.js'; +import { MfmService, Appender } from '@/core/MfmService.js'; import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import { extractApHashtagObjects } from './models/tag.js'; @@ -25,17 +25,17 @@ export class ApMfmService { } @bindThis - public getNoteHtml(note: Pick, apAppend?: string) { + public getNoteHtml(note: Pick, additionalAppender: Appender[] = []) { let noMisskeyContent = false; - const srcMfm = (note.text ?? '') + (apAppend ?? ''); + const srcMfm = (note.text ?? ''); const parsed = mfm.parse(srcMfm); - if (!apAppend && parsed?.every(n => ['text', 'unicodeEmoji', 'emojiCode', 'mention', 'hashtag', 'url'].includes(n.type))) { + if (!additionalAppender.length && parsed.every(n => ['text', 'unicodeEmoji', 'emojiCode', 'mention', 'hashtag', 'url'].includes(n.type))) { noMisskeyContent = true; } - const content = this.mfmService.toHtml(parsed, JSON.parse(note.mentionedRemoteUsers)); + const content = this.mfmService.toHtml(parsed, JSON.parse(note.mentionedRemoteUsers), additionalAppender); return { content, diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index f01874952f..55521d6e3a 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -19,7 +19,7 @@ import type { MiEmoji } from '@/models/Emoji.js'; import type { MiPoll } from '@/models/Poll.js'; import type { MiPollVote } from '@/models/PollVote.js'; import { UserKeypairService } from '@/core/UserKeypairService.js'; -import { MfmService } from '@/core/MfmService.js'; +import { MfmService, type Appender } from '@/core/MfmService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import type { MiUserKeypair } from '@/models/UserKeypair.js'; @@ -430,10 +430,24 @@ export class ApRendererService { poll = await this.pollsRepository.findOneBy({ noteId: note.id }); } - let apAppend = ''; + const apAppend: Appender[] = []; if (quote) { - apAppend += `\n\nRE: ${quote}`; + // Append quote link as `

RE: ...` + // the claas name `quote-inline` is used in non-misskey clients for styling quote notes. + // For compatibility, the span part should be kept as possible. + apAppend.push((doc, body) => { + body.appendChild(doc.createElement('br')); + body.appendChild(doc.createElement('br')); + const span = doc.createElement('span'); + span.className = 'quote-inline'; + span.appendChild(doc.createTextNode('RE: ')); + const link = doc.createElement('a'); + link.setAttribute('href', quote); + link.textContent = quote; + span.appendChild(link); + body.appendChild(span); + }); } const summary = note.cw === '' ? String.fromCharCode(0x200B) : note.cw; @@ -509,7 +523,7 @@ export class ApRendererService { const urlPart = match[0]; const urlPartParsed = new URL(urlPart); const restPart = maybeUrl.slice(match[0].length); - + return `${urlPart}${restPart}`; } catch (e) { return maybeUrl; From b2e3e658965b52873dd6771cf9771b3032a0ed15 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 15 Apr 2025 16:15:27 +0900 Subject: [PATCH 098/190] fix: use ftt for outbox (#15819) * fix: use ftt for outbox * chore: check for enableFanoutTimeline * lint: fix lint --- .../src/core/FanoutTimelineEndpointService.ts | 2 +- .../src/server/ActivityPubServerService.ts | 48 +++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/core/FanoutTimelineEndpointService.ts b/packages/backend/src/core/FanoutTimelineEndpointService.ts index b05af99c5e..ce8cc83dfd 100644 --- a/packages/backend/src/core/FanoutTimelineEndpointService.ts +++ b/packages/backend/src/core/FanoutTimelineEndpointService.ts @@ -54,7 +54,7 @@ export class FanoutTimelineEndpointService { } @bindThis - private async getMiNotes(ps: TimelineOptions): Promise { + async getMiNotes(ps: TimelineOptions): Promise { // 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]); diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index 72d57a9b1b..f7b22c44c4 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -32,6 +32,7 @@ import { isQuote, isRenote } from '@/misc/is-renote.js'; import * as Acct from '@/misc/acct.js'; import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify'; import type { FindOptionsWhere } from 'typeorm'; +import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; const ACTIVITY_JSON = 'application/activity+json; charset=utf-8'; const LD_JSON = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8'; @@ -75,6 +76,7 @@ export class ActivityPubServerService { private queueService: QueueService, private userKeypairService: UserKeypairService, private queryService: QueryService, + private fanoutTimelineEndpointService: FanoutTimelineEndpointService, ) { //this.createServer = this.createServer.bind(this); } @@ -461,16 +463,28 @@ export class ActivityPubServerService { const partOf = `${this.config.url}/users/${userId}/outbox`; if (page) { - const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId) - .andWhere('note.userId = :userId', { userId: user.id }) - .andWhere(new Brackets(qb => { - qb - .where('note.visibility = \'public\'') - .orWhere('note.visibility = \'home\''); - })) - .andWhere('note.localOnly = FALSE'); - - const notes = await query.limit(limit).getMany(); + const notes = this.meta.enableFanoutTimeline ? await this.fanoutTimelineEndpointService.getMiNotes({ + sinceId: sinceId ?? null, + untilId: untilId ?? null, + limit: limit, + allowPartial: false, // Possibly true? IDK it's OK for ordered collection. + me: null, + redisTimelines: [ + `userTimeline:${user.id}`, + `userTimelineWithReplies:${user.id}`, + ], + useDbFallback: true, + ignoreAuthorFromMute: true, + excludePureRenotes: false, + noteFilter: (note) => { + if (note.visibility !== 'home' && note.visibility !== 'public') return false; + if (note.localOnly) return false; + return true; + }, + dbFallback: async (untilId, sinceId, limit) => { + return await this.getUserNotesFromDb(sinceId, untilId, limit, user.id); + }, + }) : await this.getUserNotesFromDb(sinceId ?? null, untilId ?? null, limit, user.id); if (sinceId) notes.reverse(); @@ -508,6 +522,20 @@ export class ActivityPubServerService { } } + @bindThis + private async getUserNotesFromDb(untilId: string | null, sinceId: string | null, limit: number, userId: MiUser['id']) { + return await this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId) + .andWhere('note.userId = :userId', { userId }) + .andWhere(new Brackets(qb => { + qb + .where('note.visibility = \'public\'') + .orWhere('note.visibility = \'home\''); + })) + .andWhere('note.localOnly = FALSE') + .limit(limit) + .getMany(); + } + @bindThis private async userInfo(request: FastifyRequest, reply: FastifyReply, user: MiUser | null) { if (this.meta.federation === 'none') { From fff2783c1b8b7d0ce30841e83d917091f40b521b Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:15:56 +0900 Subject: [PATCH 099/190] =?UTF-8?q?docs:=20=E3=83=90=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=A2=E3=83=83=E3=83=97=E3=81=A8=E3=83=AD=E3=82=B0=E3=82=A2?= =?UTF-8?q?=E3=82=A6=E3=83=88=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=82=AF=E3=83=AA?= =?UTF-8?q?=E3=82=A2=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E6=9B=B8=E3=81=8D?= =?UTF-8?q?=E6=96=B9=E3=82=92=E5=A4=89=E3=81=88=E3=82=8B=20(#15808)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 「新しいクライアントからログインしたとき」がすでにログインしたことのあるクライアントだとバックアップが必要ないと読めるので「新しい」を外す 2. ログアウトしてから設定データをブラウザから削除したあとで復元できるのはバックアップをとっているときのみであることを強調 cc 1312fe34c1e499bf537f0ee49e6d72683e0101ef --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3214ef936f..f74f92c606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,7 @@ - プラグイン、テーマ、クライアントに追加されたすべてのアカウント情報も含まれるようになりました - 自動で設定データをサーバーにバックアップできるように - 設定→設定のプロファイル→自動バックアップ で有効にできます - - 新しいデバイスからログインしたり、ブラウザから設定データが消えてしまったときに自動で復元されます(復元をスキップすることも可能) + - ログインしたとき、ブラウザから設定データが消えてしまったときに自動で復元されます(復元をスキップすることも可能) - 任意の設定項目をデバイス間で同期できるように - 設定項目の「...」メニュー→「デバイス間で同期」 - 同期をオンにした際にサーバーに保存された値とローカルの値が競合する場合はどちらを優先するか選択できます @@ -58,7 +58,7 @@ - アカウントごとに設定値が分離される設定とそうでないクライアント設定が混在していた(かつ分離するかどうかを設定不可だった)のを、基本的に一律でクライアント全体に適用されるようにし、個別でアカウントごとに異なる設定を行えるように - 設定項目の「...」メニュー→「アカウントで上書き」をオンにすることで、設定値をそのアカウントでだけ適用するようにできます - ログアウトすると設定データもブラウザから消去されるようになりプライバシーが向上しました - - 再度ログインすればサーバーのバックアップから設定データを復元可能です + - バックアップを有効にしている場合、ログインした後にバックアップから設定データを復元可能です - エクスポートした設定データを他のサーバーでインポートして適用すること(設定の持ち運び)が可能になりました - 設定情報の移行は自動で行われますが、何らかの理由で失敗した場合、設定→その他→旧設定情報を移行 で再試行可能です - 過去に作成されたバックアップデータとは現在互換性がありませんのでご注意ください From fc6037af461412d914cd35a00fa004ad26d19c0f Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 18:27:45 +0900 Subject: [PATCH 100/190] enhance(backend): push notification for chat message Resolve #15831 --- CHANGELOG.md | 2 +- packages/backend/src/core/ChatService.ts | 4 ++-- .../src/core/PushNotificationService.ts | 1 + packages/sw/src/scripts/create-notification.ts | 18 ++++++++++++++++++ packages/sw/src/scripts/operations.ts | 10 +++++++++- packages/sw/src/sw.ts | 4 ++++ packages/sw/src/types.ts | 1 + 7 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f74f92c606..81b8f88536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Unreleased ### General -- +- Enhance: チャットの新規メッセージをプッシュ通知するように ### Client - Feat: チャットウィジェットを追加 diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts index b0e8cfb61c..9d294a80cb 100644 --- a/packages/backend/src/core/ChatService.ts +++ b/packages/backend/src/core/ChatService.ts @@ -232,7 +232,7 @@ export class ChatService { const packedMessageForTo = await this.chatEntityService.packMessageDetailed(inserted, toUser); this.globalEventService.publishMainStream(toUser.id, 'newChatMessage', packedMessageForTo); - //this.pushNotificationService.pushNotification(toUser.id, 'newChatMessage', packedMessageForTo); + this.pushNotificationService.pushNotification(toUser.id, 'newChatMessage', packedMessageForTo); }, 3000); } @@ -302,7 +302,7 @@ export class ChatService { if (marker == null) continue; this.globalEventService.publishMainStream(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo); - //this.pushNotificationService.pushNotification(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo); + this.pushNotificationService.pushNotification(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo); } }, 3000); diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index 1479bb00d9..9333c1ebc5 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -22,6 +22,7 @@ type PushNotificationsTypes = { note: Packed<'Note'>; }; 'readAllNotifications': undefined; + newChatMessage: Packed<'ChatMessage'>; }; // Reduce length because push message servers have character limits diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 364328d4b0..77b3f88791 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -268,6 +268,24 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif data, renotify: true, }]; + case 'newChatMessage': + if (data.body.toRoom != null) { + return [`${data.body.toRoom.name}: ${getUserName(data.body.fromUser)}: ${data.body.text}`, { + icon: data.body.fromUser.avatarUrl, + badge: iconUrl('messages'), + tag: `chat:room:${data.body.toRoomId}`, + data, + renotify: true, + }]; + } else { + return [`${getUserName(data.body.fromUser)}: ${data.body.text}`, { + icon: data.body.fromUser.avatarUrl, + badge: iconUrl('messages'), + tag: `chat:user:${data.body.fromUserId}`, + data, + renotify: true, + }]; + } default: return null; } diff --git a/packages/sw/src/scripts/operations.ts b/packages/sw/src/scripts/operations.ts index 8862c6faa5..3e72b7e7c2 100644 --- a/packages/sw/src/scripts/operations.ts +++ b/packages/sw/src/scripts/operations.ts @@ -16,7 +16,7 @@ export const cli = new Misskey.api.APIClient({ origin, fetch: (...args): Promise export async function api< E extends keyof Misskey.Endpoints, - P extends Misskey.Endpoints[E]['req'] + P extends Misskey.Endpoints[E]['req'], >(endpoint: E, userId?: string, params?: P): Promise | undefined> { let account: Pick | undefined; @@ -60,6 +60,14 @@ export function openAntenna(antennaId: string, loginId: string): ReturnType { + if (body.toRoomId != null) { + return openClient('push', `/chat/room/${body.toRoomId}`, loginId, { body }); + } else { + return openClient('push', `/chat/user/${body.toUserId}`, loginId, { body }); + } +} + // post-formのオプションから投稿フォームを開く export async function openPost(options: { initialText?: string; reply?: Misskey.entities.Note; renote?: Misskey.entities.Note }, loginId?: string): ReturnType { // クエリを作成しておく diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index bf980b83a4..298af4b4b6 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -76,6 +76,7 @@ globalThis.addEventListener('push', ev => { // case 'driveFileCreated': case 'notification': case 'unreadAntennaNote': + case 'newChatMessage': // 1日以上経過している場合は無視 if (Date.now() - data.dateTime > 1000 * 60 * 60 * 24) break; @@ -155,6 +156,9 @@ globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEv case 'unreadAntennaNote': client = await swos.openAntenna(data.body.antenna.id, loginId); break; + case 'newChatMessage': + client = await swos.openChat(data.body, loginId); + break; default: switch (action) { case 'markAllAsRead': diff --git a/packages/sw/src/types.ts b/packages/sw/src/types.ts index 4f82779808..549220396c 100644 --- a/packages/sw/src/types.ts +++ b/packages/sw/src/types.ts @@ -23,6 +23,7 @@ type PushNotificationDataSourceMap = { note: Misskey.entities.Note; }; readAllNotifications: undefined; + newChatMessage: Misskey.entities.ChatMessage; }; export type PushNotificationData = { From 45d65ffbba1145870686c0f8c7799ce900e98a9a Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 18:29:22 +0900 Subject: [PATCH 101/190] New Crowdin updates (#15786) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Spanish) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (German) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (English) --- locales/ca-ES.yml | 19 +++++++++++-------- locales/de-DE.yml | 2 ++ locales/en-US.yml | 2 ++ locales/es-ES.yml | 39 +++++++++++++++++++++++++++++++++++++++ locales/it-IT.yml | 19 ++++++++++++++----- locales/ko-KR.yml | 24 +++++++++++++----------- locales/zh-CN.yml | 3 +++ locales/zh-TW.yml | 8 ++++++-- 8 files changed, 90 insertions(+), 26 deletions(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 8f83a33356..129c3d24a5 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -356,7 +356,7 @@ banner: "Bàner" displayOfSensitiveMedia: "Visualització de contingut sensible" whenServerDisconnected: "Quan es perdi la connexió al servidor" disconnectedFromServer: "Desconnectat pel servidor" -reload: "Actualitza" +reload: "Actualitzar" doNothing: "Ignora" reloadConfirm: "Vols recarregar?" watch: "Veure" @@ -708,7 +708,7 @@ notificationSetting: "Paràmetres de notificacions" notificationSettingDesc: "Selecciona els tipus de notificacions que es mostraran" useGlobalSetting: "Fer servir la configuració global" useGlobalSettingDesc: "Si s'activa, es farà servir la configuració de notificacions del teu comte. Si no s'activa es poden fer configuracions individuals." -other: "Altre" +other: "Altres" regenerateLoginToken: "Regenerar clau de seguretat d'inici de sessió" regenerateLoginTokenDescription: "Regenera la clau de seguretat que es fa servir internament durant l'inici de sessió. Normalment aquesta acció no és necessària. Si es regenera es tancarà la sessió a tots els dispositius amb una sessió activa." theKeywordWhenSearchingForCustomEmoji: "Cercar un emoji personalitzat " @@ -979,6 +979,7 @@ document: "Documentació" numberOfPageCache: "Nombre de pàgines a la memòria cau" numberOfPageCacheDescription: "Incrementant aquest nombre farà que millori l'experiència de l'usuari, però es farà servir més memòria al dispositiu de l'usuari." logoutConfirm: "Vols sortir?" +logoutWillClearClientData: "En tancar la sessió, la informació del client al navegador s'esborrarà. Per garantir que la informació de configuració es pugui restaurar en tornar a iniciar sessió activa la còpia de seguretat automàtica de la configuració." lastActiveDate: "Fet servir per última vegada" statusbar: "Barra d'estat" pleaseSelect: "Selecciona una opció" @@ -1334,14 +1335,14 @@ postForm: "Formulari de publicació" textCount: "Nombre de caràcters " information: "Informació" chat: "Xat" -migrateOldSettings: "Migració de la configuració antiga " +migrateOldSettings: "Migrar la configuració anterior" migrateOldSettings_description: "Normalment això es fa automàticament, però si la transició no es fa, el procés es pot iniciar manualment. S'esborrarà la configuració actual." compress: "Comprimir " right: "Dreta" bottom: "A baix " top: "A dalt " embed: "Incrustar" -settingsMigrating: "Estem fent la migració de la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard i manualment anant a Preferències → Altres configuracions → Migrar configuració antiga)" +settingsMigrating: "Estem migrant la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard, manualment, anant a Preferències → Altres → Migrar configuració antiga)" readonly: "Només lectura" goToDeck: "Tornar al tauler" _chat: @@ -1359,7 +1360,7 @@ _chat: noInvitations: "No tens cap invitació " history: "Historial de converses " noHistory: "No hi ha un registre previ" - noRooms: "No hi ha habitacions" + noRooms: "No hi ha cap sala" inviteUser: "Invitar usuaris" sentInvitations: "Enviar invitacions" join: "Afegir-se " @@ -1417,8 +1418,8 @@ _settings: makeEveryTextElementsSelectable_description: "L'activació pot reduir la usabilitat en determinades ocasions." useStickyIcons: "Utilitza icones fixes" showNavbarSubButtons: "Mostrar sub botons a la barra de navegació " - ifOn: "Quan s'encén " - ifOff: "Quan s'apaga " + ifOn: "Quan s'activa" + ifOff: "Quan es desactiva" enableSyncThemesBetweenDevices: "Sincronitzar els temes instal·lats entre dispositius" _chat: showSenderName: "Mostrar el nom del remitent" @@ -1604,7 +1605,7 @@ _accountMigration: moveTo: "Migrar aquest compte a un altre" moveToLabel: "Compte al qual es vol migrar:" moveCannotBeUndone: "Les migracions dels comptes no es poden desfer." - moveAccountDescription: "Això migrarà la teva compte a un altre diferent.\n ・Els seguidors d'aquest compte és passaran al compte nou de forma automàtica\n ・Es deixaran de seguir a tots els usuaris que es segueixen actualment en aquest compte\n ・No es poden crear notes noves, etc. en aquest compte\n\nSi bé la migració de seguidors es automàtica, has de preparar alguns pasos manualment per migrar la llista d'usuaris que segueixes. Per fer això has d'exportar els seguidors que després importaraes al compte nou mitjançant el menú de configuració. El mateix procediment s'ha de seguir per less teves llistes i els teus usuaris silenciats i bloquejats.\n\n(Aquesta explicació s'aplica a Misskey v13.12.0 i posteriors. Altres aplicacions, com Mastodon, poden funcionar diferent.)" + moveAccountDescription: "Això migrarà el teu compte a un altre diferent.\n ・Els seguidors d'aquest compte és passaran al compte nou de forma automàtica\n ・Es deixaran de seguir a tots els usuaris que es segueixen actualment en aquest compte\n ・No es poden crear notes noves, etc. en aquest compte\n\nSi bé la migració de seguidors es automàtica, has de preparar alguns pasos manualment per migrar la llista d'usuaris que segueixes. Per fer això has d'exportar els seguidors que després importaraes al compte nou mitjançant el menú de configuració. El mateix procediment s'ha de seguir per less teves llistes i els teus usuaris silenciats i bloquejats.\n\n(Aquesta explicació s'aplica a Misskey v13.12.0 i posteriors. Altres aplicacions, com Mastodon, poden funcionar diferent.)" moveAccountHowTo: "Per fer la migració, primer has de crear un àlies per aquest compte al compte al qual vols migrar.\nDesprés de crear l'àlies, introdueix el compte al qual vols migrar amb el format següent: @nomusuari@servidor.exemple.com" startMigration: "Migrar" migrationConfirm: "Vols migrar aquest compte a {account}? Una vegada comenci la migració no es podrà parar O fer marxa enrere i no podràs tornar a fer servir aquest compte mai més." @@ -2368,6 +2369,7 @@ _widgets: chooseList: "Tria una llista" clicker: "Clicker" birthdayFollowings: "Usuaris que fan l'aniversari avui" + chat: "Xat" _cw: hide: "Amagar" show: "Carregar més" @@ -2634,6 +2636,7 @@ _deck: mentions: "Mencions" direct: "Publicacions directes" roleTimeline: "Línia de temps dels rols" + chat: "Xat" _dialog: charactersExceeded: "Has arribat al màxim de caràcters! Actualment és {current} de {max}" charactersBelow: "Ets per sota del mínim de caràcters! Actualment és {current} de {min}" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index b953a5717e..237603299c 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -2368,6 +2368,7 @@ _widgets: chooseList: "Liste auswählen" clicker: "Klickzähler" birthdayFollowings: "Nutzer, die heute Geburtstag haben" + chat: "Chat" _cw: hide: "Inhalt verbergen" show: "Inhalt anzeigen" @@ -2634,6 +2635,7 @@ _deck: mentions: "Erwähnungen" direct: "Direktnachrichten" roleTimeline: "Rollenchronik" + chat: "Chat" _dialog: charactersExceeded: "Maximallänge überschritten! Momentan {current} von {max}" charactersBelow: "Minimallänge unterschritten! Momentan {current} von {min}" diff --git a/locales/en-US.yml b/locales/en-US.yml index 02cc24a8b3..533682fd4f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -2368,6 +2368,7 @@ _widgets: chooseList: "Select a list" clicker: "Clicker" birthdayFollowings: "Today's Birthdays" + chat: "Chat" _cw: hide: "Hide" show: "Show content" @@ -2634,6 +2635,7 @@ _deck: mentions: "Mentions" direct: "Direct notes" roleTimeline: "Role Timeline" + chat: "Chat" _dialog: charactersExceeded: "You've exceeded the maximum character limit! Currently at {current} of {max}." charactersBelow: "You're below the minimum character limit! Currently at {current} of {min}." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index f60e9beabe..713478b67e 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -301,6 +301,7 @@ uploadFromUrlMayTakeTime: "Subir el fichero puede tardar un tiempo." explore: "Explorar" messageRead: "Ya leído" noMoreHistory: "El historial se ha acabado" +startChat: "Nuevo Chat" nUsersRead: "Leído por {n} personas" agreeTo: "De acuerdo con {0}" agree: "De acuerdo." @@ -694,6 +695,7 @@ userSaysSomethingAbout: "{name} dijo algo sobre {word}" makeActive: "Activar" display: "Apariencia" copy: "Copiar" +copiedToClipboard: "Texto copiado al portapapeles" metrics: "Métricas" overview: "Resumen" logs: "Registros" @@ -1293,18 +1295,55 @@ passkeyVerificationFailed: "La verificación de la clave de acceso ha fallado." passkeyVerificationSucceededButPasswordlessLoginDisabled: "La verificación de la clave de acceso ha sido satisfactoria pero se ha deshabilitado el inicio de sesión sin contraseña." messageToFollower: "Mensaje a seguidores" target: "Para" +prohibitedWordsForNameOfUser: "Palabras prohibidas para nombres de usuario" +prohibitedWordsForNameOfUserDescription: "Si alguna de las cadenas de esta lista está incluida en el nombre del usuario, el nombre será denegado. Los usuarios con privilegios de moderador no se ven afectados por esta restricción." +yourNameContainsProhibitedWords: "Tu nombre contiene palabras prohibidas" +yourNameContainsProhibitedWordsDescription: "Si deseas usar este nombre, por favor contacta con tu administrador/a de tu servidor" +lockdown: "Bloqueo" +pleaseSelectAccount: "Seleccione una cuenta, por favor." +availableRoles: "Roles disponibles " +acknowledgeNotesAndEnable: "Activar después de comprender las precauciones" federationSpecified: "Este servidor opera en una federación de listas blancas. No puede interactuar con otros servidores que no sean los especificados por el administrador." federationDisabled: "La federación está desactivada en este servidor. No puede interactuar con usuarios de otros servidores" preferences: "Preferencias" postForm: "Formulario" information: "Información" +right: "Derecha" +bottom: "Abajo" +top: "Arriba" +embed: "Insertar" +settingsMigrating: "La configuración está siendo migrada, por favor espera un momento... (También puedes migrar manualmente más tarde yendo a Ajustes otros migrar configuración antigua" +readonly: "Solo Lectura" _chat: + noMessagesYet: "Aún no hay mensajes" + newMessage: "Mensajes nuevos" + individualChat: "Chat individual" + individualChat_description: "Mantén una conversación privada con otra persona." invitations: "Invitar" noHistory: "No hay datos en el historial" members: "Miembros" home: "Inicio" send: "Enviar" + chatNotAvailableInOtherAccount: "La función de chat está desactivada para el otro usuario." + cannotChatWithTheUser: "No se puede iniciar un chat con este usuario" + cannotChatWithTheUser_description: "El chat no está disponible o la otra parte no ha habilitado el chat." + chatWithThisUser: "Chatear" + thisUserAllowsChatOnlyFromFollowers: "Este usuario sólo acepta chats de seguidores." + thisUserAllowsChatOnlyFromFollowing: "Este usuario sólo acepta chats de los usuarios a los que sigue." + thisUserAllowsChatOnlyFromMutualFollowing: "Este usuario sólo acepta chats de usuarios que son seguidores mutuos." + thisUserNotAllowedChatAnyone: "Este usuario no acepta chats de nadie." + chatAllowedUsers: "A quién permitir chatear." + chatAllowedUsers_note: "Puedes chatear con cualquier persona a la que hayas enviado un mensaje de chat, independientemente de esta configuración." + _chatAllowedUsers: + everyone: "Todos" + followers: "Sólo sus propios seguidores." + following: "Solo usuarios que sigues" + mutual: "Solo seguidores mutuos" + none: "Nadie" +_emojiPalette: + palettes: "Paleta\n" _settings: + api: "API" webhook: "Webhook" _accountSettings: requireSigninToViewContents: "Se requiere iniciar sesión para ver el contenido" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 44b0858fe8..75691d817f 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -424,6 +424,7 @@ antennaExcludeBots: "Escludere i Bot" antennaKeywordsDescription: "Sparando con uno spazio indichi la condizione E (and). Separando con un a capo, indichi la condizione O (or)." notifyAntenna: "Invia notifiche delle nuove note" withFileAntenna: "Solo note con file in allegato" +excludeNotesInSensitiveChannel: "Escludere le Note dai canali espliciti" enableServiceworker: "Abilita ServiceWorker" antennaUsersDescription: "Elenca un nome utente per riga" caseSensitive: "Sensibile alla distinzione tra maiuscole e minuscole" @@ -727,7 +728,7 @@ reporterOrigin: "Segnalazione da" send: "Inviare" openInNewTab: "Apri in una nuova scheda" openInSideView: "Apri in vista laterale" -defaultNavigationBehaviour: "Navigazione preimpostata" +defaultNavigationBehaviour: "Tipo di navigazione predefinita" editTheseSettingsMayBreakAccount: "Modificare queste impostazioni può danneggiare il profilo" instanceTicker: "Informazioni sull'istanza da cui vengono le note" waitingFor: "Aspettando {x}" @@ -866,7 +867,7 @@ noBotProtectionWarning: "Non è stata impostata alcuna protezione dai Bot" configure: "Imposta" postToGallery: "Pubblicare nella galleria" postToHashtag: "Pubblica a questo hashtag" -gallery: "Galleria" +gallery: "Gallerie" recentPosts: "Pubblicazioni recenti" popularPosts: "Le più visualizzate" shareWithNote: "Condividere in nota" @@ -978,6 +979,7 @@ document: "Documentazione" numberOfPageCache: "Numero di pagine cache" numberOfPageCacheDescription: "Aumenta l'usabilità, ma aumenta anche il carico e l'utilizzo della memoria." logoutConfirm: "Vuoi davvero uscire da Misskey? " +logoutWillClearClientData: "All'uscita, la configurazione del client viene rimossa dal browser. Per ripristinarla quando si effettua nuovamente l'accesso, abilitare il backup automatico." lastActiveDate: "Data dell'ultimo utilizzo" statusbar: "Barra di stato" pleaseSelect: "Scegli un'opzione" @@ -1340,6 +1342,9 @@ right: "Destra" bottom: "Sotto" top: "Sopra" embed: "Incorporare" +settingsMigrating: "Migrazione delle impostazioni. Attendere prego ... (Puoi anche migrare manualmente in un secondo momento, nel menu: Impostazioni → Altro → Migrazione delle impostazioni)" +readonly: "Sola lettura" +goToDeck: "Torna al Deck" _chat: noMessagesYet: "Ancora nessun messaggio" newMessage: "Nuovo messaggio" @@ -1369,6 +1374,7 @@ _chat: muteThisRoom: "Silenzia stanza" deleteRoom: "Elimina stanza" chatNotAvailableForThisAccountOrServer: "Questo server, o questo profilo ha disabilitato la chat." + chatIsReadOnlyForThisAccountOrServer: "Le chat, su questo server o su questo profilo, sono di sola lettura. Impossibile scrivere in chat o creare e partecipare a stanze." chatNotAvailableInOtherAccount: "La chat non è disponibile nel profilo dell'altra persona." cannotChatWithTheUser: "Impossibile chattare con questa persona" cannotChatWithTheUser_description: "La chat potrebbe non essere disponibile, oppure l'altra persona potrebbe non esserlo." @@ -1929,6 +1935,7 @@ _role: canImportFollowing: "Può importare Following" canImportMuting: "Può importare Silenziati" canImportUserLists: "Può importare liste di Profili" + chatAvailability: "Chat consentita" _condition: roleAssignedTo: "Assegnato a ruoli manualmente" isLocal: "Profilo locale" @@ -2362,6 +2369,7 @@ _widgets: chooseList: "Seleziona una lista" clicker: "Cliccheria" birthdayFollowings: "Compleanni del giorno" + chat: "Chat" _cw: hide: "Nascondere" show: "Continua la lettura..." @@ -2594,8 +2602,8 @@ _notification: renote: "Rinota" _deck: alwaysShowMainColumn: "Mostra sempre la colonna principale" - columnAlign: "Allineare colonne" - columnGap: "Margine tra le colonne" + columnAlign: "Allineamento delle colonne" + columnGap: "Spessore del margine tra colonne" deckMenuPosition: "Posizione del menu Deck" navbarPosition: "Posizione barra di navigazione" addColumn: "Aggiungi colonna" @@ -2624,10 +2632,11 @@ _deck: tl: "Timeline" antenna: "Antenne" list: "Liste" - channel: "Canale" + channel: "Canali" mentions: "Menzioni" direct: "Note Dirette" roleTimeline: "Timeline Ruolo" + chat: "Chat" _dialog: charactersExceeded: "Hai superato il limite di {max} caratteri! ({current})" charactersBelow: "Sei al di sotto del minimo di {min} caratteri! ({current})" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index fc578758a2..fb7db80186 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -489,7 +489,7 @@ next: "다음" retype: "다시 입력" noteOf: "{user}의 노트" quoteAttached: "인용함" -quoteQuestion: "인용해서 작성하시겠습니까?" +quoteQuestion: "인용해서 첨부하시겠습니까?" attachAsFileQuestion: "붙여넣으려는 글이 너무 깁니다. 텍스트 파일로 첨부하시겠습니까?" onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다" signinRequired: "진행하기 전에 로그인을 해 주세요" @@ -571,8 +571,8 @@ objectStorageSetPublicRead: "업로드할 때 'public-read'를 설정하기" s3ForcePathStyleDesc: "s3ForcePathStyle을 활성화하면, 버킷 이름을 URL의 호스트명이 아닌 경로의 일부로써 취급합니다. 셀프 호스트 Minio와 같은 서비스를 사용할 경우 활성화해야 할 수 있습니다." serverLogs: "서버 로그" deleteAll: "모두 삭제" -showFixedPostForm: "타임라인 상단에 글 작성란을 표시" -showFixedPostFormInChannel: "채널 타임라인 상단에 글 작성란을 표시" +showFixedPostForm: "타임라인 상단에 글 입력란을 표시" +showFixedPostFormInChannel: "채널 타임라인 상단에 글 입력란을 표시" withRepliesByDefaultForNewlyFollowed: "팔로우 할 때 기본적으로 답글을 타임라인에 나오게 하기" newNoteRecived: "새 노트가 있습니다" sounds: "소리" @@ -720,7 +720,7 @@ abuseReports: "신고" reportAbuse: "신고" reportAbuseRenote: "리노트 신고하기" reportAbuseOf: "{name} 신고하기" -fillAbuseReportDescription: "신고하려는 이유를 자세히 알려주세요. 특정 게시물을 신고할 때에는 게시물의 URL도 포함해 주세요." +fillAbuseReportDescription: "신고 사유를 자세히 기재해 주세요. 대상 노트나 페이지 등이 있는 경우에는 해당 URL도 기재해 주세요." abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다." reporter: "신고자" reporteeOrigin: "피신고자" @@ -825,7 +825,7 @@ editCode: "코드 수정" apply: "적용" receiveAnnouncementFromInstance: "이 서버의 알림을 이메일로 수신할게요" emailNotification: "메일 알림" -publish: "게시" +publish: "공개" inChannelSearch: "채널에서 검색" useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기" typingUsers: "{users}님이 입력 중" @@ -1081,7 +1081,7 @@ sensitiveWords: "민감한 단어" sensitiveWordsDescription: "설정한 단어가 포함된 노트의 공개 범위를 '홈'으로 강제합니다. 개행으로 구분하여 여러 개를 지정할 수 있습니다." sensitiveWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다." prohibitedWords: "금지 단어" -prohibitedWordsDescription: "설정된 단어가 포함되는 노트를 작성하려고 하면, 오류가 발생하도록 합니다. 줄바꿈으로 구분지어 복수 설정할 수 있습니다." +prohibitedWordsDescription: "설정된 단어가 포함되는 노트를 게시하려고 하면, 오류가 발생하도록 합니다. 줄바꿈으로 구분지어 복수 설정할 수 있습니다." prohibitedWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다." hiddenTags: "숨긴 해시태그" hiddenTagsDescription: "설정한 태그를 트렌드에 표시하지 않도록 합니다. 줄 바꿈으로 하나씩 나눠서 설정할 수 있습니다." @@ -1373,7 +1373,7 @@ _chat: muteThisRoom: "이 룸을 뮤트" deleteRoom: "룸을 삭제" chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다." - chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅방을 만들거나 참가할 수 없습니다." + chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅 룸을 만들거나 참가할 수 없습니다." chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다." cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다" cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다." @@ -1542,7 +1542,7 @@ _initialTutorial: description3: "이 외에도, '리스트 타임라인'이나 '채널 타임라인' 등이 있습니다. 자세한 사항은 {link}에서 확인하실 수 있습니다." _postNote: title: "노트 게시 설정" - description1: "Misskey에 노트를 쓸 때에는 다양한 옵션을 설정할 수 있습니다. 노트를 작성하는 화면은 이렇게 생겼습니다." + description1: "Misskey에 노트를 게시할 때에는 다양한 옵션 설정이 가능합니다. 노트를 게시할 때 쓰이는 '글 입력란'은 이렇게 생겼습니다." _visibility: description: "노트를 볼 수 있는 사람을 제한할 수 있습니다." public: "모든 유저에게 공개합니다." @@ -1562,7 +1562,7 @@ _initialTutorial: _howToMakeAttachmentsSensitive: title: "첨부 파일을 열람주의로 설정하려면?" description: "서버의 가이드라인에 따라 필요한 이미지, 또는 그대로 노출되기에 부적절한 미디어는 '열람 주의'를 설정해 주세요." - tryThisFile: "이 작성 창에 첨부된 이미지를 열람 주의로 설정해 보세요!" + tryThisFile: "이 입력란에 첨부된 이미지를 열람 주의로 설정해 보세요!" _exampleNote: note: "낫또 뚜껑 뜯다가 실수했다…" method: "첨부 파일을 열람 주의로 설정하려면, 해당 파일을 클릭하여 메뉴를 열고, '열람주의로 설정'을 클릭합니다." @@ -1816,7 +1816,7 @@ _achievements: description: "드라이브 폴더에 스스로를 넣게 했다" _reactWithoutRead: title: "읽고 답하긴 하시는 건가요?" - description: "100자가 넘는 노트를 작성한 지 3초 안에 리액션했다" + description: "100자가 넘는 노트를 게시한 지 3초 안에 리액션했다" _clickedClickHere: title: "여길 눌러보세요" description: "여기를 눌렀다" @@ -1845,7 +1845,7 @@ _achievements: _cookieClicked: title: "쿠키를 클릭하는 게임" description: "쿠키를 클릭했다" - flavor: "소프트웨어 착각하지 않았어?" + flavor: "소프트웨어 착각하지 않으셨나요?" _brainDiver: title: "Brain Diver" description: "Brain Diver로의 링크를 첨부했다" @@ -2368,6 +2368,7 @@ _widgets: chooseList: "리스트 선택" clicker: "클리커" birthdayFollowings: "오늘이 생일인 유저" + chat: "채팅" _cw: hide: "숨기기" show: "더 보기" @@ -2634,6 +2635,7 @@ _deck: mentions: "받은 멘션" direct: "다이렉트" roleTimeline: "역할 타임라인" + chat: "채팅" _dialog: charactersExceeded: "최대 글자수를 초과하였습니다! 현재 {current} / 최대 {max}" charactersBelow: "최소 글자수 미만입니다! 현재 {current} / 최소 {min}" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index b313c4ce1f..4b78b0a362 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -979,6 +979,7 @@ document: "文档" numberOfPageCache: "缓存页数" numberOfPageCacheDescription: "设置较高的值会更方便用户,但设备的负载和内存使用量会增加。" logoutConfirm: "是否确认登出?" +logoutWillClearClientData: "登出时将会从浏览器中删除客户端的设置信息。如果想要在再次登入时恢复设置信息,请在设置里打开自动备份。" lastActiveDate: "最后活跃时间" statusbar: "状态栏" pleaseSelect: "请选择" @@ -2367,6 +2368,7 @@ _widgets: chooseList: "选择列表" clicker: "点击器" birthdayFollowings: "今天是他们的生日" + chat: "聊天" _cw: hide: "隐藏" show: "查看更多" @@ -2633,6 +2635,7 @@ _deck: mentions: "提及" direct: "指定用户" roleTimeline: "角色时间线" + chat: "聊天" _dialog: charactersExceeded: "已经超过了最大字符数! 当前字符数 {current} / 限制字符数 {max}" charactersBelow: "低于最小字符数!当前字符数 {current} / 限制字符数 {min}" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 57b7e84b8a..cfe3b729f0 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -424,6 +424,7 @@ antennaExcludeBots: "排除機器人帳戶" antennaKeywordsDescription: "空格代表「以及」(AND),換行代表「或者」(OR)" notifyAntenna: "通知有新貼文" withFileAntenna: "僅帶有附件的貼文" +excludeNotesInSensitiveChannel: "排除敏感頻道的貼文" enableServiceworker: "啟用瀏覽器的推播通知" antennaUsersDescription: "填寫使用者名稱,以換行分隔" caseSensitive: "區分大小寫" @@ -978,6 +979,7 @@ document: "文件" numberOfPageCache: "快取頁面數" numberOfPageCacheDescription: "增加數量會提高便利性,但也會增加負荷與記憶體使用量。" logoutConfirm: "確定要登出嗎?" +logoutWillClearClientData: "當您登出時,客戶端的設定資訊將從瀏覽器中清除。為了能夠在重新登入時恢復您的設定資訊,請啟用設定內的自動備份選項。" lastActiveDate: "上次使用日期及時間" statusbar: "狀態列" pleaseSelect: "請選擇" @@ -1307,7 +1309,7 @@ availableRoles: "可用角色" acknowledgeNotesAndEnable: "了解注意事項後再開啟。" federationSpecified: "此伺服器以白名單聯邦的方式運作。除了管理員指定的伺服器外,它無法與其他伺服器互動。" federationDisabled: "此伺服器未開啟站台聯邦。無法與其他伺服器上的使用者互動。" -confirmOnReact: "反應時確認" +confirmOnReact: "在做出反應前先確認" reactAreYouSure: "用「 {emoji} 」反應嗎?" markAsSensitiveConfirm: "要將這個媒體設定為敏感嗎?" unmarkAsSensitiveConfirm: "要解除這個媒體的敏感設定嗎?" @@ -1444,7 +1446,7 @@ _accountSettings: makeNotesHiddenBefore: "隱藏過去的貼文" makeNotesHiddenBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對自己顯示(私密化)。 如果您再次停用它,貼文的公開狀態也會恢復原狀。" mayNotEffectForFederatedNotes: "聯邦發送至遠端伺服器的貼文可能會不受影響。" - mayNotEffectSomeSituations: "這些限制已經簡化。它們可能不適用於某些情況,例如在遠端伺服器上檢視或管理時。" + mayNotEffectSomeSituations: "這些限制僅是簡化版本。在某些情況下,例如在遠端伺服器上瀏覽或進行審核時,可能不會套用這些限制。" notesHavePassedSpecifiedPeriod: "早於指定時間的貼文" notesOlderThanSpecifiedDateAndTime: "指定時間和日期之前的貼文" _abuseUserReport: @@ -2366,6 +2368,7 @@ _widgets: chooseList: "選擇清單" clicker: "點擊器" birthdayFollowings: "今天生日的使用者" + chat: "聊天" _cw: hide: "隱藏" show: "顯示內容" @@ -2632,6 +2635,7 @@ _deck: mentions: "提及" direct: "指定使用者" roleTimeline: "角色時間軸" + chat: "聊天" _dialog: charactersExceeded: "您的貼文太長了!現時字數 {current}/限制字數 {max}" charactersBelow: "您的貼文太短了!現時字數 {current}/限制字數 {min}" From f5a89c253347eb78977e2d7adb3ba8998f5ebe7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Apr 2025 09:32:12 +0000 Subject: [PATCH 102/190] Bump version to 2025.4.1-alpha.0 --- CHANGELOG.md | 2 +- package.json | 2 +- packages/misskey-js/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81b8f88536..97c754a86b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 2025.4.1 ### General - Enhance: チャットの新規メッセージをプッシュ通知するように diff --git a/package.json b/package.json index 3e59baf982..88dfe766a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.0", + "version": "2025.4.1-alpha.0", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 64ac05e9a1..189826177a 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.0", + "version": "2025.4.1-alpha.0", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From ee29f31324ca3b0513325cbb14b25a59e6485d23 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:33:04 +0900 Subject: [PATCH 103/190] fix(frontend): make keep scroll pos of timeline --- CHANGELOG.md | 1 + .../src/use/use-scroll-position-keeper.ts | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 packages/frontend/src/use/use-scroll-position-keeper.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c754a86b..693b31c44a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix: ログアウトした際に処理が終了しない問題を修正 - Fix: 自動バックアップが設定されている環境でログアウト直前に設定をバックアップするように - Fix: フォルダを開いた状態でメニューからアップロードしてもルートフォルダにアップロードされる問題を修正 #15836 +- Fix: タイムラインのスクロール位置を記憶するように修正 ### Server - Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように diff --git a/packages/frontend/src/use/use-scroll-position-keeper.ts b/packages/frontend/src/use/use-scroll-position-keeper.ts new file mode 100644 index 0000000000..00cc51a459 --- /dev/null +++ b/packages/frontend/src/use/use-scroll-position-keeper.ts @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { throttle } from 'throttle-debounce'; +import { nextTick, onActivated, onUnmounted, watch } from 'vue'; +import type { Ref } from 'vue'; + +// note render skippingがオンだとズレるため、遷移直前にスクロール範囲に表示されているdata-scroll-anchor要素を特定して、復元時に当該要素までスクロールするようにする + +export function useScrollPositionKeeper(scrollContainerRef: Ref): void { + let anchorId: string | null = null; + + watch(scrollContainerRef, (el) => { + if (!el) return; + + const onScroll = () => { + if (!el) return; + const scrollContainerRect = el.getBoundingClientRect(); + const viewPosition = scrollContainerRect.height / 2; + + const anchorEls = el.querySelectorAll('[data-scroll-anchor]'); + for (let i = anchorEls.length - 1; i > -1; i--) { // 下から見た方が速い + const anchorEl = anchorEls[i] as HTMLElement; + const anchorRect = anchorEl.getBoundingClientRect(); + const anchorTop = anchorRect.top; + const anchorBottom = anchorRect.bottom; + if (anchorTop <= viewPosition && anchorBottom >= viewPosition) { + anchorId = anchorEl.getAttribute('data-scroll-anchor'); + break; + } + } + }; + + // ほんとはscrollイベントじゃなくてonBeforeDeactivatedでやりたい + // https://github.com/vuejs/vue/issues/9454 + // https://github.com/vuejs/rfcs/pull/284 + el.addEventListener('scroll', throttle(1000, onScroll), { passive: true }); + }, { + immediate: true, + }); + + onActivated(() => { + nextTick(() => { + if (!anchorId) return; + const scrollContainer = scrollContainerRef.value; + if (!scrollContainer) return; + const scrollAnchorEl = scrollContainer.querySelector(`[data-scroll-anchor="${anchorId}"]`); + if (!scrollAnchorEl) return; + scrollAnchorEl.scrollIntoView({ + behavior: 'instant', + block: 'center', + inline: 'center', + }); + }); + }); +} From 165830d6c8331f14da455cedcb4cd695aaa6c9b3 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:34:00 +0900 Subject: [PATCH 104/190] =?UTF-8?q?=E3=82=B3=E3=83=9F=E3=83=83=E3=83=88?= =?UTF-8?q?=E5=BF=98=E3=82=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkNotes.vue | 4 ++-- packages/frontend/src/pages/timeline.vue | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/MkNotes.vue b/packages/frontend/src/components/MkNotes.vue index ad6210816d..214d52ec7f 100644 --- a/packages/frontend/src/components/MkNotes.vue +++ b/packages/frontend/src/components/MkNotes.vue @@ -23,13 +23,13 @@ SPDX-License-Identifier: AGPL-3.0-only tag="div" > diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index 644b2d3d13..d2bf162ce5 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -52,12 +52,15 @@ import { miLocalStorage } from '@/local-storage.js'; import { availableBasicTimelines, hasWithReplies, isAvailableBasicTimeline, isBasicTimeline, basicTimelineIconClass } from '@/timelines.js'; import { prefer } from '@/preferences.js'; import { useRouter } from '@/router.js'; +import { useScrollPositionKeeper } from '@/use/use-scroll-position-keeper.js'; provide('shouldOmitHeaderTitle', true); const tlComponent = useTemplateRef('tlComponent'); const rootEl = useTemplateRef('rootEl'); +useScrollPositionKeeper(rootEl); + const router = useRouter(); router.useListener('same', () => { top(); From de19d9a4d429b4ce9d4713e647659fe6460bdd11 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:48:25 +0900 Subject: [PATCH 105/190] refactor(frontend): MkHorizontalSwipe -> MkSwiper --- .../src/components/{MkHorizontalSwipe.vue => MkSwiper.vue} | 0 packages/frontend/src/pages/about.vue | 6 +++--- packages/frontend/src/pages/announcements.vue | 6 +++--- packages/frontend/src/pages/channel.vue | 6 +++--- packages/frontend/src/pages/channels.vue | 6 +++--- packages/frontend/src/pages/chat/home.vue | 6 +++--- packages/frontend/src/pages/drive.file.vue | 6 +++--- packages/frontend/src/pages/explore.vue | 6 +++--- packages/frontend/src/pages/flash/flash-index.vue | 6 +++--- packages/frontend/src/pages/follow-requests.vue | 6 +++--- packages/frontend/src/pages/gallery/index.vue | 6 +++--- packages/frontend/src/pages/instance-info.vue | 6 +++--- packages/frontend/src/pages/my-clips/index.vue | 6 +++--- packages/frontend/src/pages/notifications.vue | 2 +- packages/frontend/src/pages/pages.vue | 6 +++--- packages/frontend/src/pages/search.vue | 6 +++--- packages/frontend/src/pages/user/index.vue | 6 +++--- packages/frontend/src/utility/touch.ts | 2 +- 18 files changed, 47 insertions(+), 47 deletions(-) rename packages/frontend/src/components/{MkHorizontalSwipe.vue => MkSwiper.vue} (100%) diff --git a/packages/frontend/src/components/MkHorizontalSwipe.vue b/packages/frontend/src/components/MkSwiper.vue similarity index 100% rename from packages/frontend/src/components/MkHorizontalSwipe.vue rename to packages/frontend/src/components/MkSwiper.vue diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue index b4315a5cfa..ec286f109f 100644 --- a/packages/frontend/src/pages/about.vue +++ b/packages/frontend/src/pages/about.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -28,7 +28,7 @@ import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/utility/achievements.js'; import { definePage } from '@/page.js'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; const XOverview = defineAsyncComponent(() => import('@/pages/about.overview.vue')); const XEmojis = defineAsyncComponent(() => import('@/pages/about.emojis.vue')); diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue index 1902267a6a..7a04914dd7 100644 --- a/packages/frontend/src/pages/announcements.vue +++ b/packages/frontend/src/pages/announcements.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -50,7 +50,7 @@ import { ref, computed } from 'vue'; import MkPagination from '@/components/MkPagination.vue'; import MkButton from '@/components/MkButton.vue'; import MkInfo from '@/components/MkInfo.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index a62e035198..e71d372722 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only import { computed, ref, defineAsyncComponent } from 'vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; const props = defineProps<{ fileId: string; diff --git a/packages/frontend/src/pages/explore.vue b/packages/frontend/src/pages/explore.vue index 85b9fe4932..bcece47e35 100644 --- a/packages/frontend/src/pages/explore.vue +++ b/packages/frontend/src/pages/explore.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -25,7 +25,7 @@ import XFeatured from './explore.featured.vue'; import XUsers from './explore.users.vue'; import XRoles from './explore.roles.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/pages/flash/flash-index.vue b/packages/frontend/src/pages/flash/flash-index.vue index 98ab587b55..4ef33cbe0f 100644 --- a/packages/frontend/src/pages/flash/flash-index.vue +++ b/packages/frontend/src/pages/flash/flash-index.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -43,7 +43,7 @@ import { computed, ref } from 'vue'; import MkFlashPreview from '@/components/MkFlashPreview.vue'; import MkPagination from '@/components/MkPagination.vue'; import MkButton from '@/components/MkButton.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { useRouter } from '@/router.js'; diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue index 36643b1acb..d467d875fd 100644 --- a/packages/frontend/src/pages/follow-requests.vue +++ b/packages/frontend/src/pages/follow-requests.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -52,7 +52,7 @@ import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { infoImageUrl } from '@/instance.js'; import { $i } from '@/i.js'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; const paginationComponent = useTemplateRef('paginationComponent'); diff --git a/packages/frontend/src/pages/gallery/index.vue b/packages/frontend/src/pages/gallery/index.vue index 4cf3fca83b..c6ce773ab0 100644 --- a/packages/frontend/src/pages/gallery/index.vue +++ b/packages/frontend/src/pages/gallery/index.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -50,7 +50,7 @@ import { watch, ref, computed } from 'vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkPagination from '@/components/MkPagination.vue'; import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; import { useRouter } from '@/router.js'; diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue index 66ddf627e4..fde462944c 100644 --- a/packages/frontend/src/pages/instance-info.vue +++ b/packages/frontend/src/pages/instance-info.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -153,7 +153,7 @@ import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; import MkPagination from '@/components/MkPagination.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import { getProxiedImageUrlNullable } from '@/utility/media-proxy.js'; import { dateString } from '@/filters/date.js'; import MkTextarea from '@/components/MkTextarea.vue'; diff --git a/packages/frontend/src/pages/my-clips/index.vue b/packages/frontend/src/pages/my-clips/index.vue index 1525bbef9b..5b9b3af90b 100644 --- a/packages/frontend/src/pages/my-clips/index.vue +++ b/packages/frontend/src/pages/my-clips/index.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -33,7 +33,7 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { clipsCache } from '@/cache.js'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; const pagination = { endpoint: 'clips/list' as const, diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue index 0a2bc02de5..61a1b2725c 100644 --- a/packages/frontend/src/pages/notifications.vue +++ b/packages/frontend/src/pages/notifications.vue @@ -24,7 +24,7 @@ import { computed, ref } from 'vue'; import { notificationTypes } from '@@/js/const.js'; import XNotifications from '@/components/MkNotifications.vue'; import MkNotes from '@/components/MkNotes.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; diff --git a/packages/frontend/src/pages/pages.vue b/packages/frontend/src/pages/pages.vue index c99d7f1a0f..d412bad616 100644 --- a/packages/frontend/src/pages/pages.vue +++ b/packages/frontend/src/pages/pages.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -41,7 +41,7 @@ import { computed, ref } from 'vue'; import MkPagePreview from '@/components/MkPagePreview.vue'; import MkPagination from '@/components/MkPagination.vue'; import MkButton from '@/components/MkButton.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { useRouter } from '@/router.js'; diff --git a/packages/frontend/src/pages/search.vue b/packages/frontend/src/pages/search.vue index e0cb2dcbab..814ddf3cb9 100644 --- a/packages/frontend/src/pages/search.vue +++ b/packages/frontend/src/pages/search.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -28,7 +28,7 @@ import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { notesSearchAvailable } from '@/utility/check-permissions.js'; import MkInfo from '@/components/MkInfo.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; +import MkSwiper from '@/components/MkSwiper.vue'; const props = withDefaults(defineProps<{ query?: string, diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue index 58f44d7591..83c7bf45bb 100644 --- a/packages/frontend/src/pages/user/index.vue +++ b/packages/frontend/src/pages/user/index.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only

- +
@@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
{{ i18n.ts.ok }} diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue index a569ab7c33..f5e77cbe4e 100644 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index 2335cc3db7..3dc5c2ef7e 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/admin/ads.vue b/packages/frontend/src/pages/admin/ads.vue index aa8ba2f7c3..c5baeda7b0 100644 --- a/packages/frontend/src/pages/admin/ads.vue +++ b/packages/frontend/src/pages/admin/ads.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/admin/announcements.vue b/packages/frontend/src/pages/admin/announcements.vue index ea7f0cc73d..b2d7b4889a 100644 --- a/packages/frontend/src/pages/admin/announcements.vue +++ b/packages/frontend/src/pages/admin/announcements.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue index 2674879f90..19258216f6 100644 --- a/packages/frontend/src/pages/admin/branding.vue +++ b/packages/frontend/src/pages/admin/branding.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/admin/custom-emojis-manager.local.list.search.vue b/packages/frontend/src/pages/admin/custom-emojis-manager.local.list.search.vue index ae43507d66..9938d5cc4a 100644 --- a/packages/frontend/src/pages/admin/custom-emojis-manager.local.list.search.vue +++ b/packages/frontend/src/pages/admin/custom-emojis-manager.local.list.search.vue @@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.search }}
- +
- +
{{ i18n.ts.search }} diff --git a/packages/frontend/src/pages/admin/custom-emojis-manager.register.vue b/packages/frontend/src/pages/admin/custom-emojis-manager.register.vue index 566acdea31..e8e944df32 100644 --- a/packages/frontend/src/pages/admin/custom-emojis-manager.register.vue +++ b/packages/frontend/src/pages/admin/custom-emojis-manager.register.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only --> From 7041a3de2a4880b4aa8fbab84de5e1a63b86eaca Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:57:47 +0900 Subject: [PATCH 176/190] chore: fix Chromatic CI diff strategy (#15902) --- .github/workflows/storybook.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 037e6dd7f1..57d1518d9d 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -35,10 +35,7 @@ jobs: ref: "refs/pull/${{ github.event.number }}/merge" - name: Checkout actual HEAD if: github.event_name == 'pull_request_target' - id: rev - run: | - echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT - git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3) + run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)" - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js 20.x @@ -81,21 +78,16 @@ jobs: if: github.event_name == 'pull_request_target' id: chromatic_pull_request run: | - DIFF="${{ steps.rev.outputs.base }} HEAD" - if [ "$DIFF" = "0000000000000000000000000000000000000000 HEAD" ]; then - DIFF="HEAD" - fi - CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff-tree --no-commit-id --name-only -r $(echo "$DIFF") | xargs))" + CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff-tree --no-commit-id --name-only -r origin/${GITHUB_BASE_REF}...origin/${GITHUB_HEAD_REF} | xargs))" if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then echo "skip=true" >> $GITHUB_OUTPUT fi - BRANCH="${{ github.event.pull_request.head.user.login }}:$HEAD_REF" - if [ "$BRANCH" = "misskey-dev:$HEAD_REF" ]; then - BRANCH="$HEAD_REF" + BRANCH="${{ github.event.pull_request.head.user.login }}:$GITHUB_HEAD_REF" + if [ "$BRANCH" = "misskey-dev:$GITHUB_HEAD_REF" ]; then + BRANCH="$GITHUB_HEAD_REF" fi pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name "$BRANCH" $(echo "$CHROMATIC_PARAMETER") env: - HEAD_REF: ${{ github.event.pull_request.head.ref }} CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - name: Notify that Chromatic detects changes uses: actions/github-script@v7.0.1 From b09bf25e14494030c375e6c1cbc2463ab5f8cbae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 13:03:36 +0900 Subject: [PATCH 177/190] chore(deps): update actions/setup-node action to v4.4.0 (#15901) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/api-misskey-js.yml | 2 +- .github/workflows/changelog-check.yml | 2 +- .github/workflows/check-misskey-js-autogen.yml | 2 +- .github/workflows/get-api-diff.yml | 2 +- .github/workflows/lint.yml | 6 +++--- .github/workflows/locale.yml | 2 +- .github/workflows/on-release-created.yml | 2 +- .github/workflows/storybook.yml | 2 +- .github/workflows/test-backend.yml | 4 ++-- .github/workflows/test-federation.yml | 2 +- .github/workflows/test-frontend.yml | 4 ++-- .github/workflows/test-misskey-js.yml | 2 +- .github/workflows/test-production.yml | 2 +- .github/workflows/validate-api-json.yml | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/api-misskey-js.yml b/.github/workflows/api-misskey-js.yml index 7d085821b7..6117e69c03 100644 --- a/.github/workflows/api-misskey-js.yml +++ b/.github/workflows/api-misskey-js.yml @@ -22,7 +22,7 @@ jobs: uses: pnpm/action-setup@v4.1.0 - name: Setup Node.js - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml index 2e94f433b7..5ca27749bb 100644 --- a/.github/workflows/changelog-check.yml +++ b/.github/workflows/changelog-check.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout head uses: actions/checkout@v4.2.2 - name: Setup Node.js - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' diff --git a/.github/workflows/check-misskey-js-autogen.yml b/.github/workflows/check-misskey-js-autogen.yml index 090dc70bd5..22d500c306 100644 --- a/.github/workflows/check-misskey-js-autogen.yml +++ b/.github/workflows/check-misskey-js-autogen.yml @@ -29,7 +29,7 @@ jobs: - name: setup node id: setup-node - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: pnpm diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml index c5a4f77336..2de73aff09 100644 --- a/.github/workflows/get-api-diff.yml +++ b/.github/workflows/get-api-diff.yml @@ -33,7 +33,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4c8b97e785..f27cce5b97 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -38,7 +38,7 @@ jobs: submodules: true - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - - uses: actions/setup-node@v4.3.0 + - uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' @@ -69,7 +69,7 @@ jobs: submodules: true - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - - uses: actions/setup-node@v4.3.0 + - uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' @@ -99,7 +99,7 @@ jobs: submodules: true - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - - uses: actions/setup-node@v4.3.0 + - uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/locale.yml b/.github/workflows/locale.yml index cee4c27ceb..68e45fdf61 100644 --- a/.github/workflows/locale.yml +++ b/.github/workflows/locale.yml @@ -20,7 +20,7 @@ jobs: submodules: true - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - - uses: actions/setup-node@v4.3.0 + - uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml index 9d15e0fcf1..13390f3aae 100644 --- a/.github/workflows/on-release-created.yml +++ b/.github/workflows/on-release-created.yml @@ -26,7 +26,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 57d1518d9d..ba745b6a2a 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -39,7 +39,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js 20.x - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version-file: '.node-version' cache: 'pnpm' diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 9c54b3665b..ba4eb27a58 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -62,7 +62,7 @@ jobs: fi done - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' @@ -109,7 +109,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-federation.yml b/.github/workflows/test-federation.yml index dc29de4d4f..fe30deb835 100644 --- a/.github/workflows/test-federation.yml +++ b/.github/workflows/test-federation.yml @@ -44,7 +44,7 @@ jobs: fi done - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index bec5169ed9..25d263f102 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -38,7 +38,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' @@ -93,7 +93,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml index 2d1bd20183..5b3aed9712 100644 --- a/.github/workflows/test-misskey-js.yml +++ b/.github/workflows/test-misskey-js.yml @@ -33,7 +33,7 @@ jobs: uses: pnpm/action-setup@v4.1.0 - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml index b77550a01f..70685e908e 100644 --- a/.github/workflows/test-production.yml +++ b/.github/workflows/test-production.yml @@ -26,7 +26,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' diff --git a/.github/workflows/validate-api-json.yml b/.github/workflows/validate-api-json.yml index 4023815cb1..77feb2b373 100644 --- a/.github/workflows/validate-api-json.yml +++ b/.github/workflows/validate-api-json.yml @@ -27,7 +27,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.3.0 + uses: actions/setup-node@v4.4.0 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' From 01230f6990f8a71246491a7189c51cb67b852c8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 28 Apr 2025 04:08:47 +0000 Subject: [PATCH 178/190] Bump version to 2025.4.1-beta.7 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 84b445a334..2cbb3b41a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.1-beta.6", + "version": "2025.4.1-beta.7", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index bc72e74550..16a7170069 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.1-beta.6", + "version": "2025.4.1-beta.7", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From c3b9a5346fff59817b4bc165ae13bbb9715795fb Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Mon, 28 Apr 2025 18:31:13 +0900 Subject: [PATCH 179/190] chore(ci): change the Test step to terminate with error in the federation test (#15903) * chore(ci): change the Test step to terminate with error in the federation test * chore(ci): always stop servers in the federation test --- .github/workflows/test-federation.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-federation.yml b/.github/workflows/test-federation.yml index fe30deb835..c739688dc9 100644 --- a/.github/workflows/test-federation.yml +++ b/.github/workflows/test-federation.yml @@ -71,18 +71,16 @@ jobs: docker compose logs | tail -n 300 exit 1 - name: Test - id: test - continue-on-error: true run: | cd packages/backend/test-federation docker compose run --no-deps tester - name: Log - if: ${{ steps.test.outcome == 'failure' }} + if: always() run: | cd packages/backend/test-federation docker compose logs - exit 1 - name: Stop servers + if: always() run: | cd packages/backend/test-federation docker compose down From aaa31c9d64498b9627c0ae3d0623f90bb9e589a5 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Mon, 28 Apr 2025 18:58:08 +0900 Subject: [PATCH 180/190] fix(backend): correct response schema of chat endpoints (#15904) --- .../api/endpoints/chat/messages/delete.ts | 3 - .../api/endpoints/chat/messages/react.ts | 3 - .../api/endpoints/chat/messages/unreact.ts | 3 - .../server/api/endpoints/chat/rooms/delete.ts | 3 - .../chat/rooms/invitations/ignore.ts | 3 - .../server/api/endpoints/chat/rooms/join.ts | 3 - .../server/api/endpoints/chat/rooms/leave.ts | 3 - .../server/api/endpoints/chat/rooms/mute.ts | 3 - packages/misskey-js/etc/misskey-js.api.md | 32 ---------- packages/misskey-js/src/autogen/endpoint.ts | 24 +++---- packages/misskey-js/src/autogen/entities.ts | 8 --- packages/misskey-js/src/autogen/types.ts | 64 +++++++------------ 12 files changed, 32 insertions(+), 120 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts index 63b75fb6a7..52a054303b 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/delete.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchMessage: { message: 'No such message.', diff --git a/packages/backend/src/server/api/endpoints/chat/messages/react.ts b/packages/backend/src/server/api/endpoints/chat/messages/react.ts index 5f61e7e992..2197e7bf80 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/react.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/react.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchMessage: { message: 'No such message.', diff --git a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts index 6784bb6ecf..adfcd232f9 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/unreact.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchMessage: { message: 'No such message.', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts b/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts index 82a8e1f30d..1ea81448c1 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/delete.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchRoom: { message: 'No such room.', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts index b8a228089b..88ea234527 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/ignore.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchRoom: { message: 'No such room.', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/join.ts b/packages/backend/src/server/api/endpoints/chat/rooms/join.ts index d561f9e03f..550b4da1a6 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/join.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/join.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchRoom: { message: 'No such room.', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts b/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts index a3ad0c2d6f..f99b408d67 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/leave.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchRoom: { message: 'No such room.', diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts b/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts index 11cbe7b8b9..ee60f92505 100644 --- a/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts +++ b/packages/backend/src/server/api/endpoints/chat/rooms/mute.ts @@ -16,9 +16,6 @@ export const meta = { kind: 'write:chat', - res: { - }, - errors: { noSuchRoom: { message: 'No such room.', diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index b43906109f..7069d32317 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1046,15 +1046,9 @@ type ChatMessagesCreateToUserResponse = operations['chat___messages___create-to- // @public (undocumented) type ChatMessagesDeleteRequest = operations['chat___messages___delete']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatMessagesDeleteResponse = operations['chat___messages___delete']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatMessagesReactRequest = operations['chat___messages___react']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatMessagesReactResponse = operations['chat___messages___react']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatMessagesRoomTimelineRequest = operations['chat___messages___room-timeline']['requestBody']['content']['application/json']; @@ -1076,9 +1070,6 @@ type ChatMessagesShowResponse = operations['chat___messages___show']['responses' // @public (undocumented) type ChatMessagesUnreactRequest = operations['chat___messages___unreact']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatMessagesUnreactResponse = operations['chat___messages___unreact']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatMessagesUserTimelineRequest = operations['chat___messages___user-timeline']['requestBody']['content']['application/json']; @@ -1103,9 +1094,6 @@ type ChatRoomsCreateResponse = operations['chat___rooms___create']['responses'][ // @public (undocumented) type ChatRoomsDeleteRequest = operations['chat___rooms___delete']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatRoomsDeleteResponse = operations['chat___rooms___delete']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatRoomsInvitationsCreateRequest = operations['chat___rooms___invitations___create']['requestBody']['content']['application/json']; @@ -1115,9 +1103,6 @@ type ChatRoomsInvitationsCreateResponse = operations['chat___rooms___invitations // @public (undocumented) type ChatRoomsInvitationsIgnoreRequest = operations['chat___rooms___invitations___ignore']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatRoomsInvitationsIgnoreResponse = operations['chat___rooms___invitations___ignore']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatRoomsInvitationsInboxRequest = operations['chat___rooms___invitations___inbox']['requestBody']['content']['application/json']; @@ -1139,15 +1124,9 @@ type ChatRoomsJoiningResponse = operations['chat___rooms___joining']['responses' // @public (undocumented) type ChatRoomsJoinRequest = operations['chat___rooms___join']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatRoomsJoinResponse = operations['chat___rooms___join']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatRoomsLeaveRequest = operations['chat___rooms___leave']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatRoomsLeaveResponse = operations['chat___rooms___leave']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatRoomsMembersRequest = operations['chat___rooms___members']['requestBody']['content']['application/json']; @@ -1157,9 +1136,6 @@ type ChatRoomsMembersResponse = operations['chat___rooms___members']['responses' // @public (undocumented) type ChatRoomsMuteRequest = operations['chat___rooms___mute']['requestBody']['content']['application/json']; -// @public (undocumented) -type ChatRoomsMuteResponse = operations['chat___rooms___mute']['responses']['200']['content']['application/json']; - // @public (undocumented) type ChatRoomsOwnedRequest = operations['chat___rooms___owned']['requestBody']['content']['application/json']; @@ -1688,9 +1664,7 @@ declare namespace entities { ChatMessagesCreateToUserRequest, ChatMessagesCreateToUserResponse, ChatMessagesDeleteRequest, - ChatMessagesDeleteResponse, ChatMessagesReactRequest, - ChatMessagesReactResponse, ChatMessagesRoomTimelineRequest, ChatMessagesRoomTimelineResponse, ChatMessagesSearchRequest, @@ -1698,31 +1672,25 @@ declare namespace entities { ChatMessagesShowRequest, ChatMessagesShowResponse, ChatMessagesUnreactRequest, - ChatMessagesUnreactResponse, ChatMessagesUserTimelineRequest, ChatMessagesUserTimelineResponse, ChatRoomsCreateRequest, ChatRoomsCreateResponse, ChatRoomsDeleteRequest, - ChatRoomsDeleteResponse, ChatRoomsInvitationsCreateRequest, ChatRoomsInvitationsCreateResponse, ChatRoomsInvitationsIgnoreRequest, - ChatRoomsInvitationsIgnoreResponse, ChatRoomsInvitationsInboxRequest, ChatRoomsInvitationsInboxResponse, ChatRoomsInvitationsOutboxRequest, ChatRoomsInvitationsOutboxResponse, ChatRoomsJoinRequest, - ChatRoomsJoinResponse, ChatRoomsJoiningRequest, ChatRoomsJoiningResponse, ChatRoomsLeaveRequest, - ChatRoomsLeaveResponse, ChatRoomsMembersRequest, ChatRoomsMembersResponse, ChatRoomsMuteRequest, - ChatRoomsMuteResponse, ChatRoomsOwnedRequest, ChatRoomsOwnedResponse, ChatRoomsShowRequest, diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 6390314429..56224cdbaf 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -220,9 +220,7 @@ import type { ChatMessagesCreateToUserRequest, ChatMessagesCreateToUserResponse, ChatMessagesDeleteRequest, - ChatMessagesDeleteResponse, ChatMessagesReactRequest, - ChatMessagesReactResponse, ChatMessagesRoomTimelineRequest, ChatMessagesRoomTimelineResponse, ChatMessagesSearchRequest, @@ -230,31 +228,25 @@ import type { ChatMessagesShowRequest, ChatMessagesShowResponse, ChatMessagesUnreactRequest, - ChatMessagesUnreactResponse, ChatMessagesUserTimelineRequest, ChatMessagesUserTimelineResponse, ChatRoomsCreateRequest, ChatRoomsCreateResponse, ChatRoomsDeleteRequest, - ChatRoomsDeleteResponse, ChatRoomsInvitationsCreateRequest, ChatRoomsInvitationsCreateResponse, ChatRoomsInvitationsIgnoreRequest, - ChatRoomsInvitationsIgnoreResponse, ChatRoomsInvitationsInboxRequest, ChatRoomsInvitationsInboxResponse, ChatRoomsInvitationsOutboxRequest, ChatRoomsInvitationsOutboxResponse, ChatRoomsJoinRequest, - ChatRoomsJoinResponse, ChatRoomsJoiningRequest, ChatRoomsJoiningResponse, ChatRoomsLeaveRequest, - ChatRoomsLeaveResponse, ChatRoomsMembersRequest, ChatRoomsMembersResponse, ChatRoomsMuteRequest, - ChatRoomsMuteResponse, ChatRoomsOwnedRequest, ChatRoomsOwnedResponse, ChatRoomsShowRequest, @@ -789,24 +781,24 @@ export type Endpoints = { 'chat/history': { req: ChatHistoryRequest; res: ChatHistoryResponse }; 'chat/messages/create-to-room': { req: ChatMessagesCreateToRoomRequest; res: ChatMessagesCreateToRoomResponse }; 'chat/messages/create-to-user': { req: ChatMessagesCreateToUserRequest; res: ChatMessagesCreateToUserResponse }; - 'chat/messages/delete': { req: ChatMessagesDeleteRequest; res: ChatMessagesDeleteResponse }; - 'chat/messages/react': { req: ChatMessagesReactRequest; res: ChatMessagesReactResponse }; + 'chat/messages/delete': { req: ChatMessagesDeleteRequest; res: EmptyResponse }; + 'chat/messages/react': { req: ChatMessagesReactRequest; res: EmptyResponse }; 'chat/messages/room-timeline': { req: ChatMessagesRoomTimelineRequest; res: ChatMessagesRoomTimelineResponse }; 'chat/messages/search': { req: ChatMessagesSearchRequest; res: ChatMessagesSearchResponse }; 'chat/messages/show': { req: ChatMessagesShowRequest; res: ChatMessagesShowResponse }; - 'chat/messages/unreact': { req: ChatMessagesUnreactRequest; res: ChatMessagesUnreactResponse }; + 'chat/messages/unreact': { req: ChatMessagesUnreactRequest; res: EmptyResponse }; 'chat/messages/user-timeline': { req: ChatMessagesUserTimelineRequest; res: ChatMessagesUserTimelineResponse }; 'chat/rooms/create': { req: ChatRoomsCreateRequest; res: ChatRoomsCreateResponse }; - 'chat/rooms/delete': { req: ChatRoomsDeleteRequest; res: ChatRoomsDeleteResponse }; + 'chat/rooms/delete': { req: ChatRoomsDeleteRequest; res: EmptyResponse }; 'chat/rooms/invitations/create': { req: ChatRoomsInvitationsCreateRequest; res: ChatRoomsInvitationsCreateResponse }; - 'chat/rooms/invitations/ignore': { req: ChatRoomsInvitationsIgnoreRequest; res: ChatRoomsInvitationsIgnoreResponse }; + 'chat/rooms/invitations/ignore': { req: ChatRoomsInvitationsIgnoreRequest; res: EmptyResponse }; 'chat/rooms/invitations/inbox': { req: ChatRoomsInvitationsInboxRequest; res: ChatRoomsInvitationsInboxResponse }; 'chat/rooms/invitations/outbox': { req: ChatRoomsInvitationsOutboxRequest; res: ChatRoomsInvitationsOutboxResponse }; - 'chat/rooms/join': { req: ChatRoomsJoinRequest; res: ChatRoomsJoinResponse }; + 'chat/rooms/join': { req: ChatRoomsJoinRequest; res: EmptyResponse }; 'chat/rooms/joining': { req: ChatRoomsJoiningRequest; res: ChatRoomsJoiningResponse }; - 'chat/rooms/leave': { req: ChatRoomsLeaveRequest; res: ChatRoomsLeaveResponse }; + 'chat/rooms/leave': { req: ChatRoomsLeaveRequest; res: EmptyResponse }; 'chat/rooms/members': { req: ChatRoomsMembersRequest; res: ChatRoomsMembersResponse }; - 'chat/rooms/mute': { req: ChatRoomsMuteRequest; res: ChatRoomsMuteResponse }; + 'chat/rooms/mute': { req: ChatRoomsMuteRequest; res: EmptyResponse }; 'chat/rooms/owned': { req: ChatRoomsOwnedRequest; res: ChatRoomsOwnedResponse }; 'chat/rooms/show': { req: ChatRoomsShowRequest; res: ChatRoomsShowResponse }; 'chat/rooms/update': { req: ChatRoomsUpdateRequest; res: ChatRoomsUpdateResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index f814d7b3da..b5370e99fa 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -223,9 +223,7 @@ export type ChatMessagesCreateToRoomResponse = operations['chat___messages___cre export type ChatMessagesCreateToUserRequest = operations['chat___messages___create-to-user']['requestBody']['content']['application/json']; export type ChatMessagesCreateToUserResponse = operations['chat___messages___create-to-user']['responses']['200']['content']['application/json']; export type ChatMessagesDeleteRequest = operations['chat___messages___delete']['requestBody']['content']['application/json']; -export type ChatMessagesDeleteResponse = operations['chat___messages___delete']['responses']['200']['content']['application/json']; export type ChatMessagesReactRequest = operations['chat___messages___react']['requestBody']['content']['application/json']; -export type ChatMessagesReactResponse = operations['chat___messages___react']['responses']['200']['content']['application/json']; export type ChatMessagesRoomTimelineRequest = operations['chat___messages___room-timeline']['requestBody']['content']['application/json']; export type ChatMessagesRoomTimelineResponse = operations['chat___messages___room-timeline']['responses']['200']['content']['application/json']; export type ChatMessagesSearchRequest = operations['chat___messages___search']['requestBody']['content']['application/json']; @@ -233,31 +231,25 @@ export type ChatMessagesSearchResponse = operations['chat___messages___search'][ export type ChatMessagesShowRequest = operations['chat___messages___show']['requestBody']['content']['application/json']; export type ChatMessagesShowResponse = operations['chat___messages___show']['responses']['200']['content']['application/json']; export type ChatMessagesUnreactRequest = operations['chat___messages___unreact']['requestBody']['content']['application/json']; -export type ChatMessagesUnreactResponse = operations['chat___messages___unreact']['responses']['200']['content']['application/json']; export type ChatMessagesUserTimelineRequest = operations['chat___messages___user-timeline']['requestBody']['content']['application/json']; export type ChatMessagesUserTimelineResponse = operations['chat___messages___user-timeline']['responses']['200']['content']['application/json']; export type ChatRoomsCreateRequest = operations['chat___rooms___create']['requestBody']['content']['application/json']; export type ChatRoomsCreateResponse = operations['chat___rooms___create']['responses']['200']['content']['application/json']; export type ChatRoomsDeleteRequest = operations['chat___rooms___delete']['requestBody']['content']['application/json']; -export type ChatRoomsDeleteResponse = operations['chat___rooms___delete']['responses']['200']['content']['application/json']; export type ChatRoomsInvitationsCreateRequest = operations['chat___rooms___invitations___create']['requestBody']['content']['application/json']; export type ChatRoomsInvitationsCreateResponse = operations['chat___rooms___invitations___create']['responses']['200']['content']['application/json']; export type ChatRoomsInvitationsIgnoreRequest = operations['chat___rooms___invitations___ignore']['requestBody']['content']['application/json']; -export type ChatRoomsInvitationsIgnoreResponse = operations['chat___rooms___invitations___ignore']['responses']['200']['content']['application/json']; export type ChatRoomsInvitationsInboxRequest = operations['chat___rooms___invitations___inbox']['requestBody']['content']['application/json']; export type ChatRoomsInvitationsInboxResponse = operations['chat___rooms___invitations___inbox']['responses']['200']['content']['application/json']; export type ChatRoomsInvitationsOutboxRequest = operations['chat___rooms___invitations___outbox']['requestBody']['content']['application/json']; export type ChatRoomsInvitationsOutboxResponse = operations['chat___rooms___invitations___outbox']['responses']['200']['content']['application/json']; export type ChatRoomsJoinRequest = operations['chat___rooms___join']['requestBody']['content']['application/json']; -export type ChatRoomsJoinResponse = operations['chat___rooms___join']['responses']['200']['content']['application/json']; export type ChatRoomsJoiningRequest = operations['chat___rooms___joining']['requestBody']['content']['application/json']; export type ChatRoomsJoiningResponse = operations['chat___rooms___joining']['responses']['200']['content']['application/json']; export type ChatRoomsLeaveRequest = operations['chat___rooms___leave']['requestBody']['content']['application/json']; -export type ChatRoomsLeaveResponse = operations['chat___rooms___leave']['responses']['200']['content']['application/json']; export type ChatRoomsMembersRequest = operations['chat___rooms___members']['requestBody']['content']['application/json']; export type ChatRoomsMembersResponse = operations['chat___rooms___members']['responses']['200']['content']['application/json']; export type ChatRoomsMuteRequest = operations['chat___rooms___mute']['requestBody']['content']['application/json']; -export type ChatRoomsMuteResponse = operations['chat___rooms___mute']['responses']['200']['content']['application/json']; export type ChatRoomsOwnedRequest = operations['chat___rooms___owned']['requestBody']['content']['application/json']; export type ChatRoomsOwnedResponse = operations['chat___rooms___owned']['responses']['200']['content']['application/json']; export type ChatRoomsShowRequest = operations['chat___rooms___show']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 9da5540bc1..b9d48f02ae 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -14594,11 +14594,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -14649,11 +14647,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -14877,11 +14873,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -15051,11 +15045,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -15167,11 +15159,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -15339,11 +15329,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -15451,11 +15439,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -15566,11 +15552,9 @@ export type operations = { }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': unknown; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { From e5fcb5b53f3719c0bafa1d6e39805b40c999cd2f Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 28 Apr 2025 21:25:47 +0900 Subject: [PATCH 181/190] enhance(frontend): disable router view transition Fix #15723 --- .../src/components/global/RouterView.vue | 46 +------------------ 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/packages/frontend/src/components/global/RouterView.vue b/packages/frontend/src/components/global/RouterView.vue index 78ac6900a3..27f7b18559 100644 --- a/packages/frontend/src/components/global/RouterView.vue +++ b/packages/frontend/src/components/global/RouterView.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only -->