[feature/frontend] filterable local emoji list (#1385)

This commit is contained in:
f0x52 2023-01-27 09:09:26 +01:00 committed by GitHub
parent 782169da76
commit 08f8feaec5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 25 deletions

View file

@ -419,11 +419,6 @@ label {
display: flex;
flex-direction: column;
&.scrolling {
max-height: 40rem;
overflow: auto;
}
.header, .entry {
padding: 0.5rem;
}
@ -435,6 +430,17 @@ label {
font-weight: bold;
}
.entries {
display: flex;
flex-direction: column;
&.scrolling {
height: 20rem;
max-height: 20rem;
overflow: auto;
}
}
input[type=checkbox] {
margin-left: 0.5rem;
}

View file

@ -20,13 +20,18 @@
const React = require("react");
const { Link } = require("wouter");
const syncpipe = require("syncpipe");
const { matchSorter } = require("match-sorter");
const NewEmojiForm = require("./new-emoji");
const { useTextInput } = require("../../../lib/form");
const query = require("../../../lib/query");
const { useEmojiByCategory } = require("../category-select");
const Loading = require("../../../components/loading");
const { Error } = require("../../../components/error");
const { TextInput } = require("../../../components/form/inputs");
module.exports = function EmojiOverview({ baseUrl }) {
const {
@ -53,23 +58,70 @@ module.exports = function EmojiOverview({ baseUrl }) {
return (
<>
<h1>Custom Emoji (local)</h1>
<h1>Local Custom Emoji</h1>
<p>
To use custom emoji in your toots they have to be 'local' to the instance.
You can either upload them here directly, or copy from those already
present on other (known) instances through the <Link to={`../remote`}>Remote Emoji</Link> page.
</p>
{content}
</>
);
};
function EmojiList({ emoji, baseUrl }) {
const filterField = useTextInput("filter");
const filter = filterField.value;
const emojiByCategory = useEmojiByCategory(emoji);
/* Filter emoji based on shortcode match with user input, hiding empty categories */
const { filteredEmoji, hidden } = React.useMemo(() => {
let hidden = emoji.length;
const filteredEmoji = syncpipe(emojiByCategory, [
(_) => Object.entries(emojiByCategory),
(_) => _.map(([category, entries]) => {
let filteredEntries = matchSorter(entries, filter, { keys: ["shortcode"] });
if (filteredEntries.length == 0) {
return null;
} else {
hidden -= filteredEntries.length;
return [category, filteredEntries];
}
}),
(_) => _.filter((value) => value !== null)
]);
return { filteredEmoji, hidden };
}, [filter, emojiByCategory, emoji.length]);
return (
<div>
<h2>Overview</h2>
{emoji.length > 0
? <span>{emoji.length} custom emoji {hidden > 0 && `(${hidden} filtered)`}</span>
: <span>No custom emoji yet, you can add one below.</span>
}
<div className="list emoji-list">
{emoji.length == 0 && "No local emoji yet, add one below"}
{Object.entries(emojiByCategory).map(([category, entries]) => {
return <EmojiCategory key={category} category={category} entries={entries} baseUrl={baseUrl} />;
})}
<div className="header">
<TextInput
field={filterField}
name="emoji-shortcode"
placeholder="Search"
/>
</div>
<div className="entries scrolling">
{filteredEmoji.length > 0
? (
<div className="entries scrolling">
{filteredEmoji.map(([category, entries]) => {
return <EmojiCategory key={category} category={category} entries={entries} baseUrl={baseUrl} />;
})}
</div>
)
: <div className="entry">No local emoji matched your filter.</div>
}
</div>
</div>
</div>
);

View file

@ -76,21 +76,23 @@ module.exports = function InstanceOverview({ baseUrl }) {
<span>
{blockedInstancesList.length} blocked instance{blockedInstancesList.length != 1 ? "s" : ""} {filtered > 0 && `(${filtered} filtered by search)`}
</span>
<div className="list scrolling">
{filteredInstances.map((entry) => {
return (
<Link key={entry.domain} to={`${baseUrl}/${entry.domain}`}>
<a className="entry nounderline">
<span id="domain">
{entry.domain}
</span>
<span id="date">
{new Date(entry.created_at).toLocaleString()}
</span>
</a>
</Link>
);
})}
<div className="list">
<div className="entries scrolling">
{filteredInstances.map((entry) => {
return (
<Link key={entry.domain} to={`${baseUrl}/${entry.domain}`}>
<a className="entry nounderline">
<span id="domain">
{entry.domain}
</span>
<span id="date">
{new Date(entry.created_at).toLocaleString()}
</span>
</a>
</Link>
);
})}
</div>
</div>
</div>
</div>

View file

@ -405,6 +405,10 @@ span.form-info {
.emoji-list {
background: $list-entry-bg;
.header .form-field {
flex: 1 1 auto;
}
.entry {
flex-direction: column;