From bc632cefe51d9d9cb50d787c8141365429e74396 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Thu, 22 Feb 2018 22:03:44 +0900
Subject: [PATCH] wip

---
 src/web/app/common/views/components/index.ts  |   2 +
 src/web/app/common/views/components/poll.vue  | 164 +++++++++---------
 src/web/app/desktop/views/components/home.vue |   4 +-
 .../views/components/notifications.vue        |   2 +-
 .../app/desktop/views/components/posts.vue    |   5 +-
 src/web/app/mobile/views/components/index.ts  |   2 +
 .../mobile/views/components/notification.vue  |   1 +
 .../mobile/views/components/notifications.vue |   3 +-
 src/web/app/mobile/views/components/posts.vue |   7 +-
 src/web/app/mobile/views/pages/post.vue       |   2 +-
 src/web/app/mobile/views/pages/user.vue       |   2 +-
 11 files changed, 104 insertions(+), 90 deletions(-)

diff --git a/src/web/app/common/views/components/index.ts b/src/web/app/common/views/components/index.ts
index d3f6a425f1..ab0f1767d4 100644
--- a/src/web/app/common/views/components/index.ts
+++ b/src/web/app/common/views/components/index.ts
@@ -5,6 +5,7 @@ import signup from './signup.vue';
 import forkit from './forkit.vue';
 import nav from './nav.vue';
 import postHtml from './post-html';
+import poll from './poll.vue';
 import pollEditor from './poll-editor.vue';
 import reactionIcon from './reaction-icon.vue';
 import reactionsViewer from './reactions-viewer.vue';
@@ -25,6 +26,7 @@ Vue.component('mk-signup', signup);
 Vue.component('mk-forkit', forkit);
 Vue.component('mk-nav', nav);
 Vue.component('mk-post-html', postHtml);
+Vue.component('mk-poll', poll);
 Vue.component('mk-poll-editor', pollEditor);
 Vue.component('mk-reaction-icon', reactionIcon);
 Vue.component('mk-reactions-viewer', reactionsViewer);
diff --git a/src/web/app/common/views/components/poll.vue b/src/web/app/common/views/components/poll.vue
index d06c019dba..7ed5bc6b1e 100644
--- a/src/web/app/common/views/components/poll.vue
+++ b/src/web/app/common/views/components/poll.vue
@@ -1,11 +1,11 @@
 <template>
-<div :data-is-voted="isVoted">
+<div class="mk-poll" :data-is-voted="isVoted">
 	<ul>
-		<li v-for="choice in poll.choices" :key="choice.id" @click="vote.bind(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:common.tags.mk-poll.vote-to%'.replace('{}', choice.text) : ''">
-			<div class="backdrop" :style="{ 'width:' + (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div>
+		<li v-for="choice in poll.choices" :key="choice.id" @click="vote(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:common.tags.mk-poll.vote-to%'.replace('{}', choice.text) : ''">
+			<div class="backdrop" :style="{ 'width': (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div>
 			<span>
 				<template v-if="choice.is_voted">%fa:check%</template>
-				{{ text }}
+				{{ choice.text }}
 				<span class="votes" v-if="showResult">({{ '%i18n:common.tags.mk-poll.vote-count%'.replace('{}', choice.votes) }})</span>
 			</span>
 		</li>
@@ -19,100 +19,100 @@
 </div>
 </template>
 
