summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2017-11-14 08:21:19 +0900
committersyuilo <syuilotan@yahoo.co.jp>2017-11-14 08:21:19 +0900
commit107ecfb07fe81dc5b89d9ef57a7be77657463d31 (patch)
tree65e1f0416b88304a760a853cbb010d2423c0a435 /src
parentClean up (diff)
downloadsharkey-107ecfb07fe81dc5b89d9ef57a7be77657463d31.tar.gz
sharkey-107ecfb07fe81dc5b89d9ef57a7be77657463d31.tar.bz2
sharkey-107ecfb07fe81dc5b89d9ef57a7be77657463d31.zip
なんか
Diffstat (limited to 'src')
-rw-r--r--src/api/endpoints/users/posts.ts28
-rw-r--r--src/web/app/desktop/tags/calendar.tag241
-rw-r--r--src/web/app/desktop/tags/home-widgets/timemachine.tag231
-rw-r--r--src/web/app/desktop/tags/index.ts6
-rw-r--r--src/web/app/desktop/tags/user-graphs.tag41
-rw-r--r--src/web/app/desktop/tags/user-header.tag147
-rw-r--r--src/web/app/desktop/tags/user-home.tag46
-rw-r--r--src/web/app/desktop/tags/user-photos.tag91
-rw-r--r--src/web/app/desktop/tags/user-profile.tag102
-rw-r--r--src/web/app/desktop/tags/user-timeline.tag9
-rw-r--r--src/web/app/desktop/tags/user.tag457
11 files changed, 727 insertions, 672 deletions
diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts
index d8204b8b80..fe821cf17a 100644
--- a/src/api/endpoints/users/posts.ts
+++ b/src/api/endpoints/users/posts.ts
@@ -46,9 +46,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
const [maxId, maxIdErr] = $(params.max_id).optional.id().$;
if (maxIdErr) return rej('invalid max_id param');
- // Check if both of since_id and max_id is specified
- if (sinceId && maxId) {
- return rej('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 q = userId !== undefined
@@ -66,13 +74,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
return rej('user not found');
}
- // Construct query
+ //#region Construct query
const sort = {
_id: -1
};
+
const query = {
user_id: user._id
} as any;
+
if (sinceId) {
sort._id = 1;
query._id = {
@@ -82,6 +92,15 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
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)
+ };
}
if (!includeReplies) {
@@ -94,6 +113,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
$ne: null
};
}
+ //#endregion
// Issue query
const posts = await Post
diff --git a/src/web/app/desktop/tags/calendar.tag b/src/web/app/desktop/tags/calendar.tag
new file mode 100644
index 0000000000..3535e81901
--- /dev/null
+++ b/src/web/app/desktop/tags/calendar.tag
@@ -0,0 +1,241 @@
+<mk-calendar data-melt={ opts.design == 4 || opts.design == 5 }>
+ <virtual if={ opts.design == 0 || opts.design == 1 }>
+ <button onclick={ prev } title="%i18n:desktop.tags.mk-calendar.prev%"><i class="fa fa-chevron-circle-left"></i></button>
+ <p class="title">{ '%i18n:desktop.tags.mk-calendar.title%'.replace('{1}', year).replace('{2}', month) }</p>
+ <button onclick={ next } title="%i18n:desktop.tags.mk-calendar.next%"><i class="fa fa-chevron-circle-right"></i></button>
+ </virtual>
+
+ <div class="calendar">
+ <div class="weekday" if={ opts.design == 0 || opts.design == 2 || opts.design == 4} each={ day, i in Array(7).fill(0) }
+ data-today={ year == today.getFullYear() && month == today.getMonth() + 1 && today.getDay() == i }
+ data-is-donichi={ i == 0 || i == 6 }>{ 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) }
+ data-selected={ isSelected(i + 1) }
+ data-is-out-of-range={ isOutOfRange(i + 1) }
+ data-is-donichi={ isDonichi(i + 1) }
+ onclick={ go.bind(null, i + 1) }
+ title={ isOutOfRange(i + 1) ? null : '%i18n:desktop.tags.mk-calendar.go%' }><div>{ i + 1 }</div></div>
+ </div>
+ <style>
+ :scope
+ display block
+ color #777
+ background #fff
+ border solid 1px rgba(0, 0, 0, 0.075)
+ border-radius 6px
+
+ &[data-melt]
+ background transparent !important
+ border none !important
+
+ > .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
+
+ *
+ user-select none
+
+ > div
+ width calc(100% * (1/7))
+ text-align center
+ line-height 32px
+ font-size 14px
+
+ &.weekday
+ color #19a2a9
+
+ &[data-is-donichi]
+ color #ef95a0
+
+ &[data-today]
+ box-shadow 0 0 0 1px #19a2a9 inset
+ border-radius 6px
+
+ &[data-is-donichi]
+ box-shadow 0 0 0 1px #ef95a0 inset
+
+ &.day
+ cursor pointer
+ color #777
+
+ > div
+ border-radius 6px
+
+ &:hover > div
+ background rgba(0, 0, 0, 0.025)
+
+ &:active > div
+ background rgba(0, 0, 0, 0.05)
+
+ &[data-is-donichi]
+ color #ef95a0
+
+ &[data-is-out-of-range]
+ cursor default
+ color rgba(#777, 0.5)
+
+ &[data-is-donichi]
+ color rgba(#ef95a0, 0.5)
+
+ &[data-selected]
+ font-weight bold
+
+ > div
+ background rgba(0, 0, 0, 0.025)
+
+ &:active > div
+ background rgba(0, 0, 0, 0.05)
+
+ &[data-today]
+ > div
+ color $theme-color-foreground
+ background $theme-color
+
+ &:hover > div
+ background lighten($theme-color, 10%)
+
+ &:active > div
+ background darken($theme-color, 10%)
+
+ </style>
+ <script>
+ if (this.opts.design == null) this.opts.design = 0;
+
+ 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.selected = this.today;
+ 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.isSelected = day => {
+ return this.year == this.selected.getFullYear() && this.month == this.selected.getMonth() + 1 && day == this.selected.getDate();
+ };
+
+ this.isOutOfRange = day => {
+ const test = (new Date(this.year, this.month - 1, day)).getTime();
+ return test > this.today.getTime() ||
+ (this.opts.start ? test < this.opts.start.getTime() : false);
+ };
+
+ this.isDonichi = day => {
+ const weekday = (new Date(this.year, this.month - 1, day)).getDay();
+ return weekday == 0 || weekday == 6;
+ };
+
+ 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 => {
+ if (this.isOutOfRange(day)) return;
+ const date = new Date(this.year, this.month - 1, day, 23, 59, 59, 999);
+ this.update({
+ selected: date
+ });
+ this.opts.warp(date);
+ };
+</script>
+</mk-calendar>
diff --git a/src/web/app/desktop/tags/home-widgets/timemachine.tag b/src/web/app/desktop/tags/home-widgets/timemachine.tag
index 984258d2ba..2199cf4c67 100644
--- a/src/web/app/desktop/tags/home-widgets/timemachine.tag
+++ b/src/web/app/desktop/tags/home-widgets/timemachine.tag
@@ -1,139 +1,10 @@
-<mk-timemachine-home-widget data-melt={ data.design == 4 || data.design == 5 }>
- <virtual if={ data.design == 0 || data.design == 1 }>
- <button onclick={ prev } title="%i18n:desktop.tags.mk-timemachine-home-widget.prev%"><i class="fa fa-chevron-circle-left"></i></button>
- <p class="title">{ '%i18n:desktop.tags.mk-timemachine-home-widget.title%'.replace('{1}', year).replace('{2}', month) }</p>
- <button onclick={ next } title="%i18n:desktop.tags.mk-timemachine-home-widget.next%"><i class="fa fa-chevron-circle-right"></i></button>
- </virtual>
-
- <div class="calendar">
- <div class="weekday" if={ data.design == 0 || data.design == 2 || data.design == 4} each={ day, i in Array(7).fill(0) }
- data-today={ year == today.getFullYear() && month == today.getMonth() + 1 && today.getDay() == i }
- data-is-donichi={ i == 0 || i == 6 }>{ 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) }
- data-selected={ isSelected(i + 1) }
- data-is-future={ isFuture(i + 1) }
- data-is-donichi={ isDonichi(i + 1) }
- onclick={ go.bind(null, i + 1) }
- title={ isFuture(i + 1) ? null : '%i18n:desktop.tags.mk-timemachine-home-widget.go%' }><div>{ i + 1 }</div></div>
- </div>
+<mk-timemachine-home-widget>
+ <mk-calendar design={ data.design } warp={ warp }/>
<style>
:scope
display block
- color #777
- background #fff
-
- &[data-melt]
- background transparent !important
- border none !important
-
- > .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
-
- *
- user-select none
-
- > div
- width calc(100% * (1/7))
- text-align center
- line-height 32px
- font-size 14px
-
- &.weekday
- color #19a2a9
-
- &[data-is-donichi]
- color #ef95a0
-
- &[data-today]
- box-shadow 0 0 0 1px #19a2a9 inset
- border-radius 6px
-
- &[data-is-donichi]
- box-shadow 0 0 0 1px #ef95a0 inset
-
- &.day
- cursor pointer
- color #777
-
- > div
- border-radius 6px
-
- &:hover > div
- background rgba(0, 0, 0, 0.025)
-
- &:active > div
- background rgba(0, 0, 0, 0.05)
-
- &[data-is-donichi]
- color #ef95a0
-
- &[data-is-future]
- cursor default
- color rgba(#777, 0.5)
-
- &[data-is-donichi]
- color rgba(#ef95a0, 0.5)
-
- &[data-selected]
- font-weight bold
-
- > div
- background rgba(0, 0, 0, 0.025)
-
- &:active > div
- background rgba(0, 0, 0, 0.05)
-
- &[data-today]
- > div
- color $theme-color-foreground
- background $theme-color
-
- &:hover > div
- background lighten($theme-color, 10%)
-
- &:active > div
- background darken($theme-color, 10%)
-
+ background transparent !important
+ border none !important
</style>
<script>
this.data = {
@@ -142,99 +13,7 @@
this.mixin('widget');
- 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.selected = this.today;
- 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.isSelected = day => {
- return this.year == this.selected.getFullYear() && this.month == this.selected.getMonth() + 1 && day == this.selected.getDate();
- };
-
- this.isFuture = day => {
- return (new Date(this.year, this.month - 1, day)).getTime() > this.today.getTime();
- };
-
- this.isDonichi = day => {
- const weekday = (new Date(this.year, this.month - 1, day)).getDay();
- return weekday == 0 || weekday == 6;
- };
-
- 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 => {
- if (this.isFuture(day)) return;
- const date = new Date(this.year, this.month - 1, day, 23, 59, 59, 999);
- this.update({
- selected: date
- });
+ this.warp = date => {
this.opts.tl.warp(date);
};
diff --git a/src/web/app/desktop/tags/index.ts b/src/web/app/desktop/tags/index.ts
index cd22dde352..f9df091bdc 100644
--- a/src/web/app/desktop/tags/index.ts
+++ b/src/web/app/desktop/tags/index.ts
@@ -52,13 +52,8 @@ require('./following-setuper.tag');
require('./ellipsis-icon.tag');
require('./ui.tag');
require('./home.tag');
-require('./user-header.tag');
-require('./user-profile.tag');
require('./user-timeline.tag');
require('./user.tag');
-require('./user-home.tag');
-require('./user-graphs.tag');
-require('./user-photos.tag');
require('./big-follow-button.tag');
require('./pages/entrance.tag');
require('./pages/entrance/signin.tag');
@@ -93,3 +88,4 @@ require('./user-following-window.tag');
require('./user-followers-window.tag');
require('./list-user.tag');
require('./detailed-post-window.tag');
+require('./calendar.tag');
diff --git a/src/web/app/desktop/tags/user-graphs.tag b/src/web/app/desktop/tags/user-graphs.tag
deleted file mode 100644
index 0677d8c187..0000000000
--- a/src/web/app/desktop/tags/user-graphs.tag
+++ /dev/null
@@ -1,41 +0,0 @@
-<mk-user-graphs>
- <section>
- <h1>投稿</h1>
- <mk-user-posts-graph user={ opts.user }/>
- </section>
- <section>
- <h1>フォロー/フォロワー</h1>
- <mk-user-friends-graph user={ opts.user }/>
- </section>
- <section>
- <h1>いいね</h1>
- <mk-user-likes-graph user={ opts.user }/>
- </section>
- <style>
- :scope
- display block
-
- > section
- margin 16px 0
- background #fff
- border solid 1px rgba(0, 0, 0, 0.1)
- border-radius 4px
-
- > h1
- margin 0 0 8px 0
- padding 0 16px
- line-height 40px
- font-size 1em
- color #666
- border-bottom solid 1px #eee
-
- > *:not(h1)
- margin 0 auto 16px auto
-
- </style>
- <script>
- this.on('mount', () => {
- this.trigger('loaded');
- });
- </script>
-</mk-user-graphs>
diff --git a/src/web/app/desktop/tags/user-header.tag b/src/web/app/desktop/tags/user-header.tag
deleted file mode 100644
index ea7ea6bb37..0000000000
--- a/src/web/app/desktop/tags/user-header.tag
+++ /dev/null
@@ -1,147 +0,0 @@
-<mk-user-header data-is-dark-background={ user.banner_url != null }>
- <div class="banner" ref="banner" style={ user.banner_url ? 'background-image: url(' + user.banner_url + '?thumbnail&size=1024)' : '' } onclick={ onUpdateBanner }></div><img class="avatar" src={ user.avatar_url + '?thumbnail&size=150' } alt="avatar"/>
- <div class="title">
- <p class="name" href={ '/' + user.username }>{ user.name }</p>
- <p class="username">@{ user.username }</p>
- <p class="location" if={ user.profile.location }><i class="fa fa-map-marker"></i>{ user.profile.location }</p>
- </div>
- <footer>
- <a href={ '/' + user.username }>投稿</a>
- <a href={ '/' + user.username + '/media' }>メディア</a>
- <a href={ '/' + user.username + '/graphs' }>グラフ</a>
- </footer>
- <style>
- :scope
- $footer-height = 58px
-
- display block
- background #fff
-
- &[data-is-dark-background]
- > .banner
- background-color #383838
-
- > .title
- color #fff
- background linear-gradient(transparent, rgba(0, 0, 0, 0.7))
-
- > .name
- text-shadow 0 0 8px #000
-
- > .banner
- height 280px
- background-color #f5f5f5
- background-size cover
- background-position center
-
- > .avatar
- display block
- position absolute
- bottom 16px
- left 16px
- z-index 2
- width 150px
- height 150px
- margin 0
- border solid 3px #fff
- border-radius 8px
- box-shadow 1px 1px 3px rgba(0, 0, 0, 0.2)
-
- > .title
- position absolute
- bottom $footer-height
- left 0
- width 100%
- padding 0 0 8px 195px
- color #656565
- font-family '游ゴシック', 'YuGothic', 'ヒラギノ角ゴ ProN W3', 'Hiragino Kaku Gothic ProN', 'Meiryo', 'メイリオ', sans-serif
-
- > .name
- display block
- margin 0
- line-height 40px
- font-weight bold
- font-size 2em
-
- > .username
- > .location
- display inline-block
- margin 0 16px 0 0
- line-height 20px
- opacity 0.8
-
- > i
- margin-right 4px
-
- > footer
- z-index 1
- height $footer-height
- padding-left 195px
- background #fff
-
- > a
- display inline-block
- margin 0
- width 100px
- line-height $footer-height
- color #555
-
- > button
- display block
- position absolute
- top 0
- right 0
- margin 8px
- padding 0
- width $footer-height - 16px
- line-height $footer-height - 16px - 2px
- font-size 1.2em
- color #777
- border solid 1px #eee
- border-radius 4px
-
- &:hover
- color #555
- border solid 1px #ddd
-
- </style>
- <script>
- import updateBanner from '../scripts/update-banner';
-
- this.mixin('i');
-
- this.user = this.opts.user;
-
- this.on('mount', () => {
- window.addEventListener('load', this.scroll);
- window.addEventListener('scroll', this.scroll);
- window.addEventListener('resize', this.scroll);
- });
-
- this.on('unmount', () => {
- window.removeEventListener('load', this.scroll);
- window.removeEventListener('scroll', this.scroll);
- window.removeEventListener('resize', this.scroll);
- });
-
- this.scroll = () => {
- const top = window.scrollY;
- const height = 280/*px*/;
-
- const pos = 50 - ((top / height) * 50);
- this.refs.banner.style.backgroundPosition = `center ${pos}%`;
-
- const blur = top / 32
- if (blur <= 10) this.refs.banner.style.filter = `blur(${blur}px)`;
- };
-
- this.onUpdateBanner = () => {
- if (!this.SIGNIN || this.I.id != this.user.id) return;
-
- updateBanner(this.I, i => {
- this.user.banner_url = i.banner_url;
- this.update();
- });
- };
- </script>
-</mk-user-header>
diff --git a/src/web/app/desktop/tags/user-home.tag b/src/web/app/desktop/tags/user-home.tag
deleted file mode 100644
index a879db5bb6..0000000000
--- a/src/web/app/desktop/tags/user-home.tag
+++ /dev/null
@@ -1,46 +0,0 @@
-<mk-user-home>
- <div class="side">
- <mk-user-profile user={ user }/>
- <mk-user-photos user={ user }/>
- </div>
- <main>
- <mk-user-timeline ref="tl" user={ user }/>
- </main>
- <style>
- :scope
- display flex
- justify-content center
-
- > *
- > *
- display block
- //border solid 1px #eaeaea
- border solid 1px rgba(0, 0, 0, 0.075)
- border-radius 6px
-
- &:not(:last-child)
- margin-bottom 16px
-
- > main
- flex 1 1 560px
- max-width 560px
- margin 0
- padding 16px 0 16px 16px
-
- > .side
- flex 1 1 270px
- max-width 270px
- margin 0
- padding 16px 0 16px 0
-
- </style>
- <script>
- this.user = this.opts.user;
-
- this.on('mount', () => {
- this.refs.tl.on('loaded', () => {
- this.trigger('loaded');
- });
- });
- </script>
-</mk-user-home>
diff --git a/src/web/app/desktop/tags/user-photos.tag b/src/web/app/desktop/tags/user-photos.tag
deleted file mode 100644
index dce1e50add..0000000000
--- a/src/web/app/desktop/tags/user-photos.tag
+++ /dev/null
@@ -1,91 +0,0 @@
-<mk-user-photos>
- <p class="title"><i class="fa fa-camera"></i>フォト</p>
- <p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます<mk-ellipsis/></p>
- <div class="stream" if={ !initializing && images.length > 0 }>
- <virtual each={ image in images }>
- <div class="img" style={ 'background-image: url(' + image.url + '?thumbnail&size=256)' }></div>
- </virtual>
- </div>
- <p class="empty" if={ !initializing && images.length == 0 }>写真はありません</p>
- <style>
- :scope
- display block
- background #fff
-
- > .title
- z-index 1
- margin 0
- padding 0 16px
- 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
-
- > .stream
- display -webkit-flex
- display -moz-flex
- display -ms-flex
- display flex
- justify-content center
- flex-wrap wrap
- padding 8px
-
- > .img
- flex 1 1 33%
- width 33%
- height 80px
- background-position center center
- background-size cover
- background-clip content-box
- border solid 2px transparent
-
- > .initializing
- > .empty
- margin 0
- padding 16px
- text-align center
- color #aaa
-
- > i
- margin-right 4px
-
- </style>
- <script>
- import isPromise from '../../common/scripts/is-promise';
-
- this.mixin('api');
-
- this.images = [];
- this.initializing = true;
- this.user = null;
- this.userPromise = isPromise(this.opts.user)
- ? this.opts.user
- : Promise.resolve(this.opts.user);
-
- this.on('mount', () => {
- this.userPromise.then(user => {
- this.update({
- user: user
- });
-
- this.api('users/posts', {
- user_id: this.user.id,
- with_media: true,
- limit: 9
- }).then(posts => {
- this.initializing = false;
- posts.forEach(post => {
- post.media.forEach(media => {
- if (this.images.length < 9) this.images.push(media);
- });
- });
- this.update();
- });
- });
- });
- </script>
-</mk-user-photos>
diff --git a/src/web/app/desktop/tags/user-profile.tag b/src/web/app/desktop/tags/user-profile.tag
deleted file mode 100644
index 7472a47801..0000000000
--- a/src/web/app/desktop/tags/user-profile.tag
+++ /dev/null
@@ -1,102 +0,0 @@
-<mk-user-profile>
- <div class="friend-form" if={ SIGNIN && I.id != user.id }>
- <mk-big-follow-button user={ user }/>
- <p class="followed" if={ user.is_followed }>フォローされています</p>
- </div>
- <div class="description" if={ user.description }>{ user.description }</div>
- <div class="birthday" if={ user.profile.birthday }>
- <p><i class="fa fa-birthday-cake"></i>{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.profile.birthday) }歳)</p>
- </div>
- <div class="twitter" if={ user.twitter }>
- <p><i class="fa fa-twitter"></i><a href={ 'https://twitter.com/' + user.twitter.screen_name } target="_blank">@{ user.twitter.screen_name }</a></p>
- </div>
- <div class="status">
- <p class="posts-count"><i class="fa fa-angle-right"></i><a>{ user.posts_count }</a><b>ポスト</b></p>
- <p class="following"><i class="fa fa-angle-right"></i><a onclick={ showFollowing }>{ user.following_count }</a>人を<b>フォロー</b></p>
- <p class="followers"><i class="fa fa-angle-right"></i><a onclick={ showFollowers }>{ user.followers_count }</a>人の<b>フォロワー</b></p>
- </div>
- <style>
- :scope
- display block
- background #fff
-
- > *:first-child
- border-top none !important
-
- > .friend-form
- padding 16px
- border-top solid 1px #eee
-
- > mk-big-follow-button
- width 100%
-
- > .followed
- margin 12px 0 0 0
- padding 0
- text-align center
- line-height 24px
- font-size 0.8em
- color #71afc7
- background #eefaff
- border-radius 4px
-
- > .description
- padding 16px
- color #555
- border-top solid 1px #eee
-
- > .birthday
- padding 16px
- color #555
- border-top solid 1px #eee
-
- > p
- margin 0
-
- > i
- margin-right 8px
-
- > .twitter
- padding 16px
- color #555
- border-top solid 1px #eee
-
- > p
- margin 0
-
- > i
- margin-right 8px
-
- > .status
- padding 16px
- color #555
- border-top solid 1px #eee
-
- > p
- margin 8px 0
-
- > i
- margin-left 8px
- margin-right 8px
-
- </style>
- <script>
- this.age = require('s-age');
-
- this.mixin('i');
-
- this.user = this.opts.user;
-
- this.showFollowing = () => {
- riot.mount(document.body.appendChild(document.createElement('mk-user-following-window')), {
- user: this.user
- });
- };
-
- this.showFollowers = () => {
- riot.mount(document.body.appendChild(document.createElement('mk-user-followers-window')), {
- user: this.user
- });
- };
- </script>
-</mk-user-profile>
diff --git a/src/web/app/desktop/tags/user-timeline.tag b/src/web/app/desktop/tags/user-timeline.tag
index 08ab47b160..5df13c436c 100644
--- a/src/web/app/desktop/tags/user-timeline.tag
+++ b/src/web/app/desktop/tags/user-timeline.tag
@@ -91,6 +91,7 @@
this.fetch = cb => {
this.api('users/posts', {
user_id: this.user.id,
+ max_date: this.date ? this.date.getTime() : undefined,
with_replies: this.mode == 'with-replies'
}).then(posts => {
this.update({
@@ -132,5 +133,13 @@
});
this.fetch();
};
+
+ this.warp = date => {
+ this.update({
+ date: date
+ });
+
+ this.fetch();
+ };
</script>
</mk-user-timeline>
diff --git a/src/web/app/desktop/tags/user.tag b/src/web/app/desktop/tags/user.tag
index 2e69872b78..c9bb53fedd 100644
--- a/src/web/app/desktop/tags/user.tag
+++ b/src/web/app/desktop/tags/user.tag
@@ -3,10 +3,8 @@
<header>
<mk-user-header user={ user }/>
</header>
- <div class="body">
- <mk-user-home if={ page == 'home' } user={ user }/>
- <mk-user-graphs if={ page == 'graphs' } user={ user }/>
- </div>
+ <mk-user-home if={ page == 'home' } user={ user }/>
+ <mk-user-graphs if={ page == 'graphs' } user={ user }/>
</div>
<style>
:scope
@@ -14,7 +12,7 @@
> .user
> header
- max-width 560px + 270px
+ max-width 1200px
margin 0 auto
padding 0 16px
@@ -24,11 +22,6 @@
border-radius 0 0 6px 6px
overflow hidden
- > .body
- max-width 560px + 270px
- margin 0 auto
- padding 0 16px
-
</style>
<script>
this.mixin('api');
@@ -51,3 +44,447 @@
});
</script>
</mk-user>
+
+<mk-user-header data-is-dark-background={ user.banner_url != null }>
+ <div class="banner" ref="banner" style={ user.banner_url ? 'background-image: url(' + user.banner_url + '?thumbnail&size=1024)' : '' } onclick={ onUpdateBanner }></div>
+ <img class="avatar" src={ user.avatar_url + '?thumbnail&size=150' } alt="avatar"/>
+ <div class="title">
+ <p class="name" href={ '/' + user.username }>{ user.name }</p>
+ <p class="username">@{ user.username }</p>
+ <p class="location" if={ user.profile.location }><i class="fa fa-map-marker"></i>{ user.profile.location }</p>
+ </div>
+ <footer>
+ <a href={ '/' + user.username }>投稿</a>
+ <a href={ '/' + user.username + '/media' }>メディア</a>
+ <a href={ '/' + user.username + '/graphs' }>グラフ</a>
+ </footer>
+ <style>
+ :scope
+ $footer-height = 58px
+
+ display block
+ background #fff
+
+ &[data-is-dark-background]
+ > .banner
+ background-color #383838
+
+ > .title
+ color #fff
+ background linear-gradient(transparent, rgba(0, 0, 0, 0.7))
+
+ > .name
+ text-shadow 0 0 8px #000
+
+ > .banner
+ height 280px
+ background-color #f5f5f5
+ background-size cover
+ background-position center
+
+ > .avatar
+ display block
+ position absolute
+ bottom 16px
+ left 16px
+ z-index 2
+ width 150px
+ height 150px
+ margin 0
+ border solid 3px #fff
+ border-radius 8px
+ box-shadow 1px 1px 3px rgba(0, 0, 0, 0.2)
+
+ > .title
+ position absolute
+ bottom $footer-height
+ left 0
+ width 100%
+ padding 0 0 8px 195px
+ color #656565
+ font-family '游ゴシック', 'YuGothic', 'ヒラギノ角ゴ ProN W3', 'Hiragino Kaku Gothic ProN', 'Meiryo', 'メイリオ', sans-serif
+
+ > .name
+ display block
+ margin 0
+ line-height 40px
+ font-weight bold
+ font-size 2em
+
+ > .username
+ > .location
+ display inline-block
+ margin 0 16px 0 0
+ line-height 20px
+ opacity 0.8
+
+ > i
+ margin-right 4px
+
+ > footer
+ z-index 1
+ height $footer-height
+ padding-left 195px
+ background #fff
+
+ > a
+ display inline-block
+ margin 0
+ width 100px
+ line-height $footer-height
+ color #555
+
+ > button
+ display block
+ position absolute
+ top 0
+ right 0
+ margin 8px
+ padding 0
+ width $footer-height - 16px
+ line-height $footer-height - 16px - 2px
+ font-size 1.2em
+ color #777
+ border solid 1px #eee
+ border-radius 4px
+
+ &:hover
+ color #555
+ border solid 1px #ddd
+
+ </style>
+ <script>
+ import updateBanner from '../scripts/update-banner';
+
+ this.mixin('i');
+
+ this.user = this.opts.user;
+
+ this.on('mount', () => {
+ window.addEventListener('load', this.scroll);
+ window.addEventListener('scroll', this.scroll);
+ window.addEventListener('resize', this.scroll);
+ });
+
+ this.on('unmount', () => {
+ window.removeEventListener('load', this.scroll);
+ window.removeEventListener('scroll', this.scroll);
+ window.removeEventListener('resize', this.scroll);
+ });
+
+ this.scroll = () => {
+ const top = window.scrollY;
+ const height = 280/*px*/;
+
+ const pos = 50 - ((top / height) * 50);
+ this.refs.banner.style.backgroundPosition = `center ${pos}%`;
+
+ const blur = top / 32
+ if (blur <= 10) this.refs.banner.style.filter = `blur(${blur}px)`;
+ };
+
+ this.onUpdateBanner = () => {
+ if (!this.SIGNIN || this.I.id != this.user.id) return;
+
+ updateBanner(this.I, i => {
+ this.user.banner_url = i.banner_url;
+ this.update();
+ });
+ };
+ </script>
+</mk-user-header>
+
+<mk-user-profile>
+ <div class="friend-form" if={ SIGNIN && I.id != user.id }>
+ <mk-big-follow-button user={ user }/>
+ <p class="followed" if={ user.is_followed }>フォローされています</p>
+ </div>
+ <div class="description" if={ user.description }>{ user.description }</div>
+ <div class="birthday" if={ user.profile.birthday }>
+ <p><i class="fa fa-birthday-cake"></i>{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' } ({ age(user.profile.birthday) }歳)</p>
+ </div>
+ <div class="twitter" if={ user.twitter }>
+ <p><i class="fa fa-twitter"></i><a href={ 'https://twitter.com/' + user.twitter.screen_name } target="_blank">@{ user.twitter.screen_name }</a></p>
+ </div>
+ <div class="status">
+ <p class="posts-count"><i class="fa fa-angle-right"></i><a>{ user.posts_count }</a><b>ポスト</b></p>
+ <p class="following"><i class="fa fa-angle-right"></i><a onclick={ showFollowing }>{ user.following_count }</a>人を<b>フォロー</b></p>
+ <p class="followers"><i class="fa fa-angle-right"></i><a onclick={ showFollowers }>{ user.followers_count }</a>人の<b>フォロワー</b></p>
+ </div>
+ <style>
+ :scope
+ display block
+ background #fff
+
+ > *:first-child
+ border-top none !important
+
+ > .friend-form
+ padding 16px
+ border-top solid 1px #eee
+
+ > mk-big-follow-button
+ width 100%
+
+ > .followed
+ margin 12px 0 0 0
+ padding 0
+ text-align center
+ line-height 24px
+ font-size 0.8em
+ color #71afc7
+ background #eefaff
+ border-radius 4px
+
+ > .description
+ padding 16px
+ color #555
+ border-top solid 1px #eee
+
+ > .birthday
+ padding 16px
+ color #555
+ border-top solid 1px #eee
+
+ > p
+ margin 0
+
+ > i
+ margin-right 8px
+
+ > .twitter
+ padding 16px
+ color #555
+ border-top solid 1px #eee
+
+ > p
+ margin 0
+
+ > i
+ margin-right 8px
+
+ > .status
+ padding 16px
+ color #555
+ border-top solid 1px #eee
+
+ > p
+ margin 8px 0
+
+ > i
+ margin-left 8px
+ margin-right 8px
+
+ </style>
+ <script>
+ this.age = require('s-age');
+
+ this.mixin('i');
+
+ this.user = this.opts.user;
+
+ this.showFollowing = () => {
+ riot.mount(document.body.appendChild(document.createElement('mk-user-following-window')), {
+ user: this.user
+ });
+ };
+
+ this.showFollowers = () => {
+ riot.mount(document.body.appendChild(document.createElement('mk-user-followers-window')), {
+ user: this.user
+ });
+ };
+ </script>
+</mk-user-profile>
+
+<mk-user-photos>
+ <p class="title"><i class="fa fa-camera"></i>フォト</p>
+ <p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます<mk-ellipsis/></p>
+ <div class="stream" if={ !initializing && images.length > 0 }>
+ <virtual each={ image in images }>
+ <div class="img" style={ 'background-image: url(' + image.url + '?thumbnail&size=256)' }></div>
+ </virtual>
+ </div>
+ <p class="empty" if={ !initializing && images.length == 0 }>写真はありません</p>
+ <style>
+ :scope
+ display block
+ background #fff
+
+ > .title
+ z-index 1
+ margin 0
+ padding 0 16px
+ 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
+
+ > .stream
+ display -webkit-flex
+ display -moz-flex
+ display -ms-flex
+ display flex
+ justify-content center
+ flex-wrap wrap
+ padding 8px
+
+ > .img
+ flex 1 1 33%
+ width 33%
+ height 80px
+ background-position center center
+ background-size cover
+ background-clip content-box
+ border solid 2px transparent
+
+ > .initializing
+ > .empty
+ margin 0
+ padding 16px
+ text-align center
+ color #aaa
+
+ > i
+ margin-right 4px
+
+ </style>
+ <script>
+ import isPromise from '../../common/scripts/is-promise';
+
+ this.mixin('api');
+
+ this.images = [];
+ this.initializing = true;
+ this.user = null;
+ this.userPromise = isPromise(this.opts.user)
+ ? this.opts.user
+ : Promise.resolve(this.opts.user);
+
+ this.on('mount', () => {
+ this.userPromise.then(user => {
+ this.update({
+ user: user
+ });
+
+ this.api('users/posts', {
+ user_id: this.user.id,
+ with_media: true,
+ limit: 9
+ }).then(posts => {
+ this.initializing = false;
+ posts.forEach(post => {
+ post.media.forEach(media => {
+ if (this.images.length < 9) this.images.push(media);
+ });
+ });
+ this.update();
+ });
+ });
+ });
+ </script>
+</mk-user-photos>
+
+<mk-user-home>
+ <div>
+ <mk-user-profile user={ user }/>
+ <mk-user-photos user={ user }/>
+ </div>
+ <main>
+ <mk-user-timeline ref="tl" user={ user }/>
+ </main>
+ <div>
+ <mk-calendar warp={ warp } start={ new Date(user.created_at) }/>
+ </div>
+ <style>
+ :scope
+ display flex
+ justify-content center
+ margin 0 auto
+ max-width 1200px
+
+ > *
+ > *
+ display block
+ //border solid 1px #eaeaea
+ border solid 1px rgba(0, 0, 0, 0.075)
+ border-radius 6px
+
+ &:not(:last-child)
+ margin-bottom 16px
+
+ > main
+ padding 16px
+ width calc(100% - 275px * 2)
+
+ > div
+ width 275px
+ margin 0
+
+ &:first-child
+ padding 16px 0 16px 16px
+
+ &:last-child
+ padding 16px 16px 16px 0
+
+ </style>
+ <script>
+ this.user = this.opts.user;
+
+ this.on('mount', () => {
+ this.refs.tl.on('loaded', () => {
+ this.trigger('loaded');
+ });
+ });
+
+ this.warp = date => {
+ this.refs.tl.warp(date);
+ };
+ </script>
+</mk-user-home>
+
+<mk-user-graphs>
+ <section>
+ <h1>投稿</h1>
+ <mk-user-posts-graph user={ opts.user }/>
+ </section>
+ <section>
+ <h1>フォロー/フォロワー</h1>
+ <mk-user-friends-graph user={ opts.user }/>
+ </section>
+ <section>
+ <h1>いいね</h1>
+ <mk-user-likes-graph user={ opts.user }/>
+ </section>
+ <style>
+ :scope
+ display block
+
+ > section
+ margin 16px 0
+ background #fff
+ border solid 1px rgba(0, 0, 0, 0.1)
+ border-radius 4px
+
+ > h1
+ margin 0 0 8px 0
+ padding 0 16px
+ line-height 40px
+ font-size 1em
+ color #666
+ border-bottom solid 1px #eee
+
+ > *:not(h1)
+ margin 0 auto 16px auto
+
+ </style>
+ <script>
+ this.on('mount', () => {
+ this.trigger('loaded');
+ });
+ </script>
+</mk-user-graphs>