From c038892795d4fa71bcd27ae6649911d24d4a7a83 Mon Sep 17 00:00:00 2001 From: nullobsi <me@nullob.si> Date: Fri, 12 Nov 2021 02:31:56 -0800 Subject: [PATCH 01/16] fix: mention local users in replies (#7975) * mention local users in replies * fix merge --- packages/client/src/components/post-form.vue | 4 ++-- packages/client/src/ui/chat/post-form.vue | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/client/src/components/post-form.vue b/packages/client/src/components/post-form.vue index 6d3cae39b1..882a71a371 100644 --- a/packages/client/src/components/post-form.vue +++ b/packages/client/src/components/post-form.vue @@ -278,8 +278,8 @@ export default defineComponent({ this.text += ' '; } - if (this.reply && this.reply.user.host != null) { - this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `; + if (this.reply && (this.reply.user.username != this.$i.username || (this.reply.user.host != null && this.reply.user.host != host))) { + this.text = `@${this.reply.user.username}${this.reply.user.host != null ? '@' + toASCII(this.reply.user.host) : ''} `; } if (this.reply && this.reply.text != null) { diff --git a/packages/client/src/ui/chat/post-form.vue b/packages/client/src/ui/chat/post-form.vue index 9debee2603..62aa3a6aa7 100644 --- a/packages/client/src/ui/chat/post-form.vue +++ b/packages/client/src/ui/chat/post-form.vue @@ -206,8 +206,8 @@ export default defineComponent({ this.text += ' '; } - if (this.reply && this.reply.user.host != null) { - this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `; + if (this.reply && (this.reply.user.username != this.$i.username || (this.reply.user.host != null && this.reply.user.host != host))) { + this.text = `@${this.reply.user.username}${this.reply.user.host != null ? '@' + toASCII(this.reply.user.host) : ''} `; } if (this.reply && this.reply.text != null) { From 90fade8e7212934f06ad700e7cb193aeb87beff7 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 19:33:49 +0900 Subject: [PATCH 02/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29c318348b..891707d654 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - フォロー/フォロワーを非公開にできるように - インスタンスプロフィールレンダリング ready - 通知のリアクションアイコンをホバーで拡大できるように +- 返信の際にメンションを含めるように - メールアドレスのバリデーションを強化 ### Bugfixes From 5e82064a7dce73aa93a6292eee88c924861ec5f9 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 19:39:46 +0900 Subject: [PATCH 03/16] clean up --- packages/client/package.json | 1 - packages/client/yarn.lock | 114 ++--------------------------------- 2 files changed, 6 insertions(+), 109 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 53a9d6c3c1..02ccb57e18 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -70,7 +70,6 @@ "cssnano": "5.0.10", "date-fns": "2.25.0", "dateformat": "4.5.1", - "deep-email-validator": "0.1.18", "escape-regexp": "0.0.1", "eslint": "8.2.0", "eslint-plugin-vue": "8.0.3", diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index a0a0d10141..34b936c451 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -397,11 +397,6 @@ resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc" integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g== -"@types/disposable-email-domains@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/disposable-email-domains/-/disposable-email-domains-1.0.2.tgz#0280f6b38fa7f14e54b056a434135ecd254483b1" - integrity sha512-SDKwyYTjk3y5aZBxxc38yRecpJPjsqn57STz1bNxYYlv4k11bBe7QB8w4llXDTmQXKT1mFvgGmJv+8Zdu3YmJw== - "@types/escape-regexp@0.0.0": version "0.0.0" resolved "https://registry.yarnpkg.com/@types/escape-regexp/-/escape-regexp-0.0.0.tgz#bff0225f9ef30d0dbdbe0e2a24283ee5342990c3" @@ -1479,13 +1474,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== -axios@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" - integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== - dependencies: - follow-redirects "1.5.10" - axios@^0.21.1: version "0.21.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" @@ -1628,13 +1616,6 @@ browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.71" -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -1663,11 +1644,6 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= -buffer-from@1.x: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - buffer-from@^1.0.0, buffer-from@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2350,13 +2326,6 @@ debug@4.3.2, debug@^4.3.2: dependencies: ms "2.1.2" -debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - debug@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -2388,18 +2357,6 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -deep-email-validator@0.1.18: - version "0.1.18" - resolved "https://registry.yarnpkg.com/deep-email-validator/-/deep-email-validator-0.1.18.tgz#a072a93f28e11863cc6b9ca3ae964e0e45b3ece8" - integrity sha512-eo2WEUidQvppg6Qdek8iwOqmXvaxRJ2D2VJKbIOwUgLZNFveDDdJMBsFc+yq0S+lILEUcmzrJRrCWbyoe7QUzQ== - dependencies: - "@types/disposable-email-domains" "^1.0.1" - axios "^0.19.2" - disposable-email-domains "^1.0.53" - lodash "^4.17.15" - mailcheck "^1.1.1" - ts-jest "^25.2.1" - deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -2454,11 +2411,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -disposable-email-domains@^1.0.53: - version "1.0.58" - resolved "https://registry.yarnpkg.com/disposable-email-domains/-/disposable-email-domains-1.0.58.tgz#ac9c879c02c4f0898bfb6c0c80b959c0b0b7bc51" - integrity sha512-frnNCPqTjk6t/sosPoco6EIFHbP9SazHQkeltJNfZeUyNgewaVf+kFjEfVkVDVd436Vln43YElJPb8JozhBs7Q== - doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -3013,7 +2965,7 @@ fast-glob@^3.1.1: micromatch "^4.0.2" picomatch "^2.2.1" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -3134,13 +3086,6 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - follow-redirects@^1.10.0: version "1.14.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" @@ -3952,7 +3897,7 @@ json5-loader@4.0.1: loader-utils "^2.0.0" schema-utils "^3.0.0" -json5@2.2.0, json5@2.x: +json5@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== @@ -4153,7 +4098,7 @@ lodash.isfinite@^3.3.2: resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= @@ -4173,7 +4118,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4222,12 +4167,7 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.4" -mailcheck@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mailcheck/-/mailcheck-1.1.1.tgz#d87cf6ba0b64ba512199dbf93f1489f479591e34" - integrity sha1-2Hz2ugtkulEhmdv5PxSJ9HlZHjQ= - -make-error@1.x, make-error@^1.1.1: +make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4279,14 +4219,6 @@ mfm-js@0.20.0: dependencies: twemoji-parser "13.1.x" -micromatch@4.x: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - micromatch@^4.0.0, micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" @@ -4353,7 +4285,7 @@ misskey-js@0.0.10: eventemitter3 "^4.0.7" reconnecting-websocket "^4.4.0" -mkdirp@0.x, mkdirp@~0.5.1: +mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -4754,11 +4686,6 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - pify@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5605,11 +5532,6 @@ seedrandom@3.0.5: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== -semver@6.x: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" @@ -6114,22 +6036,6 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -ts-jest@^25.2.1: - version "25.5.1" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.5.1.tgz#2913afd08f28385d54f2f4e828be4d261f4337c7" - integrity sha512-kHEUlZMK8fn8vkxDjwbHlxXRB9dHYpyzqKIGDNxbzs+Rz+ssNDSDNusEK8Fk/sDd4xE6iKoQLfFkFVaskmTJyw== - dependencies: - bs-logger "0.x" - buffer-from "1.x" - fast-json-stable-stringify "2.x" - json5 "2.x" - lodash.memoize "4.x" - make-error "1.x" - micromatch "4.x" - mkdirp "0.x" - semver "6.x" - yargs-parser "18.x" - ts-loader@9.2.6: version "9.2.6" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" @@ -6734,14 +6640,6 @@ yaml@^1.10.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@18.x: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@20.2.4, yargs-parser@^20.2.2: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From 9b876b30b27d6a02129447f6584d95a497d94c32 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 19:47:04 +0900 Subject: [PATCH 04/16] update ms to 3.0.0 --- packages/backend/@types/ms.d.ts | 12 ------------ packages/backend/package.json | 2 +- packages/backend/src/server/api/endpoints/ap/get.ts | 2 +- packages/backend/src/server/api/endpoints/ap/show.ts | 2 +- .../src/server/api/endpoints/blocking/create.ts | 2 +- .../src/server/api/endpoints/blocking/delete.ts | 2 +- .../src/server/api/endpoints/drive/files/create.ts | 2 +- .../api/endpoints/drive/files/upload-from-url.ts | 2 +- .../src/server/api/endpoints/following/create.ts | 2 +- .../src/server/api/endpoints/following/delete.ts | 2 +- .../src/server/api/endpoints/gallery/posts/create.ts | 2 +- .../src/server/api/endpoints/gallery/posts/update.ts | 2 +- .../src/server/api/endpoints/i/export-blocking.ts | 2 +- .../src/server/api/endpoints/i/export-following.ts | 2 +- .../src/server/api/endpoints/i/export-mute.ts | 2 +- .../src/server/api/endpoints/i/export-notes.ts | 2 +- .../src/server/api/endpoints/i/export-user-lists.ts | 2 +- .../src/server/api/endpoints/i/import-blocking.ts | 2 +- .../src/server/api/endpoints/i/import-following.ts | 2 +- .../src/server/api/endpoints/i/import-muting.ts | 2 +- .../src/server/api/endpoints/i/import-user-lists.ts | 2 +- .../src/server/api/endpoints/i/update-email.ts | 2 +- .../api/endpoints/messaging/messages/delete.ts | 2 +- .../backend/src/server/api/endpoints/notes/create.ts | 2 +- .../backend/src/server/api/endpoints/notes/delete.ts | 2 +- .../server/api/endpoints/notes/reactions/delete.ts | 2 +- .../src/server/api/endpoints/notes/unrenote.ts | 2 +- .../backend/src/server/api/endpoints/pages/create.ts | 2 +- .../backend/src/server/api/endpoints/pages/update.ts | 2 +- .../server/api/endpoints/request-reset-password.ts | 2 +- .../src/server/api/endpoints/users/recommendation.ts | 2 +- packages/backend/src/server/web/index.ts | 2 +- packages/backend/yarn.lock | 5 +++++ 33 files changed, 36 insertions(+), 43 deletions(-) delete mode 100644 packages/backend/@types/ms.d.ts diff --git a/packages/backend/@types/ms.d.ts b/packages/backend/@types/ms.d.ts deleted file mode 100644 index 2f0156d104..0000000000 --- a/packages/backend/@types/ms.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module 'ms' { - interface IMSOptions { - long: boolean; - } - - function ms(value: string): number; - function ms(value: number, options?: IMSOptions): string; - - namespace ms {} // Hack - - export = ms; -} diff --git a/packages/backend/package.json b/packages/backend/package.json index 4376dc4887..b1337489fa 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -135,7 +135,7 @@ "mfm-js": "0.20.0", "misskey-js": "0.0.8", "mocha": "8.4.0", - "ms": "2.1.3", + "ms": "3.0.0-canary.1", "multer": "1.4.3", "nested-property": "4.0.0", "node-fetch": "2.6.1", diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts index 78919f43b0..2f97a24774 100644 --- a/packages/backend/src/server/api/endpoints/ap/get.ts +++ b/packages/backend/src/server/api/endpoints/ap/get.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import define from '../../define'; import Resolver from '@/remote/activitypub/resolver'; import { ApiError } from '../../error'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { tags: ['federation'], diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 2280d93724..32685d44bd 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -11,7 +11,7 @@ import { Note } from '@/models/entities/note'; import { User } from '@/models/entities/user'; import { fetchMeta } from '@/misc/fetch-meta'; import { isActor, isPost, getApId } from '@/remote/activitypub/type'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { tags: ['federation'], diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 2953252394..4d33c09479 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; +import ms from 'ms'; import create from '@/services/blocking/create'; import define from '../../define'; import { ApiError } from '../../error'; diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index a66e46fdf0..ae5dab020a 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; +import ms from 'ms'; import deleteBlocking from '@/services/blocking/delete'; import define from '../../define'; import { ApiError } from '../../error'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 2abc104e6c..89755d9498 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -1,4 +1,4 @@ -import * as ms from 'ms'; +import ms from 'ms'; import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import create from '@/services/drive/add-file'; diff --git a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts index 9f10a42d24..adb5126fbe 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; +import ms from 'ms'; import uploadFromUrl from '@/services/drive/upload-from-url'; import define from '../../../define'; import { DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index ba9ca1092d..92e86bf6b2 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; +import ms from 'ms'; import create from '@/services/following/create'; import define from '../../define'; import { ApiError } from '../../error'; diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 0b0158b86e..030d30c9b5 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; +import ms from 'ms'; import deleteFollowing from '@/services/following/delete'; import define from '../../define'; import { ApiError } from '../../error'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index 38b487e6ea..34af72695d 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -1,5 +1,5 @@ import $ from 'cafy'; -import * as ms from 'ms'; +import ms from 'ms'; import define from '../../../define'; import { ID } from '../../../../../misc/cafy-id'; import { DriveFiles, GalleryPosts } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index 54eea130d3..f94606acf2 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -1,5 +1,5 @@ import $ from 'cafy'; -import * as ms from 'ms'; +import ms from 'ms'; import define from '../../../define'; import { ID } from '../../../../../misc/cafy-id'; import { DriveFiles, GalleryPosts } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/i/export-blocking.ts b/packages/backend/src/server/api/endpoints/i/export-blocking.ts index e4797da0c1..e276ecf384 100644 --- a/packages/backend/src/server/api/endpoints/i/export-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/export-blocking.ts @@ -1,6 +1,6 @@ import define from '../../define'; import { createExportBlockingJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { secure: true, diff --git a/packages/backend/src/server/api/endpoints/i/export-following.ts b/packages/backend/src/server/api/endpoints/i/export-following.ts index b0f154cda8..a351161111 100644 --- a/packages/backend/src/server/api/endpoints/i/export-following.ts +++ b/packages/backend/src/server/api/endpoints/i/export-following.ts @@ -1,6 +1,6 @@ import define from '../../define'; import { createExportFollowingJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { secure: true, diff --git a/packages/backend/src/server/api/endpoints/i/export-mute.ts b/packages/backend/src/server/api/endpoints/i/export-mute.ts index 46d547fa53..b176c7ee8d 100644 --- a/packages/backend/src/server/api/endpoints/i/export-mute.ts +++ b/packages/backend/src/server/api/endpoints/i/export-mute.ts @@ -1,6 +1,6 @@ import define from '../../define'; import { createExportMuteJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { secure: true, diff --git a/packages/backend/src/server/api/endpoints/i/export-notes.ts b/packages/backend/src/server/api/endpoints/i/export-notes.ts index 441bf16896..8cba04552e 100644 --- a/packages/backend/src/server/api/endpoints/i/export-notes.ts +++ b/packages/backend/src/server/api/endpoints/i/export-notes.ts @@ -1,6 +1,6 @@ import define from '../../define'; import { createExportNotesJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { secure: true, diff --git a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts index 24043a862a..44d43c0bea 100644 --- a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts @@ -1,6 +1,6 @@ import define from '../../define'; import { createExportUserListsJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; export const meta = { secure: true, diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index d44d0b6077..4822bd5868 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { createImportBlockingJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; import { ApiError } from '../../error'; import { DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index b3de397661..19aa2fa933 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { createImportFollowingJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; import { ApiError } from '../../error'; import { DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index c17434c587..c474dd7186 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { createImportMutingJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; import { ApiError } from '../../error'; import { DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index 9069a019a9..ceccdd1852 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { createImportUserListsJob } from '@/queue/index'; -import * as ms from 'ms'; +import ms from 'ms'; import { ApiError } from '../../error'; import { DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 9b6fb9c410..ff5a9f292c 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -3,7 +3,7 @@ import { publishMainStream } from '@/services/stream'; import define from '../../define'; import rndstr from 'rndstr'; import config from '@/config/index'; -import * as ms from 'ms'; +import ms from 'ms'; import * as bcrypt from 'bcryptjs'; import { Users, UserProfiles } from '@/models/index'; import { sendEmail } from '@/services/send-email'; diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts index bd4890fc8a..25bf676383 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts @@ -1,7 +1,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../../define'; -import * as ms from 'ms'; +import ms from 'ms'; import { ApiError } from '../../../error'; import { MessagingMessages } from '@/models/index'; import { deleteMessage } from '@/services/messages/delete'; diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 8257ea1d0f..e9584e7b8b 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -1,5 +1,5 @@ import $ from 'cafy'; -import * as ms from 'ms'; +import ms from 'ms'; import { length } from 'stringz'; import create from '@/services/note/create'; import define from '../../define'; diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts index 7163a2b9d2..7f0d59669e 100644 --- a/packages/backend/src/server/api/endpoints/notes/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/delete.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import deleteNote from '@/services/note/delete'; import define from '../../define'; -import * as ms from 'ms'; +import ms from 'ms'; import { getNote } from '../../common/getters'; import { ApiError } from '../../error'; import { Users } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts index 69550f96de..ea851458d2 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,7 +1,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import define from '../../../define'; -import * as ms from 'ms'; +import ms from 'ms'; import deleteReaction from '@/services/note/reaction/delete'; import { getNote } from '../../../common/getters'; import { ApiError } from '../../../error'; diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts index dce43d9d9c..d3fba66095 100644 --- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts +++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '@/misc/cafy-id'; import deleteNote from '@/services/note/delete'; import define from '../../define'; -import * as ms from 'ms'; +import ms from 'ms'; import { getNote } from '../../common/getters'; import { ApiError } from '../../error'; import { Notes, Users } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index c23978f093..0ec287c592 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -1,5 +1,5 @@ import $ from 'cafy'; -import * as ms from 'ms'; +import ms from 'ms'; import define from '../../define'; import { ID } from '@/misc/cafy-id'; import { Pages, DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index b3a7f26963..4aaf2aed5d 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -1,5 +1,5 @@ import $ from 'cafy'; -import * as ms from 'ms'; +import ms from 'ms'; import define from '../../define'; import { ApiError } from '../../error'; import { Pages, DriveFiles } from '@/models/index'; diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index f9928c2ee6..7bb50bf6a6 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -3,7 +3,7 @@ import { publishMainStream } from '@/services/stream'; import define from '../define'; import rndstr from 'rndstr'; import config from '@/config/index'; -import * as ms from 'ms'; +import ms from 'ms'; import { Users, UserProfiles, PasswordResetRequests } from '@/models/index'; import { sendEmail } from '@/services/send-email'; import { ApiError } from '../error'; diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts index dde6bb1037..7c775c4dcf 100644 --- a/packages/backend/src/server/api/endpoints/users/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts @@ -1,4 +1,4 @@ -import * as ms from 'ms'; +import ms from 'ms'; import $ from 'cafy'; import define from '../../define'; import { Users, Followings } from '@/models/index'; diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index fc95a36a87..d80d73f252 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -3,7 +3,7 @@ */ import { dirname } from 'path'; -import * as ms from 'ms'; +import ms from 'ms'; import * as Koa from 'koa'; import * as Router from '@koa/router'; import * as send from 'koa-send'; diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index 0346380ee1..311530db66 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -5421,6 +5421,11 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +ms@3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + multer@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.3.tgz#4db352d6992e028ac0eacf7be45c6efd0264297b" From 165d272552cabd4d28c9125698f6227c02de2c86 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 19:54:49 +0900 Subject: [PATCH 05/16] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 891707d654..e5fd4e88a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ - クライアント: fix missing i18n string - fix html conversion issue with code blocks +### Changes +- ノートにモバイルからの投稿か否かの情報を含めないように + ## 12.95.0 (2021/10/31) ### Improvements From 9ea7d75aa477f6cd1cc6d78a8efd4dbded479dbf Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 21:11:15 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat:=20=E9=80=9A=E5=A0=B1=E3=81=8C?= =?UTF-8?q?=E3=81=82=E3=81=A3=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AB=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E8=80=85=E3=81=B8E=E3=83=A1=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=A7=E9=80=9A=E7=9F=A5=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve #7025 --- CHANGELOG.md | 1 + packages/backend/package.json | 2 + .../api/endpoints/users/report-abuse.ts | 29 ++++++--- packages/backend/yarn.lock | 60 ++++++++++++++++++- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5fd4e88a7..49d411cd49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - インスタンスプロフィールレンダリング ready - 通知のリアクションアイコンをホバーで拡大できるように - 返信の際にメンションを含めるように +- 通報があったときに管理者へEメールで通知されるように - メールアドレスのバリデーションを強化 ### Bugfixes diff --git a/packages/backend/package.json b/packages/backend/package.json index b1337489fa..6c41245e66 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -59,6 +59,7 @@ "@types/redis": "2.8.32", "@types/rename": "1.0.4", "@types/request-stats": "3.0.0", + "@types/sanitize-html": "2.5.0", "@types/seedrandom": "2.4.28", "@types/sharp": "0.29.3", "@types/sinonjs__fake-timers": "6.0.4", @@ -163,6 +164,7 @@ "require-all": "3.0.0", "rndstr": "1.0.0", "s-age": "1.1.2", + "sanitize-html": "2.5.3", "seedrandom": "3.0.5", "sharp": "0.29.2", "speakeasy": "2.0.0", diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index 2c8672cd47..a1d8376651 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -1,4 +1,5 @@ import $ from 'cafy'; +import * as sanitizeHtml from 'sanitize-html'; import { ID } from '@/misc/cafy-id'; import define from '../../define'; import { publishAdminStream } from '@/services/stream'; @@ -6,6 +7,8 @@ import { ApiError } from '../../error'; import { getUser } from '../../common/getters'; import { AbuseUserReports, Users } from '@/models/index'; import { genId } from '@/misc/gen-id'; +import { sendEmail } from '@/services/send-email'; +import { fetchMeta } from '@/misc/fetch-meta'; export const meta = { tags: ['users'], @@ -26,23 +29,24 @@ export const meta = { noSuchUser: { message: 'No such user.', code: 'NO_SUCH_USER', - id: '1acefcb5-0959-43fd-9685-b48305736cb5' + id: '1acefcb5-0959-43fd-9685-b48305736cb5', }, cannotReportYourself: { message: 'Cannot report yourself.', code: 'CANNOT_REPORT_YOURSELF', - id: '1e13149e-b1e8-43cf-902e-c01dbfcb202f' + id: '1e13149e-b1e8-43cf-902e-c01dbfcb202f', }, cannotReportAdmin: { message: 'Cannot report the admin.', code: 'CANNOT_REPORT_THE_ADMIN', - id: '35e166f5-05fb-4f87-a2d5-adb42676d48f' - } - } + id: '35e166f5-05fb-4f87-a2d5-adb42676d48f', + }, + }, }; +// eslint-disable-next-line import/no-default-export export default define(meta, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { @@ -72,10 +76,10 @@ export default define(meta, async (ps, me) => { setTimeout(async () => { const moderators = await Users.find({ where: [{ - isAdmin: true + isAdmin: true, }, { - isModerator: true - }] + isModerator: true, + }], }); for (const moderator of moderators) { @@ -83,8 +87,15 @@ export default define(meta, async (ps, me) => { id: report.id, targetUserId: report.targetUserId, reporterId: report.reporterId, - comment: report.comment + comment: report.comment, }); } + + const meta = await fetchMeta(); + if (meta.email) { + sendEmail(meta.email, 'New abuse report', + sanitizeHtml(ps.comment), + sanitizeHtml(ps.comment)); + } }, 1); }); diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index 311530db66..aa8794f7b7 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -769,6 +769,13 @@ resolved "https://registry.yarnpkg.com/@types/rsvp/-/rsvp-4.0.4.tgz#55e93e7054027f1ad4b4ebc1e60e59eb091e2d32" integrity sha512-J3Ol++HCC7/hwZhanDvggFYU/GtxHxE/e7cGRWxR04BF7Tt3TqJZ84BkzQgDxmX0uu8IagiyfmfoUlBACh2Ilg== +"@types/sanitize-html@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.5.0.tgz#bfef58fbcf2674b20ffcc23c3506faa68c3a13e3" + integrity sha512-PeFIEZsO9m1+ACJlXUaimgrR+5DEDiIXhz7Hso307jmq5Yz0lb5kDp8LiTr5dMMMliC/jNNx/qds7Zoxa4zexw== + dependencies: + htmlparser2 "^6.0.0" + "@types/seedrandom@2.4.28": version "2.4.28" resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" @@ -2631,6 +2638,11 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + defer-to-connect@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" @@ -2831,7 +2843,7 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.6.0: +domutils@^2.5.2, domutils@^2.6.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3889,6 +3901,16 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^3.1.1" +htmlparser2@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + http-assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" @@ -4358,6 +4380,11 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -5471,6 +5498,11 @@ nanoid@^3.1.23: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== +nanoid@^3.1.30: + version "3.1.30" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" + integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== + napi-build-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" @@ -5940,6 +5972,11 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" @@ -6371,6 +6408,15 @@ postcss@^8.2.15: nanoid "^3.1.23" source-map-js "^0.6.2" +postcss@^8.3.11: + version "8.3.11" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858" + integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA== + dependencies: + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^0.6.2" + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" @@ -7049,6 +7095,18 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sanitize-html@2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.5.3.tgz#91aa3dc760b072cdf92f9c6973747569b1ba1cd8" + integrity sha512-DGATXd1fs/Rm287/i5FBKVYSBBUL0iAaztOA1/RFhEs4yqo39/X52i/q/CwsfCUG5cilmXSBmnQmyWfnKhBlOg== + dependencies: + deepmerge "^4.2.2" + escape-string-regexp "^4.0.0" + htmlparser2 "^6.0.0" + is-plain-object "^5.0.0" + parse-srcset "^1.0.2" + postcss "^8.3.11" + sax@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" From cfa38e875c452dcba4ab07e469b9b1ddeaafc7d4 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 21:11:21 +0900 Subject: [PATCH 07/16] refactor --- packages/backend/src/services/send-email.ts | 155 ++++++++++---------- 1 file changed, 77 insertions(+), 78 deletions(-) diff --git a/packages/backend/src/services/send-email.ts b/packages/backend/src/services/send-email.ts index d24168ec46..f5f36148f6 100644 --- a/packages/backend/src/services/send-email.ts +++ b/packages/backend/src/services/send-email.ts @@ -21,8 +21,8 @@ export async function sendEmail(to: string, subject: string, html: string, text: proxy: config.proxySmtp, auth: enableAuth ? { user: meta.smtpUser, - pass: meta.smtpPass - } : undefined + pass: meta.smtpPass, + } : undefined, } as any); try { @@ -33,86 +33,85 @@ export async function sendEmail(to: string, subject: string, html: string, text: subject: subject, text: text, html: `<!doctype html> - <html> - <head> - <meta charset="utf-8"> - <title>${ subject }</title> - <style> - html { - background: #eee; - } +<html> + <head> + <meta charset="utf-8"> + <title>${ subject }</title> + <style> + html { + background: #eee; + } - body { - padding: 16px; - margin: 0; - font-family: sans-serif; - font-size: 14px; - } + body { + padding: 16px; + margin: 0; + font-family: sans-serif; + font-size: 14px; + } - a { - text-decoration: none; - color: #86b300; - } - a:hover { - text-decoration: underline; - } + a { + text-decoration: none; + color: #86b300; + } + a:hover { + text-decoration: underline; + } - main { - max-width: 500px; - margin: 0 auto; - background: #fff; - color: #555; - } - main > header { - padding: 32px; - background: #86b300; - } - main > header > img { - max-width: 128px; - max-height: 28px; - vertical-align: bottom; - } - main > article { - padding: 32px; - } - main > article > h1 { - margin: 0 0 1em 0; - } - main > footer { - padding: 32px; - border-top: solid 1px #eee; - } + main { + max-width: 500px; + margin: 0 auto; + background: #fff; + color: #555; + } + main > header { + padding: 32px; + background: #86b300; + } + main > header > img { + max-width: 128px; + max-height: 28px; + vertical-align: bottom; + } + main > article { + padding: 32px; + } + main > article > h1 { + margin: 0 0 1em 0; + } + main > footer { + padding: 32px; + border-top: solid 1px #eee; + } - nav { - box-sizing: border-box; - max-width: 500px; - margin: 16px auto 0 auto; - padding: 0 32px; - } - nav > a { - color: #888; - } - </style> - </head> - <body> - <main> - <header> - <img src="${ meta.logoImageUrl || meta.iconUrl || iconUrl }"/> - </header> - <article> - <h1>${ subject }</h1> - <div>${ html }</div> - </article> - <footer> - <a href="${ emailSettingUrl }">${ 'Email setting' }</a> - </footer> - </main> - <nav> - <a href="${ config.url }">${ config.host }</a> - </nav> - </body> - </html> - ` + nav { + box-sizing: border-box; + max-width: 500px; + margin: 16px auto 0 auto; + padding: 0 32px; + } + nav > a { + color: #888; + } + </style> + </head> + <body> + <main> + <header> + <img src="${ meta.logoImageUrl || meta.iconUrl || iconUrl }"/> + </header> + <article> + <h1>${ subject }</h1> + <div>${ html }</div> + </article> + <footer> + <a href="${ emailSettingUrl }">${ 'Email setting' }</a> + </footer> + </main> + <nav> + <a href="${ config.url }">${ config.host }</a> + </nav> + </body> +</html>`, }); logger.info('Message sent: %s', info.messageId); From 9b092e918a7ff99049a7bf520c454cb1c323f9b8 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 21:29:59 +0900 Subject: [PATCH 08/16] refactoring --- packages/client/src/components/notification.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/notification.vue b/packages/client/src/components/notification.vue index b629820043..1f61bee6f8 100644 --- a/packages/client/src/components/notification.vue +++ b/packages/client/src/components/notification.vue @@ -69,6 +69,7 @@ <script lang="ts"> import { defineComponent, ref, onMounted, onUnmounted } from 'vue'; +import * as misskey from 'misskey-js'; import { getNoteSummary } from '@/scripts/get-note-summary'; import XReactionIcon from './reaction-icon.vue'; import MkFollowButton from './follow-button.vue'; @@ -105,7 +106,7 @@ export default defineComponent({ const reactionRef = ref(null); onMounted(() => { - let readObserver: IntersectionObserver = null; + let readObserver: IntersectionObserver | null = null; let connection = null; if (!props.notification.isRead) { @@ -168,7 +169,7 @@ export default defineComponent({ closeReactionTooltip(); }; - let changeReactionTooltipShowingState: () => void; + let changeReactionTooltipShowingState: (() => void) | null; const openReactionTooltip = () => { closeReactionTooltip(); @@ -195,7 +196,7 @@ export default defineComponent({ }; return { - getNoteSummary: (text: string) => getNoteSummary(text, i18n.locale), + getNoteSummary: (note: misskey.entities.Note) => getNoteSummary(note), followRequestDone, groupInviteDone, notePage, From 0e3213ff6dea77bff64bee2f46cde49ef80dafe4 Mon Sep 17 00:00:00 2001 From: Johann150 <johann.galle@protonmail.com> Date: Fri, 12 Nov 2021 15:15:14 +0100 Subject: [PATCH 09/16] enhance: show renoters (#7954) * refactor: deduplicate renote button into component For now the renoters tooltip just uses the reaction viewer component with a fixed emoji symbol instead. * chore: remove unnecessary CSS * fix: forgot to rename variable * enhance: use own tooltip instead of reaction viewer * clean up style * fix additional renoters number * rename file to better represent content --- .../client/src/components/note-detailed.vue | 63 ++------ packages/client/src/components/note.vue | 63 ++------ .../client/src/components/renote-button.vue | 149 ++++++++++++++++++ .../client/src/components/renote.details.vue | 46 ++++++ 4 files changed, 227 insertions(+), 94 deletions(-) create mode 100644 packages/client/src/components/renote-button.vue create mode 100644 packages/client/src/components/renote.details.vue diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue index 7550153521..09c05d7769 100644 --- a/packages/client/src/components/note-detailed.vue +++ b/packages/client/src/components/note-detailed.vue @@ -94,12 +94,7 @@ <template v-else><i class="fas fa-reply"></i></template> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> </button> - <button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> - <i class="fas fa-retweet"></i><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> - </button> - <button v-else class="button _button"> - <i class="fas fa-ban"></i> - </button> + <XRenoteButton :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <i class="fas fa-plus"></i> </button> @@ -136,16 +131,17 @@ import XReactionsViewer from './reactions-viewer.vue'; import XMediaList from './media-list.vue'; import XCwButton from './cw-button.vue'; import XPoll from './poll.vue'; -import { pleaseLogin } from '@/scripts/please-login'; -import { focusPrev, focusNext } from '@/scripts/focus'; -import { url } from '@/config'; -import copyToClipboard from '@/scripts/copy-to-clipboard'; -import { checkWordMute } from '@/scripts/check-word-mute'; -import { userPage } from '@/filters/user'; -import * as os from '@/os'; -import { noteActions, noteViewInterruptors } from '@/store'; -import { reactionPicker } from '@/scripts/reaction-picker'; -import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; +import XRenoteButton from './renote-button.vue'; +import { pleaseLogin } from '@client/scripts/please-login'; +import { focusPrev, focusNext } from '@client/scripts/focus'; +import { url } from '@client/config'; +import copyToClipboard from '@client/scripts/copy-to-clipboard'; +import { checkWordMute } from '@client/scripts/check-word-mute'; +import { userPage } from '@client/filters/user'; +import * as os from '@client/os'; +import { noteActions, noteViewInterruptors } from '@client/store'; +import { reactionPicker } from '@client/scripts/reaction-picker'; +import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; // TODO: note.vueとほぼ同じなので共通化したい export default defineComponent({ @@ -157,8 +153,9 @@ export default defineComponent({ XMediaList, XCwButton, XPoll, - MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')), - MkInstanceTicker: defineAsyncComponent(() => import('@/components/instance-ticker.vue')), + XRenoteButton, + MkUrlPreview: defineAsyncComponent(() => import('@client/components/url-preview.vue')), + MkInstanceTicker: defineAsyncComponent(() => import('@client/components/instance-ticker.vue')), }, inject: { @@ -197,7 +194,7 @@ export default defineComponent({ return { 'r': () => this.reply(true), 'e|a|plus': () => this.react(true), - 'q': () => this.renote(true), + 'q': () => this.$refs.renoteButton.renote(true), 'f|b': this.favorite, 'delete|ctrl+d': this.del, 'ctrl+q': this.renoteDirectly, @@ -238,10 +235,6 @@ export default defineComponent({ return this.$i && (this.$i.id === this.note.userId); }, - canRenote(): boolean { - return ['public', 'home'].includes(this.appearNote.visibility) || this.isMyNote; - }, - reactionsCount(): number { return this.appearNote.reactions ? sum(Object.values(this.appearNote.reactions)) @@ -459,30 +452,6 @@ export default defineComponent({ }); }, - renote(viaKeyboard = false) { - pleaseLogin(); - this.blur(); - os.popupMenu([{ - text: this.$ts.renote, - icon: 'fas fa-retweet', - action: () => { - os.api('notes/create', { - renoteId: this.appearNote.id - }); - } - }, { - text: this.$ts.quote, - icon: 'fas fa-quote-right', - action: () => { - os.post({ - renote: this.appearNote, - }); - } - }], this.$refs.renoteButton, { - viaKeyboard - }); - }, - renoteDirectly() { os.apiWithDialog('notes/create', { renoteId: this.appearNote.id diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue index b1ec674b67..19486c4dff 100644 --- a/packages/client/src/components/note.vue +++ b/packages/client/src/components/note.vue @@ -78,12 +78,7 @@ <template v-else><i class="fas fa-reply"></i></template> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> </button> - <button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> - <i class="fas fa-retweet"></i><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> - </button> - <button v-else class="button _button"> - <i class="fas fa-ban"></i> - </button> + <XRenoteButton :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <i class="fas fa-plus"></i> </button> @@ -119,16 +114,17 @@ import XReactionsViewer from './reactions-viewer.vue'; import XMediaList from './media-list.vue'; import XCwButton from './cw-button.vue'; import XPoll from './poll.vue'; -import { pleaseLogin } from '@/scripts/please-login'; -import { focusPrev, focusNext } from '@/scripts/focus'; -import { url } from '@/config'; -import copyToClipboard from '@/scripts/copy-to-clipboard'; -import { checkWordMute } from '@/scripts/check-word-mute'; -import { userPage } from '@/filters/user'; -import * as os from '@/os'; -import { noteActions, noteViewInterruptors } from '@/store'; -import { reactionPicker } from '@/scripts/reaction-picker'; -import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; +import XRenoteButton from './renote-button.vue'; +import { pleaseLogin } from '@client/scripts/please-login'; +import { focusPrev, focusNext } from '@client/scripts/focus'; +import { url } from '@client/config'; +import copyToClipboard from '@client/scripts/copy-to-clipboard'; +import { checkWordMute } from '@client/scripts/check-word-mute'; +import { userPage } from '@client/filters/user'; +import * as os from '@client/os'; +import { noteActions, noteViewInterruptors } from '@client/store'; +import { reactionPicker } from '@client/scripts/reaction-picker'; +import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; export default defineComponent({ components: { @@ -139,8 +135,9 @@ export default defineComponent({ XMediaList, XCwButton, XPoll, - MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')), - MkInstanceTicker: defineAsyncComponent(() => import('@/components/instance-ticker.vue')), + XRenoteButton, + MkUrlPreview: defineAsyncComponent(() => import('@client/components/url-preview.vue')), + MkInstanceTicker: defineAsyncComponent(() => import('@client/components/instance-ticker.vue')), }, inject: { @@ -184,7 +181,7 @@ export default defineComponent({ return { 'r': () => this.reply(true), 'e|a|plus': () => this.react(true), - 'q': () => this.renote(true), + 'q': () => this.$refs.renoteButton.renote(true), 'f|b': this.favorite, 'delete|ctrl+d': this.del, 'ctrl+q': this.renoteDirectly, @@ -225,10 +222,6 @@ export default defineComponent({ return this.$i && (this.$i.id === this.note.userId); }, - canRenote(): boolean { - return ['public', 'home'].includes(this.appearNote.visibility) || this.isMyNote; - }, - reactionsCount(): number { return this.appearNote.reactions ? sum(Object.values(this.appearNote.reactions)) @@ -435,30 +428,6 @@ export default defineComponent({ }); }, - renote(viaKeyboard = false) { - pleaseLogin(); - this.blur(); - os.popupMenu([{ - text: this.$ts.renote, - icon: 'fas fa-retweet', - action: () => { - os.api('notes/create', { - renoteId: this.appearNote.id - }); - } - }, { - text: this.$ts.quote, - icon: 'fas fa-quote-right', - action: () => { - os.post({ - renote: this.appearNote, - }); - } - }], this.$refs.renoteButton, { - viaKeyboard - }); - }, - renoteDirectly() { os.apiWithDialog('notes/create', { renoteId: this.appearNote.id diff --git a/packages/client/src/components/renote-button.vue b/packages/client/src/components/renote-button.vue new file mode 100644 index 0000000000..16ae2a2fa4 --- /dev/null +++ b/packages/client/src/components/renote-button.vue @@ -0,0 +1,149 @@ +<template> +<button + class="button _button canRenote" + @click="renote()" + v-if="canRenote" + @touchstart.passive="onMouseover" + @mouseover="onMouseover" + @mouseleave="onMouseleave" + @touchend="onMouseleave" + ref="renoteButton" +> + <i class="fas fa-retweet"></i> + <p class="count" v-if="count > 0">{{ count }}</p> +</button> +<button + v-else + class="button _button" +> + <i class="fas fa-ban"></i> +</button> +</template> + +<script lang="ts"> +import { defineComponent, ref } from 'vue'; +import XDetails from '@client/components/renote.details.vue'; +import { pleaseLogin } from '@client/scripts/please-login'; +import * as os from '@client/os'; + +export default defineComponent({ + props: { + count: { + type: Number, + required: true, + }, + note: { + type: Object, + required: true, + }, + }, + data() { + return { + close: null, + detailsTimeoutId: null, + isHovering: false + }; + }, + computed: { + canRenote(): boolean { + return ['public', 'home'].includes(this.note.visibility) || this.note.userId === this.$i.id; + }, + }, + watch: { + count(newCount, oldCount) { + if (oldCount < newCount) this.anime(); + if (this.close != null) this.openDetails(); + }, + }, + methods: { + renote(viaKeyboard = false) { + pleaseLogin(); + os.popupMenu([{ + text: this.$ts.renote, + icon: 'fas fa-retweet', + action: () => { + os.api('notes/create', { + renoteId: this.note.id + }); + } + }, { + text: this.$ts.quote, + icon: 'fas fa-quote-right', + action: () => { + os.post({ + renote: this.note, + }); + } + }], this.$refs.renoteButton, { + viaKeyboard + }); + }, + onMouseover() { + if (this.isHovering) return; + this.isHovering = true; + this.detailsTimeoutId = setTimeout(this.openDetails, 300); + }, + onMouseleave() { + if (!this.isHovering) return; + this.isHovering = false; + clearTimeout(this.detailsTimeoutId); + this.closeDetails(); + }, + openDetails() { + os.api('notes/renotes', { + noteId: this.note.id, + limit: 11 + }).then((renotes: any[]) => { + const users = renotes + .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) + .map(x => x.user); + + this.closeDetails(); + if (!this.isHovering || users.length < 1) return; + + const showing = ref(true); + os.popup(XDetails, { + showing, + users, + count: this.count, + source: this.$refs.renoteButton + }, {}, 'closed'); + + this.close = () => { + showing.value = false; + }; + }); + }, + closeDetails() { + if (this.close != null) { + this.close(); + this.close = null; + } + }, + } +}); +</script> + +<style lang="scss" scoped> +.button { + display: inline-block; + height: 32px; + margin: 2px; + padding: 0 6px; + border-radius: 4px; + + &:not(.canRenote) { + cursor: default; + } + + &.renoted { + background: var(--accent); + } + + > .count { + display: inline; + margin-left: 8px; + opacity: 0.7; + } +} +</style> diff --git a/packages/client/src/components/renote.details.vue b/packages/client/src/components/renote.details.vue new file mode 100644 index 0000000000..128d97d8de --- /dev/null +++ b/packages/client/src/components/renote.details.vue @@ -0,0 +1,46 @@ +<template> +<MkTooltip :source="source" ref="tooltip" @closed="$emit('closed')" :max-width="340"> + <div class="renoteTooltip"> + <b v-for="u in users" :key="u.id"> + <MkAvatar :user="u" style="width: 24px; height: 24px;"/><br/> + <MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/> + </b> + <span v-if="users.length < count" slot="omitted">+{{ count - users.length }}</span> + </div> +</MkTooltip> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import MkTooltip from './ui/tooltip.vue'; + +export default defineComponent({ + components: { + MkTooltip, + }, + props: { + users: { + type: Array, + required: true, + }, + count: { + type: Number, + required: true, + }, + source: { + required: true, + } + }, + emits: ['closed'], +}) +</script> + +<style lang="scss" scoped> +.renoteTooltip { + display: flex; + flex: 1; + min-width: 0; + font-size: 0.9em; + gap: 12px; +} +</style> From 4b7b51d5ccdcdad5134edc0232c98e9e8ce2caf5 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 23:53:10 +0900 Subject: [PATCH 10/16] refactor(client): use composition api for tooltip logic --- .../client/src/components/note-detailed.vue | 26 ++-- packages/client/src/components/note.vue | 26 ++-- .../client/src/components/notification.vue | 38 +---- .../components/reactions-viewer.reaction.vue | 146 ++++++++---------- .../client/src/components/renote-button.vue | 126 ++++++--------- packages/client/src/scripts/use-tooltip.ts | 44 ++++++ 6 files changed, 187 insertions(+), 219 deletions(-) create mode 100644 packages/client/src/scripts/use-tooltip.ts diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue index 09c05d7769..3b5b12a60a 100644 --- a/packages/client/src/components/note-detailed.vue +++ b/packages/client/src/components/note-detailed.vue @@ -94,7 +94,7 @@ <template v-else><i class="fas fa-reply"></i></template> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> </button> - <XRenoteButton :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> + <XRenoteButton class="button" :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <i class="fas fa-plus"></i> </button> @@ -132,16 +132,16 @@ import XMediaList from './media-list.vue'; import XCwButton from './cw-button.vue'; import XPoll from './poll.vue'; import XRenoteButton from './renote-button.vue'; -import { pleaseLogin } from '@client/scripts/please-login'; -import { focusPrev, focusNext } from '@client/scripts/focus'; -import { url } from '@client/config'; -import copyToClipboard from '@client/scripts/copy-to-clipboard'; -import { checkWordMute } from '@client/scripts/check-word-mute'; -import { userPage } from '@client/filters/user'; -import * as os from '@client/os'; -import { noteActions, noteViewInterruptors } from '@client/store'; -import { reactionPicker } from '@client/scripts/reaction-picker'; -import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; +import { pleaseLogin } from '@/scripts/please-login'; +import { focusPrev, focusNext } from '@/scripts/focus'; +import { url } from '@/config'; +import copyToClipboard from '@/scripts/copy-to-clipboard'; +import { checkWordMute } from '@/scripts/check-word-mute'; +import { userPage } from '@/filters/user'; +import * as os from '@/os'; +import { noteActions, noteViewInterruptors } from '@/store'; +import { reactionPicker } from '@/scripts/reaction-picker'; +import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; // TODO: note.vueとほぼ同じなので共通化したい export default defineComponent({ @@ -154,8 +154,8 @@ export default defineComponent({ XCwButton, XPoll, XRenoteButton, - MkUrlPreview: defineAsyncComponent(() => import('@client/components/url-preview.vue')), - MkInstanceTicker: defineAsyncComponent(() => import('@client/components/instance-ticker.vue')), + MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')), + MkInstanceTicker: defineAsyncComponent(() => import('@/components/instance-ticker.vue')), }, inject: { diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue index 19486c4dff..2ab769db43 100644 --- a/packages/client/src/components/note.vue +++ b/packages/client/src/components/note.vue @@ -78,7 +78,7 @@ <template v-else><i class="fas fa-reply"></i></template> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> </button> - <XRenoteButton :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> + <XRenoteButton class="button" :note="appearNote" :count="appearNote.renoteCount" ref="renoteButton"/> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <i class="fas fa-plus"></i> </button> @@ -115,16 +115,16 @@ import XMediaList from './media-list.vue'; import XCwButton from './cw-button.vue'; import XPoll from './poll.vue'; import XRenoteButton from './renote-button.vue'; -import { pleaseLogin } from '@client/scripts/please-login'; -import { focusPrev, focusNext } from '@client/scripts/focus'; -import { url } from '@client/config'; -import copyToClipboard from '@client/scripts/copy-to-clipboard'; -import { checkWordMute } from '@client/scripts/check-word-mute'; -import { userPage } from '@client/filters/user'; -import * as os from '@client/os'; -import { noteActions, noteViewInterruptors } from '@client/store'; -import { reactionPicker } from '@client/scripts/reaction-picker'; -import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; +import { pleaseLogin } from '@/scripts/please-login'; +import { focusPrev, focusNext } from '@/scripts/focus'; +import { url } from '@/config'; +import copyToClipboard from '@/scripts/copy-to-clipboard'; +import { checkWordMute } from '@/scripts/check-word-mute'; +import { userPage } from '@/filters/user'; +import * as os from '@/os'; +import { noteActions, noteViewInterruptors } from '@/store'; +import { reactionPicker } from '@/scripts/reaction-picker'; +import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; export default defineComponent({ components: { @@ -136,8 +136,8 @@ export default defineComponent({ XCwButton, XPoll, XRenoteButton, - MkUrlPreview: defineAsyncComponent(() => import('@client/components/url-preview.vue')), - MkInstanceTicker: defineAsyncComponent(() => import('@client/components/instance-ticker.vue')), + MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')), + MkInstanceTicker: defineAsyncComponent(() => import('@/components/instance-ticker.vue')), }, inject: { diff --git a/packages/client/src/components/notification.vue b/packages/client/src/components/notification.vue index 1f61bee6f8..40670daa9c 100644 --- a/packages/client/src/components/notification.vue +++ b/packages/client/src/components/notification.vue @@ -78,6 +78,7 @@ import notePage from '@/filters/note'; import { userPage } from '@/filters/user'; import { i18n } from '@/i18n'; import * as os from '@/os'; +import { useTooltip } from '@/scripts/use-tooltip'; export default defineComponent({ components: { @@ -153,47 +154,14 @@ export default defineComponent({ os.api('users/groups/invitations/reject', { invitationId: props.notification.invitation.id }); }; - let isReactionHovering = false; - let reactionTooltipTimeoutId; - - const onReactionMouseover = () => { - if (isReactionHovering) return; - isReactionHovering = true; - reactionTooltipTimeoutId = setTimeout(openReactionTooltip, 300); - }; - - const onReactionMouseleave = () => { - if (!isReactionHovering) return; - isReactionHovering = false; - clearTimeout(reactionTooltipTimeoutId); - closeReactionTooltip(); - }; - - let changeReactionTooltipShowingState: (() => void) | null; - - const openReactionTooltip = () => { - closeReactionTooltip(); - if (!isReactionHovering) return; - - const showing = ref(true); + const { onMouseover: onReactionMouseover, onMouseleave: onReactionMouseleave } = useTooltip((showing) => { os.popup(XReactionTooltip, { showing, reaction: props.notification.reaction ? props.notification.reaction.replace(/^:(\w+):$/, ':$1@.:') : props.notification.reaction, emojis: props.notification.note.emojis, source: reactionRef.value.$el, }, {}, 'closed'); - - changeReactionTooltipShowingState = () => { - showing.value = false; - }; - }; - - const closeReactionTooltip = () => { - if (changeReactionTooltipShowingState != null) { - changeReactionTooltipShowingState(); - changeReactionTooltipShowingState = null; - } - }; + }); return { getNoteSummary: (note: misskey.entities.Note) => getNoteSummary(note), diff --git a/packages/client/src/components/reactions-viewer.reaction.vue b/packages/client/src/components/reactions-viewer.reaction.vue index 47a3bb9720..a7769868b9 100644 --- a/packages/client/src/components/reactions-viewer.reaction.vue +++ b/packages/client/src/components/reactions-viewer.reaction.vue @@ -2,13 +2,13 @@ <button class="hkzvhatu _button" :class="{ reacted: note.myReaction == reaction, canToggle }" - @click="toggleReaction(reaction)" + @click="toggleReaction()" v-if="count > 0" @touchstart.passive="onMouseover" @mouseover="onMouseover" @mouseleave="onMouseleave" @touchend="onMouseleave" - ref="reaction" + ref="buttonRef" v-particle="canToggle" > <XReactionIcon :reaction="reaction" :custom-emojis="note.emojis"/> @@ -17,15 +17,18 @@ </template> <script lang="ts"> -import { defineComponent, ref } from 'vue'; +import { computed, defineComponent, onMounted, ref, watch } from 'vue'; import XDetails from '@/components/reactions-viewer.details.vue'; import XReactionIcon from '@/components/reaction-icon.vue'; import * as os from '@/os'; +import { useTooltip } from '@/scripts/use-tooltip'; +import { $i } from '@/account'; export default defineComponent({ components: { XReactionIcon }, + props: { reaction: { type: String, @@ -44,101 +47,78 @@ export default defineComponent({ required: true, }, }, - data() { - return { - close: null, - detailsTimeoutId: null, - isHovering: false - }; - }, - computed: { - canToggle(): boolean { - return !this.reaction.match(/@\w/) && this.$i; - }, - }, - watch: { - count(newCount, oldCount) { - if (oldCount < newCount) this.anime(); - if (this.close != null) this.openDetails(); - }, - }, - mounted() { - if (!this.isInitial) this.anime(); - }, - methods: { - toggleReaction() { - if (!this.canToggle) return; - const oldReaction = this.note.myReaction; + setup(props) { + const buttonRef = ref<HTMLElement>(); + + const canToggle = computed(() => !props.reaction.match(/@\w/) && $i); + + const toggleReaction = () => { + if (!canToggle.value) return; + + const oldReaction = props.note.myReaction; if (oldReaction) { os.api('notes/reactions/delete', { - noteId: this.note.id + noteId: props.note.id }).then(() => { - if (oldReaction !== this.reaction) { + if (oldReaction !== props.reaction) { os.api('notes/reactions/create', { - noteId: this.note.id, - reaction: this.reaction + noteId: props.note.id, + reaction: props.reaction }); } }); } else { os.api('notes/reactions/create', { - noteId: this.note.id, - reaction: this.reaction + noteId: props.note.id, + reaction: props.reaction }); } - }, - onMouseover() { - if (this.isHovering) return; - this.isHovering = true; - this.detailsTimeoutId = setTimeout(this.openDetails, 300); - }, - onMouseleave() { - if (!this.isHovering) return; - this.isHovering = false; - clearTimeout(this.detailsTimeoutId); - this.closeDetails(); - }, - openDetails() { - os.api('notes/reactions', { - noteId: this.note.id, - type: this.reaction, - limit: 11 - }).then((reactions: any[]) => { - const users = reactions - .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) - .map(x => x.user); + }; - this.closeDetails(); - if (!this.isHovering) return; - - const showing = ref(true); - os.popup(XDetails, { - showing, - reaction: this.reaction, - emojis: this.note.emojis, - users, - count: this.count, - source: this.$refs.reaction - }, {}, 'closed'); - - this.close = () => { - showing.value = false; - }; - }); - }, - closeDetails() { - if (this.close != null) { - this.close(); - this.close = null; - } - }, - anime() { + const anime = () => { if (document.hidden) return; - // TODO - }, - } + // TODO: 新しくリアクションが付いたことが視覚的に分かりやすいアニメーション + }; + + watch(() => props.count, (newCount, oldCount) => { + if (oldCount < newCount) anime(); + }); + + onMounted(() => { + if (!props.isInitial) anime(); + }); + + const { onMouseover, onMouseleave } = useTooltip(async (showing) => { + const reactions = await os.api('notes/reactions', { + noteId: props.note.id, + type: props.reaction, + limit: 11 + }); + + const users = reactions + .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) + .map(x => x.user); + + os.popup(XDetails, { + showing, + reaction: props.reaction, + emojis: props.note.emojis, + users, + count: props.count, + source: buttonRef.value + }, {}, 'closed'); + }); + + return { + buttonRef, + canToggle, + toggleReaction, + onMouseover, + onMouseleave, + }; + }, }); </script> diff --git a/packages/client/src/components/renote-button.vue b/packages/client/src/components/renote-button.vue index 16ae2a2fa4..5ddc1602ed 100644 --- a/packages/client/src/components/renote-button.vue +++ b/packages/client/src/components/renote-button.vue @@ -1,13 +1,13 @@ <template> <button - class="button _button canRenote" + class="eddddedb _button canRenote" @click="renote()" v-if="canRenote" @touchstart.passive="onMouseover" @mouseover="onMouseover" @mouseleave="onMouseleave" @touchend="onMouseleave" - ref="renoteButton" + ref="buttonRef" > <i class="fas fa-retweet"></i> <p class="count" v-if="count > 0">{{ count }}</p> @@ -21,10 +21,13 @@ </template> <script lang="ts"> -import { defineComponent, ref } from 'vue'; -import XDetails from '@client/components/renote.details.vue'; -import { pleaseLogin } from '@client/scripts/please-login'; -import * as os from '@client/os'; +import { computed, defineComponent, ref } from 'vue'; +import XDetails from '@/components/renote.details.vue'; +import { pleaseLogin } from '@/scripts/please-login'; +import * as os from '@/os'; +import { $i } from '@/account'; +import { useTooltip } from '@/scripts/use-tooltip'; +import { i18n } from '@/i18n'; export default defineComponent({ props: { @@ -37,95 +40,68 @@ export default defineComponent({ required: true, }, }, - data() { - return { - close: null, - detailsTimeoutId: null, - isHovering: false - }; - }, - computed: { - canRenote(): boolean { - return ['public', 'home'].includes(this.note.visibility) || this.note.userId === this.$i.id; - }, - }, - watch: { - count(newCount, oldCount) { - if (oldCount < newCount) this.anime(); - if (this.close != null) this.openDetails(); - }, - }, - methods: { - renote(viaKeyboard = false) { + + setup(props) { + const buttonRef = ref<HTMLElement>(); + + const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id); + + const { onMouseover, onMouseleave } = useTooltip(async (showing) => { + const renotes = await os.api('notes/renotes', { + noteId: props.note.id, + limit: 11 + }); + + const users = renotes + .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) + .map(x => x.user); + + if (users.length < 1) return; + + os.popup(XDetails, { + showing, + users, + count: props.count, + source: buttonRef.value + }, {}, 'closed'); + }); + + const renote = (viaKeyboard = false) => { pleaseLogin(); os.popupMenu([{ - text: this.$ts.renote, + text: i18n.locale.renote, icon: 'fas fa-retweet', action: () => { os.api('notes/create', { - renoteId: this.note.id + renoteId: props.note.id }); } }, { - text: this.$ts.quote, + text: i18n.locale.quote, icon: 'fas fa-quote-right', action: () => { os.post({ - renote: this.note, + renote: props.note, }); } - }], this.$refs.renoteButton, { + }], buttonRef.value, { viaKeyboard }); - }, - onMouseover() { - if (this.isHovering) return; - this.isHovering = true; - this.detailsTimeoutId = setTimeout(this.openDetails, 300); - }, - onMouseleave() { - if (!this.isHovering) return; - this.isHovering = false; - clearTimeout(this.detailsTimeoutId); - this.closeDetails(); - }, - openDetails() { - os.api('notes/renotes', { - noteId: this.note.id, - limit: 11 - }).then((renotes: any[]) => { - const users = renotes - .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) - .map(x => x.user); + }; - this.closeDetails(); - if (!this.isHovering || users.length < 1) return; - - const showing = ref(true); - os.popup(XDetails, { - showing, - users, - count: this.count, - source: this.$refs.renoteButton - }, {}, 'closed'); - - this.close = () => { - showing.value = false; - }; - }); - }, - closeDetails() { - if (this.close != null) { - this.close(); - this.close = null; - } - }, - } + return { + buttonRef, + canRenote, + renote, + onMouseover, + onMouseleave, + }; + }, }); </script> <style lang="scss" scoped> -.button { +.eddddedb { display: inline-block; height: 32px; margin: 2px; diff --git a/packages/client/src/scripts/use-tooltip.ts b/packages/client/src/scripts/use-tooltip.ts new file mode 100644 index 0000000000..2c0c36400d --- /dev/null +++ b/packages/client/src/scripts/use-tooltip.ts @@ -0,0 +1,44 @@ +import { Ref, ref } from 'vue'; + +export function useTooltip(onShow: (showing: Ref<boolean>) => void) { + let isHovering = false; + let timeoutId: number; + + let changeShowingState: (() => void) | null; + + const open = () => { + close(); + if (!isHovering) return; + + const showing = ref(true); + onShow(showing); + changeShowingState = () => { + showing.value = false; + }; + }; + + const close = () => { + if (changeShowingState != null) { + changeShowingState(); + changeShowingState = null; + } + }; + + const onMouseover = () => { + if (isHovering) return; + isHovering = true; + timeoutId = window.setTimeout(open, 300); + }; + + const onMouseleave = () => { + if (!isHovering) return; + isHovering = false; + window.clearTimeout(timeoutId); + close(); + }; + + return { + onMouseover, + onMouseleave, + }; +} From 187696c97328ffc7997ee3eba7fd98d593e99992 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 23:54:02 +0900 Subject: [PATCH 11/16] refactor(client): improve readability --- packages/client/src/components/renote-button.vue | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/client/src/components/renote-button.vue b/packages/client/src/components/renote-button.vue index 5ddc1602ed..af27bfca2f 100644 --- a/packages/client/src/components/renote-button.vue +++ b/packages/client/src/components/renote-button.vue @@ -1,8 +1,7 @@ <template> -<button +<button v-if="canRenote" class="eddddedb _button canRenote" @click="renote()" - v-if="canRenote" @touchstart.passive="onMouseover" @mouseover="onMouseover" @mouseleave="onMouseleave" @@ -12,10 +11,7 @@ <i class="fas fa-retweet"></i> <p class="count" v-if="count > 0">{{ count }}</p> </button> -<button - v-else - class="button _button" -> +<button v-else class="eddddedb _button"> <i class="fas fa-ban"></i> </button> </template> From 1161d6cae27a5007159d4ee51af0830ea60190ea Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 12 Nov 2021 23:54:45 +0900 Subject: [PATCH 12/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d411cd49..9a2045fc4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - フォロー/フォロワーを非公開にできるように - インスタンスプロフィールレンダリング ready - 通知のリアクションアイコンをホバーで拡大できるように +- RenoteボタンをホバーでRenoteしたユーザー一覧を表示するように - 返信の際にメンションを含めるように - 通報があったときに管理者へEメールで通知されるように - メールアドレスのバリデーションを強化 From 6a9e52d83c654254679ac38ae9222ccecfe95b2e Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Sat, 13 Nov 2021 00:31:35 +0900 Subject: [PATCH 13/16] New Crowdin updates (#7977) * New translations ja-JP.yml (Turkish) * New translations ja-JP.yml (Turkish) * New translations ja-JP.yml (Turkish) * New translations ja-JP.yml (Turkish) * New translations ja-JP.yml (French) * New translations ja-JP.yml (French) * New translations ja-JP.yml (Indonesian) * New translations ja-JP.yml (Indonesian) * New translations ja-JP.yml (Indonesian) --- locales/fr-FR.yml | 16 ++++++------ locales/id-ID.yml | 52 +++++++++++++++++++++++++++++++++------ locales/tr-TR.yml | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 locales/tr-TR.yml diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index c3964fff6d..5d67b5269a 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -797,6 +797,15 @@ unread: "Non lu" filter: "Filtre" controlPanel: "Panneau de contrôle" manageAccounts: "Gérer les comptes" +classic: "Classique" +_emailUnavailable: + format: "Le format de cette adresse de courriel est invalide" + mx: "Ce serveur de courriels est invalide" + smtp: "Ce serveur de courriels ne répond pas" +_ffVisibility: + public: "Public" + followers: "Visible uniquement pour les abonné·e·s" + private: "Privé" _signup: almostThere: "Bientôt fini" emailAddressInfo: "Insérez votre adresse e-mail." @@ -808,13 +817,6 @@ _accountDelete: requestAccountDelete: "Demander la suppression de votre compte" started: "La procédure de suppression a commencé." inProgress: "Suppression en cours" -_docs: - continueReading: "Lire plus" - features: "Fonctionnalités" - generalTopics: "Sujets généraux" - advancedTopics: "Sujets avancés" - admin: "Gestion" - translateWarn: "Ceci est une traduction dont le contenu peut différer du texte original." _ad: back: "Retour" reduceFrequencyOfThisAd: "Voir cette publicité moins souvent" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 06df4ce8e9..f4997e3a64 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -81,6 +81,8 @@ somethingHappened: "Terjadi kesalahan" retry: "Coba lagi" pageLoadError: "Gagal memuat halaman." pageLoadErrorDescription: "Umumnya disebabkan jaringan atau tembolok perambah. Cobalah bersihkan tembolok peramban lalu tunggu sesaat sebelum mencoba kembali." +serverIsDead: "Tidak ada respon dari server. Mohon tunggu dan coba beberapa saat lagi." +youShouldUpgradeClient: "Untuk melihat halaman ini, mohon muat ulang untuk memutakhirkan klienmu." enterListName: "Masukkan nama daftar" privacy: "Privasi" makeFollowManuallyApprove: "Permintaan mengikuti membutuhkan persetujuan" @@ -529,6 +531,8 @@ removeAllFollowing: "Tahan semua mengikuti" removeAllFollowingDescription: "Batal mengikuti semua akun dari {host}. Mohon jalankan ini ketika instansi sudah tidak ada lagi." userSuspended: "Pengguna ini telah dibekukan." userSilenced: "Pengguna ini telah dibungkam." +yourAccountSuspendedTitle: "Akun ini dibekukan" +yourAccountSuspendedDescription: "Akun ini dibekukan karena melanggar ketentuan penggunaan layanan server atau semacamnya. Hubungi admin apabila ingin tahu alasan lebih lanjut. Mohon untuk tidak membuat akun baru." menu: "Menu" divider: "Pembagi" addItem: "Tambahkan item" @@ -616,6 +620,8 @@ reportAbuse: "Laporkan" reportAbuseOf: "Laporkan {name}" fillAbuseReportDescription: "Mohon isi rincian laporan. Jika laporan ini mengenai catatan yang spesifik, mohon lampirkan serta URL catatan tersebut." abuseReported: "Laporan kamu telah dikirimkan. Terima kasih." +reporteeOrigin: "Yang dilaporkan" +reporterOrigin: "Pelapor" send: "Kirim" abuseMarkAsResolved: "Tandai laporan sebagai selesai" openInNewTab: "Buka di tab baru" @@ -762,6 +768,7 @@ middle: "Sedang" low: "Rendah" emailNotConfiguredWarning: "Alamat surel tidak disetel." ratio: "Rasio" +previewNoteText: "Tampilkan pratinjau" customCss: "Custom CSS" customCssWarn: "Pengaturan ini seharusnya digunakan jika kamu tahu cara kerjanya. Memasukkan nilai yang tidak tepat dapat menyebabkan klien tidak berfungsi semestinya." global: "Global" @@ -779,8 +786,40 @@ translate: "Terjemahkan" translatedFrom: "Terjemahkan dari {x}" accountDeletionInProgress: "Penghapusan akun sedang dalam proses" usernameInfo: "Nama yang mengidentifikasikan akun kamu dari yang lain pada server ini. Kamu dapat menggunakan alfabet (a~z, A~Z), digit (0~9) atau garis bawah (_). Username tidak dapat diubah setelahnya." +aiChanMode: "Mode Ai" keepCw: "Biarkan Peringatan Konten" +pubSub: "Akun Pub/Sub" +lastCommunication: "Komunikasi terakhir" +resolved: "Selesai" +unresolved: "Belum selesai" +itsOn: "Aktif" +itsOff: "Nonaktif" +emailRequiredForSignup: "Membutuhkan alamat surel untuk mendaftar" +unread: "Belum dibaca" +filter: "Saring" controlPanel: "Panel kontrol" +manageAccounts: "Kelola Akun" +makeReactionsPublic: "Tampilkan riwayat reaksi ke publik" +makeReactionsPublicDescription: "Pengaturan ini akan membuat daftar dari semua reaksi masa lalu kamu ditampilkan secara publik." +classic: "Klasik" +muteThread: "Bisukan thread" +unmuteThread: "Suarakan thread" +ffVisibility: "Visibilitas Mengikuti/Pengikut" +ffVisibilityDescription: "Mengatur siapa yang dapat melihat pengikutmu dan yang kamu ikuti." +_emailUnavailable: + used: "Alamat surel ini telah digunakan" + format: "Format tidak valid." + disposable: "Alamat surel temporer tidak dapat digunakan" + mx: "Server alamat surel ini tidak valid" + smtp: "Server alamat surel ini tidak merespon" +_ffVisibility: + public: "Terbitkan" + followers: "Tampil untuk pengikut saja" + private: "Tersembunyi" +_signup: + almostThere: "Hampir selesai" + emailAddressInfo: "Mohon masukkan alamat surel kamu." + emailSent: "Konfirmasi surel telah dikirimkan ke alamat surel kamu ({email}). Mohon klik tautan yang tercantum di dalamnya untuk menyelesaikan pembuatan akun." _accountDelete: accountDelete: "Hapus akun" mayTakeTime: "Karena penghapusan akun merupakan proses yang berat dan intensif, kemungkinan dapat membutuhkan waktu untuk menyelesaikan tergantung daripada berapa banyak konten yang kamu buat dan berapa banyak berkas yang telah kamu unggah." @@ -788,13 +827,6 @@ _accountDelete: requestAccountDelete: "Minta penghapusan akun" started: "Penghapusan telah dimulai" inProgress: "Penghapusan sedang dalam proses" -_docs: - continueReading: "Baca lebih lanjut" - features: "Fitur" - generalTopics: "Topik umum" - advancedTopics: "Topik tingkat lanjut" - admin: "Manajemen" - translateWarn: "Ini merupakan dokumen terjemahan. Konten di dalamnya kemungkinan dapat berbeda dari yang aslinya." _ad: back: "Kembali" reduceFrequencyOfThisAd: "Tampilkan iklan ini lebih sedikit" @@ -895,6 +927,8 @@ _mfm: fontDescription: "Setel font yang ditampilkan untuk konten." rainbow: "Pelangi" rainbowDescription: "Membuat konten muncul dalam warna pelangi." + sparkle: "Kelap-kelip" + sparkleDescription: "Memberikan konten efek partikel kelap-kelip." _reversi: reversi: "Reversi" gameSettings: "Pengaturan permainan" @@ -1121,6 +1155,10 @@ _permissions: "write:user-groups": "Sunting atau hapus grup pengguna" "read:channels": "Lihat saluran" "write:channels": "Sunting saluran" + "read:gallery": "Lihat galeri" + "write:gallery": "Sunting galeri" + "read:gallery-likes": "Lihat daftar postingan galeri yang disukai" + "write:gallery-likes": "Sunting daftar postingan galeri yang disukai" _auth: shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?" shareAccessAsk: "Apakah kamu ingin mengijinkan aplikasi ini untuk mengakses akun kamu?" diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml new file mode 100644 index 0000000000..46204d33c4 --- /dev/null +++ b/locales/tr-TR.yml @@ -0,0 +1,62 @@ +--- +_lang_: "Türkçe" +introMisskey: "Açık kaynaklı bir dağıtılmış mikroblog hizmeti olan Misskey'e hoş geldiniz.\nMisskey, neler olup bittiğini paylaşmak ve herkese sizden bahsetmek için \"notlar\" oluşturmanıza olanak tanıyan, açık kaynaklı, dağıtılmış bir mikroblog hizmetidir.\nHerkesin notlarına kendi tepkilerinizi hızlıca eklemek için \"Tepkiler\" özelliğini de kullanabilirsiniz👍.\nYeni bir dünyayı keşfedin🚀." +monthAndDay: "{month}Ay {day}Gün" +search: "Arama" +notifications: "Bildirim" +username: "Kullanıcı Adı" +password: "Şifre" +forgotPassword: "şifremi unuttum" +ok: "TAMAM" +gotIt: "Anladım" +cancel: "İptal" +enterUsername: "Kullanıcı adınızı giriniz" +noNotes: "Notlar mevcut değil." +noNotifications: "Bildirim bulunmuyor" +settings: "Ayarlar" +basicSettings: "Temel Ayarlar" +otherSettings: "Diğer Ayarlar" +openInWindow: "Bir pencere ile aç" +profile: "Profil" +timeline: "Zaman çizelgesi" +noAccountDescription: "Bu kullanıcı henüz biyografisini yazmadı" +login: "Giriş Yap " +logout: "Çıkış Yap" +signup: "Kayıt Ol" +uploading: "Yükleniyor" +users: "Kullanıcı" +addUser: "Kullanıcı Ekle" +favorite: "Favoriler" +favorites: "Favoriler" +unfavorite: "Favorilerden Kaldır" +favorited: "Favorilerime eklendi." +alreadyFavorited: "Zaten favorilerinizde kayıtlı." +pin: "Sabitlenmiş" +unpin: "Sabitlemeyi kaldır" +copyContent: "İçeriği kopyala" +copyLink: "Bağlantıyı Kopyala" +delete: "Sil" +deleteAndEdit: "Sil ve yeniden düzenle" +deleteAndEditConfirm: "Bu notu silip yeniden düzenlemek istiyor musunuz? Bu nota ilişkin tüm Tepkiler, Yeniden Notlar ve Yanıtlar da silinecektir." +addToList: "Listeye ekle" +sendMessage: "Mesaj Gönder" +copyUsername: "Kullanıcı Adını Kopyala" +searchUser: "Kullanıcıları ara" +pinned: "Sabitlenmiş" +remove: "Sil" +smtpUser: "Kullanıcı Adı" +smtpPass: "Şifre" +user: "Kullanıcı" +_mfm: + search: "Arama" +_sfx: + notification: "Bildirim" +_widgets: + notifications: "Bildirim" + timeline: "Zaman çizelgesi" +_profile: + username: "Kullanıcı Adı" +_deck: + _columns: + notifications: "Bildirim" + tl: "Zaman çizelgesi" From 0f9a6417b0b614a8206f78a7a0115ea2df999ed3 Mon Sep 17 00:00:00 2001 From: Johann150 <johann.galle@protonmail.com> Date: Sat, 13 Nov 2021 03:38:26 +0100 Subject: [PATCH 14/16] fix(client): reaction viewer layout (#7942) The profile picture and name should be grouped together as they belong, and it should be clear which picture belongs to which name. --- packages/client/src/components/reactions-viewer.details.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/reactions-viewer.details.vue b/packages/client/src/components/reactions-viewer.details.vue index 7c49bd1d9c..d80f9b9e8d 100644 --- a/packages/client/src/components/reactions-viewer.details.vue +++ b/packages/client/src/components/reactions-viewer.details.vue @@ -9,12 +9,14 @@ <template v-if="users.length <= 10"> <b v-for="u in users" :key="u.id" style="margin-right: 12px;"> <MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> + <br/> <MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/> </b> </template> <template v-if="10 < users.length"> <b v-for="u in users" :key="u.id" style="margin-right: 12px;"> <MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> + <br/> <MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/> </b> <span slot="omitted">+{{ count - 10 }}</span> @@ -64,7 +66,6 @@ export default defineComponent({ display: flex; > .reaction { - flex: 1; max-width: 100px; text-align: center; @@ -80,12 +81,13 @@ export default defineComponent({ } > .users { + display: flex; flex: 1; min-width: 0; font-size: 0.9em; border-left: solid 0.5px var(--divider); padding-left: 10px; - margin-left: 10px; + margin-left: 10px; } } </style> From 66b512af5d9c5e5dbe483ff6a5de31e2347608f9 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Sat, 13 Nov 2021 11:51:11 +0900 Subject: [PATCH 15/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2045fc4a..7e520c0061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - メールアドレスのバリデーションを強化 ### Bugfixes +- アカウント削除処理があると高負荷になる問題を修正 - クライアント: 長いメニューが画面からはみ出す問題を修正 - クライアント: コントロールパネルのジョブキューに個々のジョブが表示されないのを修正 - クライアント: fix missing i18n string From 4ab773eb92d586f6ddbf2159d6a26a837e1b3717 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Sat, 13 Nov 2021 12:23:19 +0900 Subject: [PATCH 16/16] 12.96.0 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e520c0061..032d76e457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ --> -## 12.x.x (unreleased) +## 12.96.0 (2021/11/13) ### Improvements - フォロー/フォロワーを非公開にできるように diff --git a/package.json b/package.json index 20824aca10..86f8a03cbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.95.0", + "version": "12.96.0", "codename": "indigo", "repository": { "type": "git",