diff --git a/src/components/profile-data-table.tsx b/src/components/profile-data-table.tsx index 7f366f7..f3bbd6d 100644 --- a/src/components/profile-data-table.tsx +++ b/src/components/profile-data-table.tsx @@ -174,6 +174,41 @@ export function ProfilesDataTable({ } }, [browserState.isClient, loadStoredProxies]); + // Automatically deselect profiles that become running or updating + React.useEffect(() => { + setSelectedProfiles((prev) => { + const newSet = new Set(prev); + let hasChanges = false; + + for (const profileName of prev) { + const profile = filteredData.find((p) => p.name === profileName); + if (profile) { + const isRunning = + browserState.isClient && runningProfiles.has(profile.name); + const isBrowserUpdating = isUpdating(profile.browser); + + if (isRunning || isBrowserUpdating) { + newSet.delete(profileName); + hasChanges = true; + } + } + } + + if (hasChanges) { + onSelectedProfilesChange?.(Array.from(newSet)); + return newSet; + } + + return prev; + }); + }, [ + filteredData, + runningProfiles, + isUpdating, + browserState.isClient, + onSelectedProfilesChange, + ]); + // Sync external selected profiles with internal state React.useEffect(() => { const newSet = new Set(externalSelectedProfiles); @@ -288,7 +323,16 @@ export function ProfilesDataTable({ const handleToggleAll = React.useCallback( (checked: boolean) => { const newSet = checked - ? new Set(filteredData.map((profile) => profile.name)) + ? new Set( + filteredData + .filter((profile) => { + const isRunning = + browserState.isClient && runningProfiles.has(profile.name); + const isBrowserUpdating = isUpdating(profile.browser); + return !isRunning && !isBrowserUpdating; + }) + .map((profile) => profile.name), + ) : new Set(); setSelectedProfiles(newSet); @@ -299,35 +343,76 @@ export function ProfilesDataTable({ onSelectedProfilesChange(Array.from(newSet)); } }, - [filteredData, onSelectedProfilesChange], + [ + filteredData, + onSelectedProfilesChange, + browserState.isClient, + runningProfiles, + isUpdating, + ], ); const columns: ColumnDef[] = React.useMemo( () => [ { id: "select", - header: () => ( - - handleToggleAll(!!value)} - aria-label="Select all" - className="cursor-pointer" - /> - - ), + header: () => { + const selectableProfiles = filteredData.filter((profile) => { + const isRunning = + browserState.isClient && runningProfiles.has(profile.name); + const isBrowserUpdating = isUpdating(profile.browser); + return !isRunning && !isBrowserUpdating; + }); + + return ( + + handleToggleAll(!!value)} + aria-label="Select all" + className="cursor-pointer" + /> + + ); + }, cell: ({ row }) => { const profile = row.original; const browser = profile.browser; const IconComponent = getBrowserIcon(browser); const isSelected = selectedProfiles.has(profile.name); + const isRunning = + browserState.isClient && runningProfiles.has(profile.name); + const isBrowserUpdating = isUpdating(browser); + const isDisabled = isRunning || isBrowserUpdating; + + // Show tooltip for disabled profiles + if (isDisabled) { + const tooltipMessage = isRunning + ? "Can't modify running profile" + : "Can't modify profile while browser is updating"; + + return ( + + + + {IconComponent && ( + + )} + + + +

{tooltipMessage}

+
+
+ ); + } if (showCheckboxes || isSelected) { return ( - + @@ -341,10 +426,10 @@ export function ProfilesDataTable({ } return ( - + ); @@ -487,13 +572,13 @@ export function ProfilesDataTable({ onClick={() => column.toggleSorting(column.getIsSorted() === "asc") } - className="h-auto p-0 font-semibold text-left justify-start cursor-pointer" + className="justify-start p-0 h-auto font-semibold text-left cursor-pointer" > Browser {column.getIsSorted() === "asc" ? ( - + ) : column.getIsSorted() === "desc" ? ( - + ) : null} ); @@ -715,8 +800,9 @@ export function ProfilesDataTable({ onChangeVersion, onAssignProfilesToGroup, isUpdating, - filteredData.length, launchingProfiles.has, + filteredData, + browserState.isClient, ], );