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