From 4b28d99f16e5b098204b32b8991c343392e1c949 Mon Sep 17 00:00:00 2001 From: Matt Panaro Date: Tue, 31 Dec 2024 21:32:51 -0500 Subject: [PATCH] refactor handleChange to include helper-object for quickActions parameterize and move all the objects being pushed to newQuickActions (inside of handleChange) into a helper-object called QuickActionGenerators, so that handleChange isn't so many lines; it also separates the concerns a bit between parsing search input text and generating quickActions based on it --- .../features/compose/components/search.tsx | 190 ++++++++++-------- 1 file changed, 106 insertions(+), 84 deletions(-) diff --git a/app/javascript/mastodon/features/compose/components/search.tsx b/app/javascript/mastodon/features/compose/components/search.tsx index d5f7e00baf..c38939a2d6 100644 --- a/app/javascript/mastodon/features/compose/components/search.tsx +++ b/app/javascript/mastodon/features/compose/components/search.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState, useRef } from 'react'; +import { useCallback, useState, useRef, useMemo } from 'react'; import { defineMessages, @@ -252,6 +252,103 @@ export const Search: React.FC<{ [dispatch, history], ); + const QuickActionGenerators: { + couldBeURL: (url: string) => SearchOption; + couldBeHashtag: (tag: string) => SearchOption; + couldBeUsername: (username: string) => SearchOption; + couldBeStatusSearch: (status: string) => SearchOption; + accountSearch: (account: string) => SearchOption; + } = useMemo( + () => ({ + couldBeURL: (url: string): SearchOption => ({ + key: 'open-url', + label: ( + + ), + action: () => { + dispatch(openURL({ url: url })) + .then((result) => { + if (isFulfilled(result)) { + if (result.payload.accounts[0]) { + history.push(`/@${result.payload.accounts[0].acct}`); + } else if (result.payload.statuses[0]) { + history.push( + `/@${result.payload.statuses[0].account.acct}/${result.payload.statuses[0].id}`, + ); + } + } + return void 0; + }) + .catch((e: unknown) => { + console.error(e); + }) + .finally(() => { + unfocus(); + }); + }, + }), + couldBeHashtag: (tag: string): SearchOption => ({ + key: 'go-to-hashtag', + label: ( + #{tag} }} + /> + ), + action: () => { + history.push(`/tags/${tag}`); + void dispatch(clickSearchResult({ q: tag, type: 'hashtag' })); + unfocus(); + }, + }), + couldBeUsername: (username: string): SearchOption => ({ + key: 'go-to-account', + label: ( + @{username} }} + /> + ), + action: () => { + history.push(`/@${username}`); + void dispatch(clickSearchResult({ q: username, type: 'account' })); + unfocus(); + }, + }), + couldBeStatusSearch: (status: string): SearchOption => ({ + key: 'status-search', + label: ( + {status} }} + /> + ), + action: () => { + submit(status, 'statuses'); + }, + }), + accountSearch: (account: string): SearchOption => ({ + key: 'account-search', + label: ( + {account} }} + /> + ), + action: () => { + submit(account, 'accounts'); + }, + }), + }), + [dispatch, history, submit], + ); const handleChange = useCallback( ({ target: { value } }: React.ChangeEvent) => { setValue(value); @@ -264,30 +361,7 @@ export const Search: React.FC<{ trimmedValue.startsWith('https://') && !trimmedValue.includes(' '); if (couldBeURL) { - newQuickActions.push({ - key: 'open-url', - label: ( - - ), - action: async () => { - const result = await dispatch(openURL({ url: trimmedValue })); - - if (isFulfilled(result)) { - if (result.payload.accounts[0]) { - history.push(`/@${result.payload.accounts[0].acct}`); - } else if (result.payload.statuses[0]) { - history.push( - `/@${result.payload.statuses[0].account.acct}/${result.payload.statuses[0].id}`, - ); - } - } - - unfocus(); - }, - }); + newQuickActions.push(QuickActionGenerators.couldBeURL(trimmedValue)); } const couldBeHashtag = @@ -295,81 +369,29 @@ export const Search: React.FC<{ trimmedValue.match(HASHTAG_REGEX); if (couldBeHashtag) { - newQuickActions.push({ - key: 'go-to-hashtag', - label: ( - #{trimmedValue.replace(/^#/, '')} }} - /> - ), - action: () => { - const query = trimmedValue.replace(/^#/, ''); - history.push(`/tags/${query}`); - void dispatch(clickSearchResult({ q: query, type: 'hashtag' })); - unfocus(); - }, - }); + newQuickActions.push(QuickActionGenerators.couldBeHashtag(trimmedValue.replace(/^#/, ''))); } const couldBeUsername = /^@?[a-z0-9_-]+(@[^\s]+)?$/i.exec(trimmedValue); if (couldBeUsername) { - newQuickActions.push({ - key: 'go-to-account', - label: ( - @{trimmedValue.replace(/^@/, '')} }} - /> - ), - action: () => { - const query = trimmedValue.replace(/^@/, ''); - history.push(`/@${query}`); - void dispatch(clickSearchResult({ q: query, type: 'account' })); - unfocus(); - }, - }); + newQuickActions.push(QuickActionGenerators.couldBeUsername(trimmedValue.replace(/^@/, ''))); } const couldBeStatusSearch = searchEnabled; if (couldBeStatusSearch && signedIn) { - newQuickActions.push({ - key: 'status-search', - label: ( - {trimmedValue} }} - /> - ), - action: () => { - submit(trimmedValue, 'statuses'); - }, - }); + newQuickActions.push( + QuickActionGenerators.couldBeStatusSearch(trimmedValue), + ); } - newQuickActions.push({ - key: 'account-search', - label: ( - {trimmedValue} }} - /> - ), - action: () => { - submit(trimmedValue, 'accounts'); - }, - }); + newQuickActions.push(QuickActionGenerators.accountSearch(trimmedValue)); } setQuickActions(newQuickActions); }, - [dispatch, history, signedIn, setValue, setQuickActions, submit], + [signedIn, setValue, setQuickActions, QuickActionGenerators], ); const handleClear = useCallback(() => {