From 6fea2f52f10f4cb9f6cfb9210917c615a9423307 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 5 Sep 2018 13:47:26 +0900
Subject: [PATCH] nanka iroiro

---
 locales/ja-JP.yml                             |   3 +
 .../app/common/views/components/ui/card.vue   |  27 +++-
 .../app/common/views/components/ui/radio.vue  |   2 +-
 .../app/common/views/components/ui/switch.vue |   7 ++
 .../app/mobile/views/components/notify.vue    |  18 ++-
 .../app/mobile/views/pages/settings.vue       | 118 +++++++++++-------
 .../views/pages/settings/settings.profile.vue |  68 +++++-----
 src/client/app/store.ts                       |   3 +-
 8 files changed, 155 insertions(+), 91 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index a57f724a3..1b73c825b 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1355,6 +1355,9 @@ mobile/views/pages/settings.vue:
   post-style: "投稿の表示スタイル"
   post-style-standard: "標準"
   post-style-smart: "スマート"
+  notification-position: "通知の表示"
+  notification-position-bottom: "下"
+  notification-position-top: "上"
   behavior: "動作"
   fetch-on-scroll: "スクロールで自動読み込み"
   disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
diff --git a/src/client/app/common/views/components/ui/card.vue b/src/client/app/common/views/components/ui/card.vue
index 05c51bca6..aa16b557e 100644
--- a/src/client/app/common/views/components/ui/card.vue
+++ b/src/client/app/common/views/components/ui/card.vue
@@ -24,19 +24,34 @@ export default Vue.extend({
 
 root(isDark)
 	margin 16px
-	padding 16px
 	color isDark ? #fff : #000
 	background isDark ? #282C37 : #fff
 	box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
 
-	@media (min-width 500px)
-		padding 32px
-
 	> header
-		font-weight normal
-		font-size 24px
+		padding 16px
+		font-weight bold
+		font-size 20px
 		color isDark ? #fff : #444
 
+		@media (min-width 500px)
+			padding 24px 32px
+
+	> section
+		padding 20px 16px
+		border-top solid 1px isDark ? rgba(#000, 0.3) : rgba(#000, 0.1)
+
+		@media (min-width 500px)
+			padding 32px
+
+		&.fit-top
+			padding-top 0
+
+		> header
+			margin-bottom 16px
+			font-weight bold
+			color isDark ? #fff : #444
+
 .ui-card[data-darkmode]
 	root(true)
 
diff --git a/src/client/app/common/views/components/ui/radio.vue b/src/client/app/common/views/components/ui/radio.vue
index 04a46c5a9..dcdda1cf0 100644
--- a/src/client/app/common/views/components/ui/radio.vue
+++ b/src/client/app/common/views/components/ui/radio.vue
@@ -55,7 +55,7 @@ export default Vue.extend({
 
 root(isDark)
 	display inline-block
-	margin 32px 32px 32px 0
+	margin 0 32px 0 0
 	cursor pointer
 	transition all 0.3s
 
diff --git a/src/client/app/common/views/components/ui/switch.vue b/src/client/app/common/views/components/ui/switch.vue
index a9e00d73d..e88b86780 100644
--- a/src/client/app/common/views/components/ui/switch.vue
+++ b/src/client/app/common/views/components/ui/switch.vue
@@ -64,6 +64,12 @@ root(isDark)
 	cursor pointer
 	transition all 0.3s
 
+	&:first-child
+		margin-top 0
+
+	&:last-child
+		margin-bottom 0
+
 	> *
 		user-select none
 
@@ -89,6 +95,7 @@ root(isDark)
 
 	> .button
 		display inline-block
+		flex-shrink 0
 		margin 3px 0 0 0
 		width 34px
 		height 14px
diff --git a/src/client/app/mobile/views/components/notify.vue b/src/client/app/mobile/views/components/notify.vue
index 4d9b7c0f6..7a2f7bfed 100644
--- a/src/client/app/mobile/views/components/notify.vue
+++ b/src/client/app/mobile/views/components/notify.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="mk-notify">
+<div class="mk-notify" :class="pos">
 	<div>
 		<mk-notification-preview :notification="notification"/>
 	</div>
@@ -12,11 +12,16 @@ import * as anime from 'animejs';
 
 export default Vue.extend({
 	props: ['notification'],
+	computed: {
+		pos() {
+			return this.$store.state.device.mobileNotificationPosition;
+		}
+	},
 	mounted() {
 		this.$nextTick(() => {
 			anime({
 				targets: this.$el,
-				bottom: '0px',
+				[this.pos]: '0px',
 				duration: 500,
 				easing: 'easeOutQuad'
 			});
@@ -24,7 +29,7 @@ export default Vue.extend({
 			setTimeout(() => {
 				anime({
 					targets: this.$el,
-					bottom: `-${this.$el.offsetHeight}px`,
+					[this.pos]: `-${this.$el.offsetHeight}px`,
 					duration: 500,
 					easing: 'easeOutQuad',
 					complete: () => this.$destroy()
@@ -41,7 +46,6 @@ export default Vue.extend({
 
 	position fixed
 	z-index 1024
-	bottom -($height)
 	left 0
 	right 0
 	width 100%
@@ -52,6 +56,12 @@ export default Vue.extend({
 	pointer-events none
 	font-size 80%
 
+	&.bottom
+		bottom -($height)
+
+	&.top
+		top -($height)
+
 	> div
 		height 100%
 		-webkit-backdrop-filter blur(2px)
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index 838ffd2a6..4a148dc9d 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -10,80 +10,101 @@
 			<ui-card>
 				<div slot="title">%fa:palette% %i18n:@design%</div>
 
-				<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
-				<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
-				<ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch>
-				<ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
-				<ui-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
-				<ui-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
+				<section>
+					<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
+					<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
+					<ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch>
+					<ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
+					<ui-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
+					<ui-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
+				</section>
 
-				<div>
-					<div>%i18n:@timeline%</div>
-					<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
-					<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
-					<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
-					<ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
-				</div>
+				<section>
+					<header>%i18n:@timeline%</header>
+					<div>
+						<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
+						<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
+						<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
+						<ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
+					</div>
+				</section>
 
-				<div>
-					<div>%i18n:@post-style%</div>
+				<section>
+					<header>%i18n:@post-style%</header>
 					<ui-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</ui-radio>
 					<ui-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</ui-radio>
-				</div>
+				</section>
+
+				<section>
+					<header>%i18n:@notification-position%</header>
+					<ui-radio v-model="mobileNotificationPosition" value="bottom">%i18n:@notification-position-bottom%</ui-radio>
+					<ui-radio v-model="mobileNotificationPosition" value="top">%i18n:@notification-position-top%</ui-radio>
+				</section>
 			</ui-card>
 
 			<ui-card>
 				<div slot="title">%fa:cog% %i18n:@behavior%</div>
-				<ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
-				<ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
-				<ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch>
-				<ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch>
-				<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch>
+
+				<section>
+					<ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
+					<ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
+					<ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch>
+					<ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch>
+					<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch>
+				</section>
 			</ui-card>
 
 			<ui-card>
 				<div slot="title">%fa:volume-up% %i18n:@sound%</div>
 
-				<ui-switch v-model="enableSounds">%i18n:@enable-sounds%</ui-switch>
+				<section>
+					<ui-switch v-model="enableSounds">%i18n:@enable-sounds%</ui-switch>
+				</section>
 			</ui-card>
 
 			<ui-card>
 				<div slot="title">%fa:language% %i18n:@lang%</div>
 
-				<ui-select v-model="lang" placeholder="%i18n:@auto%">
-					<optgroup label="%i18n:@recommended%">
-						<option value="">%i18n:@auto%</option>
-					</optgroup>
+				<section class="fit-top">
+					<ui-select v-model="lang" placeholder="%i18n:@auto%">
+						<optgroup label="%i18n:@recommended%">
+							<option value="">%i18n:@auto%</option>
+						</optgroup>
 
-					<optgroup label="%i18n:@specify-language%">
-						<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
-					</optgroup>
-				</ui-select>
-				<span>%fa:info-circle% %i18n:@lang-tip%</span>
+						<optgroup label="%i18n:@specify-language%">
+							<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
+						</optgroup>
+					</ui-select>
+					<span>%fa:info-circle% %i18n:@lang-tip%</span>
+				</section>
 			</ui-card>
 
 			<ui-card>
 				<div slot="title">%fa:B twitter% %i18n:@twitter%</div>
 
-				<p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
-				<p>
-					<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
-					<span v-if="$store.state.i.twitter"> or </span>
-					<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
-				</p>
+				<section>
+					<p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
+					<p>
+						<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
+						<span v-if="$store.state.i.twitter"> or </span>
+						<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
+					</p>
+				</section>
 			</ui-card>
 
 			<ui-card>
 				<div slot="title">%fa:sync-alt% %i18n:@update%</div>
 
-				<div>%i18n:@version% <i>{{ version }}</i></div>
-				<template v-if="latestVersion !== undefined">
-					<div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
-				</template>
-				<ui-button @click="checkForUpdate" :disabled="checkingForUpdate">
-					<template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
-					<template v-else>%i18n:@check-for-updates%</template>
-				</ui-button>
+				<section>
+					<div>%i18n:@version% <i>{{ version }}</i></div>
+					<template v-if="latestVersion !== undefined">
+						<div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
+					</template>
+					<ui-button @click="checkForUpdate" :disabled="checkingForUpdate">
+						<template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
+						<template v-else>%i18n:@check-for-updates%</template>
+					</ui-button>
+				</section>
 			</ui-card>
 		</div>
 
@@ -134,6 +155,11 @@ export default Vue.extend({
 			set(value) { this.$store.commit('device/set', { key: 'postStyle', value }); }
 		},
 
+		mobileNotificationPosition: {
+			get() { return this.$store.state.device.mobileNotificationPosition; },
+			set(value) { this.$store.commit('device/set', { key: 'mobileNotificationPosition', value }); }
+		},
+
 		lightmode: {
 			get() { return this.$store.state.device.lightmode; },
 			set(value) { this.$store.commit('device/set', { key: 'lightmode', value }); }
@@ -273,7 +299,7 @@ export default Vue.extend({
 <style lang="stylus" scoped>
 root(isDark)
 	margin 0 auto
-	max-width 500px
+	max-width 600px
 	width 100%
 
 	> .signin-as
diff --git a/src/client/app/mobile/views/pages/settings/settings.profile.vue b/src/client/app/mobile/views/pages/settings/settings.profile.vue
index 3b797cdde..3efeac3da 100644
--- a/src/client/app/mobile/views/pages/settings/settings.profile.vue
+++ b/src/client/app/mobile/views/pages/settings/settings.profile.vue
@@ -2,47 +2,49 @@
 <ui-card>
 	<div slot="title">%fa:user% %i18n:@title%</div>
 
-	<ui-form :disabled="saving">
-		<ui-input v-model="name" :max="30">
-			<span>%i18n:@name%</span>
-		</ui-input>
+	<section class="fit-top">
+		<ui-form :disabled="saving">
+			<ui-input v-model="name" :max="30">
+				<span>%i18n:@name%</span>
+			</ui-input>
 
-		<ui-input v-model="username" readonly>
-			<span>%i18n:@account%</span>
-			<span slot="prefix">@</span>
-			<span slot="suffix">@{{ host }}</span>
-		</ui-input>
+			<ui-input v-model="username" readonly>
+				<span>%i18n:@account%</span>
+				<span slot="prefix">@</span>
+				<span slot="suffix">@{{ host }}</span>
+			</ui-input>
 
-		<ui-input v-model="location">
-			<span>%i18n:@location%</span>
-			<span slot="prefix">%fa:map-marker-alt%</span>
-		</ui-input>
+			<ui-input v-model="location">
+				<span>%i18n:@location%</span>
+				<span slot="prefix">%fa:map-marker-alt%</span>
+			</ui-input>
 
-		<ui-input v-model="birthday" type="date">
-			<span>%i18n:@birthday%</span>
-			<span slot="prefix">%fa:birthday-cake%</span>
-		</ui-input>
+			<ui-input v-model="birthday" type="date">
+				<span>%i18n:@birthday%</span>
+				<span slot="prefix">%fa:birthday-cake%</span>
+			</ui-input>
 
-		<ui-textarea v-model="description" :max="500">
-			<span>%i18n:@description%</span>
-		</ui-textarea>
+			<ui-textarea v-model="description" :max="500">
+				<span>%i18n:@description%</span>
+			</ui-textarea>
 
-		<ui-input type="file" @change="onAvatarChange">
-			<span>%i18n:@avatar%</span>
-			<span slot="icon">%fa:image%</span>
-			<span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
-		</ui-input>
+			<ui-input type="file" @change="onAvatarChange">
+				<span>%i18n:@avatar%</span>
+				<span slot="icon">%fa:image%</span>
+				<span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
+			</ui-input>
 
-		<ui-input type="file" @change="onBannerChange">
-			<span>%i18n:@banner%</span>
-			<span slot="icon">%fa:image%</span>
-			<span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
-		</ui-input>
+			<ui-input type="file" @change="onBannerChange">
+				<span>%i18n:@banner%</span>
+				<span slot="icon">%fa:image%</span>
+				<span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
+			</ui-input>
 
-		<ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch>
+			<ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch>
 
-		<ui-button @click="save">%i18n:@save%</ui-button>
-	</ui-form>
+			<ui-button @click="save">%i18n:@save%</ui-button>
+		</ui-form>
+	</section>
 </ui-card>
 </template>
 
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 469563495..53f3eefc0 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -43,7 +43,8 @@ const defaultDeviceSettings = {
 	debug: false,
 	lightmode: false,
 	loadRawImages: false,
-	postStyle: 'standard'
+	postStyle: 'standard',
+	mobileNotificationPosition: 'bottom'
 };
 
 export default (os: MiOS) => new Vuex.Store({