From a501a3cbc4293fbf5a3558a613ff91e89f9cb28f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sat, 25 Mar 2017 23:23:22 +0900
Subject: [PATCH] #322

---
 src/api/endpoints.ts                          |   4 +
 src/api/endpoints/posts/trend.ts              |  76 ++++++++++++
 .../app/desktop/tags/home-widgets/trends.tag  | 112 ++++++++++++++++++
 src/web/app/desktop/tags/home.tag             |   1 +
 src/web/app/desktop/tags/index.js             |   1 +
 5 files changed, 194 insertions(+)
 create mode 100644 src/api/endpoints/posts/trend.ts
 create mode 100644 src/web/app/desktop/tags/home-widgets/trends.tag

diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts
index f0031b82a2..b72392db64 100644
--- a/src/api/endpoints.ts
+++ b/src/api/endpoints.ts
@@ -360,6 +360,10 @@ const endpoints: Endpoint[] = [
 			max: 100
 		}
 	},
+	{
+		name: 'posts/trend',
+		withCredential: true
+	},
 	{
 		name: 'posts/reactions',
 		withCredential: true
diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts
new file mode 100644
index 0000000000..0f0ea4876c
--- /dev/null
+++ b/src/api/endpoints/posts/trend.ts
@@ -0,0 +1,76 @@
+/**
+ * Module dependencies
+ */
+const ms = require('ms');
+import $ from 'cafy';
+import Post from '../../models/post';
+import serialize from '../../serializers/post';
+
+/**
+ * Get trend posts
+ *
+ * @param {any} params
+ * @param {any} user
+ * @return {Promise<any>}
+ */
+module.exports = (params, user) => new Promise(async (res, rej) => {
+	// Get 'limit' parameter
+	const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
+	if (limitErr) return rej('invalid limit param');
+
+	// Get 'offset' parameter
+	const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$;
+	if (offsetErr) return rej('invalid offset param');
+
+	// Get 'reply' parameter
+	const [reply, replyErr] = $(params.reply).optional.boolean().$;
+	if (replyErr) return rej('invalid reply param');
+
+	// Get 'repost' parameter
+	const [repost, repostErr] = $(params.repost).optional.boolean().$;
+	if (repostErr) return rej('invalid repost param');
+
+	// Get 'media' parameter
+	const [media, mediaErr] = $(params.media).optional.boolean().$;
+	if (mediaErr) return rej('invalid media param');
+
+	// Get 'poll' parameter
+	const [poll, pollErr] = $(params.poll).optional.boolean().$;
+	if (pollErr) return rej('invalid poll param');
+
+	const query = {
+		created_at: {
+			$gte: new Date(Date.now() - ms('1days'))
+		}
+	} as any;
+
+	if (reply != undefined) {
+		query.reply_to_id = reply ? { $exists: true, $ne: null } : null;
+	}
+
+	if (repost != undefined) {
+		query.repost_id = repost ? { $exists: true, $ne: null } : null;
+	}
+
+	if (media != undefined) {
+		query.media_ids = media ? { $exists: true, $ne: null } : null;
+	}
+
+	if (poll != undefined) {
+		query.poll = poll ? { $exists: true, $ne: null } : null;
+	}
+
+	// Issue query
+	const posts = await Post
+		.find(query, {
+			limit: limit,
+			skip: offset,
+			sort: {
+				repost_count: -1
+			}
+		});
+
+	// Serialize
+	res(await Promise.all(posts.map(async post =>
+		await serialize(post, user, { detail: true }))));
+});
diff --git a/src/web/app/desktop/tags/home-widgets/trends.tag b/src/web/app/desktop/tags/home-widgets/trends.tag
new file mode 100644
index 0000000000..0ad7729abd
--- /dev/null
+++ b/src/web/app/desktop/tags/home-widgets/trends.tag
@@ -0,0 +1,112 @@
+<mk-trends-home-widget>
+	<p class="title"><i class="fa fa-fire"></i>トレンド</p>
+	<button onclick={ refresh } title="他を見る"><i class="fa fa-refresh"></i></button>
+	<div class="post" if={ !loading && post != null }>
+		<p class="text">{ post.text }</p>
+		<p class="author">―<a href="/{ post.user.username }">@{ post.user.username }</a></p>
+	</div>
+	<p class="empty" if={ !loading && post == null }>ありません!</p>
+	<p class="loading" if={ loading }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます<mk-ellipsis></mk-ellipsis></p>
+	<style>
+		:scope
+			display block
+			background #fff
+
+			> .title
+				margin 0
+				padding 0 16px
+				line-height 42px
+				font-size 0.9em
+				font-weight bold
+				color #888
+				border-bottom solid 1px #eee
+
+				> i
+					margin-right 4px
+
+			> button
+				position absolute
+				z-index 2
+				top 0
+				right 0
+				padding 0
+				width 42px
+				font-size 0.9em
+				line-height 42px
+				color #ccc
+
+				&:hover
+					color #aaa
+
+				&:active
+					color #999
+
+			> .post
+				padding 16px
+				font-size 12px
+				font-style oblique
+				color #555
+
+				> p
+					margin 0
+
+				> .author
+					> a
+						color inherit
+
+			> .empty
+				margin 0
+				padding 16px
+				text-align center
+				color #aaa
+
+			> .loading
+				margin 0
+				padding 16px
+				text-align center
+				color #aaa
+
+				> i
+					margin-right 4px
+
+	</style>
+	<script>
+		this.mixin('api');
+
+		this.post = null;
+		this.loading = true;
+
+		this.offset = 0;
+
+		this.on('mount', () => {
+			this.fetch();
+		});
+
+		this.fetch = () => {
+			this.update({
+				loading: true,
+				post: null
+			});
+			this.api('posts/trend', {
+				limit: 1,
+				offset: this.offset,
+				repost: false,
+				reply: false,
+				media: false,
+				poll: false
+			}).then(posts => {
+				const post = posts ? posts[0] : null;
+				if (post == null) this.offset = 0;
+				this.update({
+					loading: false,
+					post: post
+				});
+			});
+		};
+
+		this.refresh = () => {
+			this.offset++;
+			this.fetch();
+		};
+	</script>
+</mk-trends-home-widget>
diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag
index 93840bdf0e..a913739af6 100644
--- a/src/web/app/desktop/tags/home.tag
+++ b/src/web/app/desktop/tags/home.tag
@@ -69,6 +69,7 @@
 				'profile',
 				'calendar',
 				'rss-reader',
+				'trends',
 				'photo-stream',
 				'version'
 			],
diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js
index 3032c9c544..f92200b3d9 100644
--- a/src/web/app/desktop/tags/index.js
+++ b/src/web/app/desktop/tags/index.js
@@ -43,6 +43,7 @@ require('./home-widgets/photo-stream.tag');
 require('./home-widgets/broadcast.tag');
 require('./home-widgets/version.tag');
 require('./home-widgets/recommended-polls.tag');
+require('./home-widgets/trends.tag');
 require('./timeline.tag');
 require('./messaging/window.tag');
 require('./messaging/room-window.tag');