From 7a1e6394831fb07e303c5ed0900dfe1ea4820de5 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Wed, 24 Apr 2024 12:12:47 +0200 Subject: [chore] Refactor settings panel routing (and other fixes) (#2864) --- web/source/settings/admin/emoji/local/detail.js | 146 -------------------- web/source/settings/admin/emoji/local/index.tsx | 35 ----- .../settings/admin/emoji/local/new-emoji.tsx | 116 ---------------- web/source/settings/admin/emoji/local/overview.js | 153 --------------------- .../settings/admin/emoji/local/use-shortcode.js | 56 -------- 5 files changed, 506 deletions(-) delete mode 100644 web/source/settings/admin/emoji/local/detail.js delete mode 100644 web/source/settings/admin/emoji/local/index.tsx delete mode 100644 web/source/settings/admin/emoji/local/new-emoji.tsx delete mode 100644 web/source/settings/admin/emoji/local/overview.js delete mode 100644 web/source/settings/admin/emoji/local/use-shortcode.js (limited to 'web/source/settings/admin/emoji/local') diff --git a/web/source/settings/admin/emoji/local/detail.js b/web/source/settings/admin/emoji/local/detail.js deleted file mode 100644 index a78e3e499..000000000 --- a/web/source/settings/admin/emoji/local/detail.js +++ /dev/null @@ -1,146 +0,0 @@ -/* - GoToSocial - Copyright (C) GoToSocial Authors admin@gotosocial.org - SPDX-License-Identifier: AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -import React, { useEffect } from "react"; -import { useRoute, Link, Redirect } from "wouter"; - -import { useComboBoxInput, useFileInput, useValue } from "../../../lib/form"; -import { CategorySelect } from "../category-select"; - -import useFormSubmit from "../../../lib/form/submit"; -import { useBaseUrl } from "../../../lib/navigation/util"; - -import FakeToot from "../../../components/fake-toot"; -import FormWithData from "../../../lib/form/form-with-data"; -import Loading from "../../../components/loading"; -import { FileInput } from "../../../components/form/inputs"; -import MutationButton from "../../../components/form/mutation-button"; -import { Error } from "../../../components/error"; - -import { useGetEmojiQuery, useEditEmojiMutation, useDeleteEmojiMutation } from "../../../lib/query/admin/custom-emoji"; - -export default function EmojiDetailRoute({ }) { - const baseUrl = useBaseUrl(); - let [_match, params] = useRoute(`${baseUrl}/:emojiId`); - if (params?.emojiId == undefined) { - return ; - } else { - return ( -
- < go back - -
- ); - } -} - -function EmojiDetailForm({ data: emoji }) { - const baseUrl = useBaseUrl(); - const form = { - id: useValue("id", emoji.id), - category: useComboBoxInput("category", { source: emoji }), - image: useFileInput("image", { - withPreview: true, - maxSize: 50 * 1024 // TODO: get from instance api - }) - }; - - const [modifyEmoji, result] = useFormSubmit(form, useEditEmojiMutation()); - - // Automatic submitting of category change - useEffect(() => { - if ( - form.category.hasChanged() && - !form.category.state.open && - !form.category.isNew) { - modifyEmoji(); - } - /* eslint-disable-next-line react-hooks/exhaustive-deps */ - }, [form.category.hasChanged(), form.category.isNew, form.category.state.open]); - - const [deleteEmoji, deleteResult] = useDeleteEmojiMutation(); - - if (deleteResult.isSuccess) { - return ; - } - - return ( - <> -
- {emoji.shortcode} -
-

{emoji.shortcode}

- deleteEmoji(emoji.id)} - className="danger" - showError={false} - result={deleteResult} - /> -
-
- -
-

Modify this emoji {result.isLoading && }

- -
- - - -
- -
- - - - - - Look at this new custom emoji {emoji.shortcode} isn't it cool? - - - {result.error && } - {deleteResult.error && } -
-
- - ); -} \ No newline at end of file diff --git a/web/source/settings/admin/emoji/local/index.tsx b/web/source/settings/admin/emoji/local/index.tsx deleted file mode 100644 index 74a891f3e..000000000 --- a/web/source/settings/admin/emoji/local/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - GoToSocial - Copyright (C) GoToSocial Authors admin@gotosocial.org - SPDX-License-Identifier: AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -import React from "react"; -import { Switch, Route } from "wouter"; - -import EmojiOverview from "./overview"; -import EmojiDetail from "./detail"; - -export default function CustomEmoji({ baseUrl }) { - return ( - - - - - - - ); -} diff --git a/web/source/settings/admin/emoji/local/new-emoji.tsx b/web/source/settings/admin/emoji/local/new-emoji.tsx deleted file mode 100644 index c6a203765..000000000 --- a/web/source/settings/admin/emoji/local/new-emoji.tsx +++ /dev/null @@ -1,116 +0,0 @@ -/* - GoToSocial - Copyright (C) GoToSocial Authors admin@gotosocial.org - SPDX-License-Identifier: AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -import React, { useMemo, useEffect } from "react"; - -import { useFileInput, useComboBoxInput } from "../../../lib/form"; -import useShortcode from "./use-shortcode"; - -import useFormSubmit from "../../../lib/form/submit"; - -import { TextInput, FileInput } from "../../../components/form/inputs"; - -import { CategorySelect } from '../category-select'; -import FakeToot from "../../../components/fake-toot"; -import MutationButton from "../../../components/form/mutation-button"; -import { useAddEmojiMutation } from "../../../lib/query/admin/custom-emoji"; -import { useInstanceV1Query } from "../../../lib/query"; - -export default function NewEmojiForm() { - const shortcode = useShortcode(); - - const { data: instance } = useInstanceV1Query(); - const emojiMaxSize = useMemo(() => { - return instance?.configuration?.emojis?.emoji_size_limit ?? 50 * 1024; - }, [instance]); - - const image = useFileInput("image", { - withPreview: true, - maxSize: emojiMaxSize - }); - - const category = useComboBoxInput("category"); - - const [submitForm, result] = useFormSubmit({ - shortcode, image, category - }, useAddEmojiMutation()); - - useEffect(() => { - if (shortcode.value === undefined || shortcode.value.length == 0) { - if (image.value != undefined) { - let [name, _ext] = image.value.name.split("."); - shortcode.setter(name); - } - } - - /* We explicitly don't want to have 'shortcode' as a dependency here - because we only want to change the shortcode to the filename if the field is empty - at the moment the file is selected, not some time after when the field is emptied - */ - /* eslint-disable-next-line react-hooks/exhaustive-deps */ - }, [image.value]); - - let emojiOrShortcode; - - if (image.previewValue != undefined) { - emojiOrShortcode = {shortcode.value}; - } else if (shortcode.value !== undefined && shortcode.value.length > 0) { - emojiOrShortcode = `:${shortcode.value}:`; - } else { - emojiOrShortcode = `:your_emoji_here:`; - } - - return ( -
-

Add new custom emoji

- - - Look at this new custom emoji {emojiOrShortcode} isn't it cool? - - -
- - - - - - - - -
- ); -} \ No newline at end of file diff --git a/web/source/settings/admin/emoji/local/overview.js b/web/source/settings/admin/emoji/local/overview.js deleted file mode 100644 index 45bfd614d..000000000 --- a/web/source/settings/admin/emoji/local/overview.js +++ /dev/null @@ -1,153 +0,0 @@ -/* - GoToSocial - Copyright (C) GoToSocial Authors admin@gotosocial.org - SPDX-License-Identifier: AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -const React = require("react"); -const { Link } = require("wouter"); -const syncpipe = require("syncpipe"); -const { matchSorter } = require("match-sorter"); - -const NewEmojiForm = require("./new-emoji").default; -const { useTextInput } = require("../../../lib/form"); - -const { useEmojiByCategory } = require("../category-select"); -const { useBaseUrl } = require("../../../lib/navigation/util"); - -const Loading = require("../../../components/loading"); -const { Error } = require("../../../components/error"); -const { TextInput } = require("../../../components/form/inputs"); -const { useListEmojiQuery } = require("../../../lib/query/admin/custom-emoji"); - -module.exports = function EmojiOverview({ }) { - const { - data: emoji = [], - isLoading, - isError, - error - } = useListEmojiQuery({ filter: "domain:local" }); - - let content = null; - - if (isLoading) { - content = ; - } else if (isError) { - content = ; - } else { - content = ( - <> - - - - ); - } - - return ( - <> -

Local Custom Emoji

-

- 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 Remote Emoji page. -

-

- Be warned! If you upload more than about 300-400 custom emojis in - total on your instance, this may lead to rate-limiting issues for users and clients - if they try to load all the emoji images at once (which is what many clients do). -

- {content} - - ); -}; - -function EmojiList({ emoji }) { - 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 ( -
-

Overview

- {emoji.length > 0 - ? {emoji.length} custom emoji {hidden > 0 && `(${hidden} filtered)`} - : No custom emoji yet, you can add one below. - } -
-
- -
-
- {filteredEmoji.length > 0 - ? ( -
- {filteredEmoji.map(([category, entries]) => { - return ; - })} -
- ) - :
No local emoji matched your filter.
- } -
-
-
- ); -} - -function EmojiCategory({ category, entries }) { - const baseUrl = useBaseUrl(); - return ( -
- {category} -
- {entries.map((e) => { - return ( - - - {e.shortcode} - - - ); - })} -
-
- ); -} \ No newline at end of file diff --git a/web/source/settings/admin/emoji/local/use-shortcode.js b/web/source/settings/admin/emoji/local/use-shortcode.js deleted file mode 100644 index 67255860f..000000000 --- a/web/source/settings/admin/emoji/local/use-shortcode.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - GoToSocial - Copyright (C) GoToSocial Authors admin@gotosocial.org - SPDX-License-Identifier: AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -const React = require("react"); - -const { useTextInput } = require("../../../lib/form"); -const { useListEmojiQuery } = require("../../../lib/query/admin/custom-emoji"); - -const shortcodeRegex = /^\w{2,30}$/; - -module.exports = function useShortcode() { - const { data: emoji = [] } = useListEmojiQuery({ - filter: "domain:local" - }); - - const emojiCodes = React.useMemo(() => { - return new Set(emoji.map((e) => e.shortcode)); - }, [emoji]); - - return useTextInput("shortcode", { - validator: function validateShortcode(code) { - // technically invalid, but hacky fix to prevent validation error on page load - if (code == "") { return ""; } - - if (emojiCodes.has(code)) { - return "Shortcode already in use"; - } - - if (code.length < 2 || code.length > 30) { - return "Shortcode must be between 2 and 30 characters"; - } - - if (!shortcodeRegex.test(code)) { - return "Shortcode must only contain letters, numbers, and underscores"; - } - - return ""; - } - }); -}; \ No newline at end of file -- cgit v1.3