From ba85942f76c0b7c0b458b48289569ada9aee2be1 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Sat, 11 Nov 2017 10:58:13 +0900 Subject: [PATCH] #905 --- locales/en.yml | 9 + locales/ja.yml | 9 + src/api/endpoints/posts/timeline.ts | 23 ++- .../desktop/tags/home-widgets/timeline.tag | 18 +- .../desktop/tags/home-widgets/timemachine.tag | 165 ++++++++++++++++++ src/web/app/desktop/tags/home.tag | 4 +- src/web/app/desktop/tags/index.js | 1 + 7 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/web/app/desktop/tags/home-widgets/timemachine.tag diff --git a/locales/en.yml b/locales/en.yml index c69dc22b1d..4eae825074 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -13,6 +13,15 @@ common: months_ago: "{}month(s) ago" years_ago: "{}year(s) ago" + weekday-short: + sunday: "S" + monday: "M" + tuesday: "T" + wednesday: "W" + thursday: "T" + friday: "F" + satruday: "S" + reactions: like: "Like" love: "Love" diff --git a/locales/ja.yml b/locales/ja.yml index 782b87bd83..82589aadff 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -13,6 +13,15 @@ common: months_ago: "{}ヶ月前" years_ago: "{}年前" + weekday-short: + sunday: "日" + monday: "月" + tuesday: "火" + wednesday: "水" + thursday: "木" + friday: "金" + satruday: "土" + reactions: like: "いいね" love: "ハート" diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 7af435e82a..0d08b95463 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -29,9 +29,17 @@ module.exports = async (params, user, app) => { const [maxId, maxIdErr] = $(params.max_id).optional.id().$; if (maxIdErr) throw 'invalid max_id param'; - // Check if both of since_id and max_id is specified - if (sinceId && maxId) { - throw 'cannot set since_id and max_id'; + // Get 'since_date' parameter + const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; + if (sinceDateErr) throw 'invalid since_date param'; + + // Get 'max_date' parameter + const [maxDate, maxDateErr] = $(params.max_date).optional.number().$; + if (maxDateErr) throw 'invalid max_date param'; + + // Check if only one of since_id, max_id, since_date, max_date specified + if ([sinceId, maxId, sinceDate, maxDate].filter(x => x != null).length > 1) { + throw 'only one of since_id, max_id, since_date, max_date can be specified'; } const { followingIds, watchingChannelIds } = await rap({ @@ -81,6 +89,15 @@ module.exports = async (params, user, app) => { query._id = { $lt: maxId }; + } else if (sinceDate) { + sort._id = 1; + query.created_at = { + $gt: new Date(sinceDate) + }; + } else if (maxDate) { + query.created_at = { + $lt: new Date(maxDate) + }; } //#endregion diff --git a/src/web/app/desktop/tags/home-widgets/timeline.tag b/src/web/app/desktop/tags/home-widgets/timeline.tag index 08d96ad715..735783049c 100644 --- a/src/web/app/desktop/tags/home-widgets/timeline.tag +++ b/src/web/app/desktop/tags/home-widgets/timeline.tag @@ -70,7 +70,13 @@ }; this.load = (cb) => { - this.api('posts/timeline').then(posts => { + this.update({ + isLoading: true + }); + + this.api('posts/timeline', { + max_date: this.date ? this.date.getTime() : undefined + }).then(posts => { this.update({ isLoading: false, isEmpty: posts.length == 0 @@ -114,5 +120,15 @@ const current = window.scrollY + window.innerHeight; if (current > document.body.offsetHeight - 8) this.more(); }; + + this.warp = date => { + console.log(date); + + this.update({ + date: date + }); + + this.load(); + }; </script> </mk-timeline-home-widget> diff --git a/src/web/app/desktop/tags/home-widgets/timemachine.tag b/src/web/app/desktop/tags/home-widgets/timemachine.tag new file mode 100644 index 0000000000..b6c53e0284 --- /dev/null +++ b/src/web/app/desktop/tags/home-widgets/timemachine.tag @@ -0,0 +1,165 @@ +<mk-timemachine-home-widget> + <button onclick={ prev }><i class="fa fa-chevron-circle-left"></i></button> + <p class="title">{ year }/{ month }</p> + <button onclick={ next }><i class="fa fa-chevron-circle-right"></i></button> + + <div class="calendar"> + <div class="weekday" each={ day, i in Array(7).fill(0) }>{ weekdayText[i] }</div> + <div each={ day, i in Array(paddingDays).fill(0) }></div> + <div class="day" each={ day, i in Array(days).fill(0) } data-today={ isToday(i + 1) } onclick={ go.bind(null, i + 1) }>{ i + 1 }</div> + </div> + <style> + :scope + display block + color #777 + background #fff + + > .title + z-index 1 + margin 0 + padding 0 16px + text-align center + line-height 42px + font-size 0.9em + font-weight bold + color #888 + box-shadow 0 1px rgba(0, 0, 0, 0.07) + + > i + margin-right 4px + + > button + position absolute + z-index 2 + top 0 + padding 0 + width 42px + font-size 0.9em + line-height 42px + color #ccc + + &:hover + color #aaa + + &:active + color #999 + + &:first-of-type + left 0 + + &:last-of-type + right 0 + + > .calendar + display flex + flex-wrap wrap + padding 16px + + > div + width calc(100% * (1/7)) + text-align center + line-height 32px + font-size 14px + + &.weekday + color #19a2a9 + + &.day + cursor pointer + + &:hover + background rgba(0, 0, 0, 0.025) + + &:active + background rgba(0, 0, 0, 0.05) + + &[data-today] + color $theme-color-foreground + background $theme-color + + &:hover + background lighten($theme-color, 10%) + + &:active + background darken($theme-color, 10%) + + </style> + <script> + const eachMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + + function isLeapYear(year) { + return (year % 400 == 0) ? true : + (year % 100 == 0) ? false : + (year % 4 == 0) ? true : + false; + } + + this.today = new Date(); + this.year = this.today.getFullYear(); + this.month = this.today.getMonth() + 1; + this.weekdayText = [ + '%i18n:common.weekday-short.sunday%', + '%i18n:common.weekday-short.monday%', + '%i18n:common.weekday-short.tuesday%', + '%i18n:common.weekday-short.wednesday%', + '%i18n:common.weekday-short.thursday%', + '%i18n:common.weekday-short.friday%', + '%i18n:common.weekday-short.satruday%' + ]; + + this.on('mount', () => { + this.calc(); + }); + + this.isToday = day => { + return this.year == this.today.getFullYear() && this.month == this.today.getMonth() + 1 && day == this.today.getDate(); + }; + + this.calc = () => { + let days = eachMonthDays[this.month - 1]; + + // うるう年なら+1日 + if (this.month == 2 && isLeapYear(this.year)) days++; + + const date = new Date(this.year, this.month - 1, 1); + const weekday = date.getDay(); + + this.update({ + paddingDays: weekday, + days: days + }); + }; + + this.prev = () => { + if (this.month == 1) { + this.update({ + year: this.year - 1, + month: 12 + }); + } else { + this.update({ + month: this.month - 1 + }); + } + this.calc(); + }; + + this.next = () => { + if (this.month == 12) { + this.update({ + year: this.year + 1, + month: 1 + }); + } else { + this.update({ + month: this.month + 1 + }); + } + this.calc(); + }; + + this.go = day => { + this.opts.tl.warp(new Date(this.year, this.month - 1, day, 23, 59, 59, 999)); + }; +</script> +</mk-timemachine-home-widget> diff --git a/src/web/app/desktop/tags/home.tag b/src/web/app/desktop/tags/home.tag index ecfe23adee..452499d70c 100644 --- a/src/web/app/desktop/tags/home.tag +++ b/src/web/app/desktop/tags/home.tag @@ -5,6 +5,7 @@ <select ref="widgetSelector"> <option value="profile">プロフィール</option> <option value="calendar">カレンダー</option> + <option value="timemachine">カレンダー(タイムマシン)</option> <option value="activity">アクティビティ</option> <option value="rss-reader">RSSリーダー</option> <option value="trends">トレンド</option> @@ -214,7 +215,8 @@ this.home.push(riot.mount(el, { id: widget.id, - data: widget.data + data: widget.data, + tl: this.refs.tl })[0]); }; diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js index ff513657ac..865c3d3e06 100644 --- a/src/web/app/desktop/tags/index.js +++ b/src/web/app/desktop/tags/index.js @@ -41,6 +41,7 @@ require('./home-widgets/activity.tag'); require('./home-widgets/server.tag'); require('./home-widgets/slideshow.tag'); require('./home-widgets/channel.tag'); +require('./home-widgets/timemachine.tag'); require('./timeline.tag'); require('./messaging/window.tag'); require('./messaging/room-window.tag');