From 545c518a5546176b19deabce9ee826393237c213 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:58:55 +0400 Subject: [PATCH] feat: don't spam update notification, show more concise toasts, don't fetch unsupported browser updates --- src-tauri/Info.plist | 50 +++++++++++----------- src-tauri/src/auto_updater.rs | 37 +++++++++++++--- src-tauri/src/settings_manager.rs | 4 +- src-tauri/src/version_updater.rs | 20 ++++++++- src/components/custom-toast.tsx | 43 +++++++++++-------- src/components/settings-dialog.tsx | 17 +++++--- src/components/version-update-settings.tsx | 24 +++++------ src/hooks/use-browser-download.ts | 43 +++++++++++++------ src/hooks/use-version-updater.ts | 44 +++++++++---------- src/lib/toast-utils.ts | 26 +++++++++++ 10 files changed, 200 insertions(+), 108 deletions(-) diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist index a6ea632..d9609e3 100644 --- a/src-tauri/Info.plist +++ b/src-tauri/Info.plist @@ -29,30 +29,30 @@ CFBundleDocumentTypes - CFBundleTypeName - HTML document - CFBundleTypeRole - Viewer - LSHandlerRank - Default - LSItemContentTypes - - public.html - public.xhtml - - - -CFBundleURLTypes - - - CFBundleURLName - Web site URL - CFBundleURLSchemes - - http - https - - - + CFBundleTypeName + HTML document + CFBundleTypeRole + Viewer + LSHandlerRank + Default + LSItemContentTypes + + public.html + public.xhtml + + + + CFBundleURLTypes + + + CFBundleURLName + Web site URL + CFBundleURLSchemes + + http + https + + + \ No newline at end of file diff --git a/src-tauri/src/auto_updater.rs b/src-tauri/src/auto_updater.rs index 6a30701..18b5fc8 100644 --- a/src-tauri/src/auto_updater.rs +++ b/src-tauri/src/auto_updater.rs @@ -54,23 +54,32 @@ impl AutoUpdater { return Ok(Vec::new()); } + let mut notifications = Vec::new(); + let mut browser_versions: HashMap> = HashMap::new(); + + // Group profiles by browser let profiles = self .browser_runner .list_profiles() .map_err(|e| format!("Failed to list profiles: {e}"))?; - let mut notifications = Vec::new(); - let mut browser_versions: HashMap> = HashMap::new(); - - // Group profiles by browser type let mut browser_profiles: HashMap> = HashMap::new(); + for profile in profiles { + // Only check supported browsers + if !self + .version_service + .is_browser_supported(&profile.browser) + .unwrap_or(false) + { + continue; + } + browser_profiles .entry(profile.browser.clone()) .or_default() .push(profile); } - // Check each browser type for (browser, profiles) in browser_profiles { // Get cached versions first, then try to fetch if needed let versions = if let Some(cached) = self @@ -97,7 +106,23 @@ impl AutoUpdater { // Check each profile for updates for profile in profiles { if let Some(update) = self.check_profile_update(&profile, &versions)? { - notifications.push(update); + // Apply chromium threshold logic + if browser == "chromium" { + // For chromium, only show notifications if there are 100+ new versions + // Count how many versions are newer than the current profile version + let newer_versions_count = versions + .iter() + .filter(|v| self.is_version_newer(&v.version, &profile.version)) + .count(); + + if newer_versions_count >= 100 { + notifications.push(update); + } else { + println!("Skipping chromium update notification: only {newer_versions_count} new versions (need 100+)"); + } + } else { + notifications.push(update); + } } } } diff --git a/src-tauri/src/settings_manager.rs b/src-tauri/src/settings_manager.rs index c9123d6..586dc32 100644 --- a/src-tauri/src/settings_manager.rs +++ b/src-tauri/src/settings_manager.rs @@ -224,12 +224,12 @@ pub async fn clear_all_version_cache_and_refetch() -> Result<(), String> { .clear_all_cache() .map_err(|e| format!("Failed to clear version cache: {e}"))?; - // Trigger auto-fetch for all supported browsers + // Trigger auto-fetch for only supported browsers let service = BrowserVersionService::new(); let supported_browsers = service.get_supported_browsers(); for browser in supported_browsers { - // Start background fetch for each browser (don't wait for completion) + // Start background fetch for each supported browser (don't wait for completion) let service_clone = BrowserVersionService::new(); let browser_clone = browser.clone(); tokio::spawn(async move { diff --git a/src-tauri/src/version_updater.rs b/src-tauri/src/version_updater.rs index bd7e9a3..bb97bef 100644 --- a/src-tauri/src/version_updater.rs +++ b/src-tauri/src/version_updater.rs @@ -259,7 +259,7 @@ impl VersionUpdater { ) -> Result, Box> { println!("Starting background version update for all browsers"); - let browsers = [ + let all_browsers = [ "firefox", "firefox-developer", "mullvad-browser", @@ -269,10 +269,28 @@ impl VersionUpdater { "tor-browser", ]; + // Filter browsers to only include those supported on the current platform + let browsers: Vec<&str> = all_browsers + .iter() + .filter(|browser| { + self + .version_service + .is_browser_supported(browser) + .unwrap_or(false) + }) + .copied() + .collect(); + let total_browsers = browsers.len(); let mut results = Vec::new(); let mut total_new_versions = 0; + println!( + "Updating {} supported browsers (filtered from {} total)", + browsers.len(), + all_browsers.len() + ); + // Emit start event let progress = VersionUpdateProgress { current_browser: "".to_string(), diff --git a/src/components/custom-toast.tsx b/src/components/custom-toast.tsx index 0fd7c69..9d451e2 100644 --- a/src/components/custom-toast.tsx +++ b/src/components/custom-toast.tsx @@ -90,6 +90,7 @@ interface VersionUpdateToastProps extends BaseToastProps { current: number; total: number; found: number; + current_browser?: string; }; } @@ -151,7 +152,7 @@ export function UnifiedToast(props: ToastProps) { const progress = "progress" in props ? props.progress : undefined; return ( -
+
{getToastIcon(type, stage)}

