Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
This commit is contained in:
		
						commit
						b9c64053e8
					
				
					 112 changed files with 351 additions and 111 deletions
				
			
		|  | @ -18,6 +18,7 @@ You should also include the user name that made the change. | |||
| - Server: always remove completed tasks of job queue @Johann150 | ||||
| - Client: make emoji stand out more on reaction button @Johann150 | ||||
| - Client: display URL of QR code for TOTP registration @tamaina | ||||
| - Client: render quote renote CWs as MFM @pixeldesu | ||||
| - API: notifications/readは配列でも受け付けるように #7667 @tamaina | ||||
| - API: ユーザー検索で、クエリがusernameの条件を満たす場合はusernameもLIKE検索するように @tamaina | ||||
| - MFM: Allow speed changes in all animated MFMs @Johann150 | ||||
|  |  | |||
|  | @ -197,7 +197,14 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s | |||
| 	const cw = note.summary === '' ? null : note.summary; | ||||
| 
 | ||||
| 	// テキストのパース
 | ||||
| 	const text = typeof note._misskey_content !== 'undefined' ? note._misskey_content : (note.content ? htmlToMfm(note.content, note.tag) : null); | ||||
| 	let text: string | null = null; | ||||
| 	if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source?.content === 'string') { | ||||
| 		text = note.source.content; | ||||
| 	} else if (typeof note._misskey_content === 'string') { | ||||
| 		text = note._misskey_content; | ||||
| 	} else if (typeof note.content === 'string') { | ||||
| 		text = htmlToMfm(note.content, note.tag); | ||||
| 	} | ||||
| 
 | ||||
| 	// vote
 | ||||
