From 745f4d24394ee1f96a91563d1280a3c5344a9ccf Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sun, 25 Oct 2020 01:23:23 +0900
Subject: [PATCH] regedit

---
 locales/ja-JP.yml                     |  4 ++
 src/client/components/ui/textarea.vue | 13 ++++-
 src/client/pages/settings/other.vue   | 17 +++---
 src/client/pages/settings/regedit.vue | 77 +++++++++++++++++++++++++++
 src/client/store.ts                   | 18 +++++++
 5 files changed, 121 insertions(+), 8 deletions(-)
 create mode 100644 src/client/pages/settings/regedit.vue

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index bccb82e51b..f4c22d1fff 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -593,6 +593,10 @@ fillAbuseReportDescription: "通報理由の詳細を記入してください。
 abuseReported: "内容が送信されました。ご報告ありがとうございました。"
 send: "送信"
 abuseMarkAsResolved: "対応済みにする"
+openInNewTab: "新しいタブで開く"
+openInSideView: "サイドビューで開く"
+defaultNavigationBehaviour: "デフォルトのナビゲーション"
+editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
 
 _serverDisconnectedBehavior:
   reload: "自動でリロード"
diff --git a/src/client/components/ui/textarea.vue b/src/client/components/ui/textarea.vue
index 6820be8a7c..7d3250cc45 100644
--- a/src/client/components/ui/textarea.vue
+++ b/src/client/components/ui/textarea.vue
@@ -2,12 +2,13 @@
 <div class="adhpbeos" :class="{ focused, filled, tall, pre }">
 	<div class="input">
 		<span class="label" ref="label"><slot></slot></span>
-		<textarea ref="input"
+		<textarea ref="input" :class="{ code }"
 			:value="value"
 			:required="required"
 			:readonly="readonly"
 			:pattern="pattern"
 			:autocomplete="autocomplete"
+			:spellcheck="!code"
 			@input="onInput"
 			@focus="focused = true"
 			@blur="focused = false"
@@ -20,7 +21,6 @@
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import * as os from '@/os';
 
 export default defineComponent({
 	props: {
@@ -43,6 +43,10 @@ export default defineComponent({
 			type: String,
 			required: false
 		},
+		code: {
+			type: Boolean,
+			required: false
+		},
 		tall: {
 			type: Boolean,
 			required: false,
@@ -159,6 +163,11 @@ export default defineComponent({
 			outline: none;
 			box-shadow: none;
 			color: var(--fg);
+
+			&.code {
+				tab-size: 2;
+				font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
+			}
 		}
 	}
 
diff --git a/src/client/pages/settings/other.vue b/src/client/pages/settings/other.vue
index ebc5644162..38c2e8adb6 100644
--- a/src/client/pages/settings/other.vue
+++ b/src/client/pages/settings/other.vue
@@ -1,12 +1,17 @@
 <template>
-<div class="_section">
-	<div class="_card">
-		<div class="_content">
-			<MkSwitch v-model:value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
-				{{ $t('showFeaturedNotesInTimeline') }}
-			</MkSwitch>
+<div>
+	<div class="_section">
+		<div class="_card">
+			<div class="_content">
+				<MkSwitch v-model:value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
+					{{ $t('showFeaturedNotesInTimeline') }}
+				</MkSwitch>
+			</div>
 		</div>
 	</div>
+	<div class="_section">
+		<MkA to="/settings/regedit">RegEdit</MkA>
+	</div>
 </div>
 </template>
 
diff --git a/src/client/pages/settings/regedit.vue b/src/client/pages/settings/regedit.vue
new file mode 100644
index 0000000000..fcc249bef3
--- /dev/null
+++ b/src/client/pages/settings/regedit.vue
@@ -0,0 +1,77 @@
+<template>
+<div>
+	<div class="_section">
+		<MkInfo warn>{{ $t('editTheseSettingsMayBreakAccount') }}</MkInfo>
+	</div>
+	<div class="_section">
+		<div class="_title">Account</div>
+		<div class="_content">
+			<MkTextarea v-model:value="settings" code tall></MkTextarea>
+			<!--<MkButton @click="saveSettings">Save</MkButton>-->
+		</div>
+	</div>
+	<div class="_section">
+		<div class="_title">Device</div>
+		<div class="_content">
+			<MkTextarea v-model:value="deviceSettings" code tall></MkTextarea>
+			<MkButton @click="saveDeviceSettings">Save</MkButton>
+		</div>
+	</div>
+	<div class="_section">
+		<div class="_title">Device (per account)</div>
+		<div class="_content">
+			<MkTextarea v-model:value="deviceUserSettings" code tall></MkTextarea>
+			<MkButton @click="saveDeviceUserSettings">Save</MkButton>
+		</div>
+	</div>
+</div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import { faCode } from '@fortawesome/free-solid-svg-icons';
+import * as JSON5 from 'json5';
+import MkInfo from '@/components/ui/info.vue';
+import MkButton from '@/components/ui/button.vue';
+import MkTextarea from '@/components/ui/textarea.vue';
+import * as os from '@/os';
+
+export default defineComponent({
+	components: {
+		MkInfo, MkButton, MkTextarea
+	},
+
+	emits: ['info'],
+
+	data() {
+		return {
+			INFO: {
+				header: [{
+					title: 'RegEdit',
+					icon: faCode
+				}]
+			},
+
+			settings: JSON5.stringify(this.$store.state.settings, null, '\t'),
+			deviceSettings: JSON5.stringify(this.$store.state.device, null, '\t'),
+			deviceUserSettings: JSON5.stringify(this.$store.state.deviceUser, null, '\t'),
+		};
+	},
+
+	mounted() {
+		this.$emit('info', this.INFO);
+	},
+
+	methods: {
+		saveDeviceSettings() {
+			const obj = JSON5.parse(this.deviceSettings);
+			this.$store.commit('device/overwrite', obj);
+		},
+
+		saveDeviceUserSettings() {
+			const obj = JSON5.parse(this.deviceUserSettings);
+			this.$store.commit('deviceUser/overwrite', obj);
+		},
+	}
+});
+</script>
diff --git a/src/client/store.ts b/src/client/store.ts
index f1ad23e1f5..e95191809f 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -202,6 +202,15 @@ export const store = createStore({
 			state: defaultDeviceSettings,
 
 			mutations: {
+				overwrite(state, x) {
+					for (const k of Object.keys(state)) {
+						if (x[k] === undefined) delete state[k];
+					}
+					for (const k of Object.keys(x)) {
+						state[k] = x[k];
+					}
+				},
+
 				set(state, x: { key: string; value: any }) {
 					state[x.key] = x.value;
 				},
@@ -218,6 +227,15 @@ export const store = createStore({
 			state: defaultDeviceUserSettings,
 
 			mutations: {
+				overwrite(state, x) {
+					for (const k of Object.keys(state)) {
+						if (x[k] === undefined) delete state[k];
+					}
+					for (const k of Object.keys(x)) {
+						state[k] = x[k];
+					}
+				},
+
 				init(state, x) {
 					for (const [key, value] of Object.entries(defaultDeviceUserSettings)) {
 						if (x[key]) {