diff options
| author | Acid Chicken (硫酸鶏) <root@acid-chicken.com> | 2023-04-03 13:01:15 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-03 13:01:15 +0900 |
| commit | 8a9847b06a3b0ec7acd69258435664ab82e8a9e7 (patch) | |
| tree | 09030e98032845e75357fb00c03cd250089c3222 /packages | |
| parent | fix: the avatar in the title bar is clipped (diff) | |
| parent | Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop (diff) | |
| download | misskey-8a9847b06a3b0ec7acd69258435664ab82e8a9e7.tar.gz misskey-8a9847b06a3b0ec7acd69258435664ab82e8a9e7.tar.bz2 misskey-8a9847b06a3b0ec7acd69258435664ab82e8a9e7.zip | |
Merge branch 'develop' into acid-chicken-patch-1
Diffstat (limited to 'packages')
114 files changed, 541 insertions, 533 deletions
diff --git a/packages/backend/migration/1680491187535-cleanup.js b/packages/backend/migration/1680491187535-cleanup.js new file mode 100644 index 0000000000..1e609ca060 --- /dev/null +++ b/packages/backend/migration/1680491187535-cleanup.js @@ -0,0 +1,10 @@ +export class cleanup1680491187535 { + name = 'cleanup1680491187535' + + async up(queryRunner) { + await queryRunner.query(`DROP TABLE "antenna_note" `); + } + + async down(queryRunner) { + } +} diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index aaa26a8321..4bd3f39af2 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -12,7 +12,7 @@ import { PushNotificationService } from '@/core/PushNotificationService.js'; import * as Acct from '@/misc/acct.js'; import type { Packed } from '@/misc/json-schema.js'; import { DI } from '@/di-symbols.js'; -import type { MutingsRepository, NotesRepository, AntennaNotesRepository, AntennasRepository, UserListJoiningsRepository } from '@/models/index.js'; +import type { MutingsRepository, NotesRepository, AntennasRepository, UserListJoiningsRepository } from '@/models/index.js'; import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import { StreamMessages } from '@/server/api/stream/types.js'; @@ -24,6 +24,9 @@ export class AntennaService implements OnApplicationShutdown { private antennas: Antenna[]; constructor( + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.redisSubscriber) private redisSubscriber: Redis.Redis, @@ -33,9 +36,6 @@ export class AntennaService implements OnApplicationShutdown { @Inject(DI.notesRepository) private notesRepository: NotesRepository, - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, - @Inject(DI.antennasRepository) private antennasRepository: AntennasRepository, @@ -92,54 +92,13 @@ export class AntennaService implements OnApplicationShutdown { @bindThis public async addNoteToAntenna(antenna: Antenna, note: Note, noteUser: { id: User['id']; }): Promise<void> { - // 通知しない設定になっているか、自分自身の投稿なら既読にする - const read = !antenna.notify || (antenna.userId === noteUser.id); - - this.antennaNotesRepository.insert({ - id: this.idService.genId(), - antennaId: antenna.id, - noteId: note.id, - read: read, - }); - + this.redisClient.xadd( + `antennaTimeline:${antenna.id}`, + 'MAXLEN', '~', '200', + `${this.idService.parse(note.id).date.getTime()}-*`, + 'note', note.id); + this.globalEventService.publishAntennaStream(antenna.id, 'note', note); - - if (!read) { - const mutings = await this.mutingsRepository.find({ - where: { - muterId: antenna.userId, - }, - select: ['muteeId'], - }); - - // Copy - const _note: Note = { - ...note, - }; - - if (note.replyId != null) { - _note.reply = await this.notesRepository.findOneByOrFail({ id: note.replyId }); - } - if (note.renoteId != null) { - _note.renote = await this.notesRepository.findOneByOrFail({ id: note.renoteId }); - } - - if (isUserRelated(_note, new Set<string>(mutings.map(x => x.muteeId)))) { - return; - } - - // 2秒経っても既読にならなかったら通知 - setTimeout(async () => { - const unread = await this.antennaNotesRepository.findOneBy({ antennaId: antenna.id, read: false }); - if (unread) { - this.globalEventService.publishMainStream(antenna.userId, 'unreadAntenna', antenna); - this.pushNotificationService.pushNotification(antenna.userId, 'unreadAntennaNote', { - antenna: { id: antenna.id, name: antenna.name }, - note: await this.noteEntityService.pack(note), - }); - } - }, 2000); - } } // NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている diff --git a/packages/backend/src/core/IdService.ts b/packages/backend/src/core/IdService.ts index 31c0819e50..94084ad84f 100644 --- a/packages/backend/src/core/IdService.ts +++ b/packages/backend/src/core/IdService.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { ulid } from 'ulid'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import { genAid } from '@/misc/id/aid.js'; +import { genAid, parseAid } from '@/misc/id/aid.js'; import { genMeid } from '@/misc/id/meid.js'; import { genMeidg } from '@/misc/id/meidg.js'; import { genObjectId } from '@/misc/id/object-id.js'; @@ -32,4 +32,17 @@ export class IdService { default: throw new Error('unrecognized id generation method'); } } + + @bindThis + public parse(id: string): { date: Date; } { + switch (this.method) { + case 'aid': return parseAid(id); + // TODO + //case 'meid': + //case 'meidg': + //case 'ulid': + //case 'objectid': + default: throw new Error('unrecognized id generation method'); + } + } } diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 7d08053761..7af7099432 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -1,6 +1,7 @@ import { setImmediate } from 'node:timers/promises'; import * as mfm from 'mfm-js'; import { In, DataSource } from 'typeorm'; +import Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { extractMentions } from '@/misc/extract-mentions.js'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; @@ -150,6 +151,9 @@ export class NoteCreateService implements OnApplicationShutdown { @Inject(DI.db) private db: DataSource, + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -321,6 +325,14 @@ export class NoteCreateService implements OnApplicationShutdown { const note = await this.insertNote(user, data, tags, emojis, mentionedUsers); + if (data.channel) { + this.redisClient.xadd( + `channelTimeline:${data.channel.id}`, + 'MAXLEN', '~', '1000', + `${this.idService.parse(note.id).date.getTime()}-*`, + 'note', note.id); + } + setImmediate('post created', { signal: this.#shutdownController.signal }).then( () => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!), () => { /* aborted, ignore this */ }, diff --git a/packages/backend/src/core/NoteReadService.ts b/packages/backend/src/core/NoteReadService.ts index 22d72815ec..1bf0eb918f 100644 --- a/packages/backend/src/core/NoteReadService.ts +++ b/packages/backend/src/core/NoteReadService.ts @@ -8,7 +8,7 @@ import type { Packed } from '@/misc/json-schema.js'; import type { Note } from '@/models/entities/Note.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import type { UsersRepository, NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository, FollowingsRepository, ChannelFollowingsRepository, AntennaNotesRepository } from '@/models/index.js'; +import type { UsersRepository, NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository, FollowingsRepository, ChannelFollowingsRepository } from '@/models/index.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; import { NotificationService } from './NotificationService.js'; @@ -38,9 +38,6 @@ export class NoteReadService implements OnApplicationShutdown { @Inject(DI.channelFollowingsRepository) private channelFollowingsRepository: ChannelFollowingsRepository, - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, - private userEntityService: UserEntityService, private idService: IdService, private globalEventService: GlobalEventService, @@ -121,7 +118,6 @@ export class NoteReadService implements OnApplicationShutdown { const readMentions: (Note | Packed<'Note'>)[] = []; const readSpecifiedNotes: (Note | Packed<'Note'>)[] = []; const readChannelNotes: (Note | Packed<'Note'>)[] = []; - const readAntennaNotes: (Note | Packed<'Note'>)[] = []; for (const note of notes) { if (note.mentions && note.mentions.includes(userId)) { @@ -133,14 +129,6 @@ export class NoteReadService implements OnApplicationShutdown { if (note.channelId && followingChannels.has(note.channelId)) { readChannelNotes.push(note); } - - if (note.user != null) { // たぶんnullになることは無いはずだけど一応 - for (const antenna of myAntennas) { - if (await this.antennaService.checkHitAntenna(antenna, note, note.user)) { - readAntennaNotes.push(note); - } - } - } } if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0) || (readChannelNotes.length > 0)) { @@ -186,35 +174,6 @@ export class NoteReadService implements OnApplicationShutdown { noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id)]), }); } - - if (readAntennaNotes.length > 0) { - await this.antennaNotesRepository.update({ - antennaId: In(myAntennas.map(a => a.id)), - noteId: In(readAntennaNotes.map(n => n.id)), - }, { - read: true, - }); - - // TODO: まとめてクエリしたい - for (const antenna of myAntennas) { - const count = await this.antennaNotesRepository.countBy({ - antennaId: antenna.id, - read: false, - }); - - if (count === 0) { - this.globalEventService.publishMainStream(userId, 'readAntenna', antenna); - this.pushNotificationService.pushNotification(userId, 'readAntenna', { antennaId: antenna.id }); - } - } - - this.userEntityService.getHasUnreadAntenna(userId).then(unread => { - if (!unread) { - this.globalEventService.publishMainStream(userId, 'readAllAntennas'); - this.pushNotificationService.pushNotification(userId, 'readAllAntennas', undefined); - } - }); - } } onApplicationShutdown(signal?: string | undefined): void { diff --git a/packages/backend/src/core/VideoProcessingService.ts b/packages/backend/src/core/VideoProcessingService.ts index eccfeb0e7d..5869905db0 100644 --- a/packages/backend/src/core/VideoProcessingService.ts +++ b/packages/backend/src/core/VideoProcessingService.ts @@ -37,7 +37,7 @@ export class VideoProcessingService { }); }); - return await this.imageProcessingService.convertToWebp(`${dir}/out.png`, 498, 280); + return await this.imageProcessingService.convertToWebp(`${dir}/out.png`, 498, 422); } finally { cleanup(); } diff --git a/packages/backend/src/core/entities/AntennaEntityService.ts b/packages/backend/src/core/entities/AntennaEntityService.ts index e02daefd64..328511f5df 100644 --- a/packages/backend/src/core/entities/AntennaEntityService.ts +++ b/packages/backend/src/core/entities/AntennaEntityService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import type { AntennaNotesRepository, AntennasRepository } from '@/models/index.js'; +import type { AntennasRepository } from '@/models/index.js'; import type { Packed } from '@/misc/json-schema.js'; import type { Antenna } from '@/models/entities/Antenna.js'; import { bindThis } from '@/decorators.js'; @@ -10,9 +10,6 @@ export class AntennaEntityService { constructor( @Inject(DI.antennasRepository) private antennasRepository: AntennasRepository, - - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, ) { } @@ -22,8 +19,6 @@ export class AntennaEntityService { ): Promise<Packed<'Antenna'>> { const antenna = typeof src === 'object' ? src : await this.antennasRepository.findOneByOrFail({ id: src }); - const hasUnreadNote = (await this.antennaNotesRepository.findOneBy({ antennaId: antenna.id, read: false })) != null; - return { id: antenna.id, createdAt: antenna.createdAt.toISOString(), @@ -38,7 +33,7 @@ export class AntennaEntityService { withReplies: antenna.withReplies, withFile: antenna.withFile, isActive: antenna.isActive, - hasUnreadNote, + hasUnreadNote: false, // TODO }; } } diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index b693883e06..61fd6f2f66 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -12,7 +12,7 @@ import { KVCache } from '@/misc/cache.js'; import type { Instance } from '@/models/entities/Instance.js'; import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js'; import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js'; -import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, AnnouncementsRepository, AntennaNotesRepository, PagesRepository, UserProfile, RenoteMutingsRepository } from '@/models/index.js'; +import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, NotificationsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, AnnouncementsRepository, PagesRepository, UserProfile, RenoteMutingsRepository } from '@/models/index.js'; import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import type { OnModuleInit } from '@nestjs/common'; @@ -108,9 +108,6 @@ export class UserEntityService implements OnModuleInit { @Inject(DI.announcementsRepository) private announcementsRepository: AnnouncementsRepository, - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, - @Inject(DI.pagesRepository) private pagesRepository: PagesRepository, @@ -223,6 +220,7 @@ export class UserEntityService implements OnModuleInit { @bindThis public async getHasUnreadAntenna(userId: User['id']): Promise<boolean> { + /* const myAntennas = (await this.antennaService.getAntennas()).filter(a => a.userId === userId); const unread = myAntennas.length > 0 ? await this.antennaNotesRepository.findOneBy({ @@ -231,6 +229,8 @@ export class UserEntityService implements OnModuleInit { }) : null; return unread != null; + */ + return false; // TODO } @bindThis diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 4f475a03ad..f2ab6cb864 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -54,7 +54,6 @@ export const DI = { clipNotesRepository: Symbol('clipNotesRepository'), clipFavoritesRepository: Symbol('clipFavoritesRepository'), antennasRepository: Symbol('antennasRepository'), - antennaNotesRepository: Symbol('antennaNotesRepository'), promoNotesRepository: Symbol('promoNotesRepository'), promoReadsRepository: Symbol('promoReadsRepository'), relaysRepository: Symbol('relaysRepository'), diff --git a/packages/backend/src/misc/id/aid.ts b/packages/backend/src/misc/id/aid.ts index 19c8546f95..93a9929aa7 100644 --- a/packages/backend/src/misc/id/aid.ts +++ b/packages/backend/src/misc/id/aid.ts @@ -23,3 +23,8 @@ export function genAid(date: Date): string { counter++; return getTime(t) + getNoise(); } + +export function parseAid(id: string): { date: Date; } { + const time = parseInt(id.slice(0, 8), 36) + TIME2000; + return { date: new Date(time) }; +} diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index da7faf9ffb..b74ee3689c 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { User, Note, Announcement, AnnouncementRead, App, NoteFavorite, NoteThreadMuting, NoteReaction, NoteUnread, Notification, Poll, PollVote, UserProfile, UserKeypair, UserPending, AttestationChallenge, UserSecurityKey, UserPublickey, UserList, UserListJoining, UserNotePining, UserIp, UsedUsername, Following, FollowRequest, Instance, Emoji, DriveFile, DriveFolder, Meta, Muting, RenoteMuting, Blocking, SwSubscription, Hashtag, AbuseUserReport, RegistrationTicket, AuthSession, AccessToken, Signin, Page, PageLike, GalleryPost, GalleryLike, ModerationLog, Clip, ClipNote, Antenna, AntennaNote, PromoNote, PromoRead, Relay, MutedNote, Channel, ChannelFollowing, ChannelFavorite, RegistryItem, Webhook, Ad, PasswordResetRequest, RetentionAggregation, FlashLike, Flash, Role, RoleAssignment, ClipFavorite } from './index.js'; +import { User, Note, Announcement, AnnouncementRead, App, NoteFavorite, NoteThreadMuting, NoteReaction, NoteUnread, Notification, Poll, PollVote, UserProfile, UserKeypair, UserPending, AttestationChallenge, UserSecurityKey, UserPublickey, UserList, UserListJoining, UserNotePining, UserIp, UsedUsername, Following, FollowRequest, Instance, Emoji, DriveFile, DriveFolder, Meta, Muting, RenoteMuting, Blocking, SwSubscription, Hashtag, AbuseUserReport, RegistrationTicket, AuthSession, AccessToken, Signin, Page, PageLike, GalleryPost, GalleryLike, ModerationLog, Clip, ClipNote, Antenna, PromoNote, PromoRead, Relay, MutedNote, Channel, ChannelFollowing, ChannelFavorite, RegistryItem, Webhook, Ad, PasswordResetRequest, RetentionAggregation, FlashLike, Flash, Role, RoleAssignment, ClipFavorite } from './index.js'; import type { DataSource } from 'typeorm'; import type { Provider } from '@nestjs/common'; @@ -298,12 +298,6 @@ const $antennasRepository: Provider = { inject: [DI.db], }; -const $antennaNotesRepository: Provider = { - provide: DI.antennaNotesRepository, - useFactory: (db: DataSource) => db.getRepository(AntennaNote), - inject: [DI.db], -}; - const $promoNotesRepository: Provider = { provide: DI.promoNotesRepository, useFactory: (db: DataSource) => db.getRepository(PromoNote), @@ -453,7 +447,6 @@ const $roleAssignmentsRepository: Provider = { $clipNotesRepository, $clipFavoritesRepository, $antennasRepository, - $antennaNotesRepository, $promoNotesRepository, $promoReadsRepository, $relaysRepository, @@ -521,7 +514,6 @@ const $roleAssignmentsRepository: Provider = { $clipNotesRepository, $clipFavoritesRepository, $antennasRepository, - $antennaNotesRepository, $promoNotesRepository, $promoReadsRepository, $relaysRepository, diff --git a/packages/backend/src/models/entities/AntennaNote.ts b/packages/backend/src/models/entities/AntennaNote.ts deleted file mode 100644 index 5524a89367..0000000000 --- a/packages/backend/src/models/entities/AntennaNote.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; -import { Note } from './Note.js'; -import { Antenna } from './Antenna.js'; - -@Entity() -@Index(['noteId', 'antennaId'], { unique: true }) -export class AntennaNote { - @PrimaryColumn(id()) - public id: string; - - @Index() - @Column({ - ...id(), - comment: 'The note ID.', - }) - public noteId: Note['id']; - - @ManyToOne(type => Note, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public note: Note | null; - - @Index() - @Column({ - ...id(), - comment: 'The antenna ID.', - }) - public antennaId: Antenna['id']; - - @ManyToOne(type => Antenna, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public antenna: Antenna | null; - - @Index() - @Column('boolean', { - default: false, - }) - public read: boolean; -} diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 79bd014cea..c4c9717ed5 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -4,7 +4,6 @@ import { Ad } from '@/models/entities/Ad.js'; import { Announcement } from '@/models/entities/Announcement.js'; import { AnnouncementRead } from '@/models/entities/AnnouncementRead.js'; import { Antenna } from '@/models/entities/Antenna.js'; -import { AntennaNote } from '@/models/entities/AntennaNote.js'; import { App } from '@/models/entities/App.js'; import { AttestationChallenge } from '@/models/entities/AttestationChallenge.js'; import { AuthSession } from '@/models/entities/AuthSession.js'; @@ -73,7 +72,6 @@ export { Announcement, AnnouncementRead, Antenna, - AntennaNote, App, AttestationChallenge, AuthSession, @@ -141,7 +139,6 @@ export type AdsRepository = Repository<Ad>; export type AnnouncementsRepository = Repository<Announcement>; export type AnnouncementReadsRepository = Repository<AnnouncementRead>; export type AntennasRepository = Repository<Antenna>; -export type AntennaNotesRepository = Repository<AntennaNote>; export type AppsRepository = Repository<App>; export type AttestationChallengesRepository = Repository<AttestationChallenge>; export type AuthSessionsRepository = Repository<AuthSession>; diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index cbe3814a24..024aa114fc 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -12,7 +12,6 @@ import { Ad } from '@/models/entities/Ad.js'; import { Announcement } from '@/models/entities/Announcement.js'; import { AnnouncementRead } from '@/models/entities/AnnouncementRead.js'; import { Antenna } from '@/models/entities/Antenna.js'; -import { AntennaNote } from '@/models/entities/AntennaNote.js'; import { App } from '@/models/entities/App.js'; import { AttestationChallenge } from '@/models/entities/AttestationChallenge.js'; import { AuthSession } from '@/models/entities/AuthSession.js'; @@ -168,7 +167,6 @@ export const entities = [ ClipNote, ClipFavorite, Antenna, - AntennaNote, PromoNote, PromoRead, Relay, diff --git a/packages/backend/src/queue/processors/CleanProcessorService.ts b/packages/backend/src/queue/processors/CleanProcessorService.ts index 9534454fd7..3feb86f86f 100644 --- a/packages/backend/src/queue/processors/CleanProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanProcessorService.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In, LessThan } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { AntennaNotesRepository, AntennasRepository, MutedNotesRepository, NotificationsRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/index.js'; +import type { AntennasRepository, MutedNotesRepository, NotificationsRepository, RoleAssignmentsRepository, UserIpsRepository } from '@/models/index.js'; import type { Config } from '@/config.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; @@ -29,9 +29,6 @@ export class CleanProcessorService { @Inject(DI.antennasRepository) private antennasRepository: AntennasRepository, - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, - @Inject(DI.roleAssignmentsRepository) private roleAssignmentsRepository: RoleAssignmentsRepository, diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 039ba1115a..364f9d9c05 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -1,10 +1,12 @@ import { Inject, Injectable } from '@nestjs/common'; +import Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { NotesRepository, AntennaNotesRepository, AntennasRepository } from '@/models/index.js'; +import type { NotesRepository, AntennasRepository } from '@/models/index.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteReadService } from '@/core/NoteReadService.js'; import { DI } from '@/di-symbols.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; +import { IdService } from '@/core/IdService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -50,15 +52,16 @@ export const paramDef = { @Injectable() export default class extends Endpoint<typeof meta, typeof paramDef> { constructor( + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @Inject(DI.antennasRepository) private antennasRepository: AntennasRepository, - @Inject(DI.antennaNotesRepository) - private antennaNotesRepository: AntennaNotesRepository, - + private idService: IdService, private noteEntityService: NoteEntityService, private queryService: QueryService, private noteReadService: NoteReadService, @@ -73,9 +76,24 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { throw new ApiError(meta.errors.noSuchAntenna); } - const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), - ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) - .innerJoin(this.antennaNotesRepository.metadata.targetName, 'antennaNote', 'antennaNote.noteId = note.id') + const noteIdsRes = await this.redisClient.xrevrange( + `antennaTimeline:${antenna.id}`, + ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+', + '-', + 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1 + + if (noteIdsRes.length === 0) { + return []; + } + + const noteIds = noteIdsRes.map(x => x[1][1]).filter(x => x !== ps.untilId); + + if (noteIds.length === 0) { + return []; + } + + const query = this.notesRepository.createQueryBuilder('note') + .where('note.id IN (:...noteIds)', { noteIds: noteIds }) .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('user.avatar', 'avatar') .leftJoinAndSelect('user.banner', 'banner') @@ -86,16 +104,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') - .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') - .andWhere('antennaNote.antennaId = :antennaId', { antennaId: antenna.id }); + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); this.queryService.generateVisibilityQuery(query, me); this.queryService.generateMutedUserQuery(query, me); this.queryService.generateBlockedUserQuery(query, me); - const notes = await query - .take(ps.limit) - .getMany(); + const notes = await query.getMany(); + notes.sort((a, b) => a.id > b.id ? -1 : 1); if (notes.length > 0) { this.noteReadService.read(me.id, notes); diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index cdaa400137..eef343d139 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -1,10 +1,12 @@ import { Inject, Injectable } from '@nestjs/common'; +import Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { ChannelsRepository, NotesRepository } from '@/models/index.js'; import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { DI } from '@/di-symbols.js'; +import { IdService } from '@/core/IdService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -48,12 +50,16 @@ export const paramDef = { @Injectable() export default class extends Endpoint<typeof meta, typeof paramDef> { constructor( + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.notesRepository) private notesRepository: NotesRepository, @Inject(DI.channelsRepository) private channelsRepository: ChannelsRepository, + private idService: IdService, private noteEntityService: NoteEntityService, private queryService: QueryService, private activeUsersChart: ActiveUsersChart, @@ -67,9 +73,25 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { throw new ApiError(meta.errors.noSuchChannel); } + const noteIdsRes = await this.redisClient.xrevrange( + `channelTimeline:${channel.id}`, + ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+', + '-', + 'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1 + + if (noteIdsRes.length === 0) { + return []; + } + + const noteIds = noteIdsRes.map(x => x[1][1]).filter(x => x !== ps.untilId); + + if (noteIds.length === 0) { + return []; + } + //#region Construct query - const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) - .andWhere('note.channelId = :channelId', { channelId: channel.id }) + const query = this.notesRepository.createQueryBuilder('note') + .where('note.id IN (:...noteIds)', { noteIds: noteIds }) .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('user.avatar', 'avatar') .leftJoinAndSelect('user.banner', 'banner') @@ -90,7 +112,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { } //#endregion - const timeline = await query.take(ps.limit).getMany(); + const timeline = await query.getMany(); + timeline.sort((a, b) => a.id > b.id ? -1 : 1); if (me) this.activeUsersChart.read(me); diff --git a/packages/frontend/@types/vue.d.ts b/packages/frontend/@types/vue.d.ts deleted file mode 100644 index 9c9c34ccc5..0000000000 --- a/packages/frontend/@types/vue.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/// <reference types="vue/macros-global" /> - -import type { $i } from '@/account'; -import type { defaultStore } from '@/store'; -import type { instance } from '@/instance'; -import type { i18n } from '@/i18n'; - -declare module 'vue' { - interface ComponentCustomProperties { - $i: typeof $i; - $store: typeof defaultStore; - $instance: typeof instance; - $t: typeof i18n['t']; - $ts: typeof i18n['ts']; - } -} diff --git a/packages/frontend/src/components/MkContainer.vue b/packages/frontend/src/components/MkContainer.vue index 833fa9d382..1834224b8d 100644 --- a/packages/frontend/src/components/MkContainer.vue +++ b/packages/frontend/src/components/MkContainer.vue @@ -14,10 +14,10 @@ </div> </header> <Transition - :enter-active-class="$store.state.animation ? $style.transition_toggle_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_toggle_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_toggle_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_toggle_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_toggle_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_toggle_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_toggle_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_toggle_leaveTo : ''" @enter="enter" @after-enter="afterEnter" @leave="leave" @@ -26,7 +26,7 @@ <div v-show="showBody" ref="content" :class="[$style.content, { [$style.omitted]: omitted }]"> <slot></slot> <button v-if="omitted" :class="$style.fade" class="_button" @click="() => { ignoreOmit = true; omitted = false; }"> - <span :class="$style.fadeLabel">{{ $ts.showMore }}</span> + <span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span> </button> </div> </Transition> @@ -35,6 +35,8 @@ <script lang="ts"> import { defineComponent } from 'vue'; +import { defaultStore } from '@/store'; +import { i18n } from '@/i18n'; export default defineComponent({ props: { @@ -79,6 +81,7 @@ export default defineComponent({ showBody: this.expanded, omitted: null, ignoreOmit: false, + defaultStore, }; }, mounted() { diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue index 21cccaabde..5bdf477241 100644 --- a/packages/frontend/src/components/MkContextMenu.vue +++ b/packages/frontend/src/components/MkContextMenu.vue @@ -1,10 +1,10 @@ <template> <Transition appear - :enter-active-class="$store.state.animation ? $style.transition_fade_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_fade_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_fade_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_fade_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_fade_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_fade_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_fade_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_fade_leaveTo : ''" > <div ref="rootEl" :class="$style.root" :style="{ zIndex }" @contextmenu.prevent.stop="() => {}"> <MkMenu :items="items" :align="'left'" @close="$emit('closed')"/> @@ -18,6 +18,7 @@ import MkMenu from './MkMenu.vue'; import { MenuItem } from './types/menu.vue'; import contains from '@/scripts/contains'; import * as os from '@/os'; +import { defaultStore } from '@/store'; const props = defineProps<{ items: MenuItem[]; diff --git a/packages/frontend/src/components/MkDonation.vue b/packages/frontend/src/components/MkDonation.vue index 9baa90ebfe..b5ae4c6c48 100644 --- a/packages/frontend/src/components/MkDonation.vue +++ b/packages/frontend/src/components/MkDonation.vue @@ -14,7 +14,7 @@ <div :class="$style.text"> <I18n :src="i18n.ts.pleaseDonate" tag="span"> <template #host> - {{ $instance.name ?? host }} + {{ instance.name ?? host }} </template> </I18n> <div style="margin-top: 0.2em;"> @@ -37,6 +37,7 @@ import { host } from '@/config'; import { i18n } from '@/i18n'; import * as os from '@/os'; import { miLocalStorage } from '@/local-storage'; +import { instance } from '@/instance'; const emit = defineEmits<{ (ev: 'closed'): void; diff --git a/packages/frontend/src/components/MkFoldableSection.vue b/packages/frontend/src/components/MkFoldableSection.vue index d4b1bee9e4..475e01c8d4 100644 --- a/packages/frontend/src/components/MkFoldableSection.vue +++ b/packages/frontend/src/components/MkFoldableSection.vue @@ -9,7 +9,7 @@ </button> </header> <Transition - :name="$store.state.animation ? 'folder-toggle' : ''" + :name="defaultStore.state.animation ? 'folder-toggle' : ''" @enter="enter" @after-enter="afterEnter" @leave="leave" @@ -26,6 +26,7 @@ import { defineComponent } from 'vue'; import tinycolor from 'tinycolor2'; import { miLocalStorage } from '@/local-storage'; +import { defaultStore } from '@/store'; const miLocalStoragePrefix = 'ui:folder:' as const; @@ -44,6 +45,7 @@ export default defineComponent({ }, data() { return { + defaultStore, bg: null, showBody: (this.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`) === 't') : this.expanded, }; diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue index 2748a9e491..58cc0de5c8 100644 --- a/packages/frontend/src/components/MkFolder.vue +++ b/packages/frontend/src/components/MkFolder.vue @@ -22,10 +22,10 @@ <div v-if="openedAtLeastOnce" :class="[$style.body, { [$style.bgSame]: bgSame }]" :style="{ maxHeight: maxHeight ? `${maxHeight}px` : null, overflow: maxHeight ? `auto` : null }"> <Transition - :enter-active-class="$store.state.animation ? $style.transition_toggle_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_toggle_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_toggle_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_toggle_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_toggle_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_toggle_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_toggle_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_toggle_leaveTo : ''" @enter="enter" @after-enter="afterEnter" @leave="leave" @@ -46,6 +46,7 @@ <script lang="ts" setup> import { nextTick, onMounted } from 'vue'; +import { defaultStore } from '@/store'; const props = withDefaults(defineProps<{ defaultOpen?: boolean; diff --git a/packages/frontend/src/components/MkFormDialog.vue b/packages/frontend/src/components/MkFormDialog.vue index 971bb806af..979df2e7c1 100644 --- a/packages/frontend/src/components/MkFormDialog.vue +++ b/packages/frontend/src/components/MkFormDialog.vue @@ -18,15 +18,15 @@ <div class="_gaps_m"> <template v-for="item in Object.keys(form).filter(item => !form[item].hidden)"> <MkInput v-if="form[item].type === 'number'" v-model="values[item]" type="number" :step="form[item].step || 1"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <template v-if="form[item].description" #caption>{{ form[item].description }}</template> </MkInput> <MkInput v-else-if="form[item].type === 'string' && !form[item].multiline" v-model="values[item]" type="text"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <template v-if="form[item].description" #caption>{{ form[item].description }}</template> </MkInput> <MkTextarea v-else-if="form[item].type === 'string' && form[item].multiline" v-model="values[item]"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <template v-if="form[item].description" #caption>{{ form[item].description }}</template> </MkTextarea> <MkSwitch v-else-if="form[item].type === 'boolean'" v-model="values[item]"> @@ -34,15 +34,15 @@ <template v-if="form[item].description" #caption>{{ form[item].description }}</template> </MkSwitch> <MkSelect v-else-if="form[item].type === 'enum'" v-model="values[item]"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <option v-for="item in form[item].enum" :key="item.value" :value="item.value">{{ item.label }}</option> </MkSelect> <MkRadios v-else-if="form[item].type === 'radio'" v-model="values[item]"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <option v-for="item in form[item].options" :key="item.value" :value="item.value">{{ item.label }}</option> </MkRadios> <MkRange v-else-if="form[item].type === 'range'" v-model="values[item]" :min="form[item].min" :max="form[item].max" :step="form[item].step" :text-converter="form[item].textConverter"> - <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> + <template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ i18n.ts.optional }})</span></template> <template v-if="form[item].description" #caption>{{ form[item].description }}</template> </MkRange> <MkButton v-else-if="form[item].type === 'button'" @click="form[item].action($event, values)"> @@ -64,6 +64,7 @@ import MkRange from './MkRange.vue'; import MkButton from './MkButton.vue'; import MkRadios from './MkRadios.vue'; import MkModalWindow from '@/components/MkModalWindow.vue'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -93,6 +94,7 @@ export default defineComponent({ data() { return { values: {}, + i18n, }; }, diff --git a/packages/frontend/src/components/MkGoogle.vue b/packages/frontend/src/components/MkGoogle.vue index 007728176e..227054d963 100644 --- a/packages/frontend/src/components/MkGoogle.vue +++ b/packages/frontend/src/components/MkGoogle.vue @@ -1,12 +1,13 @@ <template> <div :class="$style.root"> <input v-model="query" :class="$style.input" type="search" :placeholder="q"> - <button :class="$style.button" @click="search"><i class="ti ti-search"></i> {{ $ts.searchByGoogle }}</button> + <button :class="$style.button" @click="search"><i class="ti ti-search"></i> {{ i18n.ts.searchByGoogle }}</button> </div> </template> <script lang="ts" setup> import { ref } from 'vue'; +import { i18n } from '@/i18n'; const props = defineProps<{ q: string; diff --git a/packages/frontend/src/components/MkMediaBanner.vue b/packages/frontend/src/components/MkMediaBanner.vue index c0401a6455..1576144f6b 100644 --- a/packages/frontend/src/components/MkMediaBanner.vue +++ b/packages/frontend/src/components/MkMediaBanner.vue @@ -2,8 +2,8 @@ <div class="mk-media-banner"> <div v-if="media.isSensitive && hide" class="sensitive" @click="hide = false"> <span class="icon"><i class="ti ti-alert-triangle"></i></span> - <b>{{ $ts.sensitive }}</b> - <span>{{ $ts.clickToShow }}</span> + <b>{{ i18n.ts.sensitive }}</b> + <span>{{ i18n.ts.clickToShow }}</span> </div> <div v-else-if="media.type.startsWith('audio') && media.type !== 'audio/midi'" class="audio"> <VuePlyr :options="{ volume: 0.5 }"> @@ -33,6 +33,7 @@ import * as misskey from 'misskey-js'; import VuePlyr from 'vue-plyr'; import { ColdDeviceStorage } from '@/store'; import 'vue-plyr/dist/vue-plyr.css'; +import { i18n } from '@/i18n'; const props = withDefaults(defineProps<{ media: misskey.entities.DriveFile; diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue index 979c3eed28..e02a7af09e 100644 --- a/packages/frontend/src/components/MkMediaVideo.vue +++ b/packages/frontend/src/components/MkMediaVideo.vue @@ -1,8 +1,8 @@ <template> <div v-if="hide" class="icozogqfvdetwohsdglrbswgrejoxbdj" @click="hide = false"> <div> - <b><i class="ti ti-alert-triangle"></i> {{ $ts.sensitive }}</b> - <span>{{ $ts.clickToShow }}</span> + <b><i class="ti ti-alert-triangle"></i> {{ i18n.ts.sensitive }}</b> + <span>{{ i18n.ts.clickToShow }}</span> </div> </div> <div v-else class="kkjnbbplepmiyuadieoenjgutgcmtsvu"> @@ -28,6 +28,7 @@ import * as misskey from 'misskey-js'; import VuePlyr from 'vue-plyr'; import { defaultStore } from '@/store'; import 'vue-plyr/dist/vue-plyr.css'; +import { i18n } from '@/i18n'; const props = defineProps<{ video: misskey.entities.DriveFile; diff --git a/packages/frontend/src/components/MkMention.vue b/packages/frontend/src/components/MkMention.vue index f586eeff4d..481c3710ca 100644 --- a/packages/frontend/src/components/MkMention.vue +++ b/packages/frontend/src/components/MkMention.vue @@ -3,7 +3,7 @@ <img :class="$style.icon" :src="`/avatar/@${username}@${host}`" alt=""> <span> <span :class="$style.username">@{{ username }}</span> - <span v-if="(host != localHost) || $store.state.showFullAcct" :class="$style.host">@{{ toUnicode(host) }}</span> + <span v-if="(host != localHost) || defaultStore.state.showFullAcct" :class="$style.host">@{{ toUnicode(host) }}</span> </span> </MkA> </template> @@ -14,6 +14,7 @@ import { } from 'vue'; import tinycolor from 'tinycolor2'; import { host as localHost } from '@/config'; import { $i } from '@/account'; +import { defaultStore } from '@/store'; const props = defineProps<{ username: string; diff --git a/packages/frontend/src/components/MkModalPageWindow.vue b/packages/frontend/src/components/MkModalPageWindow.vue index 68a3eda3d8..b38865f525 100644 --- a/packages/frontend/src/components/MkModalPageWindow.vue +++ b/packages/frontend/src/components/MkModalPageWindow.vue @@ -2,7 +2,7 @@ <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> <div ref="rootEl" class="hrmcaedk" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> <div class="header" @contextmenu="onContextmenu"> - <button v-if="history.length > 0" v-tooltip="$ts.goBack" class="_button" @click="back()"><i class="ti ti-arrow-left"></i></button> + <button v-if="history.length > 0" v-tooltip="i18n.ts.goBack" class="_button" @click="back()"><i class="ti ti-arrow-left"></i></button> <span v-else style="display: inline-block; width: 20px"></span> <span v-if="pageMetadata?.value" class="title"> <i v-if="pageMetadata?.value.icon" class="icon" :class="pageMetadata?.value.icon"></i> diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index eb9793fcc1..700bbde6f0 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -57,7 +57,7 @@ <div v-if="translating || translation" :class="$style.translation"> <MkLoading v-if="translating" mini/> <div v-else :class="$style.translated"> - <b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b> + <b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b> <Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/> </div> </div> diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 715fd3a9a8..67bdfd2258 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -70,7 +70,7 @@ <div v-if="translating || translation" class="translation"> <MkLoading v-if="translating" mini/> <div v-else class="translated"> - <b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b> + <b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b> <Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/> </div> </div> diff --git a/packages/frontend/src/components/MkNotePreview.vue b/packages/frontend/src/components/MkNotePreview.vue index 1cc01386ba..16196834b7 100644 --- a/packages/frontend/src/components/MkNotePreview.vue +++ b/packages/frontend/src/components/MkNotePreview.vue @@ -16,6 +16,7 @@ <script lang="ts" setup> import { } from 'vue'; +import { $i } from '@/account'; const props = defineProps<{ text: string; diff --git a/packages/frontend/src/components/MkNoteSimple.vue b/packages/frontend/src/components/MkNoteSimple.vue index 2b541e6094..bd27a43b61 100644 --- a/packages/frontend/src/components/MkNoteSimple.vue +++ b/packages/frontend/src/components/MkNoteSimple.vue @@ -22,6 +22,7 @@ import * as misskey from 'misskey-js'; import MkNoteHeader from '@/components/MkNoteHeader.vue'; import MkSubNoteContent from '@/components/MkSubNoteContent.vue'; import MkCwButton from '@/components/MkCwButton.vue'; +import { $i } from '@/account'; const props = defineProps<{ note: misskey.entities.Note; diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue index ab6d62fba5..c293641355 100644 --- a/packages/frontend/src/components/MkNoteSub.vue +++ b/packages/frontend/src/components/MkNoteSub.vue @@ -33,6 +33,7 @@ import MkCwButton from '@/components/MkCwButton.vue'; import { notePage } from '@/filters/note'; import * as os from '@/os'; import { i18n } from '@/i18n'; +import { $i } from '@/account'; const props = withDefaults(defineProps<{ note: misskey.entities.Note; diff --git a/packages/frontend/src/components/MkOmit.vue b/packages/frontend/src/components/MkOmit.vue index a806d92b22..9232ebb7c9 100644 --- a/packages/frontend/src/components/MkOmit.vue +++ b/packages/frontend/src/components/MkOmit.vue @@ -2,13 +2,14 @@ <div ref="content" :class="[$style.content, { [$style.omitted]: omitted }]"> <slot></slot> <button v-if="omitted" :class="$style.fade" class="_button" @click="() => { ignoreOmit = true; omitted = false; }"> - <span :class="$style.fadeLabel">{{ $ts.showMore }}</span> + <span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span> </button> </div> </template> <script lang="ts" setup> import { onMounted } from 'vue'; +import { i18n } from '@/i18n'; const props = withDefaults(defineProps<{ maxHeight: number; diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue index a1a61a6fd6..cd8af560e4 100644 --- a/packages/frontend/src/components/MkPagination.vue +++ b/packages/frontend/src/components/MkPagination.vue @@ -1,9 +1,9 @@ <template> <Transition - :enter-active-class="$store.state.animation ? $style.transition_fade_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_fade_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_fade_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_fade_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_fade_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_fade_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_fade_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_fade_leaveTo : ''" mode="out-in" > <MkLoading v-if="fetching"/> @@ -163,21 +163,22 @@ async function init(): Promise<void> { const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await os.api(props.pagination.endpoint, { ...params, - limit: props.pagination.noPaging ? (props.pagination.limit || 10) : (props.pagination.limit || 10) + 1, + limit: props.pagination.limit ?? 10, }).then(res => { for (let i = 0; i < res.length; i++) { const item = res[i]; if (i === 3) item._shouldInsertAd_ = true; } - if (!props.pagination.noPaging && (res.length > (props.pagination.limit || 10))) { - res.pop(); - if (props.pagination.reversed) moreFetching.value = true; + + if (res.length === 0 || props.pagination.noPaging) { items.value = res; - more.value = true; + more.value = false; } else { + if (props.pagination.reversed) moreFetching.value = true; items.value = res; - more.value = false; + more.value = true; } + offset.value = res.length; error.value = false; fetching.value = false; @@ -198,7 +199,7 @@ const fetchMore = async (): Promise<void> => { const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await os.api(props.pagination.endpoint, { ...params, - limit: SECOND_FETCH_LIMIT + 1, + limit: SECOND_FETCH_LIMIT, ...(props.pagination.offsetMode ? { offset: offset.value, } : { @@ -227,28 +228,26 @@ const fetchMore = async (): Promise<void> => { }); }; - if (res.length > SECOND_FETCH_LIMIT) { - res.pop(); - + if (res.length === 0) { if (props.pagination.reversed) { reverseConcat(res).then(() => { - more.value = true; + more.value = false; moreFetching.value = false; }); } else { items.value = items.value.concat(res); - more.value = true; + more.value = false; moreFetching.value = false; } } else { if (props.pagination.reversed) { reverseConcat(res).then(() => { - more.value = false; + more.value = true; moreFetching.value = false; }); } else { items.value = items.value.concat(res); - more.value = false; + more.value = true; moreFetching.value = false; } } @@ -264,20 +263,19 @@ const fetchMoreAhead = async (): Promise<void> => { const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await os.api(props.pagination.endpoint, { ...params, - limit: SECOND_FETCH_LIMIT + 1, + limit: SECOND_FETCH_LIMIT, ...(props.pagination.offsetMode ? { offset: offset.value, } : { sinceId: items.value[items.value.length - 1].id, }), }).then(res => { - if (res.length > SECOND_FETCH_LIMIT) { - res.pop(); + if (res.length === 0) { items.value = items.value.concat(res); - more.value = true; + more.value = false; } else { items.value = items.value.concat(res); - more.value = false; + more.value = true; } offset.value += res.length; moreFetching.value = false; diff --git a/packages/frontend/src/components/MkPoll.vue b/packages/frontend/src/components/MkPoll.vue index fcbd8ad351..0810061ff9 100644 --- a/packages/frontend/src/components/MkPoll.vue +++ b/packages/frontend/src/components/MkPoll.vue @@ -6,12 +6,12 @@ <span> <template v-if="choice.isVoted"><i class="ti ti-check"></i></template> <Mfm :text="choice.text" :plain="true"/> - <span v-if="showResult" class="votes">({{ $t('_poll.votesCount', { n: choice.votes }) }})</span> + <span v-if="showResult" class="votes">({{ i18n.t('_poll.votesCount', { n: choice.votes }) }})</span> </span> </li> </ul> <p v-if="!readOnly"> - <span>{{ $t('_poll.totalVotes', { n: total }) }}</span> + <span>{{ i18n.t('_poll.totalVotes', { n: total }) }}</span> <span> · </span> <a v-if="!closed && !isVoted" @click="showResult = !showResult">{{ showResult ? i18n.ts._poll.vote : i18n.ts._poll.showResult }}</a> <span v-if="isVoted">{{ i18n.ts._poll.voted }}</span> diff --git a/packages/frontend/src/components/MkPollEditor.vue b/packages/frontend/src/components/MkPollEditor.vue index 9567c58b99..471ec39169 100644 --- a/packages/frontend/src/components/MkPollEditor.vue +++ b/packages/frontend/src/components/MkPollEditor.vue @@ -5,7 +5,7 @@ </p> <ul> <li v-for="(choice, i) in choices" :key="i"> - <MkInput class="input" small :model-value="choice" :placeholder="$t('_poll.choiceN', { n: i + 1 })" @update:model-value="onInput(i, $event)"> + <MkInput class="input" small :model-value="choice" :placeholder="i18n.t('_poll.choiceN', { n: i + 1 })" @update:model-value="onInput(i, $event)"> </MkInput> <button class="_button" @click="remove(i)"> <i class="ti ti-x"></i> diff --git a/packages/frontend/src/components/MkReactionsViewer.vue b/packages/frontend/src/components/MkReactionsViewer.vue index 76faffe926..3219c8a92c 100644 --- a/packages/frontend/src/components/MkReactionsViewer.vue +++ b/packages/frontend/src/components/MkReactionsViewer.vue @@ -1,27 +1,28 @@ <template> <TransitionGroup - :enter-active-class="$store.state.animation ? $style.transition_x_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_x_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_x_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_x_leaveTo : ''" - :move-class="$store.state.animation ? $style.transition_x_move : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_x_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_x_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_x_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_x_leaveTo : ''" + :move-class="defaultStore.state.animation ? $style.transition_x_move : ''" tag="div" :class="$style.root" > <XReaction v-for="[reaction, count] in reactions" :key="reaction" :reaction="reaction" :count="count" :is-initial="initialReactions.has(reaction)" :note="note"/> - <slot v-if="hasMoreReactions" name="more" /> + <slot v-if="hasMoreReactions" name="more"/> </TransitionGroup> </template> <script lang="ts" setup> import * as misskey from 'misskey-js'; -import XReaction from '@/components/MkReactionsViewer.reaction.vue'; import { watch } from 'vue'; +import XReaction from '@/components/MkReactionsViewer.reaction.vue'; +import { defaultStore } from '@/store'; const props = withDefaults(defineProps<{ - note: misskey.entities.Note; - maxNumber?: number; + note: misskey.entities.Note; + maxNumber?: number; }>(), { - maxNumber: Infinity, + maxNumber: Infinity, }); const initialReactions = new Set(Object.keys(props.note.reactions)); diff --git a/packages/frontend/src/components/MkSample.vue b/packages/frontend/src/components/MkSample.vue index 8b7fc2ef76..7a3bc20888 100644 --- a/packages/frontend/src/components/MkSample.vue +++ b/packages/frontend/src/components/MkSample.vue @@ -36,6 +36,7 @@ import MkTextarea from '@/components/MkTextarea.vue'; import MkRadio from '@/components/MkRadio.vue'; import * as os from '@/os'; import * as config from '@/config'; +import { $i } from '@/account'; export default defineComponent({ components: { @@ -51,6 +52,7 @@ export default defineComponent({ text: '', flag: true, radio: 'misskey', + $i, mfm: `Hello world! This is an @example mention. BTW you are @${this.$i ? this.$i.username : 'guest'}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.`, }; }, diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue index 9f90f5eecb..1ac7107aa7 100644 --- a/packages/frontend/src/components/MkSubNoteContent.vue +++ b/packages/frontend/src/components/MkSubNoteContent.vue @@ -8,7 +8,7 @@ <MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA> </div> <details v-if="note.files.length > 0"> - <summary>({{ $t('withNFiles', { n: note.files.length }) }})</summary> + <summary>({{ i18n.t('withNFiles', { n: note.files.length }) }})</summary> <MkMediaList :media-list="note.files"/> </details> <details v-if="note.poll"> @@ -27,6 +27,7 @@ import * as misskey from 'misskey-js'; import MkMediaList from '@/components/MkMediaList.vue'; import MkPoll from '@/components/MkPoll.vue'; import { i18n } from '@/i18n'; +import { $i } from '@/account'; const props = defineProps<{ note: misskey.entities.Note; diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index 87f7c61a92..6741e7a18b 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -1,5 +1,5 @@ <template> -<MkNotes ref="tlComponent" :no-gap="!$store.state.showGapBetweenNotesInTimeline" :pagination="pagination" @queue="emit('queue', $event)"/> +<MkNotes ref="tlComponent" :no-gap="!defaultStore.state.showGapBetweenNotesInTimeline" :pagination="pagination" @queue="emit('queue', $event)"/> </template> <script lang="ts" setup> @@ -8,6 +8,7 @@ import MkNotes from '@/components/MkNotes.vue'; import { stream } from '@/stream'; import * as sound from '@/scripts/sound'; import { $i } from '@/account'; +import { defaultStore } from '@/store'; const props = defineProps<{ src: string; diff --git a/packages/frontend/src/components/MkToast.vue b/packages/frontend/src/components/MkToast.vue index 6d59702569..ad53c7f289 100644 --- a/packages/frontend/src/components/MkToast.vue +++ b/packages/frontend/src/components/MkToast.vue @@ -1,10 +1,10 @@ <template> <div> <Transition - :enter-active-class="$store.state.animation ? $style.transition_toast_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_toast_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_toast_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_toast_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_toast_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_toast_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_toast_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_toast_leaveTo : ''" appear @after-leave="emit('closed')" > <div v-if="showing" class="_acrylic" :class="$style.root" :style="{ zIndex }"> @@ -19,6 +19,7 @@ <script lang="ts" setup> import { onMounted } from 'vue'; import * as os from '@/os'; +import { defaultStore } from '@/store'; defineProps<{ message: string; diff --git a/packages/frontend/src/components/MkTokenGenerateWindow.vue b/packages/frontend/src/components/MkTokenGenerateWindow.vue index 6035c20d23..56be044405 100644 --- a/packages/frontend/src/components/MkTokenGenerateWindow.vue +++ b/packages/frontend/src/components/MkTokenGenerateWindow.vue @@ -10,7 +10,7 @@ @closed="$emit('closed')" @ok="ok()" > - <template #header>{{ title || $ts.generateAccessToken }}</template> + <template #header>{{ title || i18n.ts.generateAccessToken }}</template> <MkSpacer :margin-min="20" :margin-max="28"> <div class="_gaps_m"> @@ -19,15 +19,15 @@ </div> <div> <MkInput v-model="name"> - <template #label>{{ $ts.name }}</template> + <template #label>{{ i18n.ts.name }}</template> </MkInput> </div> - <div><b>{{ $ts.permission }}</b></div> + <div><b>{{ i18n.ts.permission }}</b></div> <div class="_buttons"> <MkButton inline @click="disableAll">{{ i18n.ts.disableAll }}</MkButton> <MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton> </div> - <MkSwitch v-for="kind in (initialPermissions || kinds)" :key="kind" v-model="permissions[kind]">{{ $t(`_permissions.${kind}`) }}</MkSwitch> + <MkSwitch v-for="kind in (initialPermissions || kinds)" :key="kind" v-model="permissions[kind]">{{ i18n.t(`_permissions.${kind}`) }}</MkSwitch> </div> </MkSpacer> </MkModalWindow> diff --git a/packages/frontend/src/components/MkTooltip.vue b/packages/frontend/src/components/MkTooltip.vue index 0b0556de39..2d34b090ed 100644 --- a/packages/frontend/src/components/MkTooltip.vue +++ b/packages/frontend/src/components/MkTooltip.vue @@ -1,9 +1,9 @@ <template> <Transition - :enter-active-class="$store.state.animation ? $style.transition_tooltip_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_tooltip_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_tooltip_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_tooltip_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_tooltip_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_tooltip_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_tooltip_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_tooltip_leaveTo : ''" appear @after-leave="emit('closed')" > <div v-show="showing" ref="el" :class="$style.root" class="_acrylic _shadow" :style="{ zIndex, maxWidth: maxWidth + 'px' }"> @@ -19,6 +19,7 @@ import { nextTick, onMounted, onUnmounted, shallowRef } from 'vue'; import * as os from '@/os'; import { calcPopupPosition } from '@/scripts/popup-position'; +import { defaultStore } from '@/store'; const props = withDefaults(defineProps<{ showing: boolean; diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue index 094709e093..635ac3e8bd 100644 --- a/packages/frontend/src/components/MkUrlPreview.vue +++ b/packages/frontend/src/components/MkUrlPreview.vue @@ -23,7 +23,7 @@ </template> <template v-else-if="tweetId && tweetExpanded"> <div ref="twitter" :class="$style.twitter"> - <iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&hideCard=false&hideThread=false&lang=en&theme=${$store.state.darkMode ? 'dark' : 'light'}&id=${tweetId}`"></iframe> + <iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&hideCard=false&hideThread=false&lang=en&theme=${defaultStore.state.darkMode ? 'dark' : 'light'}&id=${tweetId}`"></iframe> </div> <div :class="$style.action"> <MkButton :small="true" inline @click="tweetExpanded = false"> @@ -77,6 +77,7 @@ import * as os from '@/os'; import { deviceKind } from '@/scripts/device-kind'; import MkButton from '@/components/MkButton.vue'; import { versatileLang } from '@/scripts/intl-const'; +import { defaultStore } from '@/store'; type SummalyResult = Awaited<ReturnType<typeof summaly>>; diff --git a/packages/frontend/src/components/MkUrlPreviewPopup.vue b/packages/frontend/src/components/MkUrlPreviewPopup.vue index a0ad3c7fdd..e244be3e96 100644 --- a/packages/frontend/src/components/MkUrlPreviewPopup.vue +++ b/packages/frontend/src/components/MkUrlPreviewPopup.vue @@ -1,6 +1,6 @@ <template> <div class="fgmtyycl" :style="{ zIndex, top: top + 'px', left: left + 'px' }"> - <Transition :name="$store.state.animation ? '_transition_zoom' : ''" @after-leave="emit('closed')"> + <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" @after-leave="emit('closed')"> <MkUrlPreview v-if="showing" class="_popup _shadow" :url="url"/> </Transition> </div> @@ -10,6 +10,7 @@ import { onMounted } from 'vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import * as os from '@/os'; +import { defaultStore } from '@/store'; const props = defineProps<{ showing: boolean; diff --git a/packages/frontend/src/components/MkUserInfo.vue b/packages/frontend/src/components/MkUserInfo.vue index 1486423b3d..5086c1b319 100644 --- a/packages/frontend/src/components/MkUserInfo.vue +++ b/packages/frontend/src/components/MkUserInfo.vue @@ -6,7 +6,7 @@ <MkA class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA> <p class="username"><MkAcct :user="user"/></p> </div> - <span v-if="$i && $i.id !== user.id && user.isFollowed" class="followed">{{ $ts.followsYou }}</span> + <span v-if="$i && $i.id !== user.id && user.isFollowed" class="followed">{{ i18n.ts.followsYou }}</span> <div class="description"> <div v-if="user.description" class="mfm"> <Mfm :text="user.description" :author="user" :i="$i"/> @@ -33,6 +33,7 @@ import * as misskey from 'misskey-js'; import MkFollowButton from '@/components/MkFollowButton.vue'; import { userPage } from '@/filters/user'; import { i18n } from '@/i18n'; +import { $i } from '@/account'; defineProps<{ user: misskey.entities.UserDetailed; diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue index 93e914f6dd..8ca0355448 100644 --- a/packages/frontend/src/components/MkUserPopup.vue +++ b/packages/frontend/src/components/MkUserPopup.vue @@ -1,15 +1,15 @@ <template> <Transition - :enter-active-class="$store.state.animation ? $style.transition_popup_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_popup_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_popup_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_popup_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_popup_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_popup_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_popup_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_popup_leaveTo : ''" appear @after-leave="emit('closed')" > <div v-if="showing" :class="$style.root" class="_popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { emit('mouseover'); }" @mouseleave="() => { emit('mouseleave'); }"> <div v-if="user != null"> <div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"> - <span v-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ $ts.followsYou }}</span> + <span v-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span> </div> <svg viewBox="0 0 128 128" :class="$style.avatarBack"> <g transform="matrix(1.6,0,0,1.6,-38.4,-51.2)"> @@ -27,15 +27,15 @@ </div> <div :class="$style.status"> <div :class="$style.statusItem"> - <div :class="$style.statusItemLabel">{{ $ts.notes }}</div> + <div :class="$style.statusItemLabel">{{ i18n.ts.notes }}</div> <div>{{ number(user.notesCount) }}</div> </div> <div :class="$style.statusItem"> - <div :class="$style.statusItemLabel">{{ $ts.following }}</div> + <div :class="$style.statusItemLabel">{{ i18n.ts.following }}</div> <div>{{ number(user.followingCount) }}</div> </div> <div :class="$style.statusItem"> - <div :class="$style.statusItemLabel">{{ $ts.followers }}</div> + <div :class="$style.statusItemLabel">{{ i18n.ts.followers }}</div> <div>{{ number(user.followersCount) }}</div> </div> </div> @@ -59,6 +59,8 @@ import * as os from '@/os'; import { getUserMenu } from '@/scripts/get-user-menu'; import number from '@/filters/number'; import { i18n } from '@/i18n'; +import { defaultStore } from '@/store'; +import { $i } from '@/account'; const props = defineProps<{ showing: boolean; diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue index e7ad2b9a43..30b5391e9a 100644 --- a/packages/frontend/src/components/MkWindow.vue +++ b/packages/frontend/src/components/MkWindow.vue @@ -1,9 +1,9 @@ <template> <Transition - :enter-active-class="$store.state.animation ? $style.transition_window_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_window_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_window_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_window_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_window_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_window_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_window_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_window_leaveTo : ''" appear @after-leave="$emit('closed')" > @@ -47,6 +47,7 @@ import contains from '@/scripts/contains'; import * as os from '@/os'; import { MenuItem } from '@/types/menu'; import { i18n } from '@/i18n'; +import { defaultStore } from '@/store'; const minHeight = 50; const minWidth = 250; diff --git a/packages/frontend/src/components/MkYoutubePlayer.vue b/packages/frontend/src/components/MkYoutubePlayer.vue index 460b038838..4d765fe2f7 100644 --- a/packages/frontend/src/components/MkYoutubePlayer.vue +++ b/packages/frontend/src/components/MkYoutubePlayer.vue @@ -6,7 +6,7 @@ </template> <div class="poamfof"> - <Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="player.url && (player.url.startsWith('http://') || player.url.startsWith('https://'))" class="player"> <iframe v-if="!fetching" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/> </div> @@ -21,6 +21,7 @@ <script lang="ts" setup> import MkWindow from '@/components/MkWindow.vue'; import { versatileLang } from '@/scripts/intl-const'; +import { defaultStore } from '@/store'; const props = defineProps<{ url: string; diff --git a/packages/frontend/src/components/form/suspense.vue b/packages/frontend/src/components/form/suspense.vue index 936e12aa7b..3a44c3da3d 100644 --- a/packages/frontend/src/components/form/suspense.vue +++ b/packages/frontend/src/components/form/suspense.vue @@ -1,5 +1,5 @@ <template> -<Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> +<Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="pending"> <MkLoading/> </div> @@ -8,8 +8,8 @@ </div> <div v-else> <div class="wszdbhzo"> - <div><i class="ti ti-alert-triangle"></i> {{ $ts.somethingHappened }}</div> - <MkButton inline class="retry" @click="retry"><i class="ti ti-reload"></i> {{ $ts.retry }}</MkButton> + <div><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</div> + <MkButton inline class="retry" @click="retry"><i class="ti ti-reload"></i> {{ i18n.ts.retry }}</MkButton> </div> </div> </Transition> @@ -18,6 +18,8 @@ <script lang="ts"> import { defineComponent, PropType, ref, watch } from 'vue'; import MkButton from '@/components/MkButton.vue'; +import { defaultStore } from '@/store'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -72,6 +74,8 @@ export default defineComponent({ rejected, result, retry, + defaultStore, + i18n, }; }, }); diff --git a/packages/frontend/src/components/global/MkAcct.vue b/packages/frontend/src/components/global/MkAcct.vue index 2a43ded9e1..e06ab64e86 100644 --- a/packages/frontend/src/components/global/MkAcct.vue +++ b/packages/frontend/src/components/global/MkAcct.vue @@ -1,7 +1,7 @@ <template> <span> <span>@{{ user.username }}</span> - <span v-if="user.host || detail || $store.state.showFullAcct" style="opacity: 0.5;">@{{ user.host || host }}</span> + <span v-if="user.host || detail || defaultStore.state.showFullAcct" style="opacity: 0.5;">@{{ user.host || host }}</span> </span> </template> @@ -9,6 +9,7 @@ import * as misskey from 'misskey-js'; import { toUnicode } from 'punycode/'; import { host as hostRaw } from '@/config'; +import { defaultStore } from '@/store'; defineProps<{ user: misskey.entities.UserDetailed; diff --git a/packages/frontend/src/components/global/MkAd.vue b/packages/frontend/src/components/global/MkAd.vue index e0304c8bc5..b8f749bd1c 100644 --- a/packages/frontend/src/components/global/MkAd.vue +++ b/packages/frontend/src/components/global/MkAd.vue @@ -9,9 +9,9 @@ <div v-else :class="$style.menu"> <div :class="$style.menuContainer"> <div>Ads by {{ host }}</div> - <!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>--> - <MkButton v-if="chosen.ratio !== 0" :class="$style.menuButton" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton> - <button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button> + <!--<MkButton class="button" primary>{{ i18n.ts._ad.like }}</MkButton>--> + <MkButton v-if="chosen.ratio !== 0" :class="$style.menuButton" @click="reduceFrequency">{{ i18n.ts._ad.reduceFrequencyOfThisAd }}</MkButton> + <button class="_textButton" @click="toggleMenu">{{ i18n.ts._ad.back }}</button> </div> </div> </div> @@ -26,6 +26,7 @@ import MkButton from '@/components/MkButton.vue'; import { defaultStore } from '@/store'; import * as os from '@/os'; import { $i } from '@/account'; +import { i18n } from '@/i18n'; type Ad = (typeof instance)['ads'][number]; diff --git a/packages/frontend/src/components/global/MkError.vue b/packages/frontend/src/components/global/MkError.vue index 7390a9dfb9..513ef21d35 100644 --- a/packages/frontend/src/components/global/MkError.vue +++ b/packages/frontend/src/components/global/MkError.vue @@ -1,5 +1,5 @@ <template> -<Transition :name="$store.state.animation ? '_transition_zoom' : ''" appear> +<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear> <div :class="$style.root"> <img :class="$style.img" src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> <p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</p> @@ -11,6 +11,7 @@ <script lang="ts" setup> import MkButton from '@/components/MkButton.vue'; import { i18n } from '@/i18n'; +import { defaultStore } from '@/store'; const emit = defineEmits<{ (ev: 'retry'): void; diff --git a/packages/frontend/src/components/page/page.post.vue b/packages/frontend/src/components/page/page.post.vue index 6de0a78694..55da610cb6 100644 --- a/packages/frontend/src/components/page/page.post.vue +++ b/packages/frontend/src/components/page/page.post.vue @@ -16,6 +16,8 @@ import { apiUrl } from '@/config'; import * as os from '@/os'; import { PostBlock } from '@/scripts/hpml/block'; import { Hpml } from '@/scripts/hpml/evaluator'; +import { defaultStore } from '@/store'; +import { $i } from '@/account'; export default defineComponent({ components: { @@ -54,9 +56,9 @@ export default defineComponent({ canvas.toBlob(blob => { const formData = new FormData(); formData.append('file', blob); - formData.append('i', this.$i.token); - if (this.$store.state.uploadFolder) { - formData.append('folderId', this.$store.state.uploadFolder); + formData.append('i', $i.token); + if (defaultStore.state.uploadFolder) { + formData.append('folderId', defaultStore.state.uploadFolder); } window.fetch(apiUrl + '/drive/files/create', { diff --git a/packages/frontend/src/components/page/page.text.vue b/packages/frontend/src/components/page/page.text.vue index 689c484521..e0e4959efa 100644 --- a/packages/frontend/src/components/page/page.text.vue +++ b/packages/frontend/src/components/page/page.text.vue @@ -6,11 +6,12 @@ </template> <script lang="ts"> -import { TextBlock } from '@/scripts/hpml/block'; -import { Hpml } from '@/scripts/hpml/evaluator'; import { defineAsyncComponent, defineComponent, PropType } from 'vue'; import * as mfm from 'mfm-js'; +import { TextBlock } from '@/scripts/hpml/block'; +import { Hpml } from '@/scripts/hpml/evaluator'; import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; +import { $i } from '@/account'; export default defineComponent({ components: { @@ -29,6 +30,7 @@ export default defineComponent({ data() { return { text: this.hpml.interpolate(this.block.text), + $i, }; }, computed: { diff --git a/packages/frontend/src/init.ts b/packages/frontend/src/init.ts index a2dff87e8e..26c5adfc70 100644 --- a/packages/frontend/src/init.ts +++ b/packages/frontend/src/init.ts @@ -198,15 +198,6 @@ if (_DEV_) { app.config.performance = true; } -// TODO: 廃止 -app.config.globalProperties = { - $i, - $store: defaultStore, - $instance: instance, - $t: i18n.t, - $ts: i18n.ts, -}; - widgets(app); directives(app); components(app); @@ -356,7 +347,7 @@ const hotkeys = { }, 's': (): void => { mainRouter.push('/search'); - } + }, }; if ($i) { diff --git a/packages/frontend/src/pages/_error_.vue b/packages/frontend/src/pages/_error_.vue index 5001b5a8b4..f53fec7d94 100644 --- a/packages/frontend/src/pages/_error_.vue +++ b/packages/frontend/src/pages/_error_.vue @@ -1,6 +1,6 @@ <template> <MkLoading v-if="!loaded"/> -<Transition :name="$store.state.animation ? '_transition_zoom' : ''" appear> +<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear> <div v-show="loaded" class="mjndxjch"> <img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> <p><b><i class="ti ti-alert-triangle"></i> {{ i18n.ts.pageLoadError }}</b></p> @@ -27,6 +27,7 @@ import { unisonReload } from '@/scripts/unison-reload'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { miLocalStorage } from '@/local-storage'; +import { defaultStore } from '@/store'; const props = withDefaults(defineProps<{ error?: Error; diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index 7f3b4fd937..d461430234 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -3,7 +3,7 @@ <MkButton v-if="$i && ($i.isModerator || $i.policies.canManageCustomEmojis)" primary link to="/custom-emojis-manager">{{ i18n.ts.manageCustomEmojis }}</MkButton> <div class="query"> - <MkInput v-model="q" class="" :placeholder="$ts.search"> + <MkInput v-model="q" class="" :placeholder="i18n.ts.search"> <template #prefix><i class="ti ti-search"></i></template> </MkInput> @@ -15,14 +15,14 @@ </div> <MkFoldableSection v-if="searchEmojis" class="emojis"> - <template #header>{{ $ts.searchResult }}</template> + <template #header>{{ i18n.ts.searchResult }}</template> <div class="zuvgdzyt"> <XEmoji v-for="emoji in searchEmojis" :key="emoji.name" class="emoji" :emoji="emoji"/> </div> </MkFoldableSection> <MkFoldableSection v-for="category in customEmojiCategories" v-once :key="category" class="emojis"> - <template #header>{{ category || $ts.other }}</template> + <template #header>{{ category || i18n.ts.other }}</template> <div class="zuvgdzyt"> <XEmoji v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" class="emoji" :emoji="emoji"/> </div> @@ -32,13 +32,14 @@ <script lang="ts" setup> import { watch } from 'vue'; +import * as Misskey from 'misskey-js'; import XEmoji from './emojis.emoji.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import { customEmojis, customEmojiCategories, getCustomEmojiTags } from '@/custom-emojis'; import { i18n } from '@/i18n'; -import * as Misskey from 'misskey-js'; +import { $i } from '@/account'; const customEmojiTags = getCustomEmojiTags(); let q = $ref(''); diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue index be0c1828a3..d54d93eaee 100644 --- a/packages/frontend/src/pages/about.vue +++ b/packages/frontend/src/pages/about.vue @@ -3,18 +3,18 @@ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer v-if="tab === 'overview'" :content-max="600" :margin-min="20"> <div class="_gaps_m"> - <div class="fwhjspax" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"> + <div class="fwhjspax" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"> <div class="content"> - <img :src="$instance.iconUrl ?? $instance.faviconUrl ?? '/favicon.ico'" alt="" class="icon"/> + <img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" class="icon"/> <div class="name"> - <b>{{ $instance.name ?? host }}</b> + <b>{{ instance.name ?? host }}</b> </div> </div> </div> <MkKeyValue> <template #key>{{ i18n.ts.description }}</template> - <template #value><div v-html="$instance.description"></div></template> + <template #value><div v-html="instance.description"></div></template> </MkKeyValue> <FormSection> @@ -23,7 +23,7 @@ <template #key>Misskey</template> <template #value>{{ version }}</template> </MkKeyValue> - <div v-html="i18n.t('poweredByMisskeyDescription', { name: $instance.name ?? host })"> + <div v-html="i18n.t('poweredByMisskeyDescription', { name: instance.name ?? host })"> </div> <FormLink to="/about-misskey">{{ i18n.ts.aboutMisskey }}</FormLink> </div> @@ -34,14 +34,14 @@ <FormSplit> <MkKeyValue> <template #key>{{ i18n.ts.administrator }}</template> - <template #value>{{ $instance.maintainerName }}</template> + <template #value>{{ instance.maintainerName }}</template> </MkKeyValue> <MkKeyValue> <template #key>{{ i18n.ts.contact }}</template> - <template #value>{{ $instance.maintainerEmail }}</template> + <template #value>{{ instance.maintainerEmail }}</template> </MkKeyValue> </FormSplit> - <FormLink v-if="$instance.tosUrl" :to="$instance.tosUrl" external>{{ i18n.ts.tos }}</FormLink> + <FormLink v-if="instance.tosUrl" :to="instance.tosUrl" external>{{ i18n.ts.tos }}</FormLink> </div> </FormSection> @@ -101,6 +101,7 @@ import number from '@/filters/number'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { claimAchievement } from '@/scripts/achievements'; +import { instance } from '@/instance'; const props = withDefaults(defineProps<{ initialTab?: string; diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index 8aae39cba1..963393d7e5 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -4,7 +4,7 @@ <MkSpacer :content-max="700" :margin-min="16"> <div class="lxpfedzu"> <div class="banner"> - <img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> + <img :src="instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> </div> <MkInfo v-if="thereIsUnresolvedAbuseReport" warn class="info">{{ i18n.ts.thereIsUnresolvedAbuseReportWarning }} <MkA to="/admin/abuses" class="_link">{{ i18n.ts.check }}</MkA></MkInfo> @@ -221,7 +221,7 @@ onUnmounted(() => { }); watch(router.currentRef, (to) => { - if (to.route.path === "/admin" && to.child?.route.name == null && !narrow) { + if (to.route.path === '/admin' && to.child?.route.name == null && !narrow) { router.replace('/admin/overview'); } }); diff --git a/packages/frontend/src/pages/admin/object-storage.vue b/packages/frontend/src/pages/admin/object-storage.vue index cbe38b2d81..704b27c174 100644 --- a/packages/frontend/src/pages/admin/object-storage.vue +++ b/packages/frontend/src/pages/admin/object-storage.vue @@ -7,7 +7,7 @@ <MkSwitch v-model="useObjectStorage">{{ i18n.ts.useObjectStorage }}</MkSwitch> <template v-if="useObjectStorage"> - <MkInput v-model="objectStorageBaseUrl"> + <MkInput v-model="objectStorageBaseUrl" :placeholder="'https://example.com'"> <template #label>{{ i18n.ts.objectStorageBaseUrl }}</template> <template #caption>{{ i18n.ts.objectStorageBaseUrlDesc }}</template> </MkInput> @@ -22,8 +22,9 @@ <template #caption>{{ i18n.ts.objectStoragePrefixDesc }}</template> </MkInput> - <MkInput v-model="objectStorageEndpoint"> + <MkInput v-model="objectStorageEndpoint" :placeholder="'example.com'"> <template #label>{{ i18n.ts.objectStorageEndpoint }}</template> + <template #prefix>https://</template> <template #caption>{{ i18n.ts.objectStorageEndpointDesc }}</template> </MkInput> @@ -60,6 +61,7 @@ <MkSwitch v-model="objectStorageS3ForcePathStyle"> <template #label>s3ForcePathStyle</template> + <template #caption>{{ i18n.ts.s3ForcePathStyleDesc }}</template> </MkSwitch> </template> </div> diff --git a/packages/frontend/src/pages/admin/overview.instances.vue b/packages/frontend/src/pages/admin/overview.instances.vue index 7d530d6b95..6c2ffd4742 100644 --- a/packages/frontend/src/pages/admin/overview.instances.vue +++ b/packages/frontend/src/pages/admin/overview.instances.vue @@ -1,6 +1,6 @@ <template> <div class="wbrkwale"> - <Transition :name="$store.state.animation ? '_transition_zoom' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in"> <MkLoading v-if="fetching"/> <div v-else class="instances"> <MkA v-for="(instance, i) in instances" :key="instance.id" v-tooltip.mfm.noDelay="`${instance.name}\n${instance.host}\n${instance.softwareName} ${instance.softwareVersion}`" :to="`/instance-info/${instance.host}`" class="instance"> @@ -16,6 +16,7 @@ import { ref } from 'vue'; import * as os from '@/os'; import { useInterval } from '@/scripts/use-interval'; import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue'; +import { defaultStore } from '@/store'; const instances = ref([]); const fetching = ref(true); diff --git a/packages/frontend/src/pages/admin/overview.moderators.vue b/packages/frontend/src/pages/admin/overview.moderators.vue index ff689b8bf9..fee6a1394e 100644 --- a/packages/frontend/src/pages/admin/overview.moderators.vue +++ b/packages/frontend/src/pages/admin/overview.moderators.vue @@ -1,6 +1,6 @@ <template> <div> - <Transition :name="$store.state.animation ? '_transition_zoom' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in"> <MkLoading v-if="fetching"/> <div v-else :class="$style.root" class="_panel"> <MkA v-for="user in moderators" :key="user.id" class="user" :to="`/user-info/${user.id}`"> @@ -14,6 +14,7 @@ <script lang="ts" setup> import { onMounted } from 'vue'; import * as os from '@/os'; +import { defaultStore } from '@/store'; let moderators: any = $ref(null); let fetching = $ref(true); diff --git a/packages/frontend/src/pages/admin/overview.stats.vue b/packages/frontend/src/pages/admin/overview.stats.vue index 3dc1ed8ec5..142e70c698 100644 --- a/packages/frontend/src/pages/admin/overview.stats.vue +++ b/packages/frontend/src/pages/admin/overview.stats.vue @@ -1,6 +1,6 @@ <template> <div> - <Transition :name="$store.state.animation ? '_transition_zoom' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in"> <MkLoading v-if="fetching"/> <div v-else :class="$style.root"> <div class="item _panel users"> @@ -62,6 +62,7 @@ import MkNumberDiff from '@/components/MkNumberDiff.vue'; import MkNumber from '@/components/MkNumber.vue'; import { i18n } from '@/i18n'; import { customEmojis } from '@/custom-emojis'; +import { defaultStore } from '@/store'; let stats: any = $ref(null); let usersComparedToThePrevDay = $ref<number>(); diff --git a/packages/frontend/src/pages/admin/overview.users.vue b/packages/frontend/src/pages/admin/overview.users.vue index 3379d064cd..5df7b468f3 100644 --- a/packages/frontend/src/pages/admin/overview.users.vue +++ b/packages/frontend/src/pages/admin/overview.users.vue @@ -1,6 +1,6 @@ <template> <div :class="$style.root"> - <Transition :name="$store.state.animation ? '_transition_zoom' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" mode="out-in"> <MkLoading v-if="fetching"/> <div v-else class="users"> <MkA v-for="(user, i) in newUsers" :key="user.id" :to="`/user-info/${user.id}`" class="user"> @@ -15,6 +15,7 @@ import * as os from '@/os'; import { useInterval } from '@/scripts/use-interval'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; +import { defaultStore } from '@/store'; let newUsers = $ref(null); let fetching = $ref(true); diff --git a/packages/frontend/src/pages/admin/relays.vue b/packages/frontend/src/pages/admin/relays.vue index 55d33e0158..7ebcdfc583 100644 --- a/packages/frontend/src/pages/admin/relays.vue +++ b/packages/frontend/src/pages/admin/relays.vue @@ -9,7 +9,7 @@ <i v-if="relay.status === 'accepted'" class="ti ti-check icon accepted"></i> <i v-else-if="relay.status === 'rejected'" class="ti ti-ban icon rejected"></i> <i v-else class="ti ti-clock icon requesting"></i> - <span>{{ $t(`_relayStatus.${relay.status}`) }}</span> + <span>{{ i18n.t(`_relayStatus.${relay.status}`) }}</span> </div> <MkButton class="button" inline danger @click="remove(relay.inbox)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton> </div> diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue index 131f6d11ea..16a0ee8373 100644 --- a/packages/frontend/src/pages/announcements.vue +++ b/packages/frontend/src/pages/announcements.vue @@ -10,7 +10,7 @@ <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/> </div> <div v-if="$i && !announcement.isRead" class="footer"> - <MkButton primary @click="read(items, announcement, i)"><i class="ti ti-check"></i> {{ $ts.gotIt }}</MkButton> + <MkButton primary @click="read(items, announcement, i)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton> </div> </section> </MkPagination> @@ -25,6 +25,7 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { $i } from '@/account'; const pagination = { endpoint: 'announcements' as const, diff --git a/packages/frontend/src/pages/antenna-timeline.vue b/packages/frontend/src/pages/antenna-timeline.vue index cf803d6c7f..62e8178af1 100644 --- a/packages/frontend/src/pages/antenna-timeline.vue +++ b/packages/frontend/src/pages/antenna-timeline.vue @@ -2,7 +2,7 @@ <MkStickyContainer> <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <div ref="rootEl" v-hotkey.global="keymap" class="tqmomfks"> - <div v-if="queue > 0" class="new"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div> + <div v-if="queue > 0" class="new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div> <div class="tl"> <MkTimeline ref="tlEl" :key="antennaId" diff --git a/packages/frontend/src/pages/auth.form.vue b/packages/frontend/src/pages/auth.form.vue index f8484185f5..40a6d782b0 100644 --- a/packages/frontend/src/pages/auth.form.vue +++ b/packages/frontend/src/pages/auth.form.vue @@ -1,25 +1,25 @@ <template> - <section> - <div v-if="app.permission.length > 0"> - <p>{{ $t('_auth.permission', { name }) }}</p> - <ul> - <li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> - </ul> - </div> - <div>{{ i18n.t('_auth.shareAccess', { name: `${name} (${app.id})` }) }}</div> - <div :class="$style.buttons"> - <MkButton inline @click="cancel">{{ i18n.ts.cancel }}</MkButton> - <MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> - </div> - </section> +<section> + <div v-if="app.permission.length > 0"> + <p>{{ i18n.t('_auth.permission', { name }) }}</p> + <ul> + <li v-for="p in app.permission" :key="p">{{ i18n.t(`_permissions.${p}`) }}</li> + </ul> + </div> + <div>{{ i18n.t('_auth.shareAccess', { name: `${name} (${app.id})` }) }}</div> + <div :class="$style.buttons"> + <MkButton inline @click="cancel">{{ i18n.ts.cancel }}</MkButton> + <MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> + </div> +</section> </template> <script lang="ts" setup> import { } from 'vue'; +import { AuthSession } from 'misskey-js/built/entities'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; import { i18n } from '@/i18n'; -import { AuthSession } from 'misskey-js/built/entities'; const props = defineProps<{ session: AuthSession; diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue index 4f8afb9ea2..2f40e7ded6 100644 --- a/packages/frontend/src/pages/auth.vue +++ b/packages/frontend/src/pages/auth.vue @@ -20,7 +20,7 @@ <h1>{{ i18n.ts._auth.denied }}</h1> </div> <div v-if="state == 'accepted' && session"> - <h1>{{ session.app.isAuthorized ? $t('already-authorized') : i18n.ts.allowed }}</h1> + <h1>{{ session.app.isAuthorized ? i18n.t('already-authorized') : i18n.ts.allowed }}</h1> <p v-if="session.app.callbackUrl"> {{ i18n.ts._auth.callback }} <MkEllipsis/> diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index 76201aa85f..961ef4b751 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -2,9 +2,9 @@ <MkStickyContainer> <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="700"> - <Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="flash" :key="flash.id"> - <Transition :name="$store.state.animation ? 'zoom' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'zoom' : ''" mode="out-in"> <div v-if="started" :class="$style.started"> <div class="main _panel"> <MkAsUi v-if="root" :component="root" :components="components"/> @@ -63,6 +63,8 @@ import { AsUiComponent, AsUiRoot, registerAsUiLib } from '@/scripts/aiscript/ui' import { createAiScriptEnv } from '@/scripts/aiscript/api'; import MkFolder from '@/components/MkFolder.vue'; import MkCode from '@/components/MkCode.vue'; +import { defaultStore } from '@/store'; +import { $i } from '@/account'; const props = defineProps<{ id: string; diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue index 4bf7c8c514..e0f3c105e1 100644 --- a/packages/frontend/src/pages/gallery/post.vue +++ b/packages/frontend/src/pages/gallery/post.vue @@ -3,7 +3,7 @@ <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="1000" :margin-min="16" :margin-max="32"> <div class="_root"> - <Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="post" class="rkxwuolj"> <div class="files"> <div v-for="file in post.files" :key="file.id" class="file"> @@ -67,6 +67,8 @@ import { url } from '@/config'; import { useRouter } from '@/router'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { defaultStore } from '@/store'; +import { $i } from '@/account'; const router = useRouter(); diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue index 915adff277..8e0624f555 100644 --- a/packages/frontend/src/pages/miauth.vue +++ b/packages/frontend/src/pages/miauth.vue @@ -1,6 +1,6 @@ <template> <MkStickyContainer> - <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template> + <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="800"> <div v-if="$i"> <div v-if="state == 'waiting'"> @@ -15,13 +15,13 @@ </div> <div v-else> <div v-if="_permissions.length > 0"> - <p v-if="name">{{ $t('_auth.permission', { name }) }}</p> + <p v-if="name">{{ i18n.t('_auth.permission', { name }) }}</p> <p v-else>{{ i18n.ts._auth.permissionAsk }}</p> <ul> - <li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li> + <li v-for="p in _permissions" :key="p">{{ i18n.t(`_permissions.${p}`) }}</li> </ul> </div> - <div v-if="name">{{ $t('_auth.shareAccess', { name }) }}</div> + <div v-if="name">{{ i18n.t('_auth.shareAccess', { name }) }}</div> <div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div> <div :class="$style.buttons"> <MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton> diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue index 3e5e1ffe9d..d9baa1096a 100644 --- a/packages/frontend/src/pages/note.vue +++ b/packages/frontend/src/pages/note.vue @@ -3,7 +3,7 @@ <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="800"> <div class="fcuexfpr"> - <Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="note" class="note"> <div v-if="showNext" class="_margin"> <MkNotes class="" :pagination="nextPagination" :no-gap="true"/> @@ -50,6 +50,7 @@ import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; import { dateString } from '@/filters/date'; import MkClipPreview from '@/components/MkClipPreview.vue'; +import { defaultStore } from '@/store'; const props = defineProps<{ noteId: string; diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue index fe230ad095..ffeb8ba285 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue @@ -1,7 +1,7 @@ <template> <!-- eslint-disable vue/no-mutating-props --> <XContainer :draggable="true" @remove="() => $emit('remove')"> - <template #header><i class="ti ti-photo"></i> {{ $ts._pages.blocks.image }}</template> + <template #header><i class="ti ti-photo"></i> {{ i18n.ts._pages.blocks.image }}</template> <template #func> <button @click="choose()"> <i class="ti ti-folder"></i> @@ -20,6 +20,7 @@ import { onMounted } from 'vue'; import XContainer from '../page-editor.container.vue'; import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue'; import * as os from '@/os'; +import { i18n } from '@/i18n'; const props = defineProps<{ modelValue: any diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue index cc39d2c412..a388a8d0c1 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue @@ -1,14 +1,14 @@ <template> <!-- eslint-disable vue/no-mutating-props --> <XContainer :draggable="true" @remove="() => $emit('remove')"> - <template #header><i class="ti ti-note"></i> {{ $ts._pages.blocks.note }}</template> + <template #header><i class="ti ti-note"></i> {{ i18n.ts._pages.blocks.note }}</template> <section style="padding: 0 16px 0 16px;"> <MkInput v-model="id"> - <template #label>{{ $ts._pages.blocks._note.id }}</template> - <template #caption>{{ $ts._pages.blocks._note.idDescription }}</template> + <template #label>{{ i18n.ts._pages.blocks._note.id }}</template> + <template #caption>{{ i18n.ts._pages.blocks._note.idDescription }}</template> </MkInput> - <MkSwitch v-model="props.modelValue.detailed"><span>{{ $ts._pages.blocks._note.detailed }}</span></MkSwitch> + <MkSwitch v-model="props.modelValue.detailed"><span>{{ i18n.ts._pages.blocks._note.detailed }}</span></MkSwitch> <MkNote v-if="note && !props.modelValue.detailed" :key="note.id + ':normal'" v-model:note="note" style="margin-bottom: 16px;"/> <MkNoteDetailed v-if="note && props.modelValue.detailed" :key="note.id + ':detail'" v-model:note="note" style="margin-bottom: 16px;"/> @@ -25,6 +25,7 @@ import MkSwitch from '@/components/MkSwitch.vue'; import MkNote from '@/components/MkNote.vue'; import MkNoteDetailed from '@/components/MkNoteDetailed.vue'; import * as os from '@/os'; +import { i18n } from '@/i18n'; const props = defineProps<{ modelValue: any diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue index ee494b7574..bf21ae3c67 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue @@ -1,7 +1,7 @@ <template> <!-- eslint-disable vue/no-mutating-props --> <XContainer :draggable="true" @remove="() => $emit('remove')"> - <template #header><i class="ti ti-align-left"></i> {{ $ts._pages.blocks.text }}</template> + <template #header><i class="ti ti-align-left"></i> {{ i18n.ts._pages.blocks.text }}</template> <section class="vckmsadr"> <textarea v-model="text"></textarea> @@ -13,6 +13,7 @@ /* eslint-disable vue/no-mutating-props */ import { watch } from 'vue'; import XContainer from '../page-editor.container.vue'; +import { i18n } from '@/i18n'; const props = defineProps<{ modelValue: any diff --git a/packages/frontend/src/pages/page-editor/page-editor.container.vue b/packages/frontend/src/pages/page-editor/page-editor.container.vue index 15cdda5efb..dd733403af 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.container.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.container.vue @@ -16,8 +16,8 @@ </button> </div> </header> - <p v-show="showBody" v-if="error != null" class="error">{{ $t('_pages.script.typeError', { slot: error.arg + 1, expect: $t(`script.types.${error.expect}`), actual: $t(`script.types.${error.actual}`) }) }}</p> - <p v-show="showBody" v-if="warn != null" class="warn">{{ $t('_pages.script.thereIsEmptySlot', { slot: warn.slot + 1 }) }}</p> + <p v-show="showBody" v-if="error != null" class="error">{{ i18n.t('_pages.script.typeError', { slot: error.arg + 1, expect: i18n.t(`script.types.${error.expect}`), actual: i18n.t(`script.types.${error.actual}`) }) }}</p> + <p v-show="showBody" v-if="warn != null" class="warn">{{ i18n.t('_pages.script.thereIsEmptySlot', { slot: warn.slot + 1 }) }}</p> <div v-show="showBody" class="body"> <slot></slot> </div> @@ -26,6 +26,7 @@ <script lang="ts"> import { defineComponent } from 'vue'; +import { i18n } from '@/i18n'; export default defineComponent({ props: { @@ -54,6 +55,7 @@ export default defineComponent({ data() { return { showBody: this.expanded, + i18n, }; }, methods: { diff --git a/packages/frontend/src/pages/page-editor/page-editor.vue b/packages/frontend/src/pages/page-editor/page-editor.vue index c4b37c91c6..bcf30e23a7 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.vue @@ -3,42 +3,42 @@ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="700"> <div class="jqqmcavi"> - <MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="ti ti-external-link"></i> {{ $ts._pages.viewPage }}</MkButton> - <MkButton v-if="!readonly" inline primary class="button" @click="save"><i class="ti ti-device-floppy"></i> {{ $ts.save }}</MkButton> - <MkButton v-if="pageId" inline class="button" @click="duplicate"><i class="ti ti-copy"></i> {{ $ts.duplicate }}</MkButton> - <MkButton v-if="pageId && !readonly" inline class="button" danger @click="del"><i class="ti ti-trash"></i> {{ $ts.delete }}</MkButton> + <MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="ti ti-external-link"></i> {{ i18n.ts._pages.viewPage }}</MkButton> + <MkButton v-if="!readonly" inline primary class="button" @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> + <MkButton v-if="pageId" inline class="button" @click="duplicate"><i class="ti ti-copy"></i> {{ i18n.ts.duplicate }}</MkButton> + <MkButton v-if="pageId && !readonly" inline class="button" danger @click="del"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton> </div> <div v-if="tab === 'settings'"> <div class="_gaps_m"> <MkInput v-model="title"> - <template #label>{{ $ts._pages.title }}</template> + <template #label>{{ i18n.ts._pages.title }}</template> </MkInput> <MkInput v-model="summary"> - <template #label>{{ $ts._pages.summary }}</template> + <template #label>{{ i18n.ts._pages.summary }}</template> </MkInput> <MkInput v-model="name"> <template #prefix>{{ url }}/@{{ author.username }}/pages/</template> - <template #label>{{ $ts._pages.url }}</template> + <template #label>{{ i18n.ts._pages.url }}</template> </MkInput> - <MkSwitch v-model="alignCenter">{{ $ts._pages.alignCenter }}</MkSwitch> + <MkSwitch v-model="alignCenter">{{ i18n.ts._pages.alignCenter }}</MkSwitch> <MkSelect v-model="font"> - <template #label>{{ $ts._pages.font }}</template> - <option value="serif">{{ $ts._pages.fontSerif }}</option> - <option value="sans-serif">{{ $ts._pages.fontSansSerif }}</option> + <template #label>{{ i18n.ts._pages.font }}</template> + <option value="serif">{{ i18n.ts._pages.fontSerif }}</option> + <option value="sans-serif">{{ i18n.ts._pages.fontSansSerif }}</option> </MkSelect> - <MkSwitch v-model="hideTitleWhenPinned">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch> + <MkSwitch v-model="hideTitleWhenPinned">{{ i18n.ts._pages.hideTitleWhenPinned }}</MkSwitch> <div class="eyeCatch"> - <MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="ti ti-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton> + <MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="ti ti-plus"></i> {{ i18n.ts._pages.eyeCatchingImageSet }}</MkButton> <div v-else-if="eyeCatchingImage"> <img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/> - <MkButton v-if="!readonly" @click="removeEyeCatchingImage()"><i class="ti ti-trash"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton> + <MkButton v-if="!readonly" @click="removeEyeCatchingImage()"><i class="ti ti-trash"></i> {{ i18n.ts._pages.eyeCatchingImageRemove }}</MkButton> </div> </div> </div> diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index b26255ce61..5a0f58c8df 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -2,7 +2,7 @@ <MkStickyContainer> <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="700"> - <Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in"> + <Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in"> <div v-if="page" :key="page.id" class="xcukqgmh"> <div class="main"> <!-- @@ -75,8 +75,9 @@ import MkPagination from '@/components/MkPagination.vue'; import MkPagePreview from '@/components/MkPagePreview.vue'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; -import { pageViewInterruptors } from '@/store'; +import { pageViewInterruptors, defaultStore } from '@/store'; import { deepClone } from '@/scripts/clone'; +import { $i } from '@/account'; const props = defineProps<{ pageName: string; diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue index 861414cef8..955d812154 100644 --- a/packages/frontend/src/pages/settings/apps.vue +++ b/packages/frontend/src/pages/settings/apps.vue @@ -24,7 +24,7 @@ <details> <summary>{{ i18n.ts.details }}</summary> <ul> - <li v-for="p in token.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> + <li v-for="p in token.permission" :key="p">{{ i18n.t(`_permissions.${p}`) }}</li> </ul> </details> <div class="actions"> diff --git a/packages/frontend/src/pages/settings/delete-account.vue b/packages/frontend/src/pages/settings/delete-account.vue index bbd5513954..c6e79165c5 100644 --- a/packages/frontend/src/pages/settings/delete-account.vue +++ b/packages/frontend/src/pages/settings/delete-account.vue @@ -11,7 +11,7 @@ import FormInfo from '@/components/MkInfo.vue'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; -import { signout } from '@/account'; +import { signout, $i } from '@/account'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; diff --git a/packages/frontend/src/pages/settings/sounds.vue b/packages/frontend/src/pages/settings/sounds.vue index 006a2377d4..8855a275c6 100644 --- a/packages/frontend/src/pages/settings/sounds.vue +++ b/packages/frontend/src/pages/settings/sounds.vue @@ -8,7 +8,7 @@ <template #label>{{ i18n.ts.sounds }}</template> <div class="_gaps_s"> <MkFolder v-for="type in Object.keys(sounds)" :key="type"> - <template #label>{{ $t('_sfx.' + type) }}</template> + <template #label>{{ i18n.t('_sfx.' + type) }}</template> <template #suffix>{{ sounds[type].type ?? i18n.ts.none }}</template> <XSound :type="sounds[type].type" :volume="sounds[type].volume" @update="(res) => updated(type, res)"/> diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index 62b0b4551a..9f13f7a1dd 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -3,8 +3,8 @@ <template #header><MkPageHeader v-model:tab="src" :actions="headerActions" :tabs="$i ? headerTabs : headerTabsWhenNotLogin" :display-my-avatar="true"/></template> <MkSpacer :content-max="800"> <div ref="rootEl" v-hotkey.global="keymap"> - <XTutorial v-if="$i && $store.reactiveState.tutorial.value != -1" class="_panel" style="margin-bottom: var(--margin);"/> - <MkPostForm v-if="$store.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/> + <XTutorial v-if="$i && defaultStore.reactiveState.tutorial.value != -1" class="_panel" style="margin-bottom: var(--margin);"/> + <MkPostForm v-if="defaultStore.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/> <div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div> <div :class="$style.tl"> diff --git a/packages/frontend/src/pages/user-info.vue b/packages/frontend/src/pages/user-info.vue index 571f058240..94718d1533 100644 --- a/packages/frontend/src/pages/user-info.vue +++ b/packages/frontend/src/pages/user-info.vue @@ -192,7 +192,7 @@ import { url } from '@/config'; import { userPage, acct } from '@/filters/user'; import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; -import { iAmAdmin, iAmModerator } from '@/account'; +import { iAmAdmin, iAmModerator, $i } from '@/account'; import MkRolePreview from '@/components/MkRolePreview.vue'; const props = withDefaults(defineProps<{ diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index c45c0600a7..1ce0bedbe3 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -57,7 +57,7 @@ </dl> <dl v-if="user.birthday" class="field"> <dt class="name"><i class="ti ti-cake ti-fw"></i> {{ i18n.ts.birthday }}</dt> - <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd> + <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ i18n.t('yearsOld', { age }) }})</dd> </dl> <dl class="field"> <dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt> diff --git a/packages/frontend/src/pages/user/index.activity.vue b/packages/frontend/src/pages/user/index.activity.vue index 8ff3374446..2d9ee85bc4 100644 --- a/packages/frontend/src/pages/user/index.activity.vue +++ b/packages/frontend/src/pages/user/index.activity.vue @@ -1,7 +1,7 @@ <template> <MkContainer> <template #icon><i class="ti ti-chart-line"></i></template> - <template #header>{{ $ts.activity }}</template> + <template #header>{{ i18n.ts.activity }}</template> <template #func="{ buttonStyleClass }"> <button class="_button" :class="buttonStyleClass" @click="showMenu"> <i class="ti ti-dots"></i> diff --git a/packages/frontend/src/pages/user/index.photos.vue b/packages/frontend/src/pages/user/index.photos.vue index 85f6591eee..e710dab2d9 100644 --- a/packages/frontend/src/pages/user/index.photos.vue +++ b/packages/frontend/src/pages/user/index.photos.vue @@ -1,7 +1,7 @@ <template> <MkContainer :max-height="300" :foldable="true"> <template #icon><i class="ti ti-photo"></i></template> - <template #header>{{ $ts.images }}</template> + <template #header>{{ i18n.ts.images }}</template> <div :class="$style.root"> <MkLoading v-if="fetching"/> <div v-if="!fetching && images.length > 0" :class="$style.stream"> @@ -14,7 +14,7 @@ <ImgWithBlurhash :hash="image.file.blurhash" :src="thumbnail(image.file)" :title="image.file.name"/> </MkA> </div> - <p v-if="!fetching && images.length == 0" :class="$style.empty">{{ $ts.nothing }}</p> + <p v-if="!fetching && images.length == 0" :class="$style.empty">{{ i18n.ts.nothing }}</p> </div> </MkContainer> </template> diff --git a/packages/frontend/src/pages/welcome.entrance.a.vue b/packages/frontend/src/pages/welcome.entrance.a.vue index b6f9b3eb23..4d8d76db18 100644 --- a/packages/frontend/src/pages/welcome.entrance.a.vue +++ b/packages/frontend/src/pages/welcome.entrance.a.vue @@ -14,7 +14,7 @@ </div> <div class="contents"> <div class="main"> - <img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> + <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> <button class="_button _acrylic menu" @click="showMenu"><i class="ti ti-dots"></i></button> <div class="fg"> <h1> diff --git a/packages/frontend/src/pages/welcome.entrance.b.vue b/packages/frontend/src/pages/welcome.entrance.b.vue index 7c7dfcc850..03bf174710 100644 --- a/packages/frontend/src/pages/welcome.entrance.b.vue +++ b/packages/frontend/src/pages/welcome.entrance.b.vue @@ -10,22 +10,22 @@ </h1> <div class="about"> <!-- eslint-disable-next-line vue/no-v-html --> - <div class="desc" v-html="meta.description || $ts.headlineMisskey"></div> + <div class="desc" v-html="meta.description || i18n.ts.headlineMisskey"></div> </div> <div class="action"> - <MkButton class="signup" inline gradate @click="signup()">{{ $ts.signup }}</MkButton> - <MkButton class="signin" inline @click="signin()">{{ $ts.login }}</MkButton> + <MkButton class="signup" inline gradate @click="signup()">{{ i18n.ts.signup }}</MkButton> + <MkButton class="signin" inline @click="signin()">{{ i18n.ts.login }}</MkButton> </div> <div v-if="onlineUsersCount && stats" class="status"> <div> - <I18n :src="$ts.nUsers" text-tag="span" class="users"> + <I18n :src="i18n.ts.nUsers" text-tag="span" class="users"> <template #n><b>{{ number(stats.originalUsersCount) }}</b></template> </I18n> - <I18n :src="$ts.nNotes" text-tag="span" class="notes"> + <I18n :src="i18n.ts.nNotes" text-tag="span" class="notes"> <template #n><b>{{ number(stats.originalNotesCount) }}</b></template> </I18n> </div> - <I18n :src="$ts.onlineUsersCount" text-tag="span" class="online"> + <I18n :src="i18n.ts.onlineUsersCount" text-tag="span" class="online"> <template #n><b>{{ onlineUsersCount }}</b></template> </I18n> </div> @@ -47,6 +47,7 @@ import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue'; import { host, instanceName } from '@/config'; import * as os from '@/os'; import number from '@/filters/number'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -64,6 +65,7 @@ export default defineComponent({ stats: null, tags: [], onlineUsersCount: null, + i18n, }; }, @@ -103,19 +105,19 @@ export default defineComponent({ showMenu(ev) { os.popupMenu([{ - text: this.$t('aboutX', { x: instanceName }), + text: i18n.t('aboutX', { x: instanceName }), icon: 'ti ti-info-circle', action: () => { os.pageWindow('/about'); }, }, { - text: this.$ts.aboutMisskey, + text: i18n.ts.aboutMisskey, icon: 'ti ti-info-circle', action: () => { os.pageWindow('/about-misskey'); }, }, null, { - text: this.$ts.help, + text: i18n.ts.help, icon: 'ti ti-question-circle', action: () => { window.open('https://misskey-hub.net/help.md', '_blank'); diff --git a/packages/frontend/src/pages/welcome.entrance.c.vue b/packages/frontend/src/pages/welcome.entrance.c.vue index f566d1a56a..eca4e5764d 100644 --- a/packages/frontend/src/pages/welcome.entrance.c.vue +++ b/packages/frontend/src/pages/welcome.entrance.c.vue @@ -22,22 +22,22 @@ </h1> <div class="about"> <!-- eslint-disable-next-line vue/no-v-html --> - <div class="desc" v-html="meta.description || $ts.headlineMisskey"></div> + <div class="desc" v-html="meta.description || i18n.ts.headlineMisskey"></div> </div> <div class="action"> - <MkButton inline gradate @click="signup()">{{ $ts.signup }}</MkButton> - <MkButton inline @click="signin()">{{ $ts.login }}</MkButton> + <MkButton inline gradate @click="signup()">{{ i18n.ts.signup }}</MkButton> + <MkButton inline @click="signin()">{{ i18n.ts.login }}</MkButton> </div> <div v-if="onlineUsersCount && stats" class="status"> <div> - <I18n :src="$ts.nUsers" text-tag="span" class="users"> + <I18n :src="i18n.ts.nUsers" text-tag="span" class="users"> <template #n><b>{{ number(stats.originalUsersCount) }}</b></template> </I18n> - <I18n :src="$ts.nNotes" text-tag="span" class="notes"> + <I18n :src="i18n.ts.nNotes" text-tag="span" class="notes"> <template #n><b>{{ number(stats.originalNotesCount) }}</b></template> </I18n> </div> - <I18n :src="$ts.onlineUsersCount" text-tag="span" class="online"> + <I18n :src="i18n.ts.onlineUsersCount" text-tag="span" class="online"> <template #n><b>{{ onlineUsersCount }}</b></template> </I18n> </div> @@ -45,10 +45,10 @@ </div> </div> <nav class="nav"> - <MkA to="/announcements">{{ $ts.announcements }}</MkA> - <MkA to="/explore">{{ $ts.explore }}</MkA> - <MkA to="/channels">{{ $ts.channel }}</MkA> - <MkA to="/featured">{{ $ts.featured }}</MkA> + <MkA to="/announcements">{{ i18n.ts.announcements }}</MkA> + <MkA to="/explore">{{ i18n.ts.explore }}</MkA> + <MkA to="/channels">{{ i18n.ts.channel }}</MkA> + <MkA to="/featured">{{ i18n.ts.featured }}</MkA> </nav> </div> </div> @@ -58,15 +58,16 @@ <script lang="ts"> import { defineComponent } from 'vue'; import { toUnicode } from 'punycode/'; +import XTimeline from './welcome.timeline.vue'; import XSigninDialog from '@/components/MkSigninDialog.vue'; import XSignupDialog from '@/components/MkSignupDialog.vue'; import MkButton from '@/components/MkButton.vue'; import MkNote from '@/components/MkNote.vue'; import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue'; -import XTimeline from './welcome.timeline.vue'; import { host, instanceName } from '@/config'; import * as os from '@/os'; import number from '@/filters/number'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -84,6 +85,7 @@ export default defineComponent({ stats: null, tags: [], onlineUsersCount: null, + i18n, }; }, @@ -123,22 +125,22 @@ export default defineComponent({ showMenu(ev) { os.popupMenu([{ - text: this.$t('aboutX', { x: instanceName }), + text: i18n.t('aboutX', { x: instanceName }), icon: 'ti ti-info-circle', action: () => { os.pageWindow('/about'); }, }, { - text: this.$ts.aboutMisskey, + text: i18n.ts.aboutMisskey, icon: 'ti ti-info-circle', action: () => { os.pageWindow('/about-misskey'); }, }, null, { - text: this.$ts.help, + text: i18n.ts.help, icon: 'ti ti-question-circle', action: () => { - window.open(`https://misskey-hub.net/help.md`, '_blank'); + window.open('https://misskey-hub.net/help.md', '_blank'); }, }], ev.currentTarget ?? ev.target); }, diff --git a/packages/frontend/src/pages/welcome.setup.vue b/packages/frontend/src/pages/welcome.setup.vue index 8b43fa368b..212d156a83 100644 --- a/packages/frontend/src/pages/welcome.setup.vue +++ b/packages/frontend/src/pages/welcome.setup.vue @@ -2,19 +2,19 @@ <form class="mk-setup" @submit.prevent="submit()"> <h1>Welcome to Misskey!</h1> <div class="_gaps_m"> - <p>{{ $ts.intro }}</p> + <p>{{ i18n.ts.intro }}</p> <MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" :spellcheck="false" required data-cy-admin-username> - <template #label>{{ $ts.username }}</template> + <template #label>{{ i18n.ts.username }}</template> <template #prefix>@</template> <template #suffix>@{{ host }}</template> </MkInput> <MkInput v-model="password" type="password" data-cy-admin-password> - <template #label>{{ $ts.password }}</template> + <template #label>{{ i18n.ts.password }}</template> <template #prefix><i class="ti ti-lock"></i></template> </MkInput> <div class="bottom"> <MkButton gradate type="submit" :disabled="submitting" data-cy-admin-ok> - {{ submitting ? $ts.processing : $ts.done }}<MkEllipsis v-if="submitting"/> + {{ submitting ? i18n.ts.processing : i18n.ts.done }}<MkEllipsis v-if="submitting"/> </MkButton> </div> </div> diff --git a/packages/frontend/src/pages/welcome.timeline.vue b/packages/frontend/src/pages/welcome.timeline.vue index c34d43dc1c..6a507ee1ed 100644 --- a/packages/frontend/src/pages/welcome.timeline.vue +++ b/packages/frontend/src/pages/welcome.timeline.vue @@ -5,30 +5,31 @@ <div class="_panel" :class="$style.content"> <div :class="$style.body"> <MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA> - <Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" /> + <Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i"/> <MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA> </div> <div v-if="note.files.length > 0" :class="$style.richcontent"> - <MkMediaList :media-list="note.files" /> + <MkMediaList :media-list="note.files"/> </div> <div v-if="note.poll"> - <MkPoll :note="note" :readOnly="true" /> + <MkPoll :note="note" :read-only="true"/> </div> </div> - <MkReactionsViewer ref="reactionsViewer" :note="note" /> + <MkReactionsViewer ref="reactionsViewer" :note="note"/> </div> </div> </div> </template> <script lang="ts" setup> +import { Note } from 'misskey-js/built/entities'; +import { onUpdated } from 'vue'; import MkReactionsViewer from '@/components/MkReactionsViewer.vue'; import MkMediaList from '@/components/MkMediaList.vue'; import MkPoll from '@/components/MkPoll.vue'; import * as os from '@/os'; -import { Note } from 'misskey-js/built/entities'; -import { onUpdated } from 'vue'; import { getScrollContainer } from '@/scripts/scroll'; +import { $i } from '@/account'; let notes = $ref<Note[]>([]); let isScrolling = $ref(false); diff --git a/packages/frontend/src/ui/_common_/common.vue b/packages/frontend/src/ui/_common_/common.vue index 976345f9ee..e1561cb396 100644 --- a/packages/frontend/src/ui/_common_/common.vue +++ b/packages/frontend/src/ui/_common_/common.vue @@ -11,11 +11,11 @@ <TransitionGroup tag="div" :class="$style.notifications" - :move-class="$store.state.animation ? $style.transition_notification_move : ''" - :enter-active-class="$store.state.animation ? $style.transition_notification_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_notification_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_notification_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_notification_leaveTo : ''" + :move-class="defaultStore.state.animation ? $style.transition_notification_move : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_notification_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_notification_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_notification_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_notification_leaveTo : ''" > <XNotification v-for="notification in notifications" :key="notification.id" :notification="notification" :class="$style.notification"/> </TransitionGroup> @@ -40,6 +40,7 @@ import * as sound from '@/scripts/sound'; import { $i } from '@/account'; import { stream } from '@/stream'; import { i18n } from '@/i18n'; +import { defaultStore } from '@/store'; const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue')); const XUpload = defineAsyncComponent(() => import('./upload.vue')); diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 935aceea7c..7a94a0c3ee 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -2,9 +2,9 @@ <div class="kmwsukvl"> <div class="body"> <div class="top"> - <div class="banner" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"></div> + <div class="banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> <button v-click-anime class="item _button instance" @click="openInstanceMenu"> - <img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> + <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> </button> </div> <div class="middle"> @@ -47,9 +47,10 @@ import { computed, defineAsyncComponent, toRef } from 'vue'; import { openInstanceMenu } from './common'; import * as os from '@/os'; import { navbarItemDef } from '@/navbar'; -import { openAccountMenu as openAccountMenu_ } from '@/account'; +import { $i, openAccountMenu as openAccountMenu_ } from '@/account'; import { defaultStore } from '@/store'; import { i18n } from '@/i18n'; +import { instance } from '@/instance'; const menu = toRef(defaultStore.state, 'menu'); const otherMenuItemIndicated = computed(() => { diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index 3c161f6797..3b4b161422 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -2,9 +2,9 @@ <div class="mvcprjjd" :class="{ iconOnly }"> <div class="body"> <div class="top"> - <div class="banner" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"></div> - <button v-click-anime v-tooltip.noDelay.right="$instance.name ?? i18n.ts.instance" class="item _button instance" @click="openInstanceMenu"> - <img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> + <div class="banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div> + <button v-click-anime v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="item _button instance" @click="openInstanceMenu"> + <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> </button> </div> <div class="middle"> @@ -60,6 +60,7 @@ import { navbarItemDef } from '@/navbar'; import { $i, openAccountMenu as openAccountMenu_ } from '@/account'; import { defaultStore } from '@/store'; import { i18n } from '@/i18n'; +import { instance } from '@/instance'; const iconOnly = ref(false); diff --git a/packages/frontend/src/ui/_common_/stream-indicator.vue b/packages/frontend/src/ui/_common_/stream-indicator.vue index b46422d6cd..2a856e2a45 100644 --- a/packages/frontend/src/ui/_common_/stream-indicator.vue +++ b/packages/frontend/src/ui/_common_/stream-indicator.vue @@ -1,5 +1,5 @@ <template> -<div v-if="hasDisconnected && $store.state.serverDisconnectedBehavior === 'quiet'" :class="$style.root" class="_panel _shadow" @click="resetDisconnected"> +<div v-if="hasDisconnected && defaultStore.state.serverDisconnectedBehavior === 'quiet'" :class="$style.root" class="_panel _shadow" @click="resetDisconnected"> <div><i class="ti ti-alert-triangle"></i> {{ i18n.ts.disconnectedFromServer }}</div> <div :class="$style.command" class="_buttons"> <MkButton :class="$style.commandButton" small primary @click="reload">{{ i18n.ts.reload }}</MkButton> @@ -14,6 +14,7 @@ import { stream } from '@/stream'; import { i18n } from '@/i18n'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; +import { defaultStore } from '@/store'; const zIndex = os.claimZIndex('high'); diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue index 3dfb371d32..5e632c16d0 100644 --- a/packages/frontend/src/ui/classic.header.vue +++ b/packages/frontend/src/ui/classic.header.vue @@ -3,9 +3,9 @@ <div class="body"> <div class="left"> <button v-click-anime class="item _button instance" @click="openInstanceMenu"> - <img :src="$instance.iconUrl ?? $instance.faviconUrl ?? '/favicon.ico'" class="_ghost"/> + <img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" class="_ghost"/> </button> - <MkA v-click-anime v-tooltip="$ts.timeline" class="item index" active-class="active" to="/" exact> + <MkA v-click-anime v-tooltip="i18n.ts.timeline" class="item index" active-class="active" to="/" exact> <i class="ti ti-home ti-fw"></i> </MkA> <template v-for="item in menu"> @@ -16,7 +16,7 @@ </component> </template> <div class="divider"></div> - <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime v-tooltip="$ts.controlPanel" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null"> + <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime v-tooltip="i18n.ts.controlPanel" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null"> <i class="ti ti-dashboard ti-fw"></i> </MkA> <button v-click-anime class="item _button" @click="more"> @@ -25,7 +25,7 @@ </button> </div> <div class="right"> - <MkA v-click-anime v-tooltip="$ts.settings" class="item" active-class="active" to="/settings" :behavior="settingsWindowed ? 'modalWindow' : null"> + <MkA v-click-anime v-tooltip="i18n.ts.settings" class="item" active-class="active" to="/settings" :behavior="settingsWindowed ? 'modalWindow' : null"> <i class="ti ti-settings ti-fw"></i> </MkA> <button v-click-anime class="item _button account" @click="openAccountMenu"> @@ -47,9 +47,12 @@ import { openInstanceMenu } from './_common_/common'; import { host } from '@/config'; import * as os from '@/os'; import { navbarItemDef } from '@/navbar'; -import { openAccountMenu } from '@/account'; +import { openAccountMenu, $i } from '@/account'; import MkButton from '@/components/MkButton.vue'; import { mainRouter } from '@/router'; +import { defaultStore } from '@/store'; +import { instance } from '@/instance'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -63,12 +66,16 @@ export default defineComponent({ connection: null, navbarItemDef: navbarItemDef, settingsWindowed: false, + defaultStore, + instance, + $i, + i18n, }; }, computed: { menu(): string[] { - return this.$store.state.menu; + return defaultStore.state.menu; }, otherNavItemIndicated(): boolean { @@ -81,7 +88,7 @@ export default defineComponent({ }, watch: { - '$store.reactiveState.menuDisplay.value'() { + 'defaultStore.reactiveState.menuDisplay.value'() { this.calcViewState(); }, }, diff --git a/packages/frontend/src/ui/classic.sidebar.vue b/packages/frontend/src/ui/classic.sidebar.vue index 6fff233ac5..42ea5cd785 100644 --- a/packages/frontend/src/ui/classic.sidebar.vue +++ b/packages/frontend/src/ui/classic.sidebar.vue @@ -5,12 +5,12 @@ </button> <div class="post" data-cy-open-post-form @click="post"> <MkButton class="button" gradate full rounded> - <i class="ti ti-pencil ti-fw"></i><span v-if="!iconOnly" class="text">{{ $ts.note }}</span> + <i class="ti ti-pencil ti-fw"></i><span v-if="!iconOnly" class="text">{{ i18n.ts.note }}</span> </MkButton> </div> <div class="divider"></div> <MkA v-click-anime class="item index" active-class="active" to="/" exact> - <i class="ti ti-home ti-fw"></i><span class="text">{{ $ts.timeline }}</span> + <i class="ti ti-home ti-fw"></i><span class="text">{{ i18n.ts.timeline }}</span> </MkA> <template v-for="item in menu"> <div v-if="item === '-'" class="divider"></div> @@ -21,19 +21,19 @@ </template> <div class="divider"></div> <MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null"> - <i class="ti ti-dashboard ti-fw"></i><span class="text">{{ $ts.controlPanel }}</span> + <i class="ti ti-dashboard ti-fw"></i><span class="text">{{ i18n.ts.controlPanel }}</span> </MkA> <button v-click-anime class="item _button" @click="more"> - <i class="ti ti-dots ti-fw"></i><span class="text">{{ $ts.more }}</span> + <i class="ti ti-dots ti-fw"></i><span class="text">{{ i18n.ts.more }}</span> <span v-if="otherNavItemIndicated" class="indicator"><i class="_indicatorCircle"></i></span> </button> <MkA v-click-anime class="item" active-class="active" to="/settings" :behavior="settingsWindowed ? 'modalWindow' : null"> - <i class="ti ti-settings ti-fw"></i><span class="text">{{ $ts.settings }}</span> + <i class="ti ti-settings ti-fw"></i><span class="text">{{ i18n.ts.settings }}</span> </MkA> <div class="divider"></div> <div class="about"> <button v-click-anime class="item _button" @click="openInstanceMenu"> - <img :src="$instance.iconUrl ?? $instance.faviconUrl ?? '/favicon.ico'" class="_ghost"/> + <img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" class="_ghost"/> </button> </div> <!--<MisskeyLogo class="misskey"/>--> @@ -46,11 +46,14 @@ import { openInstanceMenu } from './_common_/common'; import { host } from '@/config'; import * as os from '@/os'; import { navbarItemDef } from '@/navbar'; -import { openAccountMenu } from '@/account'; +import { openAccountMenu, $i } from '@/account'; import MkButton from '@/components/MkButton.vue'; import { StickySidebar } from '@/scripts/sticky-sidebar'; import { mainRouter } from '@/router'; //import MisskeyLogo from '@assets/client/misskey.svg'; +import { defaultStore } from '@/store'; +import { instance } from '@/instance'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -66,12 +69,16 @@ export default defineComponent({ navbarItemDef: navbarItemDef, iconOnly: false, settingsWindowed: false, + defaultStore, + instance, + $i, + i18n, }; }, computed: { menu(): string[] { - return this.$store.state.menu; + return this.defaultStore.state.menu; }, otherNavItemIndicated(): boolean { @@ -84,7 +91,7 @@ export default defineComponent({ }, watch: { - '$store.reactiveState.menuDisplay.value'() { + 'defaultStore.reactiveState.menuDisplay.value'() { this.calcViewState(); }, @@ -111,7 +118,7 @@ export default defineComponent({ openInstanceMenu, calcViewState() { - this.iconOnly = (window.innerWidth <= 1400) || (this.$store.state.menuDisplay === 'sideIcon'); + this.iconOnly = (window.innerWidth <= 1400) || (this.defaultStore.state.menuDisplay === 'sideIcon'); this.settingsWindowed = (window.innerWidth > 1400); }, diff --git a/packages/frontend/src/ui/classic.vue b/packages/frontend/src/ui/classic.vue index a359463d9b..4838272a9e 100644 --- a/packages/frontend/src/ui/classic.vue +++ b/packages/frontend/src/ui/classic.vue @@ -21,7 +21,7 @@ </div> </div> - <Transition :name="$store.state.animation ? 'tray-back' : ''"> + <Transition :name="defaultStore.state.animation ? 'tray-back' : ''"> <div v-if="widgetsShowing" class="tray-back _modalBg" @@ -30,11 +30,11 @@ ></div> </Transition> - <Transition :name="$store.state.animation ? 'tray' : ''"> + <Transition :name="defaultStore.state.animation ? 'tray' : ''"> <XWidgets v-if="widgetsShowing" class="tray"/> </Transition> - <iframe v-if="$store.state.aiChanMode" ref="live2d" class="ivnzpscs" src="https://misskey-dev.github.io/mascot-web/?scale=2&y=1.4"></iframe> + <iframe v-if="defaultStore.state.aiChanMode" ref="live2d" class="ivnzpscs" src="https://misskey-dev.github.io/mascot-web/?scale=2&y=1.4"></iframe> <XCommon/> </div> diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index be168b4282..4db7c9413a 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -53,10 +53,10 @@ </div> <Transition - :enter-active-class="$store.state.animation ? $style.transition_menuDrawerBg_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_menuDrawerBg_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_menuDrawerBg_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_menuDrawerBg_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_leaveTo : ''" > <div v-if="drawerMenuShowing" @@ -68,10 +68,10 @@ </Transition> <Transition - :enter-active-class="$store.state.animation ? $style.transition_menuDrawer_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_menuDrawer_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_menuDrawer_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_menuDrawer_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_menuDrawer_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_menuDrawer_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_menuDrawer_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_menuDrawer_leaveTo : ''" > <div v-if="drawerMenuShowing" :class="$style.menu"> <XDrawerMenu/> @@ -99,6 +99,7 @@ import { i18n } from '@/i18n'; import { mainRouter } from '@/router'; import { unisonReload } from '@/scripts/unison-reload'; import { deviceKind } from '@/scripts/device-kind'; +import { defaultStore } from '@/store'; const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue')); mainRouter.navHook = (path, flag): boolean => { diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index 11d1c85e38..ab3d01532b 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -27,10 +27,10 @@ </div> <Transition - :enter-active-class="$store.state.animation ? $style.transition_menuDrawerBg_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_menuDrawerBg_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_menuDrawerBg_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_menuDrawerBg_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_menuDrawerBg_leaveTo : ''" > <div v-if="drawerMenuShowing" @@ -42,10 +42,10 @@ </Transition> <Transition - :enter-active-class="$store.state.animation ? $style.transition_menuDrawer_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_menuDrawer_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_menuDrawer_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_menuDrawer_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_menuDrawer_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_menuDrawer_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_menuDrawer_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_menuDrawer_leaveTo : ''" > <div v-if="drawerMenuShowing" :class="$style.menuDrawer"> <XDrawerMenu/> @@ -53,10 +53,10 @@ </Transition> <Transition - :enter-active-class="$store.state.animation ? $style.transition_widgetsDrawerBg_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_widgetsDrawerBg_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_widgetsDrawerBg_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_widgetsDrawerBg_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_widgetsDrawerBg_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_widgetsDrawerBg_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_widgetsDrawerBg_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_widgetsDrawerBg_leaveTo : ''" > <div v-if="widgetsShowing" @@ -68,10 +68,10 @@ </Transition> <Transition - :enter-active-class="$store.state.animation ? $style.transition_widgetsDrawer_enterActive : ''" - :leave-active-class="$store.state.animation ? $style.transition_widgetsDrawer_leaveActive : ''" - :enter-from-class="$store.state.animation ? $style.transition_widgetsDrawer_enterFrom : ''" - :leave-to-class="$store.state.animation ? $style.transition_widgetsDrawer_leaveTo : ''" + :enter-active-class="defaultStore.state.animation ? $style.transition_widgetsDrawer_enterActive : ''" + :leave-active-class="defaultStore.state.animation ? $style.transition_widgetsDrawer_leaveActive : ''" + :enter-from-class="defaultStore.state.animation ? $style.transition_widgetsDrawer_enterFrom : ''" + :leave-to-class="defaultStore.state.animation ? $style.transition_widgetsDrawer_leaveTo : ''" > <div v-if="widgetsShowing" :class="$style.widgetsDrawer"> <button class="_button" :class="$style.widgetsCloseButton" @click="widgetsShowing = false"><i class="ti ti-x"></i></button> diff --git a/packages/frontend/src/ui/visitor/a.vue b/packages/frontend/src/ui/visitor/a.vue index 023b7fdb94..4761036075 100644 --- a/packages/frontend/src/ui/visitor/a.vue +++ b/packages/frontend/src/ui/visitor/a.vue @@ -1,19 +1,19 @@ <template> <div class="mk-app"> - <div v-if="mainRouter.currentRoute?.name === 'index'" class="banner" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"> + <div v-if="mainRouter.currentRoute?.name === 'index'" class="banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"> <div> <h1 v-if="meta"><img v-if="meta.logoImageUrl" class="logo" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span></h1> <div v-if="meta" class="about"> <!-- eslint-disable-next-line vue/no-v-html --> - <div class="desc" v-html="meta.description || $ts.introMisskey"></div> + <div class="desc" v-html="meta.description || i18n.ts.introMisskey"></div> </div> <div class="action"> - <button class="_button primary" @click="signup()">{{ $ts.signup }}</button> - <button class="_button" @click="signin()">{{ $ts.login }}</button> + <button class="_button primary" @click="signup()">{{ i18n.ts.signup }}</button> + <button class="_button" @click="signin()">{{ i18n.ts.login }}</button> </div> </div> </div> - <div v-else class="banner-mini" :style="{ backgroundImage: `url(${ $instance.bannerUrl })` }"> + <div v-else class="banner-mini" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"> <div> <h1 v-if="meta"><img v-if="meta.logoImageUrl" class="logo" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span></h1> </div> @@ -42,8 +42,10 @@ import XHeader from './header.vue'; import { host, instanceName } from '@/config'; import * as os from '@/os'; import MkButton from '@/components/MkButton.vue'; -import { ColdDeviceStorage } from '@/store'; +import { defaultStore, ColdDeviceStorage } from '@/store'; import { mainRouter } from '@/router'; +import { instance } from '@/instance'; +import { i18n } from '@/i18n'; const DESKTOP_THRESHOLD = 1100; @@ -66,6 +68,9 @@ export default defineComponent({ }, mainRouter, isDesktop: window.innerWidth >= DESKTOP_THRESHOLD, + defaultStore, + instance, + i18n, }; }, @@ -74,7 +79,7 @@ export default defineComponent({ return { 'd': () => { if (ColdDeviceStorage.get('syncDeviceDarkMode')) return; - this.$store.set('darkMode', !this.$store.state.darkMode); + this.defaultStore.set('darkMode', !this.defaultStore.state.darkMode); }, 's': () => { mainRouter.push('/search'); diff --git a/packages/frontend/src/ui/visitor/b.vue b/packages/frontend/src/ui/visitor/b.vue index e2168768e8..5287a670c5 100644 --- a/packages/frontend/src/ui/visitor/b.vue +++ b/packages/frontend/src/ui/visitor/b.vue @@ -24,7 +24,7 @@ </div> </div> - <Transition :name="$store.state.animation ? 'tray-back' : ''"> + <Transition :name="'tray-back'"> <div v-if="showMenu" class="menu-back _modalBg" @@ -33,20 +33,20 @@ ></div> </Transition> - <Transition :name="$store.state.animation ? 'tray' : ''"> + <Transition :name="'tray'"> <div v-if="showMenu" class="menu"> - <MkA to="/" class="link" active-class="active"><i class="ti ti-home icon"></i>{{ $ts.home }}</MkA> - <MkA v-if="isTimelineAvailable" to="/timeline" class="link" active-class="active"><i class="ti ti-message icon"></i>{{ $ts.timeline }}</MkA> - <MkA to="/explore" class="link" active-class="active"><i class="ti ti-hash icon"></i>{{ $ts.explore }}</MkA> - <MkA to="/announcements" class="link" active-class="active"><i class="ti ti-speakerphone icon"></i>{{ $ts.announcements }}</MkA> - <MkA to="/channels" class="link" active-class="active"><i class="ti ti-device-tv icon"></i>{{ $ts.channel }}</MkA> + <MkA to="/" class="link" active-class="active"><i class="ti ti-home icon"></i>{{ i18n.ts.home }}</MkA> + <MkA v-if="isTimelineAvailable" to="/timeline" class="link" active-class="active"><i class="ti ti-message icon"></i>{{ i18n.ts.timeline }}</MkA> + <MkA to="/explore" class="link" active-class="active"><i class="ti ti-hash icon"></i>{{ i18n.ts.explore }}</MkA> + <MkA to="/announcements" class="link" active-class="active"><i class="ti ti-speakerphone icon"></i>{{ i18n.ts.announcements }}</MkA> + <MkA to="/channels" class="link" active-class="active"><i class="ti ti-device-tv icon"></i>{{ i18n.ts.channel }}</MkA> <div class="divider"></div> - <MkA to="/pages" class="link" active-class="active"><i class="ti ti-news icon"></i>{{ $ts.pages }}</MkA> + <MkA to="/pages" class="link" active-class="active"><i class="ti ti-news icon"></i>{{ i18n.ts.pages }}</MkA> <MkA to="/play" class="link" active-class="active"><i class="ti ti-player-play icon"></i>Play</MkA> - <MkA to="/gallery" class="link" active-class="active"><i class="ti ti-icons icon"></i>{{ $ts.gallery }}</MkA> + <MkA to="/gallery" class="link" active-class="active"><i class="ti ti-icons icon"></i>{{ i18n.ts.gallery }}</MkA> <div class="action"> - <button class="_buttonPrimary" @click="signup()">{{ $ts.signup }}</button> - <button class="_button" @click="signin()">{{ $ts.login }}</button> + <button class="_buttonPrimary" @click="signup()">{{ i18n.ts.signup }}</button> + <button class="_button" @click="signin()">{{ i18n.ts.login }}</button> </div> </div> </Transition> @@ -65,6 +65,7 @@ import XSignupDialog from '@/components/MkSignupDialog.vue'; import { ColdDeviceStorage, defaultStore } from '@/store'; import { mainRouter } from '@/router'; import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata'; +import { i18n } from '@/i18n'; const DESKTOP_THRESHOLD = 1100; diff --git a/packages/frontend/src/ui/visitor/header.vue b/packages/frontend/src/ui/visitor/header.vue index aaa7e77e90..7de81f6431 100644 --- a/packages/frontend/src/ui/visitor/header.vue +++ b/packages/frontend/src/ui/visitor/header.vue @@ -2,14 +2,14 @@ <div class="sqxihjet"> <div v-if="narrow === false" class="wide"> <div class="content"> - <MkA to="/" class="link" active-class="active"><i class="ti ti-home icon"></i>{{ $ts.home }}</MkA> - <MkA v-if="isTimelineAvailable" to="/timeline" class="link" active-class="active"><i class="ti ti-message icon"></i>{{ $ts.timeline }}</MkA> - <MkA to="/explore" class="link" active-class="active"><i class="ti ti-hash icon"></i>{{ $ts.explore }}</MkA> - <MkA to="/channels" class="link" active-class="active"><i class="ti ti-device-tv icon"></i>{{ $ts.channel }}</MkA> + <MkA to="/" class="link" active-class="active"><i class="ti ti-home icon"></i>{{ i18n.ts.home }}</MkA> + <MkA v-if="isTimelineAvailable" to="/timeline" class="link" active-class="active"><i class="ti ti-message icon"></i>{{ i18n.ts.timeline }}</MkA> + <MkA to="/explore" class="link" active-class="active"><i class="ti ti-hash icon"></i>{{ i18n.ts.explore }}</MkA> + <MkA to="/channels" class="link" active-class="active"><i class="ti ti-device-tv icon"></i>{{ i18n.ts.channel }}</MkA> <div class="right"> - <button class="_button search" @click="search()"><i class="ti ti-search icon"></i><span>{{ $ts.search }}</span></button> - <button class="_buttonPrimary signup" @click="signup()">{{ $ts.signup }}</button> - <button class="_button login" @click="signin()">{{ $ts.login }}</button> + <button class="_button search" @click="search()"><i class="ti ti-search icon"></i><span>{{ i18n.ts.search }}</span></button> + <button class="_buttonPrimary signup" @click="signup()">{{ i18n.ts.signup }}</button> + <button class="_button login" @click="signin()">{{ i18n.ts.login }}</button> </div> </div> </div> @@ -28,6 +28,7 @@ import XSignupDialog from '@/components/MkSignupDialog.vue'; import * as os from '@/os'; import { instance } from '@/instance'; import { mainRouter } from '@/router'; +import { i18n } from '@/i18n'; export default defineComponent({ data() { @@ -35,6 +36,7 @@ export default defineComponent({ narrow: null, showMenu: false, isTimelineAvailable: instance.policies.ltlAvailable || instance.policies.gtlAvailable, + i18n, }; }, diff --git a/packages/frontend/src/ui/visitor/kanban.vue b/packages/frontend/src/ui/visitor/kanban.vue index 05ded834ee..ce7fcfe944 100644 --- a/packages/frontend/src/ui/visitor/kanban.vue +++ b/packages/frontend/src/ui/visitor/kanban.vue @@ -1,6 +1,6 @@ <!-- eslint-disable vue/no-v-html --> <template> -<div class="rwqkcmrc" :style="{ backgroundImage: transparent ? 'none' : `url(${ $instance.backgroundImageUrl })` }"> +<div class="rwqkcmrc" :style="{ backgroundImage: transparent ? 'none' : `url(${ instance.backgroundImageUrl })` }"> <div class="back" :class="{ transparent }"></div> <div class="contents"> <div class="wrapper"> @@ -9,14 +9,14 @@ </h1> <template v-if="full"> <div v-if="meta" class="about"> - <div class="desc" v-html="meta.description || $ts.introMisskey"></div> + <div class="desc" v-html="meta.description || i18n.ts.introMisskey"></div> </div> <div class="action"> - <button class="_buttonPrimary" @click="signup()">{{ $ts.signup }}</button> - <button class="_button" @click="signin()">{{ $ts.login }}</button> + <button class="_buttonPrimary" @click="signup()">{{ i18n.ts.signup }}</button> + <button class="_button" @click="signin()">{{ i18n.ts.login }}</button> </div> <div class="announcements panel"> - <header>{{ $ts.announcements }}</header> + <header>{{ i18n.ts.announcements }}</header> <MkPagination v-slot="{items}" :pagination="announcements" class="list"> <section v-for="announcement in items" :key="announcement.id" class="item"> <div class="title">{{ announcement.title }}</div> @@ -45,6 +45,8 @@ import MkPagination from '@/components/MkPagination.vue'; import XSigninDialog from '@/components/MkSigninDialog.vue'; import XSignupDialog from '@/components/MkSignupDialog.vue'; import MkButton from '@/components/MkButton.vue'; +import { instance } from '@/instance'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { @@ -81,6 +83,8 @@ export default defineComponent({ endpoint: 'announcements', limit: 10, }, + instance, + i18n, }; }, diff --git a/packages/frontend/src/widgets/WidgetCalendar.vue b/packages/frontend/src/widgets/WidgetCalendar.vue index de2e4b179d..58d0732263 100644 --- a/packages/frontend/src/widgets/WidgetCalendar.vue +++ b/packages/frontend/src/widgets/WidgetCalendar.vue @@ -2,11 +2,11 @@ <div :class="[$style.root, { _panel: !widgetProps.transparent }]" data-cy-mkw-calendar> <div :class="[$style.calendar, { [$style.isHoliday]: isHoliday }]"> <p :class="$style.monthAndYear"> - <span :class="$style.year">{{ $t('yearX', { year }) }}</span> - <span :class="$style.month">{{ $t('monthX', { month }) }}</span> + <span :class="$style.year">{{ i18n.t('yearX', { year }) }}</span> + <span :class="$style.month">{{ i18n.t('monthX', { month }) }}</span> </p> - <p v-if="month === 1 && day === 1" class="day">🎉{{ $t('dayX', { day }) }}<span style="display: inline-block; transform: scaleX(-1);">🎉</span></p> - <p v-else :class="$style.day">{{ $t('dayX', { day }) }}</p> + <p v-if="month === 1 && day === 1" class="day">🎉{{ i18n.t('dayX', { day }) }}<span style="display: inline-block; transform: scaleX(-1);">🎉</span></p> + <p v-else :class="$style.day">{{ i18n.t('dayX', { day }) }}</p> <p :class="$style.weekDay">{{ weekDay }}</p> </div> <div :class="$style.info"> diff --git a/packages/frontend/src/widgets/WidgetFederation.vue b/packages/frontend/src/widgets/WidgetFederation.vue index 7dcd5cb42e..2033b074e0 100644 --- a/packages/frontend/src/widgets/WidgetFederation.vue +++ b/packages/frontend/src/widgets/WidgetFederation.vue @@ -5,7 +5,7 @@ <div class="wbrkwalb"> <MkLoading v-if="fetching"/> - <TransitionGroup v-else tag="div" :name="$store.state.animation ? 'chart' : ''" class="instances"> + <TransitionGroup v-else tag="div" :name="defaultStore.state.animation ? 'chart' : ''" class="instances"> <div v-for="(instance, i) in instances" :key="instance.id" class="instance"> <img :src="getInstanceIcon(instance)" alt=""/> <div class="body"> @@ -29,6 +29,7 @@ import * as os from '@/os'; import { useInterval } from '@/scripts/use-interval'; import { i18n } from '@/i18n'; import { getProxiedImageUrlNullable } from '@/scripts/media-proxy'; +import { defaultStore } from '@/store'; const name = 'federation'; diff --git a/packages/frontend/src/widgets/WidgetInstanceInfo.vue b/packages/frontend/src/widgets/WidgetInstanceInfo.vue index 3a3b071b7d..d702fd2cb0 100644 --- a/packages/frontend/src/widgets/WidgetInstanceInfo.vue +++ b/packages/frontend/src/widgets/WidgetInstanceInfo.vue @@ -1,12 +1,12 @@ <template> <div class="_panel"> - <div :class="$style.container" :style="{ backgroundImage: $instance.bannerUrl ? `url(${ $instance.bannerUrl })` : null }"> + <div :class="$style.container" :style="{ backgroundImage: instance.bannerUrl ? `url(${ instance.bannerUrl })` : null }"> <div :class="$style.iconContainer"> - <img :src="$instance.iconUrl ?? $instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.icon"/> + <img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.icon"/> </div> <div :class="$style.bodyContainer"> <div :class="$style.body"> - <MkA :class="$style.name" to="/about" behavior="window">{{ $instance.name }}</MkA> + <MkA :class="$style.name" to="/about" behavior="window">{{ instance.name }}</MkA> <div :class="$style.host">{{ host }}</div> </div> </div> @@ -18,6 +18,7 @@ import { useWidgetPropsManager, Widget, WidgetComponentExpose } from './widget'; import { GetFormResultType } from '@/scripts/form'; import { host } from '@/config'; +import { instance } from '@/instance'; const name = 'instanceInfo'; diff --git a/packages/frontend/src/widgets/WidgetSlideshow.vue b/packages/frontend/src/widgets/WidgetSlideshow.vue index 22a0024271..915e7aaaf4 100644 --- a/packages/frontend/src/widgets/WidgetSlideshow.vue +++ b/packages/frontend/src/widgets/WidgetSlideshow.vue @@ -4,7 +4,7 @@ <p v-if="widgetProps.folderId == null"> {{ i18n.ts.folder }} </p> - <p v-if="widgetProps.folderId != null && images.length === 0 && !fetching">{{ $t('no-image') }}</p> + <p v-if="widgetProps.folderId != null && images.length === 0 && !fetching">{{ i18n.t('no-image') }}</p> <div ref="slideA" class="slide a"></div> <div ref="slideB" class="slide b"></div> </div> diff --git a/packages/frontend/src/widgets/WidgetTimeline.vue b/packages/frontend/src/widgets/WidgetTimeline.vue index 0f6f25b0a9..71ee75f6cb 100644 --- a/packages/frontend/src/widgets/WidgetTimeline.vue +++ b/packages/frontend/src/widgets/WidgetTimeline.vue @@ -10,7 +10,7 @@ </template> <template #header> <button class="_button" @click="choose"> - <span>{{ widgetProps.src === 'list' ? widgetProps.list.name : widgetProps.src === 'antenna' ? widgetProps.antenna.name : $t('_timelines.' + widgetProps.src) }}</span> + <span>{{ widgetProps.src === 'list' ? widgetProps.list.name : widgetProps.src === 'antenna' ? widgetProps.antenna.name : i18n.t('_timelines.' + widgetProps.src) }}</span> <i :class="menuOpened ? 'ti ti-chevron-up' : 'ti ti-chevron-down'" style="margin-left: 8px;"></i> </button> </template> diff --git a/packages/frontend/src/widgets/WidgetTrends.vue b/packages/frontend/src/widgets/WidgetTrends.vue index fc8a310ece..01450a7ab5 100644 --- a/packages/frontend/src/widgets/WidgetTrends.vue +++ b/packages/frontend/src/widgets/WidgetTrends.vue @@ -5,11 +5,11 @@ <div class="wbrkwala"> <MkLoading v-if="fetching"/> - <TransitionGroup v-else tag="div" :name="$store.state.animation ? 'chart' : ''" class="tags"> + <TransitionGroup v-else tag="div" :name="defaultStore.state.animation ? 'chart' : ''" class="tags"> <div v-for="stat in stats" :key="stat.tag"> <div class="tag"> <MkA class="a" :to="`/tags/${ encodeURIComponent(stat.tag) }`" :title="stat.tag">#{{ stat.tag }}</MkA> - <p>{{ $t('nUsersMentioned', { n: stat.usersCount }) }}</p> + <p>{{ i18n.t('nUsersMentioned', { n: stat.usersCount }) }}</p> </div> <MkMiniChart class="chart" :src="stat.chart"/> </div> @@ -27,6 +27,7 @@ import MkMiniChart from '@/components/MkMiniChart.vue'; import * as os from '@/os'; import { useInterval } from '@/scripts/use-interval'; import { i18n } from '@/i18n'; +import { defaultStore } from '@/store'; const name = 'hashtags'; |