| 	if (reply && reply.hasPoll) { | ||||
|  |  | |||
|  | @ -138,6 +138,10 @@ export default async function renderNote(note: Note, dive = true, isTalk = false | |||
| 		summary, | ||||
| 		content, | ||||
| 		_misskey_content: text, | ||||
| 		source: { | ||||
| 			content: text, | ||||
| 			mediaType: "text/x.misskeymarkdown", | ||||
| 		}, | ||||
| 		_misskey_quote: quote, | ||||
| 		quoteUrl: quote, | ||||
| 		published: note.createdAt.toISOString(), | ||||
|  |  | |||
|  | @ -106,7 +106,10 @@ export const isPost = (object: IObject): object is IPost => | |||
| 
 | ||||
| export interface IPost extends IObject { | ||||
| 	type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event'; | ||||
| 	_misskey_content?: string; | ||||
| 	source?: { | ||||
| 		content: string; | ||||
| 		mediaType: string; | ||||
| 	}; | ||||
| 	_misskey_quote?: string; | ||||
| 	quoteUrl?: string; | ||||
| 	_misskey_talk: boolean; | ||||
|  | @ -114,7 +117,10 @@ export interface IPost extends IObject { | |||
| 
 | ||||
| export interface IQuestion extends IObject { | ||||
| 	type: 'Note' | 'Question'; | ||||
| 	_misskey_content?: string; | ||||
| 	source?: { | ||||
| 		content: string; | ||||
| 		mediaType: string; | ||||
| 	}; | ||||
| 	_misskey_quote?: string; | ||||
| 	quoteUrl?: string; | ||||
| 	oneOf?: IQuestionChoice[]; | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:drive', | ||||
| 
 | ||||
| 	description: 'Find the notes to which the given file is attached.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:drive', | ||||
| 
 | ||||
| 	description: 'Check if a given file exists.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'boolean', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:drive', | ||||
| 
 | ||||
| 	description: 'Upload a new drive file.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:drive', | ||||
| 
 | ||||
| 	description: 'Delete an existing drive file.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchFile: { | ||||
| 			message: 'No such file.', | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:drive', | ||||
| 
 | ||||
| 	description: 'Search for a drive file by a hash of the contents.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:drive', | ||||
| 
 | ||||
| 	description: 'Search for a drive file by the given parameters.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:drive', | ||||
| 
 | ||||
| 	description: 'Show the properties of a drive file.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:drive', | ||||
| 
 | ||||
| 	description: 'Update the properties of a drive file.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		invalidFileName: { | ||||
| 			message: 'Invalid file name.', | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ export const meta = { | |||
| 		max: 60, | ||||
| 	}, | ||||
| 
 | ||||
| 	description: 'Request the server to download a new drive file from the specified URL.', | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	kind: 'write:drive', | ||||
|  |  | |||
|  | @ -10,8 +10,12 @@ import { genId } from '@/misc/gen-id.js'; | |||
| import { IsNull } from 'typeorm'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['reset password'], | ||||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Request a users password to be reset.', | ||||
| 
 | ||||
| 	limit: { | ||||
| 		duration: ms('1hour'), | ||||
| 		max: 3, | ||||
|  |  | |||
|  | @ -3,8 +3,12 @@ import { ApiError } from '../error.js'; | |||
| import { resetDb } from '@/db/postgre.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['non-productive'], | ||||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Only available when running with <code>NODE_ENV=testing</code>. Reset the database and flush Redis.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 
 | ||||
| 	}, | ||||
|  |  | |||
|  | @ -5,8 +5,12 @@ import { Users, UserProfiles, PasswordResetRequests } from '@/models/index.js'; | |||
| import { ApiError } from '../error.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['reset password'], | ||||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Complete the password reset that was previously requested.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 
 | ||||
| 	}, | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	description: 'Register to receive push notifications.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ export const meta = { | |||
| 	tags: ['account'], | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	description: 'Unregister from receiving push notifications.', | ||||
| } as const; | ||||
| 
 | ||||
| export const paramDef = { | ||||
|  |  | |||
|  | @ -1,6 +1,10 @@ | |||
| import define from '../define.js'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['non-productive'], | ||||
| 
 | ||||
| 	description: 'Endpoint for testing input validation.', | ||||
| 
 | ||||
| 	requireCredential: false, | ||||
| } as const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,18 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js'; | |||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users', 'clips'], | ||||
| 
 | ||||
| 	description: 'Show all clips this user owns.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			optional: false, nullable: false, | ||||
| 			ref: 'Clip', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| export const paramDef = { | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Show everyone that follows this user.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Show everyone that this user is following.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -4,6 +4,18 @@ import { makePaginationQuery } from '../../../common/make-pagination-query.js'; | |||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users', 'gallery'], | ||||
| 
 | ||||
| 	description: 'Show all gallery posts by the given user.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			optional: false, nullable: false, | ||||
| 			ref: 'GalleryPost', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| export const paramDef = { | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Get a list of other users that the specified user frequently replies to.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Create a new group.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Delete an existing group.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Join a group the authenticated user has been invited to.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchInvitation: { | ||||
| 			message: 'No such invitation.', | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Delete an existing group invitation for the authenticated user without joining the group.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchInvitation: { | ||||
| 			message: 'No such invitation.', | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Invite a user to an existing group.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:user-groups', | ||||
| 
 | ||||
| 	description: 'List the groups that the authenticated user is a member of.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Leave a group. The owner of a group can not leave. They must transfer ownership or delete the group instead.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:user-groups', | ||||
| 
 | ||||
| 	description: 'List the groups that the authenticated user is the owner of.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Removes a specified user from a group. The owner can not be removed.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchGroup: { | ||||
| 			message: 'No such group.', | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:user-groups', | ||||
| 
 | ||||
| 	description: 'Show the properties of a group.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Transfer ownership of a group from the authenticated user to another user.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:user-groups', | ||||
| 
 | ||||
| 	description: 'Update the properties of a group.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	description: 'Create a new list of users.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	description: 'Delete an existing list of users.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchList: { | ||||
| 			message: 'No such list.', | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:account', | ||||
| 
 | ||||
| 	description: 'Show all lists that the authenticated user has created.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	description: 'Remove a user from a list.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchList: { | ||||
| 			message: 'No such list.', | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	description: 'Add a user to an existing list.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchList: { | ||||
| 			message: 'No such list.', | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:account', | ||||
| 
 | ||||
| 	description: 'Show the properties of a list.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	description: 'Update the properties of a list.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ import { generateMutedInstanceQuery } from '../../common/generate-muted-instance | |||
| export const meta = { | ||||
| 	tags: ['users', 'notes'], | ||||
| 
 | ||||
| 	description: 'Show all notes that this user created.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -4,6 +4,18 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js'; | |||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users', 'pages'], | ||||
| 
 | ||||
| 	description: 'Show all pages this user created.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
| 		items: { | ||||
| 			type: 'object', | ||||
| 			optional: false, nullable: false, | ||||
| 			ref: 'Page', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| export const paramDef = { | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Show all reactions this user made.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:account', | ||||
| 
 | ||||
| 	description: 'Show users that the authenticated user might be interested to follow.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	description: 'Show the different kinds of relations between the authenticated user and the specified user(s).', | ||||
| 
 | ||||
| 	res: { | ||||
| 		optional: false, nullable: false, | ||||
| 		oneOf: [ | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	description: 'File a report.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Search for a user by username and/or host.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Search for users.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Show the properties of a user.', | ||||
| 
 | ||||
| 	res: { | ||||
| 		optional: false, nullable: false, | ||||
| 		oneOf: [ | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	description: 'Show statistics about a user.', | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
|  | @ -15,6 +17,94 @@ export const meta = { | |||
| 			id: '9e638e45-3b25-4ef7-8f95-07e8498f1819', | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
| 		properties: { | ||||
| 			notesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			repliesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			renotesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			repliedCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			renotedCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			pollVotesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			pollVotedCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			localFollowingCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			remoteFollowingCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			localFollowersCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			remoteFollowersCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			followingCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			followersCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			sentReactionsCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			receivedReactionsCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			noteFavoritesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			pageLikesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			pageLikedCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			driveFilesCount: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			driveUsage: { | ||||
| 				type: 'integer', | ||||
| 				optional: false, nullable: false, | ||||
| 				description: 'Drive usage in bytes', | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| export const paramDef = { | ||||
|  |  | |||
|  | @ -15,6 +15,12 @@ module.exports = { | |||
| 		'plugin:vue/vue3-recommended', | ||||
| 	], | ||||
| 	rules: { | ||||
| 		'@typescript-eslint/no-empty-interface': [ | ||||
| 			'error', | ||||
| 			{ | ||||
| 				'allowSingleExtends': true, | ||||
| 			}, | ||||
| 		], | ||||
| 		// window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため
 | ||||
| 		// data の禁止理由: 抽象的すぎるため
 | ||||
| 		// e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため
 | ||||
|  |  | |||
|  | @ -27,8 +27,7 @@ type CaptchaContainer = { | |||
| }; | ||||
| 
 | ||||
| declare global { | ||||
| 	interface Window extends CaptchaContainer { | ||||
| 	} | ||||
| 	interface Window extends CaptchaContainer { } | ||||
| } | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ function onMouseover() { | |||
| } | ||||
| 
 | ||||
| function onMouseout() { | ||||
| 	hover.value = false | ||||
| 	hover.value = false; | ||||
| } | ||||
| 
 | ||||
| function onDragover(ev: DragEvent) { | ||||
|  | @ -204,7 +204,7 @@ function deleteFolder() { | |||
| 			defaultStore.set('uploadFolder', null); | ||||
| 		} | ||||
| 	}).catch(err => { | ||||
| 		switch(err.id) { | ||||
| 		switch (err.id) { | ||||
| 			case 'b0fc8a17-963c-405d-bfbc-859a487295e1': | ||||
| 				os.alert({ | ||||
| 					type: 'error', | ||||
|  |  | |||
|  | @ -143,7 +143,7 @@ const fetching = ref(true); | |||
| 
 | ||||
| const ilFilesObserver = new IntersectionObserver( | ||||
| 	(entries) => entries.some((entry) => entry.isIntersecting) && !fetching.value && moreFiles.value && fetchMoreFiles() | ||||
| ) | ||||
| ); | ||||
| 
 | ||||
| watch(folder, () => emit('cd', folder.value)); | ||||
| 
 | ||||
|  | @ -332,7 +332,7 @@ function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) { | |||
| 		// 削除時に親フォルダに移動 | ||||
| 		move(folderToDelete.parentId); | ||||
| 	}).catch(err => { | ||||
| 		switch(err.id) { | ||||
| 		switch (err.id) { | ||||
| 			case 'b0fc8a17-963c-405d-bfbc-859a487295e1': | ||||
| 				os.alert({ | ||||
| 					type: 'error', | ||||
|  | @ -607,7 +607,7 @@ function onContextmenu(ev: MouseEvent) { | |||
| onMounted(() => { | ||||
| 	if (defaultStore.state.enableInfiniteScroll && loadMoreFiles.value) { | ||||
| 		nextTick(() => { | ||||
| 			ilFilesObserver.observe(loadMoreFiles.value?.$el) | ||||
| 			ilFilesObserver.observe(loadMoreFiles.value?.$el); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -628,7 +628,7 @@ onMounted(() => { | |||
| onActivated(() => { | ||||
| 	if (defaultStore.state.enableInfiniteScroll) { | ||||
| 		nextTick(() => { | ||||
| 			ilFilesObserver.observe(loadMoreFiles.value?.$el) | ||||
| 			ilFilesObserver.observe(loadMoreFiles.value?.$el); | ||||
| 		}); | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import { onBeforeUnmount, onMounted, ref } from 'vue'; | ||||
| import { onBeforeUnmount, onMounted } from 'vue'; | ||||
| import * as Misskey from 'misskey-js'; | ||||
| import * as os from '@/os'; | ||||
| import { stream } from '@/stream'; | ||||
|  | @ -43,32 +43,30 @@ const props = withDefaults(defineProps<{ | |||
| 	large: false, | ||||
| }); | ||||
| 
 | ||||
| const isFollowing = ref(props.user.isFollowing); | ||||
| const hasPendingFollowRequestFromYou = ref(props.user.hasPendingFollowRequestFromYou); | ||||
| const wait = ref(false); | ||||
| let isFollowing = $ref(props.user.isFollowing); | ||||
| let hasPendingFollowRequestFromYou = $ref(props.user.hasPendingFollowRequestFromYou); | ||||
| let wait = $ref(false); | ||||
| const connection = stream.useChannel('main'); | ||||
| 
 | ||||
| if (props.user.isFollowing == null) { | ||||
| 	os.api('users/show', { | ||||
| 		userId: props.user.id | ||||
| 	}).then(u => { | ||||
| 		isFollowing.value = u.isFollowing; | ||||
| 		hasPendingFollowRequestFromYou.value = u.hasPendingFollowRequestFromYou; | ||||
| 	}); | ||||
| 	}) | ||||
| 	.then(onFollowChange); | ||||
| } | ||||
| 
 | ||||
| function onFollowChange(user: Misskey.entities.UserDetailed) { | ||||
| 	if (user.id === props.user.id) { | ||||
| 		isFollowing.value = user.isFollowing; | ||||
| 		hasPendingFollowRequestFromYou.value = user.hasPendingFollowRequestFromYou; | ||||
| 		isFollowing = user.isFollowing; | ||||
| 		hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| async function onClick() { | ||||
| 	wait.value = true; | ||||
| 	wait = true; | ||||
| 
 | ||||
| 	try { | ||||
| 		if (isFollowing.value) { | ||||
| 		if (isFollowing) { | ||||
| 			const { canceled } = await os.confirm({ | ||||
| 				type: 'warning', | ||||
| 				text: i18n.t('unfollowConfirm', { name: props.user.name || props.user.username }), | ||||
|  | @ -80,26 +78,22 @@ async function onClick() { | |||
| 				userId: props.user.id | ||||
| 			}); | ||||
| 		} else { | ||||
| 			if (hasPendingFollowRequestFromYou.value) { | ||||
| 			if (hasPendingFollowRequestFromYou) { | ||||
| 				await os.api('following/requests/cancel', { | ||||
| 					userId: props.user.id | ||||
| 				}); | ||||
| 			} else if (props.user.isLocked) { | ||||
| 				await os.api('following/create', { | ||||
| 					userId: props.user.id | ||||
| 				}); | ||||
| 				hasPendingFollowRequestFromYou.value = true; | ||||
| 				hasPendingFollowRequestFromYou = false; | ||||
| 			} else { | ||||
| 				await os.api('following/create', { | ||||
| 					userId: props.user.id | ||||
| 				}); | ||||
| 				hasPendingFollowRequestFromYou.value = true; | ||||
| 				hasPendingFollowRequestFromYou = true; | ||||
| 			} | ||||
| 		} | ||||
| 	} catch (err) { | ||||
| 		console.error(err); | ||||
| 	} finally { | ||||
| 		wait.value = false; | ||||
| 		wait = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ const props = withDefaults(defineProps<{ | |||
| 	defaultOpen: boolean; | ||||
| }>(), { | ||||
|   defaultOpen: false, | ||||
| }) | ||||
| }); | ||||
| 
 | ||||
| let opened = $ref(props.defaultOpen); | ||||
| let openedAtLeastOnce = $ref(props.defaultOpen); | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			value: this.modelValue, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		value() { | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ export default defineComponent({ | |||
| 					.then(response => response.json()) | ||||
| 					.then(f => { | ||||
| 						ok(f); | ||||
| 					}) | ||||
| 					}); | ||||
| 				}); | ||||
| 			}); | ||||
| 			os.promiseDialog(promise); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import MkDriveFileThumbnail from './drive-file-thumbnail.vue' | ||||
| import MkDriveFileThumbnail from './drive-file-thumbnail.vue'; | ||||
| import * as os from '@/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -114,19 +114,19 @@ export default defineComponent({ | |||
| 			this.menu = os.popupMenu([{ | ||||
| 				text: this.$ts.renameFile, | ||||
| 				icon: 'fas fa-i-cursor', | ||||
| 				action: () => { this.rename(file) } | ||||
| 				action: () => { this.rename(file); } | ||||
| 			}, { | ||||
| 				text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, | ||||
| 				icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye', | ||||
| 				action: () => { this.toggleSensitive(file) } | ||||
| 				action: () => { this.toggleSensitive(file); } | ||||
| 			}, { | ||||
| 				text: this.$ts.describeFile, | ||||
| 				icon: 'fas fa-i-cursor', | ||||
| 				action: () => { this.describe(file) } | ||||
| 				action: () => { this.describe(file); } | ||||
| 			}, { | ||||
| 				text: this.$ts.attachCancel, | ||||
| 				icon: 'fas fa-times-circle', | ||||
| 				action: () => { this.detachMedia(file.id) } | ||||
| 				action: () => { this.detachMedia(file.id); } | ||||
| 			}], ev.currentTarget ?? ev.target).then(() => this.menu = null); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -442,7 +442,7 @@ function onCompositionEnd(ev: CompositionEvent) { | |||
| } | ||||
| 
 | ||||
| async function onPaste(ev: ClipboardEvent) { | ||||
| 	for (const { item, i } of Array.from(ev.clipboardData.items).map((item, i) => ({item, i}))) { | ||||
| 	for (const { item, i } of Array.from(ev.clipboardData.items).map((item, i) => ({ item, i }))) { | ||||
| 		if (item.kind === 'file') { | ||||
| 			const file = item.getAsFile(); | ||||
| 			const lio = file.name.lastIndexOf('.'); | ||||
|  |  | |||
|  | @ -222,7 +222,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 		return { | ||||
| 			chartEl, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ export default defineComponent({ | |||
| 			flag: true, | ||||
| 			radio: 'misskey', | ||||
| 			mfm: `Hello world! This is an @example mention. BTW you are @${this.$i ? this.$i.username : 'guest'}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.` | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
|  |  | |||
|  | @ -159,7 +159,7 @@ function queryKey() { | |||
| 
 | ||||
| function onSubmit() { | ||||
| 	signing = true; | ||||
| 	console.log('submit') | ||||
| 	console.log('submit'); | ||||
| 	if (!totpLogin && user && user.twoFactorEnabled) { | ||||
| 		if (window.PublicKeyCredential && user.securityKeys) { | ||||
| 			os.api('signin', { | ||||
|  | @ -222,7 +222,7 @@ function loginFailed(err) { | |||
| 			break; | ||||
| 		} | ||||
| 		default: { | ||||
| 			console.log(err) | ||||
| 			console.log(err); | ||||
| 			os.alert({ | ||||
| 				type: 'error', | ||||
| 				title: i18n.ts.loginFailed, | ||||
|  |  | |||
|  | @ -111,7 +111,7 @@ export default defineComponent({ | |||
| 			ToSAgreement: false, | ||||
| 			hCaptchaResponse: null, | ||||
| 			reCaptchaResponse: null, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -96,11 +96,11 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY) { | ||||
| 				const origin = {x: circleCenterX, y: circleCenterY}; | ||||
| 				const dist1 = distance({x: 0, y: 0}, origin); | ||||
| 				const dist2 = distance({x: boxW, y: 0}, origin); | ||||
| 				const dist3 = distance({x: 0, y: boxH}, origin); | ||||
| 				const dist4 = distance({x: boxW, y: boxH }, origin); | ||||
| 				const origin = { x: circleCenterX, y: circleCenterY }; | ||||
| 				const dist1 = distance({ x: 0, y: 0 }, origin); | ||||
| 				const dist2 = distance({ x: boxW, y: 0 }, origin); | ||||
| 				const dist3 = distance({ x: 0, y: boxH }, origin); | ||||
| 				const dist4 = distance({ x: boxW, y: boxH }, origin); | ||||
| 				return Math.max(dist1, dist2, dist3, dist4) * 2; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -234,7 +234,7 @@ onMounted(() => { | |||
| 		} | ||||
| 		fixed.value = (type.value === 'drawer') || (getFixedContainer(props.src) != null); | ||||
| 
 | ||||
| 		await nextTick() | ||||
| 		await nextTick(); | ||||
| 		 | ||||
| 		align(); | ||||
| 	}, { immediate: true, }); | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ const setPosition = () => { | |||
| 		} | ||||
| 
 | ||||
| 		return [left, top]; | ||||
| 	} | ||||
| 	}; | ||||
| 
 | ||||
| 	const calcPosWhenBottom = () => { | ||||
| 		let left: number; | ||||
|  | @ -84,7 +84,7 @@ const setPosition = () => { | |||
| 		} | ||||
| 
 | ||||
| 		return [left, top]; | ||||
| 	} | ||||
| 	}; | ||||
| 
 | ||||
| 	const calcPosWhenLeft = () => { | ||||
| 		let left: number; | ||||
|  | @ -105,7 +105,7 @@ const setPosition = () => { | |||
| 		} | ||||
| 
 | ||||
| 		return [left, top]; | ||||
| 	} | ||||
| 	}; | ||||
| 
 | ||||
| 	const calcPosWhenRight = () => { | ||||
| 		let left: number; | ||||
|  | @ -126,7 +126,7 @@ const setPosition = () => { | |||
| 		} | ||||
| 
 | ||||
| 		return [left, top]; | ||||
| 	} | ||||
| 	}; | ||||
| 
 | ||||
| 	const calc = (): { | ||||
| 		left: number; | ||||
|  | @ -172,7 +172,7 @@ const setPosition = () => { | |||
| 		} | ||||
| 
 | ||||
| 		return null as never; | ||||
| 	} | ||||
| 	}; | ||||
| 
 | ||||
| 	const { left, top, transformOrigin } = calc(); | ||||
| 	el.value.style.transformOrigin = transformOrigin; | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${requestLang}`).the | |||
| 		sitename = info.sitename; | ||||
| 		fetching = false; | ||||
| 		player = info.player; | ||||
| 	}) | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| function adjustTweetHeight(message: any) { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ export default { | |||
| 			} else { | ||||
| 				return el.parentElement ? getBgColor(el.parentElement) : 'transparent'; | ||||
| 			} | ||||
| 		} | ||||
| 		}; | ||||
| 	 | ||||
| 		const parentBg = getBgColor(src.parentElement); | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,12 +25,12 @@ function calc(src: Element) { | |||
| 		return; | ||||
| 	} | ||||
| 	if (info.intersection) { | ||||
| 		info.intersection.disconnect() | ||||
| 		info.intersection.disconnect(); | ||||
| 		delete info.intersection; | ||||
| 	}; | ||||
| 	} | ||||
| 
 | ||||
| 	info.fn(width, height); | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
| 	mounted(src, binding, vn) { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ export default { | |||
| 			} else { | ||||
| 				return el.parentElement ? getBgColor(el.parentElement) : 'transparent'; | ||||
| 			} | ||||
| 		} | ||||
| 		}; | ||||
| 	 | ||||
| 		const parentBg = getBgColor(src.parentElement); | ||||
| 
 | ||||
|  |  | |||
|  | @ -60,9 +60,9 @@ function calc(el: Element) { | |||
| 		return; | ||||
| 	} | ||||
| 	if (info.intersection) { | ||||
| 		info.intersection.disconnect() | ||||
| 		info.intersection.disconnect(); | ||||
| 		delete info.intersection; | ||||
| 	}; | ||||
| 	} | ||||
| 
 | ||||
| 	mountings.set(el, Object.assign(info, { previousWidth: width })); | ||||
| 
 | ||||
|  |  | |||
|  | @ -285,7 +285,7 @@ export function inputDate(props: { | |||
| 	}); | ||||
| } | ||||
| 
 | ||||
| export function select<C extends any = any>(props: { | ||||
| export function select<C = any>(props: { | ||||
| 	title?: string | null; | ||||
| 	text?: string | null; | ||||
| 	default?: string | null; | ||||
|  |  | |||
|  | @ -159,7 +159,7 @@ const remoteMenu = (emoji, ev: MouseEvent) => { | |||
| 	}, { | ||||
| 		text: i18n.ts.import, | ||||
| 		icon: 'fas fa-plus', | ||||
| 		action: () => { im(emoji) } | ||||
| 		action: () => { im(emoji); } | ||||
| 	}], ev.currentTarget ?? ev.target); | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -132,7 +132,7 @@ export default defineComponent({ | |||
| 			overviewHeight: '1fr', | ||||
| 			queueHeight: '1fr', | ||||
| 			paused: false, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ import * as symbols from '@/symbols'; | |||
| import * as config from '@/config'; | ||||
| import { i18n } from '@/i18n'; | ||||
| 
 | ||||
| const connection = markRaw(stream.useChannel('queueStats')) | ||||
| const connection = markRaw(stream.useChannel('queueStats')); | ||||
| 
 | ||||
| function clear() { | ||||
| 	os.confirm({ | ||||
|  | @ -41,7 +41,7 @@ onMounted(() => { | |||
| 			length: 200 | ||||
| 		}); | ||||
| 	}); | ||||
| }) | ||||
| }); | ||||
| 
 | ||||
| onBeforeUnmount(() => { | ||||
| 	connection.dispose(); | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ export default defineComponent({ | |||
| 	computed: { | ||||
| 		name(): string { | ||||
| 			const el = document.createElement('div'); | ||||
| 			el.textContent = this.app.name | ||||
| 			el.textContent = this.app.name; | ||||
| 			return el.innerHTML; | ||||
| 		}, | ||||
| 		app(): any { | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ export default defineComponent({ | |||
| 			tags: emojiTags, | ||||
| 			selectedTags: new Set(), | ||||
| 			searchEmojis: null, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	watch: { | ||||
|  |  | |||
|  | @ -127,7 +127,7 @@ function getStatus(instance) { | |||
| 	if (instance.isSuspended) return 'suspended'; | ||||
| 	if (instance.isNotResponding) return 'error'; | ||||
| 	return 'alive'; | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| defineExpose({ | ||||
| 	[symbols.PAGE_INFO]: { | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ export default defineComponent({ | |||
| 			description: null, | ||||
| 			title: null, | ||||
| 			isSensitive: false, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	watch: { | ||||
|  |  | |||
|  | @ -123,11 +123,11 @@ export default defineComponent({ | |||
| 			os.popupMenu([{ | ||||
| 				text: this.$ts.messagingWithUser, | ||||
| 				icon: 'fas fa-user', | ||||
| 				action: () => { this.startUser() } | ||||
| 				action: () => { this.startUser(); } | ||||
| 			}, { | ||||
| 				text: this.$ts.messagingWithGroup, | ||||
| 				icon: 'fas fa-users', | ||||
| 				action: () => { this.startGroup() } | ||||
| 				action: () => { this.startGroup(); } | ||||
| 			}], ev.currentTarget ?? ev.target); | ||||
| 		}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ export default defineComponent({ | |||
| 					text: this.text, | ||||
| 					file: this.file | ||||
| 				} | ||||
| 			} | ||||
| 			}; | ||||
| 
 | ||||
| 			localStorage.setItem('message_drafts', JSON.stringify(drafts)); | ||||
| 		}, | ||||
|  |  | |||
|  | @ -341,7 +341,7 @@ export default defineComponent({ | |||
| 			preview_rainbow: `$[rainbow 🍮] $[rainbow.speed=5s 🍮]`, | ||||
| 			preview_sparkle: `$[sparkle 🍮]`, | ||||
| 			preview_rotate: `$[rotate 🍮]`, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ defineExpose({ | |||
| 		icon: 'fas fa-satellite', | ||||
| 		bg: 'var(--bg)' | ||||
| 	} | ||||
| }) | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
|  |  | |||
|  | @ -114,7 +114,7 @@ export default defineComponent({ | |||
| 			readonly: this.readonly, | ||||
| 			getScriptBlockList: this.getScriptBlockList, | ||||
| 			getPageBlockList: this.getPageBlockList | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ async function run() { | |||
| 			text: error.message | ||||
| 		}); | ||||
| 	} | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| function highlighter(code) { | ||||
| 	return highlight(code, languages.js, 'javascript'); | ||||
|  |  | |||
|  | @ -142,7 +142,7 @@ function registerKey() { | |||
| 		registration.value = null; | ||||
| 		key.lastUsed = new Date(); | ||||
| 		os.success(); | ||||
| 	}) | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function unregisterKey(key) { | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ const init = async () => { | |||
| 		accounts.value = response; | ||||
| 		console.log(accounts.value); | ||||
| 	}); | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| function menu(account, ev) { | ||||
| 	os.popupMenu([{ | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ const pagination = { | |||
| 	params: { | ||||
| 		sort: '+lastUsedAt' | ||||
| 	} | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| function revoke(token) { | ||||
| 	os.api('i/revoke-token', { tokenId: token.id }).then(() => { | ||||
|  |  | |||
|  | @ -120,7 +120,7 @@ const darkThemeId = computed({ | |||
| 		return darkTheme.value.id; | ||||
| 	}, | ||||
| 	set(id) { | ||||
| 		ColdDeviceStorage.set('darkTheme', themes.value.find(x => x.id === id)) | ||||
| 		ColdDeviceStorage.set('darkTheme', themes.value.find(x => x.id === id)); | ||||
| 	} | ||||
| }); | ||||
| const lightTheme = ColdDeviceStorage.ref('lightTheme'); | ||||
|  | @ -129,7 +129,7 @@ const lightThemeId = computed({ | |||
| 		return lightTheme.value.id; | ||||
| 	}, | ||||
| 	set(id) { | ||||
| 		ColdDeviceStorage.set('lightTheme', themes.value.find(x => x.id === id)) | ||||
| 		ColdDeviceStorage.set('lightTheme', themes.value.find(x => x.id === id)); | ||||
| 	} | ||||
| }); | ||||
| const darkMode = computed(defaultStore.makeGetterSetter('darkMode')); | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ async function save() { | |||
| 
 | ||||
| 		// check each line if it is a RegExp or not | ||||
| 		for (let i = 0; i < lines.length; i++) { | ||||
| 			const line = lines[i] | ||||
| 			const line = lines[i]; | ||||
| 			const regexp = line.match(/^\/(.+)\/(.*)$/); | ||||
| 			if (regexp) { | ||||
| 				// check that the RegExp is valid | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ export default defineComponent({ | |||
| 			localOnly: null as boolean | null, | ||||
| 			files: [] as Misskey.entities.DriveFile[], | ||||
| 			visibleUsers: [] as Misskey.entities.User[], | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	async created() { | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ | |||
| import { watch } from 'vue'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import tinycolor from 'tinycolor2'; | ||||
| import { v4 as uuid} from 'uuid'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import JSON5 from 'json5'; | ||||
| 
 | ||||
| import FormButton from '@/components/ui/button.vue'; | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ | |||
| <script lang="ts"> | ||||
| export default { | ||||
| 	name: 'MkTimelinePage', | ||||
| } | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ export default defineComponent({ | |||
| 			password: '', | ||||
| 			submitting: false, | ||||
| 			host, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			notes: [], | ||||
| 			isScrolling: false, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ const defaultLocaleStringFormats: {[index: string]: string} = { | |||
| function formatLocaleString(date: Date, format: string): string { | ||||
| 	return format.replace(/\{\{(\w+)(:(\w+))?\}\}/g, (match: string, kind: string, unused?, option?: string) => { | ||||
| 		if (['weekday', 'era', 'year', 'month', 'day', 'hour', 'minute', 'second', 'timeZoneName'].includes(kind)) { | ||||
| 			return date.toLocaleString(window.navigator.language, {[kind]: option ? option : defaultLocaleStringFormats[kind]}); | ||||
| 			return date.toLocaleString(window.navigator.language, { [kind]: option ? option : defaultLocaleStringFormats[kind] }); | ||||
| 		} else { | ||||
| 			return match; | ||||
| 		} | ||||
|  | @ -24,8 +24,8 @@ export function formatDateTimeString(date: Date, format: string): string { | |||
| 	return format | ||||
| 		.replace(/yyyy/g, date.getFullYear().toString()) | ||||
| 		.replace(/yy/g, date.getFullYear().toString().slice(-2)) | ||||
| 		.replace(/MMMM/g, date.toLocaleString(window.navigator.language, { month: 'long'})) | ||||
| 		.replace(/MMM/g, date.toLocaleString(window.navigator.language, { month: 'short'})) | ||||
| 		.replace(/MMMM/g, date.toLocaleString(window.navigator.language, { month: 'long' })) | ||||
| 		.replace(/MMM/g, date.toLocaleString(window.navigator.language, { month: 'short' })) | ||||
| 		.replace(/MM/g, (`0${date.getMonth() + 1}`).slice(-2)) | ||||
| 		.replace(/M/g, (date.getMonth() + 1).toString()) | ||||
| 		.replace(/dd/g, (`0${date.getDate()}`).slice(-2)) | ||||
|  |  | |||
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