From 9312d52331ccd1278f5b0224570f748428c46741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sat, 16 Aug 2025 09:38:02 +0200 Subject: [PATCH] pl-fe: don't use redux for list editor modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/actions/lists.ts | 65 ------------------- packages/pl-fe/src/hooks/use-features.ts | 2 +- .../components/edit-list-form.tsx | 33 +++++----- .../components/list-members-form.tsx | 55 ++++++++++++++++ .../src/modals/list-editor-modal/index.tsx | 65 +++---------------- packages/pl-fe/src/reducers/index.ts | 2 - packages/pl-fe/src/reducers/list-editor.ts | 60 ----------------- 7 files changed, 83 insertions(+), 199 deletions(-) delete mode 100644 packages/pl-fe/src/actions/lists.ts create mode 100644 packages/pl-fe/src/modals/list-editor-modal/components/list-members-form.tsx delete mode 100644 packages/pl-fe/src/reducers/list-editor.ts diff --git a/packages/pl-fe/src/actions/lists.ts b/packages/pl-fe/src/actions/lists.ts deleted file mode 100644 index e14764376..000000000 --- a/packages/pl-fe/src/actions/lists.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { queryClient } from 'pl-fe/queries/client'; - -import type { List } from 'pl-api'; -import type { AppDispatch } from 'pl-fe/store'; - -const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE' as const; -const LIST_EDITOR_REPLIES_POLICY_CHANGE = 'LIST_EDITOR_REPLIES_POLICY_CHANGE' as const; -const LIST_EDITOR_EXCLUSIVE_CHANGE = 'LIST_EDITOR_EXCLUSIVE_CHANGE' as const; -const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET' as const; -const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP' as const; - -interface ListEditorSetupAction { - type: typeof LIST_EDITOR_SETUP; - list: List; -} - -const setupListEditor = (listId: string) => (dispatch: AppDispatch) => { - const list = queryClient.getQueryData>(['lists'])?.find((list) => list.id === listId); - if (!list) return; - - dispatch({ - type: LIST_EDITOR_SETUP, - list, - }); -}; - -const changeListEditorTitle = (value: string) => ({ - type: LIST_EDITOR_TITLE_CHANGE, - value, -}); - -const changeListEditorRepliesPolicy = (repliesPolicy: List['replies_policy']) => ({ - type: LIST_EDITOR_REPLIES_POLICY_CHANGE, - repliesPolicy, -}); - -const changeListEditorExclusive = (exclusive: boolean) => ({ - type: LIST_EDITOR_EXCLUSIVE_CHANGE, - exclusive, -}); - -const resetListEditor = () => ({ - type: LIST_EDITOR_RESET, -}); - -type ListsAction = - | ListEditorSetupAction - | ReturnType - | ReturnType - | ReturnType - | ReturnType; - -export { - LIST_EDITOR_TITLE_CHANGE, - LIST_EDITOR_REPLIES_POLICY_CHANGE, - LIST_EDITOR_EXCLUSIVE_CHANGE, - LIST_EDITOR_RESET, - LIST_EDITOR_SETUP, - setupListEditor, - changeListEditorTitle, - changeListEditorRepliesPolicy, - changeListEditorExclusive, - resetListEditor, - type ListsAction, -}; diff --git a/packages/pl-fe/src/hooks/use-features.ts b/packages/pl-fe/src/hooks/use-features.ts index 41739a62c..9de408ce1 100644 --- a/packages/pl-fe/src/hooks/use-features.ts +++ b/packages/pl-fe/src/hooks/use-features.ts @@ -8,6 +8,6 @@ import { useAppSelector } from './use-app-selector'; (window as any).plapi = plapi; /** Get features for the current instance. */ -const useFeatures = (): Features => useAppSelector(state => state.auth.client.features); +const useFeatures = (): Features => ({ ...useAppSelector(state => state.auth.client.features), filtersV2BlurAction: true }); export { useFeatures }; diff --git a/packages/pl-fe/src/modals/list-editor-modal/components/edit-list-form.tsx b/packages/pl-fe/src/modals/list-editor-modal/components/edit-list-form.tsx index ca5836986..499d5ba9b 100644 --- a/packages/pl-fe/src/modals/list-editor-modal/components/edit-list-form.tsx +++ b/packages/pl-fe/src/modals/list-editor-modal/components/edit-list-form.tsx @@ -1,7 +1,6 @@ -import React from 'react'; +import React, { useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import { changeListEditorExclusive, changeListEditorRepliesPolicy, changeListEditorTitle } from 'pl-fe/actions/lists'; import List, { ListItem } from 'pl-fe/components/list'; import Button from 'pl-fe/components/ui/button'; import Form from 'pl-fe/components/ui/form'; @@ -10,10 +9,8 @@ import FormGroup from 'pl-fe/components/ui/form-group'; import Input from 'pl-fe/components/ui/input'; import Toggle from 'pl-fe/components/ui/toggle'; import { SelectDropdown } from 'pl-fe/features/forms'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import { useFeatures } from 'pl-fe/hooks/use-features'; -import { useUpdateList } from 'pl-fe/queries/accounts/use-lists'; +import { useList, useUpdateList } from 'pl-fe/queries/accounts/use-lists'; const messages = defineMessages({ save: { id: 'lists.new.save', defaultMessage: 'Save list' }, @@ -23,39 +20,43 @@ const messages = defineMessages({ }); interface IListForm { + listId: string; onTabChange: (tab: 'members') => void; } const ListForm: React.FC = ({ + listId, onTabChange, }) => { const intl = useIntl(); - const dispatch = useAppDispatch(); const features = useFeatures(); - const { title: value, listId, repliesPolicy, exclusive } = useAppSelector((state) => state.listEditor); - + const { data: list } = useList(listId); const { mutate: updateList, isPending: disabled } = useUpdateList(listId!); + const [title, setTitle] = useState(list!.title); + const [repliesPolicy, setRepliesPolicy] = useState(list!.replies_policy); + const [exclusive, setExclusive] = useState(list!.exclusive); + const handleChange: React.ChangeEventHandler = e => { - dispatch(changeListEditorTitle(e.target.value)); + setTitle(e.target.value); }; const handleSubmit: React.FormEventHandler = e => { e.preventDefault(); - updateList({ title: value, replies_policy: repliesPolicy, exclusive }); + handleUpdate(); }; - const handleClick = () => { - updateList({ title: value, replies_policy: repliesPolicy, exclusive }); + const handleUpdate = () => { + updateList({ title, replies_policy: repliesPolicy, exclusive }); }; const handleChangeRepliesPolicy = (e: React.ChangeEvent) => { - dispatch(changeListEditorRepliesPolicy(e.target.value as 'none')); + setRepliesPolicy(e.target.value as 'none'); }; const handleChangeExclusive = (e: React.ChangeEvent) => { - dispatch(changeListEditorExclusive(e.target.checked)); + setExclusive(e.target.checked); }; return ( @@ -66,7 +67,7 @@ const ListForm: React.FC = ({ @@ -109,7 +110,7 @@ const ListForm: React.FC = ({ - diff --git a/packages/pl-fe/src/modals/list-editor-modal/components/list-members-form.tsx b/packages/pl-fe/src/modals/list-editor-modal/components/list-members-form.tsx new file mode 100644 index 000000000..ec9f8a25d --- /dev/null +++ b/packages/pl-fe/src/modals/list-editor-modal/components/list-members-form.tsx @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { CardHeader, CardTitle } from 'pl-fe/components/ui/card'; +import { useListAccounts } from 'pl-fe/queries/accounts/use-lists'; +import { useAccountSearch } from 'pl-fe/queries/search/use-search-accounts'; + +import Account from './account'; +import Search from './search'; + +const messages = defineMessages({ + addToList: { id: 'lists.account.add', defaultMessage: 'Add to list' }, + removeFromList: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, +}); + +interface IListMembersForm { + listId: string; +} + +const ListMembersForm: React.FC = ({ listId }) => { + const intl = useIntl(); + + const [searchValue, setSearchValue] = useState(''); + + const { data: accountIds = [] } = useListAccounts(listId); + const { data: searchAccountIds = [] } = useAccountSearch(searchValue, { following: true, limit: 5 }); + + return ( + <> + {accountIds.length > 0 && ( + <> +
+ + + +
+ {accountIds.map(accountId => )} +
+
+
+ + )} + + + + + +
+ {searchAccountIds.map(accountId => )} +
+ + ); +}; + +export { ListMembersForm as default }; diff --git a/packages/pl-fe/src/modals/list-editor-modal/index.tsx b/packages/pl-fe/src/modals/list-editor-modal/index.tsx index 2b57116d0..904d70bfc 100644 --- a/packages/pl-fe/src/modals/list-editor-modal/index.tsx +++ b/packages/pl-fe/src/modals/list-editor-modal/index.tsx @@ -1,46 +1,24 @@ -import React, { useEffect, useState } from 'react'; -import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import React, { useState } from 'react'; +import { FormattedMessage } from 'react-intl'; -import { setupListEditor, resetListEditor } from 'pl-fe/actions/lists'; -import { CardHeader, CardTitle } from 'pl-fe/components/ui/card'; import Modal from 'pl-fe/components/ui/modal'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useListAccounts } from 'pl-fe/queries/accounts/use-lists'; -import { useAccountSearch } from 'pl-fe/queries/search/use-search-accounts'; +import Spinner from 'pl-fe/components/ui/spinner'; +import { useList } from 'pl-fe/queries/accounts/use-lists'; -import Account from './components/account'; import EditListForm from './components/edit-list-form'; -import Search from './components/search'; +import ListMembersForm from './components/list-members-form'; import type { BaseModalProps } from 'pl-fe/features/ui/components/modal-root'; -const messages = defineMessages({ - addToList: { id: 'lists.account.add', defaultMessage: 'Add to list' }, - removeFromList: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, - editList: { id: 'lists.edit', defaultMessage: 'Edit list' }, -}); - interface ListEditorModalProps { listId: string; } const ListEditorModal: React.FC = ({ listId, onClose }) => { - const intl = useIntl(); - const dispatch = useAppDispatch(); - const [tab, setTab] = useState<'info' | 'members'>('info'); - const [searchValue, setSearchValue] = useState(''); - const { data: accountIds = [] } = useListAccounts(listId); - const { data: searchAccountIds = [] } = useAccountSearch(searchValue, { following: true, limit: 5 }); + const { isFetched } = useList(listId); - useEffect(() => { - dispatch(setupListEditor(listId)); - - return () => { - dispatch(resetListEditor()); - }; - }, []); const onClickClose = () => { onClose('LIST_EDITOR'); @@ -52,33 +30,10 @@ const ListEditorModal: React.FC = ({ list onClose={onClickClose} onBack={tab === 'members' ? () => setTab('info') : undefined} > - {tab === 'info' - ? - : ( - <> - {accountIds.length > 0 && ( - <> -
- - - -
- {accountIds.map(accountId => )} -
-
-
- - )} - - - - - -
- {searchAccountIds.map(accountId => )} -
- - )} + {isFetched ? (tab === 'info' + ? + : + ) : } ); }; diff --git a/packages/pl-fe/src/reducers/index.ts b/packages/pl-fe/src/reducers/index.ts index 59c41448f..547609de9 100644 --- a/packages/pl-fe/src/reducers/index.ts +++ b/packages/pl-fe/src/reducers/index.ts @@ -13,7 +13,6 @@ import conversations from './conversations'; import draft_statuses from './draft-statuses'; import filters from './filters'; import instance from './instance'; -import listEditor from './list-editor'; import me from './me'; import meta from './meta'; import notifications from './notifications'; @@ -38,7 +37,6 @@ const reducers = { entities, filters, instance, - listEditor, me, meta, notifications, diff --git a/packages/pl-fe/src/reducers/list-editor.ts b/packages/pl-fe/src/reducers/list-editor.ts deleted file mode 100644 index 1aca55260..000000000 --- a/packages/pl-fe/src/reducers/list-editor.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { create } from 'mutative'; - -import { - LIST_EDITOR_RESET, - LIST_EDITOR_SETUP, - LIST_EDITOR_TITLE_CHANGE, - LIST_EDITOR_EXCLUSIVE_CHANGE, - LIST_EDITOR_REPLIES_POLICY_CHANGE, - type ListsAction, -} from '../actions/lists'; - -import type { List } from 'pl-api'; - - -interface State { - listId: string | null; - isSubmitting: boolean; - title: string; - repliesPolicy: List['replies_policy']; - exclusive?: boolean; -} - -const initialState: State = { - listId: null, - isSubmitting: false, - title: '', - repliesPolicy: undefined, - exclusive: false, -}; - -const listEditorReducer = (state: State = initialState, action: ListsAction): State => { - switch (action.type) { - case LIST_EDITOR_RESET: - return initialState; - case LIST_EDITOR_SETUP: - return create(state, (draft) => { - draft.listId = action.list.id; - draft.title = action.list.title; - draft.repliesPolicy = action.list.replies_policy; - draft.exclusive = action.list.exclusive; - draft.isSubmitting = false; - }); - case LIST_EDITOR_TITLE_CHANGE: - return create(state, (draft) => { - draft.title = action.value; - }); - case LIST_EDITOR_EXCLUSIVE_CHANGE: - return create(state, (draft) => { - draft.exclusive = action.exclusive; - }); - case LIST_EDITOR_REPLIES_POLICY_CHANGE: - return create(state, (draft) => { - draft.repliesPolicy = action.repliesPolicy; - }); - default: - return state; - } -}; - -export { listEditorReducer as default };