summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locales/index.d.ts4
-rw-r--r--locales/ja-JP.yml1
-rw-r--r--packages/frontend/src/pages/settings/theme.vue35
3 files changed, 33 insertions, 7 deletions
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 16003570a2..492688773f 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -8367,6 +8367,10 @@ export interface Locale extends ILocale {
*/
"code": string;
/**
+ * テーマコードをコピー
+ */
+ "copyThemeCode": string;
+ /**
* 説明
*/
"description": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 6ef92e0f2e..3aa8e44ce7 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -2193,6 +2193,7 @@ _theme:
install: "テーマのインストール"
manage: "テーマの管理"
code: "テーマコード"
+ copyThemeCode: "テーマコードをコピー"
description: "説明"
installed: "{name}をインストールしました"
installedThemes: "インストールされたテーマ"
diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue
index f3a6458109..accb1ccc55 100644
--- a/packages/frontend/src/pages/settings/theme.vue
+++ b/packages/frontend/src/pages/settings/theme.vue
@@ -56,7 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="instanceLightTheme.id"
/>
- <label :for="`themeRadio_${instanceLightTheme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${instanceLightTheme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(instanceLightTheme, $event)">
<MkThemePreview :theme="instanceLightTheme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ instanceLightTheme.name }}</div>
</label>
@@ -76,7 +76,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="theme.id"
/>
- <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(theme, $event)">
<MkThemePreview :theme="theme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ theme.name }}</div>
</label>
@@ -96,7 +96,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="theme.id"
/>
- <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(theme, $event)">
<MkThemePreview :theme="theme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ theme.name }}</div>
</label>
@@ -127,7 +127,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="instanceDarkTheme.id"
/>
- <label :for="`themeRadio_${instanceDarkTheme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${instanceDarkTheme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(instanceDarkTheme, $event)">
<MkThemePreview :theme="instanceDarkTheme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ instanceDarkTheme.name }}</div>
</label>
@@ -147,7 +147,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="theme.id"
/>
- <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(theme, $event)">
<MkThemePreview :theme="theme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ theme.name }}</div>
</label>
@@ -167,7 +167,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.themeRadio"
:value="theme.id"
/>
- <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button">
+ <label :for="`themeRadio_${theme.id}`" :class="$style.themeItemRoot" class="_button" @contextmenu.prevent.stop="onThemeContextmenu(theme, $event)">
<MkThemePreview :theme="theme" :class="$style.themeItemPreview"/>
<div :class="$style.themeItemCaption">{{ theme.name }}</div>
</label>
@@ -210,7 +210,7 @@ import FormSection from '@/components/form/section.vue';
import FormLink from '@/components/form/link.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkThemePreview from '@/components/MkThemePreview.vue';
-import { getBuiltinThemesRef, getThemesRef } from '@/theme.js';
+import { getBuiltinThemesRef, getThemesRef, removeTheme } from '@/theme.js';
import { isDeviceDarkmode } from '@/utility/is-device-darkmode.js';
import { store } from '@/store.js';
import { i18n } from '@/i18n.js';
@@ -218,6 +218,7 @@ import { instance } from '@/instance.js';
import { uniqueBy } from '@/utility/array.js';
import { definePage } from '@/page.js';
import { prefer } from '@/preferences.js';
+import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
const installedThemes = getThemesRef();
const builtinThemes = getBuiltinThemesRef();
@@ -295,6 +296,26 @@ function changeThemesSyncEnabled(value: boolean) {
}
}
+function onThemeContextmenu(theme: Theme, ev: MouseEvent) {
+ os.contextMenu([{
+ type: 'label',
+ text: theme.name,
+ }, {
+ icon: 'ti ti-clipboard',
+ text: i18n.ts._theme.copyThemeCode,
+ action: () => {
+ copyToClipboard(JSON5.stringify(theme, null, '\t'));
+ },
+ }, {
+ icon: 'ti ti-trash',
+ text: i18n.ts.delete,
+ danger: true,
+ action: () => {
+ removeTheme(theme);
+ },
+ }], ev);
+}
+
const headerActions = computed(() => []);
const headerTabs = computed(() => []);