From 08c176e549e6ba2fc1a4cbbf4b09c7d0226c7f13 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Mon, 18 Mar 2019 01:03:35 +0900
Subject: [PATCH] =?UTF-8?q?=E4=B8=8D=E6=98=8E=E3=81=AA=E3=83=AA=E3=82=A2?=
 =?UTF-8?q?=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AE=E3=83=95=E3=82=A9?=
 =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=83=90=E3=83=83=E3=82=AF=E3=81=AB=20star?=
 =?UTF-8?q?=20=E3=82=92=E4=BD=BF=E3=81=86=E3=82=88=E3=81=86=E3=81=AB?=
 =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 locales/ja-JP.yml                                   |  1 +
 src/client/app/admin/views/instance.vue             |  4 ++++
 .../app/common/views/components/reaction-icon.vue   |  1 +
 src/misc/get-reaction-emoji.ts                      |  3 ++-
 src/misc/reaction-lib.ts                            |  4 +++-
 src/models/meta.ts                                  |  1 +
 src/models/note-reaction.ts                         | 13 -------------
 src/server/api/endpoints/admin/update-meta.ts       | 11 +++++++++++
 src/server/api/endpoints/meta.ts                    |  1 +
 src/server/api/openapi/schemas.ts                   |  3 ++-
 10 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index cec462955f..0316927952 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1239,6 +1239,7 @@ admin/views/instance.vue:
   disable-global-timeline: "グローバルタイムラインを無効にする"
   disabling-timelines-info: "これらのタイムラインを無効にしても、管理者およびモデレーターは引き続き利用できます。"
   enable-emoji-reaction: "リアクションに絵文字を使えるようにする"
+  use-star-for-reaction-fallback: "不明なリアクションのフォールバックに star を使う"
   invite: "招待"
   save: "保存"
   saved: "保存しました"
diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue
index ab337f1871..2d2a07784b 100644
--- a/src/client/app/admin/views/instance.vue
+++ b/src/client/app/admin/views/instance.vue
@@ -26,6 +26,7 @@
 			<ui-switch v-model="disableGlobalTimeline">{{ $t('disable-global-timeline') }}</ui-switch>
 			<ui-info>{{ $t('disabling-timelines-info') }}</ui-info>
 			<ui-switch v-model="enableEmojiReaction">{{ $t('enable-emoji-reaction') }}</ui-switch>
+			<ui-switch v-model="useStarForReactionFallback">{{ $t('use-star-for-reaction-fallback') }}</ui-switch>
 		</section>
 		<section class="fit-bottom">
 			<header><fa icon="cloud"/> {{ $t('drive-config') }}</header>
@@ -157,6 +158,7 @@ export default Vue.extend({
 			disableLocalTimeline: false,
 			disableGlobalTimeline: false,
 			enableEmojiReaction: true,
+			useStarForReactionFallback: false,
 			mascotImageUrl: null,
 			bannerUrl: null,
 			errorImageUrl: null,
@@ -209,6 +211,7 @@ export default Vue.extend({
 			this.disableLocalTimeline = meta.disableLocalTimeline;
 			this.disableGlobalTimeline = meta.disableGlobalTimeline;
 			this.enableEmojiReaction = meta.enableEmojiReaction;
+			this.useStarForReactionFallback = meta.useStarForReactionFallback;
 			this.mascotImageUrl = meta.mascotImageUrl;
 			this.bannerUrl = meta.bannerUrl;
 			this.errorImageUrl = meta.errorImageUrl;
@@ -271,6 +274,7 @@ export default Vue.extend({
 				disableLocalTimeline: this.disableLocalTimeline,
 				disableGlobalTimeline: this.disableGlobalTimeline,
 				enableEmojiReaction: this.enableEmojiReaction,
+				useStarForReactionFallback: this.useStarForReactionFallback,
 				mascotImageUrl: this.mascotImageUrl,
 				bannerUrl: this.bannerUrl,
 				errorImageUrl: this.errorImageUrl,
diff --git a/src/client/app/common/views/components/reaction-icon.vue b/src/client/app/common/views/components/reaction-icon.vue
index 1991669507..022d57dc44 100644
--- a/src/client/app/common/views/components/reaction-icon.vue
+++ b/src/client/app/common/views/components/reaction-icon.vue
@@ -31,6 +31,7 @@ export default Vue.extend({
 				case 'confused': return '😥';
 				case 'rip': return '😇';
 				case 'pudding': return (this.$store.getters.isSignedIn && this.$store.state.settings.iLikeSushi) ? '🍣' : '🍮';
+				case 'star': return '⭐';
 				default: return this.reaction;
 			}
 		},
diff --git a/src/misc/get-reaction-emoji.ts b/src/misc/get-reaction-emoji.ts
index 9d6956c4ac..c2e0b98582 100644
--- a/src/misc/get-reaction-emoji.ts
+++ b/src/misc/get-reaction-emoji.ts
@@ -10,6 +10,7 @@ export default function(reaction: string): string {
 		case 'confused': return '😥';
 		case 'rip': return '😇';
 		case 'pudding': return '🍮';
-		default: return '';
+		case 'star': return '⭐';
+		default: return reaction;
 	}
 }
diff --git a/src/misc/reaction-lib.ts b/src/misc/reaction-lib.ts
index c81e35b371..a27fb883b1 100644
--- a/src/misc/reaction-lib.ts
+++ b/src/misc/reaction-lib.ts
@@ -1,5 +1,6 @@
 import Emoji from '../models/emoji';
 import { emojiRegex } from './emoji-regex';
+import fetchMeta from './fetch-meta';
 
 const basic10: Record<string, string> = {
 	'👍': 'like',
@@ -15,7 +16,8 @@ const basic10: Record<string, string> = {
 };
 
 export async function getFallbackReaction(): Promise<string> {
-	return 'like';
+	const meta = await fetchMeta();
+	return  meta.useStarForReactionFallback ? 'star' : 'like';
 }
 
 export async function toDbReaction(reaction: string, enableEmoji = true): Promise<string> {
diff --git a/src/models/meta.ts b/src/models/meta.ts
index bea4714bf7..5ca0f01236 100644
--- a/src/models/meta.ts
+++ b/src/models/meta.ts
@@ -195,6 +195,7 @@ export type IMeta = {
 	disableLocalTimeline?: boolean;
 	disableGlobalTimeline?: boolean;
 	enableEmojiReaction?: boolean;
+	useStarForReactionFallback?: boolean;
 	hidedTags?: string[];
 	mascotImageUrl?: string;
 	bannerUrl?: string;
diff --git a/src/models/note-reaction.ts b/src/models/note-reaction.ts
index 1152161ea5..dc741614a7 100644
--- a/src/models/note-reaction.ts
+++ b/src/models/note-reaction.ts
@@ -20,19 +20,6 @@ export interface INoteReaction {
 	reaction: string;
 }
 
-export const validateReaction = $.str.or([
-	'like',
-	'love',
-	'laugh',
-	'hmm',
-	'surprise',
-	'congrats',
-	'angry',
-	'confused',
-	'rip',
-	'pudding'
-]);
-
 /**
  * Pack a reaction for API response
  */
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index 9afe90295e..f8f7cb5d9a 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -48,6 +48,13 @@ export const meta = {
 			}
 		},
 
+		useStarForReactionFallback: {
+			validator: $.optional.nullable.bool,
+			desc: {
+				'ja-JP': '不明なリアクションのフォールバックに star リアクションを使うか'
+			}
+		},
+
 		hidedTags: {
 			validator: $.optional.nullable.arr($.str),
 			desc: {
@@ -362,6 +369,10 @@ export default define(meta, async (ps) => {
 		set.enableEmojiReaction = ps.enableEmojiReaction;
 	}
 
+	if (typeof ps.useStarForReactionFallback === 'boolean') {
+		set.useStarForReactionFallback = ps.useStarForReactionFallback;
+	}
+
 	if (Array.isArray(ps.hidedTags)) {
 		set.hidedTags = ps.hidedTags;
 	}
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 1759a3c2f0..7b04f50894 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -152,6 +152,7 @@ export default define(meta, async (ps, me) => {
 	}
 
 	if (me && (me.isAdmin || me.isModerator)) {
+		response.useStarForReactionFallback = instance.useStarForReactionFallback;
 		response.hidedTags = instance.hidedTags;
 		response.recaptchaSecretKey = instance.recaptchaSecretKey;
 		response.proxyAccount = instance.proxyAccount;
diff --git a/src/server/api/openapi/schemas.ts b/src/server/api/openapi/schemas.ts
index 7b9dc35f27..70a0d6faf0 100644
--- a/src/server/api/openapi/schemas.ts
+++ b/src/server/api/openapi/schemas.ts
@@ -392,7 +392,8 @@ export const schemas = {
 					'angry',
 					'confused',
 					'rip',
-					'pudding'
+					'pudding',
+					'star'
 				],
 				description: 'The reaction type.'
 			},