From a00a1fd6b5b6b0d34ea40f39e5db188a6c2a4793 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Sun, 1 May 2022 08:50:09 +0200 Subject: [PATCH 001/126] Refactor custom-css to use Composition API (#8571) * refactor(client): refactor custom-css to use Composition API * Apply review suggestion from @Johann150 Co-authored-by: Johann150 Co-authored-by: Johann150 --- .../client/src/pages/settings/custom-css.vue | 56 ++++++++----------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/packages/client/src/pages/settings/custom-css.vue b/packages/client/src/pages/settings/custom-css.vue index 556ee30c1d..20db077ceb 100644 --- a/packages/client/src/pages/settings/custom-css.vue +++ b/packages/client/src/pages/settings/custom-css.vue @@ -1,6 +1,6 @@ - From b00bf5740a01051dfb04b9aed3b5381c59d52c5c Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 1 May 2022 06:59:43 +0000 Subject: [PATCH 002/126] modify CHANGELOG.md --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b07e9002cf..510bf2121f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,6 @@ ## 12.x.x (unreleased) ### Improvements -- API: notifications/readは配列でも受け付けるように -- /share のクエリでリプライやファイル等の情報を渡せるように -- ページロードエラーページにリロードボタンを追加 ### Bugfixes - @@ -18,6 +15,9 @@ You should also include the user name that made the change. ### Improvements - enhance: ドライブに画像ファイルをアップロードするときオリジナル画像を破棄してwebpublicのみ保持するオプション @tamaina +- enhance: API: notifications/readは配列でも受け付けるように #7667 @tamaina +- enhance: プッシュ通知を複数アカウント対応に #7667 @tamaina +- enhance: プッシュ通知にクリックやactionを設定 #7667 @tamaina ### Bugfixes - Client: fix settings page @tamaina From 60391ff37e147c906a8736dbfede9d3b5e7ede3a Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sun, 1 May 2022 19:14:14 +0900 Subject: [PATCH 003/126] fix: Add rel attribute to host-meta (#8583) * Add rel attribute to host-meta * CHANGELOG --- CHANGELOG.md | 1 + packages/backend/src/server/well-known.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510bf2121f..a13686b438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ You should also include the user name that made the change. - Client: fix profile tabs @futchitwo - Server: await promises when following or unfollowing users @Johann150 - Client: fix abuse reports page to be able to show all reports @Johann150 +- Federation: Add rel attribute to host-meta @mei23 ## 12.110.1 (2022/04/23) diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index 7530b4e0ba..1d094f2edd 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -41,6 +41,7 @@ router.options(allPath, async ctx => { router.get('/.well-known/host-meta', async ctx => { ctx.set('Content-Type', xrd); ctx.body = XRD({ element: 'Link', attributes: { + rel: 'lrdd', type: xrd, template: `${config.url}${webFingerPath}?resource={uri}`, } }); From 6ed010b19238be79435238df604a78b2e10e9c4b Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 1 May 2022 12:23:34 +0200 Subject: [PATCH 004/126] fix _misskey_content of quote renotes (#8533) --- packages/backend/src/services/note/create.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index f14bc2059b..ceb5e8cc71 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -187,6 +187,8 @@ export default async (user: { id: User['id']; username: User['username']; host: if (data.text) { data.text = data.text.trim(); + } else { + data.text = null; } let tags = data.apHashtags; From a89003b57a27379f056e4f1be907e41e91b7b598 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 1 May 2022 22:51:07 +0900 Subject: [PATCH 005/126] refactor: use Vite to build instead of webpack (#8575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update stream.ts * https://github.com/misskey-dev/misskey/pull/7769#issuecomment-917542339 * fix lint * clean up? * add app * fix * nanka iroiro * wip * wip * fix lint * fix loginId * fix * refactor * refactor * remove follow action * clean up * Revert "remove follow action" This reverts commit defbb416480905af2150d1c92f10d8e1d1288c0a. * Revert "clean up" This reverts commit f94919cb9cff41e274044fc69c56ad36a33974f2. * remove fetch specification * renoteの条件追加 * apiFetch => cli * bypass fetch? * fix * refactor: use path alias * temp: add submodule * remove submodule * enhane: unison-reloadに指定したパスに移動できるように * null * null * feat: ログインするアカウントのIDをクエリ文字列で指定する機能 * null * await? * rename * rename * Update read.ts * merge * get-note-summary * fix * swパッケージに * add missing packages * fix getNoteSummary * add webpack-cli * :v: * remove plugins * sw-inject分離したがテストしてない * fix notification.vue * remove a blank line * disconnect intersection observer * disconnect2 * fix notification.vue * remove a blank line * disconnect intersection observer * disconnect2 * fix * :v: * clean up config * typesを戻した * Update packages/client/src/components/notification.vue Co-authored-by: Acid Chicken (硫酸鶏) * disconnect * oops * Failed to load the script unexpectedly回避 sw.jsとlib.tsを分離してみた * truncate notification * Update packages/client/src/ui/_common_/common.vue Co-authored-by: syuilo * clean up * clean up * キャッシュ対策 * Truncate push notification message * クライアントがあったらストリームに接続しているということなので通知しない判定の位置を修正 * components/drive-file-thumbnail.vue * components/drive-select-dialog.vue * components/drive-window.vue * merge * fix * Service Workerのビルドにesbuildを使うようにする * return createEmptyNotification() * fix * i18n.ts * update * :v: * remove ts-loader * fix * fix * enhance: Service Workerを常に登録するように * pollEnded * URLをsw.jsに戻す * clean up * wip * wip * wip * wip * wip * wip * :v: * use import * fix * install rollup * use defineAsyncComponent. * fix emojilist * wip use defineAsyncComponent * popup(import -> popup(defineAsyncComponent(() => import * draggable? * fix init import * clean up * fix router * add comment * :v: * :v: * :v: * remove webpack * update vite * fix boot sequence * Revert "fix boot sequence" This reverts commit e893dbf37aed83bf9f12e427d98c78a7065b4a39. * revert boot import * never make two app div * ; * remove console.log * change clientEntry sequence * fix * Revert "fix" This reverts commit 12741b3d89950a31dbb1bb81477ddb27b0e9951a. * fix * add comment https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210 * add log * add comment Co-authored-by: Acid Chicken (硫酸鶏) Co-authored-by: syuilo --- gulpfile.js | 1 - packages/backend/src/config/load.ts | 2 + packages/backend/src/config/types.ts | 1 + packages/backend/src/server/web/boot.js | 14 +- packages/backend/src/server/web/index.ts | 4 + .../backend/src/server/web/views/base.pug | 4 + packages/client/@types/theme.d.ts | 5 + packages/client/package.json | 24 +- packages/client/src/account.ts | 6 +- .../client/src/components/abuse-report.vue | 8 +- .../client/src/components/analog-clock.vue | 2 +- packages/client/src/components/chart.vue | 12 +- packages/client/src/components/drive.file.vue | 4 +- .../client/src/components/drive.folder.vue | 4 +- .../client/src/components/emoji-picker.vue | 2 +- packages/client/src/components/form/range.vue | 4 +- .../client/src/components/global/header.vue | 2 +- packages/client/src/components/global/url.vue | 4 +- packages/client/src/components/link.vue | 4 +- packages/client/src/components/mention.vue | 2 +- .../src/components/post-form-attaches.vue | 2 +- packages/client/src/components/post-form.vue | 4 +- packages/client/src/components/signin.vue | 4 +- packages/client/src/components/signup.vue | 2 +- packages/client/src/components/ui/folder.vue | 2 +- packages/client/src/components/widgets.vue | 2 +- packages/client/src/directives/tooltip.ts | 4 +- .../client/src/directives/user-preview.ts | 4 +- packages/client/src/init.ts | 42 +- packages/client/src/os.ts | 47 +- packages/client/src/pages/admin/emojis.vue | 4 +- packages/client/src/pages/admin/files.vue | 4 +- packages/client/src/pages/api-console.vue | 4 +- packages/client/src/pages/reset-password.vue | 4 +- .../client/src/pages/settings/accounts.vue | 6 +- packages/client/src/pages/settings/api.vue | 4 +- packages/client/src/pages/settings/drive.vue | 2 +- .../src/pages/settings/notifications.vue | 4 +- .../src/pages/settings/plugin.install.vue | 4 +- .../client/src/pages/settings/reaction.vue | 4 +- .../src/pages/settings/theme.install.vue | 2 +- .../src/pages/settings/theme.manage.vue | 2 +- packages/client/src/pages/settings/theme.vue | 2 +- packages/client/src/pages/theme-editor.vue | 4 +- packages/client/src/pages/user/index.vue | 2 +- packages/client/src/router.ts | 51 +- packages/client/src/scripts/autocomplete.ts | 6 +- packages/client/src/scripts/emojilist.ts | 2 +- packages/client/src/scripts/get-note-menu.ts | 4 +- packages/client/src/scripts/get-user-menu.ts | 3 +- packages/client/src/scripts/hpml/lib.ts | 4 +- .../client/src/scripts/reaction-picker.ts | 4 +- packages/client/src/scripts/theme.ts | 38 +- packages/client/src/store.ts | 7 +- packages/client/src/ui/_common_/common.vue | 2 +- .../src/ui/_common_/sidebar-for-mobile.vue | 4 +- packages/client/src/ui/_common_/sidebar.vue | 4 +- packages/client/src/ui/classic.header.vue | 4 +- packages/client/src/ui/classic.sidebar.vue | 4 +- .../src/ui/deck/notifications-column.vue | 4 +- packages/client/src/widgets/notifications.vue | 3 +- packages/client/tsconfig.json | 6 + packages/client/vite.config.ts | 72 + packages/client/vite.json5.ts | 38 + packages/client/webpack.config.js | 192 -- packages/client/yarn.lock | 2102 ++--------------- 66 files changed, 548 insertions(+), 2280 deletions(-) create mode 100644 packages/client/@types/theme.d.ts create mode 100644 packages/client/vite.config.ts create mode 100644 packages/client/vite.json5.ts delete mode 100644 packages/client/webpack.config.js diff --git a/gulpfile.js b/gulpfile.js index b7aa4e328e..90f8ebaabe 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -37,7 +37,6 @@ gulp.task('copy:client:locales', cb => { gulp.task('build:backend:script', () => { return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js']) - .pipe(replace('VERSION', JSON.stringify(meta.version))) .pipe(replace('LANGS', JSON.stringify(Object.keys(locales)))) .pipe(terser({ toplevel: true diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 7f765463e4..c2e6bea45e 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -25,6 +25,7 @@ const path = process.env.NODE_ENV === 'test' export default function load() { const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/meta.json`, 'utf-8')); + const clientManifest = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/_client_dist_/manifest.json`, 'utf-8')); const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source; const mixin = {} as Mixin; @@ -45,6 +46,7 @@ export default function load() { mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`; mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`; mixin.userAgent = `Misskey/${meta.version} (${config.url})`; + mixin.clientEntry = clientManifest['src/init.ts'].file.replace(/^_client_dist_\//, ''); if (!config.redis.prefix) config.redis.prefix = mixin.host; diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 58a27803cb..948545db7a 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -80,6 +80,7 @@ export type Mixin = { authUrl: string; driveUrl: string; userAgent: string; + clientEntry: string; }; export type Config = Source & Mixin; diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 751e8619bf..a9ee0df4f1 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -58,15 +58,11 @@ ? `?salt=${localStorage.getItem('salt')}` : ''; - const script = document.createElement('script'); - script.setAttribute('src', `/assets/app.${v}.js${salt}`); - script.setAttribute('async', 'true'); - script.setAttribute('defer', 'true'); - script.addEventListener('error', async () => { - await checkUpdate(); - renderError('APP_FETCH_FAILED'); - }); - document.head.appendChild(script); + import(`/assets/${CLIENT_ENTRY}${salt}`) + .catch(async () => { + await checkUpdate(); + renderError('APP_FETCH_FAILED'); + }) //#endregion //#region Theme diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 061ea50609..9e31f2389e 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -4,6 +4,7 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { PathOrFileDescriptor, readFileSync } from 'node:fs'; import ms from 'ms'; import Koa from 'koa'; import Router from '@koa/router'; @@ -73,6 +74,9 @@ app.use(views(_dirname + '/views', { extension: 'pug', options: { version: config.version, + clientEntry: () => process.env.NODE_ENV === 'production' ? + config.clientEntry : + JSON.parse(readFileSync(`${_dirname}/../../../../../built/_client_dist_/manifest.json`, 'utf-8'))['src/init.ts'].file.replace(/^_client_dist_\//, ''), config, }, })); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 1513208310..d79354d118 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -50,6 +50,10 @@ html style include ../style.css + script. + var VERSION = "#{version}"; + var CLIENT_ENTRY = "#{clientEntry()}"; + script include ../boot.js diff --git a/packages/client/@types/theme.d.ts b/packages/client/@types/theme.d.ts new file mode 100644 index 0000000000..b8b906b82e --- /dev/null +++ b/packages/client/@types/theme.d.ts @@ -0,0 +1,5 @@ +import { Theme } from '../src/scripts/theme'; + +declare module '@/themes/*.json5' { + export = Theme; +} diff --git a/packages/client/package.json b/packages/client/package.json index e533e1fb87..1d62d78d88 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,8 +1,8 @@ { "private": true, "scripts": { - "watch": "webpack --watch", - "build": "webpack", + "watch": "vite build --watch --mode development", + "build": "vite build", "lint": "eslint --quiet \"src/**/*.{ts,vue}\"" }, "resolutions": { @@ -12,8 +12,11 @@ "dependencies": { "@discordapp/twemoji": "13.1.1", "@fortawesome/fontawesome-free": "6.1.1", + "@rollup/plugin-alias": "3.1.9", + "@rollup/plugin-json": "4.1.0", "@syuilo/aiscript": "0.11.1", "@typescript-eslint/parser": "5.20.0", + "@vitejs/plugin-vue": "2.3.1", "@vue/compiler-sfc": "3.2.33", "abort-controller": "3.0.0", "autobind-decorator": "2.4.0", @@ -28,8 +31,6 @@ "chartjs-plugin-zoom": "1.2.1", "compare-versions": "4.1.3", "content-disposition": "0.5.4", - "css-loader": "6.7.1", - "cssnano": "5.1.7", "date-fns": "2.28.0", "escape-regexp": "0.0.1", "eslint": "8.14.0", @@ -40,7 +41,6 @@ "idb-keyval": "6.1.0", "insert-text-at-cursor": "0.3.0", "json5": "2.2.1", - "json5-loader": "4.0.1", "katex": "0.15.3", "matter-js": "0.18.0", "mfm-js": "0.21.0", @@ -51,8 +51,6 @@ "parse5": "6.0.1", "photoswipe": "5.2.4", "portscanner": "2.2.0", - "postcss": "8.4.12", - "postcss-loader": "6.2.1", "prismjs": "1.28.0", "private-ip": "2.3.3", "promise-limit": "2.7.0", @@ -63,19 +61,17 @@ "random-seed": "0.3.0", "reflect-metadata": "0.1.13", "rndstr": "1.0.0", + "rollup": "2.70.2", "s-age": "1.1.2", "sass": "1.50.1", - "sass-loader": "12.6.0", "seedrandom": "3.0.5", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "style-loader": "3.3.1", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", "three": "0.139.2", "throttle-debounce": "4.0.1", "tinycolor2": "1.4.2", - "ts-loader": "9.2.8", "tsc-alias": "1.5.0", "tsconfig-paths": "3.14.1", "twemoji-parser": "14.0.0", @@ -83,15 +79,11 @@ "uuid": "8.3.2", "v-debounce": "0.1.2", "vanilla-tilt": "1.7.2", + "vite": "2.9.6", "vue": "3.2.33", - "vue-loader": "17.0.0", "vue-prism-editor": "2.0.0-alpha.2", "vue-router": "4.0.14", - "vue-style-loader": "4.1.3", - "vue-svg-loader": "0.17.0-beta.2", "vuedraggable": "4.0.1", - "webpack": "5.72.0", - "webpack-cli": "4.9.2", "websocket": "1.0.34", "ws": "8.5.0" }, @@ -113,8 +105,6 @@ "@types/throttle-debounce": "4.0.0", "@types/tinycolor2": "1.4.3", "@types/uuid": "8.3.4", - "@types/webpack": "5.28.0", - "@types/webpack-stream": "3.2.12", "@types/websocket": "1.0.5", "@types/ws": "8.5.3", "@typescript-eslint/eslint-plugin": "5.20.0", diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts index f4dcab319c..6f806ccc58 100644 --- a/packages/client/src/account.ts +++ b/packages/client/src/account.ts @@ -1,5 +1,5 @@ import { del, get, set } from '@/scripts/idb-proxy'; -import { reactive } from 'vue'; +import { defineAsyncComponent, reactive } from 'vue'; import * as misskey from 'misskey-js'; import { apiUrl } from '@/config'; import { waiting, api, popup, popupMenu, success, alert } from '@/os'; @@ -141,7 +141,7 @@ export async function openAccountMenu(opts: { onChoose?: (account: misskey.entities.UserDetailed) => void; }, ev: MouseEvent) { function showSigninDialog() { - popup(import('@/components/signin-dialog.vue'), {}, { + popup(defineAsyncComponent(() => import('@/components/signin-dialog.vue')), {}, { done: res => { addAccount(res.id, res.i); success(); @@ -150,7 +150,7 @@ export async function openAccountMenu(opts: { } function createAccount() { - popup(import('@/components/signup-dialog.vue'), {}, { + popup(defineAsyncComponent(() => import('@/components/signup-dialog.vue')), {}, { done: res => { addAccount(res.id, res.i); switchAccountWithToken(res.i); diff --git a/packages/client/src/components/abuse-report.vue b/packages/client/src/components/abuse-report.vue index b67cef209b..46d45b690f 100644 --- a/packages/client/src/components/abuse-report.vue +++ b/packages/client/src/components/abuse-report.vue @@ -43,20 +43,20 @@ export default defineComponent({ MkSwitch, }, - emits: ['resolved'], - props: { report: { type: Object, required: true, } - } + }, + + emits: ['resolved'], data() { return { forward: this.report.forwarded, }; - } + }, methods: { acct, diff --git a/packages/client/src/components/analog-clock.vue b/packages/client/src/components/analog-clock.vue index 59b8e97304..18dd1e3f41 100644 --- a/packages/client/src/components/analog-clock.vue +++ b/packages/client/src/components/analog-clock.vue @@ -42,7 +42,7 @@ From 1f222e6cd19dcf2f4bb679e810090f11ce6fdc6a Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 3 May 2022 13:34:48 +0200 Subject: [PATCH 009/126] refactor(client): refactor settings/theme to use Composition API (#8595) --- packages/client/src/pages/settings/theme.vue | 151 ++++++++----------- 1 file changed, 64 insertions(+), 87 deletions(-) diff --git a/packages/client/src/pages/settings/theme.vue b/packages/client/src/pages/settings/theme.vue index a3ddc9a2ff..64b384bdcd 100644 --- a/packages/client/src/pages/settings/theme.vue +++ b/packages/client/src/pages/settings/theme.vue @@ -85,12 +85,11 @@ - From f8c66be130f3209e9c993fdde95ded6fecdfeeaf Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Wed, 4 May 2022 03:10:34 +0200 Subject: [PATCH 010/126] refactor(client): refactor settings/security to use Composition API (#8592) --- .../client/src/pages/settings/security.vue | 136 ++++++++---------- 1 file changed, 61 insertions(+), 75 deletions(-) diff --git a/packages/client/src/pages/settings/security.vue b/packages/client/src/pages/settings/security.vue index 6fb3f1c413..401648790a 100644 --- a/packages/client/src/pages/settings/security.vue +++ b/packages/client/src/pages/settings/security.vue @@ -1,17 +1,17 @@ - From 9230334a319c93d1604576778ed39c9de9d510ce Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Wed, 4 May 2022 05:25:19 +0200 Subject: [PATCH 022/126] Refactor settings/notifications to use Composition API (#8587) * refactor(client): refactor settings/notifications to use Composition API * fix(client): use async/await for API methods --- .../src/pages/settings/notifications.vue | 88 ++++++++----------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/packages/client/src/pages/settings/notifications.vue b/packages/client/src/pages/settings/notifications.vue index 334216ff33..6fe2ac55a4 100644 --- a/packages/client/src/pages/settings/notifications.vue +++ b/packages/client/src/pages/settings/notifications.vue @@ -1,71 +1,59 @@ From d075ead80a7bbec84de2129b6579b9410e0b1154 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 11:21:38 +0200 Subject: [PATCH 023/126] fix(client): fix duplicate token request dialog in plugin install (#8612) --- .../src/pages/settings/plugin.install.vue | 42 +++++-------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/packages/client/src/pages/settings/plugin.install.vue b/packages/client/src/pages/settings/plugin.install.vue index 5cf427d18f..6ece531462 100644 --- a/packages/client/src/pages/settings/plugin.install.vue +++ b/packages/client/src/pages/settings/plugin.install.vue @@ -78,37 +78,6 @@ async function install() { return; } - const token = permissions == null || permissions.length === 0 ? null : await new Promise((res, rej) => { - os.popup(import('@/components/token-generate-window.vue'), { - title: i18n.ts.tokenRequested, - information: i18n.ts.pluginTokenRequestedDescription, - initialName: name, - initialPermissions: permissions - }, { - done: async result => { - const { name, permissions } = result; - const { token } = await os.api('miauth/gen-token', { - session: null, - name: name, - permission: permissions, - }); - - res(token); - } - }, 'closed'); - }); - - installPlugin({ - id: uuid(), - meta: { - name, version, author, description, permissions, config - }, - token, - ast: serialize(ast) - }); - - os.success(); - const token = permissions == null || permissions.length === 0 ? null : await new Promise((res, rej) => { os.popup(defineAsyncComponent(() => import('@/components/token-generate-window.vue')), { title: i18n.ts.tokenRequested, @@ -128,6 +97,17 @@ async function install() { }, 'closed'); }); + installPlugin({ + id: uuid(), + meta: { + name, version, author, description, permissions, config + }, + token, + ast: serialize(ast) + }); + + os.success(); + nextTick(() => { unisonReload(); }); From a36f54dec2bd9033f7bc0992a44af88740f4a1dc Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 5 May 2022 18:33:24 +0900 Subject: [PATCH 024/126] Update CONTRIBUTING.md --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a696bc5ceb..1d82a0cbb3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,6 +62,19 @@ Be willing to comment on the good points and not just the things you want fixed - Are there any omissions or gaps? - Does it check for anomalies? +## Merge +For now, basically only @syuilo has the authority to merge PRs into develop because he is most familiar with the codebase. +However, minor fixes, refactoring, and urgent changes may be merged at the discretion of a contributor. + +## Release +For now, basically only @syuilo has the authority to release Misskey. +However, in case of emergency, a release can be made at the discretion of a contributor. + +### Release Instructions +1. commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) +2. follow the `master` branch to the `develop` branch. +3. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) + ## Localization (l10n) Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management. You can improve our translations with your Crowdin account. From 56436b99bb9dbff1e8bef8045bdfe52129388b8c Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 5 May 2022 18:36:30 +0900 Subject: [PATCH 025/126] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d82a0cbb3..efdccc7848 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,6 +74,8 @@ However, in case of emergency, a release can be made at the discretion of a cont 1. commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) 2. follow the `master` branch to the `develop` branch. 3. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) + - The target branch must be `master` + - The tag name must be the version ## Localization (l10n) Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management. From dd8cb7846fc7f8295a3780bad4b05f9d46dcf3a9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 5 May 2022 18:38:30 +0900 Subject: [PATCH 026/126] Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index efdccc7848..cafca625d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,8 +74,8 @@ However, in case of emergency, a release can be made at the discretion of a cont 1. commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) 2. follow the `master` branch to the `develop` branch. 3. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) - - The target branch must be `master` - - The tag name must be the version + - The target branch must be `master` + - The tag name must be the version ## Localization (l10n) Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management. From 7362c2da76ce8f03fb0a2eabf301db3966b52dd0 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 13:45:50 +0200 Subject: [PATCH 027/126] Fix lint issues in Drive components (#8613) * fix(client): Fix lint issues in Drive components * fix(client): only use !=/== for null comparisons * Update drive.vue Co-authored-by: syuilo --- .../src/components/drive-file-thumbnail.vue | 2 +- .../src/components/drive-select-dialog.vue | 4 +- .../client/src/components/drive-window.vue | 2 +- packages/client/src/components/drive.file.vue | 22 ++--- .../client/src/components/drive.folder.vue | 14 ++-- .../src/components/drive.nav-folder.vue | 42 +++++----- packages/client/src/components/drive.vue | 82 +++++++++---------- 7 files changed, 84 insertions(+), 84 deletions(-) diff --git a/packages/client/src/components/drive-file-thumbnail.vue b/packages/client/src/components/drive-file-thumbnail.vue index 81b80e7e8e..dd24440e82 100644 --- a/packages/client/src/components/drive-file-thumbnail.vue +++ b/packages/client/src/components/drive-file-thumbnail.vue @@ -42,7 +42,7 @@ const is = computed(() => { "application/x-tar", "application/gzip", "application/x-7z-compressed" - ].some(e => e === props.file.type)) return 'archive'; + ].some(archiveType => archiveType === props.file.type)) return 'archive'; return 'unknown'; }); diff --git a/packages/client/src/components/drive-select-dialog.vue b/packages/client/src/components/drive-select-dialog.vue index f6c59457d1..03974559d2 100644 --- a/packages/client/src/components/drive-select-dialog.vue +++ b/packages/client/src/components/drive-select-dialog.vue @@ -33,8 +33,8 @@ withDefaults(defineProps<{ }); const emit = defineEmits<{ - (e: 'done', r?: Misskey.entities.DriveFile[]): void; - (e: 'closed'): void; + (ev: 'done', r?: Misskey.entities.DriveFile[]): void; + (ev: 'closed'): void; }>(); const dialog = ref>(); diff --git a/packages/client/src/components/drive-window.vue b/packages/client/src/components/drive-window.vue index d08c5fb674..5bbfca83c9 100644 --- a/packages/client/src/components/drive-window.vue +++ b/packages/client/src/components/drive-window.vue @@ -24,6 +24,6 @@ defineProps<{ }>(); const emit = defineEmits<{ - (e: 'closed'): void; + (ev: 'closed'): void; }>(); diff --git a/packages/client/src/components/drive.file.vue b/packages/client/src/components/drive.file.vue index e2f78a84ec..aaf7ca3ca3 100644 --- a/packages/client/src/components/drive.file.vue +++ b/packages/client/src/components/drive.file.vue @@ -50,9 +50,9 @@ const props = withDefaults(defineProps<{ }); const emit = defineEmits<{ - (e: 'chosen', r: Misskey.entities.DriveFile): void; - (e: 'dragstart'): void; - (e: 'dragend'): void; + (ev: 'chosen', r: Misskey.entities.DriveFile): void; + (ev: 'dragstart'): void; + (ev: 'dragend'): void; }>(); const isDragging = ref(false); @@ -99,14 +99,14 @@ function onClick(ev: MouseEvent) { } } -function onContextmenu(e: MouseEvent) { - os.contextMenu(getMenu(), e); +function onContextmenu(ev: MouseEvent) { + os.contextMenu(getMenu(), ev); } -function onDragstart(e: DragEvent) { - if (e.dataTransfer) { - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FILE_, JSON.stringify(props.file)); +function onDragstart(ev: DragEvent) { + if (ev.dataTransfer) { + ev.dataTransfer.effectAllowed = 'move'; + ev.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FILE_, JSON.stringify(props.file)); } isDragging.value = true; @@ -137,7 +137,7 @@ function describe() { title: i18n.ts.describeFile, input: { placeholder: i18n.ts.inputNewDescription, - default: props.file.comment !== null ? props.file.comment : '', + default: props.file.comment != null ? props.file.comment : '', }, image: props.file }, { @@ -146,7 +146,7 @@ function describe() { let comment = result.result; os.api('drive/files/update', { fileId: props.file.id, - comment: comment.length == 0 ? null : comment + comment: comment.length === 0 ? null : comment }); } }, 'closed'); diff --git a/packages/client/src/components/drive.folder.vue b/packages/client/src/components/drive.folder.vue index e7003a8074..d530f8beff 100644 --- a/packages/client/src/components/drive.folder.vue +++ b/packages/client/src/components/drive.folder.vue @@ -84,12 +84,12 @@ function onDragover(ev: DragEvent) { return; } - const isFile = ev.dataTransfer.items[0].kind == 'file'; - const isDriveFile = ev.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = ev.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_; + const isFile = ev.dataTransfer.items[0].kind === 'file'; + const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; + const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; if (isFile || isDriveFile || isDriveFolder) { - ev.dataTransfer.dropEffect = ev.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + ev.dataTransfer.dropEffect = ev.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move'; } else { ev.dataTransfer.dropEffect = 'none'; } @@ -118,7 +118,7 @@ function onDrop(ev: DragEvent) { //#region ドライブのファイル const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); - if (driveFile != null && driveFile != '') { + if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); os.api('drive/files/update', { @@ -130,11 +130,11 @@ function onDrop(ev: DragEvent) { //#region ドライブのフォルダ const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); - if (driveFolder != null && driveFolder != '') { + if (driveFolder != null && driveFolder !== '') { const folder = JSON.parse(driveFolder); // 移動先が自分自身ならreject - if (folder.id == props.folder.id) return; + if (folder.id === props.folder.id) return; emit('removeFolder', folder.id); os.api('drive/folders/update', { diff --git a/packages/client/src/components/drive.nav-folder.vue b/packages/client/src/components/drive.nav-folder.vue index 67223267c1..5482703317 100644 --- a/packages/client/src/components/drive.nav-folder.vue +++ b/packages/client/src/components/drive.nav-folder.vue @@ -24,10 +24,10 @@ const props = defineProps<{ }>(); const emit = defineEmits<{ - (e: 'move', v?: Misskey.entities.DriveFolder): void; - (e: 'upload', file: File, folder?: Misskey.entities.DriveFolder | null): void; - (e: 'removeFile', v: Misskey.entities.DriveFile['id']): void; - (e: 'removeFolder', v: Misskey.entities.DriveFolder['id']): void; + (ev: 'move', v?: Misskey.entities.DriveFolder): void; + (ev: 'upload', file: File, folder?: Misskey.entities.DriveFolder | null): void; + (ev: 'removeFile', v: Misskey.entities.DriveFile['id']): void; + (ev: 'removeFolder', v: Misskey.entities.DriveFolder['id']): void; }>(); const hover = ref(false); @@ -45,22 +45,22 @@ function onMouseout() { hover.value = false; } -function onDragover(e: DragEvent) { - if (!e.dataTransfer) return; +function onDragover(ev: DragEvent) { + if (!ev.dataTransfer) return; // このフォルダがルートかつカレントディレクトリならドロップ禁止 if (props.folder == null && props.parentFolder == null) { - e.dataTransfer.dropEffect = 'none'; + ev.dataTransfer.dropEffect = 'none'; } - const isFile = e.dataTransfer.items[0].kind == 'file'; - const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_; + const isFile = ev.dataTransfer.items[0].kind === 'file'; + const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; + const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; if (isFile || isDriveFile || isDriveFolder) { - e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + ev.dataTransfer.dropEffect = ev.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move'; } else { - e.dataTransfer.dropEffect = 'none'; + ev.dataTransfer.dropEffect = 'none'; } return false; @@ -74,22 +74,22 @@ function onDragleave() { if (props.folder || props.parentFolder) draghover.value = false; } -function onDrop(e: DragEvent) { +function onDrop(ev: DragEvent) { draghover.value = false; - if (!e.dataTransfer) return; + if (!ev.dataTransfer) return; // ファイルだったら - if (e.dataTransfer.files.length > 0) { - for (const file of Array.from(e.dataTransfer.files)) { + if (ev.dataTransfer.files.length > 0) { + for (const file of Array.from(ev.dataTransfer.files)) { emit('upload', file, props.folder); } return; } //#region ドライブのファイル - const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); - if (driveFile != null && driveFile != '') { + const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); emit('removeFile', file.id); os.api('drive/files/update', { @@ -100,11 +100,11 @@ function onDrop(e: DragEvent) { //#endregion //#region ドライブのフォルダ - const driveFolder = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); - if (driveFolder != null && driveFolder != '') { + const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); + if (driveFolder != null && driveFolder !== '') { const folder = JSON.parse(driveFolder); // 移動先が自分自身ならreject - if (props.folder && folder.id == props.folder.id) return; + if (props.folder && folder.id === props.folder.id) return; emit('removeFolder', folder.id); os.api('drive/folders/update', { folderId: folder.id, diff --git a/packages/client/src/components/drive.vue b/packages/client/src/components/drive.vue index 2ec885b00c..42ec3a5995 100644 --- a/packages/client/src/components/drive.vue +++ b/packages/client/src/components/drive.vue @@ -110,11 +110,11 @@ const props = withDefaults(defineProps<{ }); const emit = defineEmits<{ - (e: 'selected', v: Misskey.entities.DriveFile | Misskey.entities.DriveFolder): void; - (e: 'change-selection', v: Misskey.entities.DriveFile[] | Misskey.entities.DriveFolder[]): void; - (e: 'move-root'): void; - (e: 'cd', v: Misskey.entities.DriveFolder | null): void; - (e: 'open-folder', v: Misskey.entities.DriveFolder): void; + (ev: 'selected', v: Misskey.entities.DriveFile | Misskey.entities.DriveFolder): void; + (ev: 'change-selection', v: Misskey.entities.DriveFile[] | Misskey.entities.DriveFolder[]): void; + (ev: 'move-root'): void; + (ev: 'cd', v: Misskey.entities.DriveFolder | null): void; + (ev: 'open-folder', v: Misskey.entities.DriveFolder): void; }>(); const loadMoreFiles = ref>(); @@ -153,7 +153,7 @@ function onStreamDriveFileCreated(file: Misskey.entities.DriveFile) { function onStreamDriveFileUpdated(file: Misskey.entities.DriveFile) { const current = folder.value ? folder.value.id : null; - if (current != file.folderId) { + if (current !== file.folderId) { removeFile(file); } else { addFile(file, true); @@ -170,7 +170,7 @@ function onStreamDriveFolderCreated(createdFolder: Misskey.entities.DriveFolder) function onStreamDriveFolderUpdated(updatedFolder: Misskey.entities.DriveFolder) { const current = folder.value ? folder.value.id : null; - if (current != updatedFolder.parentId) { + if (current !== updatedFolder.parentId) { removeFolder(updatedFolder); } else { addFolder(updatedFolder, true); @@ -181,23 +181,23 @@ function onStreamDriveFolderDeleted(folderId: string) { removeFolder(folderId); } -function onDragover(e: DragEvent): any { - if (!e.dataTransfer) return; +function onDragover(ev: DragEvent): any { + if (!ev.dataTransfer) return; // ドラッグ元が自分自身の所有するアイテムだったら if (isDragSource.value) { // 自分自身にはドロップさせない - e.dataTransfer.dropEffect = 'none'; + ev.dataTransfer.dropEffect = 'none'; return; } - const isFile = e.dataTransfer.items[0].kind == 'file'; - const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_; - const isDriveFolder = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_; + const isFile = ev.dataTransfer.items[0].kind === 'file'; + const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; + const isDriveFolder = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FOLDER_; if (isFile || isDriveFile || isDriveFolder) { - e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + ev.dataTransfer.dropEffect = ev.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move'; } else { - e.dataTransfer.dropEffect = 'none'; + ev.dataTransfer.dropEffect = 'none'; } return false; @@ -211,24 +211,24 @@ function onDragleave() { draghover.value = false; } -function onDrop(e: DragEvent): any { +function onDrop(ev: DragEvent): any { draghover.value = false; - if (!e.dataTransfer) return; + if (!ev.dataTransfer) return; // ドロップされてきたものがファイルだったら - if (e.dataTransfer.files.length > 0) { - for (const file of Array.from(e.dataTransfer.files)) { + if (ev.dataTransfer.files.length > 0) { + for (const file of Array.from(ev.dataTransfer.files)) { upload(file, folder.value); } return; } //#region ドライブのファイル - const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); - if (driveFile != null && driveFile != '') { + const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); - if (files.value.some(f => f.id == file.id)) return; + if (files.value.some(f => f.id === file.id)) return; removeFile(file.id); os.api('drive/files/update', { fileId: file.id, @@ -238,13 +238,13 @@ function onDrop(e: DragEvent): any { //#endregion //#region ドライブのフォルダ - const driveFolder = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); - if (driveFolder != null && driveFolder != '') { + const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_); + if (driveFolder != null && driveFolder !== '') { const droppedFolder = JSON.parse(driveFolder); // 移動先が自分自身ならreject - if (folder.value && droppedFolder.id == folder.value.id) return false; - if (folders.value.some(f => f.id == droppedFolder.id)) return false; + if (folder.value && droppedFolder.id === folder.value.id) return false; + if (folders.value.some(f => f.id === droppedFolder.id)) return false; removeFolder(droppedFolder.id); os.api('drive/folders/update', { folderId: droppedFolder.id, @@ -357,16 +357,16 @@ function onChangeFileInput() { } function upload(file: File, folderToUpload?: Misskey.entities.DriveFolder | null) { - uploadFile(file, (folderToUpload && typeof folderToUpload == 'object') ? folderToUpload.id : null, undefined, keepOriginal.value).then(res => { + uploadFile(file, (folderToUpload && typeof folderToUpload === 'object') ? folderToUpload.id : null, undefined, keepOriginal.value).then(res => { addFile(res, true); }); } function chooseFile(file: Misskey.entities.DriveFile) { - const isAlreadySelected = selectedFiles.value.some(f => f.id == file.id); + const isAlreadySelected = selectedFiles.value.some(f => f.id === file.id); if (props.multiple) { if (isAlreadySelected) { - selectedFiles.value = selectedFiles.value.filter(f => f.id != file.id); + selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id); } else { selectedFiles.value.push(file); } @@ -382,10 +382,10 @@ function chooseFile(file: Misskey.entities.DriveFile) { } function chooseFolder(folderToChoose: Misskey.entities.DriveFolder) { - const isAlreadySelected = selectedFolders.value.some(f => f.id == folderToChoose.id); + const isAlreadySelected = selectedFolders.value.some(f => f.id === folderToChoose.id); if (props.multiple) { if (isAlreadySelected) { - selectedFolders.value = selectedFolders.value.filter(f => f.id != folderToChoose.id); + selectedFolders.value = selectedFolders.value.filter(f => f.id !== folderToChoose.id); } else { selectedFolders.value.push(folderToChoose); } @@ -404,7 +404,7 @@ function move(target?: Misskey.entities.DriveFolder) { if (!target) { goRoot(); return; - } else if (typeof target == 'object') { + } else if (typeof target === 'object') { target = target.id; } @@ -430,9 +430,9 @@ function move(target?: Misskey.entities.DriveFolder) { function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { const current = folder.value ? folder.value.id : null; - if (current != folderToAdd.parentId) return; + if (current !== folderToAdd.parentId) return; - if (folders.value.some(f => f.id == folderToAdd.id)) { + if (folders.value.some(f => f.id === folderToAdd.id)) { const exist = folders.value.map(f => f.id).indexOf(folderToAdd.id); folders.value[exist] = folderToAdd; return; @@ -447,9 +447,9 @@ function addFolder(folderToAdd: Misskey.entities.DriveFolder, unshift = false) { function addFile(fileToAdd: Misskey.entities.DriveFile, unshift = false) { const current = folder.value ? folder.value.id : null; - if (current != fileToAdd.folderId) return; + if (current !== fileToAdd.folderId) return; - if (files.value.some(f => f.id == fileToAdd.id)) { + if (files.value.some(f => f.id === fileToAdd.id)) { const exist = files.value.map(f => f.id).indexOf(fileToAdd.id); files.value[exist] = fileToAdd; return; @@ -464,12 +464,12 @@ function addFile(fileToAdd: Misskey.entities.DriveFile, unshift = false) { function removeFolder(folderToRemove: Misskey.entities.DriveFolder | string) { const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove; - folders.value = folders.value.filter(f => f.id != folderIdToRemove); + folders.value = folders.value.filter(f => f.id !== folderIdToRemove); } function removeFile(file: Misskey.entities.DriveFile | string) { const fileId = typeof file === 'object' ? file.id : file; - files.value = files.value.filter(f => f.id != fileId); + files.value = files.value.filter(f => f.id !== fileId); } function appendFile(file: Misskey.entities.DriveFile) { @@ -512,7 +512,7 @@ async function fetch() { folderId: folder.value ? folder.value.id : null, limit: foldersMax + 1 }).then(fetchedFolders => { - if (fetchedFolders.length == foldersMax + 1) { + if (fetchedFolders.length === foldersMax + 1) { moreFolders.value = true; fetchedFolders.pop(); } @@ -524,7 +524,7 @@ async function fetch() { type: props.type, limit: filesMax + 1 }).then(fetchedFiles => { - if (fetchedFiles.length == filesMax + 1) { + if (fetchedFiles.length === filesMax + 1) { moreFiles.value = true; fetchedFiles.pop(); } @@ -551,7 +551,7 @@ function fetchMoreFiles() { untilId: files.value[files.value.length - 1].id, limit: max + 1 }).then(files => { - if (files.length == max + 1) { + if (files.length === max + 1) { moreFiles.value = true; files.pop(); } else { From 1168e25721af9a2430e8ec8147487f247dc7ec99 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 5 May 2022 20:46:46 +0900 Subject: [PATCH 028/126] fix (client): fix mention icon height (#8615) --- packages/client/src/components/mention.vue | 40 ++++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/packages/client/src/components/mention.vue b/packages/client/src/components/mention.vue index 39a333c5e8..70c2f49afa 100644 --- a/packages/client/src/components/mention.vue +++ b/packages/client/src/components/mention.vue @@ -1,21 +1,21 @@ - From bd620a8c7782d485d4385cc95af744edef5986c9 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 15:41:10 +0200 Subject: [PATCH 029/126] refactor(client): refactor 2FA settings to Composition API (#8599) --- packages/client/src/pages/settings/2fa.vue | 325 ++++++++++----------- 1 file changed, 157 insertions(+), 168 deletions(-) diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue index 10599d99ff..9ebf5101cd 100644 --- a/packages/client/src/pages/settings/2fa.vue +++ b/packages/client/src/pages/settings/2fa.vue @@ -1,49 +1,49 @@ -
  • {{ $ts._2fa.step2 }}
  • -
  • {{ $ts._2fa.step3 }}
    - - {{ $ts.done }} +
  • {{ i18n.ts._2fa.step2 }}
  • +
  • {{ i18n.ts._2fa.step3 }}
    + + {{ i18n.ts.done }}
  • - {{ $ts._2fa.step4 }} + {{ i18n.ts._2fa.step4 }} - From 31c73fdfa2984c386b39f7e9ef70a52c1735efe3 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 5 May 2022 15:45:22 +0200 Subject: [PATCH 030/126] chore: synchronize code and database schema (#8577) * chore: remove default null null is always the default value if a table column is nullable, and typeorm's @Column only accepts strings for default. * chore: synchronize code with database schema * chore: sync generated migrations with code --- .../migration/1651224615271-foreign-key.js | 89 +++++++++++++++++++ .../src/models/entities/access-token.ts | 6 -- .../src/models/entities/auth-session.ts | 2 +- packages/backend/src/models/entities/clip.ts | 2 +- .../backend/src/models/entities/drive-file.ts | 1 - packages/backend/src/models/entities/emoji.ts | 1 + .../backend/src/models/entities/instance.ts | 20 ++--- packages/backend/src/models/entities/meta.ts | 4 +- .../backend/src/models/entities/muting.ts | 1 - packages/backend/src/models/entities/note.ts | 6 +- .../src/models/entities/user-profile.ts | 1 + packages/backend/src/models/entities/user.ts | 2 +- 12 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 packages/backend/migration/1651224615271-foreign-key.js diff --git a/packages/backend/migration/1651224615271-foreign-key.js b/packages/backend/migration/1651224615271-foreign-key.js new file mode 100644 index 0000000000..44ba7fb6c4 --- /dev/null +++ b/packages/backend/migration/1651224615271-foreign-key.js @@ -0,0 +1,89 @@ +export class foreignKeyReports1651224615271 { + name = 'foreignKeyReports1651224615271' + + async up(queryRunner) { + await Promise.all([ + queryRunner.query(`ALTER INDEX "public"."IDX_seoignmeoprigmkpodgrjmkpormg" RENAME TO "IDX_c8cc87bd0f2f4487d17c651fbf"`), + queryRunner.query(`DROP INDEX "public"."IDX_note_on_channelId_and_id_desc"`), + + // remove unnecessary default null, see also down + queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "followersUri" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "session" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "appId" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "name" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "description" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "iconUrl" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "softwareName" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "softwareVersion" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "name" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "description" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "maintainerName" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "maintainerEmail" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "iconUrl" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "faviconUrl" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "instance" ALTER COLUMN "themeColor" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "clip" ALTER COLUMN "description" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "channelId" DROP DEFAULT`), + queryRunner.query(`ALTER TABLE "abuse_user_report" ALTER COLUMN "comment" DROP DEFAULT`), + + queryRunner.query(`CREATE INDEX "IDX_315c779174fe8247ab324f036e" ON "drive_file" ("isLink")`), + queryRunner.query(`CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId")`), + queryRunner.query(`CREATE INDEX "IDX_a9021cc2e1feb5f72d3db6e9f5" ON "abuse_user_report" ("targetUserId")`), + + queryRunner.query(`DELETE FROM "abuse_user_report" WHERE "targetUserId" NOT IN (SELECT "id" FROM "user")`).then(() => { + queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_a9021cc2e1feb5f72d3db6e9f5f" FOREIGN KEY ("targetUserId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + }), + + queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b" UNIQUE ("noteId")`), + queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6" UNIQUE ("userId")`), + queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9" UNIQUE ("userId")`), + queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "UQ_10c146e4b39b443ede016f6736d" UNIQUE ("userId")`), + queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c" UNIQUE ("noteId")`), + + queryRunner.query(`ALTER TABLE "page" RENAME CONSTRAINT "FK_3126dd7c502c9e4d7597ef7ef10" TO "FK_a9ca79ad939bf06066b81c9d3aa"`), + + queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum" ADD VALUE 'pollEnded' AFTER 'pollVote'`), + ]); + } + + async down(queryRunner) { + await Promise.all([ + // There is no ALTER TYPE REMOVE VALUE query, so the reverse operation is a bit more complex + queryRunner.query(`UPDATE "user_profile" SET "mutingNotificationTypes" = array_remove("mutingNotificationTypes", 'pollEnded')`) + .then(() => + queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`) + ).then(() => + queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`) + ).then(() => + queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum_old"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum_old"[]`) + ).then(() => + queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`) + ).then(() => + queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum"`) + ).then(() => + queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum_old" RENAME TO "user_profile_mutingnotificationtypes_enum"`) + ), + + queryRunner.query(`ALTER TABLE "page" RENAME CONSTRAINT "FK_a9ca79ad939bf06066b81c9d3aa" TO "FK_3126dd7c502c9e4d7597ef7ef10"`), + + queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c"`), + queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "UQ_10c146e4b39b443ede016f6736d"`), + queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9"`), + queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6"`), + queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b"`), + + queryRunner.query(`ALTER TABLE "abuse_user_report" ALTER COLUMN "comment" SET DEFAULT '{}'`), + queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_a9021cc2e1feb5f72d3db6e9f5f"`), + + queryRunner.query(`DROP INDEX "public"."IDX_a9021cc2e1feb5f72d3db6e9f5"`), + queryRunner.query(`DROP INDEX "public"."IDX_f22169eb10657bded6d875ac8f"`), + queryRunner.query(`DROP INDEX "public"."IDX_315c779174fe8247ab324f036e"`), + + /* DEFAULT's are not set again because if the column can be NULL, then DEFAULT NULL is not necessary. + see also https://github.com/typeorm/typeorm/issues/7579#issuecomment-835423615 */ + + queryRunner.query(`CREATE INDEX "IDX_note_on_channelId_and_id_desc" ON "note" ("id", "channelId") `), + queryRunner.query(`ALTER INDEX "public"."IDX_c8cc87bd0f2f4487d17c651fbf" RENAME TO "IDX_seoignmeoprigmkpodgrjmkpormg"`), + ]); + } +} diff --git a/packages/backend/src/models/entities/access-token.ts b/packages/backend/src/models/entities/access-token.ts index 69cdc49cec..c6e2141a46 100644 --- a/packages/backend/src/models/entities/access-token.ts +++ b/packages/backend/src/models/entities/access-token.ts @@ -15,7 +15,6 @@ export class AccessToken { @Column('timestamp with time zone', { nullable: true, - default: null, }) public lastUsedAt: Date | null; @@ -29,7 +28,6 @@ export class AccessToken { @Column('varchar', { length: 128, nullable: true, - default: null, }) public session: string | null; @@ -52,7 +50,6 @@ export class AccessToken { @Column({ ...id(), nullable: true, - default: null, }) public appId: App['id'] | null; @@ -65,21 +62,18 @@ export class AccessToken { @Column('varchar', { length: 128, nullable: true, - default: null, }) public name: string | null; @Column('varchar', { length: 512, nullable: true, - default: null, }) public description: string | null; @Column('varchar', { length: 512, nullable: true, - default: null, }) public iconUrl: string | null; diff --git a/packages/backend/src/models/entities/auth-session.ts b/packages/backend/src/models/entities/auth-session.ts index b825856201..295d1b486c 100644 --- a/packages/backend/src/models/entities/auth-session.ts +++ b/packages/backend/src/models/entities/auth-session.ts @@ -23,7 +23,7 @@ export class AuthSession { ...id(), nullable: true, }) - public userId: User['id']; + public userId: User['id'] | null; @ManyToOne(type => User, { onDelete: 'CASCADE', diff --git a/packages/backend/src/models/entities/clip.ts b/packages/backend/src/models/entities/clip.ts index da6b3c7a7f..1386684c32 100644 --- a/packages/backend/src/models/entities/clip.ts +++ b/packages/backend/src/models/entities/clip.ts @@ -37,7 +37,7 @@ export class Clip { public isPublic: boolean; @Column('varchar', { - length: 2048, nullable: true, default: null, + length: 2048, nullable: true, comment: 'The description of the Clip.', }) public description: string | null; diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 3d375f0e35..a636d1d519 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -79,7 +79,6 @@ export class DriveFile { }) public properties: { width?: number; height?: number; orientation?: number; avgColor?: string }; - @Index() @Column('boolean') public storedInternal: boolean; diff --git a/packages/backend/src/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts index b72ca72331..7332dd1857 100644 --- a/packages/backend/src/models/entities/emoji.ts +++ b/packages/backend/src/models/entities/emoji.ts @@ -36,6 +36,7 @@ export class Emoji { @Column('varchar', { length: 512, + default: '', }) public publicUrl: string; diff --git a/packages/backend/src/models/entities/instance.ts b/packages/backend/src/models/entities/instance.ts index bb24d6b30f..7ea9234384 100644 --- a/packages/backend/src/models/entities/instance.ts +++ b/packages/backend/src/models/entities/instance.ts @@ -107,53 +107,53 @@ export class Instance { public isSuspended: boolean; @Column('varchar', { - length: 64, nullable: true, default: null, + length: 64, nullable: true, comment: 'The software of the Instance.', }) public softwareName: string | null; @Column('varchar', { - length: 64, nullable: true, default: null, + length: 64, nullable: true, }) public softwareVersion: string | null; @Column('boolean', { - nullable: true, default: null, + nullable: true, }) public openRegistrations: boolean | null; @Column('varchar', { - length: 256, nullable: true, default: null, + length: 256, nullable: true, }) public name: string | null; @Column('varchar', { - length: 4096, nullable: true, default: null, + length: 4096, nullable: true, }) public description: string | null; @Column('varchar', { - length: 128, nullable: true, default: null, + length: 128, nullable: true, }) public maintainerName: string | null; @Column('varchar', { - length: 256, nullable: true, default: null, + length: 256, nullable: true, }) public maintainerEmail: string | null; @Column('varchar', { - length: 256, nullable: true, default: null, + length: 256, nullable: true, }) public iconUrl: string | null; @Column('varchar', { - length: 256, nullable: true, default: null, + length: 256, nullable: true, }) public faviconUrl: string | null; @Column('varchar', { - length: 64, nullable: true, default: null, + length: 64, nullable: true, }) public themeColor: string | null; diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 4d58b5f04f..80b5228bcd 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -78,7 +78,7 @@ export class Meta { public blockedHosts: string[]; @Column('varchar', { - length: 512, array: true, default: '{"/featured", "/channels", "/explore", "/pages", "/about-misskey"}', + length: 512, array: true, default: '{/featured,/channels,/explore,/pages,/about-misskey}', }) public pinnedPages: string[]; @@ -346,14 +346,12 @@ export class Meta { @Column('varchar', { length: 8192, - default: null, nullable: true, }) public defaultLightTheme: string | null; @Column('varchar', { length: 8192, - default: null, nullable: true, }) public defaultDarkTheme: string | null; diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index b3a7e7a671..8f9e69063a 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -17,7 +17,6 @@ export class Muting { @Index() @Column('timestamp with time zone', { nullable: true, - default: null, }) public expiresAt: Date | null; diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index da49d53b69..0ffeb85f69 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -53,8 +53,8 @@ export class Note { }) public threadId: string | null; - @Column('varchar', { - length: 8192, nullable: true, + @Column('text', { + nullable: true, }) public text: string | null; @@ -179,7 +179,7 @@ export class Note { @Index() @Column({ ...id(), - nullable: true, default: null, + nullable: true, comment: 'The ID of source channel.', }) public channelId: Channel['id'] | null; diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts index f95cb144c5..1778742ea2 100644 --- a/packages/backend/src/models/entities/user-profile.ts +++ b/packages/backend/src/models/entities/user-profile.ts @@ -192,6 +192,7 @@ export class UserProfile { @Column('jsonb', { default: [], + comment: 'List of instances muted by the user.', }) public mutedInstances: string[]; diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index 29d9a0c2ca..df92fb8259 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -207,7 +207,7 @@ export class User { @Column('boolean', { default: false, - comment: 'Whether to show users replying to other users in the timeline', + comment: 'Whether to show users replying to other users in the timeline.', }) public showTimelineReplies: boolean; From a6c138600f46aacdb8d9aecb17c6821ff1ce784a Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 15:51:05 +0200 Subject: [PATCH 031/126] Refactor settings/sounds to use Composition API (#8594) * refactor(client): refactor settings/sounds to use Composition API * Apply review suggestion from @Johann150 Co-authored-by: Johann150 * chore(client): remove old sound reference Co-authored-by: Johann150 --- packages/client/src/pages/settings/sounds.vue | 166 ++++++++---------- 1 file changed, 76 insertions(+), 90 deletions(-) diff --git a/packages/client/src/pages/settings/sounds.vue b/packages/client/src/pages/settings/sounds.vue index 490a1b5514..d01e87c1f8 100644 --- a/packages/client/src/pages/settings/sounds.vue +++ b/packages/client/src/pages/settings/sounds.vue @@ -1,24 +1,24 @@ - From e5a8773bfeaf06a0085fbf8c44524637213acb94 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 15:51:29 +0200 Subject: [PATCH 032/126] refactor(client): refactor settings/deck to use Composition API (#8598) --- packages/client/src/pages/settings/deck.vue | 106 ++++++++------------ 1 file changed, 44 insertions(+), 62 deletions(-) diff --git a/packages/client/src/pages/settings/deck.vue b/packages/client/src/pages/settings/deck.vue index 46b90d3d1a..2d868aa0a7 100644 --- a/packages/client/src/pages/settings/deck.vue +++ b/packages/client/src/pages/settings/deck.vue @@ -1,36 +1,36 @@ - From f3628946af19ac84ce500dccdb04e58b36f85cea Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 15:51:58 +0200 Subject: [PATCH 033/126] refactor(client): refactor settings/word-mute to use Composition API (#8597) --- .../client/src/pages/settings/word-mute.vue | 192 ++++++++---------- 1 file changed, 84 insertions(+), 108 deletions(-) diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue index c11707b6cf..97a15da5b5 100644 --- a/packages/client/src/pages/settings/word-mute.vue +++ b/packages/client/src/pages/settings/word-mute.vue @@ -1,35 +1,35 @@ - From 3ea351d8a2f50f68dc695317062ba7f471ad7542 Mon Sep 17 00:00:00 2001 From: futchitwo <74236683+futchitwo@users.noreply.github.com> Date: Thu, 5 May 2022 22:52:33 +0900 Subject: [PATCH 034/126] Enhance(MFM): Allow speed changes in all animated MFMs (#8551) * MFM: Allow speed changes in all animated MFMs * Feature(MFM): Add speed property to cheat sheet * Use template literal Oops! * Remove unnecessary template string Co-authored-by: Johann150 Co-authored-by: Johann150 --- packages/client/src/components/mfm.ts | 12 ++++++++---- packages/client/src/pages/mfm-cheat-sheet.vue | 16 ++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index 37076652fd..6ac410762d 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -91,7 +91,8 @@ export default defineComponent({ let style; switch (token.props.name) { case 'tada': { - style = `font-size: 150%;` + (this.$store.state.animatedMfm ? 'animation: tada 1s linear infinite both;' : ''); + const speed = validTime(token.props.args.speed) || '1s'; + style = 'font-size: 150%;' + (this.$store.state.animatedMfm ? `animation: tada ${speed} linear infinite both;` : ''); break; } case 'jelly': { @@ -123,11 +124,13 @@ export default defineComponent({ break; } case 'jump': { - style = this.$store.state.animatedMfm ? 'animation: mfm-jump 0.75s linear infinite;' : ''; + const speed = validTime(token.props.args.speed) || '0.75s'; + style = this.$store.state.animatedMfm ? `animation: mfm-jump ${speed} linear infinite;` : ''; break; } case 'bounce': { - style = this.$store.state.animatedMfm ? 'animation: mfm-bounce 0.75s linear infinite; transform-origin: center bottom;' : ''; + const speed = validTime(token.props.args.speed) || '0.75s'; + style = this.$store.state.animatedMfm ? `animation: mfm-bounce ${speed} linear infinite; transform-origin: center bottom;` : ''; break; } case 'flip': { @@ -168,7 +171,8 @@ export default defineComponent({ }, genEl(token.children)); } case 'rainbow': { - style = this.$store.state.animatedMfm ? 'animation: mfm-rainbow 1s linear infinite;' : ''; + const speed = validTime(token.props.args.speed) || '1s'; + style = this.$store.state.animatedMfm ? `animation: mfm-rainbow ${speed} linear infinite;` : ''; break; } case 'sparkle': { diff --git a/packages/client/src/pages/mfm-cheat-sheet.vue b/packages/client/src/pages/mfm-cheat-sheet.vue index 83ae5741c3..aa35ec2158 100644 --- a/packages/client/src/pages/mfm-cheat-sheet.vue +++ b/packages/client/src/pages/mfm-cheat-sheet.vue @@ -325,20 +325,20 @@ export default defineComponent({ preview_inlineMath: '\\(x= \\frac{-b\' \\pm \\sqrt{(b\')^2-ac}}{a}\\)', preview_quote: `> ${this.$ts._mfm.dummy}`, preview_search: `${this.$ts._mfm.dummy} 検索`, - preview_jelly: `$[jelly 🍮]`, - preview_tada: `$[tada 🍮]`, - preview_jump: `$[jump 🍮]`, - preview_bounce: `$[bounce 🍮]`, - preview_shake: `$[shake 🍮]`, - preview_twitch: `$[twitch 🍮]`, - preview_spin: `$[spin 🍮] $[spin.left 🍮] $[spin.alternate 🍮]\n$[spin.x 🍮] $[spin.x,left 🍮] $[spin.x,alternate 🍮]\n$[spin.y 🍮] $[spin.y,left 🍮] $[spin.y,alternate 🍮]`, + preview_jelly: `$[jelly 🍮] $[jelly.speed=5s 🍮]`, + preview_tada: `$[tada 🍮] $[tada.speed=5s 🍮]`, + preview_jump: `$[jump 🍮] $[jump.speed=5s 🍮]`, + preview_bounce: `$[bounce 🍮] $[bounce.speed=5s 🍮]`, + preview_shake: `$[shake 🍮] $[shake.speed=5s 🍮]`, + preview_twitch: `$[twitch 🍮] $[twitch.speed=5s 🍮]`, + preview_spin: `$[spin 🍮] $[spin.left 🍮] $[spin.alternate 🍮]\n$[spin.x 🍮] $[spin.x,left 🍮] $[spin.x,alternate 🍮]\n$[spin.y 🍮] $[spin.y,left 🍮] $[spin.y,alternate 🍮]\n\n$[spin.speed=5s 🍮]`, preview_flip: `$[flip ${this.$ts._mfm.dummy}]\n$[flip.v ${this.$ts._mfm.dummy}]\n$[flip.h,v ${this.$ts._mfm.dummy}]`, preview_font: `$[font.serif ${this.$ts._mfm.dummy}]\n$[font.monospace ${this.$ts._mfm.dummy}]\n$[font.cursive ${this.$ts._mfm.dummy}]\n$[font.fantasy ${this.$ts._mfm.dummy}]`, preview_x2: `$[x2 🍮]`, preview_x3: `$[x3 🍮]`, preview_x4: `$[x4 🍮]`, preview_blur: `$[blur ${this.$ts._mfm.dummy}]`, - preview_rainbow: `$[rainbow 🍮]`, + preview_rainbow: `$[rainbow 🍮] $[rainbow.speed=5s 🍮]`, preview_sparkle: `$[sparkle 🍮]`, preview_rotate: `$[rotate 🍮]`, } From ad860905c6043c4dfabed8b2c43029cb215a1741 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 5 May 2022 15:53:08 +0200 Subject: [PATCH 035/126] refactor(client): refactor settings/theme/manage to use Composition API (#8596) --- .../src/pages/settings/theme.manage.vue | 95 ++++++++----------- 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/packages/client/src/pages/settings/theme.manage.vue b/packages/client/src/pages/settings/theme.manage.vue index 2eb16bb701..7da439f9c0 100644 --- a/packages/client/src/pages/settings/theme.manage.vue +++ b/packages/client/src/pages/settings/theme.manage.vue @@ -1,32 +1,32 @@ - From a975a0971cb0aa3b684204f910fba8b714c0f5fb Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Sat, 7 May 2022 07:19:15 +0200 Subject: [PATCH 036/126] fix(client): fix lint issues in scripts (#8621) --- packages/client/src/scripts/2fa.ts | 8 ++--- packages/client/src/scripts/autocomplete.ts | 22 ++++++------ packages/client/src/scripts/contains.ts | 2 +- .../extract-avg-color-from-blurhash.ts | 2 +- .../client/src/scripts/get-account-from-id.ts | 2 +- packages/client/src/scripts/get-md5.ts | 10 ------ packages/client/src/scripts/get-note-menu.ts | 14 ++++---- .../client/src/scripts/get-note-summary.ts | 2 +- packages/client/src/scripts/get-user-menu.ts | 6 ++-- packages/client/src/scripts/hotkey.ts | 24 ++++++------- packages/client/src/scripts/hpml/evaluator.ts | 8 ++--- packages/client/src/scripts/idb-proxy.ts | 4 +-- packages/client/src/scripts/lookup-user.ts | 6 ++-- packages/client/src/scripts/select-file.ts | 10 +++--- packages/client/src/scripts/upload.ts | 34 +++++++++---------- packages/client/src/scripts/url.ts | 2 +- .../client/src/scripts/use-note-capture.ts | 4 +-- 17 files changed, 75 insertions(+), 85 deletions(-) delete mode 100644 packages/client/src/scripts/get-md5.ts diff --git a/packages/client/src/scripts/2fa.ts b/packages/client/src/scripts/2fa.ts index 00363cffa6..d1b9581e72 100644 --- a/packages/client/src/scripts/2fa.ts +++ b/packages/client/src/scripts/2fa.ts @@ -1,11 +1,11 @@ -export function byteify(data: string, encoding: 'ascii' | 'base64' | 'hex') { +export function byteify(string: string, encoding: 'ascii' | 'base64' | 'hex') { switch (encoding) { case 'ascii': - return Uint8Array.from(data, c => c.charCodeAt(0)); + return Uint8Array.from(string, c => c.charCodeAt(0)); case 'base64': return Uint8Array.from( atob( - data + string .replace(/-/g, '+') .replace(/_/g, '/') ), @@ -13,7 +13,7 @@ export function byteify(data: string, encoding: 'ascii' | 'base64' | 'hex') { ); case 'hex': return new Uint8Array( - data + string .match(/.{1,2}/g) .map(byte => parseInt(byte, 16)) ); diff --git a/packages/client/src/scripts/autocomplete.ts b/packages/client/src/scripts/autocomplete.ts index bf60e5805a..8d9bdee8f5 100644 --- a/packages/client/src/scripts/autocomplete.ts +++ b/packages/client/src/scripts/autocomplete.ts @@ -74,21 +74,21 @@ export class Autocomplete { emojiIndex, mfmTagIndex); - if (max == -1) { + if (max === -1) { this.close(); return; } - const isMention = mentionIndex != -1; - const isHashtag = hashtagIndex != -1; - const isMfmTag = mfmTagIndex != -1; - const isEmoji = emojiIndex != -1 && text.split(/:[a-z0-9_+\-]+:/).pop()!.includes(':'); + const isMention = mentionIndex !== -1; + const isHashtag = hashtagIndex !== -1; + const isMfmTag = mfmTagIndex !== -1; + const isEmoji = emojiIndex !== -1 && text.split(/:[a-z0-9_+\-]+:/).pop()!.includes(':'); let opened = false; if (isMention) { const username = text.substr(mentionIndex + 1); - if (username != '' && username.match(/^[a-zA-Z0-9_]+$/)) { + if (username !== '' && username.match(/^[a-zA-Z0-9_]+$/)) { this.open('user', username); opened = true; } else if (username === '') { @@ -130,7 +130,7 @@ export class Autocomplete { * サジェストを提示します。 */ private async open(type: string, q: string | null) { - if (type != this.currentType) { + if (type !== this.currentType) { this.close(); } if (this.opening) return; @@ -201,7 +201,7 @@ export class Autocomplete { const caret = this.textarea.selectionStart; - if (type == 'user') { + if (type === 'user') { const source = this.text; const before = source.substr(0, caret); @@ -219,7 +219,7 @@ export class Autocomplete { const pos = trimmedBefore.length + (acct.length + 2); this.textarea.setSelectionRange(pos, pos); }); - } else if (type == 'hashtag') { + } else if (type === 'hashtag') { const source = this.text; const before = source.substr(0, caret); @@ -235,7 +235,7 @@ export class Autocomplete { const pos = trimmedBefore.length + (value.length + 2); this.textarea.setSelectionRange(pos, pos); }); - } else if (type == 'emoji') { + } else if (type === 'emoji') { const source = this.text; const before = source.substr(0, caret); @@ -251,7 +251,7 @@ export class Autocomplete { const pos = trimmedBefore.length + value.length; this.textarea.setSelectionRange(pos, pos); }); - } else if (type == 'mfmTag') { + } else if (type === 'mfmTag') { const source = this.text; const before = source.substr(0, caret); diff --git a/packages/client/src/scripts/contains.ts b/packages/client/src/scripts/contains.ts index 770bda63bb..256e09d293 100644 --- a/packages/client/src/scripts/contains.ts +++ b/packages/client/src/scripts/contains.ts @@ -2,7 +2,7 @@ export default (parent, child, checkSame = true) => { if (checkSame && parent === child) return true; let node = child.parentNode; while (node) { - if (node == parent) return true; + if (node === parent) return true; node = node.parentNode; } return false; diff --git a/packages/client/src/scripts/extract-avg-color-from-blurhash.ts b/packages/client/src/scripts/extract-avg-color-from-blurhash.ts index 123ab7a06d..af517f2672 100644 --- a/packages/client/src/scripts/extract-avg-color-from-blurhash.ts +++ b/packages/client/src/scripts/extract-avg-color-from-blurhash.ts @@ -1,5 +1,5 @@ export function extractAvgColorFromBlurhash(hash: string) { - return typeof hash == 'string' + return typeof hash === 'string' ? '#' + [...hash.slice(2, 6)] .map(x => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~'.indexOf(x)) .reduce((a, c) => a * 83 + c, 0) diff --git a/packages/client/src/scripts/get-account-from-id.ts b/packages/client/src/scripts/get-account-from-id.ts index ba3adceecc..1da897f176 100644 --- a/packages/client/src/scripts/get-account-from-id.ts +++ b/packages/client/src/scripts/get-account-from-id.ts @@ -3,5 +3,5 @@ import { get } from '@/scripts/idb-proxy'; export async function getAccountFromId(id: string) { const accounts = await get('accounts') as { token: string; id: string; }[]; if (!accounts) console.log('Accounts are not recorded'); - return accounts.find(e => e.id === id); + return accounts.find(account => account.id === id); } diff --git a/packages/client/src/scripts/get-md5.ts b/packages/client/src/scripts/get-md5.ts deleted file mode 100644 index b002d762b1..0000000000 --- a/packages/client/src/scripts/get-md5.ts +++ /dev/null @@ -1,10 +0,0 @@ -// スクリプトサイズがデカい -//import * as crypto from 'crypto'; - -export default (data: ArrayBuffer) => { - //const buf = new Buffer(data); - //const hash = crypto.createHash('md5'); - //hash.update(buf); - //return hash.digest('hex'); - return ''; -}; diff --git a/packages/client/src/scripts/get-note-menu.ts b/packages/client/src/scripts/get-note-menu.ts index a50001b24e..aeb09ef97a 100644 --- a/packages/client/src/scripts/get-note-menu.ts +++ b/packages/client/src/scripts/get-note-menu.ts @@ -83,8 +83,8 @@ export function getNoteMenu(props: { function togglePin(pin: boolean): void { os.apiWithDialog(pin ? 'i/pin' : 'i/unpin', { noteId: appearNote.id - }, undefined, null, e => { - if (e.id === '72dab508-c64d-498f-8740-a8eec1ba385a') { + }, undefined, null, res => { + if (res.id === '72dab508-c64d-498f-8740-a8eec1ba385a') { os.alert({ type: 'error', text: i18n.ts.pinLimitExceeded @@ -209,7 +209,7 @@ export function getNoteMenu(props: { text: i18n.ts.clip, action: () => clip() }, - (appearNote.userId != $i.id) ? statePromise.then(state => state.isWatching ? { + (appearNote.userId !== $i.id) ? statePromise.then(state => state.isWatching ? { icon: 'fas fa-eye-slash', text: i18n.ts.unwatch, action: () => toggleWatch(false) @@ -227,7 +227,7 @@ export function getNoteMenu(props: { text: i18n.ts.muteThread, action: () => toggleThreadMute(true) }), - appearNote.userId == $i.id ? ($i.pinnedNoteIds || []).includes(appearNote.id) ? { + appearNote.userId === $i.id ? ($i.pinnedNoteIds || []).includes(appearNote.id) ? { icon: 'fas fa-thumbtack', text: i18n.ts.unpin, action: () => togglePin(false) @@ -246,7 +246,7 @@ export function getNoteMenu(props: { }] : [] ),*/ - ...(appearNote.userId != $i.id ? [ + ...(appearNote.userId !== $i.id ? [ null, { icon: 'fas fa-exclamation-circle', @@ -261,9 +261,9 @@ export function getNoteMenu(props: { }] : [] ), - ...(appearNote.userId == $i.id || $i.isModerator || $i.isAdmin ? [ + ...(appearNote.userId === $i.id || $i.isModerator || $i.isAdmin ? [ null, - appearNote.userId == $i.id ? { + appearNote.userId === $i.id ? { icon: 'fas fa-edit', text: i18n.ts.deleteAndEdit, action: delEdit diff --git a/packages/client/src/scripts/get-note-summary.ts b/packages/client/src/scripts/get-note-summary.ts index 54b8d109d6..d57e1c3029 100644 --- a/packages/client/src/scripts/get-note-summary.ts +++ b/packages/client/src/scripts/get-note-summary.ts @@ -24,7 +24,7 @@ export const getNoteSummary = (note: misskey.entities.Note): string => { } // ファイルが添付されているとき - if ((note.files || []).length != 0) { + if ((note.files || []).length !== 0) { summary += ` (${i18n.t('withNFiles', { n: note.files.length })})`; } diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index b9e4066e42..1d2b761117 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -169,7 +169,7 @@ export function getUserMenu(user) { action: () => { os.post({ specified: user }); } - }, meId != user.id ? { + }, meId !== user.id ? { type: 'link', icon: 'fas fa-comments', text: i18n.ts.startMessaging, @@ -178,13 +178,13 @@ export function getUserMenu(user) { icon: 'fas fa-list-ul', text: i18n.ts.addToList, action: pushList - }, meId != user.id ? { + }, meId !== user.id ? { icon: 'fas fa-users', text: i18n.ts.inviteToGroup, action: inviteGroup } : undefined] as any; - if ($i && meId != user.id) { + if ($i && meId !== user.id) { menu = menu.concat([null, { icon: user.isMuted ? 'fas fa-eye' : 'fas fa-eye-slash', text: user.isMuted ? i18n.ts.unmute : i18n.ts.mute, diff --git a/packages/client/src/scripts/hotkey.ts b/packages/client/src/scripts/hotkey.ts index 2b3f491fd8..fd9c74f6c8 100644 --- a/packages/client/src/scripts/hotkey.ts +++ b/packages/client/src/scripts/hotkey.ts @@ -53,34 +53,34 @@ const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([patterns, c const ignoreElemens = ['input', 'textarea']; -function match(e: KeyboardEvent, patterns: Action['patterns']): boolean { - const key = e.code.toLowerCase(); +function match(ev: KeyboardEvent, patterns: Action['patterns']): boolean { + const key = ev.code.toLowerCase(); return patterns.some(pattern => pattern.which.includes(key) && - pattern.ctrl === e.ctrlKey && - pattern.shift === e.shiftKey && - pattern.alt === e.altKey && - !e.metaKey + pattern.ctrl === ev.ctrlKey && + pattern.shift === ev.shiftKey && + pattern.alt === ev.altKey && + !ev.metaKey ); } export const makeHotkey = (keymap: Keymap) => { const actions = parseKeymap(keymap); - return (e: KeyboardEvent) => { + return (ev: KeyboardEvent) => { if (document.activeElement) { if (ignoreElemens.some(el => document.activeElement!.matches(el))) return; if (document.activeElement.attributes['contenteditable']) return; } for (const action of actions) { - const matched = match(e, action.patterns); + const matched = match(ev, action.patterns); if (matched) { - if (!action.allowRepeat && e.repeat) return; + if (!action.allowRepeat && ev.repeat) return; - e.preventDefault(); - e.stopPropagation(); - action.callback(e); + ev.preventDefault(); + ev.stopPropagation(); + action.callback(ev); break; } } diff --git a/packages/client/src/scripts/hpml/evaluator.ts b/packages/client/src/scripts/hpml/evaluator.ts index 6329c0860e..0469a31cbb 100644 --- a/packages/client/src/scripts/hpml/evaluator.ts +++ b/packages/client/src/scripts/hpml/evaluator.ts @@ -85,7 +85,7 @@ export class Hpml { public eval() { try { this.vars.value = this.evaluateVars(); - } catch (e) { + } catch (err) { //this.onError(e); } } @@ -103,7 +103,7 @@ export class Hpml { public callAiScript(fn: string) { try { if (this.aiscript) this.aiscript.execFn(this.aiscript.scope.get(fn), []); - } catch (e) {} + } catch (err) {} } @autobind @@ -185,7 +185,7 @@ export class Hpml { if (this.aiscript) { try { return utils.valToJs(this.aiscript.scope.get(expr.value)); - } catch (e) { + } catch (err) { return null; } } else { @@ -194,7 +194,7 @@ export class Hpml { } // Define user function - if (expr.type == 'fn') { + if (expr.type === 'fn') { return { slots: expr.value.slots.map(x => x.name), exec: (slotArg: Record) => { diff --git a/packages/client/src/scripts/idb-proxy.ts b/packages/client/src/scripts/idb-proxy.ts index 5f76ae30bb..d462a0d7ce 100644 --- a/packages/client/src/scripts/idb-proxy.ts +++ b/packages/client/src/scripts/idb-proxy.ts @@ -13,8 +13,8 @@ let idbAvailable = typeof window !== 'undefined' ? !!window.indexedDB : true; if (idbAvailable) { try { await iset('idb-test', 'test'); - } catch (e) { - console.error('idb error', e); + } catch (err) { + console.error('idb error', err); idbAvailable = false; } } diff --git a/packages/client/src/scripts/lookup-user.ts b/packages/client/src/scripts/lookup-user.ts index 8de5c84ce8..2d00e51621 100644 --- a/packages/client/src/scripts/lookup-user.ts +++ b/packages/client/src/scripts/lookup-user.ts @@ -25,12 +25,12 @@ export async function lookupUser() { _notFound = true; } }; - usernamePromise.then(show).catch(e => { - if (e.code === 'NO_SUCH_USER') { + usernamePromise.then(show).catch(err => { + if (err.code === 'NO_SUCH_USER') { notFound(); } }); - idPromise.then(show).catch(e => { + idPromise.then(show).catch(err => { notFound(); }); } diff --git a/packages/client/src/scripts/select-file.ts b/packages/client/src/scripts/select-file.ts index 49a46f0bb2..461d613b42 100644 --- a/packages/client/src/scripts/select-file.ts +++ b/packages/client/src/scripts/select-file.ts @@ -19,10 +19,10 @@ function select(src: any, label: string | null, multiple: boolean): Promise { res(multiple ? driveFiles : driveFiles[0]); - }).catch(e => { + }).catch(err => { os.alert({ type: 'error', - text: e + text: err }); }); @@ -54,9 +54,9 @@ function select(src: any, label: string | null, multiple: boolean): Promise { - if (data.marker === marker) { - res(multiple ? [data.file] : data.file); + connection.on('urlUploadFinished', urlResponse => { + if (urlResponse.marker === marker) { + res(multiple ? [urlResponse.file] : urlResponse.file); connection.dispose(); } }); diff --git a/packages/client/src/scripts/upload.ts b/packages/client/src/scripts/upload.ts index 7e4f793b44..2f7b30b58d 100644 --- a/packages/client/src/scripts/upload.ts +++ b/packages/client/src/scripts/upload.ts @@ -33,13 +33,13 @@ export function uploadFile( name?: string, keepOriginal: boolean = defaultStore.state.keepOriginalUploading ): Promise { - if (folder && typeof folder == 'object') folder = folder.id; + if (folder && typeof folder === 'object') folder = folder.id; return new Promise((resolve, reject) => { const id = Math.random().toString(); const reader = new FileReader(); - reader.onload = async (e) => { + reader.onload = async (ev) => { const ctx = reactive({ id: id, name: name || file.name || 'untitled', @@ -64,24 +64,24 @@ export function uploadFile( try { resizedImage = await readAndCompressImage(file, config); ctx.name = file.type !== imgConfig.mimeType ? `${ctx.name}.${mimeTypeMap[compressTypeMap[file.type].mimeType]}` : ctx.name; - } catch (e) { - console.error('Failed to resize image', e); + } catch (err) { + console.error('Failed to resize image', err); } } - const data = new FormData(); - data.append('i', $i.token); - data.append('force', 'true'); - data.append('file', resizedImage || file); - data.append('name', ctx.name); - if (folder) data.append('folderId', folder); + const formData = new FormData(); + formData.append('i', $i.token); + formData.append('force', 'true'); + formData.append('file', resizedImage || file); + formData.append('name', ctx.name); + if (folder) formData.append('folderId', folder); const xhr = new XMLHttpRequest(); xhr.open('POST', apiUrl + '/drive/files/create', true); xhr.onload = (ev) => { if (xhr.status !== 200 || ev.target == null || ev.target.response == null) { // TODO: 消すのではなくて再送できるようにしたい - uploads.value = uploads.value.filter(x => x.id != id); + uploads.value = uploads.value.filter(x => x.id !== id); alert({ type: 'error', @@ -97,17 +97,17 @@ export function uploadFile( resolve(driveFile); - uploads.value = uploads.value.filter(x => x.id != id); + uploads.value = uploads.value.filter(x => x.id !== id); }; - xhr.upload.onprogress = e => { - if (e.lengthComputable) { - ctx.progressMax = e.total; - ctx.progressValue = e.loaded; + xhr.upload.onprogress = ev => { + if (ev.lengthComputable) { + ctx.progressMax = ev.total; + ctx.progressValue = ev.loaded; } }; - xhr.send(data); + xhr.send(formData); }; reader.readAsArrayBuffer(file); }); diff --git a/packages/client/src/scripts/url.ts b/packages/client/src/scripts/url.ts index c7f2b7c1e7..542b00e0f0 100644 --- a/packages/client/src/scripts/url.ts +++ b/packages/client/src/scripts/url.ts @@ -4,7 +4,7 @@ export function query(obj: {}): string { .reduce((a, [k, v]) => (a[k] = v, a), {} as Record); return Object.entries(params) - .map((e) => `${e[0]}=${encodeURIComponent(e[1])}`) + .map((p) => `${p[0]}=${encodeURIComponent(p[1])}`) .join('&'); } diff --git a/packages/client/src/scripts/use-note-capture.ts b/packages/client/src/scripts/use-note-capture.ts index b2a96062c7..f1f976693e 100644 --- a/packages/client/src/scripts/use-note-capture.ts +++ b/packages/client/src/scripts/use-note-capture.ts @@ -11,8 +11,8 @@ export function useNoteCapture(props: { const note = props.note; const connection = $i ? stream : null; - function onStreamNoteUpdated(data): void { - const { type, id, body } = data; + function onStreamNoteUpdated(noteData): void { + const { type, id, body } = noteData; if (id !== note.value.id) return; From 7bd45e57290ad1fad2343041e03fde0c70a6b752 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Sat, 7 May 2022 10:00:05 +0200 Subject: [PATCH 037/126] Fix lint issues in emoji picker components (#8620) * fix(client): fix lint issues in emoji picker components * fix(client): switch argument naming for emoji picker section event --- .../client/src/components/emoji-picker-window.vue | 4 ++-- .../client/src/components/emoji-picker.section.vue | 2 +- packages/client/src/components/emoji-picker.vue | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/client/src/components/emoji-picker-window.vue b/packages/client/src/components/emoji-picker-window.vue index 4d27fb48ba..610690d701 100644 --- a/packages/client/src/components/emoji-picker-window.vue +++ b/packages/client/src/components/emoji-picker-window.vue @@ -25,8 +25,8 @@ withDefaults(defineProps<{ }); const emit = defineEmits<{ - (e: 'chosen', v: any): void; - (e: 'closed'): void; + (ev: 'chosen', v: any): void; + (ev: 'closed'): void; }>(); function chosen(emoji: any) { diff --git a/packages/client/src/components/emoji-picker.section.vue b/packages/client/src/components/emoji-picker.section.vue index 1026e894d1..52f7047487 100644 --- a/packages/client/src/components/emoji-picker.section.vue +++ b/packages/client/src/components/emoji-picker.section.vue @@ -24,7 +24,7 @@ const props = defineProps<{ }>(); const emit = defineEmits<{ - (e: 'chosen', v: string, ev: MouseEvent): void; + (ev: 'chosen', v: string, event: MouseEvent): void; }>(); const shown = ref(!!props.initialShown); diff --git a/packages/client/src/components/emoji-picker.vue b/packages/client/src/components/emoji-picker.vue index ae74f04c02..522f636474 100644 --- a/packages/client/src/components/emoji-picker.vue +++ b/packages/client/src/components/emoji-picker.vue @@ -97,7 +97,7 @@ const props = withDefaults(defineProps<{ }); const emit = defineEmits<{ - (e: 'chosen', v: string): void; + (ev: 'chosen', v: string): void; }>(); const search = ref(); @@ -138,7 +138,7 @@ watch(q, () => { const emojis = customEmojis; const matches = new Set(); - const exactMatch = emojis.find(e => e.name === newQ); + const exactMatch = emojis.find(emoji => emoji.name === newQ); if (exactMatch) matches.add(exactMatch); if (newQ.includes(' ')) { // AND検索 @@ -201,7 +201,7 @@ watch(q, () => { const emojis = emojilist; const matches = new Set(); - const exactMatch = emojis.find(e => e.name === newQ); + const exactMatch = emojis.find(emoji => emoji.name === newQ); if (exactMatch) matches.add(exactMatch); if (newQ.includes(' ')) { // AND検索 @@ -295,7 +295,7 @@ function chosen(emoji: any, ev?: MouseEvent) { // 最近使った絵文字更新 if (!pinned.value.includes(key)) { let recents = defaultStore.state.recentlyUsedEmojis; - recents = recents.filter((e: any) => e !== key); + recents = recents.filter((emoji: any) => emoji !== key); recents.unshift(key); defaultStore.set('recentlyUsedEmojis', recents.splice(0, 32)); } @@ -313,12 +313,12 @@ function done(query?: any): boolean | void { if (query == null || typeof query !== 'string') return; const q2 = query.replace(/:/g, ''); - const exactMatchCustom = customEmojis.find(e => e.name === q2); + const exactMatchCustom = customEmojis.find(emoji => emoji.name === q2); if (exactMatchCustom) { chosen(exactMatchCustom); return true; } - const exactMatchUnicode = emojilist.find(e => e.char === q2 || e.name === q2); + const exactMatchUnicode = emojilist.find(emoji => emoji.char === q2 || emoji.name === q2); if (exactMatchUnicode) { chosen(exactMatchUnicode); return true; From a29ff7b1fa45e01bc7c097e8d770a4c4eedf2a8f Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Sat, 7 May 2022 10:01:01 +0200 Subject: [PATCH 038/126] Fix lint issues in post form component (#8619) * fix(client): fix lint issues in post form * Apply review suggestions from @Johann150 Co-authored-by: Johann150 Co-authored-by: Johann150 --- packages/client/src/components/post-form.vue | 97 ++++++++++---------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/packages/client/src/components/post-form.vue b/packages/client/src/components/post-form.vue index 6d79736003..488c55231f 100644 --- a/packages/client/src/components/post-form.vue +++ b/packages/client/src/components/post-form.vue @@ -228,7 +228,7 @@ if (props.mention) { text += ' '; } -if (props.reply && (props.reply.user.username != $i.username || (props.reply.user.host != null && props.reply.user.host != host))) { +if (props.reply && (props.reply.user.username !== $i.username || (props.reply.user.host != null && props.reply.user.host !== host))) { text = `@${props.reply.user.username}${props.reply.user.host != null ? '@' + toASCII(props.reply.user.host) : ''} `; } @@ -239,16 +239,15 @@ if (props.reply && props.reply.text != null) { for (const x of extractMentions(ast)) { const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : - (otherHost == null || otherHost == host) ? + (otherHost == null || otherHost === host) ? `@${x.username}` : `@${x.username}@${toASCII(otherHost)}`; // 自分は除外 - if ($i.username == x.username && x.host == null) continue; - if ($i.username == x.username && x.host == host) continue; + if ($i.username === x.username && (x.host == null || x.host === host)) continue; // 重複は除外 - if (text.indexOf(`${mention} `) != -1) continue; + if (text.includes(`${mention} `)) continue; text += `${mention} `; } @@ -303,7 +302,7 @@ function checkMissingMention() { const ast = mfm.parse(text); for (const x of extractMentions(ast)) { - if (!visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) { + if (!visibleUsers.some(u => (u.username === x.username) && (u.host === x.host))) { hasNotSpecifiedMentions = true; return; } @@ -316,7 +315,7 @@ function addMissingMention() { const ast = mfm.parse(text); for (const x of extractMentions(ast)) { - if (!visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) { + if (!visibleUsers.some(u => (u.username === x.username) && (u.host === x.host))) { os.api('users/show', { username: x.username, host: x.host }).then(user => { visibleUsers.push(user); }); @@ -357,7 +356,7 @@ function chooseFileFrom(ev) { } function detachFile(id) { - files = files.filter(x => x.id != id); + files = files.filter(x => x.id !== id); } function updateFiles(_files) { @@ -427,24 +426,24 @@ function clear() { quoteId = null; } -function onKeydown(e: KeyboardEvent) { - if ((e.which === 10 || e.which === 13) && (e.ctrlKey || e.metaKey) && canPost) post(); - if (e.which === 27) emit('esc'); +function onKeydown(ev: KeyboardEvent) { + if ((ev.which === 10 || ev.which === 13) && (ev.ctrlKey || ev.metaKey) && canPost) post(); + if (ev.which === 27) emit('esc'); typing(); } -function onCompositionUpdate(e: CompositionEvent) { - imeText = e.data; +function onCompositionUpdate(ev: CompositionEvent) { + imeText = ev.data; typing(); } -function onCompositionEnd(e: CompositionEvent) { +function onCompositionEnd(ev: CompositionEvent) { imeText = ''; } -async function onPaste(e: ClipboardEvent) { - for (const { item, i } of Array.from(e.clipboardData.items).map((item, i) => ({item, i}))) { - if (item.kind == 'file') { +async function onPaste(ev: ClipboardEvent) { + for (const { item, i } of Array.from(ev.clipboardData.items).map((item, i) => ({item, i}))) { + if (item.kind === 'file') { const file = item.getAsFile(); const lio = file.name.lastIndexOf('.'); const ext = lio >= 0 ? file.name.slice(lio) : ''; @@ -453,10 +452,10 @@ async function onPaste(e: ClipboardEvent) { } } - const paste = e.clipboardData.getData('text'); + const paste = ev.clipboardData.getData('text'); if (!props.renote && !quoteId && paste.startsWith(url + '/notes/')) { - e.preventDefault(); + ev.preventDefault(); os.confirm({ type: 'info', @@ -472,49 +471,49 @@ async function onPaste(e: ClipboardEvent) { } } -function onDragover(e) { - if (!e.dataTransfer.items[0]) return; - const isFile = e.dataTransfer.items[0].kind == 'file'; - const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_; +function onDragover(ev) { + if (!ev.dataTransfer.items[0]) return; + const isFile = ev.dataTransfer.items[0].kind === 'file'; + const isDriveFile = ev.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_; if (isFile || isDriveFile) { - e.preventDefault(); + ev.preventDefault(); draghover = true; - e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + ev.dataTransfer.dropEffect = ev.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move'; } } -function onDragenter(e) { +function onDragenter(ev) { draghover = true; } -function onDragleave(e) { +function onDragleave(ev) { draghover = false; } -function onDrop(e): void { +function onDrop(ev): void { draghover = false; // ファイルだったら - if (e.dataTransfer.files.length > 0) { - e.preventDefault(); - for (const x of Array.from(e.dataTransfer.files)) upload(x); + if (ev.dataTransfer.files.length > 0) { + ev.preventDefault(); + for (const x of Array.from(ev.dataTransfer.files)) upload(x); return; } //#region ドライブのファイル - const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); - if (driveFile != null && driveFile != '') { + const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_); + if (driveFile != null && driveFile !== '') { const file = JSON.parse(driveFile); files.push(file); - e.preventDefault(); + ev.preventDefault(); } //#endregion } function saveDraft() { - const data = JSON.parse(localStorage.getItem('drafts') || '{}'); + const draftData = JSON.parse(localStorage.getItem('drafts') || '{}'); - data[draftKey] = { + draftData[draftKey] = { updatedAt: new Date(), data: { text: text, @@ -527,20 +526,20 @@ function saveDraft() { } }; - localStorage.setItem('drafts', JSON.stringify(data)); + localStorage.setItem('drafts', JSON.stringify(draftData)); } function deleteDraft() { - const data = JSON.parse(localStorage.getItem('drafts') || '{}'); + const draftData = JSON.parse(localStorage.getItem('drafts') || '{}'); - delete data[draftKey]; + delete draftData[draftKey]; - localStorage.setItem('drafts', JSON.stringify(data)); + localStorage.setItem('drafts', JSON.stringify(draftData)); } async function post() { - let data = { - text: text == '' ? undefined : text, + let postData = { + text: text === '' ? undefined : text, fileIds: files.length > 0 ? files.map(f => f.id) : undefined, replyId: props.reply ? props.reply.id : undefined, renoteId: props.renote ? props.renote.id : quoteId ? quoteId : undefined, @@ -549,18 +548,18 @@ async function post() { cw: useCw ? cw || '' : undefined, localOnly: localOnly, visibility: visibility, - visibleUserIds: visibility == 'specified' ? visibleUsers.map(u => u.id) : undefined, + visibleUserIds: visibility === 'specified' ? visibleUsers.map(u => u.id) : undefined, }; if (withHashtags && hashtags && hashtags.trim() !== '') { const hashtags_ = hashtags.trim().split(' ').map(x => x.startsWith('#') ? x : '#' + x).join(' '); - data.text = data.text ? `${data.text} ${hashtags_}` : hashtags_; + postData.text = postData.text ? `${postData.text} ${hashtags_}` : hashtags_; } // plugin if (notePostInterruptors.length > 0) { for (const interruptor of notePostInterruptors) { - data = await interruptor.handler(JSON.parse(JSON.stringify(data))); + postData = await interruptor.handler(JSON.parse(JSON.stringify(postData))); } } @@ -572,13 +571,13 @@ async function post() { } posting = true; - os.api('notes/create', data, token).then(() => { + os.api('notes/create', postData, token).then(() => { clear(); nextTick(() => { deleteDraft(); emit('posted'); - if (data.text && data.text != '') { - const hashtags_ = mfm.parse(data.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag); + if (postData.text && postData.text !== '') { + const hashtags_ = mfm.parse(postData.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag); const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; localStorage.setItem('hashtags', JSON.stringify(unique(hashtags_.concat(history)))); } @@ -662,7 +661,7 @@ onMounted(() => { cw = draft.data.cw; visibility = draft.data.visibility; localOnly = draft.data.localOnly; - files = (draft.data.files || []).filter(e => e); + files = (draft.data.files || []).filter(draftFile => draftFile); if (draft.data.poll) { poll = draft.data.poll; } From 9fc5e8688f99545086e9226cf3179486efd9255e Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Thu, 12 May 2022 19:31:26 +0200 Subject: [PATCH 039/126] fix(client): add setup attribute to notification page (#8648) --- packages/client/src/pages/settings/notifications.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/pages/settings/notifications.vue b/packages/client/src/pages/settings/notifications.vue index 6fe2ac55a4..b8fff95a8d 100644 --- a/packages/client/src/pages/settings/notifications.vue +++ b/packages/client/src/pages/settings/notifications.vue @@ -9,7 +9,7 @@ -