mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature/frontend] filterable local emoji list (#1385)
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
@@ -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>
|
||||
|
Reference in New Issue
Block a user