msg convo actions

inbox2
Thibault Duplessis 2020-01-26 10:30:23 -06:00
parent 26bbf71694
commit 25e869f71b
7 changed files with 160 additions and 106 deletions

View File

@ -0,0 +1,4 @@
<svg viewBox="-1 -1 52 52" xmlns="http://www.w3.org/2000/svg">
<path fill="#000000" stroke="#000000" stroke-linejoin="round" style="stroke-width:3"
d="M38.956.5c-3.53.418-6.452.902-9.286 2.984C5.534 1.786-.692 18.533.68 29.364 3.493 50.214 31.918 55.785 41.329 41.7c-7.444 7.696-19.276 8.752-28.323 3.084C3.959 39.116-.506 27.392 4.683 17.567 9.873 7.742 18.996 4.535 29.03 6.405c2.43-1.418 5.225-3.22 7.655-3.187l-1.694 4.86 12.752 21.37c-.439 5.654-5.459 6.112-5.459 6.112-.574-1.47-1.634-2.942-4.842-6.036-3.207-3.094-17.465-10.177-15.788-16.207-2.001 6.967 10.311 14.152 14.04 17.663 3.73 3.51 5.426 6.04 5.795 6.756 0 0 9.392-2.504 7.838-8.927L37.4 7.171z"/>
</svg>

After

Width:  |  Height:  |  Size: 671 B

View File

@ -5,11 +5,11 @@
@extend %flex-column;
flex: 1 1 100%;
&__head {
@extend %flex-center;
@extend %flex-between;
flex: 0 0 $msg-top-height;
background: $c-bg-zebra2;
border-bottom: $border;
padding: 0 1vw;
padding: 0 1.5em 0 1vw;
.user-link {
@extend %flex-center-nowrap;
flex: 0 0 auto;
@ -23,6 +23,15 @@
font-size: 1.5em;
}
}
&__actions {
@extend %flex-center;
}
}
&__action.button {
color: $c-font;
&.bad:hover {
color: $c-bad;
}
}
&__reply {
@extend %flex-center-nowrap;
@ -37,6 +46,11 @@
background: $c-bg-box;
resize: none;
}
&__block {
flex: 1 1 auto;
text-align: center;
margin: .6em;
}
}
}
}

View File

@ -55,4 +55,14 @@ export default class MsgCtrl {
this.redraw();
}
}
block = () => {
const userId = this.data.convo?.thread.contact.id;
if (userId) network.block(userId).then(() => this.openConvo(userId));
}
unblock = () => {
const userId = this.data.convo?.thread.contact.id;
if (userId) network.unblock(userId).then(() => this.openConvo(userId));
}
}

View File

@ -36,6 +36,20 @@ export function search(q: string) {
});
}
export function block(u: string) {
return $.ajax({
url: `/rel/block/${u}`,
method: 'post'
});
}
export function unblock(u: string) {
return $.ajax({
url: `/rel/unblock/${u}`,
method: 'post'
});
}
export function post(dest: string, text: string) {
window.lichess.pubsub.emit('socket.send', 'msgSend', { dest, text });
}

View File

@ -0,0 +1,52 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Convo } from '../interfaces'
import { bind } from './util';
import MsgCtrl from '../ctrl';
export default function renderActions(ctrl: MsgCtrl, convo: Convo): VNode[] {
const user = convo.thread.contact, nodes = [];
const cls = 'msg-app__convo__action.button.button-empty';
nodes.push(
h(`a.${cls}`, {
key: 'play',
attrs: {
'data-icon': 'U',
href: `/?user=${user.name}#friend`,
title: ctrl.trans.noarg('challengeToPlay')
}
})
);
if (convo.relations.out === false) nodes.push(
h(`button.${cls}.unbad.text.hover-text`, {
key: 'unblock',
attrs: {
'data-icon': 'k',
title: ctrl.trans.noarg('blocked'),
'data-hover-text': ctrl.trans.noarg('unblock')
},
hook: bind('click', ctrl.unblock)
})
);
else nodes.push(
h(`button.${cls}.bad`, {
key: 'block',
attrs: {
'data-icon': 'k',
title: ctrl.trans.noarg('block')
},
hook: bind('click', ctrl.block)
})
);
nodes.push(
h(`button.${cls}.bad.confirm`, {
key: 'report',
attrs: {
'data-icon': '!',
href: '/report/flag',
title: ctrl.trans.noarg('report')
}
})
);
return nodes;
}

View File

