Compare commits
22 Commits
40f64b9a8b
...
82fd3ae323
Author | SHA1 | Date |
---|---|---|
|
82fd3ae323 | |
|
3954837cfa | |
|
7ea4cad12e | |
|
d864e9a269 | |
|
4e0434c275 | |
|
e2f939080a | |
|
6956f44d1f | |
|
a393d5a87e | |
|
6c634de482 | |
|
fc02e0d34d | |
|
cb1a90ddad | |
|
f0fb3a56a8 | |
|
b8ae7edcec | |
|
a55fae6d6f | |
|
2a1e7a4270 | |
|
26063ca7b5 | |
|
73cae46132 | |
|
6d58e2c3e5 | |
|
46915d2ae3 | |
|
6e3494a389 | |
|
5963e8c484 | |
|
73c837a1e1 |
|
@ -81,7 +81,7 @@ jobs:
|
|||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Restore eslint cache
|
||||
uses: actions/cache@v4.2.4
|
||||
uses: actions/cache@v4.3.0
|
||||
with:
|
||||
path: ${{ env.eslint-cache-path }}
|
||||
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
|
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
# api-artifact
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v7.0.1
|
||||
uses: actions/github-script@v7.1.0
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
|
|
@ -90,7 +90,7 @@ jobs:
|
|||
env:
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Notify that Chromatic detects changes
|
||||
uses: actions/github-script@v7.0.1
|
||||
uses: actions/github-script@v7.1.0
|
||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## 2025.9.1
|
||||
## 2025.10.0
|
||||
|
||||
### NOTE
|
||||
- pnpm 10.16.0 が必要です
|
||||
|
@ -7,6 +7,8 @@
|
|||
- Feat: 予約投稿ができるようになりました
|
||||
- デフォルトで作成可能数は1になっています。適宜ロールのポリシーで設定を行ってください。
|
||||
- Enhance: 広告ごとにセンシティブフラグを設定できるようになりました
|
||||
- Enhance: 依存関係の更新
|
||||
- Enhance: 翻訳の更新
|
||||
|
||||
### Client
|
||||
- Feat: アカウントのQRコードを表示・読み取りできるようになりました
|
||||
|
|
22
package.json
22
package.json
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "2025.9.1-alpha.2",
|
||||
"version": "2025.10.0-beta.0",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/misskey-dev/misskey.git"
|
||||
},
|
||||
"packageManager": "pnpm@10.16.0",
|
||||
"packageManager": "pnpm@10.17.1",
|
||||
"workspaces": [
|
||||
"packages/frontend-shared",
|
||||
"packages/frontend",
|
||||
|
@ -54,30 +54,30 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"cssnano": "7.1.1",
|
||||
"esbuild": "0.25.9",
|
||||
"esbuild": "0.25.10",
|
||||
"execa": "9.6.0",
|
||||
"fast-glob": "3.3.3",
|
||||
"glob": "11.0.3",
|
||||
"ignore-walk": "7.0.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"postcss": "8.5.6",
|
||||
"tar": "7.4.3",
|
||||
"tar": "7.5.1",
|
||||
"terser": "5.44.0",
|
||||
"typescript": "5.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@misskey-dev/eslint-plugin": "2.1.0",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "14.5.4",
|
||||
"eslint": "9.35.0",
|
||||
"globals": "16.3.0",
|
||||
"eslint": "9.36.0",
|
||||
"globals": "16.4.0",
|
||||
"ncp": "2.0.0",
|
||||
"pnpm": "10.16.0",
|
||||
"start-server-and-test": "2.1.0"
|
||||
"pnpm": "10.17.1",
|
||||
"start-server-and-test": "2.1.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tensorflow/tfjs-core": "4.22.0"
|
||||
|
|
|
@ -39,17 +39,17 @@
|
|||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"@swc/core-darwin-arm64": "1.13.5",
|
||||
"@swc/core-darwin-x64": "1.13.5",
|
||||
"@swc/core-darwin-arm64": "1.13.19",
|
||||
"@swc/core-darwin-x64": "1.13.19",
|
||||
"@swc/core-freebsd-x64": "1.3.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.13.5",
|
||||
"@swc/core-linux-arm64-gnu": "1.13.5",
|
||||
"@swc/core-linux-arm64-musl": "1.13.5",
|
||||
"@swc/core-linux-x64-gnu": "1.13.5",
|
||||
"@swc/core-linux-x64-musl": "1.13.5",
|
||||
"@swc/core-win32-arm64-msvc": "1.13.5",
|
||||
"@swc/core-win32-ia32-msvc": "1.13.5",
|
||||
"@swc/core-win32-x64-msvc": "1.13.5",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.13.19",
|
||||
"@swc/core-linux-arm64-gnu": "1.13.19",
|
||||
"@swc/core-linux-arm64-musl": "1.13.19",
|
||||
"@swc/core-linux-x64-gnu": "1.13.19",
|
||||
"@swc/core-linux-x64-musl": "1.13.19",
|
||||
"@swc/core-win32-arm64-msvc": "1.13.19",
|
||||
"@swc/core-win32-ia32-msvc": "1.13.19",
|
||||
"@swc/core-win32-x64-msvc": "1.13.19",
|
||||
"@tensorflow/tfjs": "4.22.0",
|
||||
"@tensorflow/tfjs-node": "4.22.0",
|
||||
"bufferutil": "4.0.9",
|
||||
|
@ -69,8 +69,8 @@
|
|||
"utf-8-validate": "6.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.883.0",
|
||||
"@aws-sdk/lib-storage": "3.883.0",
|
||||
"@aws-sdk/client-s3": "3.896.0",
|
||||
"@aws-sdk/lib-storage": "3.895.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.2",
|
||||
"@fastify/cookie": "11.0.2",
|
||||
|
@ -82,7 +82,7 @@
|
|||
"@fastify/view": "10.0.2",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/summaly": "5.2.3",
|
||||
"@napi-rs/canvas": "0.1.79",
|
||||
"@napi-rs/canvas": "0.1.80",
|
||||
"@nestjs/common": "11.1.6",
|
||||
"@nestjs/core": "11.1.6",
|
||||
"@nestjs/testing": "11.1.6",
|
||||
|
@ -103,29 +103,29 @@
|
|||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "1.20.3",
|
||||
"bullmq": "5.58.5",
|
||||
"bullmq": "5.58.8",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "9.0.2",
|
||||
"chalk": "5.6.0",
|
||||
"chalk-template": "1.1.0",
|
||||
"chalk": "5.6.2",
|
||||
"chalk-template": "1.1.2",
|
||||
"chokidar": "4.0.3",
|
||||
"cli-highlight": "2.1.11",
|
||||
"color-convert": "2.0.1",
|
||||
"content-disposition": "0.5.4",
|
||||
"date-fns": "2.30.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"fastify": "5.6.0",
|
||||
"fastify": "5.6.1",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "19.6.0",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.4",
|
||||
"got": "14.4.8",
|
||||
"got": "14.4.9",
|
||||
"happy-dom": "16.8.1",
|
||||
"hpagent": "1.2.0",
|
||||
"htmlescape": "1.1.1",
|
||||
"http-link-header": "1.1.3",
|
||||
"ioredis": "5.7.0",
|
||||
"ioredis": "5.8.0",
|
||||
"ip-cidr": "4.0.2",
|
||||
"ipaddr.js": "2.2.0",
|
||||
"is-svg": "5.1.0",
|
||||
|
@ -135,14 +135,14 @@
|
|||
"jsonld": "8.3.3",
|
||||
"jsrsasign": "11.1.0",
|
||||
"juice": "11.0.1",
|
||||
"meilisearch": "0.52.0",
|
||||
"meilisearch": "0.53.0",
|
||||
"mfm-js": "0.25.0",
|
||||
"microformats-parser": "2.0.4",
|
||||
"mime-types": "2.1.35",
|
||||
"misskey-js": "workspace:*",
|
||||
"misskey-reversi": "workspace:*",
|
||||
"ms": "3.0.0-canary.202508261828",
|
||||
"nanoid": "5.1.5",
|
||||
"nanoid": "5.1.6",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"nodemailer": "6.10.1",
|
||||
|
@ -175,12 +175,12 @@
|
|||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"systeminformation": "5.27.8",
|
||||
"systeminformation": "5.27.10",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.5",
|
||||
"tsc-alias": "1.8.16",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typeorm": "0.3.26",
|
||||
"typeorm": "0.3.27",
|
||||
"typescript": "5.9.2",
|
||||
"ulid": "2.4.0",
|
||||
"vary": "1.1.2",
|
||||
|
@ -210,7 +210,7 @@
|
|||
"@types/jsrsasign": "10.5.15",
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/ms": "0.7.34",
|
||||
"@types/node": "22.18.1",
|
||||
"@types/node": "22.18.6",
|
||||
"@types/nodemailer": "6.4.19",
|
||||
"@types/oauth": "0.9.6",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
|
@ -231,8 +231,8 @@
|
|||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
|
|
|
@ -37,17 +37,23 @@ class HttpRequestServiceAgent extends http.Agent {
|
|||
|
||||
@bindThis
|
||||
public createConnection(options: http.ClientRequestArgs, callback?: (err: Error | null, stream: stream.Duplex) => void): stream.Duplex {
|
||||
const socket = super.createConnection(options, callback)
|
||||
.on('connect', () => {
|
||||
if (socket instanceof net.Socket && process.env.NODE_ENV === 'production') {
|
||||
const address = socket.remoteAddress;
|
||||
if (address && ipaddr.isValid(address)) {
|
||||
if (this.isPrivateIp(address)) {
|
||||
socket.destroy(new Error(`Blocked address: ${address}`));
|
||||
}
|
||||
const socket = super.createConnection(options, callback);
|
||||
|
||||
if (socket == null) {
|
||||
throw new Error('Failed to create socket');
|
||||
}
|
||||
|
||||
socket.on('connect', () => {
|
||||
if (socket instanceof net.Socket && process.env.NODE_ENV === 'production') {
|
||||
const address = socket.remoteAddress;
|
||||
if (address && ipaddr.isValid(address)) {
|
||||
if (this.isPrivateIp(address)) {
|
||||
socket.destroy(new Error(`Blocked address: ${address}`));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
@ -76,17 +82,23 @@ class HttpsRequestServiceAgent extends https.Agent {
|
|||
|
||||
@bindThis
|
||||
public createConnection(options: http.ClientRequestArgs, callback?: (err: Error | null, stream: stream.Duplex) => void): stream.Duplex {
|
||||
const socket = super.createConnection(options, callback)
|
||||
.on('connect', () => {
|
||||
if (socket instanceof net.Socket && process.env.NODE_ENV === 'production') {
|
||||
const address = socket.remoteAddress;
|
||||
if (address && ipaddr.isValid(address)) {
|
||||
if (this.isPrivateIp(address)) {
|
||||
socket.destroy(new Error(`Blocked address: ${address}`));
|
||||
}
|
||||
const socket = super.createConnection(options, callback);
|
||||
|
||||
if (socket == null) {
|
||||
throw new Error('Failed to create socket');
|
||||
}
|
||||
|
||||
socket.on('connect', () => {
|
||||
if (socket instanceof net.Socket && process.env.NODE_ENV === 'production') {
|
||||
const address = socket.remoteAddress;
|
||||
if (address && ipaddr.isValid(address)) {
|
||||
if (this.isPrivateIp(address)) {
|
||||
socket.destroy(new Error(`Blocked address: ${address}`));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,15 +11,15 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/node": "22.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.38.0",
|
||||
"@typescript-eslint/parser": "8.38.0",
|
||||
"rollup": "4.46.2",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"rollup": "4.52.2",
|
||||
"typescript": "5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"estree-walker": "3.0.3",
|
||||
"magic-string": "0.30.17",
|
||||
"vite": "7.0.7"
|
||||
"magic-string": "0.30.19",
|
||||
"vite": "7.1.7"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"@rollup/pluginutils": "5.3.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.1",
|
||||
"@vue/compiler-sfc": "3.5.21",
|
||||
"@vue/compiler-sfc": "3.5.22",
|
||||
"astring": "1.9.0",
|
||||
"buraha": "0.0.1",
|
||||
"estree-walker": "3.0.3",
|
||||
|
@ -26,47 +26,47 @@
|
|||
"mfm-js": "0.25.0",
|
||||
"misskey-js": "workspace:*",
|
||||
"punycode.js": "2.3.1",
|
||||
"rollup": "4.50.1",
|
||||
"sass": "1.92.1",
|
||||
"shiki": "3.12.2",
|
||||
"rollup": "4.52.2",
|
||||
"sass": "1.93.2",
|
||||
"shiki": "3.13.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tsc-alias": "1.8.16",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typescript": "5.9.2",
|
||||
"uuid": "11.1.0",
|
||||
"vite": "7.1.5",
|
||||
"vue": "3.5.21"
|
||||
"vite": "7.1.7",
|
||||
"vue": "3.5.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@misskey-dev/summaly": "5.2.3",
|
||||
"@tabler/icons-webfont": "3.34.1",
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
"@testing-library/vue": "8.1.0",
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/micromatch": "4.0.9",
|
||||
"@types/node": "22.18.1",
|
||||
"@types/node": "22.18.6",
|
||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"@vue/runtime-core": "3.5.21",
|
||||
"@vue/runtime-core": "3.5.22",
|
||||
"acorn": "8.15.0",
|
||||
"cross-env": "10.0.0",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.4.0",
|
||||
"eslint-plugin-vue": "10.5.0",
|
||||
"fast-glob": "3.3.3",
|
||||
"happy-dom": "18.0.1",
|
||||
"intersection-observer": "0.12.2",
|
||||
"micromatch": "4.0.8",
|
||||
"msw": "2.11.1",
|
||||
"msw": "2.11.3",
|
||||
"nodemon": "3.1.10",
|
||||
"prettier": "3.6.2",
|
||||
"start-server-and-test": "2.1.0",
|
||||
"tsx": "4.20.5",
|
||||
"start-server-and-test": "2.1.2",
|
||||
"tsx": "4.20.6",
|
||||
"vite-plugin-turbosnap": "1.0.3",
|
||||
"vue-component-type-helpers": "3.0.6",
|
||||
"vue-component-type-helpers": "3.0.8",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-tsc": "3.0.6"
|
||||
"vue-tsc": "3.0.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"esbuild": "0.25.9",
|
||||
"eslint-plugin-vue": "10.4.0",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"esbuild": "0.25.10",
|
||||
"eslint-plugin-vue": "10.5.0",
|
||||
"nodemon": "3.1.10",
|
||||
"typescript": "5.9.2",
|
||||
"vue-eslint-parser": "10.2.0"
|
||||
|
@ -35,6 +35,6 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"misskey-js": "workspace:*",
|
||||
"vue": "3.5.21"
|
||||
"vue": "3.5.22"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
"@rollup/plugin-json": "6.1.0",
|
||||
"@rollup/plugin-replace": "6.0.2",
|
||||
"@rollup/pluginutils": "5.3.0",
|
||||
"@sentry/vue": "10.10.0",
|
||||
"@syuilo/aiscript": "1.1.0",
|
||||
"@sentry/vue": "10.15.0",
|
||||
"@syuilo/aiscript": "1.1.2",
|
||||
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.1",
|
||||
"@vue/compiler-sfc": "3.5.21",
|
||||
"@vue/compiler-sfc": "3.5.22",
|
||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15",
|
||||
"analytics": "0.8.19",
|
||||
"astring": "1.9.0",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"chartjs-chart-matrix": "3.0.0",
|
||||
"chartjs-plugin-gradient": "0.6.1",
|
||||
"chartjs-plugin-zoom": "2.2.0",
|
||||
"chromatic": "13.1.4",
|
||||
"chromatic": "13.2.1",
|
||||
"compare-versions": "6.1.1",
|
||||
"cropperjs": "2.0.1",
|
||||
"date-fns": "4.1.0",
|
||||
|
@ -52,12 +52,12 @@
|
|||
"icons-subsetter": "workspace:*",
|
||||
"idb-keyval": "6.2.2",
|
||||
"insert-text-at-cursor": "0.3.0",
|
||||
"ios-haptics": "0.1.0",
|
||||
"ios-haptics": "0.1.4",
|
||||
"is-file-animated": "1.0.2",
|
||||
"json5": "2.2.3",
|
||||
"magic-string": "0.30.18",
|
||||
"magic-string": "0.30.19",
|
||||
"matter-js": "0.20.0",
|
||||
"mediabunny": "1.15.1",
|
||||
"mediabunny": "1.21.0",
|
||||
"mfm-js": "0.25.0",
|
||||
"misskey-bubble-game": "workspace:*",
|
||||
"misskey-js": "workspace:*",
|
||||
|
@ -66,10 +66,10 @@
|
|||
"punycode.js": "2.3.1",
|
||||
"qr-code-styling": "1.9.2",
|
||||
"qr-scanner": "1.4.2",
|
||||
"rollup": "4.50.1",
|
||||
"rollup": "4.52.2",
|
||||
"sanitize-html": "2.17.0",
|
||||
"sass": "1.92.1",
|
||||
"shiki": "3.12.2",
|
||||
"sass": "1.93.2",
|
||||
"shiki": "3.13.0",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.180.0",
|
||||
|
@ -79,8 +79,8 @@
|
|||
"tsconfig-paths": "4.2.0",
|
||||
"typescript": "5.9.2",
|
||||
"v-code-diff": "1.13.1",
|
||||
"vite": "7.1.5",
|
||||
"vue": "3.5.21",
|
||||
"vite": "7.1.7",
|
||||
"vue": "3.5.22",
|
||||
"vuedraggable": "next",
|
||||
"wanakana": "5.3.1"
|
||||
},
|
||||
|
@ -88,7 +88,7 @@
|
|||
"@misskey-dev/summaly": "5.2.3",
|
||||
"@storybook/addon-essentials": "8.6.14",
|
||||
"@storybook/addon-interactions": "8.6.14",
|
||||
"@storybook/addon-links": "9.1.5",
|
||||
"@storybook/addon-links": "9.1.8",
|
||||
"@storybook/addon-mdx-gfm": "8.6.14",
|
||||
"@storybook/addon-storysource": "8.6.14",
|
||||
"@storybook/blocks": "8.6.14",
|
||||
|
@ -96,57 +96,57 @@
|
|||
"@storybook/core-events": "8.6.14",
|
||||
"@storybook/manager-api": "8.6.14",
|
||||
"@storybook/preview-api": "8.6.14",
|
||||
"@storybook/react": "9.1.5",
|
||||
"@storybook/react-vite": "9.1.5",
|
||||
"@storybook/react": "9.1.8",
|
||||
"@storybook/react-vite": "9.1.8",
|
||||
"@storybook/test": "8.6.14",
|
||||
"@storybook/theming": "8.6.14",
|
||||
"@storybook/types": "8.6.14",
|
||||
"@storybook/vue3": "9.1.5",
|
||||
"@storybook/vue3-vite": "9.1.5",
|
||||
"@tabler/icons-webfont": "3.34.1",
|
||||
"@storybook/vue3": "9.1.8",
|
||||
"@storybook/vue3-vite": "9.1.8",
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
"@testing-library/vue": "8.1.0",
|
||||
"@types/canvas-confetti": "1.9.0",
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/matter-js": "0.20.0",
|
||||
"@types/matter-js": "0.20.2",
|
||||
"@types/micromatch": "4.0.9",
|
||||
"@types/node": "22.18.1",
|
||||
"@types/node": "22.18.6",
|
||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||
"@types/sanitize-html": "2.16.0",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"@vue/compiler-core": "3.5.21",
|
||||
"@vue/runtime-core": "3.5.21",
|
||||
"@vue/compiler-core": "3.5.22",
|
||||
"@vue/runtime-core": "3.5.22",
|
||||
"acorn": "8.15.0",
|
||||
"cross-env": "10.0.0",
|
||||
"cypress": "14.5.4",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.4.0",
|
||||
"eslint-plugin-vue": "10.5.0",
|
||||
"fast-glob": "3.3.3",
|
||||
"happy-dom": "18.0.1",
|
||||
"intersection-observer": "0.12.2",
|
||||
"micromatch": "4.0.8",
|
||||
"minimatch": "10.0.3",
|
||||
"msw": "2.11.1",
|
||||
"msw": "2.11.3",
|
||||
"msw-storybook-addon": "2.0.5",
|
||||
"nodemon": "3.1.10",
|
||||
"prettier": "3.6.2",
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"seedrandom": "3.0.5",
|
||||
"start-server-and-test": "2.1.0",
|
||||
"storybook": "9.1.5",
|
||||
"start-server-and-test": "2.1.2",
|
||||
"storybook": "9.1.8",
|
||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||
"tsx": "4.20.5",
|
||||
"tsx": "4.20.6",
|
||||
"vite-plugin-turbosnap": "1.0.3",
|
||||
"vitest": "3.2.4",
|
||||
"vitest-fetch-mock": "0.4.5",
|
||||
"vue-component-type-helpers": "3.0.6",
|
||||
"vue-component-type-helpers": "3.0.8",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-tsc": "3.0.6"
|
||||
"vue-tsc": "3.0.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:class="$style.thumbnail"
|
||||
:style="{ objectFit: fit }"
|
||||
/>
|
||||
<i v-else-if="is === 'image'" class="ti ti-photo" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'video'" class="ti ti-video" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'audio' || is === 'midi'" class="ti ti-file-music" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'csv'" class="ti ti-file-text" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'pdf'" class="ti ti-file-text" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'textfile'" class="ti ti-file-text" :class="$style.icon"></i>
|
||||
<i v-else-if="is === 'archive'" class="ti ti-file-zip" :class="$style.icon"></i>
|
||||
<i v-else class="ti ti-file" :class="$style.icon"></i>
|
||||
<i v-else :class="[$style.icon, fileIcon]"></i>
|
||||
|
||||
<i v-if="isThumbnailAvailable && is === 'video'" class="ti ti-video" :class="$style.iconSub"></i>
|
||||
</div>
|
||||
|
@ -46,6 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
|
||||
import { getFileType, getFileTypeIcon } from '@/utility/file-type.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -56,27 +50,8 @@ const props = defineProps<{
|
|||
large?: boolean;
|
||||
}>();
|
||||
|
||||
const is = computed(() => {
|
||||
if (props.file.type.startsWith('image/')) return 'image';
|
||||
if (props.file.type.startsWith('video/')) return 'video';
|
||||
if (props.file.type === 'audio/midi') return 'midi';
|
||||
if (props.file.type.startsWith('audio/')) return 'audio';
|
||||
if (props.file.type.endsWith('/csv')) return 'csv';
|
||||
if (props.file.type.endsWith('/pdf')) return 'pdf';
|
||||
if (props.file.type.startsWith('text/')) return 'textfile';
|
||||
if ([
|
||||
'application/zip',
|
||||
'application/x-cpio',
|
||||
'application/x-bzip',
|
||||
'application/x-bzip2',
|
||||
'application/java-archive',
|
||||
'application/x-rar-compressed',
|
||||
'application/x-tar',
|
||||
'application/gzip',
|
||||
'application/x-7z-compressed',
|
||||
].some(archiveType => archiveType === props.file.type)) return 'archive';
|
||||
return 'unknown';
|
||||
});
|
||||
const is = computed(() => getFileType(props.file.type));
|
||||
const fileIcon = computed(() => getFileTypeIcon(is.value));
|
||||
|
||||
const isThumbnailAvailable = computed(() => {
|
||||
return props.file.thumbnailUrl
|
||||
|
|
|
@ -79,22 +79,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div v-if="maxTextLength - textLength < 100" :class="['_acrylic', $style.textCount, { [$style.textOver]: textLength > maxTextLength }]">{{ maxTextLength - textLength }}</div>
|
||||
</div>
|
||||
<input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags">
|
||||
<XPostFormAttaches v-model="files" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
|
||||
<div v-if="uploader.items.value.length > 0" style="padding: 12px;">
|
||||
<MkTip k="postFormUploader">
|
||||
{{ i18n.ts._postForm.uploaderTip }}
|
||||
</MkTip>
|
||||
<MkUploaderItems :items="uploader.items.value" @showMenu="(item, ev) => showPerUploadItemMenu(item, ev)" @showMenuViaContextmenu="(item, ev) => showPerUploadItemMenuViaContextmenu(item, ev)"/>
|
||||
</div>
|
||||
<XPostFormAttaches
|
||||
v-model="attaches"
|
||||
:draggable="!posting && !posted"
|
||||
@detach="detachAttaches"
|
||||
@uploaderItemAborted="handleUploaderItemAbort"
|
||||
@changeDriveFileSensitivity="updateFileSensitive"
|
||||
@changeDriveFileName="updateFileName"
|
||||
@showUploaderMenu="handleShowUploaderMenu"
|
||||
/>
|
||||
<MkPollEditor v-if="poll" v-model="poll" @destroyed="poll = null"/>
|
||||
<MkNotePreview v-if="showPreview" :class="$style.preview" :text="text" :files="files" :poll="poll ?? undefined" :useCw="useCw" :cw="cw" :user="postAccount ?? $i"/>
|
||||
<div v-if="showingOptions" style="padding: 8px 16px;">
|
||||
</div>
|
||||
<footer :class="$style.footer">
|
||||
<div :class="$style.footerLeft">
|
||||
<button v-tooltip="i18n.ts.attachFile + ' (' + i18n.ts.upload + ')'" class="_button" :class="$style.footerButton" @click="chooseFileFromPc"><i class="ti ti-photo-plus"></i></button>
|
||||
<button v-tooltip="i18n.ts.attachFile + ' (' + i18n.ts.fromDrive + ')'" class="_button" :class="$style.footerButton" @click="chooseFileFromDrive"><i class="ti ti-cloud-download"></i></button>
|
||||
<button v-tooltip="i18n.ts.poll" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: poll }]" @click="togglePoll"><i class="ti ti-chart-arrows"></i></button>
|
||||
<button v-tooltip="i18n.ts.attachFile" class="_button" :class="$style.footerButton" @click="chooseFileFrom"><i class="ti ti-photo-plus"></i></button> <button v-tooltip="i18n.ts.poll" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: poll }]" @click="togglePoll"><i class="ti ti-chart-arrows"></i></button>
|
||||
<button v-tooltip="i18n.ts.useCw" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: useCw }]" @click="useCw = !useCw"><i class="ti ti-eye-off"></i></button>
|
||||
<button v-tooltip="i18n.ts.hashtags" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: withHashtags }]" @click="withHashtags = !withHashtags"><i class="ti ti-hash"></i></button>
|
||||
<button v-tooltip="i18n.ts.mention" class="_button" :class="$style.footerButton" @click="insertMention"><i class="ti ti-at"></i></button>
|
||||
|
@ -118,7 +118,7 @@ import * as Misskey from 'misskey-js';
|
|||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import { toASCII } from 'punycode.js';
|
||||
import { host, url } from '@@/js/config.js';
|
||||
import MkUploaderItems from './MkUploaderItems.vue';
|
||||
import type { Attach } from './MkPostFormAttaches.vue';
|
||||
import type { ShallowRef } from 'vue';
|
||||
import type { PostFormProps } from '@/types/post-form.js';
|
||||
import type { MenuItem } from '@/types/menu.js';
|
||||
|
@ -135,7 +135,7 @@ import { formatTimeString } from '@/utility/format-time-string.js';
|
|||
import { Autocomplete } from '@/utility/autocomplete.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { chooseDriveFile } from '@/utility/drive.js';
|
||||
import { chooseDriveFile, chooseFileFromUrl } from '@/utility/drive.js';
|
||||
import { store } from '@/store.js';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
@ -230,11 +230,6 @@ onUnmounted(() => {
|
|||
uploader.dispose();
|
||||
});
|
||||
|
||||
uploader.events.on('itemUploaded', ctx => {
|
||||
files.value.push(ctx.item.uploaded!);
|
||||
uploader.removeItem(ctx.item);
|
||||
});
|
||||
|
||||
const draftKey = computed((): string => {
|
||||
let key = targetChannel.value ? `channel:${targetChannel.value.id}` : '';
|
||||
|
||||
|
@ -297,26 +292,34 @@ const cwTextLength = computed((): number => {
|
|||
|
||||
const maxCwTextLength = 100;
|
||||
|
||||
/**
|
||||
* Computes whether the post data meets the required conditions for submission or enabling the post button.
|
||||
*
|
||||
* @param cond - Specifies the context in which the condition is being checked ('button' for UI button state, 'req' for request validation).
|
||||
*/
|
||||
function computePostDataCondition(cond: 'button' | 'req') {
|
||||
return !uploader.uploading.value && (
|
||||
1 <= textLength.value ||
|
||||
1 <= files.value.length ||
|
||||
(cond === 'button' ? (1 <= uploader.items.value.length) : false) ||
|
||||
poll.value != null ||
|
||||
renoteTargetNote.value != null ||
|
||||
quoteId.value != null
|
||||
) &&
|
||||
(textLength.value <= maxTextLength.value) &&
|
||||
(
|
||||
useCw.value ?
|
||||
(
|
||||
cw.value != null && cw.value.trim() !== '' &&
|
||||
cwTextLength.value <= maxCwTextLength
|
||||
) : true
|
||||
) &&
|
||||
(files.value.length <= 16) &&
|
||||
(!poll.value || poll.value.choices.length >= 2);
|
||||
}
|
||||
|
||||
const canPost = computed((): boolean => {
|
||||
return !props.mock && !posting.value && !posted.value && !uploader.uploading.value && (uploader.items.value.length === 0 || uploader.readyForUpload.value) &&
|
||||
(
|
||||
1 <= textLength.value ||
|
||||
1 <= files.value.length ||
|
||||
1 <= uploader.items.value.length ||
|
||||
poll.value != null ||
|
||||
renoteTargetNote.value != null ||
|
||||
quoteId.value != null
|
||||
) &&
|
||||
(textLength.value <= maxTextLength.value) &&
|
||||
(
|
||||
useCw.value ?
|
||||
(
|
||||
cw.value != null && cw.value.trim() !== '' &&
|
||||
cwTextLength.value <= maxCwTextLength
|
||||
) : true
|
||||
) &&
|
||||
(files.value.length <= 16) &&
|
||||
(!poll.value || poll.value.choices.length >= 2);
|
||||
return !props.mock && !posting.value && !posted.value && !uploader.uploading.value && (uploader.items.value.length === 0 || uploader.readyForUpload.value) && computePostDataCondition('button');
|
||||
});
|
||||
|
||||
// cannot save pure renote as draft
|
||||
|
@ -481,6 +484,29 @@ function focus() {
|
|||
}
|
||||
}
|
||||
|
||||
function chooseFileFrom(ev: MouseEvent) {
|
||||
const anchorElement = ev.currentTarget ?? ev.target;
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.attachFile,
|
||||
type: 'label',
|
||||
}, {
|
||||
text: i18n.ts.upload,
|
||||
icon: 'ti ti-upload',
|
||||
action: () => chooseFileFromPc(ev),
|
||||
}, {
|
||||
text: i18n.ts.fromDrive,
|
||||
icon: 'ti ti-cloud',
|
||||
action: () => chooseFileFromDrive(ev),
|
||||
}, {
|
||||
text: i18n.ts.fromUrl,
|
||||
icon: 'ti ti-link',
|
||||
action: () => chooseFileFromUrl().then(file => {
|
||||
attachOrder.set(file.id, files.value.length);
|
||||
files.value.push(file);
|
||||
}),
|
||||
}], anchorElement);
|
||||
}
|
||||
|
||||
function chooseFileFromPc(ev: MouseEvent) {
|
||||
if (props.mock) return;
|
||||
|
||||
|
@ -498,21 +524,85 @@ function chooseFileFromDrive(ev: MouseEvent) {
|
|||
});
|
||||
}
|
||||
|
||||
function detachFile(id) {
|
||||
files.value = files.value.filter(x => x.id !== id);
|
||||
uploader.events.on('itemUploaded', ({ item }) => {
|
||||
if (!item.uploaded) return;
|
||||
const attachesOrder = attaches.value.findIndex(f => f.id === item.id);
|
||||
const attachOrderOrder = attachOrder.get(item.id);
|
||||
if (attachesOrder >= 0 || attachOrderOrder != null) {
|
||||
const index = attachesOrder >= 0 ? attachOrderOrder ?? attachesOrder : attachOrderOrder ?? attaches.value.length;
|
||||
attachOrder.delete(item.id);
|
||||
attachOrder.set(item.uploaded.id, index);
|
||||
}
|
||||
files.value.push(item.uploaded);
|
||||
uploader.removeItem(item);
|
||||
});
|
||||
|
||||
function detachAttaches(id: string) {
|
||||
const attach = attaches.value.find(a => a.id === id);
|
||||
if (!attach) return;
|
||||
attachOrder.delete(attach.id);
|
||||
if (attach.type === 'driveFile') {
|
||||
files.value = files.value.filter(f => f.id !== attach.id);
|
||||
} else if (attach.type === 'uploaderItem') {
|
||||
uploader.removeItem(attach.file);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFileSensitive(file, sensitive) {
|
||||
function handleUploaderItemAbort(id: string) {
|
||||
if (props.mock) return;
|
||||
const item = uploader.items.value.find(i => i.id === id);
|
||||
if (!item) return;
|
||||
if (posting.value && attaches.value.length > 1) {
|
||||
// このアップロードが止まってもファイルがなくならない場合はアイテムを削除して投稿を続行
|
||||
detachAttaches(id);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFileSensitive(file: Misskey.entities.DriveFile, sensitive: boolean) {
|
||||
if (props.mock) {
|
||||
emit('fileChangeSensitive', file.id, sensitive);
|
||||
}
|
||||
files.value[files.value.findIndex(x => x.id === file.id)].isSensitive = sensitive;
|
||||
}
|
||||
|
||||
function updateFileName(file, name) {
|
||||
function updateFileName(file: Misskey.entities.DriveFile, name: string) {
|
||||
files.value[files.value.findIndex(x => x.id === file.id)].name = name;
|
||||
}
|
||||
|
||||
const attachOrder = new Map<string, number>();
|
||||
|
||||
const attaches = computed<Attach[]>({
|
||||
get: () => {
|
||||
const _attaches = [
|
||||
...files.value.map(f => ({ id: f.id, type: 'driveFile' as const, file: f })),
|
||||
...uploader.items.value.filter(i => i.uploaded == null).map(i => ({ id: i.id, type: 'uploaderItem' as const, file: i })),
|
||||
];
|
||||
_attaches.forEach((a, i) => {
|
||||
if (!attachOrder.has(a.id)) {
|
||||
attachOrder.set(a.id, i);
|
||||
}
|
||||
});
|
||||
return _attaches.sort((a, b) => {
|
||||
const aOrder = attachOrder.get(a.id) ?? 0;
|
||||
const bOrder = attachOrder.get(b.id) ?? 0;
|
||||
return aOrder - bOrder;
|
||||
});
|
||||
},
|
||||
set: (newAttaches: Attach[]) => {
|
||||
attachOrder.clear();
|
||||
newAttaches.forEach((a, i) => {
|
||||
attachOrder.set(a.id, i);
|
||||
});
|
||||
files.value = newAttaches.filter(a => a.type === 'driveFile').map(a => a.file);
|
||||
uploader.items.value = newAttaches.filter(a => a.type === 'uploaderItem').map(a => a.file);
|
||||
},
|
||||
});
|
||||
|
||||
function handleShowUploaderMenu(item: UploaderItem, ev: MouseEvent | KeyboardEvent) {
|
||||
if (props.mock) return;
|
||||
os.popupMenu(uploader.getMenu(item), ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
function setVisibility() {
|
||||
if (targetChannel.value) {
|
||||
visibility.value = 'public';
|
||||
|
@ -943,6 +1033,9 @@ async function post(ev?: MouseEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
// ここからは投稿の中身を触らせない
|
||||
posting.value = true;
|
||||
|
||||
if (uploader.items.value.some(x => x.uploaded == null)) {
|
||||
await uploadFiles();
|
||||
|
||||
|
@ -954,7 +1047,12 @@ async function post(ev?: MouseEvent) {
|
|||
|
||||
let postData = {
|
||||
text: text.value === '' ? null : text.value,
|
||||
fileIds: files.value.length > 0 ? files.value.map(f => f.id) : undefined,
|
||||
fileIds: files.value.length > 0 ? files.value.map(f => f.id).sort((a, b) => {
|
||||
// itemUploadedイベントではfilesの順番を入れ替えないため、ここでもソートして確実に順番を整える
|
||||
const aOrder = attachOrder.get(a) ?? 0;
|
||||
const bOrder = attachOrder.get(b) ?? 0;
|
||||
return aOrder - bOrder;
|
||||
}) : undefined,
|
||||
replyId: replyTargetNote.value ? replyTargetNote.value.id : undefined,
|
||||
renoteId: renoteTargetNote.value ? renoteTargetNote.value.id : quoteId.value ? quoteId.value : undefined,
|
||||
channelId: targetChannel.value ? targetChannel.value.id : undefined,
|
||||
|
@ -993,6 +1091,13 @@ async function post(ev?: MouseEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
// アップロードキャンセルでファイルの総数が変わるなどのコンディション変化が
|
||||
// あるため、canPostを再評価する
|
||||
if (!computePostDataCondition('req')) {
|
||||
posting.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let token: string | undefined = undefined;
|
||||
|
||||
if (postAccount.value) {
|
||||
|
@ -1009,7 +1114,6 @@ async function post(ev?: MouseEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
posting.value = true;
|
||||
misskeyApi('notes/create', postData, token).then((res) => {
|
||||
if (props.freezeAfterPosted) {
|
||||
posted.value = true;
|
||||
|
@ -1021,6 +1125,7 @@ async function post(ev?: MouseEvent) {
|
|||
|
||||
nextTick(() => {
|
||||
deleteDraft();
|
||||
attachOrder.clear();
|
||||
emit('posted');
|
||||
if (postData.text && postData.text !== '') {
|
||||
const hashtags_ = mfm.parse(postData.text).map(x => x.type === 'hashtag' && x.props.hashtag).filter(x => x) as string[];
|
||||
|
|
|
@ -5,18 +5,46 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div v-show="props.modelValue.length != 0" :class="$style.root">
|
||||
<Sortable :modelValue="props.modelValue" :class="$style.files" itemKey="id" :animation="150" :delay="100" :delayOnTouchOnly="true" @update:modelValue="v => emit('update:modelValue', v)">
|
||||
<Sortable
|
||||
:modelValue="props.modelValue"
|
||||
:class="$style.files"
|
||||
itemKey="id"
|
||||
:animation="150"
|
||||
:delay="100"
|
||||
:delayOnTouchOnly="true"
|
||||
:disabled="props.draggable === false"
|
||||
@update:modelValue="v => emit('update:modelValue', v)"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div
|
||||
:class="$style.file"
|
||||
:class="[$style.file, { [$style.dragEnabled]: props.draggable !== false }]"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@click="showFileMenu(element, $event)"
|
||||
@click="handleClick(element, $event)"
|
||||
@keydown.space.enter="showFileMenu(element, $event)"
|
||||
@contextmenu.prevent="showFileMenu(element, $event)"
|
||||
>
|
||||
<MkDriveFileThumbnail :data-id="element.id" :class="$style.thumbnail" :file="element" fit="cover"/>
|
||||
<div v-if="element.isSensitive" :class="$style.sensitive">
|
||||
<MkDriveFileThumbnail v-if="element.type === 'driveFile'" :data-id="element.id" :class="$style.thumbnail" :file="element.file" fit="cover"/>
|
||||
<template v-else-if="element.type === 'uploaderItem'">
|
||||
<img v-if="element.file.thumbnail" :src="element.file.thumbnail" :class="[$style.thumbnail, $style.uploaderThumbnail]" />
|
||||
<div v-else v-panel :class="[$style.thumbnail, $style.uploaderThumbnailIcon]">
|
||||
<i :class="[$style.icon, getFileTypeIcon(getFileType(element.file.file.type))]"></i>
|
||||
</div>
|
||||
<div :class="[$style.uploadProgressWrapper, { uploading: element.file.uploading }]">
|
||||
<svg :class="$style.uploadProgressSvg" viewBox="0 0 64 64">
|
||||
<circle
|
||||
:class="$style.uploadProgressFg"
|
||||
cx="32" cy="32" r="16"
|
||||
:stroke-dasharray="progressDashArray(element.file)"
|
||||
/>
|
||||
</svg>
|
||||
<div :class="$style.uploadAbortButton">
|
||||
<!-- 実際のボタン機能はhandleClick -->
|
||||
<i class="ti ti-x"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="(element.type === 'driveFile' && element.file.isSensitive) || (element.type === 'uploaderItem' && element.file.isSensitive)" :class="$style.sensitive">
|
||||
<i class="ti ti-eye-exclamation" style="margin: auto;"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,11 +60,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { UploaderItem } from '@/composables/use-uploader.js';
|
||||
|
||||
export type Attach = {
|
||||
id: string;
|
||||
type: 'driveFile';
|
||||
file: Misskey.entities.DriveFile;
|
||||
} | {
|
||||
id: string;
|
||||
type: 'uploaderItem';
|
||||
file: UploaderItem;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, inject } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import type { MenuItem } from '@/types/menu';
|
||||
import { copyToClipboard } from '@/utility/copy-to-clipboard';
|
||||
import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
|
||||
import { getFileType, getFileTypeIcon } from '@/utility/file-type.js';
|
||||
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
|
@ -48,29 +91,30 @@ import { globalEvents } from '@/events.js';
|
|||
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: Misskey.entities.DriveFile[];
|
||||
detachMediaFn?: (id: string) => void;
|
||||
draggable?: boolean;
|
||||
modelValue: Attach[];
|
||||
}>();
|
||||
|
||||
const mock = inject(DI.mock, false);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update:modelValue', value: Misskey.entities.DriveFile[]): void;
|
||||
(ev: 'update:modelValue', value: Attach[]): void;
|
||||
(ev: 'detach', id: string): void;
|
||||
(ev: 'changeSensitive', file: Misskey.entities.DriveFile, isSensitive: boolean): void;
|
||||
(ev: 'changeName', file: Misskey.entities.DriveFile, newName: string): void;
|
||||
(ev: 'uploaderItemAborted', id: string): void;
|
||||
(ev: 'changeDriveFileSensitivity', file: Misskey.entities.DriveFile, isSensitive: boolean): void;
|
||||
(ev: 'changeDriveFileName', file: Misskey.entities.DriveFile, newName: string): void;
|
||||
(ev: 'showUploaderMenu', uploaderItem: UploaderItem, event: MouseEvent | KeyboardEvent): void;
|
||||
}>();
|
||||
|
||||
let menuShowing = false;
|
||||
function progressDashArray(item: UploaderItem): string {
|
||||
const progress = item.progress ? item.progress.value / item.progress.max : 0;
|
||||
return `${progress * 100} ${100 - progress * 100}`;
|
||||
}
|
||||
|
||||
function detachMedia(id: string) {
|
||||
if (mock) return;
|
||||
|
||||
if (props.detachMediaFn) {
|
||||
props.detachMediaFn(id);
|
||||
} else {
|
||||
emit('detach', id);
|
||||
}
|
||||
emit('detach', id);
|
||||
}
|
||||
|
||||
async function detachAndDeleteMedia(file: Misskey.entities.DriveFile) {
|
||||
|
@ -91,9 +135,9 @@ async function detachAndDeleteMedia(file: Misskey.entities.DriveFile) {
|
|||
globalEvents.emit('driveFilesDeleted', [file]);
|
||||
}
|
||||
|
||||
function toggleSensitive(file) {
|
||||
function toggleDriveFileSensitivity(file: Misskey.entities.DriveFile) {
|
||||
if (mock) {
|
||||
emit('changeSensitive', file, !file.isSensitive);
|
||||
emit('changeDriveFileSensitivity', file, !file.isSensitive);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -101,11 +145,11 @@ function toggleSensitive(file) {
|
|||
fileId: file.id,
|
||||
isSensitive: !file.isSensitive,
|
||||
}).then(() => {
|
||||
emit('changeSensitive', file, !file.isSensitive);
|
||||
emit('changeDriveFileSensitivity', file, !file.isSensitive);
|
||||
});
|
||||
}
|
||||
|
||||
async function rename(file) {
|
||||
async function renameDriveFile(file: Misskey.entities.DriveFile) {
|
||||
if (mock) return;
|
||||
|
||||
const { canceled, result } = await os.inputText({
|
||||
|
@ -118,12 +162,12 @@ async function rename(file) {
|
|||
fileId: file.id,
|
||||
name: result,
|
||||
}).then(() => {
|
||||
emit('changeName', file, result);
|
||||
emit('changeDriveFileName', file, result);
|
||||
file.name = result;
|
||||
});
|
||||
}
|
||||
|
||||
async function describe(file: Misskey.entities.DriveFile) {
|
||||
async function describeDriveFile(file: Misskey.entities.DriveFile) {
|
||||
if (mock) return;
|
||||
|
||||
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkFileCaptionEditWindow.vue').then(x => x.default), {
|
||||
|
@ -143,66 +187,82 @@ async function describe(file: Misskey.entities.DriveFile) {
|
|||
});
|
||||
}
|
||||
|
||||
function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | KeyboardEvent): void {
|
||||
if (menuShowing) return;
|
||||
function handleClick(attach: Attach, ev: MouseEvent | KeyboardEvent): void {
|
||||
if (ev instanceof MouseEvent && ev.button !== 0) return; // 左クリック以外は無視
|
||||
|
||||
const isImage = file.type.startsWith('image/');
|
||||
if (attach.type === 'driveFile' || (attach.type === 'uploaderItem' && !attach.file.uploading)) {
|
||||
showFileMenu(attach, ev);
|
||||
} else {
|
||||
if (attach.file.abort) {
|
||||
attach.file.abort();
|
||||
}
|
||||
attach.file.aborted = true;
|
||||
attach.file.uploadFailed = true;
|
||||
emit('uploaderItemAborted', attach.file.id);
|
||||
}
|
||||
}
|
||||
|
||||
const menuItems: MenuItem[] = [];
|
||||
function showFileMenu(attach: Attach, ev: MouseEvent | KeyboardEvent): void {
|
||||
if (attach.type === 'driveFile') {
|
||||
const file = attach.file;
|
||||
const isImage = file.type.startsWith('image/');
|
||||
|
||||
menuItems.push({
|
||||
text: i18n.ts.renameFile,
|
||||
icon: 'ti ti-forms',
|
||||
action: () => { rename(file); },
|
||||
}, {
|
||||
text: file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
|
||||
icon: file.isSensitive ? 'ti ti-eye-exclamation' : 'ti ti-eye',
|
||||
action: () => { toggleSensitive(file); },
|
||||
}, {
|
||||
text: i18n.ts.describeFile,
|
||||
icon: 'ti ti-text-caption',
|
||||
action: () => { describe(file); },
|
||||
});
|
||||
|
||||
if (isImage) {
|
||||
const menuItems: MenuItem[] = [];
|
||||
menuItems.push({
|
||||
text: i18n.ts.preview,
|
||||
icon: 'ti ti-photo-search',
|
||||
action: async () => {
|
||||
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImgPreviewDialog.vue').then(x => x.default), {
|
||||
file: file,
|
||||
}, {
|
||||
closed: () => dispose(),
|
||||
});
|
||||
},
|
||||
text: i18n.ts.renameFile,
|
||||
icon: 'ti ti-forms',
|
||||
action: () => { renameDriveFile(file); },
|
||||
}, {
|
||||
text: file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
|
||||
icon: file.isSensitive ? 'ti ti-eye-exclamation' : 'ti ti-eye',
|
||||
action: () => { toggleDriveFileSensitivity(file); },
|
||||
}, {
|
||||
text: i18n.ts.describeFile,
|
||||
icon: 'ti ti-text-caption',
|
||||
action: () => { describeDriveFile(file); },
|
||||
});
|
||||
}
|
||||
|
||||
menuItems.push({
|
||||
type: 'divider',
|
||||
}, {
|
||||
text: i18n.ts.attachCancel,
|
||||
icon: 'ti ti-circle-x',
|
||||
action: () => { detachMedia(file.id); },
|
||||
}, {
|
||||
text: i18n.ts.deleteFile,
|
||||
icon: 'ti ti-trash',
|
||||
danger: true,
|
||||
action: () => { detachAndDeleteMedia(file); },
|
||||
});
|
||||
if (isImage) {
|
||||
menuItems.push({
|
||||
text: i18n.ts.preview,
|
||||
icon: 'ti ti-photo-search',
|
||||
action: async () => {
|
||||
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImgPreviewDialog.vue').then(x => x.default), {
|
||||
file: file,
|
||||
}, {
|
||||
closed: () => dispose(),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (prefer.s.devMode) {
|
||||
menuItems.push({ type: 'divider' }, {
|
||||
icon: 'ti ti-hash',
|
||||
text: i18n.ts.copyFileId,
|
||||
action: () => {
|
||||
copyToClipboard(file.id);
|
||||
},
|
||||
menuItems.push({
|
||||
type: 'divider',
|
||||
}, {
|
||||
text: i18n.ts.attachCancel,
|
||||
icon: 'ti ti-circle-x',
|
||||
action: () => { detachMedia(file.id); },
|
||||
}, {
|
||||
text: i18n.ts.deleteFile,
|
||||
icon: 'ti ti-trash',
|
||||
danger: true,
|
||||
action: () => { detachAndDeleteMedia(file); },
|
||||
});
|
||||
}
|
||||
|
||||
os.popupMenu(menuItems, ev.currentTarget ?? ev.target).then(() => menuShowing = false);
|
||||
menuShowing = true;
|
||||
if (prefer.s.devMode) {
|
||||
menuItems.push({ type: 'divider' }, {
|
||||
icon: 'ti ti-hash',
|
||||
text: i18n.ts.copyFileId,
|
||||
action: () => {
|
||||
copyToClipboard(file.id);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
|
||||
} else if (attach.type === 'uploaderItem') {
|
||||
emit('showUploaderMenu', attach.file, ev);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -222,13 +282,16 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | Keyboar
|
|||
width: 64px;
|
||||
height: 64px;
|
||||
margin-right: 4px;
|
||||
border-radius: 4px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
|
||||
&:focus-visible {
|
||||
outline-offset: 4px;
|
||||
}
|
||||
|
||||
&.dragEnabled {
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
|
@ -238,6 +301,24 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | Keyboar
|
|||
color: var(--MI_THEME-fg);
|
||||
}
|
||||
|
||||
.uploaderThumbnail {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.uploaderThumbnailIcon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
pointer-events: none;
|
||||
margin: auto;
|
||||
font-size: 32px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.sensitive {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
|
@ -263,4 +344,89 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | Keyboar
|
|||
color: var(--MI_THEME-error);
|
||||
}
|
||||
}
|
||||
|
||||
.uploadProgressWrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
mask-image: linear-gradient(#000, #000), url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNTAiIC8+PC9zdmc+");
|
||||
mask-position: center;
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: 100% 100%, 90px 90px;
|
||||
mask-composite: exclude;
|
||||
transition: mask-size 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.uploadProgressSvg {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.uploadProgressFg {
|
||||
fill: none;
|
||||
stroke-width: 32;
|
||||
stroke: rgba(0, 0, 0, 0.75);
|
||||
stroke-dashoffset: 25;
|
||||
transition: stroke-dasharray 0.2s ease;
|
||||
}
|
||||
|
||||
.uploadAbortButton {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uploadProgressWrapper:global(.uploading) {
|
||||
backdrop-filter: brightness(1.5);
|
||||
|
||||
&::before {
|
||||
mask-size: 100% 100%, 36px 36px;
|
||||
}
|
||||
|
||||
.uploadProgressSvg {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.file:hover .uploadProgressWrapper:global(.uploading) {
|
||||
.uploadProgressSvg {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.uploadAbortButton {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -948,6 +948,7 @@ watch([
|
|||
chatShowSenderName,
|
||||
useStickyIcons,
|
||||
enableHighQualityImagePlaceholders,
|
||||
disableShowingAnimatedImages,
|
||||
keepScreenOn,
|
||||
contextMenu,
|
||||
fontSize,
|
||||
|
@ -958,6 +959,8 @@ watch([
|
|||
enablePullToRefresh,
|
||||
reduceAnimation,
|
||||
showAvailableReactionsFirstInNote,
|
||||
animatedMfm,
|
||||
advancedMfm,
|
||||
], () => {
|
||||
suggestReload();
|
||||
});
|
||||
|
|
|
@ -511,7 +511,7 @@ export const PREF_DEF = definePreferences({
|
|||
default: false,
|
||||
},
|
||||
'experimental.enableFolderPageView': {
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
'experimental.enableHapticFeedback': {
|
||||
default: false,
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export type DetectableFileType =
|
||||
| 'image'
|
||||
| 'video'
|
||||
| 'midi'
|
||||
| 'audio'
|
||||
| 'csv'
|
||||
| 'pdf'
|
||||
| 'textfile'
|
||||
| 'archive'
|
||||
| 'unknown';
|
||||
|
||||
export function getFileType(type: string): DetectableFileType {
|
||||
if (type.startsWith('image/')) return 'image';
|
||||
if (type.startsWith('video/')) return 'video';
|
||||
if (type === 'audio/midi') return 'midi';
|
||||
if (type.startsWith('audio/')) return 'audio';
|
||||
if (type.endsWith('/csv')) return 'csv';
|
||||
if (type.endsWith('/pdf')) return 'pdf';
|
||||
if (type.startsWith('text/')) return 'textfile';
|
||||
if ([
|
||||
'application/zip',
|
||||
'application/x-cpio',
|
||||
'application/x-bzip',
|
||||
'application/x-bzip2',
|
||||
'application/java-archive',
|
||||
'application/x-rar-compressed',
|
||||
'application/x-tar',
|
||||
'application/gzip',
|
||||
'application/x-7z-compressed',
|
||||
].some(archiveType => archiveType === type)) return 'archive';
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
export function getFileTypeIcon(type: DetectableFileType) {
|
||||
switch (type) {
|
||||
case 'image': return 'ti ti-photo';
|
||||
case 'video': return 'ti ti-video';
|
||||
|
||||
case 'audio':
|
||||
case 'midi':
|
||||
return 'ti ti-file-music';
|
||||
|
||||
case 'csv':
|
||||
case 'pdf':
|
||||
case 'textfile':
|
||||
return 'ti ti-file-text';
|
||||
|
||||
case 'archive': return 'ti ti-file-zip';
|
||||
|
||||
default: return 'ti ti-file';
|
||||
}
|
||||
}
|
|
@ -11,16 +11,16 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.18.1",
|
||||
"@types/node": "22.18.6",
|
||||
"@types/wawoff2": "1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0"
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tabler/icons-webfont": "3.34.1",
|
||||
"harfbuzzjs": "0.4.11",
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
"harfbuzzjs": "0.4.12",
|
||||
"tiny-glob": "0.2.9",
|
||||
"tsx": "4.20.5",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "5.9.2",
|
||||
"wawoff2": "2.0.1"
|
||||
},
|
||||
|
|
|
@ -22,15 +22,15 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/matter-js": "0.20.0",
|
||||
"@types/matter-js": "0.20.2",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"nodemon": "3.1.10",
|
||||
"execa": "9.6.0",
|
||||
"typescript": "5.9.2",
|
||||
"esbuild": "0.25.9",
|
||||
"esbuild": "0.25.10",
|
||||
"glob": "11.0.3"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@readme/openapi-parser": "5.0.1",
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"openapi-types": "12.1.3",
|
||||
"openapi-typescript": "7.9.1",
|
||||
"ts-case-convert": "2.1.0",
|
||||
"tsx": "4.20.5",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "5.9.2"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2025.9.1-alpha.2",
|
||||
"version": "2025.10.0-beta.0",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
@ -35,12 +35,12 @@
|
|||
"directory": "packages/misskey-js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-extractor": "7.52.11",
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@microsoft/api-extractor": "7.52.13",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"esbuild": "0.25.9",
|
||||
"esbuild": "0.25.10",
|
||||
"execa": "9.6.0",
|
||||
"glob": "11.0.3",
|
||||
"ncp": "2.0.0",
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@types/node": "22.18.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.44.1",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"execa": "9.6.0",
|
||||
"nodemon": "3.1.10",
|
||||
"typescript": "5.9.2",
|
||||
"esbuild": "0.25.9",
|
||||
"esbuild": "0.25.10",
|
||||
"glob": "11.0.3"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"esbuild": "0.25.9",
|
||||
"esbuild": "0.25.10",
|
||||
"idb-keyval": "6.2.2",
|
||||
"misskey-js": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/parser": "8.42.0",
|
||||
"@typescript-eslint/parser": "8.44.1",
|
||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"nodemon": "3.1.10",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
diff --git a/driver/postgres/PostgresDriver.js b/driver/postgres/PostgresDriver.js
|
||||
index 278f29c1f3deec4939bb4ed90e6edae167f704e0..9a84c3098dda915d6c33e24d925a8fa09af9095e 100644
|
||||
index e13b903c73b71113bb529552e59fb4ce0ca8af0c..50de6a60120ece7ebf49009eac588a5313343f39 100644
|
||||
--- a/driver/postgres/PostgresDriver.js
|
||||
+++ b/driver/postgres/PostgresDriver.js
|
||||
@@ -785,10 +785,10 @@ class PostgresDriver {
|
||||
@@ -819,10 +819,10 @@ class PostgresDriver {
|
||||
const tableColumnDefault = typeof tableColumn.default === "string"
|
||||
? JSON.parse(tableColumn.default.substring(1, tableColumn.default.length - 1))
|
||||
: tableColumn.default;
|
||||
|
|
4423
pnpm-lock.yaml
4423
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@
|
|||
dependencyDashboardAutoclose: true,
|
||||
osvVulnerabilityAlerts: true,
|
||||
dependencyDashboardOSVVulnerabilitySummary: 'unresolved',
|
||||
minimumReleaseAge: '7 days',
|
||||
ignoreDeps: [
|
||||
// https://github.com/misskey-dev/misskey/pull/15489#issuecomment-2660717458
|
||||
'@typescript/lib-webworker',
|
||||
|
|
Loading…
Reference in New Issue