From 7b98c52af8ba136ddc18ea2c730f35a2759fde80 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 20 Dec 2025 12:36:21 +0000 Subject: fix(mobile): Add loading spinner to mobile list button (#2283) * fix: add loading spinner to manage lists buttons in mobile app Adds visual feedback when adding/removing bookmarks from lists on the manage lists page. The checkbox is replaced with an ActivityIndicator while the operation is in progress, preventing multiple taps and improving UX when the server is slow. Changes: - Track isPending and variables from add/remove mutations - Add isListLoading helper to check if a specific list is loading - Show ActivityIndicator instead of Checkbox during operations - Disable Pressable interaction while loading * fix: add loading spinner to manage tags page in mobile app Adds visual feedback when adding/removing tags on the manage tags page. A spinner appears on the specific tag being modified, replacing the check/plus icon during the network request. Only the tag being modified is disabled and dimmed to prevent multiple taps. Changes: - Track isPending and variables from updateTags mutation - Add isTagLoading helper to check if a specific tag is loading - Show ActivityIndicator on the specific tag being modified - Only disable the tag item that's loading * revert the change in the tags --------- Co-authored-by: Claude --- .../dashboard/bookmarks/[slug]/manage_lists.tsx | 76 +++++++++++++++------- 1 file changed, 51 insertions(+), 25 deletions(-) (limited to 'apps') diff --git a/apps/mobile/app/dashboard/bookmarks/[slug]/manage_lists.tsx b/apps/mobile/app/dashboard/bookmarks/[slug]/manage_lists.tsx index c502c07f..cc6db014 100644 --- a/apps/mobile/app/dashboard/bookmarks/[slug]/manage_lists.tsx +++ b/apps/mobile/app/dashboard/bookmarks/[slug]/manage_lists.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { FlatList, Pressable, View } from "react-native"; +import { ActivityIndicator, FlatList, Pressable, View } from "react-native"; import Checkbox from "expo-checkbox"; import { useLocalSearchParams } from "expo-router"; import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; @@ -36,7 +36,11 @@ const ListPickerPage = () => { ); const { data } = useBookmarkLists(); - const { mutate: addToList } = useAddBookmarkToList({ + const { + mutate: addToList, + isPending: isAddingToList, + variables: addVariables, + } = useAddBookmarkToList({ onSuccess: () => { toast({ message: `The bookmark has been added to the list!`, @@ -46,7 +50,11 @@ const ListPickerPage = () => { onError, }); - const { mutate: removeToList } = useRemoveBookmarkFromList({ + const { + mutate: removeToList, + isPending: isRemovingFromList, + variables: removeVariables, + } = useRemoveBookmarkFromList({ onSuccess: () => { toast({ message: `The bookmark has been removed from the list!`, @@ -67,6 +75,13 @@ const ListPickerPage = () => { } }; + const isListLoading = (listId: string) => { + return ( + (isAddingToList && addVariables?.listId === listId) || + (isRemovingFromList && removeVariables?.listId === listId) + ); + }; + const { allPaths } = data ?? {}; // Filter out lists where user is a viewer (can't add/remove bookmarks) const filteredPaths = allPaths?.filter( @@ -79,28 +94,39 @@ const ListPickerPage = () => { contentContainerStyle={{ gap: 5, }} - renderItem={(l) => ( - - toggleList(l.item[l.item.length - 1].id)} - className="flex w-full flex-row justify-between" - > - - {l.item.map((item) => `${item.icon} ${item.name}`).join(" / ")} - - { - toggleList(l.item[l.item.length - 1].id); - }} - /> - - - )} + renderItem={(l) => { + const listId = l.item[l.item.length - 1].id; + const isLoading = isListLoading(listId); + const isChecked = existingLists && existingLists.has(listId); + + return ( + + !isLoading && toggleList(listId)} + disabled={isLoading} + className="flex w-full flex-row justify-between" + > + + {l.item + .map((item) => `${item.icon} ${item.name}`) + .join(" / ")} + + {isLoading ? ( + + ) : ( + { + toggleList(listId); + }} + disabled={isLoading} + /> + )} + + + ); + }} data={filteredPaths} /> -- cgit v1.2.3-70-g09d2