refactor: block selection if the profile is launching or stopping

This commit is contained in:
zhom
2025-08-04 07:02:38 +04:00
parent e675441171
commit 83f4c2c162
3 changed files with 150 additions and 18 deletions
+58 -10
View File
@@ -106,6 +106,9 @@ export function ProfilesDataTable({
const [launchingProfiles, setLaunchingProfiles] = React.useState<Set<string>>(
new Set(),
);
const [stoppingProfiles, setStoppingProfiles] = React.useState<Set<string>>(
new Set(),
);
const [storedProxies, setStoredProxies] = React.useState<StoredProxy[]>([]);
const [selectedProfiles, setSelectedProfiles] = React.useState<Set<string>>(
@@ -156,6 +159,8 @@ export function ProfilesDataTable({
filteredData,
runningProfiles,
isUpdating,
launchingProfiles,
stoppingProfiles,
);
// Load stored proxies
@@ -174,7 +179,7 @@ export function ProfilesDataTable({
}
}, [browserState.isClient, loadStoredProxies]);
// Automatically deselect profiles that become running or updating
// Automatically deselect profiles that become running, updating, launching, or stopping
React.useEffect(() => {
setSelectedProfiles((prev) => {
const newSet = new Set(prev);
@@ -185,9 +190,11 @@ export function ProfilesDataTable({
if (profile) {
const isRunning =
browserState.isClient && runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const isBrowserUpdating = isUpdating(profile.browser);
if (isRunning || isBrowserUpdating) {
if (isRunning || isLaunching || isStopping || isBrowserUpdating) {
newSet.delete(profileName);
hasChanges = true;
}
@@ -204,6 +211,8 @@ export function ProfilesDataTable({
}, [
filteredData,
runningProfiles,
launchingProfiles,
stoppingProfiles,
isUpdating,
browserState.isClient,
onSelectedProfilesChange,
@@ -336,8 +345,15 @@ export function ProfilesDataTable({
.filter((profile) => {
const isRunning =
browserState.isClient && runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const isBrowserUpdating = isUpdating(profile.browser);
return !isRunning && !isBrowserUpdating;
return (
!isRunning &&
!isLaunching &&
!isStopping &&
!isBrowserUpdating
);
})
.map((profile) => profile.name),
)
@@ -356,6 +372,8 @@ export function ProfilesDataTable({
onSelectedProfilesChange,
browserState.isClient,
runningProfiles,
launchingProfiles,
stoppingProfiles,
isUpdating,
],
);
@@ -368,8 +386,12 @@ export function ProfilesDataTable({
const selectableProfiles = filteredData.filter((profile) => {
const isRunning =
browserState.isClient && runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const isBrowserUpdating = isUpdating(profile.browser);
return !isRunning && !isBrowserUpdating;
return (
!isRunning && !isLaunching && !isStopping && !isBrowserUpdating
);
});
return (
@@ -393,14 +415,21 @@ export function ProfilesDataTable({
const isSelected = selectedProfiles.has(profile.name);
const isRunning =
browserState.isClient && runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const isBrowserUpdating = isUpdating(browser);
const isDisabled = isRunning || isBrowserUpdating;
const isDisabled =
isRunning || isLaunching || isStopping || isBrowserUpdating;
// Show tooltip for disabled profiles
if (isDisabled) {
const tooltipMessage = isRunning
? "Can't modify running profile"
: "Can't modify profile while browser is updating";
: isLaunching
? "Can't modify profile while launching"
: isStopping
? "Can't modify profile while stopping"
: "Can't modify profile while browser is updating";
return (
<Tooltip>
@@ -462,6 +491,7 @@ export function ProfilesDataTable({
const isRunning =
browserState.isClient && runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const canLaunch = browserState.canLaunchProfile(profile);
const tooltipContent = browserState.getLaunchTooltipContent(profile);
@@ -470,7 +500,24 @@ export function ProfilesDataTable({
console.log(
`Stopping ${profile.browser} profile: ${profile.name}`,
);
await onKillProfile(profile);
setStoppingProfiles((prev) => new Set(prev).add(profile.name));
try {
await onKillProfile(profile);
console.log(
`Successfully stopped ${profile.browser} profile: ${profile.name}`,
);
} catch (error) {
console.error(
`Failed to stop ${profile.browser} profile: ${profile.name}`,
error,
);
} finally {
setStoppingProfiles((prev) => {
const next = new Set(prev);
next.delete(profile.name);
return next;
});
}
} else {
console.log(
`Launching ${profile.browser} profile: ${profile.name}`,
@@ -504,14 +551,14 @@ export function ProfilesDataTable({
<Button
variant={isRunning ? "destructive" : "default"}
size="sm"
disabled={!canLaunch || isLaunching}
disabled={!canLaunch || isLaunching || isStopping}
className={cn(
"cursor-pointer min-w-[70px]",
!canLaunch && "opacity-50",
)}
onClick={() => void handleLaunchClick()}
>
{isLaunching ? (
{isLaunching || isStopping ? (
<div className="flex gap-1 items-center">
<div className="w-3 h-3 rounded-full border border-current animate-spin border-t-transparent" />
</div>
@@ -808,7 +855,8 @@ export function ProfilesDataTable({
onChangeVersion,
onAssignProfilesToGroup,
isUpdating,
launchingProfiles.has,
launchingProfiles,
stoppingProfiles,
filteredData,
browserState.isClient,
],
+31 -1
View File
@@ -51,9 +51,21 @@ export function ProfileSelectorDialog({
const [isLoading, setIsLoading] = useState(false);
const [isLaunching, setIsLaunching] = useState(false);
const [storedProxies, setStoredProxies] = useState<StoredProxy[]>([]);
const [launchingProfiles, setLaunchingProfiles] = useState<Set<string>>(
new Set(),
);
const [stoppingProfiles, _setStoppingProfiles] = useState<Set<string>>(
new Set(),
);
// Use shared browser state hook
const browserState = useBrowserState(profiles, runningProfiles, isUpdating);
const browserState = useBrowserState(
profiles,
runningProfiles,
isUpdating,
launchingProfiles,
stoppingProfiles,
);
// Helper function to check if a profile has a proxy
const hasProxy = useCallback(
@@ -116,6 +128,7 @@ export function ProfileSelectorDialog({
if (!selectedProfile || !url) return;
setIsLaunching(true);
setLaunchingProfiles((prev) => new Set(prev).add(selectedProfile));
try {
await invoke("open_url_with_profile", {
profileName: selectedProfile,
@@ -126,6 +139,11 @@ export function ProfileSelectorDialog({
console.error("Failed to open URL with profile:", error);
} finally {
setIsLaunching(false);
setLaunchingProfiles((prev) => {
const next = new Set(prev);
next.delete(selectedProfile);
return next;
});
}
}, [selectedProfile, url, onClose]);
@@ -221,6 +239,8 @@ export function ProfileSelectorDialog({
<SelectContent>
{profiles.map((profile) => {
const isRunning = runningProfiles.has(profile.name);
const isLaunching = launchingProfiles.has(profile.name);
const isStopping = stoppingProfiles.has(profile.name);
const canUseForLinks =
browserState.canUseProfileForLinks(profile);
const tooltipContent = getProfileTooltipContent(profile);
@@ -269,6 +289,16 @@ export function ProfileSelectorDialog({
Running
</Badge>
)}
{isLaunching && (
<Badge variant="outline" className="text-xs">
Launching
</Badge>
)}
{isStopping && (
<Badge variant="outline" className="text-xs">
Stopping
</Badge>
)}
{!canUseForLinks && (
<Badge
variant="destructive"
+61 -7
View File
@@ -8,7 +8,9 @@ import type { BrowserProfile } from "@/types";
export function useBrowserState(
profiles: BrowserProfile[],
runningProfiles: Set<string>,
isUpdating?: (browser: string) => boolean,
isUpdating: (browser: string) => boolean,
launchingProfiles: Set<string>,
stoppingProfiles: Set<string>,
) {
const [isClient, setIsClient] = useState(false);
@@ -47,8 +49,15 @@ export function useBrowserState(
if (!isClient) return false;
const isRunning = runningProfiles.has(profile.name);
const isLaunching = launchingProfiles?.has(profile.name) ?? false;
const isStopping = stoppingProfiles?.has(profile.name) ?? false;
const isBrowserUpdating = isUpdating?.(profile.browser) ?? false;
// If the profile is launching or stopping, disable the button
if (isLaunching || isStopping) {
return false;
}
// If the profile is already running, it can always be stopped
if (isRunning) return true;
@@ -70,6 +79,8 @@ export function useBrowserState(
isUpdating,
isSingleInstanceBrowser,
isAnyInstanceRunning,
launchingProfiles,
stoppingProfiles,
],
);
@@ -82,10 +93,12 @@ export function useBrowserState(
if (!isClient) return false;
const isRunning = runningProfiles.has(profile.name);
const isLaunching = launchingProfiles?.has(profile.name) ?? false;
const isStopping = stoppingProfiles?.has(profile.name) ?? false;
const isBrowserUpdating = isUpdating?.(profile.browser) ?? false;
// If this specific browser is updating or downloading, block it
if (isBrowserUpdating) {
// If this specific browser is updating, downloading, launching, or stopping, block it
if (isBrowserUpdating || isLaunching || isStopping) {
return false;
}
@@ -107,7 +120,15 @@ export function useBrowserState(
// For other browsers, any profile can be used
return true;
},
[profiles, runningProfiles, isClient, isSingleInstanceBrowser, isUpdating],
[
profiles,
runningProfiles,
isClient,
isSingleInstanceBrowser,
isUpdating,
launchingProfiles,
stoppingProfiles,
],
);
/**
@@ -117,16 +138,25 @@ export function useBrowserState(
(profile: BrowserProfile): boolean => {
if (!isClient) return false;
const isRunning = runningProfiles.has(profile.name);
const isLaunching = launchingProfiles?.has(profile.name) ?? false;
const isStopping = stoppingProfiles?.has(profile.name) ?? false;
const isBrowserUpdating = isUpdating?.(profile.browser) ?? false;
// If this specific browser is updating or downloading, block selection
if (isBrowserUpdating) {
// If profile is running, launching, stopping, or browser is updating, block selection
if (isRunning || isLaunching || isStopping || isBrowserUpdating) {
return false;
}
return true;
},
[isClient, isUpdating],
[
isClient,
runningProfiles,
launchingProfiles,
stoppingProfiles,
isUpdating,
],
);
/**
@@ -137,8 +167,18 @@ export function useBrowserState(
if (!isClient) return "Loading...";
const isRunning = runningProfiles.has(profile.name);
const isLaunching = launchingProfiles?.has(profile.name) ?? false;
const isStopping = stoppingProfiles?.has(profile.name) ?? false;
const isBrowserUpdating = isUpdating?.(profile.browser) ?? false;
if (isLaunching) {
return "Launching browser...";
}
if (isStopping) {
return "Stopping browser...";
}
if (isRunning) {
return "";
}
@@ -164,6 +204,8 @@ export function useBrowserState(
isUpdating,
isSingleInstanceBrowser,
canLaunchProfile,
launchingProfiles,
stoppingProfiles,
],
);
@@ -178,8 +220,18 @@ export function useBrowserState(
if (canUseForLinks) return null;
const isLaunching = launchingProfiles?.has(profile.name) ?? false;
const isStopping = stoppingProfiles?.has(profile.name) ?? false;
const isBrowserUpdating = isUpdating?.(profile.browser) ?? false;
if (isLaunching) {
return "Profile is currently launching. Please wait.";
}
if (isStopping) {
return "Profile is currently stopping. Please wait.";
}
if (isBrowserUpdating) {
return `${getBrowserDisplayName(profile.browser)} is being updated. Please wait for the update to complete.`;
}
@@ -208,6 +260,8 @@ export function useBrowserState(
canUseProfileForLinks,
isSingleInstanceBrowser,
isUpdating,
launchingProfiles,
stoppingProfiles,
],
);