From 4175b7809b3c7841423450032ec73380f674599b Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Thu, 21 Dec 2023 02:29:30 +0100 Subject: [PATCH 01/23] chore(QueueProcessorService): show error stack for failures (#12727) --- .../src/queue/QueueProcessorService.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index ee081ccaa..b872dd65f 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -153,8 +153,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.systemQueueWorker .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => systemLogger.warn(`failed(${err}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => systemLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => systemLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -191,8 +191,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => dbLogger.warn(`failed(${err}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => dbLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => dbLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -215,8 +215,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.deliverQueueWorker .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => deliverLogger.warn(`failed(${err}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) - .on('error', (err: Error) => deliverLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => deliverLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -239,8 +239,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.inboxQueueWorker .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) - .on('failed', (job, err) => inboxLogger.warn(`failed(${err}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => inboxLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => inboxLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -263,8 +263,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.webhookDeliverQueueWorker .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => webhookLogger.warn(`failed(${err}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) - .on('error', (err: Error) => webhookLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => webhookLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -292,8 +292,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.relationshipQueueWorker .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => relationshipLogger.warn(`failed(${err}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => relationshipLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => relationshipLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); //#endregion @@ -315,8 +315,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.objectStorageQueueWorker .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => objectStorageLogger.warn(`failed(${err}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => objectStorageLogger.error(`error ${err}`, { e: renderError(err) })) + .on('failed', (job, err) => objectStorageLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); //#endregion From d14eb20122411b8ab53920ae9d48580db512650c Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Thu, 21 Dec 2023 02:29:51 +0100 Subject: [PATCH 02/23] chore(workflows): use postgres 15 everywhere (#12726) --- .github/workflows/test-backend.yml | 2 +- .github/workflows/test-frontend.yml | 2 +- chart/templates/Deployment.yml | 4 ++-- packages/backend/test/docker-compose.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 6e8327ca0..1b0f22c8e 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -17,7 +17,7 @@ jobs: services: postgres: - image: postgres:13 + image: postgres:15 ports: - 54312:5432 env: diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index e5c461e6d..18b2a8c20 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -56,7 +56,7 @@ jobs: services: postgres: - image: postgres:13 + image: postgres:15 ports: - 54312:5432 env: diff --git a/chart/templates/Deployment.yml b/chart/templates/Deployment.yml index d5dd14f59..3c7383780 100644 --- a/chart/templates/Deployment.yml +++ b/chart/templates/Deployment.yml @@ -27,7 +27,7 @@ spec: ports: - containerPort: 3000 - name: postgres - image: postgres:14-alpine + image: postgres:15-alpine env: - name: POSTGRES_USER value: "example-misskey-user" @@ -38,7 +38,7 @@ spec: ports: - containerPort: 5432 - name: redis - image: redis:alpine + image: redis:7-alpine ports: - containerPort: 6379 volumes: diff --git a/packages/backend/test/docker-compose.yml b/packages/backend/test/docker-compose.yml index da6c01dda..f2d899075 100644 --- a/packages/backend/test/docker-compose.yml +++ b/packages/backend/test/docker-compose.yml @@ -7,7 +7,7 @@ services: - "127.0.0.1:56312:6379" dbtest: - image: postgres:13 + image: postgres:15 ports: - "127.0.0.1:54312:5432" environment: From 15b0d2aff2011935f212db19feab3bec97979ae1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2023 10:39:11 +0900 Subject: [PATCH 03/23] =?UTF-8?q?enhance:=20=E3=83=AD=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=AB=E3=82=A2=E3=82=B5=E3=82=A4=E3=83=B3=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AE=E9=80=9A=E7=9F=A5=20(#1260?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * Update misskey-js.api.md * Update CHANGELOG.md * Update RoleService.ts * Update locales/ja-JP.yml Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> * Update UserListService.ts * Update misskey-js.api.md * fix (#12724) --------- Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com> --- CHANGELOG.md | 1 + locales/index.d.ts | 1 + locales/ja-JP.yml | 1 + packages/backend/src/core/RoleService.ts | 29 ++++++++-- packages/backend/src/core/UserListService.ts | 4 +- .../entities/NotificationEntityService.ts | 11 ++-- packages/backend/src/models/Notification.ts | 8 ++- .../backend/src/models/json-schema/user.ts | 2 - packages/backend/src/types.ts | 17 +++++- packages/backend/test/unit/RoleService.ts | 54 +++++++++++++++++++ .../src/components/MkNotification.vue | 6 +++ packages/frontend/src/const.ts | 16 +++++- .../src/pages/settings/notifications.vue | 2 +- packages/misskey-js/etc/misskey-js.api.md | 11 ++-- packages/misskey-js/src/consts.ts | 2 +- 15 files changed, 143 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7251fd221..9a62cbefa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ - Feat: メールアドレスの認証にverifymail.ioを使えるように (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/971ba07a44550f68d2ba31c62066db2d43a0caed) - Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83) - Feat: TL上からノートが見えなくなるワードミュートであるハードミュートを追加 +- Enhance: 公開ロールにアサインされたときに通知が作成されるように - Enhance: アイコンデコレーションを複数設定できるように - Enhance: アイコンデコレーションの位置を微調整できるように - Enhance: つながりの公開範囲をフォロー/フォロワーで個別に設定可能に #12072 diff --git a/locales/index.d.ts b/locales/index.d.ts index 25a16d4a4..f22b7f1c4 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2325,6 +2325,7 @@ export interface Locale { "pollEnded": string; "newNote": string; "unreadAntennaNote": string; + "roleAssigned": string; "emptyPushNotificationMessage": string; "achievementEarned": string; "testNotification": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 308b7ae67..2185183c9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2227,6 +2227,7 @@ _notification: pollEnded: "アンケートの結果が出ました" newNote: "新しい投稿" unreadAntennaNote: "アンテナ {name}" + roleAssigned: "ロールが付与されました" emptyPushNotificationMessage: "プッシュ通知の更新をしました" achievementEarned: "実績を獲得" testNotification: "通知テスト" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 4de719d6a..d354faa7c 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -6,7 +6,14 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; import { In } from 'typeorm'; -import type { MiRole, MiRoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js'; +import { ModuleRef } from '@nestjs/core'; +import type { + MiRole, + MiRoleAssignment, + RoleAssignmentsRepository, + RolesRepository, + UsersRepository, +} from '@/models/_.js'; import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js'; import type { MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; @@ -16,12 +23,13 @@ import { CacheService } from '@/core/CacheService.js'; import type { RoleCondFormulaValue } from '@/models/Role.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; -import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { IdService } from '@/core/IdService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import type { Packed } from '@/misc/json-schema.js'; import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; -import type { OnApplicationShutdown } from '@nestjs/common'; +import { NotificationService } from '@/core/NotificationService.js'; +import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common'; export type RolePolicies = { gtlAvailable: boolean; @@ -78,14 +86,17 @@ export const DEFAULT_POLICIES: RolePolicies = { }; @Injectable() -export class RoleService implements OnApplicationShutdown { +export class RoleService implements OnApplicationShutdown, OnModuleInit { private rolesCache: MemorySingleCache; private roleAssignmentByUserIdCache: MemoryKVCache; + private notificationService: NotificationService; public static AlreadyAssignedError = class extends Error {}; public static NotAssignedError = class extends Error {}; constructor( + private moduleRef: ModuleRef, + @Inject(DI.redis) private redisClient: Redis.Redis, @@ -120,6 +131,10 @@ export class RoleService implements OnApplicationShutdown { this.redisForSub.on('message', this.onMessage); } + async onModuleInit() { + this.notificationService = this.moduleRef.get(NotificationService.name); + } + @bindThis private async onMessage(_: string, data: string): Promise { const obj = JSON.parse(data); @@ -427,6 +442,12 @@ export class RoleService implements OnApplicationShutdown { this.globalEventService.publishInternalEvent('userRoleAssigned', created); + if (role.isPublic) { + this.notificationService.createNotification(userId, 'roleAssigned', { + roleId: roleId, + }); + } + if (moderator) { const user = await this.usersRepository.findOneByOrFail({ id: userId }); this.moderationLogService.log(moderator, 'assignRole', { diff --git a/packages/backend/src/core/UserListService.ts b/packages/backend/src/core/UserListService.ts index 702c731fc..832b715d9 100644 --- a/packages/backend/src/core/UserListService.ts +++ b/packages/backend/src/core/UserListService.ts @@ -10,15 +10,15 @@ import type { MiUser } from '@/models/User.js'; import type { MiUserList } from '@/models/UserList.js'; import type { MiUserListMembership } from '@/models/UserListMembership.js'; import { IdService } from '@/core/IdService.js'; +import type { GlobalEvents } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { bindThis } from '@/decorators.js'; -import { RoleService } from '@/core/RoleService.js'; import { QueueService } from '@/core/QueueService.js'; import { RedisKVCache } from '@/misc/cache.js'; -import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import { RoleService } from '@/core/RoleService.js'; @Injectable() export class UserListService implements OnApplicationShutdown { diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index e723ea5a5..f2124998a 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -15,8 +15,8 @@ import type { Packed } from '@/misc/json-schema.js'; import { bindThis } from '@/decorators.js'; import { isNotNull } from '@/misc/is-not-null.js'; import { FilterUnionByProperty, notificationTypes } from '@/types.js'; +import { RoleEntityService } from './RoleEntityService.js'; import type { OnModuleInit } from '@nestjs/common'; -import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; @@ -27,7 +27,7 @@ const NOTE_REQUIRED_GROUPED_NOTIFICATION_TYPES = new Set(['note', 'mention', 're export class NotificationEntityService implements OnModuleInit { private userEntityService: UserEntityService; private noteEntityService: NoteEntityService; - private customEmojiService: CustomEmojiService; + private roleEntityService: RoleEntityService; constructor( private moduleRef: ModuleRef, @@ -43,14 +43,13 @@ export class NotificationEntityService implements OnModuleInit { //private userEntityService: UserEntityService, //private noteEntityService: NoteEntityService, - //private customEmojiService: CustomEmojiService, ) { } onModuleInit() { this.userEntityService = this.moduleRef.get('UserEntityService'); this.noteEntityService = this.moduleRef.get('NoteEntityService'); - this.customEmojiService = this.moduleRef.get('CustomEmojiService'); + this.roleEntityService = this.moduleRef.get('RoleEntityService'); } @bindThis @@ -81,6 +80,7 @@ export class NotificationEntityService implements OnModuleInit { detail: false, }) ) : undefined; + const role = notification.type === 'roleAssigned' ? await this.roleEntityService.pack(notification.roleId) : undefined; return await awaitAll({ id: notification.id, @@ -92,6 +92,9 @@ export class NotificationEntityService implements OnModuleInit { ...(notification.type === 'reaction' ? { reaction: notification.reaction, } : {}), + ...(notification.type === 'roleAssigned' ? { + role: role, + } : {}), ...(notification.type === 'achievementEarned' ? { achievement: notification.achievement, } : {}), diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index 1d5fc124e..3bc2edaa0 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -3,11 +3,10 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { notificationTypes } from '@/types.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; -import { MiFollowRequest } from './FollowRequest.js'; import { MiAccessToken } from './AccessToken.js'; +import { MiRole } from './Role.js'; export type MiNotification = { type: 'note'; @@ -68,6 +67,11 @@ export type MiNotification = { id: string; createdAt: string; notifierId: MiUser['id']; +} | { + type: 'roleAssigned'; + id: string; + createdAt: string; + roleId: MiRole['id']; } | { type: 'achievementEarned'; id: string; diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 1b86b1bf1..6a0d43b1a 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -554,9 +554,7 @@ export const packedMeDetailedOnlySchema = { mention: notificationRecieveConfig, reaction: notificationRecieveConfig, pollEnded: notificationRecieveConfig, - achievementEarned: notificationRecieveConfig, receiveFollowRequest: notificationRecieveConfig, - followRequestAccepted: notificationRecieveConfig, }, }, emailNotificationTypes: { diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index e085407de..361a4931e 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -14,11 +14,26 @@ * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * receiveFollowRequest - フォローリクエストされた * followRequestAccepted - 自分の送ったフォローリクエストが承認された + * roleAssigned - ロールが付与された * achievementEarned - 実績を獲得 * app - アプリ通知 * test - テスト通知(サーバー側) */ -export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app', 'test'] as const; +export const notificationTypes = [ + 'note', + 'follow', + 'mention', + 'reply', + 'renote', + 'quote', + 'reaction', + 'pollEnded', + 'receiveFollowRequest', + 'followRequestAccepted', + 'roleAssigned', + 'achievementEarned', + 'app', + 'test'] as const; export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index f644312bc..99c691211 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -19,6 +19,7 @@ import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { sleep } from '../utils.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; @@ -32,6 +33,7 @@ describe('RoleService', () => { let rolesRepository: RolesRepository; let roleAssignmentsRepository: RoleAssignmentsRepository; let metaService: jest.Mocked; + let notificationService: jest.Mocked; let clock: lolex.InstalledClock; function createUser(data: Partial = {}) { @@ -76,6 +78,8 @@ describe('RoleService', () => { .useMocker((token) => { if (token === MetaService) { return { fetch: jest.fn() }; + } else if (token === NotificationService) { + return { createNotification: jest.fn() }; } if (typeof token === 'function') { const mockMetadata = moduleMocker.getMetadata(token) as MockFunctionMetadata; @@ -93,6 +97,7 @@ describe('RoleService', () => { roleAssignmentsRepository = app.get(DI.roleAssignmentsRepository); metaService = app.get(MetaService) as jest.Mocked; + notificationService = app.get(NotificationService) as jest.Mocked; }); afterEach(async () => { @@ -273,4 +278,53 @@ describe('RoleService', () => { expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true); }); }); + + describe('assign', () => { + test('公開ロールの場合は通知される', async () => { + const user = await createUser(); + const role = await createRole({ + isPublic: true, + }); + + await roleService.assign(user.id, role.id); + + await sleep(100); + + const assignments = await roleAssignmentsRepository.find({ + where: { + userId: user.id, + roleId: role.id, + }, + }); + expect(assignments).toHaveLength(1); + + expect(notificationService.createNotification).toHaveBeenCalled(); + expect(notificationService.createNotification.mock.lastCall![0]).toBe(user.id); + expect(notificationService.createNotification.mock.lastCall![1]).toBe('roleAssigned'); + expect(notificationService.createNotification.mock.lastCall![2]).toBe({ + roleId: role.id, + }); + }); + + test('非公開ロールの場合は通知されない', async () => { + const user = await createUser(); + const role = await createRole({ + isPublic: false, + }); + + await roleService.assign(user.id, role.id); + + await sleep(100); + + const assignments = await roleAssignmentsRepository.find({ + where: { + userId: user.id, + roleId: role.id, + }, + }); + expect(assignments).toHaveLength(1); + + expect(notificationService.createNotification).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index fcf479124..2b9af2665 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -8,6 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+
@@ -36,6 +37,7 @@ SPDX-License-Identifier: AGPL-3.0-only + {{ i18n.ts._notification.pollEnded }} {{ i18n.ts._notification.newNote }}: + {{ i18n.ts._notification.roleAssigned }} {{ i18n.ts._notification.achievementEarned }} {{ i18n.ts._notification.testNotification }} @@ -86,6 +89,9 @@ SPDX-License-Identifier: AGPL-3.0-only +
+ {{ notification.role.name }} +
{{ i18n.ts._achievements._types['_' + notification.achievement].title }} diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts index f016b7aa0..01c224ae2 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend/src/const.ts @@ -54,7 +54,21 @@ https://github.com/sindresorhus/file-type/blob/main/core.js https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers */ -export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] as const; +export const notificationTypes = [ + 'note', + 'follow', + 'mention', + 'reply', + 'renote', + 'quote', + 'reaction', + 'pollEnded', + 'receiveFollowRequest', + 'followRequestAccepted', + 'roleAssigned', + 'achievementEarned', + 'app', +] as const; export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const; export const ROLE_POLICIES = [ diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue index 394e428ed..def8fd3e6 100644 --- a/packages/frontend/src/pages/settings/notifications.vue +++ b/packages/frontend/src/pages/settings/notifications.vue @@ -68,7 +68,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkPushNotificationAllowButton from '@/components/MkPushNotificationAllowButton.vue'; import { notificationTypes } from '@/const.js'; -const nonConfigurableNotificationTypes = ['note']; +const nonConfigurableNotificationTypes = ['note', 'roleAssigned', 'followRequestAccepted', 'achievementEarned']; const allowButton = shallowRef>(); const pushRegistrationInServer = computed(() => allowButton.value?.pushRegistrationInServer); diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index abb3cae4b..ea4e0c416 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1635,9 +1635,6 @@ type FetchLike = (input: string, init?: { // @public (undocumented) type FetchRssRequest = operations['fetch-rss']['requestBody']['content']['application/json']; -// @public (undocumented) -export const ffVisibility: readonly ["public", "followers", "private"]; - // @public (undocumented) type Flash = components['schemas']['Flash']; @@ -1677,6 +1674,9 @@ type FlashUnlikeRequest = operations['flash/unlike']['requestBody']['content'][' // @public (undocumented) type FlashUpdateRequest = operations['flash/update']['requestBody']['content']['application/json']; +// @public (undocumented) +export const followersVisibilities: readonly ["public", "followers", "private"]; + // @public (undocumented) type Following = components['schemas']['Following']; @@ -1725,6 +1725,9 @@ type FollowingUpdateRequest = operations['following/update']['requestBody']['con // @public (undocumented) type FollowingUpdateResponse = operations['following/update']['responses']['200']['content']['application/json']; +// @public (undocumented) +export const followingVisibilities: readonly ["public", "followers", "private"]; + // @public (undocumented) type GalleryFeaturedRequest = operations['gallery/featured']['requestBody']['content']['application/json']; @@ -2337,7 +2340,7 @@ type Notification_2 = components['schemas']['Notification']; type NotificationsCreateRequest = operations['notifications/create']['requestBody']['content']['application/json']; // @public (undocumented) -export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "achievementEarned"]; +export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "achievementEarned"]; // @public (undocumented) type Page = components['schemas']['Page']; diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index 83d313a5f..e769bb9e6 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -1,4 +1,4 @@ -export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'achievementEarned'] as const; +export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; From b3ab96b5ee9e84a3393c20f917ebf7f1fa178347 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2023 11:23:31 +0900 Subject: [PATCH 04/23] =?UTF-8?q?fix(backend):=20=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=82=A2=E3=82=B5=E3=82=A4=E3=83=B3=E3=81=AE=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E3=81=8C=E3=81=82=E3=82=8B=E7=8A=B6=E6=85=8B=E3=81=A7?= =?UTF-8?q?=E3=83=9A=E3=83=BC=E3=82=B8=E3=82=92=E3=83=AA=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=81=99=E3=82=8B=E3=81=A8=E9=80=9A=E7=9F=A5=E6=AC=84?= =?UTF-8?q?=E3=81=AB=E4=BD=95=E3=82=82=E3=81=A7=E3=81=AA=E3=81=8F=E3=81=AA?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #12729 --- .../backend/src/core/entities/NotificationEntityService.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index f2124998a..704081ed0 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -219,6 +219,8 @@ export class NotificationEntityService implements OnModuleInit { }); } + const role = notification.type === 'roleAssigned' ? await this.roleEntityService.pack(notification.roleId) : undefined; + return await awaitAll({ id: notification.id, createdAt: new Date(notification.createdAt).toISOString(), @@ -229,6 +231,9 @@ export class NotificationEntityService implements OnModuleInit { ...(notification.type === 'reaction' ? { reaction: notification.reaction, } : {}), + ...(notification.type === 'roleAssigned' ? { + role: role, + } : {}), ...(notification.type === 'achievementEarned' ? { achievement: notification.achievement, } : {}), From c307dd4fe8a48d4b95fea916d7a449a19adee22b Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2023 11:26:41 +0900 Subject: [PATCH 05/23] perf(frontend): import snowfall-effect dynamically to reduce bundle size --- packages/frontend/src/boot/main-boot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index e3fd6d5fc..8826413f4 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -20,7 +20,6 @@ import { mainRouter } from '@/router.js'; import { initializeSw } from '@/scripts/initialize-sw.js'; import { deckStore } from '@/ui/deck/deck-store.js'; import { emojiPicker } from '@/scripts/emoji-picker.js'; -import { SnowfallEffect } from '@/scripts/snowfall-effect.js'; export async function mainBoot() { const { isClientUpdated } = await common(() => createApp( @@ -79,6 +78,7 @@ export async function mainBoot() { if (defaultStore.state.enableSeasonalScreenEffect) { const month = new Date().getMonth() + 1; if (month === 12 || month === 1) { + const SnowfallEffect = (await import('@/scripts/snowfall-effect.js')).SnowfallEffect; new SnowfallEffect().render(); } } From 757dee5664fbeb9c5f67d4b0e38d13ab2bbd8688 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Dec 2023 11:28:30 +0900 Subject: [PATCH 06/23] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a62cbefa..819c65520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ - Enhance: アイコンデコレーションを複数設定できるように - Enhance: アイコンデコレーションの位置を微調整できるように - Enhance: つながりの公開範囲をフォロー/フォロワーで個別に設定可能に #12072 +- Enhance: ローカリゼーションの更新 +- Enhance: 依存関係の更新 - Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正 ### Client From b2254a66d32bf553a16af3b584e6c5a69e64efc4 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Thu, 21 Dec 2023 11:34:19 +0900 Subject: [PATCH 07/23] chore: remove hashtag from featured immediately (#12668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: remove hashtag from featured immediately * docs(changelog): ハッシュタグのトレンド除外設定が即時に効果を持つように修正 --------- Co-authored-by: syuilo --- CHANGELOG.md | 1 + packages/backend/src/core/FeaturedService.ts | 16 +++++++++++++ packages/backend/src/core/MetaService.ts | 25 +++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 819c65520..f535aa3d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,7 @@ - Fix: 「みつける」が年越し時に壊れる問題を修正 - Fix: アカウントをブロックした際に、自身のユーザーのページでノートが相手に表示される問題を修正 - Fix: モデレーションログがモデレーターは閲覧できないように修正 +- Fix: ハッシュタグのトレンド除外設定が即時に効果を持つように修正 - Fix: HTTP Digestヘッダのアルゴリズム部分に大文字の"SHA-256"しか使えない - Fix: 管理者用APIのアクセス権限が適切に設定されていない問題を修正 diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts index d970ffa43..595383c82 100644 --- a/packages/backend/src/core/FeaturedService.ts +++ b/packages/backend/src/core/FeaturedService.ts @@ -77,6 +77,17 @@ export class FeaturedService { return Array.from(ranking.keys()); } + @bindThis + private async removeFromRanking(name: string, windowRange: number, element: string): Promise { + const currentWindow = this.getCurrentWindow(windowRange); + const previousWindow = currentWindow - 1; + + const redisPipeline = this.redisClient.pipeline(); + redisPipeline.zrem(`${name}:${currentWindow}`, element); + redisPipeline.zrem(`${name}:${previousWindow}`, element); + await redisPipeline.exec(); + } + @bindThis public updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise { return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score); @@ -126,4 +137,9 @@ export class FeaturedService { public getHashtagsRanking(threshold: number): Promise { return this.getRankingOf('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, threshold); } + + @bindThis + public removeHashtagsFromRanking(hashtag: string): Promise { + return this.removeFromRanking('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, hashtag); + } } diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index 508544dc0..80e802096 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -11,6 +11,7 @@ import { MiMeta } from '@/models/Meta.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { bindThis } from '@/decorators.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import { FeaturedService } from '@/core/FeaturedService.js'; import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() @@ -25,6 +26,7 @@ export class MetaService implements OnApplicationShutdown { @Inject(DI.db) private db: DataSource, + private featuredService: FeaturedService, private globalEventService: GlobalEventService, ) { //this.onMessage = this.onMessage.bind(this); @@ -95,6 +97,8 @@ export class MetaService implements OnApplicationShutdown { @bindThis public async update(data: Partial): Promise { + let before: MiMeta | undefined; + const updated = await this.db.transaction(async transactionalEntityManager => { const metas = await transactionalEntityManager.find(MiMeta, { order: { @@ -102,10 +106,10 @@ export class MetaService implements OnApplicationShutdown { }, }); - const meta = metas[0]; + before = metas[0]; - if (meta) { - await transactionalEntityManager.update(MiMeta, meta.id, data); + if (before) { + await transactionalEntityManager.update(MiMeta, before.id, data); const metas = await transactionalEntityManager.find(MiMeta, { order: { @@ -119,6 +123,21 @@ export class MetaService implements OnApplicationShutdown { } }); + if (data.hiddenTags) { + process.nextTick(() => { + const hiddenTags = new Set(data.hiddenTags); + if (before) { + for (const previousHiddenTag of before.hiddenTags) { + hiddenTags.delete(previousHiddenTag); + } + } + + for (const hiddenTag of hiddenTags) { + this.featuredService.removeHashtagsFromRanking(hiddenTag); + } + }); + } + this.globalEventService.publishInternalEvent('metaUpdated', updated); return updated; From c92508a57588f9237ec61a17b521e45e73672393 Mon Sep 17 00:00:00 2001 From: woxtu Date: Thu, 21 Dec 2023 11:36:45 +0900 Subject: [PATCH 08/23] Remove unused imports (#12730) --- packages/frontend/src/boot/common.ts | 8 ++++---- packages/frontend/src/boot/main-boot.ts | 8 ++++---- packages/frontend/src/boot/sub-boot.ts | 2 +- packages/frontend/src/components/MkColorInput.vue | 3 +-- packages/frontend/src/components/MkMediaBanner.vue | 2 +- packages/frontend/src/components/MkMenu.vue | 2 +- packages/frontend/src/components/MkNote.vue | 2 +- packages/frontend/src/components/MkNoteDetailed.vue | 3 +-- packages/frontend/src/components/MkNoteSimple.vue | 1 - packages/frontend/src/components/MkNoteSub.vue | 1 - packages/frontend/src/components/MkNotification.vue | 2 +- packages/frontend/src/components/MkNotifications.vue | 5 ++--- packages/frontend/src/components/MkPullToRefresh.vue | 3 +-- .../frontend/src/components/MkSignupDialog.form.vue | 1 - .../frontend/src/components/MkSignupDialog.rules.vue | 2 +- packages/frontend/src/components/MkSignupDialog.vue | 1 - packages/frontend/src/components/MkSubNoteContent.vue | 1 - .../src/components/MkUserSetupDialog.Follow.vue | 6 ------ .../src/components/MkUserSetupDialog.Privacy.vue | 4 +--- .../src/components/MkUserSetupDialog.Profile.vue | 3 +-- .../src/components/MkUserSetupDialog.User.vue | 1 - .../frontend/src/components/MkVisitorDashboard.vue | 2 -- packages/frontend/src/components/form/suspense.vue | 1 - packages/frontend/src/components/global/MkA.vue | 1 - .../src/components/global/MkAd.stories.impl.ts | 3 --- .../src/components/global/MkUserName.stories.impl.ts | 1 - packages/frontend/src/components/page/page.text.vue | 1 - packages/frontend/src/components/page/page.vue | 1 - packages/frontend/src/pages/admin-user.vue | 4 ++-- packages/frontend/src/pages/admin/branding.vue | 3 --- packages/frontend/src/pages/admin/moderation.vue | 2 -- packages/frontend/src/pages/admin/modlog.ModLog.vue | 2 -- packages/frontend/src/pages/admin/roles.role.vue | 2 +- packages/frontend/src/pages/ads.vue | 2 -- packages/frontend/src/pages/avatar-decorations.vue | 3 --- packages/frontend/src/pages/custom-emojis-manager.vue | 2 +- packages/frontend/src/pages/emoji-edit-dialog.vue | 2 +- packages/frontend/src/pages/my-lists/list.vue | 2 +- .../src/pages/page-editor/page-editor.container.vue | 1 - packages/frontend/src/pages/search.note.vue | 6 +----- packages/frontend/src/pages/search.user.vue | 5 +---- packages/frontend/src/pages/search.vue | 3 +-- packages/frontend/src/pages/settings/2fa.vue | 2 +- .../src/pages/settings/avatar-decoration.dialog.vue | 3 --- .../frontend/src/pages/settings/drive-cleaner.vue | 1 - packages/frontend/src/pages/settings/navbar.vue | 1 - .../frontend/src/pages/settings/notifications.vue | 2 +- packages/frontend/src/pages/settings/profile.vue | 2 -- packages/frontend/src/pages/settings/roles.vue | 11 +---------- packages/frontend/src/pages/timeline.vue | 1 - packages/frontend/src/pages/user-tag.vue | 3 +-- packages/frontend/src/pages/user/home.vue | 1 - packages/frontend/src/pages/welcome.entrance.a.vue | 6 ------ packages/frontend/src/pages/welcome.timeline.vue | 1 - packages/frontend/src/scripts/emoji-picker.ts | 2 +- packages/frontend/src/ui/classic.sidebar.vue | 2 +- packages/frontend/src/ui/classic.vue | 2 +- packages/frontend/src/ui/deck.vue | 1 - packages/frontend/src/ui/visitor.vue | 2 +- packages/frontend/src/widgets/WidgetActivity.vue | 2 +- packages/frontend/src/widgets/WidgetAichan.vue | 2 +- packages/frontend/src/widgets/WidgetAiscript.vue | 2 +- packages/frontend/src/widgets/WidgetAiscriptApp.vue | 2 +- packages/frontend/src/widgets/WidgetButton.vue | 2 +- packages/frontend/src/widgets/WidgetCalendar.vue | 2 +- packages/frontend/src/widgets/WidgetClicker.vue | 2 +- packages/frontend/src/widgets/WidgetClock.vue | 2 +- packages/frontend/src/widgets/WidgetDigitalClock.vue | 2 +- packages/frontend/src/widgets/WidgetFederation.vue | 2 +- packages/frontend/src/widgets/WidgetInstanceCloud.vue | 2 +- packages/frontend/src/widgets/WidgetInstanceInfo.vue | 2 +- packages/frontend/src/widgets/WidgetJobQueue.vue | 2 +- packages/frontend/src/widgets/WidgetMemo.vue | 2 +- packages/frontend/src/widgets/WidgetNotifications.vue | 2 +- packages/frontend/src/widgets/WidgetOnlineUsers.vue | 2 +- packages/frontend/src/widgets/WidgetPhotos.vue | 2 +- packages/frontend/src/widgets/WidgetPostForm.vue | 2 +- packages/frontend/src/widgets/WidgetProfile.vue | 2 +- packages/frontend/src/widgets/WidgetRss.vue | 2 +- packages/frontend/src/widgets/WidgetRssTicker.vue | 2 +- packages/frontend/src/widgets/WidgetSlideshow.vue | 2 +- packages/frontend/src/widgets/WidgetTimeline.vue | 2 +- packages/frontend/src/widgets/WidgetTrends.vue | 2 +- packages/frontend/src/widgets/WidgetUnixClock.vue | 2 +- packages/frontend/src/widgets/WidgetUserList.vue | 2 +- 85 files changed, 64 insertions(+), 141 deletions(-) diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index b0825ef11..ef69eff76 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -3,16 +3,16 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent, App } from 'vue'; +import { computed, watch, version as vueVersion, App } from 'vue'; import { compareVersions } from 'compare-versions'; import widgets from '@/widgets/index.js'; import directives from '@/directives/index.js'; import components from '@/components/index.js'; -import { version, ui, lang, updateLocale, locale } from '@/config.js'; +import { version, lang, updateLocale, locale } from '@/config.js'; import { applyTheme } from '@/scripts/theme.js'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js'; -import { i18n, updateI18n } from '@/i18n.js'; -import { $i, refreshAccount, login, updateAccount, signout } from '@/account.js'; +import { updateI18n } from '@/i18n.js'; +import { $i, refreshAccount, login } from '@/account.js'; import { defaultStore, ColdDeviceStorage } from '@/store.js'; import { fetchInstance, instance } from '@/instance.js'; import { deviceKind } from '@/scripts/device-kind.js'; diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 8826413f4..0159d0c03 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -3,14 +3,14 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent } from 'vue'; +import { createApp, markRaw, defineAsyncComponent } from 'vue'; import { common } from './common.js'; -import { version, ui, lang, updateLocale } from '@/config.js'; -import { i18n, updateI18n } from '@/i18n.js'; +import { ui } from '@/config.js'; +import { i18n } from '@/i18n.js'; import { confirm, alert, post, popup, toast } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/scripts/sound.js'; -import { $i, refreshAccount, login, updateAccount, signout } from '@/account.js'; +import { $i, updateAccount, signout } from '@/account.js'; import { defaultStore, ColdDeviceStorage } from '@/store.js'; import { makeHotkey } from '@/scripts/hotkey.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; diff --git a/packages/frontend/src/boot/sub-boot.ts b/packages/frontend/src/boot/sub-boot.ts index 9b4670e13..92ee074af 100644 --- a/packages/frontend/src/boot/sub-boot.ts +++ b/packages/frontend/src/boot/sub-boot.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { computed, createApp, watch, markRaw, version as vueVersion, defineAsyncComponent } from 'vue'; +import { createApp, defineAsyncComponent } from 'vue'; import { common } from './common.js'; export async function subBoot() { diff --git a/packages/frontend/src/components/MkColorInput.vue b/packages/frontend/src/components/MkColorInput.vue index 983a35103..a7a3eff5a 100644 --- a/packages/frontend/src/components/MkColorInput.vue +++ b/packages/frontend/src/components/MkColorInput.vue @@ -24,8 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index c245b9b6c..20c65f454 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts._aboutMisskey.about }}
{{ i18n.ts.learnMore }} + {{ i18n.ts._aboutMisskey.about }}
{{ i18n.ts.learnMore }}
I #Misskey @@ -139,73 +139,73 @@ import { $i } from '@/account.js'; const patronsWithIcon = [{ name: 'カイヤン', - icon: 'https://misskey-hub.net/patrons/a2820716883e408cb87773e377ce7c8d.jpg', + icon: 'https://assets.misskey-hub.net/patrons/a2820716883e408cb87773e377ce7c8d.jpg', }, { name: 'だれかさん', - icon: 'https://misskey-hub.net/patrons/f7409b5e5a88477a9b9d740c408de125.jpg', + icon: 'https://assets.misskey-hub.net/patrons/f7409b5e5a88477a9b9d740c408de125.jpg', }, { name: 'narazaka', - icon: 'https://misskey-hub.net/patrons/e3affff31ffb4877b1196c7360abc3e5.jpg', + icon: 'https://assets.misskey-hub.net/patrons/e3affff31ffb4877b1196c7360abc3e5.jpg', }, { name: 'ひとぅ', - icon: 'https://misskey-hub.net/patrons/8cc0d0a0a6d84c88bca1aedabf6ed5ab.jpg', + icon: 'https://assets.misskey-hub.net/patrons/8cc0d0a0a6d84c88bca1aedabf6ed5ab.jpg', }, { name: 'ぱーこ', - icon: 'https://misskey-hub.net/patrons/79c6602ffade489e8df2fcf2c2bc5d9d.jpg', + icon: 'https://assets.misskey-hub.net/patrons/79c6602ffade489e8df2fcf2c2bc5d9d.jpg', }, { name: 'わっほー☆', - icon: 'https://misskey-hub.net/patrons/d31d5d13924443a082f3da7966318a0a.jpg', + icon: 'https://assets.misskey-hub.net/patrons/d31d5d13924443a082f3da7966318a0a.jpg', }, { name: 'mollinaca', - icon: 'https://misskey-hub.net/patrons/ceb36b8f66e549bdadb3b90d5da62314.jpg', + icon: 'https://assets.misskey-hub.net/patrons/ceb36b8f66e549bdadb3b90d5da62314.jpg', }, { name: '坂本龍', - icon: 'https://misskey-hub.net/patrons/a631cf8b490145cf8dbbe4e7508cfbc2.jpg', + icon: 'https://assets.misskey-hub.net/patrons/a631cf8b490145cf8dbbe4e7508cfbc2.jpg', }, { name: 'takke', - icon: 'https://misskey-hub.net/patrons/6c3327e626c046f2914fbcd9f7557935.jpg', + icon: 'https://assets.misskey-hub.net/patrons/6c3327e626c046f2914fbcd9f7557935.jpg', }, { name: 'ぺんぎん', - icon: 'https://misskey-hub.net/patrons/6a652e0534ff4cb1836e7ce4968d76a7.jpg', + icon: 'https://assets.misskey-hub.net/patrons/6a652e0534ff4cb1836e7ce4968d76a7.jpg', }, { name: 'かみらえっと', - icon: 'https://misskey-hub.net/patrons/be1326bda7d940a482f3758ffd9ffaf6.jpg', + icon: 'https://assets.misskey-hub.net/patrons/be1326bda7d940a482f3758ffd9ffaf6.jpg', }, { name: 'へてて', - icon: 'https://misskey-hub.net/patrons/0431eacd7c6843d09de8ea9984307e86.jpg', + icon: 'https://assets.misskey-hub.net/patrons/0431eacd7c6843d09de8ea9984307e86.jpg', }, { name: 'spinlock', - icon: 'https://misskey-hub.net/patrons/6a1cebc819d540a78bf20e9e3115baa8.jpg', + icon: 'https://assets.misskey-hub.net/patrons/6a1cebc819d540a78bf20e9e3115baa8.jpg', }, { name: 'じゅくま', - icon: 'https://misskey-hub.net/patrons/3e56bdac69dd42f7a06e0f12cf2fc895.jpg', + icon: 'https://assets.misskey-hub.net/patrons/3e56bdac69dd42f7a06e0f12cf2fc895.jpg', }, { name: '清遊あみ', - icon: 'https://misskey-hub.net/patrons/de25195b88e940a388388bea2e7637d8.jpg', + icon: 'https://assets.misskey-hub.net/patrons/de25195b88e940a388388bea2e7637d8.jpg', }, { name: 'Nagi8410', - icon: 'https://misskey-hub.net/patrons/31b102ab4fc540ed806b0461575d38be.jpg', + icon: 'https://assets.misskey-hub.net/patrons/31b102ab4fc540ed806b0461575d38be.jpg', }, { name: '山岡士郎', - icon: 'https://misskey-hub.net/patrons/84b9056341684266bb1eda3e680d094d.jpg', + icon: 'https://assets.misskey-hub.net/patrons/84b9056341684266bb1eda3e680d094d.jpg', }, { name: 'よもやまたろう', - icon: 'https://misskey-hub.net/patrons/4273c9cce50d445f8f7d0f16113d6d7f.jpg', + icon: 'https://assets.misskey-hub.net/patrons/4273c9cce50d445f8f7d0f16113d6d7f.jpg', }, { name: '花咲ももか', - icon: 'https://misskey-hub.net/patrons/8c9b2b9128cb4fee99f04bb4f86f2efa.jpg', + icon: 'https://assets.misskey-hub.net/patrons/8c9b2b9128cb4fee99f04bb4f86f2efa.jpg', }, { name: 'カガミ', - icon: 'https://misskey-hub.net/patrons/226ea3a4617749548580ec2d9a263e24.jpg', + icon: 'https://assets.misskey-hub.net/patrons/226ea3a4617749548580ec2d9a263e24.jpg', }, { name: 'フランギ・シュウ', - icon: 'https://misskey-hub.net/patrons/3016d37e35f3430b90420176c912d304.jpg', + icon: 'https://assets.misskey-hub.net/patrons/3016d37e35f3430b90420176c912d304.jpg', }, { name: '百日紅', - icon: 'https://misskey-hub.net/patrons/302dce2898dd457ba03c3f7dc037900b.jpg', + icon: 'https://assets.misskey-hub.net/patrons/302dce2898dd457ba03c3f7dc037900b.jpg', }, { name: 'taichan', - icon: 'https://misskey-hub.net/patrons/f981ab0159fb4e2c998e05f7263e1cd9.png', + icon: 'https://assets.misskey-hub.net/patrons/f981ab0159fb4e2c998e05f7263e1cd9.png', }]; const patrons = [ diff --git a/packages/frontend/src/pages/share.vue b/packages/frontend/src/pages/share.vue index 3e9cac985..cb5acf3af 100644 --- a/packages/frontend/src/pages/share.vue +++ b/packages/frontend/src/pages/share.vue @@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only