You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Hydro/packages/ui-default/components/discussion/reaction.page.tsx

92 lines
3.2 KiB
TypeScript

import 'jquery.easing';
import { Popover } from '@blueprintjs/core';
import $ from 'jquery';
import { chunk } from 'lodash';
import * as React from 'react';
import ReactDOM from 'react-dom/client';
import { AutoloadPage } from 'vj/misc/Page';
import { request } from 'vj/utils';
function renderReactions(reactions, self, rootEle) {
let html = '';
for (const [k, v] of Object.entries(reactions).sort(([, v1], [, v2]) => +v2 - +v1)) {
if (!v) continue;
html += `<div class="reaction${self[k] ? ' active' : ''}""><span class="emoji">${k}</span> ${v}</div>\n`;
}
rootEle.html(html);
}
async function handleEmojiClick(payload, emoji, ele) {
const res = await request.post('', { ...payload, emoji });
if (!res.sdoc) return;
renderReactions(res.doc?.react, res.sdoc.react, ele);
}
function getRow(count) {
if (count <= 2) return 2;
if (count <= 3) return 3;
if (count <= 4) return 4;
if (count <= 6) return 6;
return 12;
}
function Reaction({ payload, ele }) {
const emojiList: string[] = (UiContext.emojiList || '👍 👎 😄 😕 ❤️ 🤔 🤣 🌿 🍋 🕊️ 👀 🤣').split(' ');
const elesPerRow = getRow(Math.sqrt(emojiList.length));
const [focus, updateFocus] = React.useState(false);
const [finish, updateFinish] = React.useState(false);
if (finish) setTimeout(() => updateFinish(false), 1000);
return (
<Popover usePortal interactionKind="hover" isOpen={finish ? false : (focus ? true : undefined)}>
<span className="icon icon-emoji"></span>
<div>
{chunk(emojiList, elesPerRow).map((line, i) => (
<div className="row" key={+i} style={{ paddingBottom: 4, paddingTop: 4 }}>
{line.map((emoji) => (
<div
key={emoji}
className={`medium-${12 / elesPerRow} small-${12 / elesPerRow} columns popover-reaction-item`}
onClick={() => handleEmojiClick(payload, emoji, ele).then(() => updateFinish(true))}
>
{emoji}
</div>
))}
</div>
))}
<div className="row" style={{ paddingTop: 7, paddingBottom: 4 }}>
<div className="medium-12 columns">
<input name="emojiSuggest" onFocus={() => updateFocus(true)} onBlur={() => updateFocus(false)}></input>
</div>
</div>
</div>
</Popover>
);
}
const reactionPage = new AutoloadPage('reactionPage', () => {
const canUseReaction = $('[data-op="react"]').length > 0;
$('[data-op="react"]').each((i, e) => {
ReactDOM.createRoot(e).render(
<Reaction payload={$(e).data('form')} ele={$(`.reactions[data-${$(e).data('form').nodeType}='${$(e).data('form').id}']`)} />,
);
});
$(document).on('click', '.reaction', async (e) => {
if (!canUseReaction) {
(window as any).showSignInDialog();
return;
}
const target = $(e.currentTarget);
const res = await request.post('', {
operation: 'reaction',
nodeType: target.parent().data('type'),
id: target.parent().data(target.parent().data('type')),
emoji: target.text().trim().split(' ')[0],
reverse: target.hasClass('active'),
});
renderReactions(res.doc?.react, res.sdoc?.react, target.parent());
});
});
export default reactionPage;