Merge develop into feature/search-drive-via-alt-text
This commit is contained in:
		
						commit
						5e65b6d01d
					
				
					 318 changed files with 1986 additions and 1489 deletions
				
			
		| 
						 | 
				
			
			@ -7,9 +7,6 @@
 | 
			
		|||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<a href="https://fedidb.org/software/sharkey">
 | 
			
		||||
		<img src="https://custom-icon-badges.herokuapp.com/badge/find_an-instance-acea31?logoColor=acea31&style=for-the-badge&logo=sharkey&labelColor=363B40" alt="find an instance"/></a>
 | 
			
		||||
 | 
			
		||||
<a href="https://docs.joinsharkey.org/docs/install/fresh/">
 | 
			
		||||
		<img src="https://custom-icon-badges.herokuapp.com/badge/create_an-instance-FBD53C?logoColor=FBD53C&style=for-the-badge&logo=server&labelColor=363B40" alt="create an instance"/></a>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2432,6 +2432,7 @@ _notification:
 | 
			
		|||
    roleAssigned: "Role given"
 | 
			
		||||
    achievementEarned: "Achievement unlocked"
 | 
			
		||||
    app: "Notifications from linked apps"
 | 
			
		||||
    edited: "Edits"
 | 
			
		||||
  _actions:
 | 
			
		||||
    followBack: "followed you back"
 | 
			
		||||
    reply: "Reply"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								locales/index.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								locales/index.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -9435,6 +9435,10 @@ export interface Locale extends ILocale {
 | 
			
		|||
             * 連携アプリからの通知
 | 
			
		||||
             */
 | 
			
		||||
            "app": string;
 | 
			
		||||
            /**
 | 
			
		||||
             * 編集済み
 | 
			
		||||
             */
 | 
			
		||||
            "edited": string;
 | 
			
		||||
        };
 | 
			
		||||
        "_actions": {
 | 
			
		||||
            /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2490,6 +2490,7 @@ _notification:
 | 
			
		|||
    roleAssigned: "ロールが付与された"
 | 
			
		||||
    achievementEarned: "実績の獲得"
 | 
			
		||||
    app: "連携アプリからの通知"
 | 
			
		||||
    edited: "編集済み"
 | 
			
		||||
 | 
			
		||||
  _actions:
 | 
			
		||||
    followBack: "フォローバック"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,7 @@
 | 
			
		|||
		"content-disposition": "0.5.4",
 | 
			
		||||
		"date-fns": "2.30.0",
 | 
			
		||||
		"deep-email-validator": "0.1.21",
 | 
			
		||||
		"fast-xml-parser": "^4.4.0",
 | 
			
		||||
		"fastify": "4.26.2",
 | 
			
		||||
		"fastify-multer": "^2.0.3",
 | 
			
		||||
		"fastify-raw-body": "4.3.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
 | 
			
		||||
import { URL } from 'node:url';
 | 
			
		||||
import { Injectable } from '@nestjs/common';
 | 
			
		||||
import { query as urlQuery } from '@/misc/prelude/url.js';
 | 
			
		||||
import { XMLParser } from 'fast-xml-parser';
 | 
			
		||||
import { HttpRequestService } from '@/core/HttpRequestService.js';
 | 
			
		||||
import { bindThis } from '@/decorators.js';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,8 @@ export type IWebFinger = {
 | 
			
		|||
const urlRegex = /^https?:\/\//;
 | 
			
		||||
const mRegex = /^([^@]+)@(.*)/;
 | 
			
		||||
 | 
			
		||||
const defaultProtocol = process.env.MISSKEY_WEBFINGER_USE_HTTP?.toLowerCase() === 'true' ? 'http' : 'https';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class WebfingerService {
 | 
			
		||||
	constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -31,25 +33,76 @@ export class WebfingerService {
 | 
			
		|||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	public async webfinger(query: string): Promise<IWebFinger> {
 | 
			
		||||
		const url = this.genUrl(query);
 | 
			
		||||
		const hostMetaUrl = this.queryToHostMetaUrl(query);
 | 
			
		||||
		const template = await this.fetchWebFingerTemplateFromHostMeta(hostMetaUrl) ?? this.queryToWebFingerTemplate(query);
 | 
			
		||||
		const url = this.genUrl(query, template);
 | 
			
		||||
 | 
			
		||||
		return await this.httpRequestService.getJson<IWebFinger>(url, 'application/jrd+json, application/json');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	private genUrl(query: string): string {
 | 
			
		||||
	private genUrl(query: string, template: string): string {
 | 
			
		||||
		if (template.indexOf('{uri}') < 0) throw new Error(`Invalid webFingerUrl: ${template}`);
 | 
			
		||||
 | 
			
		||||
		if (query.match(urlRegex)) {
 | 
			
		||||
			return template.replace('{uri}', encodeURIComponent(query));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const m = query.match(mRegex);
 | 
			
		||||
		if (m) {
 | 
			
		||||
			return template.replace('{uri}', encodeURIComponent(`acct:${query}`));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		throw new Error(`Invalid query (${query})`);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	private queryToWebFingerTemplate(query: string): string {
 | 
			
		||||
		if (query.match(urlRegex)) {
 | 
			
		||||
			const u = new URL(query);
 | 
			
		||||
			return `${u.protocol}//${u.hostname}/.well-known/webfinger?` + urlQuery({ resource: query });
 | 
			
		||||
			return `${u.protocol}//${u.hostname}/.well-known/webfinger?resource={uri}`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const m = query.match(mRegex);
 | 
			
		||||
		if (m) {
 | 
			
		||||
			const hostname = m[2];
 | 
			
		||||
			const useHttp = process.env.MISSKEY_WEBFINGER_USE_HTTP && process.env.MISSKEY_WEBFINGER_USE_HTTP.toLowerCase() === 'true';
 | 
			
		||||
			return `http${useHttp ? '' : 's'}://${hostname}/.well-known/webfinger?${urlQuery({ resource: `acct:${query}` })}`;
 | 
			
		||||
			return `${defaultProtocol}//${hostname}/.well-known/webfinger?resource={uri}`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		throw new Error(`Invalid query (${query})`);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	private queryToHostMetaUrl(query: string): string {
 | 
			
		||||
		if (query.match(urlRegex)) {
 | 
			
		||||
			const u = new URL(query);
 | 
			
		||||
			return `${u.protocol}//${u.hostname}/.well-known/host-meta`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const m = query.match(mRegex);
 | 
			
		||||
		if (m) {
 | 
			
		||||
			const hostname = m[2];
 | 
			
		||||
			return `${defaultProtocol}://${hostname}/.well-known/host-meta`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		throw new Error(`Invalid query (${query})`);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
	private async fetchWebFingerTemplateFromHostMeta(url: string): Promise<string | null> {
 | 
			
		||||
		try {
 | 
			
		||||
			const res = await this.httpRequestService.getHtml(url, 'application/xrd+xml');
 | 
			
		||||
			const options = {
 | 
			
		||||
				ignoreAttributes: false,
 | 
			
		||||
				isArray: (_name: string, jpath: string) => jpath === 'XRD.Link',
 | 
			
		||||
			};
 | 
			
		||||
			const parser = new XMLParser(options);
 | 
			
		||||
			const hostMeta = parser.parse(res);
 | 
			
		||||
			const template = (hostMeta['XRD']['Link'] as Array<any>).filter(p => p['@_rel'] === 'lrdd')[0]['@_template'];
 | 
			
		||||
			return template.indexOf('{uri}') < 0 ? null : template;
 | 
			
		||||
		} catch (err) {
 | 
			
		||||
			console.error(`error while request host-meta for ${url}`);
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,10 @@
 | 
			
		|||
import ms from 'ms';
 | 
			
		||||
import { Inject, Injectable } from '@nestjs/common';
 | 
			
		||||
import { Endpoint } from '@/server/api/endpoint-base.js';
 | 
			
		||||
import type { UsersRepository, BlockingsRepository } from '@/models/_.js';
 | 
			
		||||
import type { UsersRepository, BlockingsRepository, MutingsRepository } from '@/models/_.js';
 | 
			
		||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
 | 
			
		||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
 | 
			
		||||
import { UserMutingService } from '@/core/UserMutingService.js';
 | 
			
		||||
import { DI } from '@/di-symbols.js';
 | 
			
		||||
import { GetterService } from '@/server/api/GetterService.js';
 | 
			
		||||
import { ApiError } from '../../error.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -69,9 +70,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
			
		|||
		@Inject(DI.blockingsRepository)
 | 
			
		||||
		private blockingsRepository: BlockingsRepository,
 | 
			
		||||
 | 
			
		||||
		@Inject(DI.mutingsRepository)
 | 
			
		||||
		private mutingsRepository: MutingsRepository,
 | 
			
		||||
 | 
			
		||||
		private userEntityService: UserEntityService,
 | 
			
		||||
		private getterService: GetterService,
 | 
			
		||||
		private userBlockingService: UserBlockingService,
 | 
			
		||||
		private userMutingService: UserMutingService,
 | 
			
		||||
	) {
 | 
			
		||||
		super(meta, paramDef, async (ps, me) => {
 | 
			
		||||
			const blocker = await this.usersRepository.findOneByOrFail({ id: me.id });
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +104,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
			
		|||
				throw new ApiError(meta.errors.alreadyBlocking);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			await this.userBlockingService.block(blocker, blockee);
 | 
			
		||||
			await Promise.all([
 | 
			
		||||
				this.userBlockingService.block(blocker, blockee),
 | 
			
		||||
				this.mutingsRepository.exists({
 | 
			
		||||
					where: {
 | 
			
		||||
						muterId: blocker.id,
 | 
			
		||||
						muteeId: blockee.id,
 | 
			
		||||
					},
 | 
			
		||||
				}).then(exists => {
 | 
			
		||||
					if (!exists) {
 | 
			
		||||
						this.userMutingService.mute(blocker, blockee, null);
 | 
			
		||||
					}
 | 
			
		||||
				}),
 | 
			
		||||
			]);
 | 
			
		||||
 | 
			
		||||
			return await this.userEntityService.pack(blockee.id, blocker, {
 | 
			
		||||
				schema: 'UserDetailedNotMe',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,10 @@
 | 
			
		|||
import ms from 'ms';
 | 
			
		||||
import { Inject, Injectable } from '@nestjs/common';
 | 
			
		||||
import { Endpoint } from '@/server/api/endpoint-base.js';
 | 
			
		||||
import type { UsersRepository, BlockingsRepository } from '@/models/_.js';
 | 
			
		||||
import type { UsersRepository, BlockingsRepository, MutingsRepository } from '@/models/_.js';
 | 
			
		||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
 | 
			
		||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
 | 
			
		||||
import { UserMutingService } from '@/core/UserMutingService.js';
 | 
			
		||||
import { DI } from '@/di-symbols.js';
 | 
			
		||||
import { GetterService } from '@/server/api/GetterService.js';
 | 
			
		||||
import { ApiError } from '../../error.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -69,9 +70,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
			
		|||
		@Inject(DI.blockingsRepository)
 | 
			
		||||
		private blockingsRepository: BlockingsRepository,
 | 
			
		||||
 | 
			
		||||
		@Inject(DI.mutingsRepository)
 | 
			
		||||
		private mutingsRepository: MutingsRepository,
 | 
			
		||||
 | 
			
		||||
		private userEntityService: UserEntityService,
 | 
			
		||||
		private getterService: GetterService,
 | 
			
		||||
		private userBlockingService: UserBlockingService,
 | 
			
		||||
		private userMutingService: UserMutingService,
 | 
			
		||||
	) {
 | 
			
		||||
		super(meta, paramDef, async (ps, me) => {
 | 
			
		||||
			const blocker = await this.usersRepository.findOneByOrFail({ id: me.id });
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +105,17 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			// Delete blocking
 | 
			
		||||
			await this.userBlockingService.unblock(blocker, blockee);
 | 
			
		||||
			await Promise.all([
 | 
			
		||||
				this.userBlockingService.unblock(blocker, blockee),
 | 
			
		||||
				this.mutingsRepository.findOneBy({
 | 
			
		||||
					muterId: blocker.id,
 | 
			
		||||
					muteeId: blockee.id,
 | 
			
		||||
				}).then(exists => {
 | 
			
		||||
					if (exists) {
 | 
			
		||||
						this.userMutingService.unmute([exists]);
 | 
			
		||||
					}
 | 
			
		||||
				}),
 | 
			
		||||
			]);
 | 
			
		||||
 | 
			
		||||
			return await this.userEntityService.pack(blockee.id, blocker, {
 | 
			
		||||
				schema: 'UserDetailedNotMe',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,20 +17,33 @@ import { bindThis } from '@/decorators.js';
 | 
			
		|||
import { ApiError } from '@/server/api/error.js';
 | 
			
		||||
import { MiMeta } from '@/models/Meta.js';
 | 
			
		||||
import type { FastifyRequest, FastifyReply } from 'fastify';
 | 
			
		||||
import * as Redis from 'ioredis';
 | 
			
		||||
import { RedisKVCache } from '@/misc/cache.js';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class UrlPreviewService {
 | 
			
		||||
	private logger: Logger;
 | 
			
		||||
	private previewCache: RedisKVCache<SummalyResult>;
 | 
			
		||||
 | 
			
		||||
	constructor(
 | 
			
		||||
		@Inject(DI.config)
 | 
			
		||||
		private config: Config,
 | 
			
		||||
 | 
			
		||||
		@Inject(DI.redis)
 | 
			
		||||
		private redisClient: Redis.Redis,
 | 
			
		||||
 | 
			
		||||
		private metaService: MetaService,
 | 
			
		||||
		private httpRequestService: HttpRequestService,
 | 
			
		||||
		private loggerService: LoggerService,
 | 
			
		||||
	) {
 | 
			
		||||
		this.logger = this.loggerService.getLogger('url-preview');
 | 
			
		||||
		this.previewCache = new RedisKVCache<SummalyResult>(this.redisClient, 'summaly', {
 | 
			
		||||
			lifetime: 1000 * 86400,
 | 
			
		||||
			memoryCacheLifetime: 1000 * 10 * 60,
 | 
			
		||||
			fetcher: (key: string) => { throw new Error('the UrlPreview cache should never fetch'); },
 | 
			
		||||
			toRedisConverter: (value) => JSON.stringify(value),
 | 
			
		||||
			fromRedisConverter: (value) => JSON.parse(value),
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@bindThis
 | 
			
		||||
| 
						 | 
				
			
			@ -75,9 +88,19 @@ export class UrlPreviewService {
 | 
			
		|||
			};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const key = `${url}@${lang}`;
 | 
			
		||||
		const cached = await this.previewCache.get(key);
 | 
			
		||||
		if (cached !== undefined) {
 | 
			
		||||
			this.logger.info(`Returning cache preview of ${key}`);
 | 
			
		||||
			// Cache 7days
 | 
			
		||||
			reply.header('Cache-Control', 'max-age=604800, immutable');
 | 
			
		||||
 | 
			
		||||
			return cached;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.logger.info(meta.urlPreviewSummaryProxyUrl
 | 
			
		||||
			? `(Proxy) Getting preview of ${url}@${lang} ...`
 | 
			
		||||
			: `Getting preview of ${url}@${lang} ...`);
 | 
			
		||||
			? `(Proxy) Getting preview of ${key} ...`
 | 
			
		||||
			: `Getting preview of ${key} ...`);
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			const summary = meta.urlPreviewSummaryProxyUrl
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +120,8 @@ export class UrlPreviewService {
 | 
			
		|||
			summary.icon = this.wrap(summary.icon);
 | 
			
		||||
			summary.thumbnail = this.wrap(summary.thumbnail);
 | 
			
		||||
 | 
			
		||||
			this.previewCache.set(key, summary);
 | 
			
		||||
 | 
			
		||||
			// Cache 7days
 | 
			
		||||
			reply.header('Cache-Control', 'max-age=604800, immutable');
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ import { M as MkContainer } from './MkContainer-!~{03M}~.js';
 | 
			
		|||
import { b as defineComponent, a as ref, e as onMounted, z as resolveComponent, g as openBlock, h as createBlock, i as withCtx, K as createTextVNode, E as toDisplayString, u as unref, l as createBaseVNode, q as normalizeClass, B as createCommentVNode, k as createElementBlock, F as Fragment, C as renderList, A as createVNode } from './vue-!~{002}~.js';
 | 
			
		||||
import './photoswipe-!~{003}~.js';
 | 
			
		||||
 | 
			
		||||
const _hoisted_1 = /* @__PURE__ */ createBaseVNode("i", { class: "ph-image-square ph-bold ph-lg" }, null, -1);
 | 
			
		||||
const _hoisted_1 = /* @__PURE__ */ createBaseVNode("i", { class: "ti ti-photo" }, null, -1);
 | 
			
		||||
const _sfc_main = /* @__PURE__ */ defineComponent({
 | 
			
		||||
  __name: "index.photos",
 | 
			
		||||
  props: {
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +178,7 @@ import {M as MkContainer} from './MkContainer-!~{03M}~.js';
 | 
			
		|||
import {b as defineComponent, a as ref, e as onMounted, z as resolveComponent, g as openBlock, h as createBlock, i as withCtx, K as createTextVNode, E as toDisplayString, u as unref, l as createBaseVNode, q as normalizeClass, B as createCommentVNode, k as createElementBlock, F as Fragment, C as renderList, A as createVNode} from './vue-!~{002}~.js';
 | 
			
		||||
import './photoswipe-!~{003}~.js';
 | 
			
		||||
const _hoisted_1 = createBaseVNode("i", {
 | 
			
		||||
  class: "ph-image-square ph-bold ph-lg"
 | 
			
		||||
  class: "ti ti-photo"
 | 
			
		||||
}, null, -1);
 | 
			
		||||
const index_photos = defineComponent({
 | 
			
		||||
  __name: "index.photos",
 | 
			
		||||
| 
						 | 
				
			
			@ -345,7 +345,7 @@ const _sfc_main = defineComponent({
 | 
			
		|||
            class: $style["date-1"]
 | 
			
		||||
          }, [
 | 
			
		||||
            h("i", {
 | 
			
		||||
              class: \`ph-caret-up ph-bold ph-lg \${$style["date-1-icon"]}\`
 | 
			
		||||
              class: \`ti ti-chevron-up \${$style["date-1-icon"]}\`
 | 
			
		||||
            }),
 | 
			
		||||
            getDateText(item.createdAt)
 | 
			
		||||
          ]),
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +354,7 @@ const _sfc_main = defineComponent({
 | 
			
		|||
          }, [
 | 
			
		||||
            getDateText(props.items[i + 1].createdAt),
 | 
			
		||||
            h("i", {
 | 
			
		||||
              class: \`ph-caret-down ph-bold ph-lg \${$style["date-2-icon"]}\`
 | 
			
		||||
              class: \`ti ti-chevron-down \${$style["date-2-icon"]}\`
 | 
			
		||||
            })
 | 
			
		||||
          ])
 | 
			
		||||
        ]));
 | 
			
		||||
| 
						 | 
				
			
			@ -511,11 +511,11 @@ const _sfc_main = defineComponent({
 | 
			
		|||
        }, [h("span", {
 | 
			
		||||
          class: $style["date-1"]
 | 
			
		||||
        }, [h("i", {
 | 
			
		||||
          class: \`ph-caret-up ph-bold ph-lg \${$style["date-1-icon"]}\`
 | 
			
		||||
          class: \`ti ti-chevron-up \${$style["date-1-icon"]}\`
 | 
			
		||||
        }), getDateText(item.createdAt)]), h("span", {
 | 
			
		||||
          class: $style["date-2"]
 | 
			
		||||
        }, [getDateText(props.items[i + 1].createdAt), h("i", {
 | 
			
		||||
          class: \`ph-caret-down ph-bold ph-lg \${$style["date-2-icon"]}\`
 | 
			
		||||
          class: \`ti ti-chevron-down \${$style["date-2-icon"]}\`
 | 
			
		||||
        })])]));
 | 
			
		||||
        return [el, separator];
 | 
			
		||||
      } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -293,7 +293,7 @@ export async function openAccountMenu(opts: {
 | 
			
		|||
			avatar: $i,
 | 
			
		||||
		}, { type: 'divider' as const }, ...(opts.includeCurrentAccount ? [createItem($i)] : []), ...accountItemPromises, {
 | 
			
		||||
			type: 'parent' as const,
 | 
			
		||||
			icon: 'ph-plus ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-plus',
 | 
			
		||||
			text: i18n.ts.addAccount,
 | 
			
		||||
			children: [{
 | 
			
		||||
				text: i18n.ts.existingAccount,
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +304,7 @@ export async function openAccountMenu(opts: {
 | 
			
		|||
			}],
 | 
			
		||||
		}, {
 | 
			
		||||
			type: 'link' as const,
 | 
			
		||||
			icon: 'ph-users ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-users',
 | 
			
		||||
			text: i18n.ts.manageAccounts,
 | 
			
		||||
			to: '/settings/accounts',
 | 
			
		||||
		}, {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<MkWindow ref="uiWindow" :initialWidth="400" :initialHeight="500" :canResize="true" @closed="emit('closed')">
 | 
			
		||||
	<template #header>
 | 
			
		||||
		<i class="ph-warning-circle ph-bold ph-lg" style="margin-right: 0.5em;"></i>
 | 
			
		||||
		<i class="ti ti-exclamation-circle" style="margin-right: 0.5em;"></i>
 | 
			
		||||
		<I18n :src="i18n.ts.reportAbuseOf" tag="span">
 | 
			
		||||
			<template #name>
 | 
			
		||||
				<b><MkAcct :user="user"/></b>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
<template>
 | 
			
		||||
<div v-if="user" :class="$style.root">
 | 
			
		||||
	<i class="ph-airplane-takeoff ph-bold ph-lg" style="margin-right: 8px;"></i>
 | 
			
		||||
	<i class="ti ti-plane-departure" style="margin-right: 8px;"></i>
 | 
			
		||||
	{{ i18n.ts.accountMoved }}
 | 
			
		||||
	<MkMention :class="$style.link" :username="user.username" :host="user.host ?? localHost"/>
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<div ref="rootEl" :class="$style.root">
 | 
			
		||||
		<div :class="$style.header">
 | 
			
		||||
			<span :class="$style.icon">
 | 
			
		||||
				<i v-if="announcement.icon === 'info'" class="ph-info ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'warning'" class="ph-warning-circle ph-bold ph-lg" style="color: var(--warn);"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'error'" class="ph-seal-warning ph-bold ph-lg" style="color: var(--error);"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'success'" class="ph-check-circle ph-bold ph-lg" style="color: var(--success);"></i>
 | 
			
		||||
				<i v-if="announcement.icon === 'info'" class="ti ti-info-circle"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'warning'" class="ti ti-alert-triangle" style="color: var(--warn);"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'error'" class="ti ti-circle-x" style="color: var(--error);"></i>
 | 
			
		||||
				<i v-else-if="announcement.icon === 'success'" class="ti ti-check" style="color: var(--success);"></i>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span :class="$style.title">{{ announcement.title }}</span>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,10 +12,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
>
 | 
			
		||||
	<template v-if="!wait">
 | 
			
		||||
		<template v-if="isFollowing">
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.unfollow }}</span><i class="ph-minus ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.unfollow }}</span><i class="ti ti-minus"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
		<template v-else>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.follow }}</span><i class="ph-plus ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.follow }}</span><i class="ti ti-plus"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
	</template>
 | 
			
		||||
	<template v-else>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,11 +8,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1" @click="updateLastReadedAt">
 | 
			
		||||
		<div class="banner" :style="bannerStyle">
 | 
			
		||||
			<div class="fade"></div>
 | 
			
		||||
			<div class="name"><i class="ph-television ph-bold ph-lg"></i> {{ channel.name }}</div>
 | 
			
		||||
			<div class="name"><i class="ti ti-device-tv"></i> {{ channel.name }}</div>
 | 
			
		||||
			<div v-if="channel.isSensitive" class="sensitiveIndicator">{{ i18n.ts.sensitive }}</div>
 | 
			
		||||
			<div class="status">
 | 
			
		||||
				<div>
 | 
			
		||||
					<i class="ph-users ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-users ti-fw"></i>
 | 
			
		||||
					<I18n :src="i18n.ts._channel.usersCount" tag="span" style="margin-left: 4px;">
 | 
			
		||||
						<template #n>
 | 
			
		||||
							<b>{{ channel.usersCount }}</b>
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					</I18n>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div>
 | 
			
		||||
					<i class="ph-pencil-simple ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-pencil ti-fw"></i>
 | 
			
		||||
					<I18n :src="i18n.ts._channel.notesCount" tag="span" style="margin-left: 4px;">
 | 
			
		||||
						<template #n>
 | 
			
		||||
							<b>{{ channel.notesCount }}</b>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<div>
 | 
			
		||||
	<div v-if="game.ready" :class="$style.game">
 | 
			
		||||
		<div :class="$style.cps" class="">{{ number(cps) }}cps</div>
 | 
			
		||||
		<div :class="$style.count" class=""><i class="ph-cookie ph-bold ph-lg" style="font-size: 70%;"></i> {{ number(cookies) }}</div>
 | 
			
		||||
		<div :class="$style.count" class=""><i class="ti ti-cookie" style="font-size: 70%;"></i> {{ number(cookies) }}</div>
 | 
			
		||||
		<button v-click-anime class="_button" @click="onClick">
 | 
			
		||||
			<img src="/client-assets/cookie.png" :class="$style.img">
 | 
			
		||||
		</button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div :class="$style.codeBlockRoot">
 | 
			
		||||
	<button :class="$style.codeBlockCopyButton" class="_button" @click="copy">
 | 
			
		||||
		<i class="ph-copy ph-bold ph-lg"></i>
 | 
			
		||||
		<i class="ti ti-copy"></i>
 | 
			
		||||
	</button>
 | 
			
		||||
	<Suspense>
 | 
			
		||||
		<template #fallback>
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<pre v-else-if="show" :class="$style.codeBlockFallbackRoot"><code :class="$style.codeBlockFallbackCode">{{ code }}</code></pre>
 | 
			
		||||
		<button v-else :class="$style.codePlaceholderRoot" @click="show = true">
 | 
			
		||||
			<div :class="$style.codePlaceholderContainer">
 | 
			
		||||
				<div><i class="ph-code ph-bold ph-lg"></i> {{ i18n.ts.code }}</div>
 | 
			
		||||
				<div><i class="ti ti-code"></i> {{ i18n.ts.code }}</div>
 | 
			
		||||
				<div>{{ i18n.ts.clickToShow }}</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div :class="$style.caption"><slot name="caption"></slot></div>
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-floppy-disk ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,8 +13,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<div :class="$style.headerSub">
 | 
			
		||||
			<slot name="func" :buttonStyleClass="$style.headerButton"></slot>
 | 
			
		||||
			<button v-if="foldable" :class="$style.headerButton" class="_button" @click="() => showBody = !showBody">
 | 
			
		||||
				<template v-if="showBody"><i class="ph-caret-up ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template v-else><i class="ph-caret-down ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template v-if="showBody"><i class="ti ti-chevron-up"></i></template>
 | 
			
		||||
				<template v-else><i class="ti ti-chevron-down"></i></template>
 | 
			
		||||
			</button>
 | 
			
		||||
		</div>
 | 
			
		||||
	</header>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ export default defineComponent({
 | 
			
		|||
						class: $style['date-1'],
 | 
			
		||||
					}, [
 | 
			
		||||
						h('i', {
 | 
			
		||||
							class: `ph-caret-up ph-bold ph-lg ${$style['date-1-icon']}`,
 | 
			
		||||
							class: `ti ti-chevron-up ${$style['date-1-icon']}`,
 | 
			
		||||
						}),
 | 
			
		||||
						getDateText(item.createdAt),
 | 
			
		||||
					]),
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ export default defineComponent({
 | 
			
		|||
					}, [
 | 
			
		||||
						getDateText(props.items[i + 1].createdAt),
 | 
			
		||||
						h('i', {
 | 
			
		||||
							class: `ph-caret-down ph-bold ph-lg ${$style['date-2-icon']}`,
 | 
			
		||||
							class: `ti ti-chevron-down ${$style['date-2-icon']}`,
 | 
			
		||||
						}),
 | 
			
		||||
					]),
 | 
			
		||||
				]));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,17 +18,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				[$style.type_info]: type === 'info',
 | 
			
		||||
			}]"
 | 
			
		||||
		>
 | 
			
		||||
			<i v-if="type === 'success'" :class="$style.iconInner" class="ph-check ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="type === 'error'" :class="$style.iconInner" class="ph-x-circle ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="type === 'warning'" :class="$style.iconInner" class="ph-warning ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="type === 'info'" :class="$style.iconInner" class="ph-info ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="type === 'question'" :class="$style.iconInner" class="ph-question ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-if="type === 'success'" :class="$style.iconInner" class="ti ti-check"></i>
 | 
			
		||||
			<i v-else-if="type === 'error'" :class="$style.iconInner" class="ti ti-circle-x"></i>
 | 
			
		||||
			<i v-else-if="type === 'warning'" :class="$style.iconInner" class="ti ti-alert-triangle"></i>
 | 
			
		||||
			<i v-else-if="type === 'info'" :class="$style.iconInner" class="ti ti-info-circle"></i>
 | 
			
		||||
			<i v-else-if="type === 'question'" :class="$style.iconInner" class="ti ti-help-circle"></i>
 | 
			
		||||
			<MkLoading v-else-if="type === 'waiting'" :class="$style.iconInner" :em="true"/>
 | 
			
		||||
		</div>
 | 
			
		||||
		<header v-if="title" :class="$style.title"><Mfm :text="title"/></header>
 | 
			
		||||
		<div v-if="text" :class="$style.text"><Mfm :text="text" :isBlock="true" /></div>
 | 
			
		||||
		<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
 | 
			
		||||
			<template v-if="input.type === 'password'" #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
			<template v-if="input.type === 'password'" #prefix><i class="ti ti-lock"></i></template>
 | 
			
		||||
			<template #caption>
 | 
			
		||||
				<span v-if="okButtonDisabledReason === 'charactersExceeded'" v-text="i18n.tsx._dialog.charactersExceeded({ current: (inputValue as string)?.length ?? 0, max: input.maxLength ?? 'NaN' })"/>
 | 
			
		||||
				<span v-else-if="okButtonDisabledReason === 'charactersBelow'" v-text="i18n.tsx._dialog.charactersBelow({ current: (inputValue as string)?.length ?? 0, min: input.minLength ?? 'NaN' })"/>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<MkButton @click="neverShow">{{ i18n.ts.neverShow }}</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<button class="_button" :class="$style.close" @click="close"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
	<button class="_button" :class="$style.close" @click="close"><i class="ti ti-x"></i></button>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	@dragend="onDragend"
 | 
			
		||||
>
 | 
			
		||||
	<p :class="$style.name">
 | 
			
		||||
		<template v-if="hover"><i :class="$style.icon" class="ph-folder ph-bold ph-lg ti-fw"></i></template>
 | 
			
		||||
		<template v-if="!hover"><i :class="$style.icon" class="ph-folder ph-bold ph-lg ti-fw"></i></template>
 | 
			
		||||
		<template v-if="hover"><i :class="$style.icon" class="ti ti-folder ti-fw"></i></template>
 | 
			
		||||
		<template v-if="!hover"><i :class="$style.icon" class="ti ti-folder ti-fw"></i></template>
 | 
			
		||||
		{{ folder.name }}
 | 
			
		||||
	</p>
 | 
			
		||||
	<p v-if="defaultStore.state.uploadFolder == folder.id" :class="$style.upload">
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +255,7 @@ function onContextmenu(ev: MouseEvent) {
 | 
			
		|||
	let menu: MenuItem[];
 | 
			
		||||
	menu = [{
 | 
			
		||||
		text: i18n.ts.openInWindow,
 | 
			
		||||
		icon: 'ph-app-window ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-app-window',
 | 
			
		||||
		action: () => {
 | 
			
		||||
			os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
 | 
			
		||||
				initialFolder: props.folder,
 | 
			
		||||
| 
						 | 
				
			
			@ -264,17 +264,17 @@ function onContextmenu(ev: MouseEvent) {
 | 
			
		|||
		},
 | 
			
		||||
	}, { type: 'divider' }, {
 | 
			
		||||
		text: i18n.ts.rename,
 | 
			
		||||
		icon: 'ph-textbox ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-forms',
 | 
			
		||||
		action: rename,
 | 
			
		||||
	}, { type: 'divider' }, {
 | 
			
		||||
		text: i18n.ts.delete,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		danger: true,
 | 
			
		||||
		action: deleteFolder,
 | 
			
		||||
	}];
 | 
			
		||||
	if (defaultStore.state.devMode) {
 | 
			
		||||
		menu = menu.concat([{ type: 'divider' }, {
 | 
			
		||||
			icon: 'ph-identification-card ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-id',
 | 
			
		||||
			text: i18n.ts.copyFolderId,
 | 
			
		||||
			action: () => {
 | 
			
		||||
				copyToClipboard(props.folder.id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	@dragleave="onDragleave"
 | 
			
		||||
	@drop.stop="onDrop"
 | 
			
		||||
>
 | 
			
		||||
	<i v-if="folder == null" class="ph-cloud ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
	<i v-if="folder == null" class="ti ti-cloud" style="margin-right: 4px;"></i>
 | 
			
		||||
	<span>{{ folder == null ? i18n.ts.drive : folder.name }}</span>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				@removeFolder="removeFolder"
 | 
			
		||||
			/>
 | 
			
		||||
			<template v-for="f in hierarchyFolders">
 | 
			
		||||
				<span :class="[$style.navPathItem, $style.navSeparator]"><i class="ph-caret-right ph-bold ph-lg"></i></span>
 | 
			
		||||
				<span :class="[$style.navPathItem, $style.navSeparator]"><i class="ti ti-chevron-right"></i></span>
 | 
			
		||||
				<XNavFolder
 | 
			
		||||
					:folder="f"
 | 
			
		||||
					:parentFolder="folder"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					@removeFolder="removeFolder"
 | 
			
		||||
				/>
 | 
			
		||||
			</template>
 | 
			
		||||
			<span v-if="folder != null" :class="[$style.navPathItem, $style.navSeparator]"><i class="ph-caret-right ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="folder != null" :class="[$style.navPathItem, $style.navSeparator]"><i class="ti ti-chevron-right"></i></span>
 | 
			
		||||
			<span v-if="folder != null" :class="[$style.navPathItem, $style.navCurrent]">{{ folder.name }}</span>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.navMenu">
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<template #prefix><i class="ph-magnifying-glass ph-bold ph-lg"></i></template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
 | 
			
		||||
			<button class="_button" @click="showMenu"><i class="ph-dots-three ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button class="_button" :class="$style.navMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
 | 
			
		||||
		</div>
 | 
			
		||||
	</nav>
 | 
			
		||||
	<div
 | 
			
		||||
| 
						 | 
				
			
			@ -637,26 +637,26 @@ function getMenu() {
 | 
			
		|||
		type: 'label',
 | 
			
		||||
	}, {
 | 
			
		||||
		text: i18n.ts.upload,
 | 
			
		||||
		icon: 'ph-upload ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-upload',
 | 
			
		||||
		action: () => { selectLocalFile(); },
 | 
			
		||||
	}, {
 | 
			
		||||
		text: i18n.ts.fromUrl,
 | 
			
		||||
		icon: 'ph-link ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-link',
 | 
			
		||||
		action: () => { urlUpload(); },
 | 
			
		||||
	}, { type: 'divider' }, {
 | 
			
		||||
		text: folder.value ? folder.value.name : i18n.ts.drive,
 | 
			
		||||
		type: 'label',
 | 
			
		||||
	}, folder.value ? {
 | 
			
		||||
		text: i18n.ts.renameFolder,
 | 
			
		||||
		icon: 'ph-textbox ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-forms',
 | 
			
		||||
		action: () => { if (folder.value) renameFolder(folder.value); },
 | 
			
		||||
	} : undefined, folder.value ? {
 | 
			
		||||
		text: i18n.ts.deleteFolder,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		action: () => { deleteFolder(folder.value as Misskey.entities.DriveFolder); },
 | 
			
		||||
	} : undefined, {
 | 
			
		||||
		text: i18n.ts.createFolder,
 | 
			
		||||
		icon: 'ph-folder ph-bold ph-lg-plus',
 | 
			
		||||
		icon: 'ti ti-folder-plus',
 | 
			
		||||
		action: () => { createFolder(); },
 | 
			
		||||
	}];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,16 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div ref="thumbnail" :class="$style.root">
 | 
			
		||||
	<ImgWithBlurhash v-if="isThumbnailAvailable" :hash="file.blurhash" :src="file.thumbnailUrl" :alt="file.name" :title="file.name" :cover="fit !== 'contain'"/>
 | 
			
		||||
	<i v-else-if="is === 'image'" class="ph-image-square ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'video'" class="ph-video ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'audio' || is === 'midi'" class="ph-file-audio ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'csv'" class="ph-file-text ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'pdf'" class="ph-file-text ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'textfile'" class="ph-file-text ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'archive'" class="ph-file-zip ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else class="ph-file ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'image'" class="ti ti-photo" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'video'" class="ti ti-video" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'audio' || is === 'midi'" class="ti ti-file-music" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'csv'" class="ti ti-file-text" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'pdf'" class="ti ti-file-text" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'textfile'" class="ti ti-file-text" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else-if="is === 'archive'" class="ti ti-file-zip" :class="$style.icon"></i>
 | 
			
		||||
	<i v-else class="ti ti-file" :class="$style.icon"></i>
 | 
			
		||||
 | 
			
		||||
	<i v-if="isThumbnailAvailable && is === 'video'" class="ph-video ph-bold ph-lg" :class="$style.iconSub"></i>
 | 
			
		||||
	<i v-if="isThumbnailAvailable && is === 'video'" class="ti ti-video" :class="$style.iconSub"></i>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<!-- フォルダの中にはカスタム絵文字だけ(Unicode絵文字もこっち) -->
 | 
			
		||||
<section v-if="!hasChildSection" v-panel style="border-radius: var(--radius-sm); border-bottom: 0.5px solid var(--divider);">
 | 
			
		||||
	<header class="_acrylic" @click="shown = !shown">
 | 
			
		||||
		<i class="toggle ti-fw" :class="shown ? 'ph-caret-down ph-bold ph-lg' : 'ph-caret-up ph-bold ph-lg'"></i> <slot></slot> (<i class="ph-bold ph-lg"></i>:{{ emojis.length }})
 | 
			
		||||
		<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> (<i class="ph-smiley-sticker ph-bold ph-lg"></i>:{{ emojis.length }})
 | 
			
		||||
	</header>
 | 
			
		||||
	<div v-if="shown" class="body">
 | 
			
		||||
		<button
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<!-- フォルダの中にはカスタム絵文字やフォルダがある -->
 | 
			
		||||
<section v-else v-panel style="border-radius: var(--radius-sm); border-bottom: 0.5px solid var(--divider);">
 | 
			
		||||
	<header class="_acrylic" @click="shown = !shown">
 | 
			
		||||
		<i class="toggle ti-fw" :class="shown ? 'ph-caret-down ph-bold ph-lg' : 'ph-caret-up ph-bold ph-lg'"></i> <slot></slot> (<i class="ph-folder ph-bold ph-lg"></i>:{{ customEmojiTree?.length }} <i class="ph-smiley-sticker ph-bold ph-lg ti-fw"></i>:{{ emojis.length }})
 | 
			
		||||
		<i class="toggle ti-fw" :class="shown ? 'ti ti-chevron-down' : 'ti ti-chevron-up'"></i> <slot></slot> (<i class="ti ti-folder ti-fw"></i>:{{ customEmojiTree?.length }} <i class="ph-smiley-sticker ph-bold ph-lg ti-fw"></i>:{{ emojis.length }})
 | 
			
		||||
	</header>
 | 
			
		||||
	<div v-if="shown" style="padding-left: 9px;">
 | 
			
		||||
		<MkEmojiPickerSection
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			</section>
 | 
			
		||||
 | 
			
		||||
			<section>
 | 
			
		||||
				<header class="_acrylic"><i class="ph-clock ph-bold ph-lg ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
 | 
			
		||||
				<header class="_acrylic"><i class="ti ti-clock ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
 | 
			
		||||
				<div class="body">
 | 
			
		||||
					<button
 | 
			
		||||
						v-for="emoji in recentlyUsedEmojisDef"
 | 
			
		||||
| 
						 | 
				
			
			@ -94,10 +94,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="tabs">
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ph-asterisk ph-bold ph-lg ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ph-smiley ph-bold ph-lg ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ph-leaf ph-bold ph-lg ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ph-hash ph-bold ph-lg ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ti ti-asterisk ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ti ti-mood-happy ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ti ti-leaf ti-fw"></i></button>
 | 
			
		||||
		<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ti ti-hash ti-fw"></i></button>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,8 +9,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<div :class="$style.title"><div><slot name="header"></slot></div></div>
 | 
			
		||||
		<div :class="$style.divider"></div>
 | 
			
		||||
		<button class="_button" :class="$style.button">
 | 
			
		||||
			<template v-if="showBody"><i class="ph-caret-up ph-bold ph-lg"></i></template>
 | 
			
		||||
			<template v-else><i class="ph-caret-down ph-bold ph-lg"></i></template>
 | 
			
		||||
			<template v-if="showBody"><i class="ti ti-chevron-up"></i></template>
 | 
			
		||||
			<template v-else><i class="ti ti-chevron-down"></i></template>
 | 
			
		||||
		</button>
 | 
			
		||||
	</header>
 | 
			
		||||
	<Transition
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,8 +19,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				</div>
 | 
			
		||||
				<div :class="$style.headerRight">
 | 
			
		||||
					<span :class="$style.headerRightText"><slot name="suffix"></slot></span>
 | 
			
		||||
					<i v-if="opened" class="ph-caret-up ph-bold ph-lg icon"></i>
 | 
			
		||||
					<i v-else class="ph-caret-down ph-bold ph-lg icon"></i>
 | 
			
		||||
					<i v-if="opened" class="ti ti-chevron-up icon"></i>
 | 
			
		||||
					<i v-else class="ti ti-chevron-down icon"></i>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,20 +12,20 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
>
 | 
			
		||||
	<template v-if="!wait">
 | 
			
		||||
		<template v-if="hasPendingFollowRequestFromYou && user.isLocked">
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.followRequestPending }}</span><i class="ph-hourglass ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.followRequestPending }}</span><i class="ti ti-hourglass-empty"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
		<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked">
 | 
			
		||||
			<!-- つまりリモートフォローの場合。 -->
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.processing }}</span><MkLoading :em="true" :colored="false"/>
 | 
			
		||||
		</template>
 | 
			
		||||
		<template v-else-if="isFollowing">
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.unfollow }}</span><i class="ph-minus ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.unfollow }}</span><i class="ti ti-minus"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
		<template v-else-if="!isFollowing && user.isLocked">
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.followRequest }}</span><i class="ph-plus ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.followRequest }}</span><i class="ti ti-plus"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
		<template v-else-if="!isFollowing && !user.isLocked">
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.follow }}</span><i class="ph-plus ph-bold ph-lg"></i>
 | 
			
		||||
			<span v-if="full" :class="$style.text">{{ i18n.ts.follow }}</span><i class="ti ti-plus"></i>
 | 
			
		||||
		</template>
 | 
			
		||||
	</template>
 | 
			
		||||
	<template v-else>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div :class="$style.root">
 | 
			
		||||
	<input v-model="query" :class="$style.input" type="search" :placeholder="q">
 | 
			
		||||
	<button :class="$style.button" @click="search"><i class="ph-magnifying-glass ph-bold ph-lg"></i> {{ i18n.ts.searchByGoogle }}</button>
 | 
			
		||||
	<button :class="$style.button" @click="search"><i class="ti ti-search"></i> {{ i18n.ts.searchByGoogle }}</button>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
<template>
 | 
			
		||||
<div :class="[$style.root, { [$style.warn]: warn }]">
 | 
			
		||||
	<i v-if="warn" class="ph-warning ph-bold ph-lg" :class="$style.i"></i>
 | 
			
		||||
	<i v-else class="ph-info ph-bold ph-lg" :class="$style.i"></i>
 | 
			
		||||
	<i v-if="warn" class="ti ti-alert-triangle" :class="$style.i"></i>
 | 
			
		||||
	<i v-else class="ti ti-info-circle" :class="$style.i"></i>
 | 
			
		||||
	<div><slot></slot></div>
 | 
			
		||||
	<button v-if="closable" :class="$style.button" class="_button" @click="close()"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
	<button v-if="closable" :class="$style.button" class="_button" @click="close()"><i class="ti ti-x"></i></button>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<div :class="$style.caption"><slot name="caption"></slot></div>
 | 
			
		||||
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-check ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,8 +50,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.buttons">
 | 
			
		||||
			<MkButton v-if="!invite.used && !isExpired" primary rounded @click="copyInviteCode()"><i class="ph-copy ph-bold ph-lg"></i> {{ i18n.ts.copy }}</MkButton>
 | 
			
		||||
			<MkButton v-if="!invite.used || moderator" danger rounded @click="deleteCode()"><i class="ph-trash ph-bold ph-lg"></i> {{ i18n.ts.delete }}</MkButton>
 | 
			
		||||
			<MkButton v-if="!invite.used && !isExpired" primary rounded @click="copyInviteCode()"><i class="ti ti-copy"></i> {{ i18n.ts.copy }}</MkButton>
 | 
			
		||||
			<MkButton v-if="!invite.used || moderator" danger rounded @click="deleteCode()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</MkFolder>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<div :class="$style.value">
 | 
			
		||||
		<slot name="value"></slot>
 | 
			
		||||
		<button v-if="copy" v-tooltip="i18n.ts.copy" class="_textButton" style="margin-left: 0.5em;" @click="copy_"><i class="ph-copy ph-bold ph-lg"></i></button>
 | 
			
		||||
		<button v-if="copy" v-tooltip="i18n.ts.copy" class="_textButton" style="margin-left: 0.5em;" @click="copy_"><i class="ti ti-copy"></i></button>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	@click.stop
 | 
			
		||||
>
 | 
			
		||||
	<slot></slot>
 | 
			
		||||
	<i v-if="target === '_blank'" class="ph-arrow-square-out ph-bold ph-lg" :class="$style.icon"></i>
 | 
			
		||||
	<i v-if="target === '_blank'" class="ti ti-external-link" :class="$style.icon"></i>
 | 
			
		||||
</component>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,8 +17,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
>
 | 
			
		||||
	<button v-if="hide" :class="$style.hidden" @click="hide = false">
 | 
			
		||||
		<div :class="$style.hiddenTextWrapper">
 | 
			
		||||
			<b v-if="audio.isSensitive" style="display: block;"><i class="ph-eye-slash ph-bold ph-lg"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.audio}${audio.size ? ' ' + bytes(audio.size) : ''})` : '' }}</b>
 | 
			
		||||
			<b v-else style="display: block;"><i class="ph-music-notes ph-bold ph-lg"></i> {{ defaultStore.state.dataSaver.media && audio.size ? bytes(audio.size) : i18n.ts.audio }}</b>
 | 
			
		||||
			<b v-if="audio.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.audio}${audio.size ? ' ' + bytes(audio.size) : ''})` : '' }}</b>
 | 
			
		||||
			<b v-else style="display: block;"><i class="ti ti-music"></i> {{ defaultStore.state.dataSaver.media && audio.size ? bytes(audio.size) : i18n.ts.audio }}</b>
 | 
			
		||||
			<span style="display: block;">{{ i18n.ts.clickToShow }}</span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</button>
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +44,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</audio>
 | 
			
		||||
		<div :class="[$style.controlsChild, $style.controlsLeft]">
 | 
			
		||||
			<button class="_button" :class="$style.controlButton" @click="togglePlayPause">
 | 
			
		||||
				<i v-if="isPlaying" class="ph-pause ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else class="ph-play ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="isPlaying" class="ti ti-player-pause-filled"></i>
 | 
			
		||||
				<i v-else class="ti ti-player-play-filled"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="[$style.controlsChild, $style.controlsRight]">
 | 
			
		||||
| 
						 | 
				
			
			@ -53,14 +53,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<i class="ph-download ph-bold ph-lg"></i>
 | 
			
		||||
			</a>
 | 
			
		||||
			<button class="_button" :class="$style.controlButton" @click="showMenu">
 | 
			
		||||
				<i class="ph-gear ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-settings"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="[$style.controlsChild, $style.controlsTime]">{{ hms(elapsedTimeMs) }}</div>
 | 
			
		||||
		<div :class="[$style.controlsChild, $style.controlsVolume]">
 | 
			
		||||
			<button class="_button" :class="$style.controlButton" @click="toggleMute">
 | 
			
		||||
				<i v-if="volume === 0" class="ph-speaker-x ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else class="ph-speaker-high ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="volume === 0" class="ti ti-volume-3"></i>
 | 
			
		||||
				<i v-else class="ti ti-volume"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<MkMediaRange
 | 
			
		||||
				v-model="volume"
 | 
			
		||||
| 
						 | 
				
			
			@ -143,13 +143,13 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		{
 | 
			
		||||
			type: 'switch',
 | 
			
		||||
			text: i18n.ts._mediaControls.loop,
 | 
			
		||||
			icon: 'ph ph-repeat',
 | 
			
		||||
			icon: 'ti ti-repeat',
 | 
			
		||||
			ref: loop,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			type: 'radio',
 | 
			
		||||
			text: i18n.ts._mediaControls.playbackRate,
 | 
			
		||||
			icon: 'ph ph-gauge',
 | 
			
		||||
			icon: 'ti ti-clock-play',
 | 
			
		||||
			ref: speed,
 | 
			
		||||
			options: {
 | 
			
		||||
				'0.25x': 0.25,
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			text: i18n.ts.hide,
 | 
			
		||||
			icon: 'ph-eye-closed ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-eye-off',
 | 
			
		||||
			action: () => {
 | 
			
		||||
				hide.value = true;
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +176,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
	if (iAmModerator) {
 | 
			
		||||
		menu.push({
 | 
			
		||||
			text: props.audio.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
 | 
			
		||||
			icon: props.audio.isSensitive ? 'ph-eye ph-bold ph-lg' : 'ph-eye-slash ph-bold ph-lg',
 | 
			
		||||
			icon: props.audio.isSensitive ? 'ti ti-eye' : 'ti ti-eye-exclamation',
 | 
			
		||||
			danger: true,
 | 
			
		||||
			action: () => toggleSensitive(props.audio),
 | 
			
		||||
		});
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +188,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		}, {
 | 
			
		||||
			type: 'link' as const,
 | 
			
		||||
			text: i18n.ts._fileViewer.title,
 | 
			
		||||
			icon: 'ph ph-info',
 | 
			
		||||
			icon: 'ti ti-info-circle',
 | 
			
		||||
			to: `/my/drive/file/${props.audio.id}`,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div :class="$style.root">
 | 
			
		||||
	<div v-if="media.isSensitive && hide" :class="$style.sensitive" @click="hide = false">
 | 
			
		||||
		<span style="font-size: 1.6em;"><i class="ph-warning ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span style="font-size: 1.6em;"><i class="ti ti-alert-triangle"></i></span>
 | 
			
		||||
		<b>{{ i18n.ts.sensitive }}</b>
 | 
			
		||||
		<span>{{ i18n.ts.clickToShow }}</span>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		:title="media.name"
 | 
			
		||||
		:download="media.name"
 | 
			
		||||
	>
 | 
			
		||||
		<span style="font-size: 1.6em;"><i class="ph-download ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span style="font-size: 1.6em;"><i class="ti ti-download"></i></span>
 | 
			
		||||
		<b>{{ media.name }}</b>
 | 
			
		||||
	</a>
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,8 +32,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<template v-if="hide">
 | 
			
		||||
		<div :class="$style.hiddenText">
 | 
			
		||||
			<div :class="$style.hiddenTextWrapper">
 | 
			
		||||
				<b v-if="image.isSensitive" style="display: block;"><i class="ph-eye-closed ph-bold ph-lg"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.image}${image.size ? ' ' + bytes(image.size) : ''})` : '' }}</b>
 | 
			
		||||
				<b v-else style="display: block;"><i class="ph-image-square ph-bold ph-lg"></i> {{ defaultStore.state.dataSaver.media && image.size ? bytes(image.size) : i18n.ts.image }}</b>
 | 
			
		||||
				<b v-if="image.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.image}${image.size ? ' ' + bytes(image.size) : ''})` : '' }}</b>
 | 
			
		||||
				<b v-else style="display: block;"><i class="ti ti-photo"></i> {{ defaultStore.state.dataSaver.media && image.size ? bytes(image.size) : i18n.ts.image }}</b>
 | 
			
		||||
				<span v-if="controls" style="display: block;">{{ i18n.ts.clickToShow }}</span>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -42,11 +42,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<div :class="$style.indicators">
 | 
			
		||||
			<div v-if="['image/gif', 'image/apng'].includes(image.type)" :class="$style.indicator">GIF</div>
 | 
			
		||||
			<div v-if="image.comment" :class="$style.indicator">ALT</div>
 | 
			
		||||
			<div v-if="image.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ph-eye-closed ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div v-if="image.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ti ti-eye-exclamation"></i></div>
 | 
			
		||||
			<div v-if="!image.comment" :class="$style.indicator" title="Image lacks descriptive text"><i class="ph-pencil-simple ph-bold ph-lg-off"></i></div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<button :class="$style.menu" class="_button" @click.stop="showMenu"><i class="ph-dots-three ph-bold ph-lg" style="vertical-align: middle;"></i></button>
 | 
			
		||||
		<i class="ph-eye-slash ph-bold ph-lg" :class="$style.hide" @click.stop="hide = true"></i>
 | 
			
		||||
		<button :class="$style.menu" class="_button" @click.stop="showMenu"><i class="ti ti-dots" style="vertical-align: middle;"></i></button>
 | 
			
		||||
		<i class="ti ti-eye-off" :class="$style.hide" @click.stop="hide = true"></i>
 | 
			
		||||
	</template>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -104,13 +104,13 @@ watch(() => props.image, () => {
 | 
			
		|||
function showMenu(ev: MouseEvent) {
 | 
			
		||||
	os.popupMenu([{
 | 
			
		||||
		text: i18n.ts.hide,
 | 
			
		||||
		icon: 'ph-eye-slash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-eye-off',
 | 
			
		||||
		action: () => {
 | 
			
		||||
			hide.value = true;
 | 
			
		||||
		},
 | 
			
		||||
	}, ...(iAmModerator ? [{
 | 
			
		||||
		text: i18n.ts.markAsSensitive,
 | 
			
		||||
		icon: 'ph-eye-closed ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-eye-exclamation',
 | 
			
		||||
		danger: true,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			os.apiWithDialog('drive/files/update', { fileId: props.image.id, isSensitive: true });
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
	}, {
 | 
			
		||||
		type: 'link' as const,
 | 
			
		||||
		text: i18n.ts._fileViewer.title,
 | 
			
		||||
		icon: 'ph ph-info',
 | 
			
		||||
		icon: 'ti ti-info-circle',
 | 
			
		||||
		to: `/my/drive/file/${props.image.id}`,
 | 
			
		||||
	}] : [])], ev.currentTarget ?? ev.target);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
>
 | 
			
		||||
	<button v-if="hide" :class="$style.hidden" @click="hide = false">
 | 
			
		||||
		<div :class="$style.hiddenTextWrapper">
 | 
			
		||||
			<b v-if="video.isSensitive" style="display: block;"><i class="ph-warning ph-bold ph-lg"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.video}${video.size ? ' ' + bytes(video.size) : ''})` : '' }}</b>
 | 
			
		||||
			<b v-else style="display: block;"><i class="ph-film-strip ph-bold ph-lg"></i> {{ defaultStore.state.dataSaver.media && video.size ? bytes(video.size) : i18n.ts.video }}</b>
 | 
			
		||||
			<b v-if="video.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.dataSaver.media ? ` (${i18n.ts.video}${video.size ? ' ' + bytes(video.size) : ''})` : '' }}</b>
 | 
			
		||||
			<b v-else style="display: block;"><i class="ti ti-movie"></i> {{ defaultStore.state.dataSaver.media && video.size ? bytes(video.size) : i18n.ts.video }}</b>
 | 
			
		||||
			<span style="display: block;">{{ i18n.ts.clickToShow }}</span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</button>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,10 +39,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		>
 | 
			
		||||
			<source :src="video.url">
 | 
			
		||||
		</video>
 | 
			
		||||
		<i class="ph-eye-closed ph-bold ph-lg" :class="$style.hide" @click="hide = true"></i>
 | 
			
		||||
		<i class="ti ti-eye-off" :class="$style.hide" @click="hide = true"></i>
 | 
			
		||||
		<div :class="$style.indicators">
 | 
			
		||||
			<div v-if="video.comment" :class="$style.indicator">ALT</div>
 | 
			
		||||
			<div v-if="video.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ph-warning ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div v-if="video.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ti ti-eye-exclamation"></i></div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,20 +60,20 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		>
 | 
			
		||||
			<source :src="video.url">
 | 
			
		||||
		</video>
 | 
			
		||||
		<button v-if="isReady && !isPlaying" class="_button" :class="$style.videoOverlayPlayButton" @click="togglePlayPause"><i class="ph-play ph-bold ph-lg"></i></button>
 | 
			
		||||
		<button v-if="isReady && !isPlaying" class="_button" :class="$style.videoOverlayPlayButton" @click="togglePlayPause"><i class="ti ti-player-play-filled"></i></button>
 | 
			
		||||
		<div v-else-if="!isActuallyPlaying" :class="$style.videoLoading">
 | 
			
		||||
			<MkLoading/>
 | 
			
		||||
		</div>
 | 
			
		||||
		<i class="ph-eye-closed ph-bold ph-lg" :class="$style.hide" @click="hide = true"></i>
 | 
			
		||||
		<i class="ti ti-eye-off" :class="$style.hide" @click="hide = true"></i>
 | 
			
		||||
		<div :class="$style.indicators">
 | 
			
		||||
			<div v-if="video.comment" :class="$style.indicator">ALT</div>
 | 
			
		||||
			<div v-if="video.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ph-warning ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div v-if="video.isSensitive" :class="$style.indicator" style="color: var(--warn);" :title="i18n.ts.sensitive"><i class="ti ti-eye-exclamation"></i></div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.videoControls" @click.self="togglePlayPause">
 | 
			
		||||
			<div :class="[$style.controlsChild, $style.controlsLeft]">
 | 
			
		||||
				<button class="_button" :class="$style.controlButton" @click="togglePlayPause">
 | 
			
		||||
					<i v-if="isPlaying" class="ph-pause ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-else class="ph-play ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-if="isPlaying" class="ti ti-player-pause-filled"></i>
 | 
			
		||||
					<i v-else class="ti ti-player-play-filled"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div :class="[$style.controlsChild, $style.controlsRight]">
 | 
			
		||||
| 
						 | 
				
			
			@ -81,18 +81,18 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<i class="ph-download ph-bold ph-lg"></i>
 | 
			
		||||
				</a>
 | 
			
		||||
				<button class="_button" :class="$style.controlButton" @click="showMenu">
 | 
			
		||||
					<i class="ph-gear ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-settings"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button class="_button" :class="$style.controlButton" @click="toggleFullscreen">
 | 
			
		||||
					<i v-if="isFullscreen" class="ph-arrows-in ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-else class="ph-arrows-out ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-if="isFullscreen" class="ti ti-arrows-minimize"></i>
 | 
			
		||||
					<i v-else class="ti ti-arrows-maximize"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div :class="[$style.controlsChild, $style.controlsTime]">{{ hms(elapsedTimeMs) }}</div>
 | 
			
		||||
			<div :class="[$style.controlsChild, $style.controlsVolume]">
 | 
			
		||||
				<button class="_button" :class="$style.controlButton" @click="toggleMute">
 | 
			
		||||
					<i v-if="volume === 0" class="ph-speaker-x ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-else class="ph-speaker-high ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-if="volume === 0" class="ti ti-volume-3"></i>
 | 
			
		||||
					<i v-else class="ti ti-volume"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<MkMediaRange
 | 
			
		||||
					v-model="volume"
 | 
			
		||||
| 
						 | 
				
			
			@ -177,13 +177,13 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		{
 | 
			
		||||
			type: 'switch',
 | 
			
		||||
			text: i18n.ts._mediaControls.loop,
 | 
			
		||||
			icon: 'ph ph-repeat',
 | 
			
		||||
			icon: 'ti ti-repeat',
 | 
			
		||||
			ref: loop,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			type: 'radio',
 | 
			
		||||
			text: i18n.ts._mediaControls.playbackRate,
 | 
			
		||||
			icon: 'ph ph-gauge',
 | 
			
		||||
			icon: 'ti ti-clock-play',
 | 
			
		||||
			ref: speed,
 | 
			
		||||
			options: {
 | 
			
		||||
				'0.25x': 0.25,
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +197,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		},
 | 
			
		||||
		...(document.pictureInPictureEnabled ? [{
 | 
			
		||||
			text: i18n.ts._mediaControls.pip,
 | 
			
		||||
			icon: 'ph ph-picture-in-picture',
 | 
			
		||||
			icon: 'ti ti-picture-in-picture',
 | 
			
		||||
			action: togglePictureInPicture,
 | 
			
		||||
		}] : []),
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			text: i18n.ts.hide,
 | 
			
		||||
			icon: 'ph-eye-closed ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-eye-off',
 | 
			
		||||
			action: () => {
 | 
			
		||||
				hide.value = true;
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +215,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
	if (iAmModerator) {
 | 
			
		||||
		menu.push({
 | 
			
		||||
			text: props.video.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
 | 
			
		||||
			icon: props.video.isSensitive ? 'ph-eye ph-bold ph-lg' : 'ph-eye-slash ph-bold ph-lg',
 | 
			
		||||
			icon: props.video.isSensitive ? 'ti ti-eye' : 'ti ti-eye-exclamation',
 | 
			
		||||
			danger: true,
 | 
			
		||||
			action: () => toggleSensitive(props.video),
 | 
			
		||||
		});
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +227,7 @@ function showMenu(ev: MouseEvent) {
 | 
			
		|||
		}, {
 | 
			
		||||
			type: 'link' as const,
 | 
			
		||||
			text: i18n.ts._fileViewer.title,
 | 
			
		||||
			icon: 'ph ph-info',
 | 
			
		||||
			icon: 'ti ti-info-circle',
 | 
			
		||||
			to: `/my/drive/file/${props.video.id}`,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]" style="pointer-events: none;"></i>
 | 
			
		||||
				<div :class="$style.item_content">
 | 
			
		||||
					<span :class="$style.item_content_text" style="pointer-events: none;">{{ item.text }}</span>
 | 
			
		||||
					<span :class="$style.caret" style="pointer-events: none;"><i class="ph-caret-right ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span :class="$style.caret" style="pointer-events: none;"><i class="ti ti-chevron-right ti-fw"></i></span>
 | 
			
		||||
				</div>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-else-if="item.type === 'radioOption'" :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.radioActive]: item.active }]" @click="clicked(item.action, $event, false)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]" style="pointer-events: none;"></i>
 | 
			
		||||
				<div :class="$style.item_content">
 | 
			
		||||
					<span :class="$style.item_content_text" style="pointer-events: none;">{{ item.text }}</span>
 | 
			
		||||
					<span :class="$style.caret" style="pointer-events: none;"><i class="ph-caret-right ph-bold ph-lg ti-fw"></i></span>
 | 
			
		||||
					<span :class="$style.caret" style="pointer-events: none;"><i class="ti ti-chevron-right ti-fw"></i></span>
 | 
			
		||||
				</div>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-else :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: getValue(item.active) }]" :disabled="getValue(item.active)" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="$emit('closed')">
 | 
			
		||||
	<div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }" @keydown="onKeydown">
 | 
			
		||||
		<div ref="headerEl" :class="$style.header">
 | 
			
		||||
			<button v-if="withOkButton" :class="$style.headerButton" class="_button" @click="$emit('close')"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="withOkButton" :class="$style.headerButton" class="_button" @click="$emit('close')"><i class="ti ti-x"></i></button>
 | 
			
		||||
			<span :class="$style.title">
 | 
			
		||||
				<slot name="header"></slot>
 | 
			
		||||
			</span>
 | 
			
		||||
			<button v-if="!withOkButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="$emit('close')"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="$emit('ok')"><i class="ph-check ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="!withOkButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="$emit('close')"><i class="ti ti-x"></i></button>
 | 
			
		||||
			<button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="$emit('ok')"><i class="ti ti-check"></i></button>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.body">
 | 
			
		||||
			<slot :width="bodyWidth" :height="bodyHeight"></slot>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,13 +20,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<Mfm :text="getNoteSummary(appearNote.reply)" :plain="true" :nowrap="true" :author="appearNote.reply.user" :nyaize="'respect'" :class="$style.collapsedInReplyToText" @click="inReplyToCollapsed = false"/>
 | 
			
		||||
	</div>
 | 
			
		||||
	<MkNoteSub v-if="appearNote.reply && !renoteCollapsed && !inReplyToCollapsed" :note="appearNote.reply" :class="$style.replyTo"/>
 | 
			
		||||
	<div v-if="pinned" :class="$style.tip"><i class="ph-push-pin ph-bold ph-lg"></i> {{ i18n.ts.pinnedNote }}</div>
 | 
			
		||||
	<!--<div v-if="appearNote._prId_" class="tip"><i class="ph-megaphone ph-bold ph-lg"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ph-x ph-bold ph-lg"></i></button></div>-->
 | 
			
		||||
	<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ph-lightning ph-bold ph-lg"></i> {{ i18n.ts.featured }}</div>-->
 | 
			
		||||
	<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
 | 
			
		||||
	<!--<div v-if="appearNote._prId_" class="tip"><i class="ti ti-speakerphone"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ti ti-x"></i></button></div>-->
 | 
			
		||||
	<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ti ti-bolt"></i> {{ i18n.ts.featured }}</div>-->
 | 
			
		||||
	<div v-if="isRenote" :class="$style.renote">
 | 
			
		||||
		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
 | 
			
		||||
		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
 | 
			
		||||
		<i class="ph-rocket-launch ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
		<i class="ti ti-repeat" style="margin-right: 4px;"></i>
 | 
			
		||||
		<I18n :src="i18n.ts.renotedBy" tag="span" :class="$style.renoteText">
 | 
			
		||||
			<template #user>
 | 
			
		||||
				<MkA v-user-preview="note.userId" :class="$style.renoteUserName" :to="userPage(note.user)">
 | 
			
		||||
| 
						 | 
				
			
			@ -36,16 +36,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</I18n>
 | 
			
		||||
		<div :class="$style.renoteInfo">
 | 
			
		||||
			<button ref="renoteTime" :class="$style.renoteTime" class="_button" @click="showRenoteMenu()">
 | 
			
		||||
				<i class="ph-dots-three ph-bold ph-lg" :class="$style.renoteMenu"></i>
 | 
			
		||||
				<i class="ti ti-dots" :class="$style.renoteMenu"></i>
 | 
			
		||||
				<MkTime :time="note.createdAt"/>
 | 
			
		||||
			</button>
 | 
			
		||||
			<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ph-television ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
			<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
 | 
			
		||||
			<span v-if="note.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +106,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
 | 
			
		||||
					</button>
 | 
			
		||||
				</div>
 | 
			
		||||
				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
				</bdi>
 | 
			
		||||
			</div>
 | 
			
		||||
			<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +116,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			</MkReactionsViewer>
 | 
			
		||||
			<footer :class="$style.footer">
 | 
			
		||||
				<button :class="$style.footerButton" class="_button" @click.stop @click="reply()">
 | 
			
		||||
					<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-arrow-back-up"></i>
 | 
			
		||||
					<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.repliesCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button
 | 
			
		||||
| 
						 | 
				
			
			@ -128,11 +128,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					@click.stop
 | 
			
		||||
					@mousedown="renoted ? undoRenote(appearNote) : boostVisibility()"
 | 
			
		||||
				>
 | 
			
		||||
					<i class="ph-rocket-launch ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-repeat"></i>
 | 
			
		||||
					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button v-else :class="$style.footerButton" class="_button" disabled>
 | 
			
		||||
					<i class="ph-prohibit ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-ban"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button
 | 
			
		||||
					v-if="canRenote && !props.mock"
 | 
			
		||||
| 
						 | 
				
			
			@ -148,17 +148,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<i class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button ref="reactButton" :class="$style.footerButton" class="_button" @click="toggleReact()" @click.stop>
 | 
			
		||||
					<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ph-heart ph-bold ph-lg" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.myReaction != null" class="ph-minus ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
 | 
			
		||||
					<i v-else class="ph-smiley ph-bold ph-lg"></i>
 | 
			
		||||
					<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.reactionCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown="clip()">
 | 
			
		||||
					<i class="ph-paperclip ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-paperclip"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="showMenu()">
 | 
			
		||||
					<i class="ph-dots-three ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-dots"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
			</footer>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -740,7 +740,7 @@ function showRenoteMenu(viaKeyboard = false): void {
 | 
			
		|||
	function getUnrenote(): MenuItem {
 | 
			
		||||
		return {
 | 
			
		||||
			text: i18n.ts.unrenote,
 | 
			
		||||
			icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-trash',
 | 
			
		||||
			danger: true,
 | 
			
		||||
			action: () => {
 | 
			
		||||
				misskeyApi('notes/delete', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws"/>
 | 
			
		||||
	<div v-if="isRenote" :class="$style.renote">
 | 
			
		||||
		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
 | 
			
		||||
		<i class="ph-rocket-launch ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
		<i class="ti ti-repeat" style="margin-right: 4px;"></i>
 | 
			
		||||
		<span :class="$style.renoteText">
 | 
			
		||||
			<I18n :src="i18n.ts.renotedBy" tag="span">
 | 
			
		||||
				<template #user>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,15 +32,15 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</span>
 | 
			
		||||
		<div :class="$style.renoteInfo">
 | 
			
		||||
			<button ref="renoteTime" class="_button" :class="$style.renoteTime" @click="showRenoteMenu()">
 | 
			
		||||
				<i v-if="isMyRenote" class="ph-dots-three ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
				<i v-if="isMyRenote" class="ti ti-dots" style="margin-right: 4px;"></i>
 | 
			
		||||
				<MkTime :time="note.createdAt"/>
 | 
			
		||||
			</button>
 | 
			
		||||
			<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<article :class="$style.note" @contextmenu.stop="onContextmenu">
 | 
			
		||||
| 
						 | 
				
			
			@ -54,12 +54,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
 | 
			
		||||
					<div :class="$style.noteHeaderInfo">
 | 
			
		||||
						<span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]">
 | 
			
		||||
							<i v-if="appearNote.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
						</span>
 | 
			
		||||
						<span v-if="appearNote.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
						<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
						<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div :class="$style.noteHeaderUsername"><MkAcct :user="appearNote.user"/></div>
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				</div>
 | 
			
		||||
				<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws"/></div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
			<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<footer :class="$style.footer">
 | 
			
		||||
			<div :class="$style.noteFooterInfo">
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			</div>
 | 
			
		||||
			<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" ref="reactionsViewer" :note="appearNote"/>
 | 
			
		||||
			<button class="_button" :class="$style.noteFooterButton" @click="reply()">
 | 
			
		||||
				<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-arrow-back-up"></i>
 | 
			
		||||
				<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button
 | 
			
		||||
| 
						 | 
				
			
			@ -129,11 +129,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				:style="renoted ? 'color: var(--accent) !important;' : ''"
 | 
			
		||||
				@mousedown="renoted ? undoRenote() : boostVisibility()"
 | 
			
		||||
			>
 | 
			
		||||
				<i class="ph-rocket-launch ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-repeat"></i>
 | 
			
		||||
				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-else class="_button" :class="$style.noteFooterButton" disabled>
 | 
			
		||||
				<i class="ph-prohibit ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-ban"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button
 | 
			
		||||
				v-if="canRenote"
 | 
			
		||||
| 
						 | 
				
			
			@ -148,23 +148,23 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<i class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
 | 
			
		||||
				<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ph-heart ph-bold ph-lg" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.myReaction != null" class="ph-minus ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
 | 
			
		||||
				<i v-else class="ph-smiley ph-bold ph-lg"></i>
 | 
			
		||||
				<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.reactionCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()">
 | 
			
		||||
				<i class="ph-paperclip ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-paperclip"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown="showMenu()">
 | 
			
		||||
				<i class="ph-dots-three ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-dots"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
		</footer>
 | 
			
		||||
	</article>
 | 
			
		||||
	<div :class="$style.tabs">
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ph-arrow-u-up-left ph-bold ph-lg"></i> {{ i18n.ts.replies }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ph-rocket-launch ph-bold ph-lg"></i> {{ i18n.ts.renotes }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ti ti-arrow-back-up"></i> {{ i18n.ts.replies }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ti ti-repeat"></i> {{ i18n.ts.renotes }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'quotes' }]" @click="tab = 'quotes'"><i class="ph-quotes ph-bold ph-lg"></i> {{ i18n.ts._notification._types.quote }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'reactions' }]" @click="tab = 'reactions'"><i class="ph-smiley ph-bold ph-lg"></i> {{ i18n.ts.reactions }}</button>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -710,7 +710,7 @@ function showRenoteMenu(viaKeyboard = false): void {
 | 
			
		|||
	pleaseLogin();
 | 
			
		||||
	os.popupMenu([{
 | 
			
		||||
		text: i18n.ts.unrenote,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		danger: true,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			misskeyApi('notes/delete', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,13 +24,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<MkTime :time="note.createdAt" colored/>
 | 
			
		||||
		</MkA>
 | 
			
		||||
		<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
			<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
		</span>
 | 
			
		||||
		<span v-if="note.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em; cursor: pointer;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ph-television ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
		<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
 | 
			
		||||
	</div>
 | 
			
		||||
</header>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<MkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="$style.reply" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply"/>
 | 
			
		||||
	</template>
 | 
			
		||||
	<div v-else :class="$style.more">
 | 
			
		||||
		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
 | 
			
		||||
		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ti ti-chevron-double-right"></i></MkA>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
<div v-else :class="$style.muted" @click="muted = false">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<MkAvatar v-else-if="['roleAssigned', 'achievementEarned'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/>
 | 
			
		||||
		<div v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ph-smiley ph-bold ph-lg" style="line-height: 1;"></i></div>
 | 
			
		||||
		<div v-else-if="notification.type === 'reaction:grouped'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ph-smiley ph-bold ph-lg" style="line-height: 1;"></i></div>
 | 
			
		||||
		<div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ph-rocket-launch ph-bold ph-lg" style="line-height: 1;"></i></div>
 | 
			
		||||
		<div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ti ti-repeat" style="line-height: 1;"></i></div>
 | 
			
		||||
		<img v-else-if="notification.type === 'test'" :class="$style.icon" :src="infoImageUrl"/>
 | 
			
		||||
		<MkAvatar v-else-if="notification.user" :class="$style.icon" :user="notification.user" link preview/>
 | 
			
		||||
		<img v-else-if="notification.icon" :class="[$style.icon, $style.icon_app]" :src="notification.icon" alt=""/>
 | 
			
		||||
| 
						 | 
				
			
			@ -29,18 +29,18 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				[$style.t_pollEnded]: notification.type === 'edited',
 | 
			
		||||
			}]"
 | 
			
		||||
		> <!-- we re-use t_pollEnded for "edited" instead of making an identical style -->
 | 
			
		||||
			<i v-if="notification.type === 'follow'" class="ph-plus ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'receiveFollowRequest'" class="ph-clock ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'followRequestAccepted'" class="ph-check ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'renote'" class="ph-rocket-launch ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'reply'" class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'mention'" class="ph-at ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'quote'" class="ph-quotes ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'pollEnded'" class="ph-chart-bar-horizontal ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'achievementEarned'" class="ph-trophy ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-if="notification.type === 'follow'" class="ti ti-plus"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'receiveFollowRequest'" class="ti ti-clock"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'followRequestAccepted'" class="ti ti-check"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'renote'" class="ti ti-repeat"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'reply'" class="ti ti-arrow-back-up"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'mention'" class="ti ti-at"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'quote'" class="ti ti-quote"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'pollEnded'" class="ti ti-chart-arrows"></i>
 | 
			
		||||
			<i v-else-if="notification.type === 'achievementEarned'" class="ti ti-medal"></i>
 | 
			
		||||
			<template v-else-if="notification.type === 'roleAssigned'">
 | 
			
		||||
				<img v-if="notification.role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="notification.role.iconUrl" alt=""/>
 | 
			
		||||
				<i v-else class="ph-seal-check ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else class="ti ti-badges"></i>
 | 
			
		||||
			</template>
 | 
			
		||||
			<i v-else-if="notification.type === 'edited'" class="ph-pencil ph-bold ph-lg"></i>
 | 
			
		||||
			<!-- notification.reaction が null になることはまずないが、ここでoptional chaining使うと一部ブラウザで刺さるので念の為 -->
 | 
			
		||||
| 
						 | 
				
			
			@ -70,14 +70,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</header>
 | 
			
		||||
		<div>
 | 
			
		||||
			<MkA v-if="notification.type === 'reaction' || notification.type === 'reaction:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
				<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
			</MkA>
 | 
			
		||||
			<MkA v-else-if="notification.type === 'renote' || notification.type === 'renote:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
				<Mfm :text="getNoteSummary(notification.note.renote)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.renote?.user"/>
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
			</MkA>
 | 
			
		||||
			<MkA v-else-if="notification.type === 'reply'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
 | 
			
		||||
				<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +92,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
 | 
			
		||||
			</MkA>
 | 
			
		||||
			<MkA v-else-if="notification.type === 'pollEnded'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
				<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
 | 
			
		||||
				<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
 | 
			
		||||
				<i class="ti ti-quote" :class="$style.quote"></i>
 | 
			
		||||
			</MkA>
 | 
			
		||||
			<div v-else-if="notification.type === 'roleAssigned'" :class="$style.text">
 | 
			
		||||
				{{ notification.role.name }}
 | 
			
		||||
| 
						 | 
				
			
			@ -109,8 +109,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<template v-else-if="notification.type === 'receiveFollowRequest'">
 | 
			
		||||
				<span :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.receiveFollowRequest }}</span>
 | 
			
		||||
				<div v-if="full && !followRequestDone" :class="$style.followRequestCommands">
 | 
			
		||||
					<MkButton :class="$style.followRequestCommandButton" rounded primary @click="acceptFollowRequest()"><i class="ph-check ph-bold ph-lg"/> {{ i18n.ts.accept }}</MkButton>
 | 
			
		||||
					<MkButton :class="$style.followRequestCommandButton" rounded danger @click="rejectFollowRequest()"><i class="ph-x ph-bold ph-lg"/> {{ i18n.ts.reject }}</MkButton>
 | 
			
		||||
					<MkButton :class="$style.followRequestCommandButton" rounded primary @click="acceptFollowRequest()"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
 | 
			
		||||
					<MkButton :class="$style.followRequestCommandButton" rounded danger @click="rejectFollowRequest()"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
 | 
			
		||||
				</div>
 | 
			
		||||
			</template>
 | 
			
		||||
			<span v-else-if="notification.type === 'test'" :class="$style.text">{{ i18n.ts._notification.notificationWillBeDisplayedLikeThis }}</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ const buttonsLeft = computed(() => {
 | 
			
		|||
 | 
			
		||||
	if (history.value.length > 1) {
 | 
			
		||||
		buttons.push({
 | 
			
		||||
			icon: 'ph-arrow-left ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-arrow-left',
 | 
			
		||||
			onClick: back,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -77,11 +77,11 @@ const buttonsLeft = computed(() => {
 | 
			
		|||
});
 | 
			
		||||
const buttonsRight = computed(() => {
 | 
			
		||||
	const buttons = [{
 | 
			
		||||
		icon: 'ph-arrows-clockwise ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-reload',
 | 
			
		||||
		title: i18n.ts.reload,
 | 
			
		||||
		onClick: reload,
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'ph-eject ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-player-eject',
 | 
			
		||||
		title: i18n.ts.showInPage,
 | 
			
		||||
		onClick: expand,
 | 
			
		||||
	}];
 | 
			
		||||
| 
						 | 
				
			
			@ -113,22 +113,22 @@ provide('forceSpacerMin', true);
 | 
			
		|||
provide('shouldBackButton', false);
 | 
			
		||||
 | 
			
		||||
const contextmenu = computed(() => ([{
 | 
			
		||||
	icon: 'ph-eject ph-bold ph-lg',
 | 
			
		||||
	icon: 'ti ti-player-eject',
 | 
			
		||||
	text: i18n.ts.showInPage,
 | 
			
		||||
	action: expand,
 | 
			
		||||
}, {
 | 
			
		||||
	icon: 'ph-frame-corners ph-bold ph-lg',
 | 
			
		||||
	icon: 'ti ti-window-maximize',
 | 
			
		||||
	text: i18n.ts.popout,
 | 
			
		||||
	action: popout,
 | 
			
		||||
}, {
 | 
			
		||||
	icon: 'ph-arrow-square-out ph-bold ph-lg',
 | 
			
		||||
	icon: 'ti ti-external-link',
 | 
			
		||||
	text: i18n.ts.openInNewTab,
 | 
			
		||||
	action: () => {
 | 
			
		||||
		window.open(url + windowRouter.getCurrentPath(), '_blank', 'noopener');
 | 
			
		||||
		windowEl.value?.close();
 | 
			
		||||
	},
 | 
			
		||||
}, {
 | 
			
		||||
	icon: 'ph-link ph-bold ph-lg',
 | 
			
		||||
	icon: 'ti ti-link',
 | 
			
		||||
	text: i18n.ts.copyLink,
 | 
			
		||||
	action: () => {
 | 
			
		||||
		copyToClipboard(url + windowRouter.getCurrentPath());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,16 +22,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<form @submit.prevent="done">
 | 
			
		||||
			<div class="_gaps">
 | 
			
		||||
				<MkInput ref="passwordInput" v-model="password" :placeholder="i18n.ts.password" type="password" autocomplete="current-password webauthn" required :withPasswordToggle="true">
 | 
			
		||||
					<template #prefix><i class="ph-password ph-bold ph-lg"></i></template>
 | 
			
		||||
					<template #prefix><i class="ti ti-password"></i></template>
 | 
			
		||||
				</MkInput>
 | 
			
		||||
 | 
			
		||||
				<MkInput v-if="$i.twoFactorEnabled" v-model="token" type="text" :pattern="isBackupCode ? '^[A-Z0-9]{32}$' :'^[0-9]{6}$'" autocomplete="one-time-code" required :spellcheck="false" :inputmode="isBackupCode ? undefined : 'numeric'">
 | 
			
		||||
					<template #label>{{ i18n.ts.token }} ({{ i18n.ts['2fa'] }})</template>
 | 
			
		||||
					<template #prefix><i v-if="isBackupCode" class="ph-keyhole ph-bold ph-lg"></i><i v-else class="ph-numpad ph-bold ph-lg"></i></template>
 | 
			
		||||
					<template #prefix><i v-if="isBackupCode" class="ti ti-key"></i><i v-else class="ti ti-123"></i></template>
 | 
			
		||||
					<template #caption><button class="_textButton" type="button" @click="isBackupCode = !isBackupCode">{{ isBackupCode ? i18n.ts.useTotp : i18n.ts.useBackupCode }}</button></template>
 | 
			
		||||
				</MkInput>
 | 
			
		||||
 | 
			
		||||
				<MkButton :disabled="(password ?? '') == '' || ($i.twoFactorEnabled && (token ?? '') == '')" type="submit" primary rounded style="margin: 0 auto;"><i class="ph-lock ph-bold ph-lg-open"></i> {{ i18n.ts.continue }}</MkButton>
 | 
			
		||||
				<MkButton :disabled="(password ?? '') == '' || ($i.twoFactorEnabled && (token ?? '') == '')" type="submit" primary rounded style="margin: 0 auto;"><i class="ti ti-lock-open"></i> {{ i18n.ts.continue }}</MkButton>
 | 
			
		||||
			</div>
 | 
			
		||||
		</form>
 | 
			
		||||
	</MkSpacer>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<li v-for="(choice, i) in poll.choices" :key="i" :class="$style.choice" @click="vote(i)">
 | 
			
		||||
			<div :class="$style.bg" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
 | 
			
		||||
			<span :class="$style.fg">
 | 
			
		||||
				<template v-if="choice.isVoted"><i class="ph-check ph-bold ph-lg" style="margin-right: 4px; color: var(--accent);"></i></template>
 | 
			
		||||
				<template v-if="choice.isVoted"><i class="ti ti-check" style="margin-right: 4px; color: var(--accent);"></i></template>
 | 
			
		||||
				<Mfm :text="choice.text" :plain="true"/>
 | 
			
		||||
				<span v-if="showResult" style="margin-left: 4px; opacity: 0.7;">({{ i18n.tsx._poll.votesCount({ n: choice.votes }) }})</span>
 | 
			
		||||
			</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div class="zmdxowus">
 | 
			
		||||
	<p v-if="choices.length < 2" class="caution">
 | 
			
		||||
		<i class="ph-warning ph-bold ph-lg"></i>{{ i18n.ts._poll.noOnlyOneChoice }}
 | 
			
		||||
		<i class="ti ti-alert-triangle"></i>{{ i18n.ts._poll.noOnlyOneChoice }}
 | 
			
		||||
	</p>
 | 
			
		||||
	<ul>
 | 
			
		||||
		<li v-for="(choice, i) in choices" :key="i">
 | 
			
		||||
			<MkInput class="input" small :modelValue="choice" :placeholder="i18n.tsx._poll.choiceN({ n: i + 1 })" @update:modelValue="onInput(i, $event)">
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<button class="_button" @click="remove(i)">
 | 
			
		||||
				<i class="ph-x ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-x"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
		</li>
 | 
			
		||||
	</ul>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
>
 | 
			
		||||
	<header :class="$style.header">
 | 
			
		||||
		<div :class="$style.headerLeft">
 | 
			
		||||
			<button v-if="!fixed" :class="$style.cancel" class="_button" @click="cancel"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="!fixed" :class="$style.cancel" class="_button" @click="cancel"><i class="ti ti-x"></i></button>
 | 
			
		||||
			<button v-click-anime v-tooltip="i18n.ts.switchAccount" :class="$style.account" class="_button" @click="openAccountMenu">
 | 
			
		||||
				<MkAvatar :user="postAccount ?? $i" :class="$style.avatar"/>
 | 
			
		||||
			</button>
 | 
			
		||||
| 
						 | 
				
			
			@ -21,24 +21,24 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<div :class="$style.headerRight">
 | 
			
		||||
			<template v-if="!(channel != null && fixed)">
 | 
			
		||||
				<button v-if="channel == null" ref="visibilityButton" v-click-anime v-tooltip="i18n.ts.visibility" :class="['_button', $style.headerRightItem, $style.visibility]" @click="setVisibility">
 | 
			
		||||
					<span v-if="visibility === 'public'"><i class="ph-globe-hemisphere-west ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'home'"><i class="ph-house ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'followers'"><i class="ph-lock ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'specified'"><i class="ph-envelope ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'public'"><i class="ti ti-world"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'home'"><i class="ti ti-home"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'followers'"><i class="ti ti-lock"></i></span>
 | 
			
		||||
					<span v-if="visibility === 'specified'"><i class="ti ti-mail"></i></span>
 | 
			
		||||
					<span :class="$style.headerRightButtonText">{{ i18n.ts._visibility[visibility] }}</span>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button v-else class="_button" :class="[$style.headerRightItem, $style.visibility]" disabled>
 | 
			
		||||
					<span><i class="ph-television ph-bold ph-lg"></i></span>
 | 
			
		||||
					<span><i class="ti ti-device-tv"></i></span>
 | 
			
		||||
					<span :class="$style.headerRightButtonText">{{ channel.name }}</span>
 | 
			
		||||
				</button>
 | 
			
		||||
			</template>
 | 
			
		||||
			<button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified'" @click="toggleLocalOnly">
 | 
			
		||||
				<span v-if="!localOnly"><i class="ph-rocket-launch ph-bold ph-lg"></i></span>
 | 
			
		||||
				<span v-else><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
				<span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
 | 
			
		||||
				<span v-else><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-click-anime v-tooltip="i18n.ts.reactionAcceptance" class="_button" :class="[$style.headerRightItem, { [$style.danger]: reactionAcceptance === 'likeOnly' }]" @click="toggleReactionAcceptance">
 | 
			
		||||
				<span v-if="reactionAcceptance === 'likeOnly'"><i class="ph-heart ph-bold ph-lg"></i></span>
 | 
			
		||||
				<span v-else-if="reactionAcceptance === 'likeOnlyForRemote'"><i class="ph-heart ph-bold ph-lg"></i></span>
 | 
			
		||||
				<span v-if="reactionAcceptance === 'likeOnly'"><i class="ti ti-heart"></i></span>
 | 
			
		||||
				<span v-else-if="reactionAcceptance === 'likeOnlyForRemote'"><i class="ti ti-heart-plus"></i></span>
 | 
			
		||||
				<span v-else><i class="ph-smiley ph-bold ph-lg"></i></span>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-click-anime class="_button" :class="$style.submit" :disabled="!canPost" data-cy-open-post-form-submit @click="post">
 | 
			
		||||
| 
						 | 
				
			
			@ -46,22 +46,22 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<template v-if="posted"></template>
 | 
			
		||||
					<template v-else-if="posting"><MkEllipsis/></template>
 | 
			
		||||
					<template v-else>{{ submitText }}</template>
 | 
			
		||||
					<i style="margin-left: 6px;" :class="posted ? 'ph-check ph-bold ph-lg' : reply ? 'ph-arrow-u-up-left ph-bold ph-lg' : renote ? 'ph-quotes ph-bold ph-lg' : 'ph-paper-plane-tilt ph-bold ph-lg'"></i>
 | 
			
		||||
					<i style="margin-left: 6px;" :class="posted ? 'ti ti-check' : reply ? 'ti ti-arrow-back-up' : renote ? 'ti ti-quote' : 'ti ti-send'"></i>
 | 
			
		||||
				</div>
 | 
			
		||||
			</button>
 | 
			
		||||
		</div>
 | 
			
		||||
	</header>
 | 
			
		||||
	<MkNoteSimple v-if="reply" :class="$style.targetNote" :hideFiles="true" :note="reply"/>
 | 
			
		||||
	<MkNoteSimple v-if="renote" :class="$style.targetNote" :hideFiles="true" :note="renote"/>
 | 
			
		||||
	<div v-if="quoteId" :class="$style.withQuote"><i class="ph-quotes ph-bold ph-lg"></i> {{ i18n.ts.quoteAttached }}<button @click="quoteId = null"><i class="ph-x ph-bold ph-lg"></i></button></div>
 | 
			
		||||
	<div v-if="quoteId" :class="$style.withQuote"><i class="ti ti-quote"></i> {{ i18n.ts.quoteAttached }}<button @click="quoteId = null"><i class="ti ti-x"></i></button></div>
 | 
			
		||||
	<div v-if="visibility === 'specified'" :class="$style.toSpecified">
 | 
			
		||||
		<span style="margin-right: 8px;">{{ i18n.ts.recipient }}</span>
 | 
			
		||||
		<div :class="$style.visibleUsers">
 | 
			
		||||
			<span v-for="u in visibleUsers" :key="u.id" :class="$style.visibleUser">
 | 
			
		||||
				<MkAcct :user="u"/>
 | 
			
		||||
				<button class="_button" style="padding: 4px 8px;" @click="removeVisibleUser(u)"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
				<button class="_button" style="padding: 4px 8px;" @click="removeVisibleUser(u)"><i class="ti ti-x"></i></button>
 | 
			
		||||
			</span>
 | 
			
		||||
			<button class="_buttonPrimary" style="padding: 4px; border-radius: var(--radius-sm);" @click="addVisibleUser"><i class="ph-plus ph-bold ph-lg ti-fw"></i></button>
 | 
			
		||||
			<button class="_buttonPrimary" style="padding: 4px; border-radius: var(--radius-sm);" @click="addVisibleUser"><i class="ti ti-plus ti-fw"></i></button>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +79,19 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<footer :class="$style.footer">
 | 
			
		||||
		<div :class="$style.footerLeft">
 | 
			
		||||
			<button v-tooltip="i18n.ts.attachFile" class="_button" :class="$style.footerButton" @click="chooseFileFrom"><i class="ph-image-square ph-bold ph-lg-plus"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.poll" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: poll }]" @click="togglePoll"><i class="ph-chart-bar-horizontal ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.useCw" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: useCw }]" @click="useCw = !useCw"><i class="ph-eye-slash ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.mention" class="_button" :class="$style.footerButton" @click="insertMention"><i class="ph-at ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.hashtags" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: withHashtags }]" @click="withHashtags = !withHashtags"><i class="ph-hash ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugins" class="_button" :class="$style.footerButton" @click="showActions"><i class="ph-plug ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ph-smiley ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-if="showAddMfmFunction" v-tooltip="i18n.ts.addMfmFunction" :class="['_button', $style.footerButton]" @click="insertMfmFunction"><i class="ph-palette ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.attachFile" class="_button" :class="$style.footerButton" @click="chooseFileFrom"><i class="ti ti-photo-plus"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.poll" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: poll }]" @click="togglePoll"><i class="ti ti-chart-arrows"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.useCw" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: useCw }]" @click="useCw = !useCw"><i class="ti ti-eye-off"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.mention" class="_button" :class="$style.footerButton" @click="insertMention"><i class="ti ti-at"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.hashtags" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: withHashtags }]" @click="withHashtags = !withHashtags"><i class="ti ti-hash"></i></button>
 | 
			
		||||
			<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugins" class="_button" :class="$style.footerButton" @click="showActions"><i class="ti ti-plug"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ti ti-mood-happy"></i></button>
 | 
			
		||||
			<button v-if="showAddMfmFunction" v-tooltip="i18n.ts.addMfmFunction" :class="['_button', $style.footerButton]" @click="insertMfmFunction"><i class="ti ti-palette"></i></button>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.footerRight">
 | 
			
		||||
			<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ph-eye ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ti ti-eye"></i></button>
 | 
			
		||||
			<button v-tooltip="'MFM Cheatsheet'" class="_button" :class="$style.footerButton" @click="MFMWindow"><i class="ph-notebook ph-bold ph-lg"></i></button>
 | 
			
		||||
			<!--<button v-tooltip="i18n.ts.more" class="_button" :class="$style.footerButton" @click="showingOptions = !showingOptions"><i class="ph-dots-three ph-bold ph-lg"></i></button>-->
 | 
			
		||||
			<!--<button v-tooltip="i18n.ts.more" class="_button" :class="$style.footerButton" @click="showingOptions = !showingOptions"><i class="ti ti-dots"></i></button>-->
 | 
			
		||||
		</div>
 | 
			
		||||
	</footer>
 | 
			
		||||
	<datalist id="hashtags">
 | 
			
		||||
| 
						 | 
				
			
			@ -773,7 +773,7 @@ async function post(ev?: MouseEvent) {
 | 
			
		|||
			visibility.value = 'home';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	if (defaultStore.state.warnMissingAltText) {
 | 
			
		||||
		const filesData = toRaw(files.value);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -793,7 +793,7 @@ async function post(ev?: MouseEvent) {
 | 
			
		|||
			});
 | 
			
		||||
 | 
			
		||||
			if (canceled) return;
 | 
			
		||||
			if (result === 'cancel') return;	
 | 
			
		||||
			if (result === 'cancel') return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<div :class="$style.file" @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
 | 
			
		||||
				<MkDriveFileThumbnail :data-id="element.id" :class="$style.thumbnail" :file="element" fit="cover"/>
 | 
			
		||||
				<div v-if="element.isSensitive" :class="$style.sensitive">
 | 
			
		||||
					<i class="ph-eye-closed ph-bold ph-lg" style="margin: auto;"></i>
 | 
			
		||||
					<i class="ti ti-eye-exclamation" style="margin: auto;"></i>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -137,29 +137,29 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent): void {
 | 
			
		|||
	const isImage = file.type.startsWith('image/');
 | 
			
		||||
	os.popupMenu([{
 | 
			
		||||
		text: i18n.ts.renameFile,
 | 
			
		||||
		icon: 'ph-textbox ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-forms',
 | 
			
		||||
		action: () => { rename(file); },
 | 
			
		||||
	}, {
 | 
			
		||||
		text: file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
 | 
			
		||||
		icon: file.isSensitive ? 'ph-eye-closed ph-bold ph-lg' : 'ph-eye ph-bold ph-lg',
 | 
			
		||||
		icon: file.isSensitive ? 'ti ti-eye-exclamation' : 'ti ti-eye',
 | 
			
		||||
		action: () => { toggleSensitive(file); },
 | 
			
		||||
	}, {
 | 
			
		||||
		text: i18n.ts.describeFile,
 | 
			
		||||
		icon: 'ph-text-indent ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-text-caption',
 | 
			
		||||
		action: () => { describe(file); },
 | 
			
		||||
	}, ...isImage ? [{
 | 
			
		||||
		text: i18n.ts.cropImage,
 | 
			
		||||
		icon: 'ph-crop ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-crop',
 | 
			
		||||
		action: () : void => { crop(file); },
 | 
			
		||||
	}] : [], {
 | 
			
		||||
		type: 'divider',
 | 
			
		||||
	}, {
 | 
			
		||||
		text: i18n.ts.attachCancel,
 | 
			
		||||
		icon: 'ph-x-circle ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-circle-x',
 | 
			
		||||
		action: () => { detachMedia(file.id); },
 | 
			
		||||
	}, {
 | 
			
		||||
		text: i18n.ts.deleteFile,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		danger: true,
 | 
			
		||||
		action: () => { detachAndDeleteMedia(file); },
 | 
			
		||||
	}], ev.currentTarget ?? ev.target).then(() => menuShowing = false);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<div v-if="isPullStart" :class="$style.frame" :style="`--frame-min-height: ${pullDistance / (PULL_BRAKE_BASE + (pullDistance / PULL_BRAKE_FACTOR))}px;`">
 | 
			
		||||
		<div :class="$style.frameContent">
 | 
			
		||||
			<MkLoading v-if="isRefreshing" :class="$style.loader" :em="true"/>
 | 
			
		||||
			<i v-else class="ph-arrow-line-down ph-bold ph-lg" :class="[$style.icon, { [$style.refresh]: isPullEnd }]"></i>
 | 
			
		||||
			<i v-else class="ti ti-arrow-bar-to-down" :class="[$style.icon, { [$style.refresh]: isPullEnd }]"></i>
 | 
			
		||||
			<div :class="$style.text">
 | 
			
		||||
				<template v-if="isPullEnd">{{ i18n.ts.releaseToRefresh }}</template>
 | 
			
		||||
				<template v-else-if="isRefreshing">{{ i18n.ts.refreshing }}</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ async function menu(ev) {
 | 
			
		|||
 | 
			
		||||
	os.popupMenu([{
 | 
			
		||||
		text: i18n.ts.info,
 | 
			
		||||
		icon: 'ph-info ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-info-circle',
 | 
			
		||||
		action: async () => {
 | 
			
		||||
			os.popup(MkCustomEmojiDetailedDialog, {
 | 
			
		||||
				emoji: await misskeyApiGet('emoji', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
<div :class="$style.root"><i class="ph-warning ph-bold ph-lg" style="margin-right: 8px;"></i>{{ i18n.ts.remoteUserCaution }}<a :class="$style.link" :href="href" rel="nofollow noopener" target="_blank">{{ i18n.ts.showOnRemote }}</a></div>
 | 
			
		||||
<div :class="$style.root"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i>{{ i18n.ts.remoteUserCaution }}<a :class="$style.link" :href="href" rel="nofollow noopener" target="_blank">{{ i18n.ts.showOnRemote }}</a></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<img :class="$style.badge" :src="role.iconUrl"/>
 | 
			
		||||
			</template>
 | 
			
		||||
			<template v-else>
 | 
			
		||||
				<i v-if="role.isAdministrator" class="ph-crown ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="role.isModerator" class="ph-shield ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else class="ph-user ph-bold ph-lg" style="opacity: 0.7;"></i>
 | 
			
		||||
				<i v-if="role.isAdministrator" class="ti ti-crown" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="role.isModerator" class="ti ti-shield" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else class="ti ti-user" style="opacity: 0.7;"></i>
 | 
			
		||||
			</template>
 | 
			
		||||
		</span>
 | 
			
		||||
		<span :class="$style.name">{{ role.name }}</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,11 +23,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		>
 | 
			
		||||
			<slot></slot>
 | 
			
		||||
		</select>
 | 
			
		||||
		<div ref="suffixEl" :class="$style.suffix"><i class="ph-caret-down ph-bold ph-lg" :class="[$style.chevron, { [$style.chevronOpening]: opening }]"></i></div>
 | 
			
		||||
		<div ref="suffixEl" :class="$style.suffix"><i class="ti ti-chevron-down" :class="[$style.chevron, { [$style.chevronOpening]: opening }]"></i></div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div :class="$style.caption"><slot name="caption"></slot></div>
 | 
			
		||||
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-floppy-disk ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<template #suffix>@{{ host }}</template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-if="!user || user && !user.usePasswordLessLogin" v-model="password" :placeholder="i18n.ts.password" type="password" autocomplete="current-password webauthn" :withPasswordToggle="true" required data-cy-signin-password>
 | 
			
		||||
				<template #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template #prefix><i class="ti ti-lock"></i></template>
 | 
			
		||||
				<template #caption><button class="_textButton" type="button" @click="resetPassword">{{ i18n.ts.forgotPassword }}</button></template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkButton type="submit" large primary rounded :disabled="signing" style="margin: 0 auto;">{{ signing ? i18n.ts.loggingIn : i18n.ts.login }}</MkButton>
 | 
			
		||||
| 
						 | 
				
			
			@ -34,11 +34,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<div class="twofa-group totp-group _gaps">
 | 
			
		||||
				<MkInput v-if="user && user.usePasswordLessLogin" v-model="password" type="password" autocomplete="current-password" :withPasswordToggle="true" required>
 | 
			
		||||
					<template #label>{{ i18n.ts.password }}</template>
 | 
			
		||||
					<template #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
					<template #prefix><i class="ti ti-lock"></i></template>
 | 
			
		||||
				</MkInput>
 | 
			
		||||
				<MkInput v-model="token" type="text" :pattern="isBackupCode ? '^[A-Z0-9]{32}$' :'^[0-9]{6}$'" autocomplete="one-time-code" required :spellcheck="false" :inputmode="isBackupCode ? undefined : 'numeric'">
 | 
			
		||||
					<template #label>{{ i18n.ts.token }} ({{ i18n.ts['2fa'] }})</template>
 | 
			
		||||
					<template #prefix><i v-if="isBackupCode" class="ph-keyhole ph-bold ph-lg"></i><i v-else class="ph-numpad ph-bold ph-lg"></i></template>
 | 
			
		||||
					<template #prefix><i v-if="isBackupCode" class="ti ti-key"></i><i v-else class="ti ti-123"></i></template>
 | 
			
		||||
					<template #caption><button class="_textButton" type="button" @click="isBackupCode = !isBackupCode">{{ isBackupCode ? i18n.ts.useTotp : i18n.ts.useBackupCode }}</button></template>
 | 
			
		||||
				</MkInput>
 | 
			
		||||
				<MkButton type="submit" :disabled="signing" large primary rounded style="margin: 0 auto;">{{ signing ? i18n.ts.loggingIn : i18n.ts.login }}</MkButton>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,60 +6,60 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div>
 | 
			
		||||
	<div :class="$style.banner">
 | 
			
		||||
		<i class="ph-user-list ph-bold ph-lg"></i>
 | 
			
		||||
		<i class="ti ti-user-edit"></i>
 | 
			
		||||
	</div>
 | 
			
		||||
	<MkSpacer :marginMin="20" :marginMax="32">
 | 
			
		||||
		<form class="_gaps_m" autocomplete="new-password" @submit.prevent="onSubmit">
 | 
			
		||||
			<MkInput v-if="instance.disableRegistration" v-model="invitationCode" type="text" :spellcheck="false" required>
 | 
			
		||||
				<template #label>{{ i18n.ts.invitationCode }}</template>
 | 
			
		||||
				<template #prefix><i class="ph-key ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template #prefix><i class="ti ti-key"></i></template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :spellcheck="false" autocomplete="username" required data-cy-signup-username @update:modelValue="onChangeUsername">
 | 
			
		||||
				<template #label>{{ i18n.ts.username }} <div v-tooltip:dialog="i18n.ts.usernameInfo" class="_button _help"><i class="ph-question ph-bold ph-lg"></i></div></template>
 | 
			
		||||
				<template #label>{{ i18n.ts.username }} <div v-tooltip:dialog="i18n.ts.usernameInfo" class="_button _help"><i class="ti ti-help-circle"></i></div></template>
 | 
			
		||||
				<template #prefix>@</template>
 | 
			
		||||
				<template #suffix>@{{ host }}</template>
 | 
			
		||||
				<template #caption>
 | 
			
		||||
					<div><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.cannotBeChangedLater }}</div>
 | 
			
		||||
					<div><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.cannotBeChangedLater }}</div>
 | 
			
		||||
					<span v-if="usernameState === 'wait'" style="color:#999"><MkLoading :em="true"/> {{ i18n.ts.checking }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'ok'" style="color: var(--success)"><i class="ph-check ph-bold ph-lg ti-fw"></i> {{ i18n.ts.available }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'unavailable'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.unavailable }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'error'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.error }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'invalid-format'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.usernameInvalidFormat }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'min-range'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.tooShort }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'max-range'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.tooLong }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'ok'" style="color: var(--success)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.available }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'unavailable'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.unavailable }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'error'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.error }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'invalid-format'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.usernameInvalidFormat }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'min-range'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.tooShort }}</span>
 | 
			
		||||
					<span v-else-if="usernameState === 'max-range'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.tooLong }}</span>
 | 
			
		||||
				</template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-if="instance.emailRequiredForSignup" v-model="email" :debounce="true" type="email" :spellcheck="false" required data-cy-signup-email @update:modelValue="onChangeEmail">
 | 
			
		||||
				<template #label>{{ i18n.ts.emailAddress }} <div v-tooltip:dialog="i18n.ts._signup.emailAddressInfo" class="_button _help"><i class="ph-question ph-bold ph-lg"></i></div></template>
 | 
			
		||||
				<template #prefix><i class="ph-envelope ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template #label>{{ i18n.ts.emailAddress }} <div v-tooltip:dialog="i18n.ts._signup.emailAddressInfo" class="_button _help"><i class="ti ti-help-circle"></i></div></template>
 | 
			
		||||
				<template #prefix><i class="ti ti-mail"></i></template>
 | 
			
		||||
				<template #caption>
 | 
			
		||||
					<span v-if="emailState === 'wait'" style="color:#999"><MkLoading :em="true"/> {{ i18n.ts.checking }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'ok'" style="color: var(--success)"><i class="ph-check ph-bold ph-lg ti-fw"></i> {{ i18n.ts.available }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:used'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.used }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:format'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.format }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:disposable'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.disposable }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:banned'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.banned }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:mx'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.mx }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:smtp'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts._emailUnavailable.smtp }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.unavailable }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'error'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.error }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'ok'" style="color: var(--success)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.available }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:used'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.used }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:format'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.format }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:disposable'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.disposable }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:banned'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.banned }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:mx'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.mx }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable:smtp'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts._emailUnavailable.smtp }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'unavailable'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.unavailable }}</span>
 | 
			
		||||
					<span v-else-if="emailState === 'error'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.error }}</span>
 | 
			
		||||
				</template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-model="password" type="password" autocomplete="new-password" required data-cy-signup-password @update:modelValue="onChangePassword">
 | 
			
		||||
				<template #label>{{ i18n.ts.password }}</template>
 | 
			
		||||
				<template #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template #prefix><i class="ti ti-lock"></i></template>
 | 
			
		||||
				<template #caption>
 | 
			
		||||
					<span v-if="passwordStrength == 'low'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.weakPassword }}</span>
 | 
			
		||||
					<span v-if="passwordStrength == 'medium'" style="color: var(--warn)"><i class="ph-check ph-bold ph-lg ti-fw"></i> {{ i18n.ts.normalPassword }}</span>
 | 
			
		||||
					<span v-if="passwordStrength == 'high'" style="color: var(--success)"><i class="ph-check ph-bold ph-lg ti-fw"></i> {{ i18n.ts.strongPassword }}</span>
 | 
			
		||||
					<span v-if="passwordStrength == 'low'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.weakPassword }}</span>
 | 
			
		||||
					<span v-if="passwordStrength == 'medium'" style="color: var(--warn)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.normalPassword }}</span>
 | 
			
		||||
					<span v-if="passwordStrength == 'high'" style="color: var(--success)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.strongPassword }}</span>
 | 
			
		||||
				</template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-model="retypedPassword" type="password" autocomplete="new-password" required data-cy-signup-password-retype @update:modelValue="onChangePasswordRetype">
 | 
			
		||||
				<template #label>{{ i18n.ts.password }} ({{ i18n.ts.retype }})</template>
 | 
			
		||||
				<template #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
				<template #prefix><i class="ti ti-lock"></i></template>
 | 
			
		||||
				<template #caption>
 | 
			
		||||
					<span v-if="passwordRetypeState == 'match'" style="color: var(--success)"><i class="ph-check ph-bold ph-lg ti-fw"></i> {{ i18n.ts.passwordMatched }}</span>
 | 
			
		||||
					<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ph-warning ph-bold ph-lg ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span>
 | 
			
		||||
					<span v-if="passwordRetypeState == 'match'" style="color: var(--success)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.passwordMatched }}</span>
 | 
			
		||||
					<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span>
 | 
			
		||||
				</template>
 | 
			
		||||
			</MkInput>
 | 
			
		||||
			<MkInput v-if="instance.approvalRequiredForSignup" v-model="reason" type="text" :spellcheck="false" required data-cy-signup-reason>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<div>
 | 
			
		||||
	<div :class="$style.banner">
 | 
			
		||||
		<i class="ph-check ph-bold ph-lglist"></i>
 | 
			
		||||
		<i class="ti ti-checklist"></i>
 | 
			
		||||
	</div>
 | 
			
		||||
	<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
		<div class="_gaps_m">
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
			<MkFolder v-if="availableServerRules" :defaultOpen="true">
 | 
			
		||||
				<template #label>{{ i18n.ts.serverRules }}</template>
 | 
			
		||||
				<template #suffix><i v-if="agreeServerRules" class="ph-check ph-bold ph-lg" style="color: var(--success)"></i></template>
 | 
			
		||||
				<template #suffix><i v-if="agreeServerRules" class="ti ti-check" style="color: var(--success)"></i></template>
 | 
			
		||||
 | 
			
		||||
				<ol class="_gaps_s" :class="$style.rules">
 | 
			
		||||
					<li v-for="item in instance.serverRules" :class="$style.rule"><div :class="$style.ruleText" v-html="sanitizeHtml(item)"></div></li>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,10 +32,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
			<MkFolder v-if="availableTos || availablePrivacyPolicy" :defaultOpen="true">
 | 
			
		||||
				<template #label>{{ tosPrivacyPolicyLabel }}</template>
 | 
			
		||||
				<template #suffix><i v-if="agreeTosAndPrivacyPolicy" class="ph-check ph-bold ph-lg" style="color: var(--success)"></i></template>
 | 
			
		||||
				<template #suffix><i v-if="agreeTosAndPrivacyPolicy" class="ti ti-check" style="color: var(--success)"></i></template>
 | 
			
		||||
				<div class="_gaps_s">
 | 
			
		||||
					<div v-if="availableTos"><a :href="instance.tosUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.termsOfService }} <i class="ph-arrow-square-out ph-bold ph-lg"></i></a></div>
 | 
			
		||||
					<div v-if="availablePrivacyPolicy"><a :href="instance.privacyPolicyUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.privacyPolicy }} <i class="ph-arrow-square-out ph-bold ph-lg"></i></a></div>
 | 
			
		||||
					<div v-if="availableTos"><a :href="instance.tosUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.termsOfService }} <i class="ti ti-external-link"></i></a></div>
 | 
			
		||||
					<div v-if="availablePrivacyPolicy"><a :href="instance.privacyPolicyUrl ?? undefined" class="_link" target="_blank">{{ i18n.ts.privacyPolicy }} <i class="ti ti-external-link"></i></a></div>
 | 
			
		||||
				</div>
 | 
			
		||||
 | 
			
		||||
				<MkSwitch :modelValue="agreeTosAndPrivacyPolicy" style="margin-top: 16px;" @update:modelValue="updateAgreeTosAndPrivacyPolicy">{{ i18n.ts.agree }}</MkSwitch>
 | 
			
		||||
| 
						 | 
				
			
			@ -43,9 +43,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
			<MkFolder :defaultOpen="true">
 | 
			
		||||
				<template #label>{{ i18n.ts.basicNotesBeforeCreateAccount }}</template>
 | 
			
		||||
				<template #suffix><i v-if="agreeNote" class="ph-check ph-bold ph-lg" style="color: var(--success)"></i></template>
 | 
			
		||||
				<template #suffix><i v-if="agreeNote" class="ti ti-check" style="color: var(--success)"></i></template>
 | 
			
		||||
 | 
			
		||||
				<a href="https://activitypub.software/TransFem-org/Sharkey/-/blob/stable/IMPORTANT_NOTES.md" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }} <i class="ph-arrow-square-out ph-bold ph-lg"></i></a>
 | 
			
		||||
				<a href="https://activitypub.software/TransFem-org/Sharkey/-/blob/stable/IMPORTANT_NOTES.md" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }} <i class="ti ti-external-link"></i></a>
 | 
			
		||||
 | 
			
		||||
				<MkSwitch :modelValue="agreeNote" style="margin-top: 16px;" data-cy-signup-rules-notes-agree @update:modelValue="updateAgreeNote">{{ i18n.ts.agree }}</MkSwitch>
 | 
			
		||||
			</MkFolder>
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
			<div class="_buttonsCenter">
 | 
			
		||||
				<MkButton inline rounded @click="emit('cancel')">{{ i18n.ts.cancel }}</MkButton>
 | 
			
		||||
				<MkButton inline primary rounded gradate :disabled="!agreed" data-cy-signup-rules-continue @click="emit('done')">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
				<MkButton inline primary rounded gradate :disabled="!agreed" data-cy-signup-rules-continue @click="emit('done')">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</MkSpacer>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<MkButton @click="close">{{ i18n.ts.gotIt }}</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<button class="_button" :class="$style.close" @click="close"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
	<button class="_button" :class="$style.close" @click="close"><i class="ti ti-x"></i></button>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<span @click="toggle">
 | 
			
		||||
				<slot name="label"></slot><slot></slot>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span v-if="helpText" v-tooltip:dialog="helpText" class="_button _help" :class="$style.help"><i class="ph-question ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="helpText" v-tooltip:dialog="helpText" class="_button _help" :class="$style.help"><i class="ti ti-help-circle"></i></span>
 | 
			
		||||
		</span>
 | 
			
		||||
		<p :class="$style.caption"><slot name="caption"></slot></p>
 | 
			
		||||
	</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<Mfm :text="v" :isBlock="true" />
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-floppy-disk ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<div style="text-align: center; padding: 0 16px;">{{ i18n.ts._initialTutorial._note.description }}</div>
 | 
			
		||||
	<MkNote :class="$style.exampleNoteRoot" style="pointer-events: none;" :note="exampleNote" :mock="true"/>
 | 
			
		||||
	<div class="_gaps_s">
 | 
			
		||||
		<div><i class="ph-arrow-u-up-left ph-bold ph-lg"></i> <b>{{ i18n.ts.reply }}</b> … {{ i18n.ts._initialTutorial._note.reply }}</div>
 | 
			
		||||
		<div><i class="ph-rocket-launch ph-bold ph-lg"></i> <b>{{ i18n.ts.renote }}</b> … {{ i18n.ts._initialTutorial._note.renote }}</div>
 | 
			
		||||
		<div><i class="ti ti-arrow-back-up"></i> <b>{{ i18n.ts.reply }}</b> … {{ i18n.ts._initialTutorial._note.reply }}</div>
 | 
			
		||||
		<div><i class="ti ti-repeat"></i> <b>{{ i18n.ts.renote }}</b> … {{ i18n.ts._initialTutorial._note.renote }}</div>
 | 
			
		||||
		<div><i class="ph-smiley ph-bold ph-lg"></i> <b>{{ i18n.ts.reaction }}</b> … {{ i18n.ts._initialTutorial._note.reaction }}</div>
 | 
			
		||||
		<div><i class="ph-dots-three ph-bold ph-lg"></i> <b>{{ i18n.ts.menu }}</b> … {{ i18n.ts._initialTutorial._note.menu }}</div>
 | 
			
		||||
		<div><i class="ti ti-dots"></i> <b>{{ i18n.ts.menu }}</b> … {{ i18n.ts._initialTutorial._note.menu }}</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
<div v-else-if="phase === 'howToReact'" class="_gaps">
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</I18n>
 | 
			
		||||
	<MkNote :class="$style.exampleNoteRoot" :note="exampleNote" :mock="true" @reaction="addReaction" @removeReaction="removeReaction"/>
 | 
			
		||||
	<div v-if="onceReacted">
 | 
			
		||||
		<b style="color: var(--accent);"><i class="ph-check ph-bold ph-lg"></i> {{ i18n.ts._initialTutorial.wellDone }}</b> {{ i18n.ts._initialTutorial._reaction.reactNotification }}<br>
 | 
			
		||||
		<b style="color: var(--accent);"><i class="ti ti-check"></i> {{ i18n.ts._initialTutorial.wellDone }}</b> {{ i18n.ts._initialTutorial._reaction.reactNotification }}<br>
 | 
			
		||||
		<I18n :src="i18n.ts._initialTutorial._reaction.reactDone">
 | 
			
		||||
			<template #undo>
 | 
			
		||||
				<i class="ph-minus ph-bold ph-lg"></i>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,16 +11,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<template #label>{{ i18n.ts.visibility }}</template>
 | 
			
		||||
		<div class="_gaps">
 | 
			
		||||
			<div>{{ i18n.ts._initialTutorial._postNote._visibility.description }}</div>
 | 
			
		||||
			<div><i class="ph-globe-hemisphere-west ph-bold ph-lg"></i> <b>{{ i18n.ts._visibility.public }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.public }}</div>
 | 
			
		||||
			<div><i class="ph-house ph-bold ph-lg"></i> <b>{{ i18n.ts._visibility.home }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.home }}</div>
 | 
			
		||||
			<div><i class="ph-lock ph-bold ph-lg"></i> <b>{{ i18n.ts._visibility.followers }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.followers }}</div>
 | 
			
		||||
			<div><i class="ti ti-world"></i> <b>{{ i18n.ts._visibility.public }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.public }}</div>
 | 
			
		||||
			<div><i class="ti ti-home"></i> <b>{{ i18n.ts._visibility.home }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.home }}</div>
 | 
			
		||||
			<div><i class="ti ti-lock"></i> <b>{{ i18n.ts._visibility.followers }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.followers }}</div>
 | 
			
		||||
			<div class="_gaps_s">
 | 
			
		||||
				<div><i class="ph-envelope ph-bold ph-lg"></i> <b>{{ i18n.ts._visibility.specified }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.direct }}</div>
 | 
			
		||||
				<div><i class="ti ti-mail"></i> <b>{{ i18n.ts._visibility.specified }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.direct }}</div>
 | 
			
		||||
				<MkInfo :warn="true">
 | 
			
		||||
					<b>{{ i18n.ts._initialTutorial._postNote._visibility.doNotSendConfidencialOnDirect1 }}</b> {{ i18n.ts._initialTutorial._postNote._visibility.doNotSendConfidencialOnDirect2 }}
 | 
			
		||||
				</MkInfo>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div><i class="ph-rocket ph-bold ph-lg"></i> <b>{{ i18n.ts._visibility.disableFederation }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.localOnly }}</div>
 | 
			
		||||
			<div><i class="ti ti-rocket-off"></i> <b>{{ i18n.ts._visibility.disableFederation }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.localOnly }}</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</MkFormSection>
 | 
			
		||||
	<MkFormSection>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		:initialNote="exampleNote"
 | 
			
		||||
		@fileChangeSensitive="doSucceeded"
 | 
			
		||||
	></MkPostForm>
 | 
			
		||||
	<div v-if="onceSucceeded"><b style="color: var(--accent);"><i class="ph-check ph-bold ph-lg"></i> {{ i18n.ts._initialTutorial.wellDone }}</b> {{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.sensitiveSucceeded }}</div>
 | 
			
		||||
	<div v-if="onceSucceeded"><b style="color: var(--accent);"><i class="ti ti-check"></i> {{ i18n.ts._initialTutorial.wellDone }}</b> {{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.sensitiveSucceeded }}</div>
 | 
			
		||||
	<MkFolder>
 | 
			
		||||
		<template #label>{{ i18n.ts.previewNoteText }}</template>
 | 
			
		||||
		<MkNote :mock="true" :note="exampleNote" :class="$style.exampleRoot"></MkNote>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<div class="_gaps">
 | 
			
		||||
	<div style="text-align: center; padding: 0 16px;">{{ i18n.ts._initialTutorial._timeline.description1 }}</div>
 | 
			
		||||
	<div class="_gaps_s">
 | 
			
		||||
		<div><i class="ph-house ph-bold pg-lg"></i> <b>{{ i18n.ts._timelines.home }}</b> … {{ i18n.ts._initialTutorial._timeline.home }}</div>
 | 
			
		||||
		<div><i class="ph-planet ph-bold pg-lg"></i> <b>{{ i18n.ts._timelines.local }}</b> … {{ i18n.ts._initialTutorial._timeline.local }}</div>
 | 
			
		||||
		<div><i class="ph-rocket-launch ph-bold ph-lg"></i> <b>{{ i18n.ts._timelines.social }}</b> … {{ i18n.ts._initialTutorial._timeline.social }}</div>
 | 
			
		||||
		<div><i class="ph-globe-hemisphere-west ph-bold ph-lg"></i> <b>{{ i18n.ts._timelines.global }}</b> … {{ i18n.ts._initialTutorial._timeline.global }}</div>
 | 
			
		||||
		<div><i class="ti ti-home"></i> <b>{{ i18n.ts._timelines.home }}</b> … {{ i18n.ts._initialTutorial._timeline.home }}</div>
 | 
			
		||||
		<div><i class="ti ti-planet"></i> <b>{{ i18n.ts._timelines.local }}</b> … {{ i18n.ts._initialTutorial._timeline.local }}</div>
 | 
			
		||||
		<div><i class="ti ti-universe"></i> <b>{{ i18n.ts._timelines.social }}</b> … {{ i18n.ts._initialTutorial._timeline.social }}</div>
 | 
			
		||||
		<div><i class="ti ti-whirl"></i> <b>{{ i18n.ts._timelines.global }}</b> … {{ i18n.ts._initialTutorial._timeline.global }}</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="_gaps_s">
 | 
			
		||||
		<div>{{ i18n.ts._initialTutorial._timeline.description2 }}</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	@close="close(true)"
 | 
			
		||||
	@closed="emit('closed')"
 | 
			
		||||
>
 | 
			
		||||
	<template v-if="page === 1" #header><i class="ph-pencil-simple ph-bold pg-lg"></i> {{ i18n.ts._initialTutorial._note.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 2" #header><i class="ph-smiley ph-bold pg-lg"></i> {{ i18n.ts._initialTutorial._reaction.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 3" #header><i class="ph-house ph-bold pg-lg"></i> {{ i18n.ts._initialTutorial._timeline.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 4" #header><i class="ph-plus ph-bold pg-lg"></i> {{ i18n.ts._initialTutorial._postNote.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 5" #header><i class="ph-eye-slash ph-bold pg-lg"></i> {{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.title }}</template>
 | 
			
		||||
	<template v-if="page === 1" #header><i class="ti ti-pencil"></i> {{ i18n.ts._initialTutorial._note.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 2" #header><i class="ti ti-mood-smile"></i> {{ i18n.ts._initialTutorial._reaction.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 3" #header><i class="ti ti-home"></i> {{ i18n.ts._initialTutorial._timeline.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 4" #header><i class="ti ti-pencil-plus"></i> {{ i18n.ts._initialTutorial._postNote.title }}</template>
 | 
			
		||||
	<template v-else-if="page === 5" #header><i class="ti ti-eye-exclamation"></i> {{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.title }}</template>
 | 
			
		||||
	<template v-else #header>{{ i18n.ts._initialTutorial.title }}</template>
 | 
			
		||||
 | 
			
		||||
	<div style="overflow-x: clip;">
 | 
			
		||||
| 
						 | 
				
			
			@ -31,10 +31,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
 | 
			
		||||
					<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
						<div class="_gaps" style="text-align: center;">
 | 
			
		||||
							<i class="ph-confetti ph-bold pg-lg" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<i class="ti ti-confetti" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<div style="font-size: 120%;">{{ i18n.ts._initialTutorial._landing.title }}</div>
 | 
			
		||||
							<div>{{ i18n.ts._initialTutorial._landing.description }}</div>
 | 
			
		||||
							<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" @click="page++">{{ i18n.ts._initialTutorial.launchTutorial }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
							<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" @click="page++">{{ i18n.ts._initialTutorial.launchTutorial }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							<MkButton style="margin: 0 auto;" transparent rounded @click="close(true)">{{ i18n.ts.close }}</MkButton>
 | 
			
		||||
						</div>
 | 
			
		||||
					</MkSpacer>
 | 
			
		||||
| 
						 | 
				
			
			@ -48,8 +48,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton v-if="initialPage !== 1" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 1" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -66,8 +66,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate :disabled="!isReactionTutorialPushed" @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate :disabled="!isReactionTutorialPushed" @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +81,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -96,8 +96,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -114,8 +114,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate :disabled="!isSensitiveTutorialSucceeded" @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold pg-lg"></i></MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate :disabled="!isSensitiveTutorialSucceeded" @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
 | 
			
		||||
					<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
						<div class="_gaps" style="text-align: center;">
 | 
			
		||||
							<i class="ph-check ph-bold pg-lg" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<div style="font-size: 120%;">{{ i18n.ts._initialTutorial._done.title }}</div>
 | 
			
		||||
							<I18n :src="i18n.ts._initialTutorial._done.description" tag="div" style="padding: 0 16px;">
 | 
			
		||||
								<template #link>
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
							</I18n>
 | 
			
		||||
							<div>{{ i18n.tsx._initialAccountSetting.haveFun({ name: instance.name ?? host }) }}</div>
 | 
			
		||||
							<div class="_buttonsCenter" style="margin-top: 16px;">
 | 
			
		||||
								<MkButton v-if="initialPage !== 4" rounded @click="page--"><i class="ph-arrow-left ph-bold pg-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton v-if="initialPage !== 4" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton rounded primary gradate @click="close(false)">{{ i18n.ts.close }}</MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<div :class="$style.action">
 | 
			
		||||
		<MkButton :small="true" inline @click="playerEnabled = false">
 | 
			
		||||
			<i class="ph-x ph-bold ph-lg"></i> {{ i18n.ts.disablePlayer }}
 | 
			
		||||
			<i class="ti ti-x"></i> {{ i18n.ts.disablePlayer }}
 | 
			
		||||
		</MkButton>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<div :class="$style.action">
 | 
			
		||||
		<MkButton :small="true" inline @click="tweetExpanded = false">
 | 
			
		||||
			<i class="ph-x ph-bold ph-lg"></i> {{ i18n.ts.close }}
 | 
			
		||||
			<i class="ti ti-x"></i> {{ i18n.ts.close }}
 | 
			
		||||
		</MkButton>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -67,15 +67,15 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<template v-if="showActions">
 | 
			
		||||
		<div v-if="tweetId" :class="$style.action">
 | 
			
		||||
			<MkButton :small="true" inline @click="tweetExpanded = true">
 | 
			
		||||
				<i class="ph-twitter-logo ph-bold ph-lg"></i> {{ i18n.ts.expandTweet }}
 | 
			
		||||
				<i class="ti ti-brand-x"></i> {{ i18n.ts.expandTweet }}
 | 
			
		||||
			</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div v-if="!playerEnabled && player.url" :class="$style.action">
 | 
			
		||||
			<MkButton :small="true" inline @click="playerEnabled = true">
 | 
			
		||||
				<i class="ph-play ph-bold ph-lg"></i> {{ i18n.ts.enablePlayer }}
 | 
			
		||||
				<i class="ti ti-player-play"></i> {{ i18n.ts.enablePlayer }}
 | 
			
		||||
			</MkButton>
 | 
			
		||||
			<MkButton v-if="!isMobile" :small="true" inline @click="openPlayer()">
 | 
			
		||||
				<i class="ph-picture-in-picture ph-bold ph-lg"></i> {{ i18n.ts.openInWindow }}
 | 
			
		||||
				<i class="ti ti-picture-in-picture"></i> {{ i18n.ts.openInWindow }}
 | 
			
		||||
			</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
	</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,10 +24,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				</MkTextarea>
 | 
			
		||||
				<MkRadios v-model="icon">
 | 
			
		||||
					<template #label>{{ i18n.ts.icon }}</template>
 | 
			
		||||
					<option value="info"><i class="ph-info ph-bold ph-lg"></i></option>
 | 
			
		||||
					<option value="warning"><i class="ph-warning ph-bold ph-lg" style="color: var(--warn);"></i></option>
 | 
			
		||||
					<option value="error"><i class="ph-x-circle ph-bold ph-lg" style="color: var(--error);"></i></option>
 | 
			
		||||
					<option value="success"><i class="ph-check ph-bold ph-lg" style="color: var(--success);"></i></option>
 | 
			
		||||
					<option value="info"><i class="ti ti-info-circle"></i></option>
 | 
			
		||||
					<option value="warning"><i class="ti ti-alert-triangle" style="color: var(--warn);"></i></option>
 | 
			
		||||
					<option value="error"><i class="ti ti-circle-x" style="color: var(--error);"></i></option>
 | 
			
		||||
					<option value="success"><i class="ti ti-check" style="color: var(--success);"></i></option>
 | 
			
		||||
				</MkRadios>
 | 
			
		||||
				<MkRadios v-model="display">
 | 
			
		||||
					<template #label>{{ i18n.ts.display }}</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,11 +39,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					{{ i18n.ts._announcement.needConfirmationToRead }}
 | 
			
		||||
					<template #caption>{{ i18n.ts._announcement.needConfirmationToReadDescription }}</template>
 | 
			
		||||
				</MkSwitch>
 | 
			
		||||
				<MkButton v-if="announcement" danger @click="del()"><i class="ph-trash ph-bold ph-lg"></i> {{ i18n.ts.delete }}</MkButton>
 | 
			
		||||
				<MkButton v-if="announcement" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
 | 
			
		||||
			</div>
 | 
			
		||||
		</MkSpacer>
 | 
			
		||||
		<div :class="$style.footer">
 | 
			
		||||
			<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ph-check ph-bold ph-lg"></i> {{ props.announcement ? i18n.ts.update : i18n.ts.create }}</MkButton>
 | 
			
		||||
			<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.announcement ? i18n.ts.update : i18n.ts.create }}</MkButton>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</MkModalWindow>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<div>{{ number(user.followersCount) }}</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<button class="_button" :class="$style.menu" @click="showMenu"><i class="ph-dots-three ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button class="_button" :class="$style.menu" @click="showMenu"><i class="ti ti-dots"></i></button>
 | 
			
		||||
			<MkFollowButton v-if="$i && user.id != $i.id" v-model:user="user" :class="$style.follow" mini/>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div v-else>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
	<MkFolder>
 | 
			
		||||
		<template #label>{{ i18n.ts.makeFollowManuallyApprove }}</template>
 | 
			
		||||
		<template #icon><i class="ph-lock ph-bold ph-lg"></i></template>
 | 
			
		||||
		<template #icon><i class="ti ti-lock"></i></template>
 | 
			
		||||
		<template #suffix>{{ isLocked ? i18n.ts.on : i18n.ts.off }}</template>
 | 
			
		||||
 | 
			
		||||
		<MkSwitch v-model="isLocked">{{ i18n.ts.makeFollowManuallyApprove }}<template #caption>{{ i18n.ts.lockedAccountInfo }}</template></MkSwitch>
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
	<MkFolder>
 | 
			
		||||
		<template #label>{{ i18n.ts.hideOnlineStatus }}</template>
 | 
			
		||||
		<template #icon><i class="ph-eye-slash ph-bold ph-lg"></i></template>
 | 
			
		||||
		<template #icon><i class="ti ti-eye-off"></i></template>
 | 
			
		||||
		<template #suffix>{{ hideOnlineStatus ? i18n.ts.on : i18n.ts.off }}</template>
 | 
			
		||||
 | 
			
		||||
		<MkSwitch v-model="hideOnlineStatus">{{ i18n.ts.hideOnlineStatus }}<template #caption>{{ i18n.ts.hideOnlineStatusDescription }}</template></MkSwitch>
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
	<MkFolder>
 | 
			
		||||
		<template #label>{{ i18n.ts.noCrawle }}</template>
 | 
			
		||||
		<template #icon><i class="ph-planet ph-bold ph-lg"></i></template>
 | 
			
		||||
		<template #icon><i class="ti ti-world-x"></i></template>
 | 
			
		||||
		<template #suffix>{{ noCrawle ? i18n.ts.on : i18n.ts.off }}</template>
 | 
			
		||||
 | 
			
		||||
		<MkSwitch v-model="noCrawle">{{ i18n.ts.noCrawle }}<template #caption>{{ i18n.ts.noCrawleDescription }}</template></MkSwitch>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,8 +18,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div :class="$style.footer">
 | 
			
		||||
		<MkButton v-if="!isFollowing" primary gradate rounded full @click="follow"><i class="ph-plus ph-bold ph-lg"></i> {{ i18n.ts.follow }}</MkButton>
 | 
			
		||||
		<div v-else style="opacity: 0.7; text-align: center;">{{ i18n.ts.youFollowing }} <i class="ph-check ph-bold ph-lg"></i></div>
 | 
			
		||||
		<MkButton v-if="!isFollowing" primary gradate rounded full @click="follow"><i class="ti ti-plus"></i> {{ i18n.ts.follow }}</MkButton>
 | 
			
		||||
		<div v-else style="opacity: 0.7; text-align: center;">{{ i18n.ts.youFollowing }} <i class="ti ti-check"></i></div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,10 +12,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	@close="close(true)"
 | 
			
		||||
	@closed="emit('closed')"
 | 
			
		||||
>
 | 
			
		||||
	<template v-if="page === 1" #header><i class="ph-user-list ph-bold ph-lg"></i> {{ i18n.ts._initialAccountSetting.profileSetting }}</template>
 | 
			
		||||
	<template v-else-if="page === 2" #header><i class="ph-lock ph-bold ph-lg"></i> {{ i18n.ts._initialAccountSetting.privacySetting }}</template>
 | 
			
		||||
	<template v-else-if="page === 3" #header><i class="ph-user-plus ph-bold ph-lg"></i> {{ i18n.ts.follow }}</template>
 | 
			
		||||
	<template v-else-if="page === 4" #header><i class="ph-bell-ringing ph-bold ph-lg"></i> {{ i18n.ts.pushNotification }}</template>
 | 
			
		||||
	<template v-if="page === 1" #header><i class="ti ti-user-edit"></i> {{ i18n.ts._initialAccountSetting.profileSetting }}</template>
 | 
			
		||||
	<template v-else-if="page === 2" #header><i class="ti ti-lock"></i> {{ i18n.ts._initialAccountSetting.privacySetting }}</template>
 | 
			
		||||
	<template v-else-if="page === 3" #header><i class="ti ti-user-plus"></i> {{ i18n.ts.follow }}</template>
 | 
			
		||||
	<template v-else-if="page === 4" #header><i class="ti ti-bell-plus"></i> {{ i18n.ts.pushNotification }}</template>
 | 
			
		||||
	<template v-else-if="page === 5" #header>{{ i18n.ts.done }}</template>
 | 
			
		||||
	<template v-else #header>{{ i18n.ts.initialAccountSetting }}</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,10 +35,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
 | 
			
		||||
					<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
						<div class="_gaps" style="text-align: center;">
 | 
			
		||||
							<i class="ph-confetti ph-bold ph-lg" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<i class="ti ti-confetti" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<div style="font-size: 120%;">{{ i18n.ts._initialAccountSetting.accountCreated }}</div>
 | 
			
		||||
							<div>{{ i18n.ts._initialAccountSetting.letsStartAccountSetup }}</div>
 | 
			
		||||
							<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" data-cy-user-setup-continue @click="page++">{{ i18n.ts._initialAccountSetting.profileSetting }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
							<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" data-cy-user-setup-continue @click="page++">{{ i18n.ts._initialAccountSetting.profileSetting }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							<MkButton style="margin: 0 auto;" transparent rounded @click="later(true)">{{ i18n.ts.later }}</MkButton>
 | 
			
		||||
						</div>
 | 
			
		||||
					</MkSpacer>
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +52,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ph-arrow-left ph-bold ph-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +67,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						</MkSpacer>
 | 
			
		||||
						<div :class="$style.pageFooter">
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ph-arrow-left ph-bold ph-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +81,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					</MkSpacer>
 | 
			
		||||
					<div :class="$style.pageFooter">
 | 
			
		||||
						<div class="_buttonsCenter">
 | 
			
		||||
							<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ph-arrow-left ph-bold ph-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
							<MkButton primary rounded gradate style="" data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
							<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
							<MkButton primary rounded gradate style="" data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -91,13 +91,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<div :class="$style.centerPage">
 | 
			
		||||
					<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
						<div class="_gaps" style="text-align: center;">
 | 
			
		||||
							<i class="ph-bell-ringing ph-bold ph-lg" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<i class="ti ti-bell-ringing-2" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<div style="font-size: 120%;">{{ i18n.ts.pushNotification }}</div>
 | 
			
		||||
							<div style="padding: 0 16px;">{{ i18n.tsx._initialAccountSetting.pushNotificationDescription({ name: instance.name ?? host }) }}</div>
 | 
			
		||||
							<MkPushNotificationAllowButton primary showOnlyToRegister style="margin: 0 auto;"/>
 | 
			
		||||
							<div class="_buttonsCenter" style="margin-top: 16px;">
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ph-arrow-left ph-bold ph-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</MkSpacer>
 | 
			
		||||
| 
						 | 
				
			
			@ -108,14 +108,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
 | 
			
		||||
					<MkSpacer :marginMin="20" :marginMax="28">
 | 
			
		||||
						<div class="_gaps" style="text-align: center;">
 | 
			
		||||
							<i class="ph-check ph-bold ph-lg" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--accent);"></i>
 | 
			
		||||
							<div style="font-size: 120%;">{{ i18n.ts._initialAccountSetting.initialAccountSettingCompleted }}</div>
 | 
			
		||||
							<div>{{ i18n.tsx._initialAccountSetting.youCanContinueTutorial({ name: instance.name ?? host }) }}</div>
 | 
			
		||||
							<div class="_buttonsCenter" style="margin-top: 16px;">
 | 
			
		||||
								<MkButton rounded primary gradate data-cy-user-setup-continue @click="launchTutorial()">{{ i18n.ts._initialAccountSetting.startTutorial }} <i class="ph-arrow-right ph-bold ph-lg"></i></MkButton>
 | 
			
		||||
								<MkButton rounded primary gradate data-cy-user-setup-continue @click="launchTutorial()">{{ i18n.ts._initialAccountSetting.startTutorial }} <i class="ti ti-arrow-right"></i></MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="_buttonsCenter">
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ph-arrow-left ph-bold ph-lg"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
 | 
			
		||||
								<MkButton rounded primary data-cy-user-setup-continue @click="setupComplete()">{{ i18n.ts.close }}</MkButton>
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,28 +10,28 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			{{ i18n.ts.visibility }}
 | 
			
		||||
		</div>
 | 
			
		||||
		<button key="public" :disabled="isSilenced || isReplyVisibilitySpecified" class="_button" :class="[$style.item, { [$style.active]: v === 'public' }]" data-index="1" @click="choose('public')">
 | 
			
		||||
			<div :class="$style.icon"><i class="ph-globe-hemisphere-west ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div :class="$style.icon"><i class="ti ti-world"></i></div>
 | 
			
		||||
			<div :class="$style.body">
 | 
			
		||||
				<span :class="$style.itemTitle">{{ i18n.ts._visibility.public }}</span>
 | 
			
		||||
				<span :class="$style.itemDescription">{{ i18n.ts._visibility.publicDescription }}</span>
 | 
			
		||||
			</div>
 | 
			
		||||
		</button>
 | 
			
		||||
		<button key="home" :disabled="isReplyVisibilitySpecified" class="_button" :class="[$style.item, { [$style.active]: v === 'home' }]" data-index="2" @click="choose('home')">
 | 
			
		||||
			<div :class="$style.icon"><i class="ph-house ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div :class="$style.icon"><i class="ti ti-home"></i></div>
 | 
			
		||||
			<div :class="$style.body">
 | 
			
		||||
				<span :class="$style.itemTitle">{{ i18n.ts._visibility.home }}</span>
 | 
			
		||||
				<span :class="$style.itemDescription">{{ i18n.ts._visibility.homeDescription }}</span>
 | 
			
		||||
			</div>
 | 
			
		||||
		</button>
 | 
			
		||||
		<button key="followers" :disabled="isReplyVisibilitySpecified" class="_button" :class="[$style.item, { [$style.active]: v === 'followers' }]" data-index="3" @click="choose('followers')">
 | 
			
		||||
			<div :class="$style.icon"><i class="ph-lock ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div :class="$style.icon"><i class="ti ti-lock"></i></div>
 | 
			
		||||
			<div :class="$style.body">
 | 
			
		||||
				<span :class="$style.itemTitle">{{ i18n.ts._visibility.followers }}</span>
 | 
			
		||||
				<span :class="$style.itemDescription">{{ i18n.ts._visibility.followersDescription }}</span>
 | 
			
		||||
			</div>
 | 
			
		||||
		</button>
 | 
			
		||||
		<button key="specified" :disabled="localOnly" class="_button" :class="[$style.item, { [$style.active]: v === 'specified' }]" data-index="4" @click="choose('specified')">
 | 
			
		||||
			<div :class="$style.icon"><i class="ph-envelope ph-bold ph-lg"></i></div>
 | 
			
		||||
			<div :class="$style.icon"><i class="ti ti-mail"></i></div>
 | 
			
		||||
			<div :class="$style.body">
 | 
			
		||||
				<span :class="$style.itemTitle">{{ i18n.ts._visibility.specified }}</span>
 | 
			
		||||
				<span :class="$style.itemDescription">{{ i18n.ts._visibility.specifiedDescription }}</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<div v-if="instance" :class="$style.root">
 | 
			
		||||
	<div :class="[$style.main, $style.panel]">
 | 
			
		||||
		<img :src="instance.iconUrl || '/apple-touch-icon.png'" alt="" :class="$style.mainIcon"/>
 | 
			
		||||
		<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ph-dots-three ph-bold ph-lg"></i></button>
 | 
			
		||||
		<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
 | 
			
		||||
		<div :class="$style.mainFg">
 | 
			
		||||
			<h1 :class="$style.mainTitle">
 | 
			
		||||
				<!-- 背景色によってはロゴが見えなくなるのでとりあえず無効に -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<MkModal ref="modal" :preferType="'dialog'" :zPriority="'high'" @click="success ? done() : () => {}" @closed="emit('closed')">
 | 
			
		||||
	<div :class="[$style.root, { [$style.iconOnly]: (text == null) || success }]">
 | 
			
		||||
		<i v-if="success" :class="[$style.icon, $style.success]" class="ph-check ph-bold ph-lg"></i>
 | 
			
		||||
		<i v-if="success" :class="[$style.icon, $style.success]" class="ti ti-check"></i>
 | 
			
		||||
		<MkLoading v-else :class="[$style.icon, $style.waiting]" :em="true"/>
 | 
			
		||||
		<div v-if="text && !success" :class="$style.text">{{ text }}<MkEllipsis/></div>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<template #label>{{ i18n.ts.selectWidget }}</template>
 | 
			
		||||
				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.ts._widgets[widget] }}</option>
 | 
			
		||||
			</MkSelect>
 | 
			
		||||
			<MkButton inline primary data-cy-widget-add @click="addWidget"><i class="ph-plus ph-bold ph-lg"></i> {{ i18n.ts.add }}</MkButton>
 | 
			
		||||
			<MkButton inline primary data-cy-widget-add @click="addWidget"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
 | 
			
		||||
			<MkButton inline @click="$emit('exit')">{{ i18n.ts.close }}</MkButton>
 | 
			
		||||
		</header>
 | 
			
		||||
		<Sortable
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +25,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		>
 | 
			
		||||
			<template #item="{element}">
 | 
			
		||||
				<div :class="[$style.widget, $style.customizeContainer]" data-cy-customize-container>
 | 
			
		||||
					<button :class="$style.customizeContainerConfig" class="_button" @click.prevent.stop="configWidget(element.id)"><i class="ph-gear ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button :class="$style.customizeContainerRemove" data-cy-customize-container-remove class="_button" @click.prevent.stop="removeWidget(element)"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button :class="$style.customizeContainerConfig" class="_button" @click.prevent.stop="configWidget(element.id)"><i class="ti ti-settings"></i></button>
 | 
			
		||||
					<button :class="$style.customizeContainerRemove" data-cy-customize-container-remove class="_button" @click.prevent.stop="removeWidget(element)"><i class="ti ti-x"></i></button>
 | 
			
		||||
					<div class="handle">
 | 
			
		||||
						<component :is="`widget-${element.name}`" :ref="el => widgetRefs[element.id] = el" class="widget" :class="$style.customizeContainerHandleWidget" :widget="element" @updateProps="updateWidget(element.id, $event)"/>
 | 
			
		||||
					</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ function onContextmenu(widget: Widget, ev: MouseEvent) {
 | 
			
		|||
		type: 'label',
 | 
			
		||||
		text: i18n.ts._widgets[widget.name],
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'ph-gear ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-settings',
 | 
			
		||||
		text: i18n.ts.settings,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			configWidget(widget.id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,11 +27,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<template v-if="!minimized">
 | 
			
		||||
						<button v-for="button in buttonsRight" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
 | 
			
		||||
					</template>
 | 
			
		||||
					<button v-if="canResize && minimized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMinimize()"><i class="ph-frame-corners ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button v-else-if="canResize && !maximized" v-tooltip="i18n.ts.windowMinimize" class="_button" :class="$style.headerButton" @click="minimize()"><i class="ph-arrows-in-simple ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button v-if="canResize && maximized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMaximize()"><i class="ph-picture-in-picture ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button v-else-if="canResize && !maximized && !minimized" v-tooltip="i18n.ts.windowMaximize" class="_button" :class="$style.headerButton" @click="maximize()"><i class="ph-frame-corners ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button v-if="closeButton" v-tooltip="i18n.ts.close" class="_button" :class="$style.headerButton" @click="close()"><i class="ph-x ph-bold ph-lg"></i></button>
 | 
			
		||||
					<button v-if="canResize && minimized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMinimize()"><i class="ti ti-maximize"></i></button>
 | 
			
		||||
					<button v-else-if="canResize && !maximized" v-tooltip="i18n.ts.windowMinimize" class="_button" :class="$style.headerButton" @click="minimize()"><i class="ti ti-minimize"></i></button>
 | 
			
		||||
					<button v-if="canResize && maximized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMaximize()"><i class="ti ti-picture-in-picture"></i></button>
 | 
			
		||||
					<button v-else-if="canResize && !maximized && !minimized" v-tooltip="i18n.ts.windowMaximize" class="_button" :class="$style.headerButton" @click="maximize()"><i class="ti ti-rectangle"></i></button>
 | 
			
		||||
					<button v-if="closeButton" v-tooltip="i18n.ts.close" class="_button" :class="$style.headerButton" @click="close()"><i class="ti ti-x"></i></button>
 | 
			
		||||
				</span>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div :class="$style.content">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<template>
 | 
			
		||||
<MkWindow :initialWidth="640" :initialHeight="402" :canResize="true" :closeButton="true">
 | 
			
		||||
	<template #header>
 | 
			
		||||
		<i class="icon ph-youtube-logo ph-bold ph-lg" style="margin-right: 0.5em;"></i>
 | 
			
		||||
		<i class="icon ti ti-brand-youtube" style="margin-right: 0.5em;"></i>
 | 
			
		||||
		<span>{{ title ?? 'YouTube' }}</span>
 | 
			
		||||
	</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,13 +21,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</MkA>:
 | 
			
		||||
		<Mfm :text="getNoteSummary(appearNote.reply)" :plain="true" :nowrap="true" :author="appearNote.reply.user" :nyaize="'respect'" :class="$style.collapsedInReplyToText" @click="inReplyToCollapsed = false"/>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div v-if="pinned" :class="$style.tip"><i class="ph-push-pin ph-bold ph-lg"></i> {{ i18n.ts.pinnedNote }}</div>
 | 
			
		||||
	<!--<div v-if="appearNote._prId_" class="tip"><i class="ph-megaphone ph-bold ph-lg"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ph-x ph-bold ph-lg"></i></button></div>-->
 | 
			
		||||
	<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ph-lightning ph-bold ph-lg"></i> {{ i18n.ts.featured }}</div>-->
 | 
			
		||||
	<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
 | 
			
		||||
	<!--<div v-if="appearNote._prId_" class="tip"><i class="ti ti-speakerphone"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ti ti-x"></i></button></div>-->
 | 
			
		||||
	<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ti ti-bolt"></i> {{ i18n.ts.featured }}</div>-->
 | 
			
		||||
	<div v-if="isRenote" :class="$style.renote">
 | 
			
		||||
		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
 | 
			
		||||
		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
 | 
			
		||||
		<i class="ph-rocket-launch ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
		<i class="ti ti-repeat" style="margin-right: 4px;"></i>
 | 
			
		||||
		<I18n :src="i18n.ts.renotedBy" tag="span" :class="$style.renoteText">
 | 
			
		||||
			<template #user>
 | 
			
		||||
				<MkA v-user-preview="note.userId" :class="$style.renoteUserName" :to="userPage(note.user)">
 | 
			
		||||
| 
						 | 
				
			
			@ -37,16 +37,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</I18n>
 | 
			
		||||
		<div :class="$style.renoteInfo">
 | 
			
		||||
			<button ref="renoteTime" :class="$style.renoteTime" class="_button" @click="showRenoteMenu()">
 | 
			
		||||
				<i class="ph-dots-three ph-bold ph-lg" :class="$style.renoteMenu"></i>
 | 
			
		||||
				<i class="ti ti-dots" :class="$style.renoteMenu"></i>
 | 
			
		||||
				<MkTime :time="note.createdAt"/>
 | 
			
		||||
			</button>
 | 
			
		||||
			<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ph-television ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
			<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
 | 
			
		||||
			<span v-if="note.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
						<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
 | 
			
		||||
					</button>
 | 
			
		||||
				</div>
 | 
			
		||||
				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
				<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
			</div>
 | 
			
		||||
			<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
 | 
			
		||||
				<template #more>
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			</MkReactionsViewer>
 | 
			
		||||
			<footer :class="$style.footer">
 | 
			
		||||
				<button :class="$style.footerButton" class="_button" @click.stop @click="reply()">
 | 
			
		||||
					<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-arrow-back-up"></i>
 | 
			
		||||
					<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.repliesCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button
 | 
			
		||||
| 
						 | 
				
			
			@ -129,11 +129,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					@click.stop
 | 
			
		||||
					@mousedown="renoted ? undoRenote(appearNote) : boostVisibility()"
 | 
			
		||||
				>
 | 
			
		||||
					<i class="ph-rocket-launch ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-repeat"></i>
 | 
			
		||||
					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button v-else :class="$style.footerButton" class="_button" disabled>
 | 
			
		||||
					<i class="ph-prohibit ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-ban"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button
 | 
			
		||||
					v-if="canRenote && !props.mock"
 | 
			
		||||
| 
						 | 
				
			
			@ -149,17 +149,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
					<i class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button ref="reactButton" :class="$style.footerButton" class="_button" @click="toggleReact()" @click.stop>
 | 
			
		||||
					<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ph-heart ph-bold ph-lg" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.myReaction != null" class="ph-minus ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
					<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i>
 | 
			
		||||
					<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
 | 
			
		||||
					<i v-else class="ph-smiley ph-bold ph-lg"></i>
 | 
			
		||||
					<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.reactionCount) }}</p>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown="clip()">
 | 
			
		||||
					<i class="ph-paperclip ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-paperclip"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
				<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="showMenu()">
 | 
			
		||||
					<i class="ph-dots-three ph-bold ph-lg"></i>
 | 
			
		||||
					<i class="ti ti-dots"></i>
 | 
			
		||||
				</button>
 | 
			
		||||
			</footer>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -740,7 +740,7 @@ function showRenoteMenu(viaKeyboard = false): void {
 | 
			
		|||
	function getUnrenote(): MenuItem {
 | 
			
		||||
		return {
 | 
			
		||||
			text: i18n.ts.unrenote,
 | 
			
		||||
			icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-trash',
 | 
			
		||||
			danger: true,
 | 
			
		||||
			action: () => {
 | 
			
		||||
				misskeyApi('notes/delete', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	</div>
 | 
			
		||||
	<div v-if="isRenote" :class="$style.renote">
 | 
			
		||||
		<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
 | 
			
		||||
		<i class="ph-rocket-launch ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
		<i class="ti ti-repeat" style="margin-right: 4px;"></i>
 | 
			
		||||
		<span :class="$style.renoteText">
 | 
			
		||||
			<I18n :src="i18n.ts.renotedBy" tag="span">
 | 
			
		||||
				<template #user>
 | 
			
		||||
| 
						 | 
				
			
			@ -28,15 +28,15 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		</span>
 | 
			
		||||
		<div :class="$style.renoteInfo">
 | 
			
		||||
			<button ref="renoteTime" class="_button" :class="$style.renoteTime" @click="showRenoteMenu()">
 | 
			
		||||
				<i v-if="isMyRenote" class="ph-dots-three ph-bold ph-lg" style="margin-right: 4px;"></i>
 | 
			
		||||
				<i v-if="isMyRenote" class="ti ti-dots" style="margin-right: 4px;"></i>
 | 
			
		||||
				<MkTime :time="note.createdAt"/>
 | 
			
		||||
			</button>
 | 
			
		||||
			<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
				<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
			</span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
			<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<template v-if="appearNote.reply && appearNote.reply.replyId">
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +64,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<div :class="$style.noteHeaderBody">
 | 
			
		||||
					<div :class="$style.noteHeaderInfo">
 | 
			
		||||
						<span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]">
 | 
			
		||||
							<i v-if="appearNote.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
							<i v-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
							<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
						</span>
 | 
			
		||||
						<span v-if="appearNote.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
						<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
						<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
					</div>
 | 
			
		||||
					<SkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
 | 
			
		||||
				</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				</div>
 | 
			
		||||
				<div v-if="appearNote.renote" :class="$style.quote"><SkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws"/></div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
			<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div :class="$style.noteFooterInfo">
 | 
			
		||||
			<div v-if="appearNote.updatedAt">
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" ref="reactionsViewer" :note="appearNote"/>
 | 
			
		||||
		<footer :class="$style.footer">
 | 
			
		||||
			<button class="_button" :class="$style.noteFooterButton" @click="reply()">
 | 
			
		||||
				<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-arrow-back-up"></i>
 | 
			
		||||
				<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button
 | 
			
		||||
| 
						 | 
				
			
			@ -137,11 +137,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				:style="renoted ? 'color: var(--accent) !important;' : ''"
 | 
			
		||||
				@mousedown="renoted ? undoRenote() : boostVisibility()"
 | 
			
		||||
			>
 | 
			
		||||
				<i class="ph-rocket-launch ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-repeat"></i>
 | 
			
		||||
				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-else class="_button" :class="$style.noteFooterButton" disabled>
 | 
			
		||||
				<i class="ph-prohibit ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-ban"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button
 | 
			
		||||
				v-if="canRenote"
 | 
			
		||||
| 
						 | 
				
			
			@ -156,23 +156,23 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
				<i class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
 | 
			
		||||
				<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ph-heart ph-bold ph-lg" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.myReaction != null" class="ph-minus ph-bold ph-lg" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
 | 
			
		||||
				<i v-if="appearNote.reactionAcceptance === 'likeOnly' && appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--eventReactionHeart);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.myReaction != null" class="ti ti-minus" style="color: var(--accent);"></i>
 | 
			
		||||
				<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
 | 
			
		||||
				<i v-else class="ph-smiley ph-bold ph-lg"></i>
 | 
			
		||||
				<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.reactionCount) }}</p>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()">
 | 
			
		||||
				<i class="ph-paperclip ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-paperclip"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
			<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown="showMenu()">
 | 
			
		||||
				<i class="ph-dots-three ph-bold ph-lg"></i>
 | 
			
		||||
				<i class="ti ti-dots"></i>
 | 
			
		||||
			</button>
 | 
			
		||||
		</footer>
 | 
			
		||||
	</article>
 | 
			
		||||
	<div :class="$style.tabs">
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ph-arrow-u-up-left ph-bold ph-lg"></i> {{ i18n.ts.replies }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ph-rocket-launch ph-bold ph-lg"></i> {{ i18n.ts.renotes }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ti ti-arrow-back-up"></i> {{ i18n.ts.replies }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ti ti-repeat"></i> {{ i18n.ts.renotes }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'quotes' }]" @click="tab = 'quotes'"><i class="ph-quotes ph-bold ph-lg"></i> {{ i18n.ts._notification._types.quote }}</button>
 | 
			
		||||
		<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'reactions' }]" @click="tab = 'reactions'"><i class="ph-smiley ph-bold ph-lg"></i> {{ i18n.ts.reactions }}</button>
 | 
			
		||||
	</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -719,7 +719,7 @@ function showRenoteMenu(viaKeyboard = false): void {
 | 
			
		|||
	pleaseLogin();
 | 
			
		||||
	os.popupMenu([{
 | 
			
		||||
		text: i18n.ts.unrenote,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		danger: true,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			misskeyApi('notes/delete', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,13 +61,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<MkTime :time="note.createdAt" colored/>
 | 
			
		||||
		</MkA>
 | 
			
		||||
		<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
 | 
			
		||||
			<i v-if="note.visibility === 'home'" class="ph-house ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'followers'" class="ph-lock ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'specified'" ref="specified" class="ph-envelope ph-bold ph-lg"></i>
 | 
			
		||||
			<i v-if="note.visibility === 'home'" class="ti ti-home"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
 | 
			
		||||
			<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
 | 
			
		||||
		</span>
 | 
			
		||||
		<span v-if="note.updatedAt" ref="menuVersionsButton" style="margin-left: 0.5em; cursor: pointer;" title="Edited" @mousedown="menuVersions()"><i class="ph-pencil-simple ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ph-rocket ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ph-television ph-bold ph-lg"></i></span>
 | 
			
		||||
		<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 | 
			
		||||
		<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
 | 
			
		||||
	</div>
 | 
			
		||||
</header>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="props.isReply"/>
 | 
			
		||||
	</template>
 | 
			
		||||
	<div v-else :class="$style.more">
 | 
			
		||||
		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
 | 
			
		||||
		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ti ti-chevron-double-right"></i></MkA>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
<div v-else :class="$style.muted" @click="muted = false">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<span :class="$style.text"><slot></slot></span>
 | 
			
		||||
		<span :class="$style.suffix">
 | 
			
		||||
			<span :class="$style.suffixText"><slot name="suffix"></slot></span>
 | 
			
		||||
			<i class="ph-arrow-square-out ph-bold ph-lg"></i>
 | 
			
		||||
			<i class="ti ti-external-link"></i>
 | 
			
		||||
		</span>
 | 
			
		||||
	</a>
 | 
			
		||||
	<a v-else-if="onClick" :class="[$style.main, { [$style.active]: active }]" class="_button" :behavior="behavior" @click="onClick">
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
		<span :class="$style.text"><slot></slot></span>
 | 
			
		||||
		<span :class="$style.suffix">
 | 
			
		||||
			<span :class="$style.suffixText"><slot name="suffix"></slot></span>
 | 
			
		||||
			<i class="ph-caret-right ph-bold ph-lg"></i>
 | 
			
		||||
			<i class="ti ti-chevron-right"></i>
 | 
			
		||||
		</span>
 | 
			
		||||
	</MkA>
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
</div>
 | 
			
		||||
<div v-else>
 | 
			
		||||
	<div :class="$style.error">
 | 
			
		||||
		<div><i class="ph-warning ph-bold ph-lg"></i> {{ i18n.ts.somethingHappened }}</div>
 | 
			
		||||
		<MkButton inline style="margin-top: 16px;" @click="retry"><i class="ph-arrow-clockwise ph-bold ph-lg"></i> {{ i18n.ts.retry }}</MkButton>
 | 
			
		||||
		<div><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</div>
 | 
			
		||||
		<MkButton inline style="margin-top: 16px;" @click="retry"><i class="ti ti-reload"></i> {{ i18n.ts.retry }}</MkButton>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,25 +55,25 @@ function onContextmenu(ev) {
 | 
			
		|||
		type: 'label',
 | 
			
		||||
		text: props.to,
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'ph-app-window ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-app-window',
 | 
			
		||||
		text: i18n.ts.openInWindow,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			os.pageWindow(props.to);
 | 
			
		||||
		},
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'ph-eject ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-player-eject',
 | 
			
		||||
		text: i18n.ts.showInPage,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			router.push(props.to, 'forcePage');
 | 
			
		||||
		},
 | 
			
		||||
	}, { type: 'divider' }, {
 | 
			
		||||
		icon: 'ph-arrow-square-out ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-external-link',
 | 
			
		||||
		text: i18n.ts.openInNewTab,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			window.open(props.to, '_blank', 'noopener');
 | 
			
		||||
		},
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'ph-link ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-link',
 | 
			
		||||
		text: i18n.ts.copyLink,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			copyToClipboard(`${url}${props.to}`);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			}"
 | 
			
		||||
		>
 | 
			
		||||
			<img :src="chosen.imageUrl" :class="$style.img">
 | 
			
		||||
			<button class="_button" :class="$style.i" @click.prevent.stop="toggleMenu"><i :class="$style.iIcon" class="ph-info ph-bold ph-lg"></i></button>
 | 
			
		||||
			<button class="_button" :class="$style.i" @click.prevent.stop="toggleMenu"><i :class="$style.iIcon" class="ti ti-info-circle"></i></button>
 | 
			
		||||
		</component>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div v-else :class="$style.menu">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ function onClick(ev: MouseEvent) {
 | 
			
		|||
			text: `:${props.name}:`,
 | 
			
		||||
		}, {
 | 
			
		||||
			text: i18n.ts.copy,
 | 
			
		||||
			icon: 'ph-copy ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-copy',
 | 
			
		||||
			action: () => {
 | 
			
		||||
				copyToClipboard(`:${props.name}:`);
 | 
			
		||||
				os.success();
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ function onClick(ev: MouseEvent) {
 | 
			
		|||
			},
 | 
			
		||||
		}] : []), {
 | 
			
		||||
			text: i18n.ts.info,
 | 
			
		||||
			icon: 'ph-info ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-info-circle',
 | 
			
		||||
			action: async () => {
 | 
			
		||||
				os.popup(MkCustomEmojiDetailedDialog, {
 | 
			
		||||
					emoji: await misskeyApiGet('emoji', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ function onClick(ev: MouseEvent) {
 | 
			
		|||
			text: props.emoji,
 | 
			
		||||
		}, {
 | 
			
		||||
			text: i18n.ts.copy,
 | 
			
		||||
			icon: 'ph-copy ph-bold ph-lg',
 | 
			
		||||
			icon: 'ti ti-copy',
 | 
			
		||||
			action: () => {
 | 
			
		||||
				copyToClipboard(props.emoji);
 | 
			
		||||
				os.success();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear>
 | 
			
		||||
	<div :class="$style.root">
 | 
			
		||||
		<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
 | 
			
		||||
		<p :class="$style.text"><i class="ph-warning ph-bold ph-lg"></i> {{ i18n.ts.somethingHappened }}</p>
 | 
			
		||||
		<p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</p>
 | 
			
		||||
		<MkButton :class="$style.button" @click="() => emit('retry')">{{ i18n.ts.retry }}</MkButton>
 | 
			
		||||
	</div>
 | 
			
		||||
</Transition>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -360,7 +360,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
 | 
			
		|||
							style: 'display: inline-block; font-size: 90%; border: solid 1px var(--divider); border-radius: var(--radius-ellipse); padding: 4px 10px 4px 6px;',
 | 
			
		||||
						}, [
 | 
			
		||||
							h('i', {
 | 
			
		||||
								class: 'ph-clock ph-bold ph-lg',
 | 
			
		||||
								class: 'ti ti-clock',
 | 
			
		||||
								style: 'margin-right: 0.25em;',
 | 
			
		||||
							}),
 | 
			
		||||
							h(MkTime, {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ export const Icon = {
 | 
			
		|||
		tabs: [
 | 
			
		||||
			{
 | 
			
		||||
				...OneTab.args.tabs[0],
 | 
			
		||||
				icon: 'ph-house ph-bold ph-lg',
 | 
			
		||||
				icon: 'ti ti-home',
 | 
			
		||||
			},
 | 
			
		||||
		],
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -86,17 +86,17 @@ export const SomeTabs = {
 | 
			
		|||
			{
 | 
			
		||||
				key: 'princess',
 | 
			
		||||
				title: 'Princess',
 | 
			
		||||
				icon: 'ph-crown ph-bold ph-lg',
 | 
			
		||||
				icon: 'ti ti-crown',
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				key: 'fairy',
 | 
			
		||||
				title: 'Fairy',
 | 
			
		||||
				icon: 'ph-snowflake ph-bold ph-lg',
 | 
			
		||||
				icon: 'ti ti-snowflake',
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				key: 'angel',
 | 
			
		||||
				title: 'Angel',
 | 
			
		||||
				icon: 'ph-feather ph-bold ph-lg',
 | 
			
		||||
				icon: 'ti ti-feather',
 | 
			
		||||
			},
 | 
			
		||||
		],
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
	<span v-if="pathname != ''" :class="$style.pathname">{{ self ? pathname.substring(1) : pathname }}</span>
 | 
			
		||||
	<span :class="$style.query">{{ query }}</span>
 | 
			
		||||
	<span :class="$style.hash">{{ hash }}</span>
 | 
			
		||||
	<i v-if="target === '_blank'" :class="$style.icon" class="ph-arrow-square-out ph-bold ph-lg"></i>
 | 
			
		||||
	<i v-if="target === '_blank'" :class="$style.icon" class="ti ti-external-link"></i>
 | 
			
		||||
</component>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
<!-- 動的ページのブロックの代替。利用できないということを表示する -->
 | 
			
		||||
<template>
 | 
			
		||||
<div :class="$style.root">
 | 
			
		||||
	<div :class="$style.heading"><i class="ph ph-dice-5 ph-bold ph-lg"></i> {{ i18n.ts._pages.blocks.dynamic }}</div>
 | 
			
		||||
	<div :class="$style.heading"><i class="ti ti-dice-5"></i> {{ i18n.ts._pages.blocks.dynamic }}</div>
 | 
			
		||||
	<I18n :src="i18n.ts._pages.blocks.dynamicDescription" tag="div" :class="$style.text">
 | 
			
		||||
		<template #play>
 | 
			
		||||
			<MkA to="/play" class="_link">Play</MkA>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -119,6 +119,7 @@ export const notificationTypes = [
 | 
			
		|||
	'roleAssigned',
 | 
			
		||||
	'achievementEarned',
 | 
			
		||||
	'app',
 | 
			
		||||
	'edited'
 | 
			
		||||
] as const;
 | 
			
		||||
export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ import { unisonReload } from '@/scripts/unison-reload.js';
 | 
			
		|||
export const navbarItemDef = reactive({
 | 
			
		||||
	notifications: {
 | 
			
		||||
		title: i18n.ts.notifications,
 | 
			
		||||
		icon: 'ph-bell ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-bell',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		indicated: computed(() => $i != null && $i.hasUnreadNotification),
 | 
			
		||||
		indicateValue: computed(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,66 +34,66 @@ export const navbarItemDef = reactive({
 | 
			
		|||
	},
 | 
			
		||||
	drive: {
 | 
			
		||||
		title: i18n.ts.drive,
 | 
			
		||||
		icon: 'ph-cloud ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-cloud',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: '/my/drive',
 | 
			
		||||
	},
 | 
			
		||||
	followRequests: {
 | 
			
		||||
		title: i18n.ts.followRequests,
 | 
			
		||||
		icon: 'ph-user-plus ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-user-plus',
 | 
			
		||||
		show: computed(() => $i != null && $i.isLocked),
 | 
			
		||||
		indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest),
 | 
			
		||||
		to: '/my/follow-requests',
 | 
			
		||||
	},
 | 
			
		||||
	explore: {
 | 
			
		||||
		title: i18n.ts.explore,
 | 
			
		||||
		icon: 'ph-hash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-hash',
 | 
			
		||||
		to: '/explore',
 | 
			
		||||
	},
 | 
			
		||||
	announcements: {
 | 
			
		||||
		title: i18n.ts.announcements,
 | 
			
		||||
		icon: 'ph-megaphone ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-speakerphone',
 | 
			
		||||
		indicated: computed(() => $i != null && $i.hasUnreadAnnouncement),
 | 
			
		||||
		to: '/announcements',
 | 
			
		||||
	},
 | 
			
		||||
	search: {
 | 
			
		||||
		title: i18n.ts.search,
 | 
			
		||||
		icon: 'ph-magnifying-glass ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-search',
 | 
			
		||||
		to: '/search',
 | 
			
		||||
	},
 | 
			
		||||
	lookup: {
 | 
			
		||||
		title: i18n.ts.lookup,
 | 
			
		||||
		icon: 'ph-binoculars ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-world-search',
 | 
			
		||||
		action: (ev) => {
 | 
			
		||||
			lookup();
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	lists: {
 | 
			
		||||
		title: i18n.ts.lists,
 | 
			
		||||
		icon: 'ph-list ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-list',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: '/my/lists',
 | 
			
		||||
	},
 | 
			
		||||
	antennas: {
 | 
			
		||||
		title: i18n.ts.antennas,
 | 
			
		||||
		icon: 'ph-flying-saucer ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-antenna',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: '/my/antennas',
 | 
			
		||||
	},
 | 
			
		||||
	favorites: {
 | 
			
		||||
		title: i18n.ts.favorites,
 | 
			
		||||
		icon: 'ph-star ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-star',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: '/my/favorites',
 | 
			
		||||
	},
 | 
			
		||||
	pages: {
 | 
			
		||||
		title: i18n.ts.pages,
 | 
			
		||||
		icon: 'ph-newspaper ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-news',
 | 
			
		||||
		to: '/pages',
 | 
			
		||||
	},
 | 
			
		||||
	play: {
 | 
			
		||||
		title: 'Play',
 | 
			
		||||
		icon: 'ph-play ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-player-play',
 | 
			
		||||
		to: '/play',
 | 
			
		||||
	},
 | 
			
		||||
	gallery: {
 | 
			
		||||
| 
						 | 
				
			
			@ -103,29 +103,29 @@ export const navbarItemDef = reactive({
 | 
			
		|||
	},
 | 
			
		||||
	clips: {
 | 
			
		||||
		title: i18n.ts.clip,
 | 
			
		||||
		icon: 'ph-paperclip ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-paperclip',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: '/my/clips',
 | 
			
		||||
	},
 | 
			
		||||
	channels: {
 | 
			
		||||
		title: i18n.ts.channel,
 | 
			
		||||
		icon: 'ph-television ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-device-tv',
 | 
			
		||||
		to: '/channels',
 | 
			
		||||
	},
 | 
			
		||||
	achievements: {
 | 
			
		||||
		title: i18n.ts.achievements,
 | 
			
		||||
		icon: 'ph-trophy ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-medal',
 | 
			
		||||
		show: computed(() => $i != null && instance.enableAchievements),
 | 
			
		||||
		to: '/my/achievements',
 | 
			
		||||
	},
 | 
			
		||||
	games: {
 | 
			
		||||
		title: 'Games',
 | 
			
		||||
		icon: 'ph-game-controller ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-device-gamepad',
 | 
			
		||||
		to: '/games',
 | 
			
		||||
	},
 | 
			
		||||
	ui: {
 | 
			
		||||
		title: i18n.ts.switchUi,
 | 
			
		||||
		icon: 'ph-devices ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-devices',
 | 
			
		||||
		action: (ev) => {
 | 
			
		||||
			os.popupMenu([{
 | 
			
		||||
				text: i18n.ts.default,
 | 
			
		||||
| 
						 | 
				
			
			@ -153,27 +153,27 @@ export const navbarItemDef = reactive({
 | 
			
		|||
	},
 | 
			
		||||
	about: {
 | 
			
		||||
		title: i18n.ts.about,
 | 
			
		||||
		icon: 'ph-info ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-info-circle',
 | 
			
		||||
		action: (ev) => {
 | 
			
		||||
			openInstanceMenu(ev);
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	reload: {
 | 
			
		||||
		title: i18n.ts.reload,
 | 
			
		||||
		icon: 'ph-arrows-clockwise ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-refresh',
 | 
			
		||||
		action: (ev) => {
 | 
			
		||||
			location.reload();
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	profile: {
 | 
			
		||||
		title: i18n.ts.profile,
 | 
			
		||||
		icon: 'ph-user ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-user',
 | 
			
		||||
		show: computed(() => $i != null),
 | 
			
		||||
		to: `/@${$i?.username}`,
 | 
			
		||||
	},
 | 
			
		||||
	cacheClear: {
 | 
			
		||||
		title: i18n.ts.clearCache,
 | 
			
		||||
		icon: 'ph-trash ph-bold ph-lg',
 | 
			
		||||
		icon: 'ti ti-trash',
 | 
			
		||||
		action: (ev) => {
 | 
			
		||||
			clearCache();
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue