Merge remote-tracking branch 'msky/develop' into deps-update-pnpm
This commit is contained in:
commit
0c61097917
|
@ -5,7 +5,12 @@
|
||||||
- Fix: システムアカウントが削除できる問題を修正
|
- Fix: システムアカウントが削除できる問題を修正
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
-
|
- Enhance: モデレーターがセンシティブ設定を変更する際に確認ダイアログを出すように
|
||||||
|
- Enhance: ユーザーページのノート一覧と前後のノート表示でチャンネルのノートを含めるように
|
||||||
|
- Enhance: 「UIのアニメーションを減らす」で画面上のエフェクトも減らせるように
|
||||||
|
- Fix: 削除して編集の削除タイミングを投稿後になるように `#14498`
|
||||||
|
- Fix: フォローされたときのメッセージがちらつくことがある問題を修正
|
||||||
|
- Fix: 投稿ダイアログがサイズ限界を超えた際にスクロールできない問題を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
|
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
|
||||||
|
|
|
@ -5262,6 +5262,14 @@ export interface Locale extends ILocale {
|
||||||
* " {emoji} " をリアクションしますか?
|
* " {emoji} " をリアクションしますか?
|
||||||
*/
|
*/
|
||||||
"reactAreYouSure": ParameterizedString<"emoji">;
|
"reactAreYouSure": ParameterizedString<"emoji">;
|
||||||
|
/**
|
||||||
|
* このメディアをセンシティブとして設定しますか?
|
||||||
|
*/
|
||||||
|
"markAsSensitiveConfirm": string;
|
||||||
|
/**
|
||||||
|
* このメディアのセンシティブ指定を解除しますか?
|
||||||
|
*/
|
||||||
|
"unmarkAsSensitiveConfirm": string;
|
||||||
"_accountSettings": {
|
"_accountSettings": {
|
||||||
/**
|
/**
|
||||||
* コンテンツの表示にログインを必須にする
|
* コンテンツの表示にログインを必須にする
|
||||||
|
|
|
@ -1311,6 +1311,8 @@ federationSpecified: "このサーバーはホワイトリスト連合で運用
|
||||||
federationDisabled: "このサーバーは連合が無効化されています。他のサーバーのユーザーとやり取りすることはできません。"
|
federationDisabled: "このサーバーは連合が無効化されています。他のサーバーのユーザーとやり取りすることはできません。"
|
||||||
confirmOnReact: "リアクションする際に確認する"
|
confirmOnReact: "リアクションする際に確認する"
|
||||||
reactAreYouSure: "\" {emoji} \" をリアクションしますか?"
|
reactAreYouSure: "\" {emoji} \" をリアクションしますか?"
|
||||||
|
markAsSensitiveConfirm: "このメディアをセンシティブとして設定しますか?"
|
||||||
|
unmarkAsSensitiveConfirm: "このメディアのセンシティブ指定を解除しますか?"
|
||||||
|
|
||||||
_accountSettings:
|
_accountSettings:
|
||||||
requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
|
requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
"misskey-js": "workspace:*",
|
"misskey-js": "workspace:*",
|
||||||
"frontend-shared": "workspace:*",
|
"frontend-shared": "workspace:*",
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"rollup": "4.34.8",
|
"rollup": "4.34.9",
|
||||||
"sass": "1.85.1",
|
"sass": "1.85.1",
|
||||||
"shiki": "3.1.0",
|
"shiki": "3.1.0",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"@types/micromatch": "4.0.9",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "22.13.7",
|
"@types/node": "22.13.8",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@types/ws": "8.5.14",
|
"@types/ws": "8.5.14",
|
||||||
|
@ -60,11 +60,11 @@
|
||||||
"micromatch": "4.0.8",
|
"micromatch": "4.0.8",
|
||||||
"msw": "2.7.3",
|
"msw": "2.7.3",
|
||||||
"nodemon": "3.1.9",
|
"nodemon": "3.1.9",
|
||||||
"prettier": "3.5.2",
|
"prettier": "3.5.3",
|
||||||
"start-server-and-test": "2.0.10",
|
"start-server-and-test": "2.0.10",
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
"vue-component-type-helpers": "2.2.4",
|
"vue-component-type-helpers": "2.2.8",
|
||||||
"vue-eslint-parser": "9.4.3",
|
"vue-eslint-parser": "9.4.3",
|
||||||
"vue-tsc": "2.2.4"
|
"vue-tsc": "2.2.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "22.13.7",
|
"@types/node": "22.13.8",
|
||||||
"@typescript-eslint/eslint-plugin": "8.25.0",
|
"@typescript-eslint/eslint-plugin": "8.25.0",
|
||||||
"@typescript-eslint/parser": "8.25.0",
|
"@typescript-eslint/parser": "8.25.0",
|
||||||
"esbuild": "0.25.0",
|
"esbuild": "0.25.0",
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
"chartjs-plugin-zoom": "2.2.0",
|
"chartjs-plugin-zoom": "2.2.0",
|
||||||
"chromatic": "11.26.1",
|
"chromatic": "11.26.1",
|
||||||
"compare-versions": "6.1.1",
|
"compare-versions": "6.1.1",
|
||||||
"cropperjs": "2.0.0-rc.2",
|
"cropperjs": "2.0.0",
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
"estree-walker": "3.0.3",
|
"estree-walker": "3.0.3",
|
||||||
"eventemitter3": "5.0.1",
|
"eventemitter3": "5.0.1",
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
"misskey-reversi": "workspace:*",
|
"misskey-reversi": "workspace:*",
|
||||||
"photoswipe": "5.4.4",
|
"photoswipe": "5.4.4",
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"rollup": "4.34.8",
|
"rollup": "4.34.9",
|
||||||
"sanitize-html": "2.14.0",
|
"sanitize-html": "2.14.0",
|
||||||
"sass": "1.85.1",
|
"sass": "1.85.1",
|
||||||
"shiki": "3.1.0",
|
"shiki": "3.1.0",
|
||||||
|
@ -78,30 +78,30 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/summaly": "5.2.0",
|
"@misskey-dev/summaly": "5.2.0",
|
||||||
"@storybook/addon-actions": "8.6.2",
|
"@storybook/addon-actions": "8.6.3",
|
||||||
"@storybook/addon-essentials": "8.6.2",
|
"@storybook/addon-essentials": "8.6.3",
|
||||||
"@storybook/addon-interactions": "8.6.2",
|
"@storybook/addon-interactions": "8.6.3",
|
||||||
"@storybook/addon-links": "8.6.2",
|
"@storybook/addon-links": "8.6.3",
|
||||||
"@storybook/addon-mdx-gfm": "8.6.2",
|
"@storybook/addon-mdx-gfm": "8.6.3",
|
||||||
"@storybook/addon-storysource": "8.6.2",
|
"@storybook/addon-storysource": "8.6.3",
|
||||||
"@storybook/blocks": "8.6.2",
|
"@storybook/blocks": "8.6.3",
|
||||||
"@storybook/components": "8.6.2",
|
"@storybook/components": "8.6.3",
|
||||||
"@storybook/core-events": "8.6.2",
|
"@storybook/core-events": "8.6.3",
|
||||||
"@storybook/manager-api": "8.6.2",
|
"@storybook/manager-api": "8.6.3",
|
||||||
"@storybook/preview-api": "8.6.2",
|
"@storybook/preview-api": "8.6.3",
|
||||||
"@storybook/react": "8.6.2",
|
"@storybook/react": "8.6.3",
|
||||||
"@storybook/react-vite": "8.6.2",
|
"@storybook/react-vite": "8.6.3",
|
||||||
"@storybook/test": "8.6.2",
|
"@storybook/test": "8.6.3",
|
||||||
"@storybook/theming": "8.6.2",
|
"@storybook/theming": "8.6.3",
|
||||||
"@storybook/types": "8.6.2",
|
"@storybook/types": "8.6.3",
|
||||||
"@storybook/vue3": "8.6.2",
|
"@storybook/vue3": "8.6.3",
|
||||||
"@storybook/vue3-vite": "8.6.2",
|
"@storybook/vue3-vite": "8.6.3",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/canvas-confetti": "1.9.0",
|
"@types/canvas-confetti": "1.9.0",
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"@types/matter-js": "0.19.8",
|
"@types/matter-js": "0.19.8",
|
||||||
"@types/micromatch": "4.0.9",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "22.13.7",
|
"@types/node": "22.13.8",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/sanitize-html": "2.13.0",
|
"@types/sanitize-html": "2.13.0",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
|
@ -124,18 +124,18 @@
|
||||||
"msw": "2.7.3",
|
"msw": "2.7.3",
|
||||||
"msw-storybook-addon": "2.0.4",
|
"msw-storybook-addon": "2.0.4",
|
||||||
"nodemon": "3.1.9",
|
"nodemon": "3.1.9",
|
||||||
"prettier": "3.5.2",
|
"prettier": "3.5.3",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"start-server-and-test": "2.0.10",
|
"start-server-and-test": "2.0.10",
|
||||||
"storybook": "8.6.2",
|
"storybook": "8.6.3",
|
||||||
"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": "3.0.7",
|
"vitest": "3.0.7",
|
||||||
"vitest-fetch-mock": "0.4.4",
|
"vitest-fetch-mock": "0.4.4",
|
||||||
"vue-component-type-helpers": "2.2.4",
|
"vue-component-type-helpers": "2.2.8",
|
||||||
"vue-eslint-parser": "9.4.3",
|
"vue-eslint-parser": "9.4.3",
|
||||||
"vue-tsc": "2.2.4"
|
"vue-tsc": "2.2.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,7 +413,7 @@ function computeButtonTitle(ev: MouseEvent): void {
|
||||||
|
|
||||||
function chosen(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef, ev?: MouseEvent) {
|
function chosen(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef, ev?: MouseEvent) {
|
||||||
const el = ev && (ev.currentTarget ?? ev.target) as HTMLElement | null | undefined;
|
const el = ev && (ev.currentTarget ?? ev.target) as HTMLElement | null | undefined;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
|
|
@ -259,7 +259,14 @@ function showMenu(ev: MouseEvent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
async function toggleSensitive(file: Misskey.entities.DriveFile) {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: file.isSensitive ? i18n.ts.unmarkAsSensitiveConfirm : i18n.ts.markAsSensitiveConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
os.apiWithDialog('drive/files/update', {
|
os.apiWithDialog('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
isSensitive: !file.isSensitive,
|
isSensitive: !file.isSensitive,
|
||||||
|
|
|
@ -124,11 +124,21 @@ function showMenu(ev: MouseEvent) {
|
||||||
|
|
||||||
if (iAmModerator) {
|
if (iAmModerator) {
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
text: i18n.ts.markAsSensitive,
|
text: props.image.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
|
||||||
icon: 'ti ti-eye-exclamation',
|
icon: 'ti ti-eye-exclamation',
|
||||||
danger: true,
|
danger: true,
|
||||||
action: () => {
|
action: async () => {
|
||||||
os.apiWithDialog('drive/files/update', { fileId: props.image.id, isSensitive: true });
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: props.image.isSensitive ? i18n.ts.unmarkAsSensitiveConfirm : i18n.ts.markAsSensitiveConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
os.apiWithDialog('drive/files/update', {
|
||||||
|
fileId: props.image.id,
|
||||||
|
isSensitive: !props.image.isSensitive,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,7 +284,14 @@ function showMenu(ev: MouseEvent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
async function toggleSensitive(file: Misskey.entities.DriveFile) {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: file.isSensitive ? i18n.ts.unmarkAsSensitiveConfirm : i18n.ts.markAsSensitiveConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
os.apiWithDialog('drive/files/update', {
|
os.apiWithDialog('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
isSensitive: !file.isSensitive,
|
isSensitive: !file.isSensitive,
|
||||||
|
|
|
@ -479,7 +479,7 @@ function react(): void {
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
});
|
});
|
||||||
const el = reactButton.value;
|
const el = reactButton.value;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
|
|
@ -442,7 +442,7 @@ function react(): void {
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
});
|
});
|
||||||
const el = reactButton.value;
|
const el = reactButton.value;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
|
|
@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
|
<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
|
||||||
<div v-show="useCw" :class="$style.cwOuter">
|
<div v-show="useCw" :class="$style.cwOuter">
|
||||||
<input ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown" @keyup="onKeyup" @compositionend="onCompositionEnd">
|
<input ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown" @keyup="onKeyup" @compositionend="onCompositionEnd">
|
||||||
<div v-if="maxCwTextLength - cwTextLength < 20" :class="['_acrylic', $style.cwTextCount, { [$style.cwTextOver]: cwTextLength > maxCwTextLength }]">{{ maxCwTextLength - cwTextLength }}</div>
|
<div v-if="maxCwTextLength - cwTextLength < 20" :class="['_acrylic', $style.cwTextCount, { [$style.cwTextOver]: cwTextLength > maxCwTextLength }]">{{ maxCwTextLength - cwTextLength }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="[$style.textOuter, { [$style.withCw]: useCw }]">
|
<div :class="[$style.textOuter, { [$style.withCw]: useCw }]">
|
||||||
<div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div>
|
<div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div>
|
||||||
|
@ -104,18 +104,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed } from 'vue';
|
import { inject, watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed } from 'vue';
|
||||||
import type { ShallowRef } from 'vue';
|
|
||||||
import * as mfm from 'mfm-js';
|
import * as mfm from 'mfm-js';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||||
import { toASCII } from 'punycode.js';
|
import { toASCII } from 'punycode.js';
|
||||||
import { host, url } from '@@/js/config.js';
|
import { host, url } from '@@/js/config.js';
|
||||||
|
import type { ShallowRef } from 'vue';
|
||||||
import type { PostFormProps } from '@/types/post-form.js';
|
import type { PostFormProps } from '@/types/post-form.js';
|
||||||
import MkNoteSimple from '@/components/MkNoteSimple.vue';
|
import type { PollEditorModelValue } from '@/components/MkPollEditor.vue';
|
||||||
import MkNotePreview from '@/components/MkNotePreview.vue';
|
import MkNotePreview from '@/components/MkNotePreview.vue';
|
||||||
import XPostFormAttaches from '@/components/MkPostFormAttaches.vue';
|
import XPostFormAttaches from '@/components/MkPostFormAttaches.vue';
|
||||||
import MkPollEditor from '@/components/MkPollEditor.vue';
|
import MkPollEditor from '@/components/MkPollEditor.vue';
|
||||||
import type { PollEditorModelValue } from '@/components/MkPollEditor.vue';
|
import MkNoteSimple from '@/components/MkNoteSimple.vue';
|
||||||
import { erase, unique } from '@/scripts/array.js';
|
import { erase, unique } from '@/scripts/array.js';
|
||||||
import { extractMentions } from '@/scripts/extract-mentions.js';
|
import { extractMentions } from '@/scripts/extract-mentions.js';
|
||||||
import { formatTimeString } from '@/scripts/format-time-string.js';
|
import { formatTimeString } from '@/scripts/format-time-string.js';
|
||||||
|
@ -150,6 +150,7 @@ const props = withDefaults(defineProps<PostFormProps & {
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
mock: false,
|
mock: false,
|
||||||
initialLocalOnly: undefined,
|
initialLocalOnly: undefined,
|
||||||
|
deleteInitialNoteAfterPost: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
provide('mock', props.mock);
|
provide('mock', props.mock);
|
||||||
|
@ -751,7 +752,7 @@ async function post(ev?: MouseEvent) {
|
||||||
if (ev) {
|
if (ev) {
|
||||||
const el = (ev.currentTarget ?? ev.target) as HTMLElement | null;
|
const el = (ev.currentTarget ?? ev.target) as HTMLElement | null;
|
||||||
|
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
@ -845,6 +846,12 @@ async function post(ev?: MouseEvent) {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
// 削除して編集の対象ノートを削除
|
||||||
|
if (props.initialNote && props.deleteInitialNoteAfterPost) {
|
||||||
|
misskeyApi('notes/delete', {
|
||||||
|
noteId: props.initialNote.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
deleteDraft();
|
deleteDraft();
|
||||||
emit('posted');
|
emit('posted');
|
||||||
if (postData.text && postData.text !== '') {
|
if (postData.text && postData.text !== '') {
|
||||||
|
@ -896,6 +903,11 @@ async function post(ev?: MouseEvent) {
|
||||||
if (m === 0 && s === 0) {
|
if (m === 0 && s === 0) {
|
||||||
claimAchievement('postedAt0min0sec');
|
claimAchievement('postedAt0min0sec');
|
||||||
}
|
}
|
||||||
|
if (props.initialNote && props.deleteInitialNoteAfterPost) {
|
||||||
|
if (date.getTime() - new Date(props.initialNote.createdAt).getTime() < 1000 * 60 && props.initialNote.userId === $i.id) {
|
||||||
|
claimAchievement('noteDeletedWithin1min');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
posting.value = false;
|
posting.value = false;
|
||||||
|
@ -1070,6 +1082,8 @@ defineExpose({
|
||||||
&.modal {
|
&.modal {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 520px;
|
max-width: 520px;
|
||||||
|
overflow-x: clip;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,23 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MkModal ref="modal" :preferType="'dialog'" @click="modal?.close()" @closed="onModalClosed()" @esc="modal?.close()">
|
<MkModal
|
||||||
<MkPostForm ref="form" :class="$style.form" v-bind="props" autofocus freezeAfterPosted @posted="onPosted" @cancel="modal?.close()" @esc="modal?.close()"/>
|
ref="modal"
|
||||||
|
:preferType="'dialog'"
|
||||||
|
@click="modal?.close()"
|
||||||
|
@closed="onModalClosed()"
|
||||||
|
@esc="modal?.close()"
|
||||||
|
>
|
||||||
|
<MkPostForm
|
||||||
|
ref="form"
|
||||||
|
:class="$style.form"
|
||||||
|
v-bind="props"
|
||||||
|
autofocus
|
||||||
|
freezeAfterPosted
|
||||||
|
@posted="onPosted"
|
||||||
|
@cancel="modal?.close()"
|
||||||
|
@esc="modal?.close()"
|
||||||
|
/>
|
||||||
</MkModal>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||||
|
import { defaultStore } from '@/store.js';
|
||||||
import { popup } from '@/os.js';
|
import { popup } from '@/os.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted(el, binding, vn) {
|
mounted(el, binding, vn) {
|
||||||
// 明示的に false であればバインドしない
|
// 明示的に false であればバインドしない
|
||||||
if (binding.value === false) return;
|
if (binding.value === false) return;
|
||||||
|
if (!defaultStore.state.animation) return;
|
||||||
|
|
||||||
el.addEventListener('click', () => {
|
el.addEventListener('click', () => {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
|
|
|
@ -36,8 +36,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkA v-if="file.user" class="user" :to="`/admin/user/${file.user.id}`">
|
<MkA v-if="file.user" class="user" :to="`/admin/user/${file.user.id}`">
|
||||||
<MkUserCardMini :user="file.user"/>
|
<MkUserCardMini :user="file.user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<MkSwitch v-model="isSensitive" @update:modelValue="toggleIsSensitive">{{ i18n.ts.sensitive }}</MkSwitch>
|
<MkSwitch :modelValue="isSensitive" @update:modelValue="toggleSensitive">{{ i18n.ts.sensitive }}</MkSwitch>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -117,9 +118,21 @@ async function del() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleIsSensitive(v) {
|
async function toggleSensitive() {
|
||||||
await misskeyApi('drive/files/update', { fileId: props.fileId, isSensitive: v });
|
if (!file.value) return;
|
||||||
isSensitive.value = v;
|
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: isSensitive.value ? i18n.ts.unmarkAsSensitiveConfirm : i18n.ts.markAsSensitiveConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (canceled) return;
|
||||||
|
isSensitive.value = !isSensitive.value;
|
||||||
|
|
||||||
|
os.apiWithDialog('drive/files/update', {
|
||||||
|
fileId: file.value.id,
|
||||||
|
isSensitive: !file.value.isSensitive,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = computed(() => [{
|
const headerActions = computed(() => [{
|
||||||
|
|
|
@ -87,6 +87,7 @@ const prevUserPagination: Paging = {
|
||||||
params: computed(() => note.value ? ({
|
params: computed(() => note.value ? ({
|
||||||
userId: note.value.userId,
|
userId: note.value.userId,
|
||||||
untilId: note.value.id,
|
untilId: note.value.id,
|
||||||
|
withChannelNotes: true,
|
||||||
}) : undefined),
|
}) : undefined),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,6 +98,8 @@ const nextUserPagination: Paging = {
|
||||||
params: computed(() => note.value ? ({
|
params: computed(() => note.value ? ({
|
||||||
userId: note.value.userId,
|
userId: note.value.userId,
|
||||||
sinceId: note.value.id,
|
sinceId: note.value.id,
|
||||||
|
withChannelNotes: true,
|
||||||
|
includeSensitiveChannel: $i != null,
|
||||||
}) : undefined),
|
}) : undefined),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
|
import { apLookup } from '@/scripts/lookup.js';
|
||||||
import { useRouter } from '@/router/supplier.js';
|
import { useRouter } from '@/router/supplier.js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
|
@ -260,13 +261,7 @@ async function search() {
|
||||||
text: i18n.ts.lookupConfirm,
|
text: i18n.ts.lookupConfirm,
|
||||||
});
|
});
|
||||||
if (!confirm.canceled) {
|
if (!confirm.canceled) {
|
||||||
const promise = misskeyApi('ap/show', {
|
const res = await apLookup(searchParams.value.query);
|
||||||
uri: searchParams.value.query,
|
|
||||||
});
|
|
||||||
|
|
||||||
os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
|
|
||||||
|
|
||||||
const res = await promise;
|
|
||||||
|
|
||||||
if (res.type === 'User') {
|
if (res.type === 'User') {
|
||||||
router.push(`/@${res.object.username}@${res.object.host}`);
|
router.push(`/@${res.object.username}@${res.object.host}`);
|
||||||
|
|
|
@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="user.followedMessage != null" class="followedMessage">
|
<div v-if="user.followedMessage != null" class="followedMessage">
|
||||||
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin shadow>
|
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin>
|
||||||
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
|
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
|
||||||
<div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user"/></MkSparkle></div>
|
<div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user"/></MkSparkle></div>
|
||||||
</MkFukidashi>
|
</MkFukidashi>
|
||||||
|
|
|
@ -43,7 +43,7 @@ const pagination = computed(() => tab.value === 'featured' ? {
|
||||||
userId: props.user.id,
|
userId: props.user.id,
|
||||||
withRenotes: tab.value === 'all',
|
withRenotes: tab.value === 'all',
|
||||||
withReplies: tab.value === 'all',
|
withReplies: tab.value === 'all',
|
||||||
withChannelNotes: tab.value === 'all',
|
withChannelNotes: true,
|
||||||
withFiles: tab.value === 'files',
|
withFiles: tab.value === 'files',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
import type { Ref, ShallowRef } from 'vue';
|
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { url } from '@@/js/config.js';
|
import { url } from '@@/js/config.js';
|
||||||
import { claimAchievement } from './achievements.js';
|
import { claimAchievement } from './achievements.js';
|
||||||
|
import type { Ref, ShallowRef } from 'vue';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
@ -208,15 +208,7 @@ export function getNoteMenu(props: {
|
||||||
}).then(({ canceled }) => {
|
}).then(({ canceled }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
misskeyApi('notes/delete', {
|
os.post({ initialNote: appearNote, renote: appearNote.renote, reply: appearNote.reply, channel: appearNote.channel, deleteInitialNoteAfterPost: true });
|
||||||
noteId: appearNote.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
os.post({ initialNote: appearNote, renote: appearNote.renote, reply: appearNote.reply, channel: appearNote.channel });
|
|
||||||
|
|
||||||
if (Date.now() - new Date(appearNote.createdAt).getTime() < 1000 * 60 && appearNote.userId === $i.id) {
|
|
||||||
claimAchievement('noteDeletedWithin1min');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,7 +550,7 @@ export function getRenoteMenu(props: {
|
||||||
icon: 'ti ti-repeat',
|
icon: 'ti ti-repeat',
|
||||||
action: () => {
|
action: () => {
|
||||||
const el = props.renoteButton.value;
|
const el = props.renoteButton.value;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
@ -596,7 +588,7 @@ export function getRenoteMenu(props: {
|
||||||
icon: 'ti ti-repeat',
|
icon: 'ti ti-repeat',
|
||||||
action: () => {
|
action: () => {
|
||||||
const el = props.renoteButton.value;
|
const el = props.renoteButton.value;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
@ -647,7 +639,7 @@ export function getRenoteMenu(props: {
|
||||||
text: channel.name,
|
text: channel.name,
|
||||||
action: () => {
|
action: () => {
|
||||||
const el = props.renoteButton.value;
|
const el = props.renoteButton.value;
|
||||||
if (el) {
|
if (el && defaultStore.state.animation) {
|
||||||
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);
|
||||||
|
|
|
@ -29,45 +29,7 @@ export async function lookup(router?: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.startsWith('https://')) {
|
if (query.startsWith('https://')) {
|
||||||
const promise = misskeyApi('ap/show', {
|
const res = await apLookup(query);
|
||||||
uri: query,
|
|
||||||
});
|
|
||||||
|
|
||||||
os.promiseDialog(promise, null, (err) => {
|
|
||||||
let title = i18n.ts.somethingHappened;
|
|
||||||
let text = err.message + '\n' + err.id;
|
|
||||||
|
|
||||||
switch (err.id) {
|
|
||||||
case '974b799e-1a29-4889-b706-18d4dd93e266':
|
|
||||||
title = i18n.ts._remoteLookupErrors._federationNotAllowed.title;
|
|
||||||
text = i18n.ts._remoteLookupErrors._federationNotAllowed.description;
|
|
||||||
break;
|
|
||||||
case '1a5eab56-e47b-48c2-8d5e-217b897d70db':
|
|
||||||
title = i18n.ts._remoteLookupErrors._uriInvalid.title;
|
|
||||||
text = i18n.ts._remoteLookupErrors._uriInvalid.description;
|
|
||||||
break;
|
|
||||||
case '81b539cf-4f57-4b29-bc98-032c33c0792e':
|
|
||||||
title = i18n.ts._remoteLookupErrors._requestFailed.title;
|
|
||||||
text = i18n.ts._remoteLookupErrors._requestFailed.description;
|
|
||||||
break;
|
|
||||||
case '70193c39-54f3-4813-82f0-70a680f7495b':
|
|
||||||
title = i18n.ts._remoteLookupErrors._responseInvalid.title;
|
|
||||||
text = i18n.ts._remoteLookupErrors._responseInvalid.description;
|
|
||||||
break;
|
|
||||||
case 'dc94d745-1262-4e63-a17d-fecaa57efc82':
|
|
||||||
title = i18n.ts._remoteLookupErrors._noSuchObject.title;
|
|
||||||
text = i18n.ts._remoteLookupErrors._noSuchObject.description;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
os.alert({
|
|
||||||
type: 'error',
|
|
||||||
title,
|
|
||||||
text,
|
|
||||||
});
|
|
||||||
}, i18n.ts.fetchingAsApObject);
|
|
||||||
|
|
||||||
const res = await promise;
|
|
||||||
|
|
||||||
if (res.type === 'User') {
|
if (res.type === 'User') {
|
||||||
_router.push(`/@${res.object.username}@${res.object.host}`);
|
_router.push(`/@${res.object.username}@${res.object.host}`);
|
||||||
|
@ -78,3 +40,45 @@ export async function lookup(router?: Router) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function apLookup(query: string) {
|
||||||
|
const promise = misskeyApi('ap/show', {
|
||||||
|
uri: query,
|
||||||
|
});
|
||||||
|
|
||||||
|
os.promiseDialog(promise, null, (err) => {
|
||||||
|
let title = i18n.ts.somethingHappened;
|
||||||
|
let text = err.message + '\n' + err.id;
|
||||||
|
|
||||||
|
switch (err.id) {
|
||||||
|
case '974b799e-1a29-4889-b706-18d4dd93e266':
|
||||||
|
title = i18n.ts._remoteLookupErrors._federationNotAllowed.title;
|
||||||
|
text = i18n.ts._remoteLookupErrors._federationNotAllowed.description;
|
||||||
|
break;
|
||||||
|
case '1a5eab56-e47b-48c2-8d5e-217b897d70db':
|
||||||
|
title = i18n.ts._remoteLookupErrors._uriInvalid.title;
|
||||||
|
text = i18n.ts._remoteLookupErrors._uriInvalid.description;
|
||||||
|
break;
|
||||||
|
case '81b539cf-4f57-4b29-bc98-032c33c0792e':
|
||||||
|
title = i18n.ts._remoteLookupErrors._requestFailed.title;
|
||||||
|
text = i18n.ts._remoteLookupErrors._requestFailed.description;
|
||||||
|
break;
|
||||||
|
case '70193c39-54f3-4813-82f0-70a680f7495b':
|
||||||
|
title = i18n.ts._remoteLookupErrors._responseInvalid.title;
|
||||||
|
text = i18n.ts._remoteLookupErrors._responseInvalid.description;
|
||||||
|
break;
|
||||||
|
case 'dc94d745-1262-4e63-a17d-fecaa57efc82':
|
||||||
|
title = i18n.ts._remoteLookupErrors._noSuchObject.title;
|
||||||
|
text = i18n.ts._remoteLookupErrors._noSuchObject.description;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
os.alert({
|
||||||
|
type: 'error',
|
||||||
|
title,
|
||||||
|
text,
|
||||||
|
});
|
||||||
|
}, i18n.ts.fetchingAsApObject);
|
||||||
|
|
||||||
|
return await promise;
|
||||||
|
}
|
||||||
|
|
|
@ -19,4 +19,5 @@ export interface PostFormProps {
|
||||||
initialVisibleUsers?: Misskey.entities.UserDetailed[];
|
initialVisibleUsers?: Misskey.entities.UserDetailed[];
|
||||||
initialNote?: Misskey.entities.Note;
|
initialNote?: Misskey.entities.Note;
|
||||||
instant?: boolean;
|
instant?: boolean;
|
||||||
|
deleteInitialNoteAfterPost?: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/matter-js": "0.19.8",
|
"@types/matter-js": "0.19.8",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@types/node": "22.13.7",
|
"@types/node": "22.13.8",
|
||||||
"@typescript-eslint/eslint-plugin": "8.25.0",
|
"@typescript-eslint/eslint-plugin": "8.25.0",
|
||||||
"@typescript-eslint/parser": "8.25.0",
|
"@typescript-eslint/parser": "8.25.0",
|
||||||
"nodemon": "3.1.9",
|
"nodemon": "3.1.9",
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "22.13.7",
|
"@types/node": "22.13.8",
|
||||||
"@typescript-eslint/eslint-plugin": "8.25.0",
|
"@typescript-eslint/eslint-plugin": "8.25.0",
|
||||||
"@typescript-eslint/parser": "8.25.0",
|
"@typescript-eslint/parser": "8.25.0",
|
||||||
"execa": "9.5.2",
|
"execa": "9.5.2",
|
||||||
|
|
971
pnpm-lock.yaml
971
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue