mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-23 07:34:09 +02:00
Merge branch 'develop' into room
This commit is contained in:
@@ -53,28 +53,28 @@
|
||||
"utf-8-validate": "6.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.1027.0",
|
||||
"@aws-sdk/lib-storage": "3.1027.0",
|
||||
"@aws-sdk/client-s3": "3.1030.0",
|
||||
"@aws-sdk/lib-storage": "3.1030.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.4",
|
||||
"@fastify/cors": "11.2.0",
|
||||
"@fastify/express": "4.0.5",
|
||||
"@fastify/http-proxy": "11.4.4",
|
||||
"@fastify/multipart": "9.4.0",
|
||||
"@fastify/static": "9.1.0",
|
||||
"@fastify/multipart": "10.0.0",
|
||||
"@fastify/static": "9.1.3",
|
||||
"@kitajs/html": "4.2.13",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
"@napi-rs/canvas": "0.1.97",
|
||||
"@nestjs/common": "11.1.18",
|
||||
"@nestjs/core": "11.1.18",
|
||||
"@nestjs/testing": "11.1.18",
|
||||
"@oxc-project/runtime": "0.124.0",
|
||||
"@nestjs/common": "11.1.19",
|
||||
"@nestjs/core": "11.1.19",
|
||||
"@nestjs/testing": "11.1.19",
|
||||
"@oxc-project/runtime": "0.125.0",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "10.47.0",
|
||||
"@sentry/profiling-node": "10.47.0",
|
||||
"@sentry/node": "10.48.0",
|
||||
"@sentry/profiling-node": "10.48.0",
|
||||
"@simplewebauthn/server": "13.3.0",
|
||||
"@sinonjs/fake-timers": "15.3.0",
|
||||
"@sinonjs/fake-timers": "15.3.2",
|
||||
"@smithy/node-http-handler": "4.5.2",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"accepts": "1.3.8",
|
||||
@@ -84,7 +84,7 @@
|
||||
"bcryptjs": "3.0.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "2.2.2",
|
||||
"bullmq": "5.73.2",
|
||||
"bullmq": "5.73.5",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"chalk": "5.6.2",
|
||||
"chalk-template": "1.1.2",
|
||||
@@ -96,7 +96,7 @@
|
||||
"fastify": "5.8.5",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "5.2.0",
|
||||
"file-type": "21.3.4",
|
||||
"file-type": "22.0.1",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.5",
|
||||
"got": "14.6.6",
|
||||
@@ -138,7 +138,7 @@
|
||||
"rename": "1.0.4",
|
||||
"rss-parser": "3.13.0",
|
||||
"rxjs": "7.8.2",
|
||||
"sanitize-html": "2.17.2",
|
||||
"sanitize-html": "2.17.3",
|
||||
"secure-json-parse": "4.1.0",
|
||||
"semver": "7.7.4",
|
||||
"sharp": "0.33.5",
|
||||
@@ -158,9 +158,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kitajs/ts-html-plugin": "4.1.4",
|
||||
"@nestjs/platform-express": "11.1.18",
|
||||
"@nestjs/platform-express": "11.1.19",
|
||||
"@rollup/plugin-esm-shim": "0.1.8",
|
||||
"@sentry/vue": "10.47.0",
|
||||
"@sentry/vue": "10.48.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@types/accepts": "1.3.7",
|
||||
"@types/archiver": "7.0.0",
|
||||
@@ -174,7 +174,7 @@
|
||||
"@types/mime-types": "3.0.1",
|
||||
"@types/ms": "2.1.0",
|
||||
"@types/node": "24.12.2",
|
||||
"@types/nodemailer": "7.0.11",
|
||||
"@types/nodemailer": "8.0.0",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
"@types/oauth2orize-pkce": "0.1.2",
|
||||
"@types/pg": "8.20.0",
|
||||
@@ -192,8 +192,8 @@
|
||||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@vitest/coverage-v8": "4.1.4",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cbor": "10.0.12",
|
||||
@@ -208,6 +208,6 @@
|
||||
"supertest": "7.2.2",
|
||||
"vite": "8.0.8",
|
||||
"vitest": "4.1.4",
|
||||
"vitest-mock-extended": "3.1.1"
|
||||
"vitest-mock-extended": "4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ export default defineConfig((args) => {
|
||||
're2',
|
||||
'ipaddr.js',
|
||||
'oauth2orize',
|
||||
'file-type',
|
||||
];
|
||||
|
||||
if (isE2E) {
|
||||
|
||||
@@ -533,7 +533,8 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
||||
roleId: In(administratorRoles.map(r => r.id)),
|
||||
}) : [];
|
||||
// TODO: isRootなアカウントも含める
|
||||
return assigns.map(a => a.userId);
|
||||
// Setを経由して重複を除去(ユーザIDは重複する可能性があるので)
|
||||
return [...new Set(assigns.map(a => a.userId))].sort((x, y) => x.localeCompare(y));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
||||
@@ -164,4 +164,3 @@ export class SignupService {
|
||||
return { account, secret };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async add(actor: MiRemoteUser, activity: IAdd, resolver?: Resolver): Promise<string | void> {
|
||||
if (actor.uri !== activity.actor) {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async delete(actor: MiRemoteUser, activity: IDelete): Promise<string> {
|
||||
if (actor.uri !== activity.actor) {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async remove(actor: MiRemoteUser, activity: IRemove, resolver?: Resolver): Promise<string | void> {
|
||||
if (actor.uri !== activity.actor) {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -643,7 +643,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async undo(actor: MiRemoteUser, activity: IUndo, resolver?: Resolver): Promise<string> {
|
||||
if (actor.uri !== activity.actor) {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -777,7 +777,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async update(actor: MiRemoteUser, activity: IUpdate, resolver?: Resolver): Promise<string> {
|
||||
if (actor.uri !== activity.actor) {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
return 'skip: invalid actor';
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ export class MetaEntityService {
|
||||
sentryForFrontend: this.config.sentryForFrontend ?? null,
|
||||
mediaProxy: this.config.mediaProxy,
|
||||
enableUrlPreview: instance.urlPreviewEnabled,
|
||||
noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local',
|
||||
noteSearchableScope: (this.config.fulltextSearch?.provider === 'meilisearch' && this.config.meilisearch?.scope === 'local') ? 'local' : 'global',
|
||||
maxFileSize: this.config.maxFileSize,
|
||||
federation: this.meta.federation,
|
||||
};
|
||||
|
||||
@@ -115,9 +115,9 @@ export class InboxProcessorService implements OnApplicationShutdown {
|
||||
// 対象が4xxならスキップ
|
||||
if (err instanceof StatusError) {
|
||||
if (!err.isRetryable) {
|
||||
throw new Bull.UnrecoverableError(`skip: Ignored deleted actors on both ends ${activity.actor} - ${err.statusCode}`);
|
||||
throw new Bull.UnrecoverableError(`skip: Ignored deleted actors on both ends ${getApId(activity.actor)} - ${err.statusCode}`);
|
||||
}
|
||||
throw new Error(`Error in actor ${activity.actor} - ${err.statusCode}`);
|
||||
throw new Error(`Error in actor ${getApId(activity.actor)} - ${err.statusCode}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export class InboxProcessorService implements OnApplicationShutdown {
|
||||
const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);
|
||||
|
||||
// また、signatureのsignerは、activity.actorと一致する必要がある
|
||||
if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {
|
||||
if (!httpSignatureValidated || authUser.user.uri !== getApId(activity.actor)) {
|
||||
// 一致しなくても、でもLD-Signatureがありそうならそっちも見る
|
||||
const ldSignature = activity.signature;
|
||||
if (ldSignature) {
|
||||
@@ -187,8 +187,8 @@ export class InboxProcessorService implements OnApplicationShutdown {
|
||||
//#endregion
|
||||
|
||||
// もう一度actorチェック
|
||||
if (authUser.user.uri !== activity.actor) {
|
||||
throw new Bull.UnrecoverableError(`skip: LD-Signature user(${authUser.user.uri}) !== activity.actor(${activity.actor})`);
|
||||
if (authUser.user.uri !== getApId(activity.actor)) {
|
||||
throw new Bull.UnrecoverableError(`skip: LD-Signature user(${authUser.user.uri}) !== activity.actor(${getApId(activity.actor)})`);
|
||||
}
|
||||
|
||||
const ldHost = this.utilityService.extractDbHost(authUser.user.uri);
|
||||
@@ -243,17 +243,17 @@ export class InboxProcessorService implements OnApplicationShutdown {
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof IdentifiableError) {
|
||||
if (e.id === '689ee33f-f97c-479a-ac49-1b9f8140af99') {
|
||||
return 'blocked notes with prohibited words';
|
||||
}
|
||||
if (e.id === '85ab9bd7-3a41-4530-959d-f07073900109') {
|
||||
return 'actor has been suspended';
|
||||
}
|
||||
if (e.id === 'd450b8a9-48e4-4dab-ae36-f4db763fda7c') { // invalid Note
|
||||
return e.message;
|
||||
}
|
||||
if (e.id === '9f466dab-c856-48cd-9e65-ff90ff750580') {
|
||||
return 'note contains too many mentions';
|
||||
switch (e.id) {
|
||||
case '689ee33f-f97c-479a-ac49-1b9f8140af99':
|
||||
return 'blocked notes with prohibited words';
|
||||
case '85ab9bd7-3a41-4530-959d-f07073900109':
|
||||
return 'actor has been suspended';
|
||||
case 'd450b8a9-48e4-4dab-ae36-f4db763fda7c': // invalid Note
|
||||
return e.message;
|
||||
case '9f466dab-c856-48cd-9e65-ff90ff750580':
|
||||
return 'note contains too many mentions';
|
||||
case '09d79f9e-64f1-4316-9cfa-e75c4d091574': // Instance is blocked
|
||||
return 'skip: blocked instance';
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
|
||||
@@ -696,6 +696,19 @@ describe('RoleService', () => {
|
||||
expect(adminIds).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should not include duplicate user IDs if a user has multiple administrator roles', async () => {
|
||||
const adminUser = await createUser();
|
||||
const adminRole1 = await createRole({ name: 'admin1', isAdministrator: true });
|
||||
const adminRole2 = await createRole({ name: 'admin2', isAdministrator: true });
|
||||
|
||||
await roleService.assign(adminUser.id, adminRole1.id);
|
||||
await roleService.assign(adminUser.id, adminRole2.id);
|
||||
|
||||
const adminIds = await roleService.getAdministratorIds();
|
||||
|
||||
expect(adminIds).toEqual([adminUser.id]);
|
||||
});
|
||||
|
||||
// TODO: rootユーザーは現在実装に含まれていないため、テストもそれに倣う
|
||||
test('should not include the root user', async () => {
|
||||
const rootUser = await createUser();
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"devDependencies": {
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"rollup": "4.60.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"@rollup/plugin-json": "6.1.0",
|
||||
"@rollup/pluginutils": "5.3.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.5",
|
||||
"@vitejs/plugin-vue": "6.0.6",
|
||||
"buraha": "0.0.1",
|
||||
"estree-walker": "3.0.3",
|
||||
"frontend-shared": "workspace:*",
|
||||
@@ -40,21 +40,21 @@
|
||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@vitest/coverage-v8": "4.1.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@vitest/coverage-v8": "4.1.4",
|
||||
"@vue/runtime-core": "3.5.32",
|
||||
"acorn": "8.16.0",
|
||||
"cross-env": "10.1.0",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"happy-dom": "20.8.9",
|
||||
"happy-dom": "20.9.0",
|
||||
"intersection-observer": "0.12.2",
|
||||
"micromatch": "4.0.8",
|
||||
"msw": "2.13.2",
|
||||
"prettier": "3.8.1",
|
||||
"msw": "2.13.3",
|
||||
"prettier": "3.8.3",
|
||||
"sass-embedded": "1.99.0",
|
||||
"start-server-and-test": "2.1.5",
|
||||
"start-server-and-test": "3.0.2",
|
||||
"tsx": "4.21.0",
|
||||
"vite": "8.0.8",
|
||||
"vite-plugin-turbosnap": "1.0.3",
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"esbuild": "0.28.0",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"nodemon": "3.1.14",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": false,
|
||||
"outDir": "./js-built/",
|
||||
"outDir": "./js-built",
|
||||
"removeComments": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
@@ -17,6 +17,7 @@
|
||||
"noImplicitReturns": true,
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"rootDir": "./js",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"@@/*": ["./*"]
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
"@github/webauthn-json": "2.1.1",
|
||||
"@mcaptcha/core-glue": "0.1.0-alpha-5",
|
||||
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
||||
"@sentry/vue": "10.47.0",
|
||||
"@sentry/vue": "10.48.0",
|
||||
"@syuilo/aiscript": "1.2.1",
|
||||
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.5",
|
||||
"@vitejs/plugin-vue": "6.0.6",
|
||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.16",
|
||||
"analytics": "0.8.19",
|
||||
"broadcast-channel": "7.3.0",
|
||||
@@ -46,7 +46,7 @@
|
||||
"date-fns": "4.1.0",
|
||||
"eventemitter3": "5.0.4",
|
||||
"execa": "9.6.1",
|
||||
"exifreader": "4.38.0",
|
||||
"exifreader": "4.38.1",
|
||||
"frontend-shared": "workspace:*",
|
||||
"i18n": "workspace:*",
|
||||
"icons-subsetter": "workspace:*",
|
||||
@@ -110,9 +110,9 @@
|
||||
"@types/textarea-caret": "3.0.4",
|
||||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@vitest/coverage-v8": "4.1.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@vitest/coverage-v8": "4.1.4",
|
||||
"@vue/compiler-core": "3.5.32",
|
||||
"acorn": "8.16.0",
|
||||
"astring": "1.9.0",
|
||||
@@ -121,27 +121,27 @@
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"estree-walker": "3.0.3",
|
||||
"happy-dom": "20.8.9",
|
||||
"happy-dom": "20.9.0",
|
||||
"intersection-observer": "0.12.2",
|
||||
"micromatch": "4.0.8",
|
||||
"minimatch": "10.2.5",
|
||||
"msw": "2.13.2",
|
||||
"msw": "2.13.3",
|
||||
"msw-storybook-addon": "2.0.7",
|
||||
"nodemon": "3.1.14",
|
||||
"prettier": "3.8.1",
|
||||
"prettier": "3.8.3",
|
||||
"react": "19.2.5",
|
||||
"react-dom": "19.2.5",
|
||||
"rolldown": "1.0.0-rc.15",
|
||||
"sass-embedded": "1.99.0",
|
||||
"seedrandom": "3.0.5",
|
||||
"start-server-and-test": "2.1.5",
|
||||
"start-server-and-test": "3.0.2",
|
||||
"storybook": "10.3.5",
|
||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||
"tsx": "4.21.0",
|
||||
"vite": "8.0.8",
|
||||
"vite-plugin-glsl": "1.6.0",
|
||||
"vite-plugin-turbosnap": "1.0.3",
|
||||
"vitest": "4.1.3",
|
||||
"vitest": "4.1.4",
|
||||
"vitest-fetch-mock": "0.4.5",
|
||||
"vue-component-type-helpers": "3.2.6",
|
||||
"vue-eslint-parser": "10.4.0",
|
||||
|
||||
@@ -182,15 +182,28 @@ function showMenu(ev: MouseEvent) {
|
||||
text: i18n.ts._mediaControls.playbackRate,
|
||||
icon: 'ti ti-clock-play',
|
||||
ref: speed,
|
||||
options: {
|
||||
'0.25x': 0.25,
|
||||
'0.5x': 0.5,
|
||||
'0.75x': 0.75,
|
||||
'1.0x': 1,
|
||||
'1.25x': 1.25,
|
||||
'1.5x': 1.5,
|
||||
'2.0x': 2,
|
||||
},
|
||||
options: [{
|
||||
label: '0.25x',
|
||||
value: 0.25,
|
||||
}, {
|
||||
label: '0.5x',
|
||||
value: 0.5,
|
||||
}, {
|
||||
label: '0.75x',
|
||||
value: 0.75,
|
||||
}, {
|
||||
label: '1.0x',
|
||||
value: 1,
|
||||
}, {
|
||||
label: '1.25x',
|
||||
value: 1.25,
|
||||
}, {
|
||||
label: '1.5x',
|
||||
value: 1.5,
|
||||
}, {
|
||||
label: '2.0x',
|
||||
value: 2,
|
||||
}],
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
|
||||
@@ -204,15 +204,28 @@ function showMenu(ev: PointerEvent) {
|
||||
text: i18n.ts._mediaControls.playbackRate,
|
||||
icon: 'ti ti-clock-play',
|
||||
ref: speed,
|
||||
options: {
|
||||
'0.25x': 0.25,
|
||||
'0.5x': 0.5,
|
||||
'0.75x': 0.75,
|
||||
'1.0x': 1,
|
||||
'1.25x': 1.25,
|
||||
'1.5x': 1.5,
|
||||
'2.0x': 2,
|
||||
},
|
||||
options: [{
|
||||
label: '0.25x',
|
||||
value: 0.25,
|
||||
}, {
|
||||
label: '0.5x',
|
||||
value: 0.5,
|
||||
}, {
|
||||
label: '0.75x',
|
||||
value: 0.75,
|
||||
}, {
|
||||
label: '1.0x',
|
||||
value: 1,
|
||||
}, {
|
||||
label: '1.25x',
|
||||
value: 1.25,
|
||||
}, {
|
||||
label: '1.5x',
|
||||
value: 1.5,
|
||||
}, {
|
||||
label: '2.0x',
|
||||
value: 2,
|
||||
}],
|
||||
},
|
||||
...(window.document.pictureInPictureEnabled ? [{
|
||||
text: i18n.ts._mediaControls.pip,
|
||||
|
||||
@@ -132,6 +132,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
:class="['_button', $style.item, $style.parent, { [$style.active]: childShowingItem === item }]"
|
||||
:disabled="unref(item.disabled)"
|
||||
@mouseenter.prevent="preferClick ? null : showRadioOptions(item, $event)"
|
||||
@mousemove="parentMouseMove"
|
||||
@keydown.enter.prevent="preferClick ? null : showRadioOptions(item, $event)"
|
||||
@click.prevent="!preferClick ? null : showRadioOptions(item, $event)"
|
||||
>
|
||||
@@ -232,7 +233,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineAsyncComponent, inject, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, unref, watch, shallowRef, reactive } from 'vue';
|
||||
import { computed, defineAsyncComponent, inject, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, unref, watch, shallowRef, reactive, isRef } from 'vue';
|
||||
import type { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio, MenuRadioOption, MenuParent } from '@/types/menu.js';
|
||||
import type { Keymap } from '@/utility/hotkey.js';
|
||||
import MkSwitchButton from '@/components/MkSwitch.button.vue';
|
||||
@@ -338,24 +339,23 @@ function onItemMouseLeave() {
|
||||
}
|
||||
|
||||
async function showRadioOptions(item: MenuRadio, ev: MouseEvent | PointerEvent | KeyboardEvent) {
|
||||
const children: MenuItem[] = Object.keys(item.options).map<MenuRadioOption>(key => {
|
||||
const value = item.options[key];
|
||||
const children: MenuItem[] = item.options.map<MenuRadioOption>(def => {
|
||||
return {
|
||||
type: 'radioOption',
|
||||
text: key,
|
||||
text: def.label,
|
||||
action: () => {
|
||||
if ('value' in item.ref) {
|
||||
item.ref.value = value;
|
||||
if (isRef(item.ref)) {
|
||||
item.ref.value = def.value;
|
||||
} else {
|
||||
// @ts-expect-error リアクティビティは保たれる
|
||||
item.ref = value;
|
||||
item.ref = def.value;
|
||||
}
|
||||
},
|
||||
active: computed(() => {
|
||||
if ('value' in item.ref) {
|
||||
return item.ref.value === value;
|
||||
if (isRef(item.ref)) {
|
||||
return item.ref.value === def.value;
|
||||
} else {
|
||||
return item.ref === value;
|
||||
return item.ref === def.value;
|
||||
}
|
||||
}),
|
||||
};
|
||||
@@ -420,9 +420,14 @@ function close(actioned = false) {
|
||||
});
|
||||
}
|
||||
|
||||
function switchItem(item: MenuSwitch & { ref: any }) {
|
||||
function switchItem(item: MenuSwitch) {
|
||||
if (item.disabled !== undefined && (typeof item.disabled === 'boolean' ? item.disabled : item.disabled.value)) return;
|
||||
item.ref = !item.ref;
|
||||
if (isRef(item.ref)) {
|
||||
item.ref.value = !item.ref.value;
|
||||
} else {
|
||||
// @ts-expect-error リアクティビティは保たれる
|
||||
item.ref = !item.ref;
|
||||
}
|
||||
}
|
||||
|
||||
function focusUp() {
|
||||
|
||||
@@ -10,8 +10,6 @@ import type { OptionValue } from '@/types/option-value.js';
|
||||
|
||||
type ComponentProps<T extends Component> = { [K in keyof CP<T>]: MaybeRef<CP<T>[K]> };
|
||||
|
||||
type MenuRadioOptionsDef = Record<string, OptionValue>;
|
||||
|
||||
type Text = string | ComputedRef<string>;
|
||||
|
||||
export type MenuAction = (ev: PointerEvent) => void;
|
||||
@@ -32,6 +30,12 @@ interface MenuBase {
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface TextMenuBase extends MenuBase {
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface MenuDivider extends MenuBase {
|
||||
type: 'divider';
|
||||
}
|
||||
@@ -42,24 +46,18 @@ export interface MenuLabel extends MenuBase {
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
}
|
||||
|
||||
export interface MenuLink extends MenuBase {
|
||||
export interface MenuLink extends TextMenuBase {
|
||||
type: 'link';
|
||||
to: string;
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
indicate?: boolean;
|
||||
avatar?: Misskey.entities.User;
|
||||
}
|
||||
|
||||
export interface MenuA extends MenuBase {
|
||||
export interface MenuA extends TextMenuBase {
|
||||
type: 'a';
|
||||
href: string;
|
||||
target?: string;
|
||||
download?: string;
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
indicate?: boolean;
|
||||
}
|
||||
|
||||
@@ -71,22 +69,19 @@ export interface MenuUser extends MenuBase {
|
||||
action: MenuAction;
|
||||
}
|
||||
|
||||
export interface MenuSwitch extends MenuBase {
|
||||
export interface MenuSwitch extends TextMenuBase {
|
||||
type: 'switch';
|
||||
ref: Ref<boolean>;
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
disabled?: boolean | Ref<boolean>;
|
||||
}
|
||||
|
||||
export interface MenuRadio extends MenuBase {
|
||||
export interface MenuRadio extends TextMenuBase {
|
||||
type: 'radio';
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
ref: Ref<MenuRadioOptionsDef[keyof MenuRadioOptionsDef]>;
|
||||
options: MenuRadioOptionsDef;
|
||||
ref: Ref<OptionValue>;
|
||||
options: {
|
||||
label: string;
|
||||
value: OptionValue;
|
||||
}[];
|
||||
disabled?: boolean | Ref<boolean>;
|
||||
}
|
||||
|
||||
@@ -104,11 +99,8 @@ export interface MenuComponent<T extends Component = any> extends MenuBase {
|
||||
props?: ComponentProps<T>;
|
||||
}
|
||||
|
||||
export interface MenuParent extends MenuBase {
|
||||
export interface MenuParent extends TextMenuBase {
|
||||
type: 'parent';
|
||||
text: Text;
|
||||
caption?: Text | null | undefined | ComputedRef<null | undefined>;
|
||||
icon?: string;
|
||||
children: MenuItem[] | (() => Promise<MenuItem[]> | MenuItem[]);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"chokidar": "5.0.0",
|
||||
"esbuild": "0.28.0",
|
||||
"execa": "9.6.1",
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
"skipLibCheck": true,
|
||||
"types": ["node"],
|
||||
"rootDir": "./src",
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "24.12.2",
|
||||
"@types/wawoff2": "1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1"
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"@types/matter-js": "0.20.2",
|
||||
"@types/node": "24.12.2",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"esbuild": "0.28.0",
|
||||
"execa": "9.6.1",
|
||||
"nodemon": "3.1.14"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": false,
|
||||
"outDir": "./built/",
|
||||
"outDir": "./built",
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"strictFunctionTypes": true,
|
||||
@@ -15,6 +15,7 @@
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitReturns": true,
|
||||
"esModuleInterop": true,
|
||||
"rootDir": "./src",
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
],
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"devDependencies": {
|
||||
"@readme/openapi-parser": "6.0.1",
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"openapi-types": "12.1.3",
|
||||
"openapi-typescript": "7.13.0",
|
||||
"ts-case-convert": "2.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2026.4.0-alpha.6",
|
||||
"version": "2026.4.0-beta.0",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
@@ -39,15 +39,15 @@
|
||||
"devDependencies": {
|
||||
"@microsoft/api-extractor": "7.58.2",
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@vitest/coverage-v8": "4.1.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@vitest/coverage-v8": "4.1.4",
|
||||
"esbuild": "0.28.0",
|
||||
"execa": "9.6.1",
|
||||
"ncp": "2.0.0",
|
||||
"nodemon": "3.1.14",
|
||||
"tsd": "0.33.0",
|
||||
"vitest": "4.1.3",
|
||||
"vitest": "4.1.4",
|
||||
"vitest-websocket-mock": "0.5.0"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": false,
|
||||
"outDir": "./built/",
|
||||
"outDir": "./built",
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"strictFunctionTypes": true,
|
||||
@@ -16,6 +16,7 @@
|
||||
"noImplicitReturns": true,
|
||||
"esModuleInterop": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"rootDir": "./src",
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
],
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"esbuild": "0.28.0",
|
||||
"execa": "9.6.1",
|
||||
"nodemon": "3.1.14"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": false,
|
||||
"outDir": "./built/",
|
||||
"outDir": "./built",
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"strictFunctionTypes": true,
|
||||
@@ -15,6 +15,7 @@
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitReturns": true,
|
||||
"esModuleInterop": true,
|
||||
"rootDir": "./src",
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
],
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"misskey-js": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/parser": "8.58.1",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"nodemon": "3.1.14"
|
||||
|
||||
Reference in New Issue
Block a user