mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-04-23 12:26:17 +02:00
refactor: block selection if the profile is launching or stopping
This commit is contained in:
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user