lila/ui/notify/src/view.ts

110 lines
2.7 KiB
TypeScript

import { Ctrl, NotifyData, Notification } from './interfaces';
import { h, VNode } from 'snabbdom';
import spinner from 'common/spinner';
import makeRenderers from './renderers';
export default function view(ctrl: Ctrl): VNode {
const d = ctrl.data();
return h(
'div#notify-app.links.dropdown',
d && !ctrl.initiating() ? renderContent(ctrl, d) : [h('div.initiating', spinner())]
);
}
function renderContent(ctrl: Ctrl, d: NotifyData): VNode[] {
const pager = d.pager;
const nb = pager.currentPageResults.length;
const nodes: VNode[] = [];
nodes.push(
h(`div.pager.prev${pager.previousPage ? '' : '.disabled'}`, {
attrs: { 'data-icon': '' },
hook: clickHook(ctrl.previousPage),
})
);
if (nb > 0)
nodes.push(
h('button.delete.button.button-empty', {
attrs: {
'data-icon': '',
title: 'Clear',
},
hook: clickHook(ctrl.clear),
})
);
nodes.push(nb ? recentNotifications(d, ctrl.scrolling()) : empty());
if (pager.nextPage)
nodes.push(
h('div.pager.next', {
attrs: { 'data-icon': '' },
hook: clickHook(ctrl.nextPage),
})
);
if (!('Notification' in window))
nodes.push(h('div.browser-notification', 'Browser does not support notification popups'));
else if (Notification.permission == 'denied') nodes.push(notificationDenied());
return nodes;
}
export function asText(n: Notification, trans: Trans): string | undefined {
const renderers = makeRenderers(trans);
return renderers[n.type] ? renderers[n.type].text(n) : undefined;
}
function notificationDenied(): VNode {
return h(
'a.browser-notification.denied',
{
attrs: {
href: '/faq#browser-notifications',
target: '_blank',
rel: 'noopener',
},
},
'Notification popups disabled by browser setting'
);
}
function asHtml(n: Notification, trans: Trans): VNode | undefined {
const renderers = makeRenderers(trans);
return renderers[n.type] ? renderers[n.type].html(n) : undefined;
}
function clickHook(f: () => void) {
return {
insert: (vnode: VNode) => {
(vnode.elm as HTMLElement).addEventListener('click', f);
},
};
}
const contentLoaded = (vnode: VNode) => lichess.contentLoaded(vnode.elm as HTMLElement);
function recentNotifications(d: NotifyData, scrolling: boolean): VNode {
const trans = lichess.trans(d.i18n);
return h(
'div',
{
class: {
notifications: true,
scrolling,
},
hook: {
insert: contentLoaded,
postpatch: contentLoaded,
},
},
d.pager.currentPageResults.map(n => asHtml(n, trans)) as VNode[]
);
}
function empty() {
return h('div.empty.text', { attrs: { 'data-icon': '' } }, 'No notifications.');
}