diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue
index 7e29f6e0d8..b1cbdad137 100644
--- a/packages/frontend/src/pages/admin/roles.vue
+++ b/packages/frontend/src/pages/admin/roles.vue
@@ -11,6 +11,9 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._role.baseRole }}
+
+ {{ i18n.ts.save }}
+
@@ -214,7 +217,45 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.save }}
+
+ {{ i18n.ts._role._options.canImportAntennas }}
+ {{ policies.canImportAntennas ? i18n.ts.yes : i18n.ts.no }}
+
+ {{ i18n.ts.enable }}
+
+
+
+
+ {{ i18n.ts._role._options.canImportBlocking }}
+ {{ policies.canImportBlocking ? i18n.ts.yes : i18n.ts.no }}
+
+ {{ i18n.ts.enable }}
+
+
+
+
+ {{ i18n.ts._role._options.canImportFollowing }}
+ {{ policies.canImportFollowing ? i18n.ts.yes : i18n.ts.no }}
+
+ {{ i18n.ts.enable }}
+
+
+
+
+ {{ i18n.ts._role._options.canImportMuting }}
+ {{ policies.canImportMuting ? i18n.ts.yes : i18n.ts.no }}
+
+ {{ i18n.ts.enable }}
+
+
+
+
+ {{ i18n.ts._role._options.canImportUserLists }}
+ {{ policies.canImportUserLists ? i18n.ts.yes : i18n.ts.no }}
+
+ {{ i18n.ts.enable }}
+
+
{{ i18n.ts._role.new }}
@@ -240,6 +281,7 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/pages/admin/system-webhook.vue b/packages/frontend/src/pages/admin/system-webhook.vue
index 7a40eec944..c59abda24a 100644
--- a/packages/frontend/src/pages/admin/system-webhook.vue
+++ b/packages/frontend/src/pages/admin/system-webhook.vue
@@ -11,8 +11,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-
- {{ i18n.ts._webhookSettings.createWebhook }}
+
+ {{ i18n.ts._webhookSettings.createWebhook }}
@@ -89,8 +89,5 @@ definePageMetadata(() => ({
diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index 7bfa343b1d..7e5f0423f6 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -45,6 +45,7 @@ import { clipsCache } from '@/cache.js';
import { isSupportShare } from '@/scripts/navigator.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { genEmbedCode } from '@/scripts/get-embed-code.js';
+import type { MenuItem } from '@/types/menu.js';
const props = defineProps<{
clipId: string,
@@ -131,7 +132,9 @@ const headerActions = computed(() => clip.value && isOwned.value ? [{
icon: 'ti ti-share',
text: i18n.ts.share,
handler: (ev: MouseEvent): void => {
- os.popupMenu([{
+ const menuItems: MenuItem[] = [];
+
+ menuItems.push({
icon: 'ti ti-link',
text: i18n.ts.copyUrl,
action: () => {
@@ -144,17 +147,23 @@ const headerActions = computed(() => clip.value && isOwned.value ? [{
action: () => {
genEmbedCode('clips', clip.value!.id);
},
- }, ...(isSupportShare() ? [{
- icon: 'ti ti-share',
- text: i18n.ts.share,
- action: async () => {
- navigator.share({
- title: clip.value!.name,
- text: clip.value!.description ?? '',
- url: `${url}/clips/${clip.value!.id}`,
- });
- },
- }] : [])], ev.currentTarget ?? ev.target);
+ });
+
+ if (isSupportShare()) {
+ menuItems.push({
+ icon: 'ti ti-share',
+ text: i18n.ts.share,
+ action: async () => {
+ navigator.share({
+ title: clip.value!.name,
+ text: clip.value!.description ?? '',
+ url: `${url}/clips/${clip.value!.id}`,
+ });
+ },
+ });
+ }
+
+ os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
},
}] : []), {
icon: 'ti ti-trash',
diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue
index eea3f68130..4747aa5205 100644
--- a/packages/frontend/src/pages/custom-emojis-manager.vue
+++ b/packages/frontend/src/pages/custom-emojis-manager.vue
@@ -344,6 +344,7 @@ definePageMetadata(() => ({
> .img {
width: 42px;
height: 42px;
+ object-fit: contain;
}
> .body {
@@ -390,6 +391,7 @@ definePageMetadata(() => ({
> .img {
width: 32px;
height: 32px;
+ object-fit: contain;
}
> .body {
diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue
index ffedaf27bf..12ebbbe3ff 100644
--- a/packages/frontend/src/pages/drive.file.info.vue
+++ b/packages/frontend/src/pages/drive.file.info.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
+
+
+ {{ i18n.ts.save }}
+ {{ i18n.ts.show }}
+ {{ i18n.ts.delete }}
+
+
+
+
@@ -459,3 +465,10 @@ definePageMetadata(() => ({
title: flash.value ? `${i18n.ts._play.edit}: ${flash.value.title}` : i18n.ts._play.new,
}));
+
diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue
index 3b4deaf537..cf10bee0f5 100644
--- a/packages/frontend/src/pages/flash/flash.vue
+++ b/packages/frontend/src/pages/flash/flash.vue
@@ -80,7 +80,7 @@ import { defaultStore } from '@/store.js';
import { $i } from '@/account.js';
import { isSupportShare } from '@/scripts/navigator.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
-import { MenuItem } from '@/types/menu';
+import type { MenuItem } from '@/types/menu.js';
import { pleaseLogin } from '@/scripts/please-login.js';
const props = defineProps<{
@@ -104,18 +104,23 @@ function fetchFlash() {
function share(ev: MouseEvent) {
if (!flash.value) return;
- os.popupMenu([
- {
- text: i18n.ts.shareWithNote,
- icon: 'ti ti-pencil',
- action: shareWithNote,
- },
- ...(isSupportShare() ? [{
+ const menuItems: MenuItem[] = [];
+
+ menuItems.push({
+ text: i18n.ts.shareWithNote,
+ icon: 'ti ti-pencil',
+ action: shareWithNote,
+ });
+
+ if (isSupportShare()) {
+ menuItems.push({
text: i18n.ts.share,
icon: 'ti ti-share',
action: shareWithNavigator,
- }] : []),
- ], ev.currentTarget ?? ev.target);
+ });
+ }
+
+ os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
}
function copyLink() {
diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue
index dfee66d906..8c4dfc3b83 100644
--- a/packages/frontend/src/pages/gallery/post.vue
+++ b/packages/frontend/src/pages/gallery/post.vue
@@ -80,7 +80,7 @@ import { $i } from '@/account.js';
import { isSupportShare } from '@/scripts/navigator.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { useRouter } from '@/router/supplier.js';
-import { MenuItem } from '@/types/menu';
+import type { MenuItem } from '@/types/menu.js';
const router = useRouter();
@@ -171,35 +171,35 @@ function reportAbuse() {
function showMenu(ev: MouseEvent) {
if (!post.value) return;
- const menu: MenuItem[] = [
- ...($i && $i.id !== post.value.userId ? [
- {
- icon: 'ti ti-exclamation-circle',
- text: i18n.ts.reportAbuse,
- action: reportAbuse,
- },
- ...($i.isModerator || $i.isAdmin ? [
- {
- type: 'divider' as const,
- },
- {
- icon: 'ti ti-trash',
- text: i18n.ts.delete,
- danger: true,
- action: () => os.confirm({
- type: 'warning',
- text: i18n.ts.deleteConfirm,
- }).then(({ canceled }) => {
- if (canceled || !post.value) return;
+ const menuItems: MenuItem[] = [];
- os.apiWithDialog('gallery/posts/delete', { postId: post.value.id });
- }),
- },
- ] : []),
- ] : []),
- ];
+ if ($i && $i.id !== post.value.userId) {
+ menuItems.push({
+ icon: 'ti ti-exclamation-circle',
+ text: i18n.ts.reportAbuse,
+ action: reportAbuse,
+ });
- os.popupMenu(menu, ev.currentTarget ?? ev.target);
+ if ($i.isModerator || $i.isAdmin) {
+ menuItems.push({
+ type: 'divider',
+ }, {
+ icon: 'ti ti-trash',
+ text: i18n.ts.delete,
+ danger: true,
+ action: () => os.confirm({
+ type: 'warning',
+ text: i18n.ts.deleteConfirm,
+ }).then(({ canceled }) => {
+ if (canceled || !post.value) return;
+
+ os.apiWithDialog('gallery/posts/delete', { postId: post.value.id });
+ }),
+ });
+ }
+ }
+
+ os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
}
watch(() => props.postId, fetchPost, { immediate: true });
diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue
index a2ceb222fe..5f195693cc 100644
--- a/packages/frontend/src/pages/my-lists/list.vue
+++ b/packages/frontend/src/pages/my-lists/list.vue
@@ -134,12 +134,14 @@ async function removeUser(item, ev) {
async function showMembershipMenu(item, ev) {
const withRepliesRef = ref(item.withReplies);
+
os.popupMenu([{
type: 'switch',
text: i18n.ts.showRepliesToOthersInTimeline,
icon: 'ti ti-messages',
ref: withRepliesRef,
}], ev.currentTarget ?? ev.target);
+
watch(withRepliesRef, withReplies => {
misskeyApi('users/lists/update-membership', {
listId: list.value!.id,
diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue
index 381b80cd29..7926dab88b 100644
--- a/packages/frontend/src/pages/page.vue
+++ b/packages/frontend/src/pages/page.vue
@@ -121,7 +121,7 @@ import { instance } from '@/instance.js';
import { getStaticImageUrl } from '@/scripts/media-proxy.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { useRouter } from '@/router/supplier.js';
-import { MenuItem } from '@/types/menu';
+import type { MenuItem } from '@/types/menu.js';
const router = useRouter();
@@ -165,18 +165,23 @@ function fetchPage() {
function share(ev: MouseEvent) {
if (!page.value) return;
- os.popupMenu([
- {
- text: i18n.ts.shareWithNote,
- icon: 'ti ti-pencil',
- action: shareWithNote,
- },
- ...(isSupportShare() ? [{
+ const menuItems: MenuItem[] = [];
+
+ menuItems.push({
+ text: i18n.ts.shareWithNote,
+ icon: 'ti ti-pencil',
+ action: shareWithNote,
+ });
+
+ if (isSupportShare()) {
+ menuItems.push({
text: i18n.ts.share,
icon: 'ti ti-share',
action: shareWithNavigator,
- }] : []),
- ], ev.currentTarget ?? ev.target);
+ });
+ }
+
+ os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
}
function copyLink() {
@@ -256,51 +261,59 @@ function reportAbuse() {
function showMenu(ev: MouseEvent) {
if (!page.value) return;
- const menu: MenuItem[] = [
- ...($i && $i.id === page.value.userId ? [
- {
- icon: 'ti ti-code',
- text: i18n.ts._pages.viewSource,
- action: () => router.push(`/@${props.username}/pages/${props.pageName}/view-source`),
- },
- ...($i.pinnedPageId === page.value.id ? [{
+ const menuItems: MenuItem[] = [];
+
+ if ($i && $i.id === page.value.userId) {
+ menuItems.push({
+ icon: 'ti ti-pencil',
+ text: i18n.ts.editThisPage,
+ action: () => router.push(`/pages/edit/${page.value.id}`),
+ });
+
+ if ($i.pinnedPageId === page.value.id) {
+ menuItems.push({
icon: 'ti ti-pinned-off',
text: i18n.ts.unpin,
action: () => pin(false),
- }] : [{
+ });
+ } else {
+ menuItems.push({
icon: 'ti ti-pin',
text: i18n.ts.pin,
action: () => pin(true),
- }]),
- ] : []),
- ...($i && $i.id !== page.value.userId ? [
- {
- icon: 'ti ti-exclamation-circle',
- text: i18n.ts.reportAbuse,
- action: reportAbuse,
- },
- ...($i.isModerator || $i.isAdmin ? [
- {
- type: 'divider' as const,
- },
- {
- icon: 'ti ti-trash',
- text: i18n.ts.delete,
- danger: true,
- action: () => os.confirm({
- type: 'warning',
- text: i18n.ts.deleteConfirm,
- }).then(({ canceled }) => {
- if (canceled || !page.value) return;
+ });
+ }
+ } else if ($i && $i.id !== page.value.userId) {
+ menuItems.push({
+ icon: 'ti ti-code',
+ text: i18n.ts._pages.viewSource,
+ action: () => router.push(`/@${props.username}/pages/${props.pageName}/view-source`),
+ }, {
+ icon: 'ti ti-exclamation-circle',
+ text: i18n.ts.reportAbuse,
+ action: reportAbuse,
+ });
- os.apiWithDialog('pages/delete', { pageId: page.value.id });
- }),
- },
- ] : []),
- ] : []),
- ];
+ if ($i.isModerator || $i.isAdmin) {
+ menuItems.push({
+ type: 'divider',
+ }, {
+ icon: 'ti ti-trash',
+ text: i18n.ts.delete,
+ danger: true,
+ action: () => os.confirm({
+ type: 'warning',
+ text: i18n.ts.deleteConfirm,
+ }).then(({ canceled }) => {
+ if (canceled || !page.value) return;
- os.popupMenu(menu, ev.currentTarget ?? ev.target);
+ os.apiWithDialog('pages/delete', { pageId: page.value.id });
+ }),
+ });
+ }
+ }
+
+ os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
}
watch(() => path.value, fetchPage, { immediate: true });
diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue
index 31c0003130..08bb3cb76c 100644
--- a/packages/frontend/src/pages/reversi/game.setting.vue
+++ b/packages/frontend/src/pages/reversi/game.setting.vue
@@ -121,7 +121,7 @@ import MkRadios from '@/components/MkRadios.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import MkFolder from '@/components/MkFolder.vue';
import * as os from '@/os.js';
-import { MenuItem } from '@/types/menu.js';
+import type { MenuItem } from '@/types/menu.js';
import { useRouter } from '@/router/supplier.js';
const $i = signinRequired();
diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue
index 9aaa8ff9c6..897ff6acdf 100644
--- a/packages/frontend/src/pages/scratchpad.vue
+++ b/packages/frontend/src/pages/scratchpad.vue
@@ -30,6 +30,24 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -43,6 +61,7 @@ import { onDeactivated, onUnmounted, Ref, ref, watch, computed } from 'vue';
import { Interpreter, Parser, utils } from '@syuilo/aiscript';
import MkContainer from '@/components/MkContainer.vue';
import MkButton from '@/components/MkButton.vue';
+import MkTextarea from '@/components/MkTextarea.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue';
import { aiScriptReadline, createAiScriptEnv } from '@/scripts/aiscript/api.js';
import * as os from '@/os.js';
@@ -61,6 +80,7 @@ const logs = ref