mirror of
https://github.com/misskey-dev/misskey
synced 2024-12-12 05:39:00 +09:00
Merge branch 'develop' into feat-1714
This commit is contained in:
commit
aab4fa9394
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@ -10,14 +10,14 @@ on:
|
|||||||
- packages/frontend/**
|
- packages/frontend/**
|
||||||
- packages/sw/**
|
- packages/sw/**
|
||||||
- packages/misskey-js/**
|
- packages/misskey-js/**
|
||||||
- packages/shared/.eslintrc.js
|
- packages/shared/eslint.config.js
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- packages/backend/**
|
- packages/backend/**
|
||||||
- packages/frontend/**
|
- packages/frontend/**
|
||||||
- packages/sw/**
|
- packages/sw/**
|
||||||
- packages/misskey-js/**
|
- packages/misskey-js/**
|
||||||
- packages/shared/.eslintrc.js
|
- packages/shared/eslint.config.js
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pnpm_install:
|
pnpm_install:
|
||||||
|
@ -52,7 +52,11 @@ const primaries = {
|
|||||||
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
|
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
|
||||||
|
|
||||||
export function build() {
|
export function build() {
|
||||||
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
|
// vitestの挙動を調整するため、一度ローカル変数化する必要がある
|
||||||
|
// https://github.com/vitest-dev/vitest/issues/3988#issuecomment-1686599577
|
||||||
|
// https://github.com/misskey-dev/misskey/pull/14057#issuecomment-2192833785
|
||||||
|
const metaUrl = import.meta.url;
|
||||||
|
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, metaUrl), 'utf-8'))) || {}, a), {});
|
||||||
|
|
||||||
// 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
|
// 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
|
||||||
const removeEmpty = (obj) => {
|
const removeEmpty = (obj) => {
|
||||||
|
20
package.json
20
package.json
@ -55,20 +55,22 @@
|
|||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"postcss": "8.4.38",
|
"postcss": "8.4.38",
|
||||||
"tar": "6.2.1",
|
"tar": "6.2.1",
|
||||||
"terser": "5.30.3",
|
"terser": "5.31.1",
|
||||||
"typescript": "5.5.2",
|
"typescript": "5.5.3",
|
||||||
"esbuild": "0.20.2",
|
"esbuild": "0.22.0",
|
||||||
"glob": "10.3.12"
|
"glob": "10.3.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "20.12.7",
|
"@misskey-dev/eslint-plugin": "2.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "7.7.1",
|
"@types/node": "20.14.9",
|
||||||
"@typescript-eslint/parser": "7.7.1",
|
"@typescript-eslint/eslint-plugin": "7.15.0",
|
||||||
|
"@typescript-eslint/parser": "7.15.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "13.7.3",
|
"cypress": "13.13.0",
|
||||||
"eslint": "8.57.0",
|
"eslint": "9.6.0",
|
||||||
|
"globals": "15.7.0",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"start-server-and-test": "2.0.3"
|
"start-server-and-test": "2.0.4"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tensorflow/tfjs-core": "4.4.0"
|
"@tensorflow/tfjs-core": "4.4.0"
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
node_modules
|
|
||||||
/built
|
|
||||||
/.eslintrc.js
|
|
||||||
/@types/**/*
|
|
@ -1,32 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json', './test/tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../shared/.eslintrc.js',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'import/order': ['warn', {
|
|
||||||
'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
|
||||||
'pathGroups': [
|
|
||||||
{
|
|
||||||
'pattern': '@/**',
|
|
||||||
'group': 'external',
|
|
||||||
'position': 'after'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
'no-restricted-globals': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
'name': '__dirname',
|
|
||||||
'message': 'Not in ESModule. Use `import.meta.url` instead.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': '__filename',
|
|
||||||
'message': 'Not in ESModule. Use `import.meta.url` instead.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
46
packages/backend/eslint.config.js
Normal file
46
packages/backend/eslint.config.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
ignores: ['**/node_modules', 'built', '@types/**/*'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json', './test/tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'import/order': ['warn', {
|
||||||
|
groups: [
|
||||||
|
'builtin',
|
||||||
|
'external',
|
||||||
|
'internal',
|
||||||
|
'parent',
|
||||||
|
'sibling',
|
||||||
|
'index',
|
||||||
|
'object',
|
||||||
|
'type',
|
||||||
|
],
|
||||||
|
pathGroups: [{
|
||||||
|
pattern: '@/**',
|
||||||
|
group: 'external',
|
||||||
|
position: 'after',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
'no-restricted-globals': ['error', {
|
||||||
|
name: '__dirname',
|
||||||
|
message: 'Not in ESModule. Use `import.meta.url` instead.',
|
||||||
|
}, {
|
||||||
|
name: '__filename',
|
||||||
|
message: 'Not in ESModule. Use `import.meta.url` instead.',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -65,43 +65,43 @@
|
|||||||
"utf-8-validate": "6.0.3"
|
"utf-8-validate": "6.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "3.412.0",
|
"@aws-sdk/client-s3": "3.600.0",
|
||||||
"@aws-sdk/lib-storage": "3.412.0",
|
"@aws-sdk/lib-storage": "3.600.0",
|
||||||
"@bull-board/api": "5.17.0",
|
"@bull-board/api": "5.20.5",
|
||||||
"@bull-board/fastify": "5.17.0",
|
"@bull-board/fastify": "5.20.5",
|
||||||
"@bull-board/ui": "5.17.0",
|
"@bull-board/ui": "5.20.5",
|
||||||
"@discordapp/twemoji": "15.0.3",
|
"@discordapp/twemoji": "15.0.3",
|
||||||
"@fastify/accepts": "4.3.0",
|
"@fastify/accepts": "4.3.0",
|
||||||
"@fastify/cookie": "9.3.1",
|
"@fastify/cookie": "9.3.1",
|
||||||
"@fastify/cors": "9.0.1",
|
"@fastify/cors": "9.0.1",
|
||||||
"@fastify/express": "3.0.0",
|
"@fastify/express": "3.0.0",
|
||||||
"@fastify/http-proxy": "9.5.0",
|
"@fastify/http-proxy": "9.5.0",
|
||||||
"@fastify/multipart": "8.2.0",
|
"@fastify/multipart": "8.3.0",
|
||||||
"@fastify/static": "7.0.3",
|
"@fastify/static": "7.0.4",
|
||||||
"@fastify/view": "9.1.0",
|
"@fastify/view": "9.1.0",
|
||||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||||
"@misskey-dev/summaly": "5.1.0",
|
"@misskey-dev/summaly": "5.1.0",
|
||||||
"@napi-rs/canvas": "^0.1.52",
|
"@napi-rs/canvas": "^0.1.53",
|
||||||
"@nestjs/common": "10.3.8",
|
"@nestjs/common": "10.3.10",
|
||||||
"@nestjs/core": "10.3.8",
|
"@nestjs/core": "10.3.10",
|
||||||
"@nestjs/testing": "10.3.8",
|
"@nestjs/testing": "10.3.10",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@sentry/node": "^8.5.0",
|
"@sentry/node": "8.13.0",
|
||||||
"@sentry/profiling-node": "^8.5.0",
|
"@sentry/profiling-node": "8.13.0",
|
||||||
"@simplewebauthn/server": "10.0.0",
|
"@simplewebauthn/server": "10.0.0",
|
||||||
"@sinonjs/fake-timers": "11.2.2",
|
"@sinonjs/fake-timers": "11.2.2",
|
||||||
"@smithy/node-http-handler": "2.5.0",
|
"@smithy/node-http-handler": "2.5.0",
|
||||||
"@swc/cli": "0.3.12",
|
"@swc/cli": "0.3.12",
|
||||||
"@swc/core": "1.4.17",
|
"@swc/core": "1.6.6",
|
||||||
"@twemoji/parser": "15.1.1",
|
"@twemoji/parser": "15.1.1",
|
||||||
"accepts": "1.3.8",
|
"accepts": "1.3.8",
|
||||||
"ajv": "8.13.0",
|
"ajv": "8.16.0",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"blurhash": "2.0.5",
|
"blurhash": "2.0.5",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.2",
|
||||||
"bullmq": "5.7.8",
|
"bullmq": "5.8.3",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
"cbor": "9.0.2",
|
"cbor": "9.0.2",
|
||||||
"chalk": "5.3.0",
|
"chalk": "5.3.0",
|
||||||
@ -112,27 +112,27 @@
|
|||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
"deep-email-validator": "0.1.21",
|
"deep-email-validator": "0.1.21",
|
||||||
"fastify": "4.26.2",
|
"fastify": "4.28.1",
|
||||||
"fastify-raw-body": "4.3.0",
|
"fastify-raw-body": "4.3.0",
|
||||||
"feed": "4.2.2",
|
"feed": "4.2.2",
|
||||||
"file-type": "19.0.0",
|
"file-type": "19.0.0",
|
||||||
"fluent-ffmpeg": "2.1.2",
|
"fluent-ffmpeg": "2.1.3",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"got": "14.2.1",
|
"got": "14.4.1",
|
||||||
"happy-dom": "10.0.3",
|
"happy-dom": "10.0.3",
|
||||||
"hpagent": "1.2.0",
|
"hpagent": "1.2.0",
|
||||||
"htmlescape": "1.1.1",
|
"htmlescape": "1.1.1",
|
||||||
"http-link-header": "1.1.3",
|
"http-link-header": "1.1.3",
|
||||||
"ioredis": "5.4.1",
|
"ioredis": "5.4.1",
|
||||||
"ip-cidr": "3.1.0",
|
"ip-cidr": "4.0.1",
|
||||||
"ipaddr.js": "2.2.0",
|
"ipaddr.js": "2.2.0",
|
||||||
"is-svg": "5.0.0",
|
"is-svg": "5.0.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"jsdom": "24.0.0",
|
"jsdom": "24.1.0",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"jsonld": "8.3.2",
|
"jsonld": "8.3.2",
|
||||||
"jsrsasign": "11.1.0",
|
"jsrsasign": "11.1.0",
|
||||||
"meilisearch": "0.38.0",
|
"meilisearch": "0.41.0",
|
||||||
"mfm-js": "0.24.0",
|
"mfm-js": "0.24.0",
|
||||||
"microformats-parser": "2.0.2",
|
"microformats-parser": "2.0.2",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
@ -142,24 +142,24 @@
|
|||||||
"nanoid": "5.0.7",
|
"nanoid": "5.0.7",
|
||||||
"nested-property": "4.0.0",
|
"nested-property": "4.0.0",
|
||||||
"node-fetch": "3.3.2",
|
"node-fetch": "3.3.2",
|
||||||
"nodemailer": "6.9.13",
|
"nodemailer": "6.9.14",
|
||||||
"nsfwjs": "2.4.2",
|
"nsfwjs": "2.4.2",
|
||||||
"oauth": "0.10.0",
|
"oauth": "0.10.0",
|
||||||
"oauth2orize": "1.12.0",
|
"oauth2orize": "1.12.0",
|
||||||
"oauth2orize-pkce": "0.1.2",
|
"oauth2orize-pkce": "0.1.2",
|
||||||
"os-utils": "0.0.14",
|
"os-utils": "0.0.14",
|
||||||
"otpauth": "9.2.3",
|
"otpauth": "9.3.1",
|
||||||
"parse5": "7.1.2",
|
"parse5": "7.1.2",
|
||||||
"pg": "8.11.5",
|
"pg": "8.12.0",
|
||||||
"pkce-challenge": "4.1.0",
|
"pkce-challenge": "4.1.0",
|
||||||
"probe-image-size": "7.2.3",
|
"probe-image-size": "7.2.3",
|
||||||
"promise-limit": "2.7.0",
|
"promise-limit": "2.7.0",
|
||||||
"pug": "3.0.2",
|
"pug": "3.0.3",
|
||||||
"punycode": "2.3.1",
|
"punycode": "2.3.1",
|
||||||
"qrcode": "1.5.3",
|
"qrcode": "1.5.3",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"re2": "1.21.2",
|
"re2": "1.21.3",
|
||||||
"redis-lock": "0.1.4",
|
"redis-lock": "0.1.4",
|
||||||
"reflect-metadata": "0.2.2",
|
"reflect-metadata": "0.2.2",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
@ -167,27 +167,26 @@
|
|||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"sanitize-html": "2.13.0",
|
"sanitize-html": "2.13.0",
|
||||||
"secure-json-parse": "2.7.0",
|
"secure-json-parse": "2.7.0",
|
||||||
"sharp": "0.33.3",
|
"sharp": "0.33.4",
|
||||||
"slacc": "0.0.10",
|
"slacc": "0.0.10",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"systeminformation": "5.22.7",
|
"systeminformation": "5.22.11",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tmp": "0.2.3",
|
"tmp": "0.2.3",
|
||||||
"tsc-alias": "1.8.8",
|
"tsc-alias": "1.8.10",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typeorm": "0.3.20",
|
"typeorm": "0.3.20",
|
||||||
"typescript": "5.5.2",
|
"typescript": "5.5.3",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"vary": "1.1.2",
|
"vary": "1.1.2",
|
||||||
"web-push": "3.6.7",
|
"web-push": "3.6.7",
|
||||||
"ws": "8.17.0",
|
"ws": "8.17.1",
|
||||||
"xev": "3.0.2"
|
"xev": "3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@jest/globals": "29.7.0",
|
"@jest/globals": "29.7.0",
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
"@nestjs/platform-express": "10.3.10",
|
||||||
"@nestjs/platform-express": "10.3.8",
|
|
||||||
"@simplewebauthn/types": "10.0.0",
|
"@simplewebauthn/types": "10.0.0",
|
||||||
"@swc/jest": "0.2.36",
|
"@swc/jest": "0.2.36",
|
||||||
"@types/accepts": "1.3.7",
|
"@types/accepts": "1.3.7",
|
||||||
@ -197,21 +196,21 @@
|
|||||||
"@types/color-convert": "2.0.3",
|
"@types/color-convert": "2.0.3",
|
||||||
"@types/content-disposition": "0.5.8",
|
"@types/content-disposition": "0.5.8",
|
||||||
"@types/fluent-ffmpeg": "2.1.24",
|
"@types/fluent-ffmpeg": "2.1.24",
|
||||||
"@types/htmlescape": "^1.1.3",
|
"@types/htmlescape": "1.1.3",
|
||||||
"@types/http-link-header": "1.0.5",
|
"@types/http-link-header": "1.0.7",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/jsdom": "21.1.6",
|
"@types/jsdom": "21.1.7",
|
||||||
"@types/jsonld": "1.5.13",
|
"@types/jsonld": "1.5.14",
|
||||||
"@types/jsrsasign": "10.5.14",
|
"@types/jsrsasign": "10.5.14",
|
||||||
"@types/mime-types": "2.1.4",
|
"@types/mime-types": "2.1.4",
|
||||||
"@types/ms": "0.7.34",
|
"@types/ms": "0.7.34",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.14.9",
|
||||||
"@types/nodemailer": "6.4.15",
|
"@types/nodemailer": "6.4.15",
|
||||||
"@types/oauth": "0.9.4",
|
"@types/oauth": "0.9.5",
|
||||||
"@types/oauth2orize": "1.11.5",
|
"@types/oauth2orize": "1.11.5",
|
||||||
"@types/oauth2orize-pkce": "0.1.2",
|
"@types/oauth2orize-pkce": "0.1.2",
|
||||||
"@types/pg": "8.11.5",
|
"@types/pg": "8.11.6",
|
||||||
"@types/pug": "2.0.10",
|
"@types/pug": "2.0.10",
|
||||||
"@types/punycode": "2.1.4",
|
"@types/punycode": "2.1.4",
|
||||||
"@types/qrcode": "1.5.5",
|
"@types/qrcode": "1.5.5",
|
||||||
@ -227,18 +226,17 @@
|
|||||||
"@types/vary": "1.1.3",
|
"@types/vary": "1.1.3",
|
||||||
"@types/web-push": "3.6.3",
|
"@types/web-push": "3.6.3",
|
||||||
"@types/ws": "8.5.10",
|
"@types/ws": "8.5.10",
|
||||||
"@typescript-eslint/eslint-plugin": "7.7.1",
|
"@typescript-eslint/eslint-plugin": "7.15.0",
|
||||||
"@typescript-eslint/parser": "7.7.1",
|
"@typescript-eslint/parser": "7.15.0",
|
||||||
"aws-sdk-client-mock": "3.0.1",
|
"aws-sdk-client-mock": "4.0.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "8.57.0",
|
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"execa": "8.0.1",
|
"execa": "9.2.0",
|
||||||
"fkill": "^9.0.0",
|
"fkill": "9.0.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-mock": "29.7.0",
|
"jest-mock": "29.7.0",
|
||||||
"nodemon": "3.1.0",
|
"nodemon": "3.1.4",
|
||||||
"pid-port": "1.0.0",
|
"pid-port": "1.0.0",
|
||||||
"simple-oauth2": "5.0.0"
|
"simple-oauth2": "5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ function execStart() {
|
|||||||
|
|
||||||
async function killProc() {
|
async function killProc() {
|
||||||
if (backendProcess) {
|
if (backendProcess) {
|
||||||
|
backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
|
||||||
backendProcess.kill();
|
backendProcess.kill();
|
||||||
await new Promise(resolve => backendProcess.on('exit', resolve));
|
await new Promise(resolve => backendProcess.on('exit', resolve));
|
||||||
backendProcess = undefined;
|
backendProcess = undefined;
|
||||||
@ -46,6 +47,7 @@ async function killProc() {
|
|||||||
],
|
],
|
||||||
{
|
{
|
||||||
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
|
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
|
||||||
|
serialization: "json",
|
||||||
})
|
})
|
||||||
.on('message', async (message) => {
|
.on('message', async (message) => {
|
||||||
if (message.type === 'exit') {
|
if (message.type === 'exit') {
|
||||||
|
@ -20,7 +20,7 @@ export const packedDriveFileSchema = {
|
|||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
example: 'lenna.jpg',
|
example: '192.jpg',
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -61,7 +61,7 @@ export const meta = {
|
|||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
example: 'lenna.jpg',
|
example: '192.jpg',
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../../shared/.eslintrc.js',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'import/order': ['warn', {
|
|
||||||
'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
|
||||||
'pathGroups': [
|
|
||||||
{
|
|
||||||
'pattern': '@/**',
|
|
||||||
'group': 'external',
|
|
||||||
'position': 'after'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
'no-restricted-globals': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
'name': '__dirname',
|
|
||||||
'message': 'Not in ESModule. Use `import.meta.url` instead.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': '__filename',
|
|
||||||
'message': 'Not in ESModule. Use `import.meta.url` instead.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
43
packages/backend/test-server/eslint.config.js
Normal file
43
packages/backend/test-server/eslint.config.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'import/order': ['warn', {
|
||||||
|
groups: [
|
||||||
|
'builtin',
|
||||||
|
'external',
|
||||||
|
'internal',
|
||||||
|
'parent',
|
||||||
|
'sibling',
|
||||||
|
'index',
|
||||||
|
'object',
|
||||||
|
'type',
|
||||||
|
],
|
||||||
|
pathGroups: [{
|
||||||
|
pattern: '@/**',
|
||||||
|
group: 'external',
|
||||||
|
position: 'after',
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
'no-restricted-globals': ['error', {
|
||||||
|
name: '__dirname',
|
||||||
|
message: 'Not in ESModule. Use `import.meta.url` instead.',
|
||||||
|
}, {
|
||||||
|
name: '__filename',
|
||||||
|
message: 'Not in ESModule. Use `import.meta.url` instead.',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -1,11 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: ['../.eslintrc.cjs'],
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
jest: true,
|
|
||||||
},
|
|
||||||
};
|
|
@ -23,7 +23,7 @@ describe('Drive', () => {
|
|||||||
|
|
||||||
const marker = Math.random().toString();
|
const marker = Math.random().toString();
|
||||||
|
|
||||||
const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg';
|
const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg';
|
||||||
|
|
||||||
const catcher = makeStreamCatcher(
|
const catcher = makeStreamCatcher(
|
||||||
alice,
|
alice,
|
||||||
@ -41,14 +41,14 @@ describe('Drive', () => {
|
|||||||
const file = await catcher;
|
const file = await catcher;
|
||||||
|
|
||||||
assert.strictEqual(res.status, 204);
|
assert.strictEqual(res.status, 204);
|
||||||
assert.strictEqual(file.name, 'Lenna.jpg');
|
assert.strictEqual(file.name, '192.jpg');
|
||||||
assert.strictEqual(file.type, 'image/jpeg');
|
assert.strictEqual(file.type, 'image/jpeg');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ローカルからアップロードできる', async () => {
|
test('ローカルからアップロードできる', async () => {
|
||||||
// APIレスポンスを直接使用するので utils.js uploadFile が通過することで成功とする
|
// APIレスポンスを直接使用するので utils.js uploadFile が通過することで成功とする
|
||||||
|
|
||||||
const res = await uploadFile(alice, { path: 'Lenna.jpg', name: 'テスト画像' });
|
const res = await uploadFile(alice, { path: '192.jpg', name: 'テスト画像' });
|
||||||
|
|
||||||
assert.strictEqual(res.body?.name, 'テスト画像.jpg');
|
assert.strictEqual(res.body?.name, 'テスト画像.jpg');
|
||||||
assert.strictEqual(res.body.type, 'image/jpeg');
|
assert.strictEqual(res.body.type, 'image/jpeg');
|
||||||
|
@ -584,7 +584,7 @@ describe('Endpoints', () => {
|
|||||||
|
|
||||||
assert.strictEqual(res.status, 200);
|
assert.strictEqual(res.status, 200);
|
||||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||||
assert.strictEqual(res.body!.name, 'Lenna.jpg');
|
assert.strictEqual(res.body!.name, '192.jpg');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ファイルに名前を付けられる', async () => {
|
test('ファイルに名前を付けられる', async () => {
|
||||||
|
@ -7,12 +7,13 @@ import { INestApplicationContext } from '@nestjs/common';
|
|||||||
|
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
|
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { loadConfig } from '@/config.js';
|
import { loadConfig } from '@/config.js';
|
||||||
import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js';
|
import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js';
|
||||||
import { secureRndstr } from '@/misc/secure-rndstr.js';
|
import { secureRndstr } from '@/misc/secure-rndstr.js';
|
||||||
import { jobQueue } from '@/boot/common.js';
|
import { jobQueue } from '@/boot/common.js';
|
||||||
import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js';
|
import { api, initTestDb, signup, successfulApiCall, uploadFile } from '../utils.js';
|
||||||
import type * as misskey from 'misskey-js';
|
import type * as misskey from 'misskey-js';
|
||||||
|
|
||||||
describe('Account Move', () => {
|
describe('Account Move', () => {
|
||||||
@ -271,7 +272,7 @@ describe('Account Move', () => {
|
|||||||
|
|
||||||
assert.strictEqual(move.status, 200);
|
assert.strictEqual(move.status, 200);
|
||||||
|
|
||||||
await sleep(1000 * 3); // wait for jobs to finish
|
await setTimeout(1000 * 3); // wait for jobs to finish
|
||||||
|
|
||||||
// Unfollow delayed?
|
// Unfollow delayed?
|
||||||
const aliceFollowings = await api('users/following', {
|
const aliceFollowings = await api('users/following', {
|
||||||
@ -330,7 +331,7 @@ describe('Account Move', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Unfollowed after 10 sec (24 hours in production).', async () => {
|
test('Unfollowed after 10 sec (24 hours in production).', async () => {
|
||||||
await sleep(1000 * 8);
|
await setTimeout(1000 * 8);
|
||||||
|
|
||||||
const following = await api('users/following', {
|
const following = await api('users/following', {
|
||||||
userId: alice.id,
|
userId: alice.id,
|
||||||
|
@ -41,7 +41,7 @@ describe('Note', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('ファイルを添付できる', async () => {
|
test('ファイルを添付できる', async () => {
|
||||||
const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg');
|
||||||
|
|
||||||
const res = await api('notes/create', {
|
const res = await api('notes/create', {
|
||||||
fileIds: [file.id],
|
fileIds: [file.id],
|
||||||
@ -53,7 +53,7 @@ describe('Note', () => {
|
|||||||
}, 1000 * 10);
|
}, 1000 * 10);
|
||||||
|
|
||||||
test('他人のファイルで怒られる', async () => {
|
test('他人のファイルで怒られる', async () => {
|
||||||
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg');
|
||||||
|
|
||||||
const res = await api('notes/create', {
|
const res = await api('notes/create', {
|
||||||
text: 'test',
|
text: 'test',
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { api, post, signup, sleep, waitFire } from '../utils.js';
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import { api, post, signup, waitFire } from '../utils.js';
|
||||||
import type * as misskey from 'misskey-js';
|
import type * as misskey from 'misskey-js';
|
||||||
|
|
||||||
describe('Renote Mute', () => {
|
describe('Renote Mute', () => {
|
||||||
@ -35,7 +36,7 @@ describe('Renote Mute', () => {
|
|||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
|
|
||||||
// redisに追加されるのを待つ
|
// redisに追加されるのを待つ
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const res = await api('notes/local-timeline', {}, alice);
|
const res = await api('notes/local-timeline', {}, alice);
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ describe('Renote Mute', () => {
|
|||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
|
|
||||||
// redisに追加されるのを待つ
|
// redisに追加されるのを待つ
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const res = await api('notes/local-timeline', {}, alice);
|
const res = await api('notes/local-timeline', {}, alice);
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ describe('Renote Mute', () => {
|
|||||||
const bobRenote = await post(bob, { renoteId: carolNote.id });
|
const bobRenote = await post(bob, { renoteId: carolNote.id });
|
||||||
|
|
||||||
// redisに追加されるのを待つ
|
// redisに追加されるのを待つ
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const res = await api('notes/local-timeline', {}, alice);
|
const res = await api('notes/local-timeline', {}, alice);
|
||||||
|
|
||||||
|
@ -7,16 +7,17 @@
|
|||||||
// pnpm jest -- e2e/timelines.ts
|
// pnpm jest -- e2e/timelines.ts
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import { Redis } from 'ioredis';
|
import { Redis } from 'ioredis';
|
||||||
import { loadConfig } from '@/config.js';
|
import { loadConfig } from '@/config.js';
|
||||||
import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js';
|
import { api, post, randomString, sendEnvUpdateRequest, signup, uploadUrl } from '../utils.js';
|
||||||
|
|
||||||
function genHost() {
|
function genHost() {
|
||||||
return randomString() + '.example.com';
|
return randomString() + '.example.com';
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForPushToTl() {
|
function waitForPushToTl() {
|
||||||
return sleep(500);
|
return setTimeout(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
let redisForTimelines: Redis;
|
let redisForTimelines: Redis;
|
||||||
@ -44,7 +45,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi' });
|
const bobNote = await post(bob, { text: 'hi' });
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] });
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi', visibility: 'followers' });
|
const carolNote = await post(carol, { text: 'hi', visibility: 'followers' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -147,7 +148,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: carol.id }, alice);
|
await api('following/create', { userId: carol.id }, alice);
|
||||||
await api('following/create', { userId: carol.id }, bob);
|
await api('following/create', { userId: carol.id }, bob);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi', visibility: 'followers' });
|
const carolNote = await post(carol, { text: 'hi', visibility: 'followers' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -166,7 +167,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/create', { userId: carol.id }, alice);
|
await api('following/create', { userId: carol.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] });
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote1 = await post(bob, { text: 'hi' });
|
const bobNote1 = await post(bob, { text: 'hi' });
|
||||||
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
||||||
|
|
||||||
@ -198,7 +199,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const aliceNote = await post(alice, { text: 'hi' });
|
const aliceNote = await post(alice, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
||||||
|
|
||||||
@ -228,7 +229,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { renoteId: carolNote.id });
|
const bobNote = await post(bob, { renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { renoteId: carolNote.id });
|
const bobNote = await post(bob, { renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -262,7 +263,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -280,7 +281,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -295,7 +296,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -313,7 +314,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -359,7 +360,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const [bobFile, carolFile] = await Promise.all([
|
const [bobFile, carolFile] = await Promise.all([
|
||||||
uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'),
|
uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'),
|
||||||
uploadUrl(carol, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'),
|
uploadUrl(carol, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'),
|
||||||
@ -384,7 +385,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body);
|
const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body);
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', channelId: channel.id });
|
const bobNote = await post(bob, { text: 'hi', channelId: channel.id });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -411,7 +412,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -438,7 +439,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -566,7 +567,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: carol.id }, alice);
|
await api('following/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi', visibility: 'home' });
|
const carolNote = await post(carol, { text: 'hi', visibility: 'home' });
|
||||||
const bobNote = await post(bob, { text: 'hi' });
|
const bobNote = await post(bob, { text: 'hi' });
|
||||||
|
|
||||||
@ -582,7 +583,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi' });
|
const bobNote = await post(bob, { text: 'hi' });
|
||||||
|
|
||||||
@ -599,7 +600,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -617,7 +618,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
await api('following/update', { userId: bob.id, withReplies: true }, alice);
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -633,7 +634,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const aliceNote = await post(alice, { text: 'hi' });
|
const aliceNote = await post(alice, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
||||||
|
|
||||||
@ -703,7 +704,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -717,7 +718,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const aliceNote = await post(alice, { text: 'hi' });
|
const aliceNote = await post(alice, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
||||||
|
|
||||||
@ -820,7 +821,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi' });
|
const bobNote = await post(bob, { text: 'hi' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -835,7 +836,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -850,7 +851,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -865,7 +866,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -881,7 +882,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote1 = await post(bob, { text: 'hi' });
|
const bobNote1 = await post(bob, { text: 'hi' });
|
||||||
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
||||||
|
|
||||||
@ -899,7 +900,7 @@ describe('Timelines', () => {
|
|||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice);
|
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const aliceNote = await post(alice, { text: 'hi' });
|
const aliceNote = await post(alice, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id });
|
||||||
|
|
||||||
@ -916,7 +917,7 @@ describe('Timelines', () => {
|
|||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice);
|
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -933,7 +934,7 @@ describe('Timelines', () => {
|
|||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: true }, alice);
|
await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: true }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id });
|
||||||
|
|
||||||
@ -950,7 +951,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -966,7 +967,7 @@ describe('Timelines', () => {
|
|||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -982,7 +983,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: alice.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: alice.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' });
|
const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -999,7 +1000,7 @@ describe('Timelines', () => {
|
|||||||
const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body);
|
const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body);
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', channelId: channel.id });
|
const bobNote = await post(bob, { text: 'hi', channelId: channel.id });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -1031,7 +1032,7 @@ describe('Timelines', () => {
|
|||||||
|
|
||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -1048,7 +1049,7 @@ describe('Timelines', () => {
|
|||||||
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
|
||||||
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
|
||||||
await api('users/lists/push', { listId: list.id, userId: carol.id }, alice);
|
await api('users/lists/push', { listId: list.id, userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -1088,7 +1089,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('following/create', { userId: bob.id }, alice);
|
await api('following/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
const bobNote = await post(bob, { text: 'hi', visibility: 'followers' });
|
||||||
|
|
||||||
await waitForPushToTl();
|
await waitForPushToTl();
|
||||||
@ -1228,7 +1229,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
await api('mute/create', { userId: carol.id }, alice);
|
await api('mute/create', { userId: carol.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const carolNote = await post(carol, { text: 'hi' });
|
const carolNote = await post(carol, { text: 'hi' });
|
||||||
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id });
|
||||||
|
|
||||||
@ -1243,7 +1244,7 @@ describe('Timelines', () => {
|
|||||||
const [alice, bob] = await Promise.all([signup(), signup()]);
|
const [alice, bob] = await Promise.all([signup(), signup()]);
|
||||||
|
|
||||||
await api('mute/create', { userId: bob.id }, alice);
|
await api('mute/create', { userId: bob.id }, alice);
|
||||||
await sleep(1000);
|
await setTimeout(1000);
|
||||||
const bobNote1 = await post(bob, { text: 'hi' });
|
const bobNote1 = await post(bob, { text: 'hi' });
|
||||||
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id });
|
||||||
const bobNote3 = await post(bob, { text: 'hi', renoteId: bobNote1.id });
|
const bobNote3 = await post(bob, { text: 'hi', renoteId: bobNote1.id });
|
||||||
|
@ -17,8 +17,8 @@ describe('users/notes', () => {
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
alice = await signup({ username: 'alice' });
|
alice = await signup({ username: 'alice' });
|
||||||
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg');
|
||||||
const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.png');
|
const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.png');
|
||||||
jpgNote = await post(alice, {
|
jpgNote = await post(alice, {
|
||||||
fileIds: [jpg.id],
|
fileIds: [jpg.id],
|
||||||
});
|
});
|
||||||
|
22
packages/backend/test/eslint.config.js
Normal file
22
packages/backend/test/eslint.config.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import globals from 'globals';
|
||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
...globals.jest,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
BIN
packages/backend/test/resources/192.jpg
Normal file
BIN
packages/backend/test/resources/192.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
BIN
packages/backend/test/resources/192.png
Normal file
BIN
packages/backend/test/resources/192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
Binary file not shown.
Before Width: | Height: | Size: 463 KiB |
@ -83,21 +83,21 @@ describe('FileInfoService', () => {
|
|||||||
|
|
||||||
describe('IMAGE', () => {
|
describe('IMAGE', () => {
|
||||||
test('Generic JPEG', async () => {
|
test('Generic JPEG', async () => {
|
||||||
const path = `${resources}/Lenna.jpg`;
|
const path = `${resources}/192.jpg`;
|
||||||
const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any;
|
const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any;
|
||||||
delete info.warnings;
|
delete info.warnings;
|
||||||
delete info.blurhash;
|
delete info.blurhash;
|
||||||
delete info.sensitive;
|
delete info.sensitive;
|
||||||
delete info.porn;
|
delete info.porn;
|
||||||
assert.deepStrictEqual(info, {
|
assert.deepStrictEqual(info, {
|
||||||
size: 25360,
|
size: 5131,
|
||||||
md5: '091b3f259662aa31e2ffef4519951168',
|
md5: '8c9ed0677dd2b8f9f7472c3af247e5e3',
|
||||||
type: {
|
type: {
|
||||||
mime: 'image/jpeg',
|
mime: 'image/jpeg',
|
||||||
ext: 'jpg',
|
ext: 'jpg',
|
||||||
},
|
},
|
||||||
width: 512,
|
width: 192,
|
||||||
height: 512,
|
height: 192,
|
||||||
orientation: undefined,
|
orientation: undefined,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
|
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import { jest } from '@jest/globals';
|
import { jest } from '@jest/globals';
|
||||||
import { ModuleMocker } from 'jest-mock';
|
import { ModuleMocker } from 'jest-mock';
|
||||||
import { Test } from '@nestjs/testing';
|
import { Test } from '@nestjs/testing';
|
||||||
@ -29,7 +30,6 @@ import { secureRndstr } from '@/misc/secure-rndstr.js';
|
|||||||
import { NotificationService } from '@/core/NotificationService.js';
|
import { NotificationService } from '@/core/NotificationService.js';
|
||||||
import { RoleCondFormulaValue } from '@/models/Role.js';
|
import { RoleCondFormulaValue } from '@/models/Role.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { sleep } from '../utils.js';
|
|
||||||
import type { TestingModule } from '@nestjs/testing';
|
import type { TestingModule } from '@nestjs/testing';
|
||||||
import type { MockFunctionMetadata } from 'jest-mock';
|
import type { MockFunctionMetadata } from 'jest-mock';
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ describe('RoleService', () => {
|
|||||||
|
|
||||||
// ストリーミング経由で反映されるまでちょっと待つ
|
// ストリーミング経由で反映されるまでちょっと待つ
|
||||||
clock.uninstall();
|
clock.uninstall();
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const resultAfter25hAgain = await roleService.getUserPolicies(user.id);
|
const resultAfter25hAgain = await roleService.getUserPolicies(user.id);
|
||||||
expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true);
|
expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true);
|
||||||
@ -807,7 +807,7 @@ describe('RoleService', () => {
|
|||||||
await roleService.assign(user.id, role.id);
|
await roleService.assign(user.id, role.id);
|
||||||
|
|
||||||
clock.uninstall();
|
clock.uninstall();
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const assignments = await roleAssignmentsRepository.find({
|
const assignments = await roleAssignmentsRepository.find({
|
||||||
where: {
|
where: {
|
||||||
@ -835,7 +835,7 @@ describe('RoleService', () => {
|
|||||||
await roleService.assign(user.id, role.id);
|
await roleService.assign(user.id, role.id);
|
||||||
|
|
||||||
clock.uninstall();
|
clock.uninstall();
|
||||||
await sleep(100);
|
await setTimeout(100);
|
||||||
|
|
||||||
const assignments = await roleAssignmentsRepository.find({
|
const assignments = await roleAssignmentsRepository.find({
|
||||||
where: {
|
where: {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals';
|
import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { MiUser } from '@/models/User.js';
|
import { MiUser } from '@/models/User.js';
|
||||||
@ -16,7 +17,7 @@ import { DI } from '@/di-symbols.js';
|
|||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
import { LoggerService } from '@/core/LoggerService.js';
|
import { LoggerService } from '@/core/LoggerService.js';
|
||||||
import { SystemWebhookService } from '@/core/SystemWebhookService.js';
|
import { SystemWebhookService } from '@/core/SystemWebhookService.js';
|
||||||
import { randomString, sleep } from '../utils.js';
|
import { randomString } from '../utils.js';
|
||||||
|
|
||||||
describe('SystemWebhookService', () => {
|
describe('SystemWebhookService', () => {
|
||||||
let app: TestingModule;
|
let app: TestingModule;
|
||||||
@ -358,7 +359,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks).toEqual([webhook]);
|
expect(fetchedWebhooks).toEqual([webhook]);
|
||||||
@ -377,7 +378,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks).toEqual([]);
|
expect(fetchedWebhooks).toEqual([]);
|
||||||
@ -407,7 +408,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks).toEqual([webhook2]);
|
expect(fetchedWebhooks).toEqual([webhook2]);
|
||||||
@ -434,7 +435,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks.length).toEqual(0);
|
expect(fetchedWebhooks.length).toEqual(0);
|
||||||
@ -457,7 +458,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks).toEqual([webhook2]);
|
expect(fetchedWebhooks).toEqual([webhook2]);
|
||||||
@ -481,7 +482,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks.length).toEqual(0);
|
expect(fetchedWebhooks.length).toEqual(0);
|
||||||
@ -504,7 +505,7 @@ describe('SystemWebhookService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// redisでの配信経由で更新されるのでちょっと待つ
|
// redisでの配信経由で更新されるのでちょっと待つ
|
||||||
await sleep(500);
|
await setTimeout(500);
|
||||||
|
|
||||||
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
const fetchedWebhooks = await service.fetchActiveSystemWebhooks();
|
||||||
expect(fetchedWebhooks.length).toEqual(0);
|
expect(fetchedWebhooks.length).toEqual(0);
|
||||||
|
@ -297,7 +297,7 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO
|
|||||||
body: misskey.entities.DriveFile | null
|
body: misskey.entities.DriveFile | null
|
||||||
}> => {
|
}> => {
|
||||||
const absPath = path == null
|
const absPath = path == null
|
||||||
? new URL('resources/Lenna.jpg', import.meta.url)
|
? new URL('resources/192.jpg', import.meta.url)
|
||||||
: isAbsolute(path.toString())
|
: isAbsolute(path.toString())
|
||||||
? new URL(path)
|
? new URL(path)
|
||||||
: new URL(path, new URL('resources/', import.meta.url));
|
: new URL(path, new URL('resources/', import.meta.url));
|
||||||
@ -605,14 +605,6 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) {
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sleep(msec: number) {
|
|
||||||
return new Promise<void>(res => {
|
|
||||||
setTimeout(() => {
|
|
||||||
res();
|
|
||||||
}, msec);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function sendEnvUpdateRequest(params: { key: string, value?: string }) {
|
export async function sendEnvUpdateRequest(params: { key: string, value?: string }) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`http://localhost:${port + 1000}/env`,
|
`http://localhost:${port + 1000}/env`,
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: {
|
|
||||||
'node': false,
|
|
||||||
},
|
|
||||||
parser: 'vue-eslint-parser',
|
|
||||||
parserOptions: {
|
|
||||||
'parser': '@typescript-eslint/parser',
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
extraFileExtensions: ['.vue'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../shared/.eslintrc.js',
|
|
||||||
'plugin:vue/vue3-recommended',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/no-empty-interface': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
'allowSingleExtends': true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため
|
|
||||||
// e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため
|
|
||||||
'id-denylist': ['error', 'window', 'e'],
|
|
||||||
'no-shadow': ['warn'],
|
|
||||||
'vue/attributes-order': ['error', {
|
|
||||||
'alphabetical': false,
|
|
||||||
}],
|
|
||||||
'vue/no-use-v-if-with-v-for': ['error', {
|
|
||||||
'allowUsingIterationVar': false,
|
|
||||||
}],
|
|
||||||
'vue/no-ref-as-operand': 'error',
|
|
||||||
'vue/no-multi-spaces': ['error', {
|
|
||||||
'ignoreProperties': false,
|
|
||||||
}],
|
|
||||||
'vue/no-v-html': 'warn',
|
|
||||||
'vue/order-in-components': 'error',
|
|
||||||
'vue/html-indent': ['warn', 'tab', {
|
|
||||||
'attribute': 1,
|
|
||||||
'baseIndent': 0,
|
|
||||||
'closeBracket': 0,
|
|
||||||
'alignAttributesVertically': true,
|
|
||||||
'ignores': [],
|
|
||||||
}],
|
|
||||||
'vue/html-closing-bracket-spacing': ['warn', {
|
|
||||||
'startTag': 'never',
|
|
||||||
'endTag': 'never',
|
|
||||||
'selfClosingTag': 'never',
|
|
||||||
}],
|
|
||||||
'vue/multi-word-component-names': 'warn',
|
|
||||||
'vue/require-v-for-key': 'warn',
|
|
||||||
'vue/no-unused-components': 'warn',
|
|
||||||
'vue/no-unused-vars': 'warn',
|
|
||||||
'vue/no-dupe-keys': 'warn',
|
|
||||||
'vue/valid-v-for': 'warn',
|
|
||||||
'vue/return-in-computed-property': 'warn',
|
|
||||||
'vue/no-setup-props-reactivity-loss': 'warn',
|
|
||||||
'vue/max-attributes-per-line': 'off',
|
|
||||||
'vue/html-self-closing': 'off',
|
|
||||||
'vue/singleline-html-element-content-newline': 'off',
|
|
||||||
'vue/v-on-event-hyphenation': ['error', 'never', { autofix: true }],
|
|
||||||
'vue/attribute-hyphenation': ['error', 'never'],
|
|
||||||
},
|
|
||||||
globals: {
|
|
||||||
// Node.js
|
|
||||||
'module': false,
|
|
||||||
'require': false,
|
|
||||||
'__dirname': false,
|
|
||||||
|
|
||||||
// Misskey
|
|
||||||
'_DEV_': false,
|
|
||||||
'_LANGS_': false,
|
|
||||||
'_VERSION_': false,
|
|
||||||
'_ENV_': false,
|
|
||||||
'_PERF_PREFIX_': false,
|
|
||||||
'_DATA_TRANSFER_DRIVE_FILE_': false,
|
|
||||||
'_DATA_TRANSFER_DRIVE_FOLDER_': false,
|
|
||||||
'_DATA_TRANSFER_DECK_COLUMN_': false,
|
|
||||||
},
|
|
||||||
};
|
|
@ -47,7 +47,6 @@ await fs.readFile(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, ''))
|
.map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, ''))
|
||||||
.map((path) => (path.startsWith('.') ? path : `./${path}`))
|
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
micromatch(Array.from(modules), [
|
micromatch(Array.from(modules), [
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FORCE_REMOUNT } from '@storybook/core-events';
|
import { FORCE_RE_RENDER, FORCE_REMOUNT } from '@storybook/core-events';
|
||||||
import { addons } from '@storybook/preview-api';
|
import { addons } from '@storybook/preview-api';
|
||||||
import { type Preview, setup } from '@storybook/vue3';
|
import { type Preview, setup } from '@storybook/vue3';
|
||||||
import isChromatic from 'chromatic/isChromatic';
|
import isChromatic from 'chromatic/isChromatic';
|
||||||
@ -16,7 +16,7 @@ import '../src/style.scss';
|
|||||||
|
|
||||||
const appInitialized = Symbol();
|
const appInitialized = Symbol();
|
||||||
|
|
||||||
let lastStory = null;
|
let lastStory: string | null = null;
|
||||||
let moduleInitialized = false;
|
let moduleInitialized = false;
|
||||||
let unobserve = () => {};
|
let unobserve = () => {};
|
||||||
let misskeyOS = null;
|
let misskeyOS = null;
|
||||||
@ -110,7 +110,7 @@ const preview = {
|
|||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
Promise.all([resetIndexedDBPromise, resetDefaultStorePromise]).then(() => {
|
Promise.all([resetIndexedDBPromise, resetDefaultStorePromise]).then(() => {
|
||||||
initLocalStorage();
|
initLocalStorage();
|
||||||
channel.emit(FORCE_REMOUNT, { storyId: context.id });
|
channel.emit(FORCE_RE_RENDER, { storyId: context.id });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const story = Story();
|
const story = Story();
|
||||||
|
95
packages/frontend/eslint.config.js
Normal file
95
packages/frontend/eslint.config.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import globals from 'globals';
|
||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import parser from 'vue-eslint-parser';
|
||||||
|
import pluginVue from 'eslint-plugin-vue';
|
||||||
|
import pluginMisskey from '@misskey-dev/eslint-plugin';
|
||||||
|
import sharedConfig from '../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
files: ['src/**/*.vue'],
|
||||||
|
...pluginMisskey.configs.typescript,
|
||||||
|
},
|
||||||
|
...pluginVue.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
files: ['src/**/*.{ts,vue}'],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...Object.fromEntries(Object.entries(globals.node).map(([key]) => [key, 'off'])),
|
||||||
|
...globals.browser,
|
||||||
|
|
||||||
|
// Node.js
|
||||||
|
module: false,
|
||||||
|
require: false,
|
||||||
|
__dirname: false,
|
||||||
|
|
||||||
|
// Misskey
|
||||||
|
_DEV_: false,
|
||||||
|
_LANGS_: false,
|
||||||
|
_VERSION_: false,
|
||||||
|
_ENV_: false,
|
||||||
|
_PERF_PREFIX_: false,
|
||||||
|
_DATA_TRANSFER_DRIVE_FILE_: false,
|
||||||
|
_DATA_TRANSFER_DRIVE_FOLDER_: false,
|
||||||
|
_DATA_TRANSFER_DECK_COLUMN_: false,
|
||||||
|
},
|
||||||
|
parser,
|
||||||
|
parserOptions: {
|
||||||
|
extraFileExtensions: ['.vue'],
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-empty-interface': ['error', {
|
||||||
|
allowSingleExtends: true,
|
||||||
|
}],
|
||||||
|
// window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため
|
||||||
|
// e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため
|
||||||
|
'id-denylist': ['error', 'window', 'e'],
|
||||||
|
'no-shadow': ['warn'],
|
||||||
|
'vue/attributes-order': ['error', {
|
||||||
|
alphabetical: false,
|
||||||
|
}],
|
||||||
|
'vue/no-use-v-if-with-v-for': ['error', {
|
||||||
|
allowUsingIterationVar: false,
|
||||||
|
}],
|
||||||
|
'vue/no-ref-as-operand': 'error',
|
||||||
|
'vue/no-multi-spaces': ['error', {
|
||||||
|
ignoreProperties: false,
|
||||||
|
}],
|
||||||
|
'vue/no-v-html': 'warn',
|
||||||
|
'vue/order-in-components': 'error',
|
||||||
|
'vue/html-indent': ['warn', 'tab', {
|
||||||
|
attribute: 1,
|
||||||
|
baseIndent: 0,
|
||||||
|
closeBracket: 0,
|
||||||
|
alignAttributesVertically: true,
|
||||||
|
ignores: [],
|
||||||
|
}],
|
||||||
|
'vue/html-closing-bracket-spacing': ['warn', {
|
||||||
|
startTag: 'never',
|
||||||
|
endTag: 'never',
|
||||||
|
selfClosingTag: 'never',
|
||||||
|
}],
|
||||||
|
'vue/multi-word-component-names': 'warn',
|
||||||
|
'vue/require-v-for-key': 'warn',
|
||||||
|
'vue/no-unused-components': 'warn',
|
||||||
|
'vue/no-unused-vars': 'warn',
|
||||||
|
'vue/no-dupe-keys': 'warn',
|
||||||
|
'vue/valid-v-for': 'warn',
|
||||||
|
'vue/return-in-computed-property': 'warn',
|
||||||
|
'vue/no-setup-props-reactivity-loss': 'warn',
|
||||||
|
'vue/max-attributes-per-line': 'off',
|
||||||
|
'vue/html-self-closing': 'off',
|
||||||
|
'vue/singleline-html-element-content-newline': 'off',
|
||||||
|
'vue/v-on-event-hyphenation': ['error', 'never', {
|
||||||
|
autofix: true,
|
||||||
|
}],
|
||||||
|
'vue/attribute-hyphenation': ['error', 'never'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -22,24 +22,24 @@
|
|||||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||||
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
||||||
"@rollup/plugin-json": "6.1.0",
|
"@rollup/plugin-json": "6.1.0",
|
||||||
"@rollup/plugin-replace": "5.0.5",
|
"@rollup/plugin-replace": "5.0.7",
|
||||||
"@rollup/pluginutils": "5.1.0",
|
"@rollup/pluginutils": "5.1.0",
|
||||||
"@syuilo/aiscript": "0.18.0",
|
"@syuilo/aiscript": "0.18.0",
|
||||||
"@tabler/icons-webfont": "3.3.0",
|
"@tabler/icons-webfont": "3.3.0",
|
||||||
"@twemoji/parser": "15.1.1",
|
"@twemoji/parser": "15.1.1",
|
||||||
"@vitejs/plugin-vue": "5.0.4",
|
"@vitejs/plugin-vue": "5.0.5",
|
||||||
"@vue/compiler-sfc": "3.4.26",
|
"@vue/compiler-sfc": "3.4.31",
|
||||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.9",
|
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.9",
|
||||||
"astring": "1.8.6",
|
"astring": "1.8.6",
|
||||||
"broadcast-channel": "7.0.0",
|
"broadcast-channel": "7.0.0",
|
||||||
"buraha": "0.0.1",
|
"buraha": "0.0.1",
|
||||||
"canvas-confetti": "1.9.3",
|
"canvas-confetti": "1.9.3",
|
||||||
"chart.js": "4.4.2",
|
"chart.js": "4.4.3",
|
||||||
"chartjs-adapter-date-fns": "3.0.0",
|
"chartjs-adapter-date-fns": "3.0.0",
|
||||||
"chartjs-chart-matrix": "2.0.1",
|
"chartjs-chart-matrix": "2.0.1",
|
||||||
"chartjs-plugin-gradient": "0.6.1",
|
"chartjs-plugin-gradient": "0.6.1",
|
||||||
"chartjs-plugin-zoom": "2.0.1",
|
"chartjs-plugin-zoom": "2.0.1",
|
||||||
"chromatic": "11.3.0",
|
"chromatic": "11.5.4",
|
||||||
"compare-versions": "6.1.0",
|
"compare-versions": "6.1.0",
|
||||||
"cropperjs": "2.0.0-beta.5",
|
"cropperjs": "2.0.0-beta.5",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
@ -55,89 +55,87 @@
|
|||||||
"misskey-bubble-game": "workspace:*",
|
"misskey-bubble-game": "workspace:*",
|
||||||
"misskey-js": "workspace:*",
|
"misskey-js": "workspace:*",
|
||||||
"misskey-reversi": "workspace:*",
|
"misskey-reversi": "workspace:*",
|
||||||
"photoswipe": "5.4.3",
|
"photoswipe": "5.4.4",
|
||||||
"punycode": "2.3.1",
|
"punycode": "2.3.1",
|
||||||
"rollup": "4.17.2",
|
"rollup": "4.18.0",
|
||||||
"sanitize-html": "2.13.0",
|
"sanitize-html": "2.13.0",
|
||||||
"sass": "1.76.0",
|
"sass": "1.77.6",
|
||||||
"shiki": "1.4.0",
|
"shiki": "1.10.0",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.164.1",
|
"three": "0.165.0",
|
||||||
"throttle-debounce": "5.0.0",
|
"throttle-debounce": "5.0.2",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tsc-alias": "1.8.8",
|
"tsc-alias": "1.8.10",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "5.5.2",
|
"typescript": "5.5.3",
|
||||||
"uuid": "9.0.1",
|
"uuid": "10.0.0",
|
||||||
"v-code-diff": "1.11.0",
|
"v-code-diff": "1.12.0",
|
||||||
"vite": "5.2.11",
|
"vite": "5.3.2",
|
||||||
"vue": "3.4.26",
|
"vue": "3.4.31",
|
||||||
"vuedraggable": "next"
|
"vuedraggable": "next"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
|
||||||
"@misskey-dev/summaly": "5.1.0",
|
"@misskey-dev/summaly": "5.1.0",
|
||||||
"@storybook/addon-actions": "8.0.9",
|
"@storybook/addon-actions": "8.1.11",
|
||||||
"@storybook/addon-essentials": "8.0.9",
|
"@storybook/addon-essentials": "8.1.11",
|
||||||
"@storybook/addon-interactions": "8.0.9",
|
"@storybook/addon-interactions": "8.1.11",
|
||||||
"@storybook/addon-links": "8.0.9",
|
"@storybook/addon-links": "8.1.11",
|
||||||
"@storybook/addon-mdx-gfm": "8.0.9",
|
"@storybook/addon-mdx-gfm": "8.1.11",
|
||||||
"@storybook/addon-storysource": "8.0.9",
|
"@storybook/addon-storysource": "8.1.11",
|
||||||
"@storybook/blocks": "8.0.9",
|
"@storybook/blocks": "8.1.11",
|
||||||
"@storybook/components": "8.0.9",
|
"@storybook/components": "8.1.11",
|
||||||
"@storybook/core-events": "8.0.9",
|
"@storybook/core-events": "8.1.11",
|
||||||
"@storybook/manager-api": "8.0.9",
|
"@storybook/manager-api": "8.1.11",
|
||||||
"@storybook/preview-api": "8.0.9",
|
"@storybook/preview-api": "8.1.11",
|
||||||
"@storybook/react": "8.0.9",
|
"@storybook/react": "8.1.11",
|
||||||
"@storybook/react-vite": "8.0.9",
|
"@storybook/react-vite": "8.1.11",
|
||||||
"@storybook/test": "8.0.9",
|
"@storybook/test": "8.1.11",
|
||||||
"@storybook/theming": "8.0.9",
|
"@storybook/theming": "8.1.11",
|
||||||
"@storybook/types": "8.0.9",
|
"@storybook/types": "8.1.11",
|
||||||
"@storybook/vue3": "8.0.9",
|
"@storybook/vue3": "8.1.11",
|
||||||
"@storybook/vue3-vite": "8.0.9",
|
"@storybook/vue3-vite": "8.1.11",
|
||||||
"@testing-library/vue": "8.0.3",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/escape-regexp": "0.0.3",
|
"@types/escape-regexp": "0.0.3",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"@types/matter-js": "0.19.6",
|
"@types/matter-js": "0.19.6",
|
||||||
"@types/micromatch": "4.0.7",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.14.9",
|
||||||
"@types/punycode": "2.1.4",
|
"@types/punycode": "2.1.4",
|
||||||
"@types/sanitize-html": "2.11.0",
|
"@types/sanitize-html": "2.11.0",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@types/throttle-debounce": "5.0.2",
|
"@types/throttle-debounce": "5.0.2",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@types/uuid": "9.0.8",
|
"@types/uuid": "10.0.0",
|
||||||
"@types/ws": "8.5.10",
|
"@types/ws": "8.5.10",
|
||||||
"@typescript-eslint/eslint-plugin": "7.7.1",
|
"@typescript-eslint/eslint-plugin": "7.15.0",
|
||||||
"@typescript-eslint/parser": "7.7.1",
|
"@typescript-eslint/parser": "7.15.0",
|
||||||
"@vitest/coverage-v8": "0.34.6",
|
"@vitest/coverage-v8": "1.6.0",
|
||||||
"@vue/runtime-core": "3.4.26",
|
"@vue/runtime-core": "3.4.31",
|
||||||
"acorn": "8.11.3",
|
"acorn": "8.12.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "13.8.1",
|
"cypress": "13.13.0",
|
||||||
"eslint": "8.57.0",
|
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"eslint-plugin-vue": "9.25.0",
|
"eslint-plugin-vue": "9.26.0",
|
||||||
"fast-glob": "3.3.2",
|
"fast-glob": "3.3.2",
|
||||||
"happy-dom": "10.0.3",
|
"happy-dom": "10.0.3",
|
||||||
"intersection-observer": "0.12.2",
|
"intersection-observer": "0.12.2",
|
||||||
"micromatch": "4.0.5",
|
"micromatch": "4.0.7",
|
||||||
"msw": "2.2.14",
|
"msw": "2.3.1",
|
||||||
"msw-storybook-addon": "2.0.1",
|
"msw-storybook-addon": "2.0.2",
|
||||||
"nodemon": "3.1.0",
|
"nodemon": "3.1.4",
|
||||||
"prettier": "3.2.5",
|
"prettier": "3.3.2",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"start-server-and-test": "2.0.3",
|
"start-server-and-test": "2.0.4",
|
||||||
"storybook": "8.0.9",
|
"storybook": "8.1.11",
|
||||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
"vitest": "0.34.6",
|
"vitest": "1.6.0",
|
||||||
"vitest-fetch-mock": "0.2.2",
|
"vitest-fetch-mock": "0.2.2",
|
||||||
"vue-component-type-helpers": "2.0.16",
|
"vue-component-type-helpers": "2.0.24",
|
||||||
"vue-eslint-parser": "9.4.2",
|
"vue-eslint-parser": "9.4.3",
|
||||||
"vue-tsc": "2.0.16"
|
"vue-tsc": "2.0.24"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,10 +197,12 @@ export async function login(token: Account['token'], redirect?: string) {
|
|||||||
if (embedPage) return;
|
if (embedPage) return;
|
||||||
|
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
|
||||||
success: false,
|
success: false,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
if (_DEV_) console.log('logging as token ', token);
|
if (_DEV_) console.log('logging as token ', token);
|
||||||
const me = await fetchAccount(token, undefined, true)
|
const me = await fetchAccount(token, undefined, true)
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
@ -236,21 +238,23 @@ export async function openAccountMenu(opts: {
|
|||||||
if (!$i) return;
|
if (!$i) return;
|
||||||
|
|
||||||
function showSigninDialog() {
|
function showSigninDialog() {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
||||||
done: res => {
|
done: res => {
|
||||||
addAccount(res.id, res.i);
|
addAccount(res.id, res.i);
|
||||||
success();
|
success();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount() {
|
function createAccount() {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
||||||
done: res => {
|
done: res => {
|
||||||
addAccount(res.id, res.i);
|
addAccount(res.id, res.i);
|
||||||
switchAccountWithToken(res.i);
|
switchAccountWithToken(res.i);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchAccount(account: Misskey.entities.UserDetailed) {
|
async function switchAccount(account: Misskey.entities.UserDetailed) {
|
||||||
|
@ -35,7 +35,9 @@ export async function mainBoot() {
|
|||||||
emojiPicker.init();
|
emojiPicker.init();
|
||||||
|
|
||||||
if (isClientUpdated && $i) {
|
if (isClientUpdated && $i) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = useStream();
|
const stream = useStream();
|
||||||
@ -108,22 +110,28 @@ export async function mainBoot() {
|
|||||||
|
|
||||||
defaultStore.loaded.then(() => {
|
defaultStore.loaded.then(() => {
|
||||||
if (defaultStore.state.accountSetupWizard !== -1) {
|
if (defaultStore.state.accountSetupWizard !== -1) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) {
|
for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.on('announcementCreated', (ev) => {
|
stream.on('announcementCreated', (ev) => {
|
||||||
const announcement = ev.announcement;
|
const announcement = ev.announcement;
|
||||||
if (announcement.display === 'dialog') {
|
if (announcement.display === 'dialog') {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -247,13 +255,17 @@ export async function mainBoot() {
|
|||||||
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
||||||
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
|
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
|
||||||
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
||||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('Notification' in window) {
|
if ('Notification' in window) {
|
||||||
|
@ -12,14 +12,12 @@ import { expect, userEvent, within } from '@storybook/test';
|
|||||||
import { channel } from '../../.storybook/fakes.js';
|
import { channel } from '../../.storybook/fakes.js';
|
||||||
import { commonHandlers } from '../../.storybook/mocks.js';
|
import { commonHandlers } from '../../.storybook/mocks.js';
|
||||||
import MkChannelFollowButton from './MkChannelFollowButton.vue';
|
import MkChannelFollowButton from './MkChannelFollowButton.vue';
|
||||||
import { semaphore } from '@/scripts/test-utils.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
||||||
function sleep(ms: number) {
|
function sleep(ms: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = semaphore();
|
|
||||||
export const Default = {
|
export const Default = {
|
||||||
render(args) {
|
render(args) {
|
||||||
return {
|
return {
|
||||||
@ -46,17 +44,13 @@ export const Default = {
|
|||||||
full: true,
|
full: true,
|
||||||
},
|
},
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }) {
|
||||||
await s.acquire();
|
|
||||||
await sleep(1000);
|
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
||||||
await expect(buttonElement).toHaveTextContent(i18n.ts.follow);
|
await expect(buttonElement).toHaveTextContent(i18n.ts.follow);
|
||||||
await userEvent.click(buttonElement);
|
await userEvent.click(buttonElement);
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
await expect(buttonElement).toHaveTextContent(i18n.ts.unfollow);
|
await expect(buttonElement).toHaveTextContent(i18n.ts.unfollow);
|
||||||
await sleep(100);
|
|
||||||
await userEvent.click(buttonElement);
|
await userEvent.click(buttonElement);
|
||||||
s.release();
|
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import { StoryObj } from '@storybook/vue3';
|
import { StoryObj } from '@storybook/vue3';
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { expect, within } from '@storybook/test';
|
import { expect, userEvent, within } from '@storybook/test';
|
||||||
import { commonHandlers } from '../../.storybook/mocks.js';
|
import { commonHandlers } from '../../.storybook/mocks.js';
|
||||||
import MkClickerGame from './MkClickerGame.vue';
|
import MkClickerGame from './MkClickerGame.vue';
|
||||||
|
|
||||||
@ -41,12 +41,10 @@ export const Default = {
|
|||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const count = canvas.getByTestId('count');
|
const count = canvas.getByTestId('count');
|
||||||
// NOTE: flaky なので N/A も通しておく
|
await expect(count).toHaveTextContent('0');
|
||||||
await expect(count).toHaveTextContent(/^(0|N\/A)$/);
|
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
||||||
// FIXME: flaky
|
await userEvent.click(buttonElement);
|
||||||
// const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
await expect(count).toHaveTextContent('1');
|
||||||
// await userEvent.click(buttonElement);
|
|
||||||
// await expect(count).toHaveTextContent('1');
|
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
|
@ -35,7 +35,9 @@ const prevCookies = ref(0);
|
|||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: MouseEvent) {
|
||||||
const x = ev.clientX;
|
const x = ev.clientX;
|
||||||
const y = ev.clientY;
|
const y = ev.clientY;
|
||||||
os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
saveData.value!.cookies++;
|
saveData.value!.cookies++;
|
||||||
saveData.value!.totalCookies++;
|
saveData.value!.totalCookies++;
|
||||||
|
@ -11,13 +11,6 @@ import { expect, userEvent, within } from '@storybook/test';
|
|||||||
import { file } from '../../.storybook/fakes.js';
|
import { file } from '../../.storybook/fakes.js';
|
||||||
import MkCwButton from './MkCwButton.vue';
|
import MkCwButton from './MkCwButton.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { semaphore } from '@/scripts/test-utils.js';
|
|
||||||
|
|
||||||
function sleep(ms: number) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
const s = semaphore();
|
|
||||||
|
|
||||||
export const Default = {
|
export const Default = {
|
||||||
render(args) {
|
render(args) {
|
||||||
@ -54,8 +47,6 @@ export const Default = {
|
|||||||
text: 'Some CW content',
|
text: 'Some CW content',
|
||||||
},
|
},
|
||||||
async play({ canvasElement }) {
|
async play({ canvasElement }) {
|
||||||
await s.acquire();
|
|
||||||
await sleep(1000);
|
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
|
||||||
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.show);
|
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.show);
|
||||||
@ -63,7 +54,6 @@ export const Default = {
|
|||||||
await userEvent.click(buttonElement);
|
await userEvent.click(buttonElement);
|
||||||
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.hide);
|
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.hide);
|
||||||
await userEvent.click(buttonElement);
|
await userEvent.click(buttonElement);
|
||||||
s.release();
|
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
chromatic: {
|
chromatic: {
|
||||||
|
@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) {
|
|||||||
text: i18n.ts.openInWindow,
|
text: i18n.ts.openInWindow,
|
||||||
icon: 'ti ti-app-window',
|
icon: 'ti ti-app-window',
|
||||||
action: () => {
|
action: () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
|
||||||
initialFolder: props.folder,
|
initialFolder: props.folder,
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}, { type: 'divider' }, {
|
}, { type: 'divider' }, {
|
||||||
text: i18n.ts.rename,
|
text: i18n.ts.rename,
|
||||||
|
@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = getKey(emoji);
|
const key = getKey(emoji);
|
||||||
|
@ -37,11 +37,13 @@ const el = ref<HTMLElement | { $el: HTMLElement }>();
|
|||||||
|
|
||||||
if (isEnabledUrlPreview.value) {
|
if (isEnabledUrlPreview.value) {
|
||||||
useTooltip(el, (showing) => {
|
useTooltip(el, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
url: props.url,
|
url: props.url,
|
||||||
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -355,12 +355,14 @@ if (!props.mock && !inEmbedPage) {
|
|||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkUsersTooltip, {
|
const { dispose } = os.popup(MkUsersTooltip, {
|
||||||
showing,
|
showing,
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.renoteCount,
|
count: appearNote.value.renoteCount,
|
||||||
targetElement: renoteButton.value,
|
targetElement: renoteButton.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||||
@ -375,13 +377,15 @@ if (!props.mock && !inEmbedPage) {
|
|||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkReactionsViewerDetails, {
|
const { dispose } = os.popup(MkReactionsViewerDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.reactionCount,
|
count: appearNote.value.reactionCount,
|
||||||
targetElement: reactButton.value!,
|
targetElement: reactButton.value!,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +433,9 @@ function react(viaKeyboard = false): void {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blur();
|
blur();
|
||||||
|
@ -400,12 +400,14 @@ useTooltip(renoteButton, async (showing) => {
|
|||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkUsersTooltip, {
|
const { dispose } = os.popup(MkUsersTooltip, {
|
||||||
showing,
|
showing,
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.renoteCount,
|
count: appearNote.value.renoteCount,
|
||||||
targetElement: renoteButton.value,
|
targetElement: renoteButton.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||||
@ -420,13 +422,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
|||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkReactionsViewerDetails, {
|
const { dispose } = os.popup(MkReactionsViewerDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.reactionCount,
|
count: appearNote.value.reactionCount,
|
||||||
targetElement: reactButton.value!,
|
targetElement: reactButton.value!,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,7 +471,9 @@ function react(viaKeyboard = false): void {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blur();
|
blur();
|
||||||
|
@ -463,7 +463,7 @@ function setVisibility() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
||||||
currentVisibility: visibility.value,
|
currentVisibility: visibility.value,
|
||||||
isSilenced: $i.isSilenced,
|
isSilenced: $i.isSilenced,
|
||||||
localOnly: localOnly.value,
|
localOnly: localOnly.value,
|
||||||
@ -476,7 +476,8 @@ function setVisibility() {
|
|||||||
defaultStore.set('visibility', visibility.value);
|
defaultStore.set('visibility', visibility.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleLocalOnly() {
|
async function toggleLocalOnly() {
|
||||||
@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0");
|
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0');
|
||||||
const file = new File([paste], `${fileName}.txt`, { type: "text/plain" });
|
const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
|
||||||
upload(file, `${fileName}.txt`);
|
upload(file, `${fileName}.txt`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ async function rename(file) {
|
|||||||
async function describe(file) {
|
async function describe(file) {
|
||||||
if (mock) return;
|
if (mock) return;
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.comment !== null ? file.comment : '',
|
default: file.comment !== null ? file.comment : '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
@ -121,7 +121,8 @@ async function describe(file) {
|
|||||||
file.comment = comment;
|
file.comment = comment;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function crop(file: Misskey.entities.DriveFile): Promise<void> {
|
async function crop(file: Misskey.entities.DriveFile): Promise<void> {
|
||||||
|
@ -101,17 +101,19 @@ const steps = computed(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onMousedown = (ev: MouseEvent | TouchEvent) => {
|
function onMousedown(ev: MouseEvent | TouchEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const tooltipShowing = ref(true);
|
const tooltipShowing = ref(true);
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
||||||
showing: tooltipShowing,
|
showing: tooltipShowing,
|
||||||
text: computed(() => {
|
text: computed(() => {
|
||||||
return props.textConverter(finalValue.value);
|
return props.textConverter(finalValue.value);
|
||||||
}),
|
}),
|
||||||
targetElement: thumbEl,
|
targetElement: thumbEl,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
|
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
|
||||||
@ -152,7 +154,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => {
|
|||||||
window.addEventListener('touchmove', onDrag);
|
window.addEventListener('touchmove', onDrag);
|
||||||
window.addEventListener('mouseup', onMouseup, { once: true });
|
window.addEventListener('mouseup', onMouseup, { once: true });
|
||||||
window.addEventListener('touchend', onMouseup, { once: true });
|
window.addEventListener('touchend', onMouseup, { once: true });
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -24,11 +24,13 @@ const elRef = shallowRef();
|
|||||||
|
|
||||||
if (props.withTooltip) {
|
if (props.withTooltip) {
|
||||||
useTooltip(elRef, (showing) => {
|
useTooltip(elRef, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
|
||||||
showing,
|
showing,
|
||||||
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
|
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
|
||||||
targetElement: elRef.value.$el,
|
targetElement: elRef.value.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -115,10 +115,12 @@ async function menu(ev) {
|
|||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
|
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
|
||||||
}),
|
}),
|
||||||
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
@ -130,7 +132,9 @@ function anime() {
|
|||||||
const rect = buttonEl.value.getBoundingClientRect();
|
const rect = buttonEl.value.getBoundingClientRect();
|
||||||
const x = rect.left + 16;
|
const x = rect.left + 16;
|
||||||
const y = rect.top + (buttonEl.value.offsetHeight / 2);
|
const y = rect.top + (buttonEl.value.offsetHeight / 2);
|
||||||
os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {}, 'end');
|
const { dispose } = os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.count, (newCount, oldCount) => {
|
watch(() => props.count, (newCount, oldCount) => {
|
||||||
@ -152,13 +156,15 @@ if (!mock && !inEmbedPage) {
|
|||||||
|
|
||||||
const users = reactions.map(x => x.user);
|
const users = reactions.map(x => x.user);
|
||||||
|
|
||||||
os.popup(XDetails, {
|
const { dispose } = os.popup(XDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: props.reaction,
|
reaction: props.reaction,
|
||||||
users,
|
users,
|
||||||
count: props.count,
|
count: props.count,
|
||||||
targetElement: buttonEl.value,
|
targetElement: buttonEl.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -218,8 +218,9 @@ function loginFailed(err: any): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetPassword(): void {
|
function resetPassword(): void {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -25,15 +25,15 @@ export type MkSystemWebhookResult = {
|
|||||||
|
|
||||||
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
||||||
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
|
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
|
||||||
const res = await os.popup(
|
const { dispose: _dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
||||||
props,
|
props,
|
||||||
{
|
{
|
||||||
submitted: (ev: MkSystemWebhookResult) => {
|
submitted: (ev: MkSystemWebhookResult) => {
|
||||||
resolve({ dispose: res.dispose, result: ev });
|
resolve({ dispose: _dispose, result: ev });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: res.dispose, result: null });
|
resolve({ dispose: _dispose, result: null });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -188,11 +188,13 @@ function adjustTweetHeight(message: any) {
|
|||||||
if (height) tweetHeight.value = height;
|
if (height) tweetHeight.value = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openPlayer = (): void => {
|
function openPlayer(): void {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
|
||||||
url: requestUrl.href,
|
url: requestUrl.href,
|
||||||
|
}, {
|
||||||
|
// TODO
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
(window as any).addEventListener('message', adjustTweetHeight);
|
(window as any).addEventListener('message', adjustTweetHeight);
|
||||||
|
|
||||||
|
@ -176,9 +176,11 @@ function setupComplete() {
|
|||||||
function launchTutorial() {
|
function launchTutorial() {
|
||||||
setupComplete();
|
setupComplete();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
|
||||||
initialPage: 1,
|
initialPage: 1,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,15 +74,19 @@ misskeyApi('stats', {}).then((res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
const { dispose } = os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function signup() {
|
function signup() {
|
||||||
os.popup(XSignupDialog, {
|
const { dispose } = os.popup(XSignupDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev) {
|
function showMenu(ev) {
|
||||||
|
@ -35,12 +35,10 @@ export const Default = {
|
|||||||
// FIXME: 通るけどその後落ちるのでコメントアウト
|
// FIXME: 通るけどその後落ちるのでコメントアウト
|
||||||
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
||||||
await userEvent.pointer({ keys: '[MouseRight]', target: a });
|
await userEvent.pointer({ keys: '[MouseRight]', target: a });
|
||||||
await tick();
|
|
||||||
const menu = canvas.getByRole('menu');
|
const menu = canvas.getByRole('menu');
|
||||||
await expect(menu).toBeInTheDocument();
|
await expect(menu).toBeInTheDocument();
|
||||||
await userEvent.click(a);
|
await userEvent.click(a);
|
||||||
a.blur();
|
a.blur();
|
||||||
await tick();
|
|
||||||
await expect(menu).not.toBeInTheDocument();
|
await expect(menu).not.toBeInTheDocument();
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
|
@ -9,12 +9,6 @@ import { StoryObj } from '@storybook/vue3';
|
|||||||
import MkAd from './MkAd.vue';
|
import MkAd from './MkAd.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
||||||
let lock: Promise<undefined> | undefined;
|
|
||||||
|
|
||||||
function sleep(ms: number) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
render(args) {
|
render(args) {
|
||||||
return {
|
return {
|
||||||
@ -37,20 +31,9 @@ const common = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
async play({ canvasElement, args }) {
|
async play({ canvasElement, args }) {
|
||||||
if (lock) {
|
|
||||||
console.warn('This test is unexpectedly running twice in parallel, fix it!');
|
|
||||||
console.warn('See also: https://github.com/misskey-dev/misskey/issues/11267');
|
|
||||||
await lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolve: (value?: any) => void;
|
|
||||||
lock = new Promise(r => resolve = r);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// NOTE: sleep しないと何故か落ちる
|
|
||||||
await sleep(100);
|
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const a = canvas.getByRole<HTMLAnchorElement>('link');
|
const a = canvas.getByRole<HTMLAnchorElement>('link');
|
||||||
|
// FIXME: 通るけどその後落ちるのでコメントアウト
|
||||||
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
|
||||||
const img = within(a).getByRole('img');
|
const img = within(a).getByRole('img');
|
||||||
await expect(img).toBeInTheDocument();
|
await expect(img).toBeInTheDocument();
|
||||||
@ -83,10 +66,6 @@ const common = {
|
|||||||
await expect(aAgain).toBeInTheDocument();
|
await expect(aAgain).toBeInTheDocument();
|
||||||
const imgAgain = within(aAgain).getByRole('img');
|
const imgAgain = within(aAgain).getByRole('img');
|
||||||
await expect(imgAgain).toBeInTheDocument();
|
await expect(imgAgain).toBeInTheDocument();
|
||||||
} finally {
|
|
||||||
resolve!();
|
|
||||||
lock = undefined;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
args: {
|
args: {
|
||||||
prefer: [],
|
prefer: [],
|
||||||
|
@ -106,12 +106,12 @@ function onClick(ev: MouseEvent) {
|
|||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: customEmojiName.value,
|
name: customEmojiName.value,
|
||||||
}),
|
}),
|
||||||
}, {
|
}, {
|
||||||
anchor: ev.target,
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
|
@ -50,11 +50,13 @@ const el = ref();
|
|||||||
|
|
||||||
if (props.showUrlPreview && isEnabledUrlPreview.value) {
|
if (props.showUrlPreview && isEnabledUrlPreview.value) {
|
||||||
useTooltip(el, (showing) => {
|
useTooltip(el, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
url: props.url,
|
url: props.url,
|
||||||
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,9 @@ export default {
|
|||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
|
|
||||||
popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -51,13 +51,15 @@ export default {
|
|||||||
if (self.text == null) return;
|
if (self.text == null) return;
|
||||||
|
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
||||||
showing,
|
showing,
|
||||||
text: self.text,
|
text: self.text,
|
||||||
asMfm: binding.modifiers.mfm,
|
asMfm: binding.modifiers.mfm,
|
||||||
direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
|
direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
|
||||||
targetElement: el,
|
targetElement: el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
self._close = () => {
|
self._close = () => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
|
@ -35,7 +35,7 @@ export class UserPreview {
|
|||||||
|
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
|
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
q: this.user,
|
q: this.user,
|
||||||
source: this.el,
|
source: this.el,
|
||||||
@ -47,7 +47,8 @@ export class UserPreview {
|
|||||||
window.clearTimeout(this.showTimer);
|
window.clearTimeout(this.showTimer);
|
||||||
this.hideTimer = window.setTimeout(this.close, 500);
|
this.hideTimer = window.setTimeout(this.close, 500);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
this.promise = {
|
this.promise = {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
|
@ -117,11 +117,13 @@ export function promiseDialog<T extends Promise<any>>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
|
// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: success,
|
success: success,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
text: text,
|
text: text,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -167,12 +169,11 @@ type EmitsExtractor<T> = {
|
|||||||
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize<E> : K extends string ? never : K]: T[K];
|
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize<E> : K extends string ? never : K]: T[K];
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function popup<T extends Component>(
|
export function popup<T extends Component>(
|
||||||
component: T,
|
component: T,
|
||||||
props: ComponentProps<T>,
|
props: ComponentProps<T>,
|
||||||
events: ComponentEmit<T> = {} as ComponentEmit<T>,
|
events: ComponentEmit<T> = {} as ComponentEmit<T>,
|
||||||
disposeEvent?: keyof ComponentEmit<T>,
|
): { dispose: () => void } {
|
||||||
): Promise<{ dispose: () => void }> {
|
|
||||||
if (embedPage) return { dispose: () => {} };
|
if (embedPage) return { dispose: () => {} };
|
||||||
|
|
||||||
markRaw(component);
|
markRaw(component);
|
||||||
@ -181,16 +182,13 @@ export async function popup<T extends Component>(
|
|||||||
const dispose = () => {
|
const dispose = () => {
|
||||||
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
|
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
popups.value = popups.value.filter(popup => popup.id !== id);
|
popups.value = popups.value.filter(p => p.id !== id);
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
const state = {
|
const state = {
|
||||||
component,
|
component,
|
||||||
props,
|
props,
|
||||||
events: disposeEvent ? {
|
events,
|
||||||
...events,
|
|
||||||
[disposeEvent]: dispose,
|
|
||||||
} : events,
|
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -202,15 +200,19 @@ export async function popup<T extends Component>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function pageWindow(path: string) {
|
export function pageWindow(path: string) {
|
||||||
popup(MkPageWindow, {
|
const { dispose } = popup(MkPageWindow, {
|
||||||
initialPath: path,
|
initialPath: path,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toast(message: string) {
|
export function toast(message: string) {
|
||||||
popup(MkToast, {
|
const { dispose } = popup(MkToast, {
|
||||||
message,
|
message,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function alert(props: {
|
export function alert(props: {
|
||||||
@ -219,11 +221,12 @@ export function alert(props: {
|
|||||||
text?: string;
|
text?: string;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, props, {
|
const { dispose } = popup(MkDialog, props, {
|
||||||
done: () => {
|
done: () => {
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,14 +238,15 @@ export function confirm(props: {
|
|||||||
cancelText?: string;
|
cancelText?: string;
|
||||||
}): Promise<{ canceled: boolean }> {
|
}): Promise<{ canceled: boolean }> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
...props,
|
...props,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +268,7 @@ export function actions<T extends {
|
|||||||
canceled: false; result: T[number]['value'];
|
canceled: false; result: T[number]['value'];
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
...props,
|
...props,
|
||||||
actions: props.actions.map(a => ({
|
actions: props.actions.map(a => ({
|
||||||
text: a.text,
|
text: a.text,
|
||||||
@ -278,7 +282,8 @@ export function actions<T extends {
|
|||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +331,7 @@ export function inputText(props: {
|
|||||||
canceled: false; result: string | null;
|
canceled: false; result: string | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
@ -341,7 +346,8 @@ export function inputText(props: {
|
|||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +386,7 @@ export function inputNumber(props: {
|
|||||||
canceled: false; result: number | null;
|
canceled: false; result: number | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
@ -393,7 +399,8 @@ export function inputNumber(props: {
|
|||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +415,7 @@ export function inputDate(props: {
|
|||||||
canceled: false; result: Date;
|
canceled: false; result: Date;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
@ -420,7 +427,8 @@ export function inputDate(props: {
|
|||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
|
resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,11 +438,12 @@ export function authenticateDialog(): Promise<{
|
|||||||
canceled: false; result: { password: string; token: string | null; };
|
canceled: false; result: { password: string; token: string | null; };
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkPasswordDialog, {}, {
|
const { dispose } = popup(MkPasswordDialog, {}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
|
resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +488,7 @@ export function select<C = any>(props: {
|
|||||||
canceled: false; result: C | null;
|
canceled: false; result: C | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
select: {
|
select: {
|
||||||
@ -490,7 +499,8 @@ export function select<C = any>(props: {
|
|||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,53 +510,57 @@ export function success(): Promise<void> {
|
|||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: true,
|
success: true,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function waiting(): Promise<void> {
|
export function waiting(): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: false,
|
success: false,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
|
export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
|
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
|
||||||
includeSelf: opts.includeSelf,
|
includeSelf: opts.includeSelf,
|
||||||
localOnly: opts.localOnly,
|
localOnly: opts.localOnly,
|
||||||
}, {
|
}, {
|
||||||
ok: user => {
|
ok: user => {
|
||||||
resolve(user);
|
resolve(user);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
multiple,
|
multiple,
|
||||||
}, {
|
}, {
|
||||||
@ -555,13 +569,14 @@ export async function selectDriveFile(multiple: boolean): Promise<Misskey.entiti
|
|||||||
resolve(files);
|
resolve(files);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
|
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
multiple,
|
multiple,
|
||||||
}, {
|
}, {
|
||||||
@ -570,20 +585,22 @@ export async function selectDriveFolder(multiple: boolean): Promise<Misskey.enti
|
|||||||
resolve(folders);
|
resolve(folders);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
|
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkEmojiPickerDialog, {
|
const { dispose } = popup(MkEmojiPickerDialog, {
|
||||||
src,
|
src,
|
||||||
...opts,
|
...opts,
|
||||||
}, {
|
}, {
|
||||||
done: emoji => {
|
done: emoji => {
|
||||||
resolve(emoji);
|
resolve(emoji);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,7 +609,7 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
|
|||||||
uploadFolder?: string | null;
|
uploadFolder?: string | null;
|
||||||
}): Promise<Misskey.entities.DriveFile> {
|
}): Promise<Misskey.entities.DriveFile> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
|
||||||
file: image,
|
file: image,
|
||||||
aspectRatio: options.aspectRatio,
|
aspectRatio: options.aspectRatio,
|
||||||
uploadFolder: options.uploadFolder,
|
uploadFolder: options.uploadFolder,
|
||||||
@ -600,7 +617,8 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
|
|||||||
ok: x => {
|
ok: x => {
|
||||||
resolve(x);
|
resolve(x);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,8 +629,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
|
|||||||
onClosing?: () => void;
|
onClosing?: () => void;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let dispose;
|
const { dispose } = popup(MkPopupMenu, {
|
||||||
popup(MkPopupMenu, {
|
|
||||||
items,
|
items,
|
||||||
src,
|
src,
|
||||||
width: options?.width,
|
width: options?.width,
|
||||||
@ -626,8 +643,6 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
|
|||||||
closing: () => {
|
closing: () => {
|
||||||
if (options?.onClosing) options.onClosing();
|
if (options?.onClosing) options.onClosing();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -637,8 +652,7 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
|||||||
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let dispose;
|
const { dispose } = popup(MkContextMenu, {
|
||||||
popup(MkContextMenu, {
|
|
||||||
items,
|
items,
|
||||||
ev,
|
ev,
|
||||||
}, {
|
}, {
|
||||||
@ -646,8 +660,6 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
|||||||
resolve();
|
resolve();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -661,14 +673,11 @@ export function post(props: Record<string, any> = {}): Promise<void> {
|
|||||||
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
|
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
|
||||||
// 複数のpost formを開いたときに場合によってはエラーになる
|
// 複数のpost formを開いたときに場合によってはエラーになる
|
||||||
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
|
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
|
||||||
let dispose;
|
const { dispose } = popup(MkPostFormDialog, props, {
|
||||||
popup(MkPostFormDialog, props, {
|
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve();
|
resolve();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -464,16 +464,20 @@ function toggleRoleItem(role) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createAnnouncement() {
|
function createAnnouncement() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editAnnouncement(announcement) {
|
function editAnnouncement(announcement) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.userId, () => {
|
watch(() => props.userId, () => {
|
||||||
|
@ -109,7 +109,7 @@ async function onDeleteButtonClicked(id: string) {
|
|||||||
|
|
||||||
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
||||||
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
|
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
|
||||||
const res = await os.popup(
|
const { dispose: _dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
||||||
{
|
{
|
||||||
mode,
|
mode,
|
||||||
@ -117,10 +117,10 @@ async function showEditor(mode: 'create' | 'edit', id?: string) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
submitted: async () => {
|
submitted: async () => {
|
||||||
resolve({ dispose: res.dispose, needLoad: true });
|
resolve({ dispose: _dispose, needLoad: true });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: res.dispose, needLoad: false });
|
resolve({ dispose: _dispose, needLoad: false });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -129,18 +129,19 @@ const toggleSelect = (emoji) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const add = async (ev: MouseEvent) => {
|
const add = async (ev: MouseEvent) => {
|
||||||
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
if (result.created) {
|
if (result.created) {
|
||||||
emojisPaginationComponent.value.prepend(result.created);
|
emojisPaginationComponent.value.prepend(result.created);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = (emoji) => {
|
const edit = (emoji) => {
|
||||||
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
||||||
emoji: emoji,
|
emoji: emoji,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
@ -153,7 +154,8 @@ const edit = (emoji) => {
|
|||||||
emojisPaginationComponent.value.removeItem(emoji.id);
|
emojisPaginationComponent.value.removeItem(emoji.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const importEmoji = (emoji) => {
|
const importEmoji = (emoji) => {
|
||||||
|
@ -160,7 +160,7 @@ function rename() {
|
|||||||
function describe() {
|
function describe() {
|
||||||
if (!file.value) return;
|
if (!file.value) return;
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.value.comment ?? '',
|
default: file.value.comment ?? '',
|
||||||
file: file.value,
|
file: file.value,
|
||||||
}, {
|
}, {
|
||||||
@ -172,7 +172,8 @@ function describe() {
|
|||||||
await fetch();
|
await fetch();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteFile() {
|
async function deleteFile() {
|
||||||
|
@ -1008,8 +1008,18 @@ function attachGameEvents() {
|
|||||||
const domX = rect.left + (x * viewScale);
|
const domX = rect.left + (x * viewScale);
|
||||||
const domY = rect.top + (y * viewScale);
|
const domY = rect.top + (y * viewScale);
|
||||||
const scoreUnit = getScoreUnit(props.gameMode);
|
const scoreUnit = getScoreUnit(props.gameMode);
|
||||||
os.popup(MkRippleEffect, { x: domX, y: domY }, {}, 'end');
|
|
||||||
os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {}, 'end');
|
{
|
||||||
|
const { dispose } = os.popup(MkRippleEffect, { x: domX, y: domY }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { dispose } = os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (nextMono) {
|
if (nextMono) {
|
||||||
const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
|
const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
|
||||||
|
@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as os from '@/os.js';
|
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import * as os from '@/os.js';
|
||||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
@ -40,12 +40,12 @@ function menu(ev) {
|
|||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: props.emoji.name,
|
name: props.emoji.name,
|
||||||
})
|
}),
|
||||||
}, {
|
}, {
|
||||||
anchor: ev.target,
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
|
@ -44,7 +44,9 @@ async function save() {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.token == null) {
|
if (props.token == null) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {}, 'closed');
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
mainRouter.push('/');
|
mainRouter.push('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -108,9 +108,11 @@ async function registerTOTP(): Promise<void> {
|
|||||||
token: auth.result.token,
|
token: auth.result.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
|
||||||
twoFactorData,
|
twoFactorData,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unregisterTOTP(): Promise<void> {
|
async function unregisterTOTP(): Promise<void> {
|
||||||
|
@ -74,22 +74,24 @@ async function removeAccount(account) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addExistingAccount() {
|
function addExistingAccount() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
||||||
done: async res => {
|
done: async res => {
|
||||||
await addAccounts(res.id, res.i);
|
await addAccounts(res.id, res.i);
|
||||||
os.success();
|
os.success();
|
||||||
init();
|
init();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount() {
|
function createAccount() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
||||||
done: async res => {
|
done: async res => {
|
||||||
await addAccounts(res.id, res.i);
|
await addAccounts(res.id, res.i);
|
||||||
switchAccountWithToken(res.i);
|
switchAccountWithToken(res.i);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchAccount(account: any) {
|
async function switchAccount(account: any) {
|
||||||
|
@ -24,7 +24,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||||||
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||||
|
|
||||||
function generateToken() {
|
function generateToken() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
||||||
done: async result => {
|
done: async result => {
|
||||||
const { name, permissions } = result;
|
const { name, permissions } = result;
|
||||||
const { token } = await misskeyApi('miauth/gen-token', {
|
const { token } = await misskeyApi('miauth/gen-token', {
|
||||||
@ -39,7 +39,8 @@ function generateToken() {
|
|||||||
text: token,
|
text: token,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = computed(() => []);
|
const headerActions = computed(() => []);
|
||||||
|
@ -67,7 +67,7 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function openDecoration(avatarDecoration, index?: number) {
|
function openDecoration(avatarDecoration, index?: number) {
|
||||||
os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
|
||||||
decoration: avatarDecoration,
|
decoration: avatarDecoration,
|
||||||
usingIndex: index,
|
usingIndex: index,
|
||||||
}, {
|
}, {
|
||||||
@ -108,7 +108,8 @@ function openDecoration(avatarDecoration, index?: number) {
|
|||||||
});
|
});
|
||||||
$i.avatarDecorations = update;
|
$i.avatarDecorations = update;
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function detachAllDecorations() {
|
function detachAllDecorations() {
|
||||||
|
@ -27,7 +27,7 @@ function rename(file: Misskey.entities.DriveFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function describe(file: Misskey.entities.DriveFile) {
|
function describe(file: Misskey.entities.DriveFile) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.comment ?? '',
|
default: file.comment ?? '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
@ -37,7 +37,8 @@ function describe(file: Misskey.entities.DriveFile) {
|
|||||||
comment: caption.length === 0 ? null : caption,
|
comment: caption.length === 0 ? null : caption,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
||||||
|
@ -137,10 +137,12 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men
|
|||||||
let noteInfo = '';
|
let noteInfo = '';
|
||||||
if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
|
if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
|
||||||
noteInfo += `Local Note: ${localUrl}\n`;
|
noteInfo += `Local Note: ${localUrl}\n`;
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
||||||
user: note.user,
|
user: note.user,
|
||||||
initialComment: `${noteInfo}-----\n`,
|
initialComment: `${noteInfo}-----\n`,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -544,7 +546,9 @@ export function getRenoteMenu(props: {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.mock) {
|
if (!props.mock) {
|
||||||
@ -580,7 +584,9 @@ export function getRenoteMenu(props: {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
|
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
|
||||||
@ -629,7 +635,9 @@ export function getRenoteMenu(props: {
|
|||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.mock) {
|
if (!props.mock) {
|
||||||
|
@ -101,9 +101,11 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
function reportAbuse() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
||||||
user: user,
|
user: user,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getConfirmed(text: string): Promise<boolean> {
|
async function getConfirmed(text: string): Promise<boolean> {
|
||||||
|
@ -103,7 +103,7 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => {
|
const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
|
||||||
title: i18n.ts.tokenRequested,
|
title: i18n.ts.tokenRequested,
|
||||||
information: i18n.ts.pluginTokenRequestedDescription,
|
information: i18n.ts.pluginTokenRequestedDescription,
|
||||||
initialName: realMeta.name,
|
initialName: realMeta.name,
|
||||||
@ -118,7 +118,8 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
|
|||||||
});
|
});
|
||||||
res(token);
|
res(token);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
savePlugin({
|
savePlugin({
|
||||||
|
@ -11,7 +11,7 @@ import { popup } from '@/os.js';
|
|||||||
export function pleaseLogin(path?: string) {
|
export function pleaseLogin(path?: string) {
|
||||||
if ($i) return;
|
if ($i) return;
|
||||||
|
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
message: i18n.ts.signinRequired,
|
message: i18n.ts.signinRequired,
|
||||||
}, {
|
}, {
|
||||||
@ -20,7 +20,8 @@ export function pleaseLogin(path?: string) {
|
|||||||
window.location.href = path;
|
window.location.href = path;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
throw new Error('signin required');
|
throw new Error('signin required');
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,3 @@ export async function tick(): Promise<void> {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
await new Promise((globalThis.requestIdleCallback ?? setTimeout) as never);
|
await new Promise((globalThis.requestIdleCallback ?? setTimeout) as never);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://github.com/misskey-dev/misskey/issues/11267
|
|
||||||
*/
|
|
||||||
export function semaphore(counter = 0, waiting: (() => void)[] = []) {
|
|
||||||
return {
|
|
||||||
acquire: () => ++counter > 1 && new Promise<void>(resolve => waiting.push(resolve)),
|
|
||||||
release: () => --counter && waiting.pop()?.(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -17,20 +17,16 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
|
|||||||
borderColor: string;
|
borderColor: string;
|
||||||
text: string;
|
text: string;
|
||||||
}[] | null>(null);
|
}[] | null>(null);
|
||||||
let disposeTooltipComponent;
|
const { dispose: disposeTooltipComponent } = os.popup(MkChartTooltip, {
|
||||||
|
|
||||||
os.popup(MkChartTooltip, {
|
|
||||||
showing: tooltipShowing,
|
showing: tooltipShowing,
|
||||||
x: tooltipX,
|
x: tooltipX,
|
||||||
y: tooltipY,
|
y: tooltipY,
|
||||||
title: tooltipTitle,
|
title: tooltipTitle,
|
||||||
series: tooltipSeries,
|
series: tooltipSeries,
|
||||||
}, {}).then(({ dispose }) => {
|
}, {});
|
||||||
disposeTooltipComponent = dispose;
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (disposeTooltipComponent) disposeTooltipComponent();
|
disposeTooltipComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
|
@ -112,7 +112,9 @@ export function openInstanceMenu(ev: MouseEvent) {
|
|||||||
text: i18n.ts._initialTutorial.launchTutorial,
|
text: i18n.ts._initialTutorial.launchTutorial,
|
||||||
icon: 'ti ti-presentation',
|
icon: 'ti ti-presentation',
|
||||||
action: () => {
|
action: () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {}, 'closed');
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
} : undefined, {
|
} : undefined, {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
@ -74,8 +74,9 @@ function openAccountMenu(ev: MouseEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function more() {
|
function more() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -99,10 +99,11 @@ function openAccountMenu(ev: MouseEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -71,11 +71,12 @@ const otherNavItemIndicated = computed<boolean>(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
anchor: { x: 'center', y: 'bottom' },
|
anchor: { x: 'center', y: 'bottom' },
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAccountMenu(ev: MouseEvent) {
|
function openAccountMenu(ev: MouseEvent) {
|
||||||
|
@ -86,9 +86,11 @@ function calcViewState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAccountMenu(ev: MouseEvent) {
|
function openAccountMenu(ev: MouseEvent) {
|
||||||
|
@ -27,7 +27,7 @@ const props = defineProps<{
|
|||||||
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
|
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
|
||||||
|
|
||||||
function func() {
|
function func() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
||||||
excludeTypes: props.column.excludeTypes,
|
excludeTypes: props.column.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
@ -36,7 +36,8 @@ function func() {
|
|||||||
excludeTypes: excludeTypes,
|
excludeTypes: excludeTypes,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = [{
|
const menu = [{
|
||||||
|
@ -125,15 +125,19 @@ const keymap = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
const { dispose } = os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function signup() {
|
function signup() {
|
||||||
os.popup(XSignupDialog, {
|
const { dispose } = os.popup(XSignupDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -54,7 +54,7 @@ const { widgetProps, configure, save } = useWidgetPropsManager(name,
|
|||||||
);
|
);
|
||||||
|
|
||||||
const configureNotification = () => {
|
const configureNotification = () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
||||||
excludeTypes: widgetProps.excludeTypes,
|
excludeTypes: widgetProps.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
@ -62,7 +62,8 @@ const configureNotification = () => {
|
|||||||
widgetProps.excludeTypes = excludeTypes;
|
widgetProps.excludeTypes = excludeTypes;
|
||||||
save();
|
save();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose<WidgetComponentExpose>({
|
defineExpose<WidgetComponentExpose>({
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
},
|
},
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"include": [
|
"include": [
|
||||||
".eslintrc.js",
|
|
||||||
"./**/*.ts",
|
"./**/*.ts",
|
||||||
"./**/*.vue"
|
"./**/*.vue"
|
||||||
],
|
],
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
node_modules
|
|
||||||
/built
|
|
||||||
/coverage
|
|
||||||
/.eslintrc.js
|
|
||||||
/jest.config.ts
|
|
||||||
/test
|
|
||||||
/test-d
|
|
||||||
build.js
|
|
@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../shared/.eslintrc.js',
|
|
||||||
],
|
|
||||||
};
|
|
27
packages/misskey-bubble-game/eslint.config.js
Normal file
27
packages/misskey-bubble-game/eslint.config.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/node_modules',
|
||||||
|
'built',
|
||||||
|
'coverage',
|
||||||
|
'jest.config.ts',
|
||||||
|
'test',
|
||||||
|
'test-d',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -17,18 +17,16 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node ./build.js",
|
"build": "node ./build.js",
|
||||||
"watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"",
|
"watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"",
|
||||||
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
"eslint": "eslint './**/*.{js,jsx,ts,tsx}'",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "1.0.0",
|
|
||||||
"@types/matter-js": "0.19.6",
|
"@types/matter-js": "0.19.6",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@types/node": "20.11.5",
|
"@types/node": "20.11.5",
|
||||||
"@typescript-eslint/eslint-plugin": "7.1.0",
|
"@typescript-eslint/eslint-plugin": "7.1.0",
|
||||||
"@typescript-eslint/parser": "7.1.0",
|
"@typescript-eslint/parser": "7.1.0",
|
||||||
"eslint": "8.57.0",
|
|
||||||
"nodemon": "3.0.2",
|
"nodemon": "3.0.2",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"typescript": "5.3.3",
|
"typescript": "5.3.3",
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
node_modules
|
|
||||||
/built
|
|
||||||
/coverage
|
|
||||||
/.eslintrc.js
|
|
||||||
/jest.config.ts
|
|
||||||
/test
|
|
||||||
/test-d
|
|
||||||
build.js
|
|
@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../shared/.eslintrc.js',
|
|
||||||
],
|
|
||||||
};
|
|
@ -1,32 +1,32 @@
|
|||||||
import * as esbuild from "esbuild";
|
import fs from 'node:fs';
|
||||||
import { build } from "esbuild";
|
import { fileURLToPath } from 'node:url';
|
||||||
import { globSync } from "glob";
|
import { dirname } from 'node:path';
|
||||||
import { execa } from "execa";
|
import * as esbuild from 'esbuild';
|
||||||
import fs from "node:fs";
|
import { build } from 'esbuild';
|
||||||
import { fileURLToPath } from "node:url";
|
import { globSync } from 'glob';
|
||||||
import { dirname } from "node:path";
|
import { execa } from 'execa';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||||
|
|
||||||
const entryPoints = globSync("./src/**/**.{ts,tsx}");
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
entryPoints,
|
entryPoints,
|
||||||
minify: process.env.NODE_ENV === 'production',
|
minify: process.env.NODE_ENV === 'production',
|
||||||
outdir: "./built",
|
outdir: './built',
|
||||||
target: "es2022",
|
target: 'es2022',
|
||||||
platform: "browser",
|
platform: 'browser',
|
||||||
format: "esm",
|
format: 'esm',
|
||||||
sourcemap: 'linked',
|
sourcemap: 'linked',
|
||||||
};
|
};
|
||||||
|
|
||||||
// built配下をすべて削除する
|
// built配下をすべて削除する
|
||||||
fs.rmSync('./built', { recursive: true, force: true });
|
fs.rmSync('./built', { recursive: true, force: true });
|
||||||
|
|
||||||
if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) {
|
if (process.argv.map(arg => arg.toLowerCase()).includes('--watch')) {
|
||||||
await watchSrc();
|
await watchSrc();
|
||||||
} else {
|
} else {
|
||||||
await buildSrc();
|
await buildSrc();
|
||||||
@ -36,7 +36,7 @@ async function buildSrc() {
|
|||||||
console.log(`[${_package.name}] start building...`);
|
console.log(`[${_package.name}] start building...`);
|
||||||
|
|
||||||
await build(options)
|
await build(options)
|
||||||
.then(it => {
|
.then(() => {
|
||||||
console.log(`[${_package.name}] build succeeded.`);
|
console.log(`[${_package.name}] build succeeded.`);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@ -65,7 +65,7 @@ function buildDts() {
|
|||||||
{
|
{
|
||||||
stdout: process.stdout,
|
stdout: process.stdout,
|
||||||
stderr: process.stderr,
|
stderr: process.stderr,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ async function watchSrc() {
|
|||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
|
|
||||||
console.log(`[${_package.name}] start watching...`)
|
console.log(`[${_package.name}] start watching...`);
|
||||||
|
|
||||||
const context = await esbuild.context({ ...options, plugins });
|
const context = await esbuild.context({ ...options, plugins });
|
||||||
await context.watch();
|
await context.watch();
|
||||||
|
28
packages/misskey-js/eslint.config.js
Normal file
28
packages/misskey-js/eslint.config.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/node_modules',
|
||||||
|
'built',
|
||||||
|
'coverage',
|
||||||
|
'jest.config.ts',
|
||||||
|
'test',
|
||||||
|
'test-d',
|
||||||
|
'generator',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: ['./tsconfig.json'],
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'../../shared/.eslintrc.js',
|
|
||||||
],
|
|
||||||
};
|
|
17
packages/misskey-js/generator/eslint.config.js
Normal file
17
packages/misskey-js/generator/eslint.config.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import sharedConfig from '../../shared/eslint.config.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...sharedConfig,
|
||||||
|
{
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
sourceType: 'module',
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user