-<script lang="typescript">
-	export default {
-		props: ['post'],
-		data() {
-			return {
-				showResult: false
-			};
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+	props: ['post'],
+	data() {
+		return {
+			showResult: false
+		};
+	},
+	computed: {
+		poll(): any {
+			return this.post.poll;
 		},
-		computed: {
-			poll() {
-				return this.post.poll;
-			},
-			total() {
-				return this.poll.choices.reduce((a, b) => a + b.votes, 0);
-			},
-			isVoted() {
-				return this.poll.choices.some(c => c.is_voted);
-			}
+		total(): number {
+			return this.poll.choices.reduce((a, b) => a + b.votes, 0);
 		},
-		created() {
-			this.showResult = this.isVoted;
-		},
-		methods: {
-			toggleShowResult() {
-				this.showResult = !this.showResult;
-			},
-			vote(id) {
-				if (this.poll.choices.some(c => c.is_voted)) return;
-				(this as any).api('posts/polls/vote', {
-					post_id: this.post.id,
-					choice: id
-				}).then(() => {
-					this.poll.choices.forEach(c => {
-						if (c.id == id) {
-							c.votes++;
-							c.is_voted = true;
-						}
-					});
-					this.showResult = true;
-				});
-			}
+		isVoted(): boolean {
+			return this.poll.choices.some(c => c.is_voted);
 		}
-	};
+	},
+	created() {
+		this.showResult = this.isVoted;
+	},
+	methods: {
+		toggleShowResult() {
+			this.showResult = !this.showResult;
+		},
+		vote(id) {
+			if (this.poll.choices.some(c => c.is_voted)) return;
+			(this as any).api('posts/polls/vote', {
+				post_id: this.post.id,
+				choice: id
+			}).then(() => {
+				this.poll.choices.forEach(c => {
+					if (c.id == id) {
+						c.votes++;
+						Vue.set(c, 'is_voted', true);
+					}
+				});
+				this.showResult = true;
+			});
+		}
+	}
+});
 </script>
 
 <style lang="stylus" scoped>
-	:scope
+.mk-poll
+
+	> ul
 		display block
+		margin 0
+		padding 0
+		list-style none
 
-		> ul
+		> li
 			display block
-			margin 0
-			padding 0
-			list-style none
+			margin 4px 0
+			padding 4px 8px
+			width 100%
+			border solid 1px #eee
+			border-radius 4px
+			overflow hidden
+			cursor pointer
 
-			> li
-				display block
-				margin 4px 0
-				padding 4px 8px
-				width 100%
-				border solid 1px #eee
-				border-radius 4px
-				overflow hidden
-				cursor pointer
+			&:hover
+				background rgba(0, 0, 0, 0.05)
 
-				&:hover
-					background rgba(0, 0, 0, 0.05)
+			&:active
+				background rgba(0, 0, 0, 0.1)
 
-				&:active
-					background rgba(0, 0, 0, 0.1)
+			> .backdrop
+				position absolute
+				top 0
+				left 0
+				height 100%
+				background $theme-color
+				transition width 1s ease
 
-				> .backdrop
-					position absolute
-					top 0
-					left 0
-					height 100%
-					background $theme-color
-					transition width 1s ease
+			> .votes
+				margin-left 4px
 
-				> .votes
-					margin-left 4px
+	> p
+		a
+			color inherit
 
-		> p
-			a
-				color inherit
+	&[data-is-voted]
+		> ul > li
+			cursor default
 
-		&[data-is-voted]
-			> ul > li
-				cursor default
+			&:hover
+				background transparent
 
-				&:hover
-					background transparent
-
-				&:active
-					background transparent
+			&:active
+				background transparent
 
 </style>
diff --git a/src/web/app/desktop/views/components/home.vue b/src/web/app/desktop/views/components/home.vue
index 6b2d75d841..eabcc485dd 100644
--- a/src/web/app/desktop/views/components/home.vue
+++ b/src/web/app/desktop/views/components/home.vue
@@ -287,7 +287,7 @@ export default Vue.extend({
 			width calc(100% - 275px * 2)
 			order 2
 
-		> *:not(main)
+		> *:not(.main)
 			width 275px
 			padding 16px 0 16px 0
 
@@ -303,7 +303,7 @@ export default Vue.extend({
 			order 3
 
 		@media (max-width 1100px)
-			> *:not(main)
+			> *:not(.main)
 				display none
 
 			> .main
diff --git a/src/web/app/desktop/views/components/notifications.vue b/src/web/app/desktop/views/components/notifications.vue
index 443ebea2a2..e3a69d620d 100644
--- a/src/web/app/desktop/views/components/notifications.vue
+++ b/src/web/app/desktop/views/components/notifications.vue
@@ -10,7 +10,7 @@
 					</a>
 					<div class="text">
 						<p>
-							<mk-reaction-icon reaction={ notification.reaction }/>
+							<mk-reaction-icon :reaction="notification.reaction"/>
 							<a :href="`/${notification.user.username}`" v-user-preview="notification.user.id">{{ notification.user.name }}</a>
 						</p>
 						<a class="post-ref" :href="`/${notification.post.user.username}/${notification.post.id}`">
diff --git a/src/web/app/desktop/views/components/posts.vue b/src/web/app/desktop/views/components/posts.vue
index 7576fd31bd..ec36889ec8 100644
--- a/src/web/app/desktop/views/components/posts.vue
+++ b/src/web/app/desktop/views/components/posts.vue
@@ -1,7 +1,7 @@
 <template>
 <div class="mk-posts">
 	<template v-for="(post, i) in _posts">
-		<x-post :post.sync="post" :key="post.id"/>
+		<x-post :post="post" :key="post.id" @update:post="onPostUpdated(i, $event)"/>
 		<p class="date" v-if="i != posts.length - 1 && post._date != _posts[i + 1]._date">
 			<span>%fa:angle-up%{{ post._datetext }}</span>
 			<span>%fa:angle-down%{{ _posts[i + 1]._datetext }}</span>
@@ -41,6 +41,9 @@ export default Vue.extend({
 	methods: {
 		focus() {
 			(this.$el as any).children[0].focus();
+		},
+		onPostUpdated(i, post) {
+			Vue.set((this as any).posts, i, post);
 		}
 	}
 });
diff --git a/src/web/app/mobile/views/components/index.ts b/src/web/app/mobile/views/components/index.ts
index f5e4ce48f4..a2a87807d4 100644
--- a/src/web/app/mobile/views/components/index.ts
+++ b/src/web/app/mobile/views/components/index.ts
@@ -13,6 +13,7 @@ import userCard from './user-card.vue';
 import postDetail from './post-detail.vue';
 import followButton from './follow-button.vue';
 import friendsMaker from './friends-maker.vue';
+import notification from './notification.vue';
 import notifications from './notifications.vue';
 import notificationPreview from './notification-preview.vue';
 
@@ -29,5 +30,6 @@ Vue.component('mk-user-card', userCard);
 Vue.component('mk-post-detail', postDetail);
 Vue.component('mk-follow-button', followButton);
 Vue.component('mk-friends-maker', friendsMaker);
+Vue.component('mk-notification', notification);
 Vue.component('mk-notifications', notifications);
 Vue.component('mk-notification-preview', notificationPreview);
diff --git a/src/web/app/mobile/views/components/notification.vue b/src/web/app/mobile/views/components/notification.vue
index 98390f1c11..dce373b452 100644
--- a/src/web/app/mobile/views/components/notification.vue
+++ b/src/web/app/mobile/views/components/notification.vue
@@ -106,6 +106,7 @@ import Vue from 'vue';
 import getPostSummary from '../../../../../common/get-post-summary';
 
 export default Vue.extend({
+	props: ['notification'],
 	data() {
 		return {
 			getPostSummary
diff --git a/src/web/app/mobile/views/components/notifications.vue b/src/web/app/mobile/views/components/notifications.vue
index 99083ed4b0..1cd6e2bc13 100644
--- a/src/web/app/mobile/views/components/notifications.vue
+++ b/src/web/app/mobile/views/components/notifications.vue
@@ -10,7 +10,8 @@
 		</template>
 	</div>
 	<button class="more" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications">
-		<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:mobile.tags.mk-notifications.more%' }
+		<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>
+		{{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:mobile.tags.mk-notifications.more%' }}
 	</button>
 	<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:mobile.tags.mk-notifications.empty%</p>
 	<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
diff --git a/src/web/app/mobile/views/components/posts.vue b/src/web/app/mobile/views/components/posts.vue
index b028264b52..34fb0749a2 100644
--- a/src/web/app/mobile/views/components/posts.vue
+++ b/src/web/app/mobile/views/components/posts.vue
@@ -3,7 +3,7 @@
 	<slot name="head"></slot>
 	<slot></slot>
 	<template v-for="(post, i) in _posts">
-		<x-post :post="post" :key="post.id"/>
+		<x-post :post="post" :key="post.id" @update:post="onPostUpdated(i, $event)"/>
 		<p class="date" v-if="i != posts.length - 1 && post._date != _posts[i + 1]._date">
 			<span>%fa:angle-up%{{ post._datetext }}</span>
 			<span>%fa:angle-down%{{ _posts[i + 1]._datetext }}</span>
@@ -39,6 +39,11 @@ export default Vue.extend({
 				return post;
 			});
 		}
+	},
+	methods: {
+		onPostUpdated(i, post) {
+			Vue.set((this as any).posts, i, post);
+		}
 	}
 });
 </script>
diff --git a/src/web/app/mobile/views/pages/post.vue b/src/web/app/mobile/views/pages/post.vue
index c62a001f2d..2ed2ebfcfd 100644
--- a/src/web/app/mobile/views/pages/post.vue
+++ b/src/web/app/mobile/views/pages/post.vue
@@ -4,7 +4,7 @@
 	<main v-if="!fetching">
 		<a v-if="post.next" :href="post.next">%fa:angle-up%%i18n:mobile.tags.mk-post-page.next%</a>
 		<div>
-			<mk-post-detail :post="parent.post"/>
+			<mk-post-detail :post="post"/>
 		</div>
 		<a v-if="post.prev" :href="post.prev">%fa:angle-down%%i18n:mobile.tags.mk-post-page.prev%</a>
 	</main>
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index 335b2bc1ef..c9c1c6bfbd 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -58,7 +58,7 @@
 
 <script lang="ts">
 import Vue from 'vue';
-import age from 's-age';
+import * as age from 's-age';
 import Progress from '../../../common/scripts/loading';
 import XHome from './user/home.vue';