fix: linter and formatting

This commit is contained in:
zhom
2025-05-29 10:39:04 +04:00
parent 08678dcacc
commit 56c1f94616
37 changed files with 4013 additions and 2894 deletions
+26 -23
View File
@@ -63,7 +63,7 @@ export default function Home() {
try {
const profileList = await invoke<BrowserProfile[]>(
"list_browser_profiles"
"list_browser_profiles",
);
setProfiles(profileList);
@@ -90,9 +90,12 @@ export default function Home() {
void checkStartupUrls();
// Set up periodic update checks (every 30 minutes)
const updateInterval = setInterval(() => {
void checkForUpdates();
}, 30 * 60 * 1000);
const updateInterval = setInterval(
() => {
void checkForUpdates();
},
30 * 60 * 1000,
);
return () => {
clearInterval(updateInterval);
@@ -104,7 +107,7 @@ export default function Home() {
try {
const shouldShow = await invoke<boolean>(
"should_show_settings_on_startup"
"should_show_settings_on_startup",
);
if (shouldShow) {
setSettingsDialogOpen(true);
@@ -119,7 +122,7 @@ export default function Home() {
try {
const hasStartupUrl = await invoke<boolean>(
"check_and_handle_startup_url"
"check_and_handle_startup_url",
);
if (hasStartupUrl) {
console.log("Handled startup URL successfully");
@@ -152,10 +155,10 @@ export default function Home() {
await listen<string>("show-create-profile-dialog", (event) => {
console.log(
"Received show create profile dialog request:",
event.payload
event.payload,
);
setError(
"No profiles available. Please create a profile first before opening URLs."
"No profiles available. Please create a profile first before opening URLs.",
);
setCreateProfileDialogOpen(true);
});
@@ -177,7 +180,7 @@ export default function Home() {
} catch (error: any) {
console.log(
"Smart URL opening failed or requires profile selection:",
error
error,
);
// Check if it's the special error cases
@@ -187,7 +190,7 @@ export default function Home() {
} else if (error === "no_profiles") {
// No profiles available, show error message
setError(
"No profiles available. Please create a profile first before opening URLs."
"No profiles available. Please create a profile first before opening URLs.",
);
} else {
// Some other error occurred
@@ -225,7 +228,7 @@ export default function Home() {
setError(`Failed to update proxy settings: ${JSON.stringify(err)}`);
}
},
[currentProfileForProxy, loadProfiles]
[currentProfileForProxy, loadProfiles],
);
const handleCreateProfile = useCallback(
@@ -244,7 +247,7 @@ export default function Home() {
name: profileData.name,
browserStr: profileData.browserStr,
version: profileData.version,
}
},
);
// Update proxy if provided
@@ -261,11 +264,11 @@ export default function Home() {
throw error;
}
},
[loadProfiles]
[loadProfiles],
);
const [runningProfiles, setRunningProfiles] = useState<Set<string>>(
new Set()
new Set(),
);
const runningProfilesRef = useRef<Set<string>>(new Set());
@@ -297,7 +300,7 @@ export default function Home() {
console.error("Failed to check browser status:", err);
}
},
[isClient]
[isClient],
);
const launchProfile = useCallback(
@@ -312,12 +315,12 @@ export default function Home() {
"is_browser_disabled_for_update",
{
browser: profile.browser,
}
},
);
if (isDisabled || isUpdating(profile.browser)) {
setError(
`${profile.browser} is currently being updated. Please wait for the update to complete.`
`${profile.browser} is currently being updated. Please wait for the update to complete.`,
);
return;
}
@@ -328,7 +331,7 @@ export default function Home() {
try {
const updatedProfile = await invoke<BrowserProfile>(
"launch_browser_profile",
{ profile }
{ profile },
);
await loadProfiles();
await checkBrowserStatus(updatedProfile);
@@ -337,7 +340,7 @@ export default function Home() {
setError(`Failed to launch browser: ${JSON.stringify(err)}`);
}
},
[loadProfiles, checkBrowserStatus, isUpdating, isClient]
[loadProfiles, checkBrowserStatus, isUpdating, isClient],
);
useEffect(() => {
@@ -376,7 +379,7 @@ export default function Home() {
setError(`Failed to delete profile: ${JSON.stringify(err)}`);
}
},
[loadProfiles]
[loadProfiles],
);
const handleRenameProfile = useCallback(
@@ -391,7 +394,7 @@ export default function Home() {
throw err;
}
},
[loadProfiles]
[loadProfiles],
);
const handleKillProfile = useCallback(
@@ -405,7 +408,7 @@ export default function Home() {
setError(`Failed to kill browser: ${JSON.stringify(err)}`);
}
},
[loadProfiles]
[loadProfiles],
);
// Don't render anything until we're on the client side to prevent hydration issues
@@ -551,7 +554,7 @@ export default function Home() {
isOpen={true}
onClose={() => {
setPendingUrls((prev) =>
prev.filter((u) => u.id !== pendingUrl.id)
prev.filter((u) => u.id !== pendingUrl.id),
);
}}
url={pendingUrl.url}
+2 -2
View File
@@ -60,10 +60,10 @@ export function ChangeVersionDialog({
if (profile && selectedVersion) {
// Check if this is a downgrade
const currentVersionIndex = availableVersions.findIndex(
(v) => v.tag_name === profile.version
(v) => v.tag_name === profile.version,
);
const selectedVersionIndex = availableVersions.findIndex(
(v) => v.tag_name === selectedVersion
(v) => v.tag_name === selectedVersion,
);
// If selected version has a higher index, it's older (downgrade)
+4 -4
View File
@@ -65,7 +65,7 @@ export function CreateProfileDialog({
>([]);
const [isCreating, setIsCreating] = useState(false);
const [existingProfiles, setExistingProfiles] = useState<BrowserProfile[]>(
[]
[],
);
// Proxy settings
@@ -120,7 +120,7 @@ export function CreateProfileDialog({
const loadSupportedBrowsers = async () => {
try {
const browsers = await invoke<BrowserTypeString[]>(
"get_supported_browsers"
"get_supported_browsers",
);
setSupportedBrowsers(browsers);
if (browsers.includes("mullvad-browser")) {
@@ -156,7 +156,7 @@ export function CreateProfileDialog({
// Check for duplicate names (case insensitive)
const isDuplicate = existingProfiles.some(
(profile) => profile.name.toLowerCase() === trimmedName.toLowerCase()
(profile) => profile.name.toLowerCase() === trimmedName.toLowerCase(),
);
if (isDuplicate) {
@@ -271,7 +271,7 @@ export function CreateProfileDialog({
{browser
.split("-")
.map(
(word) => word.charAt(0).toUpperCase() + word.slice(1)
(word) => word.charAt(0).toUpperCase() + word.slice(1),
)
.join(" ")}
</SelectItem>
+10 -10
View File
@@ -298,7 +298,7 @@ export function showLoadingToast(
id?: string;
description?: string;
duration?: number;
}
},
) {
return showToast({
type: "loading",
@@ -312,16 +312,16 @@ export function showDownloadToast(
version: string,
stage: "downloading" | "extracting" | "verifying" | "completed",
progress?: { percentage: number; speed?: string; eta?: string },
options?: { suppressCompletionToast?: boolean }
options?: { suppressCompletionToast?: boolean },
) {
const title =
stage === "completed"
? `${browserName} ${version} downloaded successfully!`
: stage === "downloading"
? `Downloading ${browserName} ${version}`
: stage === "extracting"
? `Extracting ${browserName} ${version}`
: `Verifying ${browserName} ${version}`;
? `Downloading ${browserName} ${version}`
: stage === "extracting"
? `Extracting ${browserName} ${version}`
: `Verifying ${browserName} ${version}`;
// Don't show completion toast if suppressed (for auto-update scenarios)
if (stage === "completed" && options?.suppressCompletionToast) {
@@ -349,7 +349,7 @@ export function showVersionUpdateToast(
found: number;
};
duration?: number;
}
},
) {
return showToast({
type: "version-update",
@@ -364,7 +364,7 @@ export function showFetchingToast(
id?: string;
description?: string;
duration?: number;
}
},
) {
return showToast({
type: "fetching",
@@ -382,7 +382,7 @@ export function showSuccessToast(
id?: string;
description?: string;
duration?: number;
}
},
) {
return showToast({
type: "success",
@@ -397,7 +397,7 @@ export function showErrorToast(
id?: string;
description?: string;
duration?: number;
}
},
) {
return showToast({
type: "error",
+11 -11
View File
@@ -101,7 +101,7 @@ export function ProfilesDataTable({
setSorting(newSorting);
updateSorting(newSorting);
},
[sorting, updateSorting, isClient]
[sorting, updateSorting, isClient],
);
const handleRename = async () => {
@@ -131,7 +131,7 @@ export function ProfilesDataTable({
const anyTorRunning =
isClient &&
data.some(
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name)
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name),
);
const shouldDisableTorStart =
isTorBrowser && !isRunning && anyTorRunning;
@@ -159,12 +159,12 @@ export function ProfilesDataTable({
{!isClient
? "Loading..."
: isRunning
? "Click to forcefully stop the browser"
: isBrowserUpdating
? `${profile.browser} is being updated. Please wait for the update to complete.`
: shouldDisableTorStart
? "Only one TOR browser instance can run at a time. Stop the running TOR browser first."
: "Click to launch the browser"}
? "Click to forcefully stop the browser"
: isBrowserUpdating
? `${profile.browser} is being updated. Please wait for the update to complete.`
: shouldDisableTorStart
? "Only one TOR browser instance can run at a time. Stop the running TOR browser first."
: "Click to launch the browser"}
</TooltipContent>
</Tooltip>
</div>
@@ -392,7 +392,7 @@ export function ProfilesDataTable({
},
},
],
[isClient, runningProfiles, isUpdating, data]
[isClient, runningProfiles, isUpdating, data],
);
const table = useReactTable({
@@ -420,7 +420,7 @@ export function ProfilesDataTable({
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
header.getContext(),
)}
</TableHead>
);
@@ -439,7 +439,7 @@ export function ProfilesDataTable({
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
cell.getContext(),
)}
</TableCell>
))}
+7 -7
View File
@@ -58,7 +58,7 @@ export function ProfileSelectorDialog({
setIsLoading(true);
try {
const profileList = await invoke<BrowserProfile[]>(
"list_browser_profiles"
"list_browser_profiles",
);
// Sort profiles by name
@@ -92,14 +92,14 @@ export function ProfileSelectorDialog({
const canUseProfileForLinks = (
profile: BrowserProfile,
allProfiles: BrowserProfile[],
runningProfiles: Set<string>
runningProfiles: Set<string>,
): boolean => {
const isRunning = runningProfiles.has(profile.name);
// For TOR browser: Check if any TOR browser is running
if (profile.browser === "tor-browser") {
const runningTorProfiles = allProfiles.filter(
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name)
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name),
);
// If no TOR browser is running, allow any TOR profile
@@ -126,7 +126,7 @@ export function ProfileSelectorDialog({
if (profile.browser === "tor-browser") {
const runningTorProfiles = profiles.filter(
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name)
(p) => p.browser === "tor-browser" && runningProfiles.has(p.name),
);
// If another TOR profile is running, this one is not available
@@ -192,7 +192,7 @@ export function ProfileSelectorDialog({
return canUseProfileForLinks(
selectedProfileData,
profiles,
runningProfiles
runningProfiles,
);
};
@@ -261,7 +261,7 @@ export function ProfileSelectorDialog({
const canUseForLinks = canUseProfileForLinks(
profile,
profiles,
runningProfiles
runningProfiles,
);
const tooltipContent = getProfileTooltipContent(profile);
@@ -281,7 +281,7 @@ export function ProfileSelectorDialog({
<div className="flex items-center gap-2">
{(() => {
const IconComponent = getBrowserIcon(
profile.browser
profile.browser,
);
return IconComponent ? (
<IconComponent className="h-4 w-4" />
+2 -2
View File
@@ -17,7 +17,7 @@ interface CustomThemeProviderProps {
function getSystemTheme(): string {
if (typeof window !== "undefined") {
const isDarkMode = window.matchMedia(
"(prefers-color-scheme: dark)"
"(prefers-color-scheme: dark)",
).matches;
return isDarkMode ? "dark" : "light";
}
@@ -39,7 +39,7 @@ export function CustomThemeProvider({ children }: CustomThemeProviderProps) {
const systemTheme = getSystemTheme();
console.log(
"First-time user detected, applying system theme:",
systemTheme
systemTheme,
);
// Save the detected theme as the default
+1 -1
View File
@@ -15,7 +15,7 @@ function Checkbox({
data-slot="checkbox"
className={cn(
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className
className,
)}
{...props}
>
+8 -8
View File
@@ -43,7 +43,7 @@ function DropdownMenuContent({
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
className,
)}
{...props}
/>
@@ -75,7 +75,7 @@ function DropdownMenuItem({
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
{...props}
/>
@@ -93,7 +93,7 @@ function DropdownMenuCheckboxItem({
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
checked={checked}
{...props}
@@ -129,7 +129,7 @@ function DropdownMenuRadioItem({
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
{...props}
>
@@ -156,7 +156,7 @@ function DropdownMenuLabel({
data-inset={inset}
className={cn(
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className
className,
)}
{...props}
/>
@@ -185,7 +185,7 @@ function DropdownMenuShortcut({
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground ml-auto text-xs tracking-widest",
className
className,
)}
{...props}
/>
@@ -212,7 +212,7 @@ function DropdownMenuSubTrigger({
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
className
className,
)}
{...props}
>
@@ -231,7 +231,7 @@ function DropdownMenuSubContent({
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
className
className,
)}
{...props}
/>
+6 -6
View File
@@ -38,7 +38,7 @@ function SelectTrigger({
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
className,
)}
{...props}
>
@@ -64,7 +64,7 @@ function SelectContent({
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
className,
)}
position={position}
{...props}
@@ -74,7 +74,7 @@ function SelectContent({
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1",
)}
>
{children}
@@ -108,7 +108,7 @@ function SelectItem({
data-slot="select-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
className,
)}
{...props}
>
@@ -144,7 +144,7 @@ function SelectScrollUpButton({
data-slot="select-scroll-up-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className
className,
)}
{...props}
>
@@ -162,7 +162,7 @@ function SelectScrollDownButton({
data-slot="select-scroll-down-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className
className,
)}
{...props}
>
+9 -9
View File
@@ -112,7 +112,7 @@ function UpdateNotificationComponent({
export function useUpdateNotifications() {
const [notifications, setNotifications] = useState<UpdateNotification[]>([]);
const [updatingBrowsers, setUpdatingBrowsers] = useState<Set<string>>(
new Set()
new Set(),
);
const [isClient, setIsClient] = useState(false);
@@ -126,7 +126,7 @@ export function useUpdateNotifications() {
try {
const updates = await invoke<UpdateNotification[]>(
"check_for_browser_updates"
"check_for_browser_updates",
);
setNotifications(updates);
@@ -145,7 +145,7 @@ export function useUpdateNotifications() {
// Dismiss all notifications for this browser first
const browserNotifications = notifications.filter(
(n) => n.browser === browser
(n) => n.browser === browser,
);
for (const notification of browserNotifications) {
toast.dismiss(notification.id);
@@ -164,7 +164,7 @@ export function useUpdateNotifications() {
if (isDownloaded) {
// Browser already exists, skip download and go straight to profile update
console.log(
`${browserDisplayName} ${newVersion} already exists, skipping download`
`${browserDisplayName} ${newVersion} already exists, skipping download`,
);
} else {
// Mark download as auto-update in the backend for toast suppression
@@ -186,7 +186,7 @@ export function useUpdateNotifications() {
{
browser,
newVersion,
}
},
);
// Show success message based on whether profiles were updated
@@ -252,7 +252,7 @@ export function useUpdateNotifications() {
});
}
},
[notifications, checkForUpdates]
[notifications, checkForUpdates],
);
const handleDismiss = useCallback(
@@ -267,7 +267,7 @@ export function useUpdateNotifications() {
console.error("Failed to dismiss notification:", error);
}
},
[checkForUpdates, isClient]
[checkForUpdates, isClient],
);
// Separate effect to show toasts when notifications change
@@ -288,11 +288,11 @@ export function useUpdateNotifications() {
),
{
id: notification.id,
duration: Infinity, // Persistent until user action
duration: Number.POSITIVE_INFINITY, // Persistent until user action
position: "top-right",
// Remove transparent styling to fix background issue
style: undefined,
}
},
);
});
}, [notifications, updatingBrowsers, handleUpdate, handleDismiss, isClient]);
+3 -3
View File
@@ -91,7 +91,7 @@ export function VersionSelector({
<CommandGroup>
{availableVersions.map((version) => {
const isDownloaded = downloadedVersions.includes(
version.tag_name
version.tag_name,
);
return (
<CommandItem
@@ -101,7 +101,7 @@ export function VersionSelector({
onVersionSelect(
currentValue === selectedVersion
? null
: currentValue
: currentValue,
);
setVersionPopoverOpen(false);
}}
@@ -111,7 +111,7 @@ export function VersionSelector({
"mr-2 h-4 w-4",
selectedVersion === version.tag_name
? "opacity-100"
: "opacity-0"
: "opacity-0",
)}
/>
<div className="flex items-center gap-2">
+4 -5
View File
@@ -115,11 +115,10 @@ export function VersionUpdateSettings() {
<AlertTitle>How it works</AlertTitle>
<AlertDescription className="text-xs">
Version information is checked automatically every 3 hours
<br />
New versions are added to the cache without removing old ones
<br />
When creating profiles or changing versions, you&apos;ll see how
many new versions were found
<br /> New versions are added to the cache without removing old
ones
<br /> When creating profiles or changing versions, you&apos;ll see
how many new versions were found
<br /> This keeps the app responsive while ensuring you have the
latest information
</AlertDescription>
+14 -14
View File
@@ -72,7 +72,7 @@ const isAlphaVersion = (version: string): boolean => {
export function useBrowserDownload() {
const [availableVersions, setAvailableVersions] = useState<GithubRelease[]>(
[]
[],
);
const [downloadedVersions, setDownloadedVersions] = useState<string[]>([]);
const [isDownloading, setIsDownloading] = useState(false);
@@ -128,7 +128,7 @@ export function useBrowserDownload() {
undefined,
{
suppressCompletionToast: isAutoUpdate,
}
},
);
setDownloadProgress(null);
}
@@ -167,7 +167,7 @@ export function useBrowserDownload() {
`Found ${progress.new_versions_found} new browser versions!`,
{
duration: 3000,
}
},
);
}
// Dismiss any update toasts
@@ -179,7 +179,7 @@ export function useBrowserDownload() {
});
toast.dismiss();
}
}
},
);
return () => {
@@ -224,7 +224,7 @@ export function useBrowserDownload() {
try {
const versionInfos = await invoke<BrowserVersionInfo[]>(
"fetch_browser_versions_cached_first",
{ browserStr }
{ browserStr },
);
// Convert BrowserVersionInfo to GithubRelease format for compatibility
@@ -234,7 +234,7 @@ export function useBrowserDownload() {
assets: [],
published_at: versionInfo.date,
is_alpha: versionInfo.is_prerelease,
})
}),
);
setAvailableVersions(githubReleases);
@@ -259,13 +259,13 @@ export function useBrowserDownload() {
// Get versions with new count info and cached detailed info
const result = await invoke<BrowserVersionsResult>(
"fetch_browser_versions_with_count_cached_first",
{ browserStr }
{ browserStr },
);
// Get detailed version info for compatibility
const versionInfos = await invoke<BrowserVersionInfo[]>(
"fetch_browser_versions_cached_first",
{ browserStr }
{ browserStr },
);
// Convert BrowserVersionInfo to GithubRelease format for compatibility
@@ -275,7 +275,7 @@ export function useBrowserDownload() {
assets: [],
published_at: versionInfo.date,
is_alpha: versionInfo.is_prerelease,
})
}),
);
setAvailableVersions(githubReleases);
@@ -287,7 +287,7 @@ export function useBrowserDownload() {
{
duration: 3000,
description: `Total available: ${result.total_versions_count} versions`,
}
},
);
}
@@ -307,7 +307,7 @@ export function useBrowserDownload() {
try {
const downloadedVersions = await invoke<string[]>(
"get_downloaded_browser_versions",
{ browserStr }
{ browserStr },
);
setDownloadedVersions(downloadedVersions);
return downloadedVersions;
@@ -321,7 +321,7 @@ export function useBrowserDownload() {
async (
browserStr: string,
version: string,
suppressNotifications: boolean = false
suppressNotifications = false,
) => {
const browserName = getBrowserDisplayName(browserStr);
setIsDownloading(true);
@@ -345,14 +345,14 @@ export function useBrowserDownload() {
setIsDownloading(false);
}
},
[loadDownloadedVersions]
[loadDownloadedVersions],
);
const isVersionDownloaded = useCallback(
(version: string) => {
return downloadedVersions.includes(version);
},
[downloadedVersions]
[downloadedVersions],
);
return {
+3 -3
View File
@@ -15,7 +15,7 @@ export function useTableSorting() {
const loadSettings = async () => {
try {
const settings = await invoke<TableSortingSettings>(
"get_table_sorting_settings"
"get_table_sorting_settings",
);
setSortingSettings(settings);
} catch (error) {
@@ -39,7 +39,7 @@ export function useTableSorting() {
console.error("Failed to save table sorting settings:", error);
}
},
[]
[],
);
// Convert our settings to tanstack table sorting format
@@ -67,7 +67,7 @@ export function useTableSorting() {
void saveSortingSettings(newSettings);
}
},
[saveSortingSettings, isLoaded]
[saveSortingSettings, isLoaded],
);
return {
+12 -12
View File
@@ -61,7 +61,7 @@ export function useVersionUpdater() {
total: progress.total_browsers,
found: progress.new_versions_found,
},
}
},
);
} else {
showLoadingToast("Starting version update check...", {
@@ -81,7 +81,7 @@ export function useVersionUpdater() {
duration: 4000,
description:
"Version information has been updated in the background",
}
},
);
} else {
toast.success("No new browser versions found", {
@@ -103,7 +103,7 @@ export function useVersionUpdater() {
description: "Check your internet connection and try again",
});
}
}
},
);
return () => {
@@ -130,7 +130,7 @@ export function useVersionUpdater() {
const loadUpdateStatus = useCallback(async () => {
try {
const [lastUpdate, timeUntilNext] = await invoke<[number | null, number]>(
"get_version_update_status"
"get_version_update_status",
);
setLastUpdateTime(lastUpdate);
setTimeUntilNextUpdate(timeUntilNext);
@@ -143,18 +143,18 @@ export function useVersionUpdater() {
try {
setIsUpdating(true);
const results = await invoke<BackgroundUpdateResult[]>(
"trigger_manual_version_update"
"trigger_manual_version_update",
);
const totalNewVersions = results.reduce(
(sum, result) => sum + result.new_versions_count,
0
0,
);
const successfulUpdates = results.filter(
(r) => r.updated_successfully
(r) => r.updated_successfully,
).length;
const failedUpdates = results.filter(
(r) => !r.updated_successfully
(r) => !r.updated_successfully,
).length;
if (failedUpdates > 0) {
@@ -194,7 +194,7 @@ export function useVersionUpdater() {
try {
const result = await invoke<BrowserVersionsResult>(
"fetch_browser_versions_with_count",
{ browserStr }
{ browserStr },
);
// Show notification about new versions if any were found
@@ -205,7 +205,7 @@ export function useVersionUpdater() {
{
duration: 3000,
description: `Total available: ${result.total_versions_count} versions`,
}
},
);
}
@@ -215,7 +215,7 @@ export function useVersionUpdater() {
throw error;
}
},
[]
[],
);
const formatTimeUntilUpdate = useCallback((seconds: number): string => {
@@ -251,7 +251,7 @@ export function useVersionUpdater() {
return "Just now";
}
},
[]
[],
);
return {