diff --git a/frogpilot/assets/download_functions.py b/frogpilot/assets/download_functions.py index ac1b28962..bf488c466 100644 --- a/frogpilot/assets/download_functions.py +++ b/frogpilot/assets/download_functions.py @@ -29,12 +29,12 @@ def check_github_rate_limit(): print(f"Error checking GitHub rate limit: {error}") return False -def download_file(cancel_param, destination, progress_param, url, download_param, params_memory): +def download_file(cancel_param, destination, progress_param, url, download_param, params_memory, allow_unknown_size=False): try: destination.parent.mkdir(parents=True, exist_ok=True) total_size = get_remote_file_size(url) - if total_size == 0: + if total_size == 0 and not allow_unknown_size: if not url.endswith(".gif"): handle_error(None, "Download invalid...", "Download invalid...", download_param, progress_param, params_memory) return @@ -56,10 +56,13 @@ def download_file(cancel_param, destination, progress_param, url, download_param temp_file.write(chunk) downloaded_size += len(chunk) - progress = (downloaded_size / total_size) * 100 - if progress != 100: - params_memory.put(progress_param, f"{progress:.0f}%") - else: + if total_size > 0: + progress = (downloaded_size / total_size) * 100 + if progress != 100: + params_memory.put(progress_param, f"{progress:.0f}%") + else: + params_memory.put(progress_param, "Verifying authenticity...") + elif downloaded_size > 0: params_memory.put(progress_param, "Verifying authenticity...") temp_file_path.rename(destination) @@ -104,9 +107,18 @@ def handle_request_error(error, destination, download_param, progress_param, par error_message = error_map.get(type(error), "Unexpected error") handle_error(destination, f"Failed: {error_message}", error, download_param, progress_param, params_memory) -def verify_download(file_path, url): +def verify_download(file_path, url, allow_unknown_size=False): remote_file_size = get_remote_file_size(url) + if remote_file_size == 0 and allow_unknown_size: + if not file_path.is_file(): + print(f"File not found: {file_path}") + return False + if file_path.stat().st_size == 0: + print(f"File is empty: {file_path}") + return False + return True + if remote_file_size == 0: print(f"Error fetching remote size for {file_path}") return False diff --git a/frogpilot/assets/theme_manager.py b/frogpilot/assets/theme_manager.py index c674e814f..d9c6a4375 100644 --- a/frogpilot/assets/theme_manager.py +++ b/frogpilot/assets/theme_manager.py @@ -95,14 +95,14 @@ class ThemeManager: shutil.copy2(steering_wheel_image_path, steering_wheel_save_path) default_boot_logo_path = Path(__file__).parent / "other_images/frogpilot_boot_logo.png" - for default_name in ("starpilot.png", "frogpilot.png"): - boot_logo_save_path = THEME_SAVE_PATH / "bootlogos" / default_name - boot_logo_save_path.parent.mkdir(parents=True, exist_ok=True) - if not boot_logo_save_path.exists(): - shutil.copy2(default_boot_logo_path, boot_logo_save_path) + boot_logo_save_path = THEME_SAVE_PATH / "bootlogos/starpilot.png" + boot_logo_save_path.parent.mkdir(parents=True, exist_ok=True) + if not boot_logo_save_path.exists(): + shutil.copy2(default_boot_logo_path, boot_logo_save_path) def download_theme(self, theme_component, theme_name, asset_param, frogpilot_toggles): self.downloading_theme = True + allow_unknown_size = theme_component in {"boot_logos", "steering_wheels"} repo_url = get_repository_url() if not repo_url: @@ -134,7 +134,7 @@ class ThemeManager: delete_file(theme_path) print(f"Downloading theme from GitHub: {theme_name}") - download_file(CANCEL_DOWNLOAD_PARAM, theme_path, DOWNLOAD_PROGRESS_PARAM, theme_url, asset_param, params_memory) + download_file(CANCEL_DOWNLOAD_PARAM, theme_path, DOWNLOAD_PROGRESS_PARAM, theme_url, asset_param, params_memory, allow_unknown_size=allow_unknown_size) if params_memory.get_bool(CANCEL_DOWNLOAD_PARAM): delete_file(theme_path) @@ -143,7 +143,7 @@ class ThemeManager: self.downloading_theme = False return - if verify_download(theme_path, theme_url): + if verify_download(theme_path, theme_url, allow_unknown_size=allow_unknown_size): print(f"Theme {theme_name} downloaded and verified successfully from GitHub!") self.update_theme_size(theme_component, theme_name, theme_path.stat().st_size) @@ -348,6 +348,7 @@ class ThemeManager: } def handle_verification_failure(self, extension, theme_component, theme_name, asset_param, theme_path, download_path, frogpilot_toggles): + allow_unknown_size = theme_component in {"boot_logos", "steering_wheels"} if theme_component == "boot_logos": download_link = f"{GITLAB_URL}/Themes/bootlogo/{theme_name}" elif theme_component == "distance_icons": @@ -361,9 +362,9 @@ class ThemeManager: theme_url = download_link + extension print(f"Downloading theme from GitLab: {theme_name}") - download_file(CANCEL_DOWNLOAD_PARAM, theme_path, DOWNLOAD_PROGRESS_PARAM, theme_url, asset_param, params_memory) + download_file(CANCEL_DOWNLOAD_PARAM, theme_path, DOWNLOAD_PROGRESS_PARAM, theme_url, asset_param, params_memory, allow_unknown_size=allow_unknown_size) - if verify_download(theme_path, theme_url): + if verify_download(theme_path, theme_url, allow_unknown_size=allow_unknown_size): print(f"Theme {theme_name} downloaded and verified successfully from GitLab!") self.update_theme_size(theme_component, theme_name, theme_path.stat().st_size) diff --git a/frogpilot/ui/qt/offroad/theme_settings.cc b/frogpilot/ui/qt/offroad/theme_settings.cc index fe10dc693..a3e6f9581 100644 --- a/frogpilot/ui/qt/offroad/theme_settings.cc +++ b/frogpilot/ui/qt/offroad/theme_settings.cc @@ -256,7 +256,8 @@ FrogPilotThemesPanel::FrogPilotThemesPanel(FrogPilotSettingsWindow *parent) : Fr } else if (param == "BootLogo") { manageBootLogosButton = new FrogPilotButtonsControl(title, desc, icon, {tr("DELETE"), tr("DOWNLOAD"), tr("SELECT")}); QObject::connect(manageBootLogosButton, &FrogPilotButtonsControl::buttonClicked, [this](int id) { - QStringList bootLogos = getThemeList(false, QDir(bootLogosDirectory.path()), "", "BootLogo", params); + // Show all downloaded boot logos, including the currently selected one. + QStringList bootLogos = getThemeList(true, QDir(bootLogosDirectory.path()), "", "BootLogo", params); if (id == 0) { QString bootLogoToDelete = MultiOptionDialog::getSelection(tr("Select a boot logo to delete"), bootLogos, "", this);