Profile editing: Allow adding arbitrary featured tags (#38012)
This commit is contained in:
8 files changed
+120
-65
No files matched your search
@@ -1,9 +1,9 @@
|
||||
import type { ChangeEventHandler, FC } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { useIntl } from 'react-intl';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import type { ApiFeaturedTagJSON } from '@/mastodon/api_types/tags';
|
||||
import type { ApiHashtagJSON } from '@/mastodon/api_types/tags';
|
||||
import { Combobox } from '@/mastodon/components/form_fields';
|
||||
import {
|
||||
addFeaturedTag,
|
||||
@@ -15,10 +15,50 @@ import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
type SearchResult = Omit<ApiHashtagJSON, 'url' | 'history'> & {
|
||||
label?: string;
|
||||
};
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: {
|
||||
id: 'account_edit_tags.search_placeholder',
|
||||
defaultMessage: 'Enter a hashtag…',
|
||||
},
|
||||
addTag: {
|
||||
id: 'account_edit_tags.add_tag',
|
||||
defaultMessage: 'Add #{tagName}',
|
||||
},
|
||||
});
|
||||
|
||||
export const AccountEditTagSearch: FC = () => {
|
||||
const { query, isLoading, results } = useAppSelector(
|
||||
(state) => state.profileEdit.search,
|
||||
);
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
query,
|
||||
isLoading,
|
||||
results: rawResults,
|
||||
} = useAppSelector((state) => state.profileEdit.search);
|
||||
const results = useMemo(() => {
|
||||
if (!rawResults) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const results: SearchResult[] = [...rawResults]; // Make array mutable
|
||||
const trimmedQuery = query.trim();
|
||||
if (
|
||||
trimmedQuery.length > 0 &&
|
||||
results.every(
|
||||
(result) => result.name.toLowerCase() !== trimmedQuery.toLowerCase(),
|
||||
)
|
||||
) {
|
||||
results.push({
|
||||
id: 'new',
|
||||
name: trimmedQuery,
|
||||
label: intl.formatMessage(messages.addTag, { tagName: trimmedQuery }),
|
||||
});
|
||||
}
|
||||
return results;
|
||||
}, [intl, query, rawResults]);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleSearchChange: ChangeEventHandler<HTMLInputElement> = useCallback(
|
||||
@@ -28,10 +68,8 @@ export const AccountEditTagSearch: FC = () => {
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(item: ApiFeaturedTagJSON) => {
|
||||
(item: SearchResult) => {
|
||||
void dispatch(clearSearch());
|
||||
void dispatch(addFeaturedTag({ name: item.name }));
|
||||
},
|
||||
@@ -42,11 +80,8 @@ export const AccountEditTagSearch: FC = () => {
|
||||
<Combobox
|
||||
value={query}
|
||||
onChange={handleSearchChange}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'account_edit_tags.search_placeholder',
|
||||
defaultMessage: 'Enter a hashtag…',
|
||||
})}
|
||||
items={results ?? []}
|
||||
placeholder={intl.formatMessage(messages.placeholder)}
|
||||
items={results}
|
||||
isLoading={isLoading}
|
||||
renderItem={renderItem}
|
||||
onSelectItem={handleSelect}
|
||||
@@ -57,4 +92,4 @@ export const AccountEditTagSearch: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderItem = (item: ApiFeaturedTagJSON) => <p>#{item.name}</p>;
|
||||
const renderItem = (item: SearchResult) => item.label ?? `#${item.name}`;
|
||||
Reference in new issue
Block a user