This commit is contained in:
syuilo 2017-02-21 20:34:54 +09:00
parent 8647c1d71c
commit 2de118a45d
15 changed files with 243 additions and 303 deletions

View File

@ -55,21 +55,23 @@
this.fetching = true;
this.on('mount', () => {
this.api 'i/signin_history'
}).then((history) => {
this.history = history
this.fetching = false
this.update();
.catch (err) =>
console.error err
this.api('i/signin_history').then(history => {
this.update({
fetching: false,
history: history
});
});
this.stream.on 'signin' this.on-signin
this.stream.on('signin', this.onSignin);
});
this.on('unmount', () => {
this.stream.off 'signin' this.on-signin
this.stream.off('signin', this.onSignin);
});
this.on-signin = (signin) => {
@history.unshift signin
this.onSignin = signin => {
this.history.unshift(signin);
this.update();
};
</script>
</mk-signin-history>

View File

@ -1,6 +1,6 @@
<mk-following-setuper>
<p class="title">気になるユーザーをフォロー:</p>
<div class="users" if={ !loading && users.length > 0 }>
<div class="users" if={ !fetching && users.length > 0 }>
<div class="user" each={ users }><a class="avatar-anchor" href={ CONFIG.url + '/' + username }><img class="avatar" src={ avatar_url + '?thumbnail&size=42' } alt="" data-user-preview={ id }/></a>
<div class="body"><a class="name" href={ CONFIG.url + '/' + username } target="_blank" data-user-preview={ id }>{ name }</a>
<p class="username">@{ username }</p>
@ -8,8 +8,8 @@
<mk-follow-button user={ this }></mk-follow-button>
</div>
</div>
<p class="empty" if={ !loading && users.length == 0 }>おすすめのユーザーは見つかりませんでした。</p>
<p class="loading" if={ loading }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます
<p class="empty" if={ !fetching && users.length == 0 }>おすすめのユーザーは見つかりませんでした。</p>
<p class="fetching" if={ fetching }><i class="fa fa-spinner fa-pulse fa-fw"></i>読み込んでいます
<mk-ellipsis></mk-ellipsis>
</p><a class="refresh" onclick={ refresh }>もっと見る</a>
<button class="close" onclick={ close } title="閉じる"><i class="fa fa-times"></i></button>
@ -81,7 +81,7 @@
text-align center
color #aaa
> .loading
> .fetching
margin 0
padding 16px
text-align center
@ -126,38 +126,46 @@
this.mixin('api');
this.mixin('user-preview');
this.users = null
this.loading = true
this.users = null;
this.fetching = true;
this.limit = 6users
this.page = 0
this.limit = 6;
this.page = 0;
this.on('mount', () => {
this.load();
this.fetch();
});
this.load = () => {
this.loading = true
this.users = null
this.update();
this.fetch = () => {
this.update({
fetching: true,
users: null
});
this.api('users/recommendation', {
limit: @limit
offset: @limit * this.page
}).then((users) => {
this.loading = false
limit: this.limit,
offset: this.limit * this.page
}).then(users => {
this.fetching = false
this.users = users
this.update();
.catch (err, text-status) ->
console.error err
this.update({
fetching: false,
users: users
});
});
};
this.refresh = () => {
if this.users.length < @limit
this.page = 0
else
this.page++
this.load();
if (this.users.length < this.limit) {
this.page = 0;
} else {
this.page++;
}
this.fetch();
};
this.close = () => {
this.unmount();
};
</script>
</mk-following-setuper>

View File

@ -35,41 +35,26 @@
</style>
<script>
this.image = this.opts.image
this.image = this.opts.image;
this.on('mount', () => {
Velocity(this.root, {
opacity: 1
}, {
duration: 100ms
easing: 'linear'
}
#Velocity(@img, {
// scale: 1
// opacity: 1
#}, {
// duration: 200ms
// easing: 'ease-out'
#}
duration: 100,
easing: 'linear'
});
});
this.close = () => {
Velocity(this.root, {
opacity: 0
}, {
duration: 100ms
easing: 'linear'
complete: => this.unmount();
}
duration: 100,
easing: 'linear',
complete: () => this.unmount()
});
};
#Velocity(@img, {
// scale: 0.9
// opacity: 0
#}, {
// duration: 200ms
// easing: 'ease-in'
// complete: =>
// this.unmount();
#}
</script>
</mk-image-dialog>

View File