@@ -181,26 +182,30 @@ export function UnifiedToast(props: ToastProps) { )} {/* Version update progress */} - {type === "version-update" && progress && "found" in progress && ( -

-

- {progress.found} new versions found so far -

-
-
-
+ {type === "version-update" && + progress && + "current_browser" in progress && ( +
+

+ {progress.current_browser && ( + <>Looking for updates for {progress.current_browser} + )} +

+
+
+
+
+ + {progress.current}/{progress.total} +
- - {progress.current}/{progress.total} -
-
- )} + )} {/* Twilight update progress */} {type === "twilight-update" && ( diff --git a/src/components/settings-dialog.tsx b/src/components/settings-dialog.tsx index dad9346..68d311f 100644 --- a/src/components/settings-dialog.tsx +++ b/src/components/settings-dialog.tsx @@ -21,7 +21,7 @@ import { } from "@/components/ui/select"; import { usePermissions } from "@/hooks/use-permissions"; import type { PermissionType } from "@/hooks/use-permissions"; -import { showSuccessToast } from "@/lib/toast-utils"; +import { showErrorToast, showSuccessToast } from "@/lib/toast-utils"; import { invoke } from "@tauri-apps/api/core"; import { useTheme } from "next-themes"; import { useCallback, useEffect, useState } from "react"; @@ -210,11 +210,16 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) { await invoke("clear_all_version_cache_and_refetch"); showSuccessToast("Cache cleared successfully", { description: - "All browser version cache has been cleared and browsers are being refreshed", + "All browser version cache has been cleared and browsers are being refreshed.", duration: 4000, }); } catch (error) { console.error("Failed to clear cache:", error); + showErrorToast("Failed to clear cache", { + description: + error instanceof Error ? error.message : "Unknown error occurred", + duration: 4000, + }); } finally { setIsClearingCache(false); } @@ -237,9 +242,9 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) { const getPermissionIcon = (type: PermissionType) => { switch (type) { case "microphone": - return ; + return ; case "camera": - return ; + return ; } }; @@ -255,7 +260,7 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) { const getStatusBadge = (isGranted: boolean) => { if (isGranted) { return ( - + Granted ); @@ -436,7 +441,7 @@ export function SettingsDialog({ isOpen, onClose }: SettingsDialogProps) { {permissions.map((permission) => (
{getPermissionIcon(permission.permission_type)} diff --git a/src/components/version-update-settings.tsx b/src/components/version-update-settings.tsx index 7f2cea5..0bbf250 100644 --- a/src/components/version-update-settings.tsx +++ b/src/components/version-update-settings.tsx @@ -31,8 +31,8 @@ export function VersionUpdateSettings() { return ( - - + + Background Version Updates @@ -44,8 +44,8 @@ export function VersionUpdateSettings() { {/* Current Status */}
-
- +
+ Last Update
@@ -54,8 +54,8 @@ export function VersionUpdateSettings() {
-
- +
+ Next Update
@@ -69,16 +69,14 @@ export function VersionUpdateSettings() { {/* Progress indicator */} {isUpdating && updateProgress && ( - + Updating Browser Versions {updateProgress.current_browser ? ( <> - Checking {updateProgress.current_browser} ( + Looking for updates for {updateProgress.current_browser} ( {updateProgress.completed_browsers}/ {updateProgress.total_browsers}) -
- {updateProgress.new_versions_found} new versions found so far ) : ( "Starting version update..." @@ -88,7 +86,7 @@ export function VersionUpdateSettings() { )} {/* Manual update button */} -
+
Manual Update
@@ -104,14 +102,14 @@ export function VersionUpdateSettings() { size="sm" disabled={isUpdating} > - + {isUpdating ? "Updating..." : "Check Now"}
{/* Information about background updates */} - + How it works • Version information is checked automatically every 3 hours diff --git a/src/hooks/use-browser-download.ts b/src/hooks/use-browser-download.ts index 9bc5fd9..f0f70f8 100644 --- a/src/hooks/use-browser-download.ts +++ b/src/hooks/use-browser-download.ts @@ -5,11 +5,11 @@ import { showErrorToast, showFetchingToast, showSuccessToast, + showUnifiedVersionUpdateToast, } from "@/lib/toast-utils"; import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import { useCallback, useEffect, useState } from "react"; -import { toast } from "sonner"; interface GithubRelease { tag_name: string; @@ -137,31 +137,50 @@ export function useBrowserDownload() { if (progress.status === "updating") { setIsUpdatingVersions(true); - if (progress.current_browser) { - const browserName = getBrowserDisplayName(progress.current_browser); - showFetchingToast(browserName, { - id: `version-update-${progress.current_browser}`, - description: "Fetching latest release information...", - }); - } + + // Show unified progress toast + const currentBrowserName = progress.current_browser + ? getBrowserDisplayName(progress.current_browser) + : undefined; + + showUnifiedVersionUpdateToast("Checking for browser updates...", { + description: currentBrowserName + ? `Fetching ${currentBrowserName} release information...` + : "Initializing version check...", + progress: { + current: progress.completed_browsers, + total: progress.total_browsers, + found: progress.new_versions_found, + current_browser: currentBrowserName, + }, + }); } else if (progress.status === "completed") { setIsUpdatingVersions(false); + dismissToast("unified-version-update"); + if (progress.new_versions_found > 0) { showSuccessToast( `Found ${progress.new_versions_found} new browser versions!`, { - duration: 3000, + duration: 4000, + description: + "Version information has been updated in the background", }, ); + } else { + showSuccessToast("No new browser versions found", { + duration: 3000, + description: "All browser versions are up to date", + }); } - // Dismiss any update toasts - toast.dismiss(); } else if (progress.status === "error") { setIsUpdatingVersions(false); + dismissToast("unified-version-update"); + showErrorToast("Failed to check for new versions", { duration: 4000, + description: "Check your internet connection and try again", }); - toast.dismiss(); } }, ); diff --git a/src/hooks/use-version-updater.ts b/src/hooks/use-version-updater.ts index 1a184ba..6c50810 100644 --- a/src/hooks/use-version-updater.ts +++ b/src/hooks/use-version-updater.ts @@ -1,5 +1,5 @@ import { getBrowserDisplayName } from "@/lib/browser-utils"; -import { showLoadingToast, showVersionUpdateToast } from "@/lib/toast-utils"; +import { dismissToast, showUnifiedVersionUpdateToast } from "@/lib/toast-utils"; import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import { useCallback, useEffect, useState } from "react"; @@ -46,34 +46,31 @@ export function useVersionUpdater() { if (progress.status === "updating") { setIsUpdating(true); - if (progress.current_browser) { - const browserName = getBrowserDisplayName(progress.current_browser); - showVersionUpdateToast( - `Downloading release information for ${browserName}`, - { - id: "version-update-progress", - progress: { - current: progress.completed_browsers + 1, - total: progress.total_browsers, - found: progress.new_versions_found, - }, - }, - ); - } else { - showLoadingToast("Starting version update check...", { - id: "version-update-progress", - description: "Initializing browser version check...", - }); - } + // Show unified progress toast + const currentBrowserName = progress.current_browser + ? getBrowserDisplayName(progress.current_browser) + : undefined; + + showUnifiedVersionUpdateToast("Checking for browser updates...", { + description: currentBrowserName + ? `Fetching ${currentBrowserName} release information...` + : "Initializing version check...", + progress: { + current: progress.completed_browsers, + total: progress.total_browsers, + found: progress.new_versions_found, + current_browser: currentBrowserName, + }, + }); } else if (progress.status === "completed") { setIsUpdating(false); setUpdateProgress(null); + dismissToast("unified-version-update"); if (progress.new_versions_found > 0) { toast.success( `Found ${progress.new_versions_found} new browser versions!`, { - id: "version-update-progress", duration: 4000, description: "Version information has been updated in the background", @@ -81,7 +78,6 @@ export function useVersionUpdater() { ); } else { toast.success("No new browser versions found", { - id: "version-update-progress", duration: 3000, description: "All browser versions are up to date", }); @@ -92,9 +88,9 @@ export function useVersionUpdater() { } else if (progress.status === "error") { setIsUpdating(false); setUpdateProgress(null); + dismissToast("unified-version-update"); toast.error("Failed to update browser versions", { - id: "version-update-progress", duration: 4000, description: "Check your internet connection and try again", }); @@ -159,7 +155,7 @@ export function useVersionUpdater() { duration: 5000, }); } else if (totalNewVersions > 0) { - toast.success(`Found ${totalNewVersions} new browser versions!`, { + toast.success("Browser versions updated successfully", { description: `Updated ${successfulUpdates} browsers successfully`, duration: 4000, }); diff --git a/src/lib/toast-utils.ts b/src/lib/toast-utils.ts index ad75cdc..23a058d 100644 --- a/src/lib/toast-utils.ts +++ b/src/lib/toast-utils.ts @@ -43,6 +43,7 @@ export interface VersionUpdateToastProps extends BaseToastProps { current: number; total: number; found: number; + current_browser?: string; }; } @@ -214,6 +215,7 @@ export function showVersionUpdateToast( current: number; total: number; found: number; + current_browser?: string; }; duration?: number; }, @@ -301,3 +303,27 @@ export function dismissToast(id: string) { export function dismissAllToasts() { sonnerToast.dismiss(); } + +// Add a specific function for unified version update progress +export function showUnifiedVersionUpdateToast( + title: string, + options?: { + id?: string; + description?: string; + progress?: { + current: number; + total: number; + found: number; + current_browser?: string; + }; + duration?: number; + }, +) { + return showToast({ + type: "version-update", + title, + id: "unified-version-update", + duration: Number.POSITIVE_INFINITY, // Keep showing until completed + ...options, + }); +}