This commit is contained in:
syuilo 2017-02-20 20:13:42 +09:00
parent 3a39a36bed
commit 2a3a5d4b50
35 changed files with 402 additions and 367 deletions

View File

@ -114,13 +114,13 @@
this.cancel = () => {
this.api('auth/deny', {
token: @session.token
.then =>
}).then(() => {
this.trigger('denied');
this.accept = () => {
this.api('auth/accept', {
token: @session.token
.then =>
}).then(() => {
this.trigger('accepted');
</script>
</mk-form>

View File

@ -110,7 +110,7 @@
if @session.app.is_authorized
this.api('auth/accept', {
token: @session.token
.then =>
}).then(() => {
@accepted!
else
this.state = 'waiting'

View File

@ -0,0 +1,8 @@
module.exports = function(parent, child) {
let node = child.parentNode;
while (node) {
if (node == parent) return true;
node = node.parentNode;
}
return false;
}

View File

@ -126,7 +126,7 @@
this.api('signin', {
username: this.refs.username.value
password: this.refs.password.value
.then =>
}).then(() => {
location.reload();
.catch =>
alert 'something happened'

View File

@ -277,11 +277,11 @@
username: username,
password: password,
'g-recaptcha-response': grecaptcha.getResponse()
.then =>
}).then(() => {
this.api('signin', {
username: username
password: password
.then =>
}).then(() => {
location.href = CONFIG.url
.catch =>
alert '何らかの原因によりアカウントの作成に失敗しました。再度お試しください。'

View File

@ -6,100 +6,92 @@
display block
width 256px
height 256px
</style>
<script>
class Vec2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
this.on('mount', () => {
@draw!
this.clock = setInterval @draw, 1000ms
this.draw()
this.clock = setInterval(this.draw, 1000);
});
this.on('unmount', () => {
clearInterval @clock
clearInterval(this.clock);
});
this.draw = () => {
const now = new Date();
s = now.get-seconds!
m = now.getMinutes()
h = now.getHours()
const s = now.getSeconds();
const m = now.getMinutes();
const h = now.getHours();
vec2 = (x, y) ->
this.x = x
this.y = y
const ctx = this.refs.canvas.getContext('2d');
const canvW = this.refs.canvas.width;
const canvH = this.refs.canvas.height;
ctx.clearRect(0, 0, canvW, canvH);
ctx = this.refs.canvas.get-context '2d'
canv-w = this.refs.canvas.width
canv-h = this.refs.canvas.height
ctx.clear-rect 0, 0, canv-w, canv-h
{ // 背景
const center = Math.min((canvW / 2), (canvH / 2));
const lineStart = center * 0.90;
const shortLineEnd = center * 0.87;
const longLineEnd = center * 0.84;
for (let i = 0; i < 60; i++) {
const angle = Math.PI * i / 30;
const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
ctx.beginPath();
ctx.lineWidth = 1;
ctx.moveTo((canv-w / 2) + uv.x * lineStart, (canv-h / 2) + uv.y * lineStart);
if (i % 5 == 0) {
ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
ctx.lineTo((canv-w / 2) + uv.x * longLineEnd, (canv-h / 2) + uv.y * longLineEnd);
} else {
ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
ctx.lineTo((canv-w / 2) + uv.x * shortLineEnd, (canv-h / 2) + uv.y * shortLineEnd);
}
ctx.stroke();
}
}
// 背景
center = (Math.min (canv-w / 2), (canv-h / 2))
line-start = center * 0.90
line-end-short = center * 0.87
line-end-long = center * 0.84
for i from 0 to 59 by 1
angle = Math.PI * i / 30
uv = new vec2 (Math.sin angle), (-Math.cos angle)
ctx.begin-path!
ctx.line-width = 1
ctx.move-to do
(canv-w / 2) + uv.x * line-start
(canv-h / 2) + uv.y * line-start
if i % 5 == 0
ctx.stroke-style = 'rgba(255, 255, 255, 0.2)'
ctx.line-to do
(canv-w / 2) + uv.x * line-end-long
(canv-h / 2) + uv.y * line-end-long
else
ctx.stroke-style = 'rgba(255, 255, 255, 0.1)'
ctx.line-to do
(canv-w / 2) + uv.x * line-end-short
(canv-h / 2) + uv.y * line-end-short
ctx.stroke!
{ // 分
const angle = Math.PI * (m + s / 60) / 30;
const length = Math.min(canvW, canvH) / 2.6;
const uv = new vec2(Math.sin(angle), -Math.cos(angle));
ctx.beginPath();
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
ctx.stroke();
}
// 分
angle = Math.PI * (m + s / 60) / 30
length = (Math.min canv-w, canv-h) / 2.6
uv = new vec2 (Math.sin angle), (-Math.cos angle)
ctx.begin-path!
ctx.stroke-style = '#ffffff'
ctx.line-width = 2
ctx.move-to do
(canv-w / 2) - uv.x * length / 5
(canv-h / 2) - uv.y * length / 5
ctx.line-to do
(canv-w / 2) + uv.x * length
(canv-h / 2) + uv.y * length
ctx.stroke!
{ // 時
const angle = Math.PI * (h % 12 + m / 60) / 6;
const length = Math.min(canvW, canvH) / 4;
const uv = new vec2(Math.sin(angle), -Math.cos(angle));
ctx.beginPath();
ctx.strokeStyle = CONFIG.themeColor;
ctx.lineWidth = 2;
ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
ctx.stroke();
}
// 時
angle = Math.PI * (h % 12 + m / 60) / 6
length = (Math.min canv-w, canv-h) / 4
uv = new vec2 (Math.sin angle), (-Math.cos angle)
ctx.begin-path!
#ctx.stroke-style = '#ffffff'
ctx.stroke-style = CONFIG.theme-color
ctx.line-width = 2
ctx.move-to do
(canv-w / 2) - uv.x * length / 5
(canv-h / 2) - uv.y * length / 5
ctx.line-to do
(canv-w / 2) + uv.x * length
(canv-h / 2) + uv.y * length
ctx.stroke!
// 秒
angle = Math.PI * s / 30
length = (Math.min canv-w, canv-h) / 2.6
uv = new vec2 (Math.sin angle), (-Math.cos angle)
ctx.begin-path!
ctx.stroke-style = 'rgba(255, 255, 255, 0.5)'
ctx.line-width = 1
ctx.move-to do
(canv-w / 2) - uv.x * length / 5
(canv-h / 2) - uv.y * length / 5
ctx.line-to do
(canv-w / 2) + uv.x * length
(canv-h / 2) + uv.y * length
ctx.stroke!
{ // 秒
const angle = Math.PI * s / 30;
const length = Math.min(canvW, canvH) / 2.6;
const uv = new vec2(Math.sin(angle), -Math.cos(angle));
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
ctx.lineWidth = 1;
ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
ctx.stroke();
}
};
</script>
</mk-analog-clock>

View File

@ -80,108 +80,118 @@
</style>
<script>
const contains = require('../../common/scripts/contains');
this.mixin('api');
this.q = this.opts.q
this.textarea = this.opts.textarea
this.loading = true
this.users = []
this.select = -1
this.q = this.opts.q;
this.textarea = this.opts.textarea;
this.fetching = true;
this.users = [];
this.select = -1;
this.on('mount', () => {
@textarea.addEventListener 'keydown' this.on-keydown
this.textarea.addEventListener('keydown', this.onKeydown);
all = document.query-selector-all 'body *'
Array.prototype.forEach.call all, (el) =>
el.addEventListener 'mousedown' @mousedown
document.querySelectorAll('body *').forEach(el => {
el.addEventListener('mousedown', this.mousedown);
});
this.api('users/search_by_username', {
query: @q
limit: 30users
}).then((users) => {
this.users = users
this.loading = false
this.update();
.catch (err) =>
console.error err
query: this.q,
limit: 30
}).then(users => {
this.update({
fetching: false,
users: users
});
});
});
this.on('unmount', () => {
@textarea.removeEventListener 'keydown' this.on-keydown
this.textarea.removeEventListener('keydown', this.onKeydown);
all = document.query-selector-all 'body *'
Array.prototype.forEach.call all, (el) =>
el.removeEventListener 'mousedown' @mousedown
document.querySelectorAll('body *').forEach(el => {
el.removeEventListener('mousedown', this.mousedown);
});
});
this.mousedown = (e) => {
if (!contains this.root, e.target) and (this.root != e.target)
@close();
this.mousedown = e => {
if (!contains(this.root, e.target) && (this.root != e.target)) this.close();
};
this.on-click = (e) => {
@complete e.item
this.onClick = e => {
this.complete(e.item);
};
this.on-keydown = (e) => {
key = e.which
switch (key)
| 10, 13 => // Key[ENTER]
if @select != -1
e.preventDefault();
e.stopPropagation();
@complete this.users[@select]
else
@close();
| 27 => // Key[ESC]
e.preventDefault();
e.stopPropagation();
@close();
| 38 => // Key[↑]
if @select != -1
e.preventDefault();
e.stopPropagation();
@select-prev!
else
@close();
| 9, 40 => // Key[TAB] or Key[↓]
e.preventDefault();
e.stopPropagation();
@select-next!
| _ =>
@close();
this.onKeydown = e => {
const cancel = () => {
e.preventDefault();
e.stopPropagation();
};
this.select-next = () => {
@select++
switch (e.which) {
case 10: // [ENTER]
case 13: // [ENTER]
if (this.select !== -1) {
cancel();
this.complete(this.users[this.select]);
} else {
this.close();
}
break;
if @select >= this.users.length
this.select = 0
case 27: // [ESC]
cancel();
this.close();
break;
@apply-select!
case 38: // [↑]
if (this.select !== -1) {
cancel();
this.selectPrev();
} else {
this.close();
}
break;
this.select-prev = () => {
@select--
case 9: // [TAB]
case 40: // [↓]
cancel();
this.selectNext();
break;
if @select < 0
this.select = this.users.length - 1
default:
this.close();
}
};
@apply-select!
this.selectNext = () => {
if (++this.select >= this.users.length) this.select = 0;
this.applySelect();
};
this.apply-select = () => {
this.refs.users.children.forEach (el) =>
el.remove-attribute 'data-selected'
this.selectPrev = () => {
if (--this.select < 0) this.select = this.users.length - 1;
this.applySelect();
};
this.refs.users.children[@select].setAttribute 'data-selected' \true
this.refs.users.children[@select].focus();
this.applySelect = () => {
this.refs.users.children.forEach(el => {
el.removeAttribute('data-selected');
});
this.complete = (user) => {
this.opts.complete user
this.refs.users.children[this.select].setAttribute('data-selected', 'true');
this.refs.users.children[this.select].focus();
};
this.complete = user => {
this.opts.complete(user);
};
this.close = () => {
this.opts.close();
};
function contains(parent, child)
node = child.parentNode
while node?
if node == parent
return true
node = node.parentNode
return false
</script>
</mk-autocomplete-suggestion>

View File

@ -106,21 +106,21 @@
if this.user.is_following
this.api('following/delete', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = false
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
else
this.api('following/create', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = true
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
</script>

View File

@ -1,4 +1,5 @@
<mk-contextmenu><yield />
<mk-contextmenu>
<yield />
<style>
:scope
$width = 240px
@ -94,46 +95,45 @@
</style>
<script>
this.root.addEventListener 'contextmenu' (e) =>
const contains = require('../../common/scripts/contains');
this.root.addEventListener('contextmenu', e => {
e.preventDefault();
});
this.mousedown = (e) => {
this.mousedown = e => {
e.preventDefault();
if (!contains this.root, e.target) and (this.root != e.target)
@close();
return false
if (!contains(this.root, e.target) && (this.root != e.target)) this.close();
return false;
};
this.open = (pos) => {
all = document.query-selector-all 'body *'
Array.prototype.forEach.call all, (el) =>
el.addEventListener 'mousedown' @mousedown
this.root.style.display = 'block'
this.root.style.left = pos.x + 'px'
this.root.style.top = pos.y + 'px'
this.open = pos => {
document.querySelectorAll('body *').forEach(el => {
el.addEventListener('mousedown', this.mousedown);
});
Velocity(this.root, 'finish' true
Velocity(this.root, { opacity: 0 } 0ms
this.root.style.display = 'block';
this.root.style.left = pos.x + 'px';
this.root.style.top = pos.y + 'px';
Velocity(this.root, 'finish', true);
Velocity(this.root, { opacity: 0 }, 0);
Velocity(this.root, {
opacity: 1
}, {
queue: false
duration: 100ms
easing: 'linear'
}
queue: false,
duration: 100,
easing: 'linear'
});
};
this.close = () => {
all = document.query-selector-all 'body *'
Array.prototype.forEach.call all, (el) =>
el.removeEventListener 'mousedown' @mousedown
document.querySelectorAll('body *').forEach(el => {
el.removeEventListener('mousedown', this.mousedown);
});
this.trigger('closed');
this.unmount();
function contains(parent, child)
node = child.parentNode
while (node != null)
if (node == parent)
return true
node = node.parentNode
return false
};
</script>
</mk-contextmenu>

View File

@ -79,69 +79,72 @@
</style>
<script>
this.can-through = if opts.can-through? then opts.can-through else true
this.opts.buttons.forEach (button) =>
button._onclick = =>
if button.onclick?
button.onclick();
@close();
this.canThrough = opts.canThrough != null ? opts.canThrough : true;
this.opts.buttons.forEach(button => {
button._onclick = () => {
if (button.onclick) button.onclick();
this.close();
};
});
this.on('mount', () => {
this.refs.header.innerHTML = this.opts.title
this.refs.body.innerHTML = this.opts.text
this.refs.header.innerHTML = this.opts.title;
this.refs.body.innerHTML = this.opts.text;
this.refs.bg.style.pointer-events = 'auto'
Velocity(this.refs.bg, 'finish' true
this.refs.bg.style.pointerEvents = 'auto';
Velocity(this.refs.bg, 'finish', true);
Velocity(this.refs.bg, {
opacity: 1
}, {
queue: false
duration: 100ms
easing: 'linear'
}
queue: false,
duration: 100,
easing: 'linear'
});
Velocity(this.refs.main, {
opacity: 0
opacity: 0,
scale: 1.2
}, {
duration: 0
}
});
Velocity(this.refs.main, {
opacity: 1
opacity: 1,
scale: 1
}, {
duration: 300ms
duration: 300,
easing: [ 0, 0.5, 0.5, 1 ]
}
});
});
this.close = () => {
this.refs.bg.style.pointer-events = 'none'
Velocity(this.refs.bg, 'finish' true
this.refs.bg.style.pointerEvents = 'none';
Velocity(this.refs.bg, 'finish', true);
Velocity(this.refs.bg, {
opacity: 0
}, {
queue: false
duration: 300ms
queue: false,
duration: 300,
easing: 'linear'
}
});
this.refs.main.style.pointer-events = 'none'
Velocity(this.refs.main, 'finish' true
this.refs.main.style.pointerEvents = 'none';
Velocity(this.refs.main, 'finish', true);
Velocity(this.refs.main, {
opacity: 0
opacity: 0,
scale: 0.8
}, {
queue: false
duration: 300ms
easing: [ 0.5, -0.5, 1, 0.5 ]
complete: =>
this.unmount();
}
queue: false,
duration: 300,
easing: [ 0.5, -0.5, 1, 0.5 ],
complete: () => this.unmount()
});
};
this.bg-click = () => {
if @can-through
if this.opts.on-through?
this.opts.on-through!
@close();
this.bgClick = () => {
if (this.canThrough) {
if (this.opts.onThrough) this.opts.onThrough();
this.close();
}
};
</script>
</mk-dialog>

View File

@ -408,7 +408,7 @@
this.api('drive/files/update', {
file_id: file
folder_id: if this.folder? then this.folder.id else null
.then =>
}).then(() => {
// something
.catch (err, text-status) =>
console.error err
@ -425,7 +425,7 @@
this.api('drive/folders/update', {
folder_id: folder
parent_id: if this.folder? then this.folder.id else null
.then =>
}).then(() => {
// something
.catch (err) =>
if err == 'detected-circular-definition'

View File

@ -68,7 +68,7 @@
this.api('drive/files/update', {
file_id: this.file.id
name: name
.then =>
}).then(() => {
// something
.catch (err) =>
console.error err

View File

@ -54,7 +54,7 @@
this.api('drive/folders/update', {
folder_id: this.folder.id
name: name
.then =>
}).then(() => {
// something
.catch (err) =>
console.error err

View File

@ -118,7 +118,7 @@
this.api('drive/files/update', {
file_id: file
folder_id: this.folder.id
.then =>
}).then(() => {
// something
.catch (err, text-status) =>
console.error err
@ -133,7 +133,7 @@
this.api('drive/folders/update', {
folder_id: folder
parent_id: this.folder.id
.then =>
}).then(() => {
// something
.catch (err) =>
if err == 'detected-circular-definition'

View File

@ -72,7 +72,7 @@
this.api('drive/files/update', {
file_id: file
folder_id: if this.folder? then this.folder.id else null
.then =>
}).then(() => {
// something
.catch (err, text-status) =>
console.error err
@ -87,7 +87,7 @@
this.api('drive/folders/update', {
folder_id: folder
parent_id: if this.folder? then this.folder.id else null
.then =>
}).then(() => {
// something
.catch (err, text-status) =>
console.error err

View File

@ -33,9 +33,5 @@
40%
transform scale(1)
</style>
</mk-ellipsis-icon>

View File

@ -103,21 +103,21 @@
if this.user.is_following
this.api('following/delete', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = false
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
else
this.api('following/create', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = true
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
</script>

View File

@ -1,14 +0,0 @@
<mk-go-top>
<button class="hidden" title="一番上へ"><i class="fa fa-angle-up"></i></button>
<script>
window.addEventListener 'load' this.on-scroll
window.addEventListener 'scroll' this.on-scroll
window.addEventListener 'resize' this.on-scroll
this.on-scroll = () => {
if $ window .scroll-top! > 500px
@remove-class 'hidden'
else
@add-class 'hidden'
</script>
</mk-go-top>

View File

@ -39,7 +39,7 @@
this.click = () => {
dialog = document.body.appendChild(document.createElement('mk-image-dialog'));
riot.mount dialog, do
riot.mount dialog, do
image: @image
</script>
</mk-images-viewer>

View File

@ -16,7 +16,6 @@ require('./crop-window.tag');
require('./settings.tag');
require('./settings-window.tag');
require('./analog-clock.tag');
require('./go-top.tag');
require('./ui-header.tag');
require('./ui-header-account.tag');
require('./ui-header-notifications.tag');

View File

@ -1,13 +1,17 @@
<mk-input-dialog>
<mk-window ref="window" is-modal={ true } width={ '500px' }><yield to="header"><i class="fa fa-i-cursor"></i>{ parent.title }</yield>
<yield to="content">
<div class="body">
<input ref="text" oninput={ parent.update } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/>
</div>
<div class="action">
<button class="cancel" onclick={ parent.cancel }>キャンセル</button>
<button class="ok" disabled={ !parent.allowEmpty && refs.text.value.length == 0 } onclick={ parent.ok }>決定</button>
</div></yield>
<mk-window ref="window" is-modal={ true } width={ '500px' }>
<yield to="header">
<i class="fa fa-i-cursor"></i>{ parent.title }
</yield>
<yield to="content">
<div class="body">
<input ref="text" oninput={ parent.update } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/>
</div>
<div class="action">
<button class="cancel" onclick={ parent.cancel }>キャンセル</button>
<button class="ok" disabled={ !parent.allowEmpty && refs.text.value.length == 0 } onclick={ parent.ok }>決定</button>
</div>
</yield>
</mk-window>
<style>
:scope
@ -116,18 +120,17 @@
</style>
<script>
this.done = false
this.done = false;
this.title = this.opts.title
this.placeholder = this.opts.placeholder
this.default = this.opts.default
this.allow-empty = if this.opts.allow-empty? then this.opts.allow-empty else true
this.title = this.opts.title;
this.placeholder = this.opts.placeholder;
this.default = this.opts.default;
this.allowEmpty = this.opts.allowEmpty != null ? this.opts.allowEmpty : true;
this.on('mount', () => {
this.text = this.refs.window.refs.text
if @default?
@text.value = @default
@text.focus();
this.text = this.refs.window.refs.text;
if (this.default) this.text.value = this.default;
this.text.focus();
this.refs.window.on('closing', () => {
if @done
@ -138,6 +141,7 @@
this.refs.window.on('closed', () => {
this.unmount();
});
this.cancel = () => {
this.done = false
@ -148,7 +152,7 @@
this.done = true
this.refs.window.close();
this.on-keydown = (e) => {
this.onKeydown = (e) => {
if e.which == 13 // Enter
e.preventDefault();
e.stopPropagation();

View File

@ -127,13 +127,13 @@
if this.post.is_liked
this.api('posts/likes/delete', {
post_id: this.post.id
.then =>
}).then(() => {
this.post.is_liked = false
this.update();
else
this.api('posts/likes/create', {
post_id: this.post.id
.then =>
}).then(() => {
this.post.is_liked = true
this.update();
</script>

View File

@ -412,13 +412,13 @@
if this.p.is_liked
this.api('posts/likes/delete', {
post_id: this.p.id
.then =>
}).then(() => {
this.p.is_liked = false
this.update();
else
this.api('posts/likes/create', {
post_id: this.p.id
.then =>
}).then(() => {
this.p.is_liked = true
this.update();

View File

@ -455,7 +455,7 @@
.catch (err) =>
console.error err
@notify '投稿できませんでした'
.then =>
}).then(() => {
this.wait = false
this.update();

View File

@ -127,14 +127,14 @@
this.wait = true
this.api('posts/create', {
repost_id: this.opts.post.id
text: if @quote then this.refs.text.value else undefined
text: if this.quote then this.refs.text.value else undefined
}).then((data) => {
this.trigger('posted');
@notify 'Repostしました'
.catch (err) =>
console.error err
@notify 'Repostできませんでした'
.then =>
}).then(() => {
this.wait = false
this.update();

View File

@ -42,7 +42,7 @@
window.addEventListener 'scroll' this.on-scroll
this.api('posts/search', {
query: @query
query: this.query
}).then((posts) => {
this.is-loading = false
this.is-empty = posts.length == 0
@ -68,7 +68,7 @@
this.more-loading = true
this.update();
this.api('posts/search', {
query: @query
query: this.query
page: this.page + 1
}).then((posts) => {
this.more-loading = false

View File

@ -1,5 +1,11 @@
<mk-sub-post-content>
<div class="body"><a class="reply" if={ post.reply_to_id }><i class="fa fa-reply"></i></a><span ref="text"></span><a class="quote" if={ post.repost_id } href={ '/post:' + post.repost_id }>RP: ...</a></div>
<div class="body">
<a class="reply" if={ post.reply_to_id }>
<i class="fa fa-reply"></i>
</a>
<span ref="text"></span>
<a class="quote" if={ post.repost_id } href={ '/post:' + post.repost_id }>RP: ...</a>
</div>
<details if={ post.media }>
<summary>({ post.media.length }つのメディア)</summary>
<mk-images-viewer images={ post.media }></mk-images-viewer>
@ -31,15 +37,17 @@
this.mixin('text');
this.mixin('user-preview');
this.post = this.opts.post
this.post = this.opts.post;
this.on('mount', () => {
if this.post.text?
tokens = @analyze this.post.text
this.refs.text.innerHTML = @compile tokens, false
if (this.post.text) {
const tokens = this.analyze(this.post.text);
this.refs.text.innerHTML = this.compile(tokens, false);
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);
});
}
});
</script>
</mk-sub-post-content>

View File

@ -324,7 +324,7 @@
this.mixin('NotImplementedException');
this.post = this.opts.post;
this.isRepost = this.post.repost != null && this.post.text == null;
this.isRepost = this.post.repost && this.post.text == null;
this.p = this.isRepost ? this.post.repost : this.post;
this.title = this.dateStringify(this.p.created_at);
@ -354,58 +354,87 @@
});
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
}).then(() => {
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
}).then(() => {
this.p.is_liked = true;
this.update();
});
}
};
this.toggle-detail = () => {
this.is-detail-opened = !@is-detail-opened
this.update();
this.toggleDetail = () => {
this.update({
isDetailOpened: !this.isDetailOpened
});
};
this.on-key-down = (e) => {
should-be-cancel = true
switch
| e.which == 38 or e.which == 74 or (e.which == 9 and e.shift-key) => // ↑, j or Shift+Tab
focus this.root, (e) -> e.previousElementSibling
| e.which == 40 or e.which == 75 or e.which == 9 => // ↓, k or Tab
focus this.root, (e) -> e.nextElementSibling
| e.which == 81 or e.which == 69 => // q or e
@repost!
| e.which == 70 or e.which == 76 => // f or l
@like!
| e.which == 82 => // r
@reply!
| _ =>
should-be-cancel = false
this.onKeyDown = e => {
let shouldBeCancel = true;
if should-be-cancel
e.preventDefault();
switch (true) {
case e.which == 38: // [↑]
case e.which == 74: // [j]
case e.which == 9 && e.shiftKey: // [Shift] + [Tab]
focus(this.root, e => e.previousElementSibling);
break;
function focus(el, fn)
target = fn el
if target?
if target.has-attribute 'tabindex'
case e.which == 40: // [↓]
case e.which == 75: // [k]
case e.which == 9: // [Tab]
focus(this.root, e => e.nextElementSibling);
break;
case e.which == 81: // [q]
case e.which == 69: // [e]
this.repost();
break;
case e.which == 70: // [f]
case e.which == 76: // [l]
this.like();
break;
case e.which == 82: // [r]
this.reply();
break;
default:
shouldBeCancel = false;
}
if (shouldBeCancel) e.preventDefault();
};
function focus(el, fn) {
const target = fn(el);
if (target) {
if (target.hasAttribute('tabindex')) {
target.focus();
else
focus target, fn
} else {
focus(target, fn);
}
}
}
</script>
</mk-timeline-post>

View File

@ -501,7 +501,7 @@
this.ondragover = (e) => {
e.dataTransfer.dropEffect = 'none'
this.on-keydown = (e) => {
this.onKeydown = (e) => {
if e.which == 27 // Esc
if @can-close
e.preventDefault();

View File

@ -233,7 +233,7 @@
description: description
callback_url: cb
permission: permission.join ','
.then =>
}).then(() => {
location.href = '/apps'
.catch =>
alert 'アプリの作成に失敗しました。再度お試しください。'

View File

@ -192,9 +192,9 @@
name = window.prompt '名前を変更' this.file.name
if name? and name != '' and name != this.file.name
this.api('drive/files/update', {
file_id: this.file.id
file_id: this.file.id,
name: name
.then =>
}).then(() => {
this.parent.cf this.file, true
</script>

View File

@ -84,21 +84,21 @@
if this.user.is_following
this.api('following/delete', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = false
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
else
this.api('following/create', {
user_id: this.user.id
.then =>
}).then(() => {
this.user.is_following = true
.catch (err) ->
console.error err
.then =>
}).then(() => {
this.wait = false
this.update();
</script>

View File

@ -406,13 +406,13 @@
if this.p.is_liked
this.api('posts/likes/delete', {
post_id: this.p.id
.then =>
}).then(() => {
this.p.is_liked = false
this.update();
else
this.api('posts/likes/create', {
post_id: this.p.id
.then =>
}).then(() => {
this.p.is_liked = true
this.update();

View File

@ -9,24 +9,24 @@
<script>
this.mixin('api');
this.max = 30
this.offset = 0
this.max = 30;
this.offset = 0;
this.query = this.opts.query
this.with-media = this.opts.with-media
this.query = this.opts.query;
this.withMedia = this.opts.withMedia;
this.init = new Promise (res, rej) =>
this.api('posts/search', {
query: @query
}).then((posts) => {
query: this.query
}).then(posts => {
res posts
this.trigger('loaded');
this.more = () => {
@offset += @max
this.offset += this.max;
this.api('posts/search', {
query: @query
max: @max
offset: @offset
query: this.query
max: this.max
offset: this.offset
</script>
</mk-search-posts>

View File

@ -11,21 +11,21 @@
<script>
this.mixin('api');
this.user = this.opts.user
this.with-media = this.opts.with-media
this.user = this.opts.user;
this.withMedia = this.opts.withMedia;
this.init = new Promise (res, rej) =>
this.api('users/posts', {
user_id: this.user.id
with_media: @with-media
}).then((posts) => {
with_media: @withMedia
}).then(posts => {
res posts
this.trigger('loaded');
this.more = () => {
this.api('users/posts', {
user_id: this.user.id
with_media: @with-media
with_media: this.withMedia
max_id: this.refs.timeline.tail!.id
</script>
</mk-user-timeline>