From 7747ec5b6de17e8ce20e1cf59649e5e98aec9991 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 23 Jan 2021 20:05:44 +0900 Subject: [PATCH 0001/1102] Update ja-JP.yml --- locales/ja-JP.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fa215847d..992f6c842 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -678,7 +678,7 @@ onlineUsersCount: "{n}人がオンライン" nUsers: "{n}ユーザー" nNotes: "{n}ノート" sendErrorReports: "エラーリポートを送信" -sendErrorReportsDescription: "オンにすると、問題が発生したときにエラーの詳細情報がMisskeyに共有され、ソフトウェアの品質向上に役立てることができます。" +sendErrorReportsDescription: "オンにすると、問題が発生したときにエラーの詳細情報がMisskeyに共有され、ソフトウェアの品質向上に役立てることができます。エラー情報には、OSのバージョン、ブラウザの種類、行動履歴などが含まれます。" myTheme: "マイテーマ" backgroundColor: "背景" accentColor: "アクセント" From a1f346a54973dff2e464e24295e19d66bb439edd Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 27 Jan 2022 18:15:49 +0900 Subject: [PATCH 0002/1102] pages/messaging/messaging-room.vue --- packages/client/src/components/ui/window.vue | 4 - .../src/pages/messaging/messaging-room.vue | 492 ++++++++---------- 2 files changed, 220 insertions(+), 276 deletions(-) diff --git a/packages/client/src/components/ui/window.vue b/packages/client/src/components/ui/window.vue index fa32ecfde..3c6d44f44 100644 --- a/packages/client/src/components/ui/window.vue +++ b/packages/client/src/components/ui/window.vue @@ -62,10 +62,6 @@ function dragClear(fn) { } export default defineComponent({ - provide: { - inWindow: true - }, - props: { padding: { type: Boolean, diff --git a/packages/client/src/pages/messaging/messaging-room.vue b/packages/client/src/pages/messaging/messaging-room.vue index a715dad6d..fa6722b68 100644 --- a/packages/client/src/pages/messaging/messaging-room.vue +++ b/packages/client/src/pages/messaging/messaging-room.vue @@ -2,6 +2,7 @@
@@ -35,9 +36,10 @@
- From 5d37b7a2ba0b4f969dce155269f460bd2b5d6216 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter <44733677+ThatOneCalculator@users.noreply.github.com> Date: Wed, 2 Mar 2022 08:19:17 -0800 Subject: [PATCH 0202/1102] Add me as patron (#8369) --- packages/client/src/pages/about-misskey.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/pages/about-misskey.vue b/packages/client/src/pages/about-misskey.vue index 0ffb6b9e1..ff04ed84f 100644 --- a/packages/client/src/pages/about-misskey.vue +++ b/packages/client/src/pages/about-misskey.vue @@ -149,6 +149,7 @@ const patrons = [ 'oss', 'Weeble', '蝉暮せせせ', + 'ThatOneCalculator', ]; let easterEggReady = false; From 5c5be7f15e9411750f02393bbba37dde1c7c8d99 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 00:06:17 +0900 Subject: [PATCH 0203/1102] fix esm --- packages/backend/src/server/web/manifest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index c2f29d523..bcbf9b76a 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -1,5 +1,5 @@ import Koa from 'koa'; -import * as manifest from './manifest.json' assert { type: 'json' }; +import manifest from './manifest.json' assert { type: 'json' }; import { fetchMeta } from '@/misc/fetch-meta.js'; export const manifestHandler = async (ctx: Koa.Context) => { From b67f1287c6d96757161dece7a4045ad3070f9d98 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 15:32:50 +0900 Subject: [PATCH 0204/1102] fix federation chart pubsub --- packages/backend/src/services/chart/charts/federation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/services/chart/charts/federation.ts b/packages/backend/src/services/chart/charts/federation.ts index 13aa6c584..4fbd297db 100644 --- a/packages/backend/src/services/chart/charts/federation.ts +++ b/packages/backend/src/services/chart/charts/federation.ts @@ -35,7 +35,7 @@ export default class FederationChart extends Chart { Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(`following.followerHost IN (${ pubsubSubQuery.getQuery() })`) + .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) .setParameters(pubsubSubQuery.getParameters()) .getRawOne() .then(x => parseInt(x.count, 10)), From 271854e345e5c653c3ec978131563bcbb11cead1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 16:26:10 +0900 Subject: [PATCH 0205/1102] enhance(chart): better federation pub/sub calculation --- .../src/services/chart/charts/federation.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/services/chart/charts/federation.ts b/packages/backend/src/services/chart/charts/federation.ts index 4fbd297db..97855a634 100644 --- a/packages/backend/src/services/chart/charts/federation.ts +++ b/packages/backend/src/services/chart/charts/federation.ts @@ -1,6 +1,7 @@ import Chart, { KVs } from '../core.js'; -import { Followings } from '@/models/index.js'; +import { Followings, Instances } from '@/models/index.js'; import { name, schema } from './entities/federation.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; /** * フェデレーションに関するチャート @@ -17,6 +18,12 @@ export default class FederationChart extends Chart { } protected async tickMinor(): Promise>> { + const meta = await fetchMeta(); + + const suspendedInstancesQuery = Instances.createQueryBuilder('instance') + .select('instance.host') + .where('instance.isSuspended = true'); + const pubsubSubQuery = Followings.createQueryBuilder('f') .select('f.followerHost') .where('f.followerHost IS NOT NULL'); @@ -25,16 +32,22 @@ export default class FederationChart extends Chart { Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') + .andWhere(`following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followerHost)') .where('following.followerHost IS NOT NULL') + .andWhere(`following.followerHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followerHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') + .andWhere(`following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) .setParameters(pubsubSubQuery.getParameters()) .getRawOne() From 5448ed643e67b10d19c234698886590f9c1ba9f1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 16:26:21 +0900 Subject: [PATCH 0206/1102] tweak client --- packages/client/src/components/chart.vue | 8 ++++---- packages/client/src/store.ts | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/client/src/components/chart.vue b/packages/client/src/components/chart.vue index 3787c5f06..dc1ea2b2d 100644 --- a/packages/client/src/components/chart.vue +++ b/packages/client/src/components/chart.vue @@ -274,7 +274,7 @@ export default defineComponent({ y: { position: 'left', stacked: props.stacked, - suggestedMax: 100, + suggestedMax: 50, grid: { color: gridColor, borderColor: 'rgb(0, 0, 0, 0)', @@ -390,17 +390,17 @@ export default defineComponent({ color: colors.red, }, { name: 'Pub & Sub', - type: 'area', + type: 'line', data: format(raw.pubsub), color: colors.lime, }, { name: 'Pub', - type: 'area', + type: 'line', data: format(raw.pub), color: colors.purple, }, { name: 'Sub', - type: 'area', + type: 'line', data: format(raw.sub), color: colors.orange, }], diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index e6a2f4290..b9800ec60 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -68,11 +68,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'deviceAccount', default: [ 'notifications', - 'messaging', + 'favorites', 'drive', 'followRequests', '-', - 'gallery', 'featured', 'explore', 'announcements', @@ -192,7 +191,7 @@ export const defaultStore = markRaw(new Storage('base', { }, reactionPickerHeight: { where: 'device', - default: 1 + default: 2 }, reactionPickerUseDrawerForMobile: { where: 'device', From 7f4551b769cfabb86ea715cfbf16ff1fa98b6aa7 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Fri, 4 Mar 2022 09:13:10 +0100 Subject: [PATCH 0207/1102] Fix: Only allow admins to access admin views (#8361) * fix(client): only allow admins to access /admin/* * fix(client): Also allow moderators to access admin panel --- packages/client/src/router.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/router.ts b/packages/client/src/router.ts index ec48b76fd..839841f0f 100644 --- a/packages/client/src/router.ts +++ b/packages/client/src/router.ts @@ -3,7 +3,7 @@ import { createRouter, createWebHistory } from 'vue-router'; import MkLoading from '@/pages/_loading_.vue'; import MkError from '@/pages/_error_.vue'; import MkTimeline from '@/pages/timeline.vue'; -import { $i } from './account'; +import { $i, iAmModerator } from './account'; import { ui } from '@/config'; const page = (path: string, ui?: string) => defineAsyncComponent({ @@ -67,8 +67,8 @@ const defaultRoutes = [ { path: '/my/antennas/:antennaId', component: page('my-antennas/edit'), props: true }, { path: '/my/clips', component: page('my-clips/index') }, { path: '/scratchpad', component: page('scratchpad') }, - { path: '/admin/:page(.*)?', component: page('admin/index'), props: route => ({ initialPage: route.params.page || null }) }, - { path: '/admin', component: page('admin/index') }, + { path: '/admin/:page(.*)?', component: iAmModerator ? page('admin/index') : page('not-found'), props: route => ({ initialPage: route.params.page || null }) }, + { path: '/admin', component: iAmModerator ? page('admin/index') : page('not-found') }, { path: '/notes/:note', name: 'note', component: page('note'), props: route => ({ noteId: route.params.note }) }, { path: '/tags/:tag', component: page('tag'), props: route => ({ tag: route.params.tag }) }, { path: '/user-info/:user', component: page('user-info'), props: route => ({ userId: route.params.user }) }, From 2939b760d346aa5cd4f59675a5ef2ee460b60b75 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 18:04:39 +0900 Subject: [PATCH 0208/1102] set timeout for db query Resolve #8150 --- CHANGELOG.md | 2 ++ packages/backend/src/db/postgre.ts | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fc812233..88adeca87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ You should also include the user name that made the change. - インスタンスデフォルトテーマを設定できるように @syuilo - プロフィールの追加情報を最大16まで保存できるように @syuilo - 連合チャートにPub&Subを追加 @syuilo +- デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo + - 設定ファイルの`db.extra`に`statement_timeout`を設定することでタイムアウト時間を変更できます ### Bugfixes - Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index c1f7245bc..066a3c673 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -184,7 +184,7 @@ export function initDb(justBorrow = false, sync = false, forceRecreate = false) } catch (e) {} } - const log = process.env.NODE_ENV != 'production'; + const log = process.env.NODE_ENV !== 'production'; return createConnection({ type: 'postgres', @@ -193,7 +193,10 @@ export function initDb(justBorrow = false, sync = false, forceRecreate = false) username: config.db.user, password: config.db.pass, database: config.db.db, - extra: config.db.extra, + extra: { + statement_timeout: 1000 * 10, + ...config.db.extra, + }, synchronize: process.env.NODE_ENV === 'test' || sync, dropSchema: process.env.NODE_ENV === 'test' && !justBorrow, cache: !config.db.disableCache ? { From 82f9d5501bc83e428e8d03ee63e733a170440067 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 18:18:37 +0900 Subject: [PATCH 0209/1102] fix query error --- packages/backend/src/services/chart/charts/federation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/services/chart/charts/federation.ts b/packages/backend/src/services/chart/charts/federation.ts index 97855a634..89670194d 100644 --- a/packages/backend/src/services/chart/charts/federation.ts +++ b/packages/backend/src/services/chart/charts/federation.ts @@ -32,21 +32,21 @@ export default class FederationChart extends Chart { Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(`following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followerHost)') .where('following.followerHost IS NOT NULL') - .andWhere(`following.followerHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followerHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) .andWhere(`following.followerHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') - .andWhere(`following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) .setParameters(pubsubSubQuery.getParameters()) From e68278f93e82ba396ea2b1fbe0c7e0231c640421 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 20:23:53 +0900 Subject: [PATCH 0210/1102] =?UTF-8?q?feat:=20=E6=99=82=E9=99=90=E3=83=9F?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #7677 --- CHANGELOG.md | 1 + locales/ja-JP.yml | 6 +++ .../1646387162108-mute-expires-at.js | 13 ++++++ .../backend/src/models/entities/muting.ts | 7 +++ .../backend/src/models/repositories/muting.ts | 1 + packages/backend/src/models/schema/muting.ts | 5 +++ packages/backend/src/queue/index.ts | 5 +++ .../src/queue/processors/db/export-mute.ts | 3 +- .../system/check-expired-mutings.ts | 30 +++++++++++++ .../src/queue/processors/system/index.ts | 2 + .../src/server/api/endpoints/mute/create.ts | 6 +++ packages/client/src/scripts/get-user-menu.ts | 43 ++++++++++++++++--- 12 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 packages/backend/migration/1646387162108-mute-expires-at.js create mode 100644 packages/backend/src/queue/processors/system/check-expired-mutings.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 88adeca87..0c1d49f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ You should also include the user name that made the change. ### Improvements - インスタンスデフォルトテーマを設定できるように @syuilo +- ミュートに期限を設定できるように @syuilo - プロフィールの追加情報を最大16まで保存できるように @syuilo - 連合チャートにPub&Subを追加 @syuilo - デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 90dc14815..8f48c2940 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -834,6 +834,12 @@ searchByGoogle: "ググる" instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ" instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ" instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。" +mutePeriod: "ミュートする期限" +indefinitely: "無期限" +tenMinutes: "10分" +oneHour: "1時間" +oneDay: "1日" +oneWeek: "1週間" _emailUnavailable: used: "既に使用されています" diff --git a/packages/backend/migration/1646387162108-mute-expires-at.js b/packages/backend/migration/1646387162108-mute-expires-at.js new file mode 100644 index 000000000..c8be8f3c5 --- /dev/null +++ b/packages/backend/migration/1646387162108-mute-expires-at.js @@ -0,0 +1,13 @@ +export class muteExpiresAt1646387162108 { + name = 'muteExpiresAt1646387162108' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "muting" ADD "expiresAt" TIMESTAMP WITH TIME ZONE`); + await queryRunner.query(`CREATE INDEX "IDX_c1fd1c3dfb0627aa36c253fd14" ON "muting" ("expiresAt") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_c1fd1c3dfb0627aa36c253fd14"`); + await queryRunner.query(`ALTER TABLE "muting" DROP COLUMN "expiresAt"`); + } +} diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index 8cdd2af9d..b3a7e7a67 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -14,6 +14,13 @@ export class Muting { }) public createdAt: Date; + @Index() + @Column('timestamp with time zone', { + nullable: true, + default: null, + }) + public expiresAt: Date | null; + @Index() @Column({ ...id(), diff --git a/packages/backend/src/models/repositories/muting.ts b/packages/backend/src/models/repositories/muting.ts index 6ffecc302..643e0b68e 100644 --- a/packages/backend/src/models/repositories/muting.ts +++ b/packages/backend/src/models/repositories/muting.ts @@ -16,6 +16,7 @@ export class MutingRepository extends Repository { return await awaitAll({ id: muting.id, createdAt: muting.createdAt.toISOString(), + expiresAt: muting.expiresAt ? muting.expiresAt.toISOString() : null, muteeId: muting.muteeId, mutee: Users.pack(muting.muteeId, me, { detail: true, diff --git a/packages/backend/src/models/schema/muting.ts b/packages/backend/src/models/schema/muting.ts index d75a4fbfe..3ab99e17e 100644 --- a/packages/backend/src/models/schema/muting.ts +++ b/packages/backend/src/models/schema/muting.ts @@ -12,6 +12,11 @@ export const packedMutingSchema = { optional: false, nullable: false, format: 'date-time', }, + expiresAt: { + type: 'string', + optional: false, nullable: true, + format: 'date-time', + }, muteeId: { type: 'string', optional: false, nullable: false, diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 94055e9c5..1b1c21c4f 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -273,6 +273,11 @@ export default function() { repeat: { cron: '0 0 * * *' }, }); + systemQueue.add('checkExpiredMutings', { + }, { + repeat: { cron: '*/5 * * * *' }, + }); + processSystemQueue(systemQueue); } diff --git a/packages/backend/src/queue/processors/db/export-mute.ts b/packages/backend/src/queue/processors/db/export-mute.ts index 8602e00bf..9fb144abb 100644 --- a/packages/backend/src/queue/processors/db/export-mute.ts +++ b/packages/backend/src/queue/processors/db/export-mute.ts @@ -7,7 +7,7 @@ import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; import { getFullApAccount } from '@/misc/convert-host.js'; import { Users, Mutings } from '@/models/index.js'; -import { MoreThan } from 'typeorm'; +import { IsNull, MoreThan } from 'typeorm'; import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-mute'); @@ -40,6 +40,7 @@ export async function exportMute(job: Bull.Job, done: any): Promi const mutes = await Mutings.find({ where: { muterId: user.id, + expiresAt: IsNull(), ...(cursor ? { id: MoreThan(cursor) } : {}), }, take: 100, diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts new file mode 100644 index 000000000..621269e7e --- /dev/null +++ b/packages/backend/src/queue/processors/system/check-expired-mutings.ts @@ -0,0 +1,30 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Mutings } from '@/models/index.js'; +import { queueLogger } from '../../logger.js'; +import { publishUserEvent } from '@/services/stream.js'; + +const logger = queueLogger.createSubLogger('check-expired-mutings'); + +export async function checkExpiredMutings(job: Bull.Job>, done: any): Promise { + logger.info(`Checking expired mutings...`); + + const expired = await Mutings.createQueryBuilder('muting') + .where('muting.expiresAt IS NOT NULL') + .andWhere('muting.expiresAt < :now', { now: new Date() }) + .innerJoinAndSelect('muting.mutee', 'mutee') + .getMany(); + + if (expired.length > 0) { + await Mutings.delete({ + id: In(expired.map(m => m.id)), + }); + + for (const m of expired) { + publishUserEvent(m.muterId, 'unmute', m.mutee!); + } + } + + logger.succ(`All expired mutings checked.`); + done(); +} diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts index dca3249e8..f90f6efaf 100644 --- a/packages/backend/src/queue/processors/system/index.ts +++ b/packages/backend/src/queue/processors/system/index.ts @@ -2,11 +2,13 @@ import Bull from 'bull'; import { tickCharts } from './tick-charts.js'; import { resyncCharts } from './resync-charts.js'; import { cleanCharts } from './clean-charts.js'; +import { checkExpiredMutings } from './check-expired-mutings.js'; const jobs = { tickCharts, resyncCharts, cleanCharts, + checkExpiredMutings, } as Record> | Bull.ProcessPromiseFunction>>; export default function(dbQueue: Bull.Queue>) { diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index 0178aab14..dacee40d0 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -38,6 +38,7 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, + expiresAt: { type: 'integer', nullable: true }, }, required: ['userId'], } as const; @@ -67,10 +68,15 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.alreadyMuting); } + if (ps.expiresAt && ps.expiresAt <= Date.now()) { + return; + } + // Create mute await Mutings.insert({ id: genId(), createdAt: new Date(), + expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, muterId: muter.id, muteeId: mutee.id, } as Muting); diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index 6d1f25a94..192d14b83 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -56,11 +56,44 @@ export function getUserMenu(user) { } async function toggleMute() { - os.apiWithDialog(user.isMuted ? 'mute/delete' : 'mute/create', { - userId: user.id - }).then(() => { - user.isMuted = !user.isMuted; - }); + if (user.isMuted) { + os.apiWithDialog('mute/delete', { + userId: user.id, + }).then(() => { + user.isMuted = false; + }); + } else { + const { canceled, result: period } = await os.select({ + title: i18n.ts.mutePeriod, + items: [{ + value: 'indefinitely', text: i18n.ts.indefinitely, + }, { + value: 'tenMinutes', text: i18n.ts.tenMinutes, + }, { + value: 'oneHour', text: i18n.ts.oneHour, + }, { + value: 'oneDay', text: i18n.ts.oneDay, + }, { + value: 'oneWeek', text: i18n.ts.oneWeek, + }], + default: 'indefinitely', + }); + if (canceled) return; + + const expiresAt = period === 'indefinitely' ? null + : period === 'tenMinutes' ? Date.now() + (1000 * 60 * 10) + : period === 'oneHour' ? Date.now() + (1000 * 60 * 60) + : period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24) + : period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7) + : null; + + os.apiWithDialog('mute/create', { + userId: user.id, + expiresAt, + }).then(() => { + user.isMuted = true; + }); + } } async function toggleBlock() { From 3e31d1fae9e662011a9ed12b8409890e21caec4f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 5 Mar 2022 00:35:59 +0900 Subject: [PATCH 0211/1102] chore(client): hide error report setting Close #8327 --- packages/client/src/pages/settings/other.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/client/src/pages/settings/other.vue b/packages/client/src/pages/settings/other.vue index 6e48cb58a..a9903acc7 100644 --- a/packages/client/src/pages/settings/other.vue +++ b/packages/client/src/pages/settings/other.vue @@ -4,7 +4,9 @@ {{ $ts.showFeaturedNotesInTimeline }} + {{ $ts.accountInfo }} From 476dfb0f351c9b879de90fe3d1aef826ab03b82b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 5 Mar 2022 01:22:57 +0900 Subject: [PATCH 0212/1102] =?UTF-8?q?fix(client):=20register=5Fnote=5Fview?= =?UTF-8?q?=5Finterruptor()=E3=81=8C=E5=8B=95=E3=81=8B=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #8318 --- CHANGELOG.md | 1 + packages/client/src/components/note.vue | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1d49f2e..dfb09b606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ You should also include the user name that made the change. - Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo - Client: ユーザー名オートコンプリートが正しく動作しない問題を修正 @syuilo - Client: タッチ操作だとウィジェットの編集がしにくいのを修正 @xianonn +- Client: register_note_view_interruptor()が動かないのを修正 @syuilo ## 12.107.0 (2022/02/12) diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue index 93286a28b..3cd7a819d 100644 --- a/packages/client/src/components/note.vue +++ b/packages/client/src/components/note.vue @@ -138,7 +138,18 @@ const props = defineProps<{ const inChannel = inject('inChannel', null); -const note = $ref(JSON.parse(JSON.stringify(props.note))); +let note = $ref(JSON.parse(JSON.stringify(props.note))); + +// plugin +if (noteViewInterruptors.length > 0) { + onMounted(async () => { + let result = JSON.parse(JSON.stringify(note)); + for (const interruptor of noteViewInterruptors) { + result = await interruptor.handler(result); + } + note = result; + }); +} const isRenote = ( note.renote != null && @@ -152,7 +163,7 @@ const menuButton = ref(); const renoteButton = ref>(); const renoteTime = ref(); const reactButton = ref(); -let appearNote = $ref(isRenote ? note.renote as misskey.entities.Note : note); +let appearNote = $computed(() => isRenote ? note.renote as misskey.entities.Note : note); const isMyRenote = $i && ($i.id === note.userId); const showContent = ref(false); const collapsed = ref(appearNote.cw == null && appearNote.text != null && ( From 5431b5124902deb577bd3bc08e637ba5a15ccdd1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 5 Mar 2022 01:23:34 +0900 Subject: [PATCH 0213/1102] fix --- packages/client/src/components/note-detailed.vue | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue index 80233d608..d30284ca5 100644 --- a/packages/client/src/components/note-detailed.vue +++ b/packages/client/src/components/note-detailed.vue @@ -154,7 +154,18 @@ const props = defineProps<{ const inChannel = inject('inChannel', null); -const note = $ref(JSON.parse(JSON.stringify(props.note))); +let note = $ref(JSON.parse(JSON.stringify(props.note))); + +// plugin +if (noteViewInterruptors.length > 0) { + onMounted(async () => { + let result = JSON.parse(JSON.stringify(note)); + for (const interruptor of noteViewInterruptors) { + result = await interruptor.handler(result); + } + note = result; + }); +} const isRenote = ( note.renote != null && @@ -168,7 +179,7 @@ const menuButton = ref(); const renoteButton = ref>(); const renoteTime = ref(); const reactButton = ref(); -let appearNote = $ref(isRenote ? note.renote as misskey.entities.Note : note); +let appearNote = $computed(() => isRenote ? note.renote as misskey.entities.Note : note); const isMyRenote = $i && ($i.id === note.userId); const showContent = ref(false); const isDeleted = ref(false); From 446e4ce0c3193fe6ead9ec2969424816a2c33a28 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sat, 5 Mar 2022 02:00:45 +0900 Subject: [PATCH 0214/1102] =?UTF-8?q?fix:=20iPhone=20X=E4=BB=A5=E9=99=8D(?= =?UTF-8?q?=3F)=E3=81=A7=E3=83=9A=E3=83=BC=E3=82=B8=E3=81=AE=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E3=81=8C=E5=85=A8=E3=81=A6=E8=A1=A8=E7=A4=BA=E3=81=97?= =?UTF-8?q?=E3=81=8D=E3=82=8C=E3=81=AA=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#8375)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add safe-area-inset-bottom to spacer * fix * :v: * fix --- packages/client/src/components/notification-toast.vue | 2 +- packages/client/src/ui/universal.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/notification-toast.vue b/packages/client/src/components/notification-toast.vue index 4c5783e52..b808647bb 100644 --- a/packages/client/src/components/notification-toast.vue +++ b/packages/client/src/components/notification-toast.vue @@ -53,7 +53,7 @@ onMounted(() => { } @media (max-width: 500px) { - bottom: 92px; + bottom: calc(env(safe-area-inset-bottom, 0px) + 92px); padding: 0 8px; } diff --git a/packages/client/src/ui/universal.vue b/packages/client/src/ui/universal.vue index 000fec9b4..a5ff7a625 100644 --- a/packages/client/src/ui/universal.vue +++ b/packages/client/src/ui/universal.vue @@ -265,7 +265,7 @@ const wallpaper = localStorage.getItem('wallpaper') != null; min-width: 0; > .spacer { - height: 82px; + height: calc(env(safe-area-inset-bottom, 0px) + 96px); @media (min-width: ($widgets-hide-threshold + 1px)) { display: none; From 8bb586c1fde8e90468d1ed22e9fcee2488248ac3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 5 Mar 2022 02:01:38 +0900 Subject: [PATCH 0215/1102] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfb09b606..d647b98f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ You should also include the user name that made the change. - Client: ユーザー名オートコンプリートが正しく動作しない問題を修正 @syuilo - Client: タッチ操作だとウィジェットの編集がしにくいのを修正 @xianonn - Client: register_note_view_interruptor()が動かないのを修正 @syuilo +- Client: iPhone X以降(?)でページの内容が全て表示しきれないのを修正 @tamaina ## 12.107.0 (2022/02/12) From 2442592ef1a51cad901cf5e7fe30cdc85d7568cc Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 6 Mar 2022 16:06:27 +0900 Subject: [PATCH 0216/1102] =?UTF-8?q?feat:=20=E3=82=A2=E3=83=B3=E3=82=B1?= =?UTF-8?q?=E3=83=BC=E3=83=88=E7=B5=82=E4=BA=86=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve #4664 --- CHANGELOG.md | 1 + locales/ja-JP.yml | 2 ++ .../1646549089451-poll-ended-notification.js | 18 ++++++++++ .../src/models/entities/notification.ts | 3 +- .../src/models/repositories/notification.ts | 6 ++++ packages/backend/src/queue/index.ts | 4 ++- .../processors/ended-poll-notification.ts | 33 +++++++++++++++++++ packages/backend/src/queue/queues.ts | 3 +- packages/backend/src/queue/types.ts | 5 +++ packages/backend/src/services/note/create.ts | 10 ++++++ packages/backend/src/types.ts | 2 +- .../client/src/components/notification.vue | 19 +++++++++-- .../client/src/components/notifications.vue | 7 ++-- .../client/src/sw/compose-notification.ts | 5 +++ 14 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 packages/backend/migration/1646549089451-poll-ended-notification.js create mode 100644 packages/backend/src/queue/processors/ended-poll-notification.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d647b98f2..03bad049b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ You should also include the user name that made the change. ### Improvements - インスタンスデフォルトテーマを設定できるように @syuilo - ミュートに期限を設定できるように @syuilo +- アンケートが終了したときに通知が作成されるように @syuilo - プロフィールの追加情報を最大16まで保存できるように @syuilo - 連合チャートにPub&Subを追加 @syuilo - デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 8f48c2940..13f9efe9b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1667,6 +1667,7 @@ _notification: youReceivedFollowRequest: "フォローリクエストが来ました" yourFollowRequestAccepted: "フォローリクエストが承認されました" youWereInvitedToGroup: "グループに招待されました" + pollEnded: "アンケートの結果が出ました" _types: all: "すべて" @@ -1677,6 +1678,7 @@ _notification: quote: "引用" reaction: "リアクション" pollVote: "アンケートに投票された" + pollEnded: "アンケートが終了" receiveFollowRequest: "フォロー申請を受け取った" followRequestAccepted: "フォローが受理された" groupInvited: "グループに招待された" diff --git a/packages/backend/migration/1646549089451-poll-ended-notification.js b/packages/backend/migration/1646549089451-poll-ended-notification.js new file mode 100644 index 000000000..38a38ce64 --- /dev/null +++ b/packages/backend/migration/1646549089451-poll-ended-notification.js @@ -0,0 +1,18 @@ + +export class pollEndedNotification1646549089451 { + name = 'pollEndedNotification1646549089451' + + async up(queryRunner) { + await queryRunner.query(`ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`); + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum" USING "type"::"text"::"public"."notification_type_enum"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum_old"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum_old" USING "type"::"text"::"public"."notification_type_enum_old"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum"`); + await queryRunner.query(`ALTER TYPE "public"."notification_type_enum_old" RENAME TO "notification_type_enum"`); + } +} diff --git a/packages/backend/src/models/entities/notification.ts b/packages/backend/src/models/entities/notification.ts index 4a4739b8c..db3dba363 100644 --- a/packages/backend/src/models/entities/notification.ts +++ b/packages/backend/src/models/entities/notification.ts @@ -59,7 +59,8 @@ export class Notification { * renote - (自分または自分がWatchしている)投稿がRenoteされた * quote - (自分または自分がWatchしている)投稿が引用Renoteされた * reaction - (自分または自分がWatchしている)投稿にリアクションされた - * pollVote - (自分または自分がWatchしている)投稿の投票に投票された + * pollVote - (自分または自分がWatchしている)投稿のアンケートに投票された + * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * receiveFollowRequest - フォローリクエストされた * followRequestAccepted - 自分の送ったフォローリクエストが承認された * groupInvited - グループに招待された diff --git a/packages/backend/src/models/repositories/notification.ts b/packages/backend/src/models/repositories/notification.ts index 441bb7926..8e72d8aab 100644 --- a/packages/backend/src/models/repositories/notification.ts +++ b/packages/backend/src/models/repositories/notification.ts @@ -67,6 +67,12 @@ export class NotificationRepository extends Repository { }), choice: notification.choice, } : {}), + ...(notification.type === 'pollEnded' ? { + note: Notes.pack(notification.note || notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), ...(notification.type === 'groupInvited' ? { invitation: UserGroupInvitations.pack(notification.userGroupInvitationId!), } : {}), diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 1b1c21c4f..50bcccbb7 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -8,10 +8,11 @@ import processInbox from './processors/inbox.js'; import processDb from './processors/db/index.js'; import processObjectStorage from './processors/object-storage/index.js'; import processSystemQueue from './processors/system/index.js'; +import { endedPollNotification } from './processors/ended-poll-notification.js'; import { queueLogger } from './logger.js'; import { DriveFile } from '@/models/entities/drive-file.js'; import { getJobInfo } from './get-job-info.js'; -import { systemQueue, dbQueue, deliverQueue, inboxQueue, objectStorageQueue } from './queues.js'; +import { systemQueue, dbQueue, deliverQueue, inboxQueue, objectStorageQueue, endedPollNotificationQueue } from './queues.js'; import { ThinUser } from './types.js'; import { IActivity } from '@/remote/activitypub/type.js'; @@ -255,6 +256,7 @@ export default function() { deliverQueue.process(config.deliverJobConcurrency || 128, processDeliver); inboxQueue.process(config.inboxJobConcurrency || 16, processInbox); + endedPollNotificationQueue.process(endedPollNotification); processDb(dbQueue); processObjectStorage(objectStorageQueue); diff --git a/packages/backend/src/queue/processors/ended-poll-notification.ts b/packages/backend/src/queue/processors/ended-poll-notification.ts new file mode 100644 index 000000000..afac27921 --- /dev/null +++ b/packages/backend/src/queue/processors/ended-poll-notification.ts @@ -0,0 +1,33 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Notes, Polls, PollVotes } from '@/models/index.js'; +import { queueLogger } from '../logger.js'; +import { EndedPollNotificationJobData } from '@/queue/types.js'; +import { createNotification } from '@/services/create-notification.js'; + +const logger = queueLogger.createSubLogger('ended-poll-notification'); + +export async function endedPollNotification(job: Bull.Job, done: any): Promise { + const note = await Notes.findOne(job.data.noteId); + if (note == null || !note.hasPoll) { + done(); + return; + } + + const votes = await PollVotes.createQueryBuilder('vote') + .select('vote.userId') + .where('vote.noteId = :noteId', { noteId: note.id }) + .innerJoinAndSelect('vote.user', 'user') + .andWhere('user.host IS NULL') + .getMany(); + + const userIds = [...new Set([note.userId, ...votes.map(v => v.userId)])]; + + for (const userId of userIds) { + createNotification(userId, 'pollEnded', { + noteId: note.id, + }); + } + + done(); +} diff --git a/packages/backend/src/queue/queues.ts b/packages/backend/src/queue/queues.ts index 6ac4ec69c..02df58736 100644 --- a/packages/backend/src/queue/queues.ts +++ b/packages/backend/src/queue/queues.ts @@ -1,8 +1,9 @@ import config from '@/config/index.js'; import { initialize as initializeQueue } from './initialize.js'; -import { DeliverJobData, InboxJobData, DbJobData, ObjectStorageJobData } from './types.js'; +import { DeliverJobData, InboxJobData, DbJobData, ObjectStorageJobData, EndedPollNotificationJobData } from './types.js'; export const systemQueue = initializeQueue>('system'); +export const endedPollNotificationQueue = initializeQueue('endedPollNotification'); export const deliverQueue = initializeQueue('deliver', config.deliverJobPerSec || 128); export const inboxQueue = initializeQueue('inbox', config.inboxJobPerSec || 16); export const dbQueue = initializeQueue('db'); diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index de5f5d139..5191caea4 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -1,4 +1,5 @@ import { DriveFile } from '@/models/entities/drive-file.js'; +import { Note } from '@/models/entities/note'; import { User } from '@/models/entities/user.js'; import { IActivity } from '@/remote/activitypub/type.js'; import httpSignature from 'http-signature'; @@ -41,6 +42,10 @@ export type ObjectStorageFileJobData = { key: string; }; +export type EndedPollNotificationJobData = { + noteId: Note['id']; +}; + export type ThinUser = { id: User['id']; }; diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index ed242a0b5..8c5f13362 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -34,6 +34,7 @@ import { deliverToRelays } from '../relay.js'; import { Channel } from '@/models/entities/channel.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { getAntennas } from '@/misc/antenna-cache.js'; +import { endedPollNotificationQueue } from '@/queue/queues.js'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; @@ -296,6 +297,15 @@ export default async (user: { id: User['id']; username: User['username']; host: incRenoteCount(data.renote); } + if (data.poll && data.poll.expiresAt) { + const delay = data.poll.expiresAt.getTime() - Date.now(); + endedPollNotificationQueue.add({ + noteId: note.id, + }, { + delay + }); + } + if (!silent) { if (Users.isLocalUser(user)) activeUsersChart.write(user); diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 20f6f8bb8..573e2faf8 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -1,4 +1,4 @@ -export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app'] as const; +export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; diff --git a/packages/client/src/components/notification.vue b/packages/client/src/components/notification.vue index d855f81f8..1a360f990 100644 --- a/packages/client/src/components/notification.vue +++ b/packages/client/src/components/notification.vue @@ -1,7 +1,8 @@ - + + + + + + + + + + + + From 7d08b936c6f3ef558283d26435e1332a9933c281 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 17 May 2022 18:30:35 +0200 Subject: [PATCH 0472/1102] refactor(client): refactor my-antennas/index to use Composition API (#8679) --- .../client/src/pages/my-antennas/index.vue | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/client/src/pages/my-antennas/index.vue b/packages/client/src/pages/my-antennas/index.vue index 7138d269a..9f1e01f11 100644 --- a/packages/client/src/pages/my-antennas/index.vue +++ b/packages/client/src/pages/my-antennas/index.vue @@ -1,7 +1,7 @@ - From 21d54f2758903c31714c49f278141c00e33294c9 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sat, 28 May 2022 17:26:17 +0200 Subject: [PATCH 0537/1102] fix: validate text is not empty fix #8747 --- packages/backend/src/server/api/endpoints/notes/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 955f53bbc..a13329416 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -134,7 +134,7 @@ export const paramDef = { { // (re)note with text, files and poll are optional properties: { - text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: false }, + text: { type: 'string', minLength: 1, maxLength: MAX_NOTE_TEXT_LENGTH, nullable: false }, }, required: ['text'], }, From e54aa56ee13eb146cc6244ff1eaf401a0765a899 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Fri, 20 May 2022 11:11:27 +0200 Subject: [PATCH 0538/1102] chore: remove unused imports --- packages/backend/src/remote/activitypub/models/note.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 097a71661..ad24bbcd6 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -3,9 +3,9 @@ import promiseLimit from 'promise-limit'; import config from '@/config/index.js'; import Resolver from '../resolver.js'; import post from '@/services/note/create.js'; -import { resolvePerson, updatePerson } from './person.js'; +import { resolvePerson } from './person.js'; import { resolveImage } from './image.js'; -import { CacheableRemoteUser, IRemoteUser } from '@/models/entities/user.js'; +import { CacheableRemoteUser } from '@/models/entities/user.js'; import { htmlToMfm } from '../misc/html-to-mfm.js'; import { extractApHashtags } from './tag.js'; import { unique, toArray, toSingle } from '@/prelude/array.js'; @@ -15,7 +15,7 @@ import { apLogger } from '../logger.js'; import { DriveFile } from '@/models/entities/drive-file.js'; import { deliverQuestionUpdate } from '@/services/note/polls/update.js'; import { extractDbHost, toPuny } from '@/misc/convert-host.js'; -import { Emojis, Polls, MessagingMessages, Users } from '@/models/index.js'; +import { Emojis, Polls, MessagingMessages } from '@/models/index.js'; import { Note } from '@/models/entities/note.js'; import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, isEmoji, getApType } from '../type.js'; import { Emoji } from '@/models/entities/emoji.js'; From 4917961736cb4d01da31183a90a0f33623684c72 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 29 May 2022 10:57:06 +0900 Subject: [PATCH 0539/1102] preload app css (#8752) --- packages/backend/src/config/load.ts | 2 +- packages/backend/src/server/web/index.ts | 4 +-- .../backend/src/server/web/views/base.pug | 32 ++++++++++++------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index c2e6bea45..9654a4f3b 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -46,7 +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_\//, ''); + mixin.clientEntry = clientManifest['src/init.ts']; if (!config.redis.prefix) config.redis.prefix = mixin.host; diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 9e31f2389..0b2c62c04 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -74,9 +74,9 @@ app.use(views(_dirname + '/views', { extension: 'pug', options: { version: config.version, - clientEntry: () => process.env.NODE_ENV === 'production' ? + getClientEntry: () => 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_\//, ''), + JSON.parse(readFileSync(`${_dirname}/../../../../../built/_client_dist_/manifest.json`, 'utf-8'))['src/init.ts'], config, }, })); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index a488e5117..69ddb73c0 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -1,17 +1,23 @@ block vars +block loadClientEntry + - const clientEntry = getClientEntry(); + doctype html -!= '\n' +// + - + + _____ _ _ + | |_|___ ___| |_ ___ _ _ + | | | | |_ -|_ -| \'_| -_| | | + |_|_|_|_|___|___|_,_|___|_ | + |___| + Thank you for using Misskey! + If you are reading this message... how about joining the development? + https://github.com/misskey-dev/misskey + + html @@ -30,9 +36,11 @@ html link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg') - link(rel='preload' href='/assets/fontawesome/css/all.css' as='style') link(rel='stylesheet' href='/assets/fontawesome/css/all.css') + each href in clientEntry.css + link(rel='preload' href=`/assets/${href}` as='style') + title block title = title || 'Misskey' @@ -52,7 +60,7 @@ html script. var VERSION = "#{version}"; - var CLIENT_ENTRY = "#{clientEntry()}"; + var CLIENT_ENTRY = "#{clientEntry.file}"; script include ../boot.js From f1d2398eacbc69a14d09ebe5e7040be891f9e143 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 29 May 2022 10:58:54 +0900 Subject: [PATCH 0540/1102] fix(client): Vite related boot mechanism revision (#8753) * preload app css * remove salt * APP_FETCH_FAILED error * set max-age to 15s --- packages/backend/src/server/web/boot.js | 13 +++---------- packages/backend/src/server/web/index.ts | 14 +++++++------- packages/backend/src/server/web/views/base.pug | 4 ++++ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index a9ee0df4f..94329e11c 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -54,14 +54,10 @@ //#endregion //#region Script - const salt = localStorage.getItem('salt') - ? `?salt=${localStorage.getItem('salt')}` - : ''; - - import(`/assets/${CLIENT_ENTRY}${salt}`) - .catch(async () => { + import(`/assets/${CLIENT_ENTRY}`) + .catch(async e => { await checkUpdate(); - renderError('APP_FETCH_FAILED'); + renderError('APP_FETCH_FAILED', JSON.stringify(e)); }) //#endregion @@ -142,9 +138,6 @@ // eslint-disable-next-line no-inner-declarations function refresh() { - // Random - localStorage.setItem('salt', Math.random().toString().substr(2, 8)); - // Clear cache (service worker) try { navigator.serviceWorker.controller.postMessage('clear'); diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 0b2c62c04..2feee72be 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -247,7 +247,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { icon: meta.iconUrl, themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=30'); + ctx.set('Cache-Control', 'public, max-age=15'); } else { // リモートユーザーなので // モデレータがAPI経由で参照可能にするために404にはしない @@ -292,7 +292,7 @@ router.get('/notes/:note', async (ctx, next) => { themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=180'); + ctx.set('Cache-Control', 'public, max-age=15'); return; } @@ -329,7 +329,7 @@ router.get('/@:user/pages/:page', async (ctx, next) => { }); if (['public'].includes(page.visibility)) { - ctx.set('Cache-Control', 'public, max-age=180'); + ctx.set('Cache-Control', 'public, max-age=15'); } else { ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); } @@ -360,7 +360,7 @@ router.get('/clips/:clip', async (ctx, next) => { themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=180'); + ctx.set('Cache-Control', 'public, max-age=15'); return; } @@ -385,7 +385,7 @@ router.get('/gallery/:post', async (ctx, next) => { themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=180'); + ctx.set('Cache-Control', 'public, max-age=15'); return; } @@ -409,7 +409,7 @@ router.get('/channels/:channel', async (ctx, next) => { themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=180'); + ctx.set('Cache-Control', 'public, max-age=15'); return; } @@ -468,7 +468,7 @@ router.get('(.*)', async ctx => { icon: meta.iconUrl, themeColor: meta.themeColor, }); - ctx.set('Cache-Control', 'public, max-age=300'); + ctx.set('Cache-Control', 'public, max-age=15'); }); // Register router diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 69ddb73c0..230ed1578 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -37,6 +37,10 @@ html link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg') link(rel='stylesheet' href='/assets/fontawesome/css/all.css') + link(rel='modulepreload' href=`/assets/${clientEntry.file}`) + + each href in clientEntry.css + link(rel='preload' href=`/assets/${href}` as='style') each href in clientEntry.css link(rel='preload' href=`/assets/${href}` as='style') From 804fa33535baa9e5cdf49070a50a555cf2c3b1ea Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 29 May 2022 08:15:52 +0200 Subject: [PATCH 0541/1102] refactor: improve code quality (#8751) * remove unnecessary if `Array.prototype.some` already returns a boolean so an if to return true or false is completely unnecessary in this case. * perf: use count instead of find When using `count` instead of `findOneBy`, the data is not unnecessarily loaded. * remove duplicate null check The variable is checked for null in the lines above and the function returns if so. Therefore, it can not be null at this point. * simplify `getJsonSchema` Because the assigned value is `null` and the used keys are only shallow, use of `nestedProperty.set` seems inappropriate. Because the value is not read, the initial for loop can be replaced by a `for..in` loop. Since all keys will be assigned `null`, the condition of the ternary expression in the nested function will always be true. Therefore the recursion case will never happen. With this the nested function can be eliminated. * remove duplicate condition The code above already checks `dragging` and returns if it is truthy. Checking it again later is therefore unnecessary. To make this more obvious the `return` is removed in favour of using an if...else construct. * remove impossible "unknown" time The `ago` variable will always be a number and all non-negative numbers are already covered by other cases, the negative case is handled with `future` so there is no case when `unkown` could be achieved. --- locales/ja-JP.yml | 1 - .../backend/src/models/repositories/note.ts | 19 ++-- .../backend/src/models/repositories/user.ts | 91 +++++++++++-------- .../src/remote/activitypub/renderer/index.ts | 2 +- packages/backend/src/services/chart/core.ts | 27 ++---- .../client/src/components/global/time.vue | 3 +- packages/client/src/ui/deck/column.vue | 13 ++- 7 files changed, 77 insertions(+), 79 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 6354fcfda..9cd1d1eed 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1111,7 +1111,6 @@ _sfx: channel: "チャンネル通知" _ago: - unknown: "謎" future: "未来" justNow: "たった今" secondsAgo: "{n}秒前" diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index 638d78f62..c0abbb4f9 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -144,13 +144,7 @@ export const NoteRepository = db.getRepository(Note).extend({ return true; } else { // 指定されているかどうか - const specified = note.visibleUserIds.some((id: any) => meId === id); - - if (specified) { - return true; - } else { - return false; - } + return note.visibleUserIds.some((id: any) => meId === id); } } @@ -169,9 +163,12 @@ export const NoteRepository = db.getRepository(Note).extend({ } else { // フォロワーかどうか const [following, user] = await Promise.all([ - Followings.findOneBy({ - followeeId: note.userId, - followerId: meId, + Followings.count({ + where: { + followeeId: note.userId, + followerId: meId, + }, + take: 1, }), Users.findOneByOrFail({ id: meId }), ]); @@ -183,7 +180,7 @@ export const NoteRepository = db.getRepository(Note).extend({ in which case we can never know the following. Instead we have to assume that the users are following each other. */ - return following != null || (note.userHost != null && user.host != null); + return following > 0 || (note.userHost != null && user.host != null); } } diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 541fbaf00..8a4e48efd 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -61,47 +61,58 @@ export const UserRepository = db.getRepository(User).extend({ //#endregion async getRelation(me: User['id'], target: User['id']) { - const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([ - Followings.findOneBy({ - followerId: me, - followeeId: target, - }), - Followings.findOneBy({ - followerId: target, - followeeId: me, - }), - FollowRequests.findOneBy({ - followerId: me, - followeeId: target, - }), - FollowRequests.findOneBy({ - followerId: target, - followeeId: me, - }), - Blockings.findOneBy({ - blockerId: me, - blockeeId: target, - }), - Blockings.findOneBy({ - blockerId: target, - blockeeId: me, - }), - Mutings.findOneBy({ - muterId: me, - muteeId: target, - }), - ]); - - return { + return awaitAll({ id: target, - isFollowing: following1 != null, - hasPendingFollowRequestFromYou: followReq1 != null, - hasPendingFollowRequestToYou: followReq2 != null, - isFollowed: following2 != null, - isBlocking: toBlocking != null, - isBlocked: fromBlocked != null, - isMuted: mute != null, - }; + isFollowing: Followings.count({ + where: { + followerId: me, + followeeId: target, + }, + take: 1, + }).then(n => n > 0), + isFollowed: Followings.count({ + where: { + followerId: target, + followeeId: me, + }, + take: 1, + }).then(n => n > 0), + hasPendingFollowRequestFromYou: FollowRequests.count({ + where: { + followerId: me, + followeeId: target, + }, + take: 1, + }).then(n => n > 0), + hasPendingFollowRequestToYou: FollowRequests.count({ + where: { + followerId: target, + followeeId: me, + }, + take: 1, + }).then(n => n > 0), + isBlocking: Blockings.count({ + where: { + blockerId: me, + blockeeId: target, + }, + take: 1, + }).then(n => n > 0), + isBlocked: Blockings.count({ + where: { + blockerId: target, + blockeeId: me, + }, + take: 1, + }).then(n => n > 0), + isMuted: Mutings.count({ + where: { + muterId: me, + muteeId: target, + }, + take: 1, + }).then(n => n > 0), + }); }, async getHasUnreadMessagingMessage(userId: User['id']): Promise { diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index 5f6933226..f100b77ce 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -8,7 +8,7 @@ import { User } from '@/models/entities/user.js'; export const renderActivity = (x: any): IActivity | null => { if (x == null) return null; - if (x !== null && typeof x === 'object' && x.id == null) { + if (typeof x === 'object' && x.id == null) { x.id = `${config.url}/${uuid()}`; } diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts index cf69e2194..2960bac8f 100644 --- a/packages/backend/src/services/chart/core.ts +++ b/packages/backend/src/services/chart/core.ts @@ -91,27 +91,20 @@ type ToJsonSchema = { }; export function getJsonSchema(schema: S): ToJsonSchema>> { - const object = {}; - for (const [k, v] of Object.entries(schema)) { - nestedProperty.set(object, k, null); - } + const jsonSchema = { + type: 'object', + properties: {} as Record, + required: [], + }; - function f(obj: Record>) { - const jsonSchema = { - type: 'object', - properties: {} as Record, - required: [], + for (const k in schema) { + jsonSchema.properties[k] = { + type: 'array', + items: { type: 'number' }, }; - for (const [k, v] of Object.entries(obj)) { - jsonSchema.properties[k] = v === null ? { - type: 'array', - items: { type: 'number' }, - } : f(v as Record>); - } - return jsonSchema; } - return f(object) as ToJsonSchema>>; + return jsonSchema as ToJsonSchema>>; } /** diff --git a/packages/client/src/components/global/time.vue b/packages/client/src/components/global/time.vue index 02351deb5..a7f142f96 100644 --- a/packages/client/src/components/global/time.vue +++ b/packages/client/src/components/global/time.vue @@ -32,8 +32,7 @@ const relative = $computed(() => { ago >= 60 ? i18n.t('_ago.minutesAgo', { n: (~~(ago / 60)).toString() }) : ago >= 10 ? i18n.t('_ago.secondsAgo', { n: (~~(ago % 60)).toString() }) : ago >= -1 ? i18n.ts._ago.justNow : - ago < -1 ? i18n.ts._ago.future : - i18n.ts._ago.unknown); + i18n.ts._ago.future); }); function tick() { diff --git a/packages/client/src/ui/deck/column.vue b/packages/client/src/ui/deck/column.vue index fbaea64f5..31063a753 100644 --- a/packages/client/src/ui/deck/column.vue +++ b/packages/client/src/ui/deck/column.vue @@ -213,14 +213,13 @@ function onDragover(ev) { if (dragging) { // 自分自身にはドロップさせない ev.dataTransfer.dropEffect = 'none'; - return; + } else { + const isDeckColumn = ev.dataTransfer.types[0] === _DATA_TRANSFER_DECK_COLUMN_; + + ev.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none'; + + if (isDeckColumn) draghover = true; } - - const isDeckColumn = ev.dataTransfer.types[0] === _DATA_TRANSFER_DECK_COLUMN_; - - ev.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none'; - - if (!dragging && isDeckColumn) draghover = true; } function onDragleave() { From d2784030ec898e0b4e391f2eb840646f72cd7d6b Mon Sep 17 00:00:00 2001 From: futchitwo <74236683+futchitwo@users.noreply.github.com> Date: Sun, 29 May 2022 19:21:36 +0900 Subject: [PATCH 0542/1102] fix(client): fix popout url (#8494) --- packages/client/src/pages/theme-editor.vue | 2 +- packages/client/src/scripts/popout.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/client/src/pages/theme-editor.vue b/packages/client/src/pages/theme-editor.vue index 2ee530597..b7b537cea 100644 --- a/packages/client/src/pages/theme-editor.vue +++ b/packages/client/src/pages/theme-editor.vue @@ -126,7 +126,7 @@ let changed = $ref(false); useLeaveGuard($$(changed)); function showPreview() { - os.pageWindow('preview'); + os.pageWindow('/preview'); } function setBgColor(color: typeof bgColors[number]) { diff --git a/packages/client/src/scripts/popout.ts b/packages/client/src/scripts/popout.ts index b8286a2a7..580031d0a 100644 --- a/packages/client/src/scripts/popout.ts +++ b/packages/client/src/scripts/popout.ts @@ -1,8 +1,9 @@ import * as config from '@/config'; +import { appendQuery } from './url'; export function popout(path: string, w?: HTMLElement) { - let url = path.startsWith('http://') || path.startsWith('https://') ? path : config.url + "/" + path; - url += '?zen'; + let url = path.startsWith('http://') || path.startsWith('https://') ? path : config.url + path; + url = appendQuery(url, 'zen'); if (w) { const position = w.getBoundingClientRect(); const width = parseInt(getComputedStyle(w, '').width, 10); From feba678e03d3c7635d6f9f130ea4355af245e70a Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 29 May 2022 14:26:29 +0200 Subject: [PATCH 0543/1102] enhance(dev): ask for log snippets --- .github/ISSUE_TEMPLATE/01_bug-report.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/01_bug-report.md b/.github/ISSUE_TEMPLATE/01_bug-report.md index 8734fc0c3..0fecce2ee 100644 --- a/.github/ISSUE_TEMPLATE/01_bug-report.md +++ b/.github/ISSUE_TEMPLATE/01_bug-report.md @@ -22,7 +22,10 @@ First, in order to avoid duplicate Issues, please search to see if the problem y ## 🤬 Actual Behavior - + ## 📝 Steps to Reproduce From ebc2566130c785924380d504c76b270198bdc2c2 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 29 May 2022 14:32:52 +0200 Subject: [PATCH 0544/1102] fix: add missing import fix #8756 --- .../backend/src/queue/processors/db/export-custom-emojis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index 97ba62dcf..8ce1d0527 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -9,7 +9,7 @@ import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; import { Users, Emojis } from '@/models/index.js'; import { } from '@/queue/types.js'; -import { createTempDir } from '@/misc/create-temp.js'; +import { createTemp, createTempDir } from '@/misc/create-temp.js'; import { downloadUrl } from '@/misc/download-url.js'; import config from '@/config/index.js'; import { IsNull } from 'typeorm'; From 39051854635617d1b95d85b759e3c1aa6f827b4b Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Mon, 30 May 2022 04:37:34 +0200 Subject: [PATCH 0545/1102] fix(client): import shared ESLint config in client package (#8761) --- packages/client/.eslintrc.js | 105 +++++++++++++++++++--------------- packages/client/tsconfig.json | 1 + 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/packages/client/.eslintrc.js b/packages/client/.eslintrc.js index a6e23e517..1c2ab0a42 100644 --- a/packages/client/.eslintrc.js +++ b/packages/client/.eslintrc.js @@ -1,68 +1,79 @@ module.exports = { root: true, env: { - "node": false + 'node': false, }, - parser: "vue-eslint-parser", + parser: 'vue-eslint-parser', parserOptions: { - "parser": "@typescript-eslint/parser", + 'parser': '@typescript-eslint/parser', tsconfigRootDir: __dirname, - //project: ['./tsconfig.json'], + project: ['./tsconfig.json'], + extraFileExtensions: ['.vue'], }, extends: [ - //"../shared/.eslintrc.js", - "plugin:vue/vue3-recommended" + '../shared/.eslintrc.js', + 'plugin:vue/vue3-recommended', ], rules: { // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため // data の禁止理由: 抽象的すぎるため // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため - "id-denylist": ["error", "window", "data", "e"], + 'id-denylist': ['error', 'window', 'data', 'e'], 'eqeqeq': ['error', 'always', { 'null': 'ignore' }], - "no-shadow": ["warn"], - "vue/attributes-order": ["error", { - "alphabetical": false + 'no-shadow': ['warn'], + 'vue/attributes-order': ['error', { + 'alphabetical': false, }], - "vue/no-use-v-if-with-v-for": ["error", { - "allowUsingIterationVar": false + 'vue/no-use-v-if-with-v-for': ['error', { + 'allowUsingIterationVar': false, }], - "vue/no-ref-as-operand": "error", - "vue/no-multi-spaces": ["error", { - "ignoreProperties": false + 'vue/no-ref-as-operand': 'error', + 'vue/no-multi-spaces': ['error', { + 'ignoreProperties': false, }], - "vue/no-v-html": "error", - "vue/order-in-components": "error", - "vue/html-indent": ["warn", "tab", { - "attribute": 1, - "baseIndent": 0, - "closeBracket": 0, - "alignAttributesVertically": true, - "ignores": [] + 'vue/no-v-html': 'error', + 'vue/order-in-components': 'error', + 'vue/html-indent': ['warn', 'tab', { + 'attribute': 1, + 'baseIndent': 0, + 'closeBracket': 0, + 'alignAttributesVertically': true, + 'ignores': [], }], - "vue/html-closing-bracket-spacing": ["warn", { - "startTag": "never", - "endTag": "never", - "selfClosingTag": "never" + 'vue/html-closing-bracket-spacing': ['warn', { + 'startTag': 'never', + 'endTag': 'never', + 'selfClosingTag': 'never', }], - "vue/multi-word-component-names": "warn", - "vue/require-v-for-key": "warn", - "vue/no-unused-components": "warn", - "vue/valid-v-for": "warn", - "vue/return-in-computed-property": "warn", - "vue/no-setup-props-destructure": "warn", - "vue/max-attributes-per-line": "off", - "vue/html-self-closing": "off", - "vue/singleline-html-element-content-newline": "off", + 'vue/multi-word-component-names': 'warn', + 'vue/require-v-for-key': 'warn', + 'vue/no-unused-components': 'warn', + 'vue/valid-v-for': 'warn', + 'vue/return-in-computed-property': 'warn', + 'vue/no-setup-props-destructure': 'warn', + 'vue/max-attributes-per-line': 'off', + 'vue/html-self-closing': 'off', + 'vue/singleline-html-element-content-newline': 'off', }, globals: { - "require": false, - "_DEV_": false, - "_LANGS_": false, - "_VERSION_": false, - "_ENV_": false, - "_PERF_PREFIX_": false, - "_DATA_TRANSFER_DRIVE_FILE_": false, - "_DATA_TRANSFER_DRIVE_FOLDER_": false, - "_DATA_TRANSFER_DECK_COLUMN_": false - } -} + // Node.js + 'module': false, + 'require': false, + '__dirname': false, + + // Vue + '$$': false, + '$ref': false, + '$computed': false, + + // Misskey + '_DEV_': false, + '_LANGS_': false, + '_VERSION_': false, + '_ENV_': false, + '_PERF_PREFIX_': false, + '_DATA_TRANSFER_DRIVE_FILE_': false, + '_DATA_TRANSFER_DRIVE_FOLDER_': false, + '_DATA_TRANSFER_DECK_COLUMN_': false, + }, +}; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 2c387286a..f7320a725 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -39,6 +39,7 @@ }, "compileOnSave": false, "include": [ + ".eslintrc.js", "./**/*.ts", "./**/*.vue" ] From 9759ca7d24d4a7b7154043160a8d8ba34b2505dc Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 30 May 2022 05:53:36 +0000 Subject: [PATCH 0546/1102] chore: remove packages/sw/webpack.config.js --- packages/sw/webpack.config.js | 71 ----------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 packages/sw/webpack.config.js diff --git a/packages/sw/webpack.config.js b/packages/sw/webpack.config.js deleted file mode 100644 index a4bcf96dd..000000000 --- a/packages/sw/webpack.config.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * webpack configuration - */ - -const fs = require('fs'); -const webpack = require('webpack'); - -class WebpackOnBuildPlugin { - constructor(callback) { - this.callback = callback; - } - - apply(compiler) { - compiler.hooks.done.tap('WebpackOnBuildPlugin', this.callback); - } -} - -const isProduction = process.env.NODE_ENV === 'production'; - -const locales = require('../../locales'); -const meta = require('../../package.json'); - -module.exports = { - target: 'webworker', - entry: { - ['sw-lib']: './src/lib.ts' - }, - module: { - rules: [{ - test: /\.ts$/, - exclude: /node_modules/, - use: [{ - loader: 'ts-loader', - options: { - happyPackMode: true, - transpileOnly: true, - configFile: __dirname + '/tsconfig.json', - } - }] - }] - }, - plugins: [ - new webpack.ProgressPlugin({}), - new webpack.DefinePlugin({ - _VERSION_: JSON.stringify(meta.version), - _LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]) => [k, v._lang_])), - _ENV_: JSON.stringify(process.env.NODE_ENV), - _DEV_: process.env.NODE_ENV !== 'production', - _PERF_PREFIX_: JSON.stringify('Misskey:'), - }), - ], - output: { - path: __dirname + '/../../built/_sw_dist_', - filename: `[name].js`, - publicPath: `/`, - pathinfo: false, - }, - resolve: { - extensions: [ - '.js', '.ts', '.json' - ], - alias: { - '@': __dirname + '/src/', - } - }, - resolveLoader: { - modules: ['node_modules'] - }, - devtool: false, //'source-map', - mode: isProduction ? 'production' : 'development' -}; From 857055a9dd50bbc3331d2454da3897d855fdebfe Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 30 May 2022 12:09:22 +0000 Subject: [PATCH 0547/1102] chore: fix import tinycolor --- packages/client/src/pages/settings/drive.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/pages/settings/drive.vue b/packages/client/src/pages/settings/drive.vue index f235ace7c..09a2537ed 100644 --- a/packages/client/src/pages/settings/drive.vue +++ b/packages/client/src/pages/settings/drive.vue @@ -35,7 +35,7 @@ diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue index 14bbbd4f3..6234b710d 100644 --- a/packages/client/src/components/note-detailed.vue +++ b/packages/client/src/components/note-detailed.vue @@ -222,7 +222,7 @@ function react(viaKeyboard = false): void { reactionPicker.show(reactButton.value, reaction => { os.api('notes/reactions/create', { noteId: appearNote.id, - reaction: reaction + reaction: reaction, }); }, () => { focus(); @@ -233,7 +233,7 @@ function undoReact(note): void { const oldReaction = note.myReaction; if (!oldReaction) return; os.api('notes/reactions/delete', { - noteId: note.id + noteId: note.id, }); } @@ -257,7 +257,7 @@ function onContextmenu(ev: MouseEvent): void { function menu(viaKeyboard = false): void { os.popupMenu(getNoteMenu({ note: note, translating, translation, menuButton }), menuButton.value, { - viaKeyboard + viaKeyboard, }).then(focus); } @@ -269,12 +269,12 @@ function showRenoteMenu(viaKeyboard = false): void { danger: true, action: () => { os.api('notes/delete', { - noteId: note.id + noteId: note.id, }); isDeleted.value = true; - } + }, }], renoteTime.value, { - viaKeyboard: viaKeyboard + viaKeyboard: viaKeyboard, }); } @@ -288,14 +288,14 @@ function blur() { os.api('notes/children', { noteId: appearNote.id, - limit: 30 + limit: 30, }).then(res => { replies.value = res; }); if (appearNote.replyId) { os.api('notes/conversation', { - noteId: appearNote.replyId + noteId: appearNote.replyId, }).then(res => { conversation.value = res.reverse(); }); diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue index bc8a0dd19..e5744d1ce 100644 --- a/packages/client/src/components/note.vue +++ b/packages/client/src/components/note.vue @@ -210,7 +210,7 @@ function react(viaKeyboard = false): void { reactionPicker.show(reactButton.value, reaction => { os.api('notes/reactions/create', { noteId: appearNote.id, - reaction: reaction + reaction: reaction, }); }, () => { focus(); @@ -221,7 +221,7 @@ function undoReact(note): void { const oldReaction = note.myReaction; if (!oldReaction) return; os.api('notes/reactions/delete', { - noteId: note.id + noteId: note.id, }); } @@ -245,7 +245,7 @@ function onContextmenu(ev: MouseEvent): void { function menu(viaKeyboard = false): void { os.popupMenu(getNoteMenu({ note: note, translating, translation, menuButton }), menuButton.value, { - viaKeyboard + viaKeyboard, }).then(focus); } @@ -257,12 +257,12 @@ function showRenoteMenu(viaKeyboard = false): void { danger: true, action: () => { os.api('notes/delete', { - noteId: note.id + noteId: note.id, }); isDeleted.value = true; - } + }, }], renoteTime.value, { - viaKeyboard: viaKeyboard + viaKeyboard: viaKeyboard, }); } @@ -284,7 +284,7 @@ function focusAfter() { function readPromo() { os.api('promo/read', { - noteId: appearNote.id + noteId: appearNote.id, }); isDeleted.value = true; } diff --git a/packages/client/src/components/notification-setting-window.vue b/packages/client/src/components/notification-setting-window.vue index ec1efec26..64d828394 100644 --- a/packages/client/src/components/notification-setting-window.vue +++ b/packages/client/src/components/notification-setting-window.vue @@ -1,5 +1,6 @@