@ -3,7 +3,8 @@ import { VNode } from 'snabbdom/vnode'
import { Convo } from '../interfaces'
import { userName } from './util';
import renderMsgs from './msgs';
import throttle from 'common/throttle';
import renderActions from './actions';
import renderTextarea from './textarea';
import MsgCtrl from '../ctrl';
export default function renderConvo(ctrl: MsgCtrl, convo: Convo): VNode {
@ -26,109 +27,11 @@ export default function renderConvo(ctrl: MsgCtrl, convo: Convo): VNode {
]),
renderMsgs(ctrl, convo.msgs),
h('div.msg-app__convo__reply', [
h('textarea.msg-app__convo__reply__text', {
attrs: {
rows: 1,
autofocus: 1
},
hook: {
insert(vnode) {
setupTextarea(vnode.elm as HTMLTextAreaElement, user.id, ctrl.post);
}
}
})
convo.relations.out === false || convo.relations.in === false ?
h('div.msg-app__convo__reply__block.text', {
attrs: { 'data-icon': 'k' }
}, 'This conversation is blocked.') :
renderTextarea(ctrl, user)
])
]);
}
function renderActions(ctrl: MsgCtrl, convo: Convo): VNode[] {
const user = convo.thread.contact, nodes = [];
if (convo.relations.out) nodes.push(
h('button.msg-app__convo__action.text.hover-text', {
attrs: {
'data-icon': 'h',
href: `/rel/unfollow/${user.id}`,
title: ctrl.trans.noarg('following'),
'data-hover-text': ctrl.trans.noarg('unfollow')
}
})
);
else if (convo.relations.out === false) nodes.push(
h('button.msg-app__convo__action.text.hover-text', {
attrs: {
'data-icon': 'k',
href: `/rel/unblock/${user.id}`,
title: ctrl.trans.noarg('blocked'),
'data-hover-text': ctrl.trans.noarg('unblock')
}
})
);
else {
nodes.push(
h('a.msg-app__convo__action', {
attrs: {
'data-icon': 'h',
href: `/rel/follow/${user.id}`,
title: ctrl.trans.noarg('follow')
}
})
);
nodes.push(
h('a.msg-app__convo__action', {
attrs: {
'data-icon': 'k',
href: `/rel/block/${user.id}`,
title: ctrl.trans.noarg('block')
}
})
);
}
nodes.push(
h('a.msg-app__convo__action', {
attrs: {
'data-icon': 'i',
href: '/report/flag',
title: ctrl.trans.noarg('report')
}
})
);
return nodes;
}
function setupTextarea(area: HTMLTextAreaElement, contact: string, post: (text: string) => void) {
// save the textarea content until sent
const storage = window.lichess.storage.make(`msg:area:${contact}`);
// hack to automatically resize the textarea based on content
area.value = '';
let baseScrollHeight = area.scrollHeight;
area.addEventListener('input', throttle(500, () =>
setTimeout(() => {
const text = area.value.trim();
area.rows = 1;
// the resize magic
if (text) area.rows = Math.min(10, 1 + Math.ceil((area.scrollHeight - baseScrollHeight) / 19));
// and save content
storage.set(text);
})
));
// restore previously saved content
area.value = storage.get() || '';
if (area.value) area.dispatchEvent(new Event('input'));
// send the content on <enter.
area.addEventListener('keypress', (e: KeyboardEvent) => {
if ((e.which == 10 || e.which == 13) && !e.shiftKey) {
setTimeout(() => {
const txt = area.value.trim();
if (txt) post(txt);
area.value = '';
area.dispatchEvent(new Event('input')); // resize the textarea
storage.remove();
});
}
});
area.focus();
}

View File

@ -0,0 +1,57 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { User } from '../interfaces'
import MsgCtrl from '../ctrl';
import throttle from 'common/throttle';
export default function renderTextarea(ctrl: MsgCtrl, user: User): VNode {
return h('textarea.msg-app__convo__reply__text', {
attrs: {
rows: 1,
autofocus: 1
},
hook: {
insert(vnode) {
setupTextarea(vnode.elm as HTMLTextAreaElement, user.id, ctrl.post);
}
}
});
}
function setupTextarea(area: HTMLTextAreaElement, contact: string, post: (text: string) => void) {
// save the textarea content until sent
const storage = window.lichess.storage.make(`msg:area:${contact}`);
// hack to automatically resize the textarea based on content
area.value = '';
let baseScrollHeight = area.scrollHeight;
area.addEventListener('input', throttle(500, () =>
setTimeout(() => {
const text = area.value.trim();
area.rows = 1;
// the resize magic
if (text) area.rows = Math.min(10, 1 + Math.ceil((area.scrollHeight - baseScrollHeight) / 19));
// and save content
storage.set(text);
})
));
// restore previously saved content
area.value = storage.get() || '';
if (area.value) area.dispatchEvent(new Event('input'));
// send the content on <enter.
area.addEventListener('keypress', (e: KeyboardEvent) => {
if ((e.which == 10 || e.which == 13) && !e.shiftKey) {
setTimeout(() => {
const txt = area.value.trim();
if (txt) post(txt);
area.value = '';
area.dispatchEvent(new Event('input')); // resize the textarea
storage.remove();
});
}
});
area.focus();
}