From 5bd94f91fd1a7939e7217f5cfea0dd2ff4c7f396 Mon Sep 17 00:00:00 2001 From: Huu Le <20178761+huult@users.noreply.github.com> Date: Wed, 6 Aug 2025 09:08:54 +0700 Subject: [PATCH 1/2] fix category and tag list gets deselected when editing list item name --- .../categories/WorkspaceCategoriesPage.tsx | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index 645162f98e66..ecbdfc03ae11 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -25,7 +25,6 @@ import TextLink from '@components/TextLink'; import useAutoTurnSelectionModeOffWhenHasNoActiveOption from '@hooks/useAutoTurnSelectionModeOffWhenHasNoActiveOption'; import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions'; import useEnvironment from '@hooks/useEnvironment'; -import useFilteredSelection from '@hooks/useFilteredSelection'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; @@ -52,7 +51,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; -import type {PolicyCategory} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; type PolicyOption = ListItem & { @@ -90,9 +88,8 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { const isConnectionVerified = connectedIntegration && !isConnectionUnverified(policy, connectedIntegration); const currentConnectionName = getCurrentConnectionName(policy); const isQuickSettingsFlow = route.name === SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_ROOT; - const filterCategories = useCallback((category: PolicyCategory | undefined) => !!category && category.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, []); - const [selectedCategories, setSelectedCategories] = useFilteredSelection(policyCategories, filterCategories); + const [selectedCategories, setSelectedCategories] = useState([]); const canSelectMultiple = isSmallScreenWidth ? isMobileSelectionModeEnabled : true; const fetchCategories = useCallback(() => { @@ -107,9 +104,37 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const cleanupSelectedOption = useCallback(() => setSelectedCategories([]), [setSelectedCategories]); + const cleanupSelectedOption = useCallback(() => setSelectedCategories([]), []); useCleanupSelectedOptions(cleanupSelectedOption); + useEffect(() => { + if (selectedCategories.length === 0 || !canSelectMultiple) { + return; + } + + setSelectedCategories((prevSelectedCategories) => { + const newSelectedCategories = []; + + for (const categoryName of prevSelectedCategories) { + const categoryExists = policyCategories?.[categoryName]; + if (!categoryExists) { + const renamedCategory = Object.entries(policyCategories ?? {}).find(([, category]) => category.previousCategoryName === categoryName); + if (renamedCategory) { + newSelectedCategories.push(renamedCategory[0]); + continue; + } + } + + if (categoryExists && categoryExists.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { + newSelectedCategories.push(categoryName); + } + } + + return newSelectedCategories; + }); + // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps + }, [policyCategories]); + useSearchBackPress({ onClearSelection: () => setSelectedCategories([]), onNavigationCallBack: () => Navigation.goBack(backTo), From 900112e2fe4892f649b50cd251b0fc6678526f08 Mon Sep 17 00:00:00 2001 From: Huu Le <20178761+huult@users.noreply.github.com> Date: Wed, 6 Aug 2025 15:54:07 +0700 Subject: [PATCH 2/2] fix tag list diselected when editing name --- .../workspace/tags/WorkspaceTagsPage.tsx | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index e48e3475267c..1c00c6a52762 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -24,7 +24,6 @@ import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions'; import useEnvironment from '@hooks/useEnvironment'; -import useFilteredSelection from '@hooks/useFilteredSelection'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; @@ -122,9 +121,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { return policyTagLists?.at(0)?.tags; }, [isMultiLevelTags, policyTagLists]); - const filterTags = useCallback((tag?: PolicyTag | PolicyTagList) => !!tag && tag.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, []); - - const [selectedTags, setSelectedTags] = useFilteredSelection(tagsList, filterTags); + const [selectedTags, setSelectedTags] = useState([]); const isTagSelected = useCallback((tag: TagListItem) => selectedTags.includes(tag.value), [selectedTags]); @@ -136,7 +133,55 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const cleanupSelectedOption = useCallback(() => setSelectedTags([]), [setSelectedTags]); + useEffect(() => { + if (selectedTags.length === 0 || !canSelectMultiple) { + return; + } + + setSelectedTags((prevSelectedTags) => { + const newSelectedTags = []; + + for (const tagName of prevSelectedTags) { + if (isMultiLevelTags) { + const tagListExists = tagsList?.[tagName]; + if (!tagListExists) { + const renamedTagList = Object.entries(tagsList ?? {}).find(([, tagList]) => { + const typedTagList = tagList as {previousTagName?: string}; + return typedTagList.previousTagName === tagName; + }); + if (renamedTagList) { + newSelectedTags.push(renamedTagList[0]); + continue; + } + } + + if (tagListExists && tagListExists.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { + newSelectedTags.push(tagName); + } + } else { + const tagExists = tagsList?.[tagName]; + if (!tagExists) { + const renamedTag = Object.entries(tagsList ?? {}).find(([, tag]) => { + const typedTag = tag as {previousTagName?: string}; + return typedTag.previousTagName === tagName; + }); + if (renamedTag) { + newSelectedTags.push(renamedTag[0]); + continue; + } + } + + if (tagExists && tagExists.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { + newSelectedTags.push(tagName); + } + } + } + + return newSelectedTags; + }); + // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps + }, [tagsList]); + const cleanupSelectedOption = useCallback(() => setSelectedTags([]), []); useCleanupSelectedOptions(cleanupSelectedOption); useSearchBackPress({