@ -26,20 +26,22 @@
</style>
<script>
this.images = this.opts.images
this.image = @images.0
this.images = this.opts.images;
this.image = this.images[0];
this.mousemove = (e) => {
rect = this.refs.view.getBoundingClientRect();
mouse-x = e.client-x - rect.left
mouse-y = e.client-y - rect.top
xp = mouse-x / this.refs.view.offset-width * 100
yp = mouse-y / this.refs.view.offset-height * 100
this.refs.view.style.background-position = xp + '% ' + yp + '%'
this.mousemove = e => {
const rect = this.refs.view.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const xp = mouseX / this.refs.view.offsetWidth * 100;
const yp = mouseY / this.refs.view.offsetHeight * 100;
this.refs.view.style.backgroundPosition = xp + '% ' + yp + '%';
};
this.click = () => {
dialog = document.body.appendChild(document.createElement('mk-image-dialog'));
riot.mount dialog, do
image: @image
riot.mount(document.body.appendChild(document.createElement('mk-image-dialog')), {
image: this.image
});
};
</script>
</mk-images-viewer>

View File

@ -182,32 +182,36 @@
this.mixin('user-preview');
this.mixin('get-post-summary');
this.notifications = []
this.loading = true
this.notifications = [];
this.loading = true;
this.on('mount', () => {
this.api 'i/notifications'
}).then((notifications) => {
this.notifications = notifications
this.loading = false
this.update();
.catch (err, text-status) ->
console.error err
this.api('i/notifications').then(notifications => {
this.update({
loading: false,
notifications: notifications
});
});
this.stream.on 'notification' this.on-notification
this.stream.on('notification', this.onNotification);
});
this.on('unmount', () => {
this.stream.off 'notification' this.on-notification
this.stream.off('notification', this.onNotification);
});
this.on-notification = (notification) => {
@notifications.unshift notification
this.onNotification = notification => {
this.notifications.unshift(notification);
this.update();
};
this.on('update', () => {
@notifications.forEach (notification) =>
date = (new Date notification.created_at).getDate()
month = (new Date notification.created_at).getMonth() + 1
notification._date = date
notification._datetext = month + '月 ' + date + '日'
this.notifications.forEach(notification => {
const date = new Date(notification.created_at).getDate();
const month = new Date(notification.created_at).getMonth() + 1;
notification._date = date;
notification._datetext = `${month}月 ${date}日`;
});
});
</script>
</mk-notifications>

View File

@ -108,33 +108,40 @@
this.mixin('date-stringify');
this.mixin('user-preview');
this.post = this.opts.post
this.post = this.opts.post;
this.url = CONFIG.url + '/' + this.post.user.username + '/' + this.post.id
this.url = CONFIG.url + '/' + this.post.user.username + '/' + this.post.id;
this.title = @date-stringify this.post.created_at
this.title = this.dateStringify(this.post.created_at);
this.on('mount', () => {
if this.post.text?
tokens = @analyze this.post.text
this.refs.text.innerHTML = @compile tokens
if (this.p.text) {
const tokens = this.analyze(this.p.text);
this.refs.text.children.forEach (e) =>
if e.tag-name == 'MK-URL'
riot.mount e
this.refs.text.innerHTML = this.refs.text.innerHTML.replace('<p class="dummy"></p>', this.compile(tokens));
this.refs.text.children.forEach(e => {
if (e.tagName == 'MK-URL') riot.mount(e);
});
}
});
this.like = () => {
if this.post.is_liked
if (this.post.is_liked) {
this.api('posts/likes/delete', {
post_id: this.post.id
}).then(() => {
this.post.is_liked = false
this.post.is_liked = false;
this.update();
else
});
} else {
this.api('posts/likes/create', {
post_id: this.post.id
}).then(() => {
this.post.is_liked = true
this.post.is_liked = true;
this.update();
});
}
};
</script>
</mk-post-detail-sub>

View File

@ -335,102 +335,120 @@
this.mixin('date-stringify');
this.mixin('NotImplementedException');
this.fetching = true
this.loading-context = false
this.content = null
this.post = null
this.fetching = true;
this.loadingContext = false;
this.content = null;
this.post = null;
this.on('mount', () => {
this.api('posts/show', {
post_id: this.opts.post
}).then((post) => {
this.fetching = false
this.post = post
}).then(post => {
const isRepost = post.repost != null;
const p = isRepost ? post.repost : post;
this.update({
fetching: false,
post: post,
isRepost: isRepost,
p: p,
title: this.dateStringify(p.created_at)
});
this.trigger('loaded');
this.is-repost = this.post.repost?
this.p = if @is-repost then this.post.repost else this.post
if (this.p.text) {
const tokens = this.analyze(this.p.text);
this.title = @date-stringify this.p.created_at
this.refs.text.innerHTML = this.compile(tokens);
this.update();
if this.p.text?
tokens = @analyze this.p.text
this.refs.text.innerHTML = @compile tokens
this.refs.text.children.forEach (e) =>
if e.tag-name == 'MK-URL'
riot.mount e
this.refs.text.children.forEach(e => {
if (e.tagName == 'MK-URL') riot.mount(e);
});
// URLをプレビュー
tokens
.filter (t) -> t.type == 'link'
.map (t) =>
this.preview = this.refs.text.appendChild(document.createElement('mk-url-preview'));
riot.mount this.preview, do
url: t.content
.filter(t => t.type == 'link')
.map(t => {
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
url: t.content
});
});
}
// Get likes
this.api('posts/likes', {
post_id: this.p.id
post_id: this.p.id,
limit: 8
}).then((likes) => {
this.likes = likes
this.update();
}).then(likes => {
this.update({
likes: likes
});
});
// Get reposts
this.api('posts/reposts', {
post_id: this.p.id
post_id: this.p.id,
limit: 8
}).then((reposts) => {
this.reposts = reposts
this.update();
}).then(reposts => {
this.update({
reposts: reposts
});
});
// Get replies
this.api('posts/replies', {
post_id: this.p.id
post_id: this.p.id,
limit: 8
}).then((replies) => {
this.replies = replies
this.update();
this.update();
}).then(replies => {
this.update({
replies: replies
});
});
});
});
this.reply = () => {
form = document.body.appendChild(document.createElement('mk-post-form-window'));
riot.mount form, do
riot.mount(document.body.appendChild(document.createElement('mk-post-form-window')), {
reply: this.p
});
};
this.repost = () => {
form = document.body.appendChild(document.createElement('mk-repost-form-window'));
riot.mount form, do
riot.mount(document.body.appendChild(document.createElement('mk-repost-form-window')), {
post: this.p
});
};
this.like = () => {
if this.p.is_liked
if (this.p.is_liked) {
this.api('posts/likes/delete', {
post_id: this.p.id
}).then(() => {
this.p.is_liked = false
this.p.is_liked = false;
this.update();
else
});
} else {
this.api('posts/likes/create', {
post_id: this.p.id
}).then(() => {
this.p.is_liked = true
this.p.is_liked = true;
this.update();
});
}
};
this.load-context = () => {
this.loading-context = true
this.loadContext = () => {
this.loadingContext = true;
// Get context
// Fetch context
this.api('posts/context', {
post_id: this.p.reply_to_id
}).then((context) => {
this.context = context.reverse!
this.loading-context = false
this.update();
}).then(context => {
this.update({
loadContext: false,
content: context.reverse()
});
});
};
</script>
</mk-post-detail>

View File

@ -32,24 +32,31 @@
</style>
<script>
this.uploading-files = []
this.files = []
this.uploadingFiles = [];
this.files = [];
this.on('mount', () => {
this.refs.window.refs.form.focus();
this.refs.window.on('closed', () => {
this.unmount();
});
this.refs.window.refs.form.on('post', () => {
this.refs.window.close();
});
this.refs.window.refs.form.on('change-uploading-files', (files) => {
this.uploading-files = files
this.update();
this.refs.window.refs.form.on('change-uploading-files', files => {
this.update({
uploadingFiles: files
});
});
this.refs.window.refs.form.on('change-files', (files) => {
this.files = files
this.update();
this.refs.window.refs.form.on('change-files', files => {
this.update({
files: files
});
});
});
</script>
</mk-post-form-window>

View File

@ -86,8 +86,8 @@
this.mixin('date-stringify');
this.mixin('user-preview');
this.post = this.opts.post
this.post = this.opts.post;
this.title = @date-stringify this.post.created_at
this.title = this.dateStringify(this.post.created_at);
</script>
</mk-post-preview>

View File

@ -75,20 +75,25 @@
</style>
<script>
this.title = this.opts.title
this.value = parse-int this.opts.value, 10
this.max = parse-int this.opts.max, 10
this.title = this.opts.title;
this.value = parseInt(this.opts.value, 10);
this.max = parseInt(this.opts.max, 10);
this.on('mount', () => {
this.refs.window.on('closed', () => {
this.unmount();
});
});
this.update-progress = (value, max) => {
this.value = parse-int value, 10
this.max = parse-int max, 10
this.update();
this.updateProgress = (value, max) => {
this.update({
value: parseInt(value, 10),
max: parseInt(max, 10)
});
};
this.close = () => {
this.refs.window.close();
};
</script>
</mk-progress-dialog>

View File

@ -12,25 +12,32 @@
</style>
<script>
this.on-document-keydown = (e) => {
tag = e.target.tag-name.to-lower-case!
if tag != 'input' and tag != 'textarea'
if e.which == 27 // Esc
this.onDocumentKeydown = e => {
if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
if (e.which == 27) { // Esc
this.refs.window.close();
}
}
};
this.on('mount', () => {
this.refs.window.refs.form.on('cancel', () => {
this.refs.window.close();
});
this.refs.window.refs.form.on('posted', () => {
this.refs.window.close();
});
document.addEventListener 'keydown' this.on-document-keydown
document.addEventListener('keydown', this.onDocumentKeydown);
this.refs.window.on('closed', () => {
this.unmount();
});
});
this.on('unmount', () => {
document.removeEventListener 'keydown' this.on-document-keydown
document.removeEventListener('keydown', this.onDocumentKeydown);
});
</script>
</mk-repost-form-window>

View File

@ -117,28 +117,31 @@
this.mixin('api');
this.mixin('notify');
this.wait = false
this.quote = false
this.wait = false;
this.quote = false;
this.cancel = () => {
this.trigger('cancel');
};
this.ok = () => {
this.wait = true
this.wait = true;
this.api('posts/create', {
repost_id: this.opts.post.id
text: if this.quote then this.refs.text.value else undefined
}).then((data) => {
repost_id: this.opts.post.id,
text: this.quote ? this.refs.text.value : undefined
}).then(data => {
this.trigger('posted');
@notify 'Repostしました'
.catch (err) =>
console.error err
@notify 'Repostできませんでした'
this.notify('Repostしました');
}).catch(err => {
this.notify('Repostできませんでした');
}).then(() => {
this.wait = false
this.update();
this.update({
wait: false
});
});
this.onquote = () => {
this.quote = true
this.quote = true;
};
</script>
</mk-repost-form>

View File

@ -31,6 +31,7 @@
if (e.which == 80 || e.which == 78) { // p or n
e.preventDefault();
this.openPostForm();
}
};
</script>
</mk-ui>

View File

@ -1,67 +0,0 @@
<mk-user-friends-graph>
<canvas ref="canv" width="750" height="250"></canvas>
<style>
:scope
display block
width 750px
height 250px
</style>
<script>
this.mixin('api');
this.mixin('is-promise');
this.user = null
this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
this.on('mount', () => {
user <~ this.user-promise.then
this.user = user
this.update();
this.api('aggregation/users/followers', {
user_id: this.user.id
limit: 30days
}).then((followers) => {
followers = followers.reverse!
this.api('aggregation/users/following', {
user_id: this.user.id
limit: 30days
}).then((following) => {
following = following.reverse!
new Chart this.refs.canv, do
type: 'line'
data:
labels: following.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
datasets: [
{
label: 'フォロー'
data: following.map (x) => x.count
line-tension: 0
border-width: 2
fill: true
background-color: 'rgba(127, 221, 64, 0.2)'
point-background-color: '#fff'
point-radius: 4
point-border-width: 2
border-color: '#7fdd40'
},
{
label: 'フォロワー'
data: followers.map (x) => x.count
line-tension: 0
border-width: 2
fill: true
background-color: 'rgba(255, 99, 132, 0.2)'
point-background-color: '#fff'
point-radius: 4
point-border-width: 2
border-color: '#FF6384'
}
]
options:
responsive: false
</script>
</mk-user-friends-graph>

View File

@ -1,42 +0,0 @@
<mk-user-likes-graph>
<canvas ref="canv" width="750" height="250"></canvas>
<style>
:scope
display block
width 750px
height 250px
</style>
<script>
this.mixin('api');
this.mixin('is-promise');
this.user = null
this.user-promise = if @is-promise this.opts.user then this.opts.user else Promise.resolve this.opts.user
this.on('mount', () => {
user <~ this.user-promise.then
this.user = user
this.update();
this.api('aggregation/users/like', {
user_id: this.user.id
limit: 30days
}).then((likes) => {
likes = likes.reverse!
new Chart this.refs.canv, do
type: 'bar'
data:
labels: likes.map (x, i) => if i % 3 == 2 then x.date.day + '日' else ''
datasets: [
{
label: 'いいねした数'
data: likes.map (x) => x.count
background-color: '#F7796C'
}
]
options:
responsive: false
</script>
</mk-user-likes-graph>