From 3ae824c3542b0e232b9847ae702956e631acb276 Mon Sep 17 00:00:00 2001
From: syuilo
Date: Mon, 26 Feb 2018 00:39:05 +0900
Subject: [PATCH] :v:
---
src/api/endpoints/posts/create.ts | 24 +++++++-
.../desktop/views/components/post-detail.vue | 29 +++++++++
.../desktop/views/components/posts.post.vue | 35 ++++++++++-
.../app/desktop/views/components/timeline.vue | 14 ++++-
src/web/app/desktop/views/pages/search.vue | 55 ++++++++++++-----
.../mobile/views/components/post-detail.vue | 25 ++++++++
.../mobile/views/components/posts.post.vue | 30 ++++++++--
src/web/app/mobile/views/pages/search.vue | 59 +++++++++++++------
8 files changed, 227 insertions(+), 44 deletions(-)
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 0fa52221f..075e1ac9f 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -31,6 +31,10 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$;
if (textErr) return rej('invalid text');
+ // Get 'tags' parameter
+ const [tags = [], tagsErr] = $(params.tags).optional.array('string').unique().eachQ(t => t.range(1, 32)).$;
+ if (tagsErr) return rej('invalid tags');
+
// Get 'media_ids' parameter
const [mediaIds, mediaIdsErr] = $(params.media_ids).optional.array('id').unique().range(1, 4).$;
if (mediaIdsErr) return rej('invalid media_ids');
@@ -205,6 +209,23 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
}
}
+ let tokens = null;
+ if (text) {
+ // Analyze
+ tokens = parse(text);
+
+ // Extract hashtags
+ const hashtags = tokens
+ .filter(t => t.type == 'hashtag')
+ .map(t => t.hashtag);
+
+ hashtags.forEach(tag => {
+ if (tags.indexOf(tag) == -1) {
+ tags.push(tag);
+ }
+ });
+ }
+
// 投稿を作成
const post = await Post.insert({
created_at: new Date(),
@@ -215,6 +236,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
repost_id: repost ? repost._id : undefined,
poll: poll,
text: text,
+ tags: tags,
user_id: user._id,
app_id: app ? app._id : null,
@@ -423,8 +445,6 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
// If has text content
if (text) {
- // Analyze
- const tokens = parse(text);
/*
// Extract a hashtags
const hashtags = tokens
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index c453867df..1e31752fe 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -44,6 +44,9 @@
+
+ {{ tag }}
+
%fa:reply%
+
+ {{ tag }}
+
RP:
@@ -342,9 +345,9 @@ export default Vue.extend({
display block
float left
margin 0 16px 10px 0
- position -webkit-sticky
- position sticky
- top 74px
+ //position -webkit-sticky
+ //position sticky
+ //top 74px
> .avatar
display block
@@ -428,6 +431,32 @@ export default Vue.extend({
font-style oblique
color #a0bf46
+ > .tags
+ > *
+ margin 0 8px 0 0
+ padding 0 8px 0 16px
+ font-size 90%
+ color #8d969e
+ background #edf0f3
+ border-radius 4px
+
+ &:before
+ content ""
+ display block
+ position absolute
+ top 0
+ bottom 0
+ left 4px
+ width 8px
+ height 8px
+ margin auto 0
+ background #fff
+ border-radius 100%
+
+ &:hover
+ text-decoration none
+ background #e2e7ec
+
> .mk-poll
font-size 80%
diff --git a/src/web/app/desktop/views/components/timeline.vue b/src/web/app/desktop/views/components/timeline.vue
index eef62104e..0d16d60df 100644
--- a/src/web/app/desktop/views/components/timeline.vue
+++ b/src/web/app/desktop/views/components/timeline.vue
@@ -24,6 +24,7 @@ export default Vue.extend({
return {
fetching: true,
moreFetching: false,
+ existMore: false,
posts: [],
connection: null,
connectionId: null,
@@ -62,8 +63,13 @@ export default Vue.extend({
this.fetching = true;
(this as any).api('posts/timeline', {
+ limit: 11,
until_date: this.date ? this.date.getTime() : undefined
}).then(posts => {
+ if (posts.length == 11) {
+ posts.pop();
+ this.existMore = true;
+ }
this.posts = posts;
this.fetching = false;
this.$emit('loaded');
@@ -71,11 +77,17 @@ export default Vue.extend({
});
},
more() {
- if (this.moreFetching || this.fetching || this.posts.length == 0) return;
+ if (this.moreFetching || this.fetching || this.posts.length == 0 || !this.existMore) return;
this.moreFetching = true;
(this as any).api('posts/timeline', {
+ limit: 11,
until_id: this.posts[this.posts.length - 1].id
}).then(posts => {
+ if (posts.length == 11) {
+ posts.pop();
+ } else {
+ this.existMore = false;
+ }
this.posts = this.posts.concat(posts);
this.moreFetching = false;
});
diff --git a/src/web/app/desktop/views/pages/search.vue b/src/web/app/desktop/views/pages/search.vue
index b8e8db2e7..afd37c8ce 100644
--- a/src/web/app/desktop/views/pages/search.vue
+++ b/src/web/app/desktop/views/pages/search.vue
@@ -1,13 +1,13 @@
- %fa:search%「{{ query }}」に関する投稿は見つかりませんでした。
-
+ %fa:search%「{{ q }}」に関する投稿は見つかりませんでした。
+
%fa:search%
%fa:spinner .pulse .fw%
@@ -21,33 +21,34 @@ import Vue from 'vue';
import Progress from '../../../common/scripts/loading';
import parse from '../../../common/scripts/parse-search-query';
-const limit = 30;
+const limit = 20;
export default Vue.extend({
- props: ['query'],
data() {
return {
fetching: true,
moreFetching: false,
+ existMore: false,
offset: 0,
posts: []
};
},
+ watch: {
+ $route: 'fetch'
+ },
computed: {
empty(): boolean {
return this.posts.length == 0;
+ },
+ q(): string {
+ return this.$route.query.q;
}
},
mounted() {
- Progress.start();
-
document.addEventListener('keydown', this.onDocumentKeydown);
window.addEventListener('scroll', this.onScroll);
- (this as any).api('posts/search', parse(this.query)).then(posts => {
- this.posts = posts;
- this.fetching = false;
- });
+ this.fetch();
},
beforeDestroy() {
document.removeEventListener('keydown', this.onDocumentKeydown);
@@ -61,16 +62,38 @@ export default Vue.extend({
}
}
},
+ fetch() {
+ this.fetching = true;
+ Progress.start();
+
+ (this as any).api('posts/search', Object.assign({
+ limit: limit + 1,
+ offset: this.offset
+ }, parse(this.q))).then(posts => {
+ if (posts.length == limit + 1) {
+ posts.pop();
+ this.existMore = true;
+ }
+ this.posts = posts;
+ this.fetching = false;
+ Progress.done();
+ });
+ },
more() {
- if (this.moreFetching || this.fetching || this.posts.length == 0) return;
+ if (this.moreFetching || this.fetching || this.posts.length == 0 || !this.existMore) return;
this.offset += limit;
this.moreFetching = true;
- return (this as any).api('posts/search', Object.assign({}, parse(this.query), {
- limit: limit,
+ return (this as any).api('posts/search', Object.assign({
+ limit: limit + 1,
offset: this.offset
- })).then(posts => {
- this.moreFetching = false;
+ }, parse(this.q))).then(posts => {
+ if (posts.length == limit + 1) {
+ posts.pop();
+ } else {
+ this.existMore = false;
+ }
this.posts = this.posts.concat(posts);
+ this.moreFetching = false;
});
},
onScroll() {
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index 05138607f..a83744ec4 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -39,6 +39,9 @@
+
+ {{ tag }}
+
@@ -346,10 +349,7 @@ export default Vue.extend({
font-size 1.1em
color #717171
- > .dummy
- display none
-
- mk-url-preview
+ .mk-url-preview
margin-top 8px
> .channel
@@ -364,6 +364,28 @@ export default Vue.extend({
font-style oblique
color #a0bf46
+ > .tags
+ > *
+ margin 0 8px 0 0
+ padding 0 8px 0 16px
+ font-size 90%
+ color #8d969e
+ background #edf0f3
+ border-radius 4px
+
+ &:before
+ content ""
+ display block
+ position absolute
+ top 0
+ bottom 0
+ left 4px
+ width 8px
+ height 8px
+ margin auto 0
+ background #fff
+ border-radius 100%
+
[data-is-me]:after
content "you"
padding 0 4px
diff --git a/src/web/app/mobile/views/pages/search.vue b/src/web/app/mobile/views/pages/search.vue
index b6e114a82..cbab504e3 100644
--- a/src/web/app/mobile/views/pages/search.vue
+++ b/src/web/app/mobile/views/pages/search.vue
@@ -1,10 +1,10 @@
- %fa:search% {{ query }}
+ %fa:search% {{ q }}
- {{ '%i18n:mobile.tags.mk-search-posts.empty%'.replace('{}', query) }}
-