diff --git a/steam_workshop_gui.py b/steam_workshop_gui.py index 7c10d11..ac31d04 100644 --- a/steam_workshop_gui.py +++ b/steam_workshop_gui.py @@ -2808,7 +2808,7 @@ def show_blocking_update_dialog(root, update_checker, release_info): # Calculate window size and center it window_width = 600 - window_height = 500 + window_height = 600 # Increased height to accommodate buttons # Get screen dimensions screen_width = update_window.winfo_screenwidth() @@ -2825,7 +2825,7 @@ def show_blocking_update_dialog(root, update_checker, release_info): text="🔄 Update Required", fg='#ff6b6b', bg='#2b2b2b', font=('Arial', 20, 'bold')) - title_label.pack(pady=30) + title_label.pack(pady=20) # Message message_label = tk.Label(update_window, @@ -2836,7 +2836,7 @@ def show_blocking_update_dialog(root, update_checker, release_info): # Version info version_frame = tk.Frame(update_window, bg='#2b2b2b') - version_frame.pack(pady=20) + version_frame.pack(pady=15) current_label = tk.Label(version_frame, text=f"Current Version: {update_checker.current_version}", @@ -2856,14 +2856,14 @@ def show_blocking_update_dialog(root, update_checker, release_info): text="What's New:", fg='white', bg='#2b2b2b', font=('Arial', 14, 'bold')) - notes_label.pack(pady=(30, 10)) + notes_label.pack(pady=(20, 10)) # Create scrollable text widget for release notes notes_frame = tk.Frame(update_window, bg='#2b2b2b') - notes_frame.pack(fill='both', expand=True, padx=40, pady=(0, 20)) + notes_frame.pack(fill='both', expand=True, padx=40, pady=(0, 10)) notes_text = tk.Text(notes_frame, - height=8, + height=6, # Reduced height to make room for buttons bg='#404040', fg='#ffffff', font=('Arial', 11), wrap=tk.WORD, @@ -2883,14 +2883,154 @@ def show_blocking_update_dialog(root, update_checker, release_info): notes_text.insert('1.0', release_info['body']) notes_text.config(state='disabled') - # Buttons + # Buttons - fixed at bottom button_frame = tk.Frame(update_window, bg='#2b2b2b') - button_frame.pack(pady=30) + button_frame.pack(side='bottom', pady=20) # Pack at bottom with padding - def download_and_exit(): - """Open download page and exit the application""" + def auto_update(): + """Download and install the update automatically""" + try: + # Disable buttons during download + auto_btn.config(state='disabled', text='Downloading...') + download_btn.config(state='disabled') + exit_btn.config(state='disabled') + + # Update the window to show progress + update_window.update() + + # Start download in a separate thread + import threading + threading.Thread(target=perform_auto_update, daemon=True).start() + + except Exception as e: + print(f"Auto update failed: {e}") + # Re-enable buttons on error + auto_btn.config(state='normal', text='Auto Update') + download_btn.config(state='normal') + exit_btn.config(state='normal') + + def perform_auto_update(): + """Perform the actual auto update process""" + try: + import requests + import tempfile + import shutil + import subprocess + import sys + + # Find the EXE asset in the release + exe_asset = None + for asset in release_info.get('assets', []): + if asset.get('name', '').endswith('.exe'): + exe_asset = asset + break + + if not exe_asset: + raise Exception("No EXE file found in release assets") + + download_url = exe_asset.get('browser_download_url') + if not download_url: + raise Exception("No download URL found for EXE asset") + + # Update status + root.after(0, lambda: auto_btn.config(text='Downloading...')) + + # Download the new EXE + response = requests.get(download_url, stream=True) + response.raise_for_status() + + # Save to temporary file + with tempfile.NamedTemporaryFile(delete=False, suffix='.exe') as temp_file: + temp_path = temp_file.name + for chunk in response.iter_content(chunk_size=8192): + temp_file.write(chunk) + + # Get current executable path + if getattr(sys, 'frozen', False): + # Running as PyInstaller bundle + current_exe = sys.executable + else: + # Running as script - for testing + current_exe = sys.argv[0] + + # Update status + root.after(0, lambda: auto_btn.config(text='Installing...')) + + # Get configuration + from update_config import get_update_config + config = get_update_config() + auto_restart = config.get("auto_restart_after_update", True) + + # Create a batch script to replace the executable and optionally restart + if auto_restart: + restart_command = f'start "" /B "{current_exe}"' + restart_message = "Starting new version..." + else: + restart_command = 'echo Please manually start the application.' + restart_message = "Please manually start the updated application." + + batch_script = f'''@echo off +echo Updating Progression Loader... +timeout /t 3 /nobreak >nul + +REM Replace the executable +move "{temp_path}" "{current_exe}" +if errorlevel 1 ( + echo Failed to replace executable + pause + exit /b 1 +) + +echo Update complete! {restart_message} +timeout /t 1 /nobreak >nul + +REM Start the new executable (if configured) +{restart_command} + +REM Clean up this batch file +timeout /t 2 /nobreak >nul +del "%~f0" +''' + + # Write batch script to temp file + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.bat') as batch_file: + batch_file.write(batch_script) + batch_path = batch_file.name + + # Update status + root.after(0, lambda: auto_btn.config(text='Restarting...')) + + # Show success message + root.after(0, lambda: tk.messagebox.showinfo( + "Update Complete", + "Update downloaded successfully!\nThe application will restart automatically.", + parent=update_window + )) + + # Execute the batch script and exit + subprocess.Popen([batch_path], shell=True) + + # Exit the current application + root.after(2000, root.quit) + + except Exception as e: + print(f"Auto update failed: {e}") + # Re-enable buttons on error + root.after(0, lambda: auto_btn.config(state='normal', text='Auto Update')) + root.after(0, lambda: download_btn.config(state='normal')) + root.after(0, lambda: exit_btn.config(state='normal')) + + # Show error message + root.after(0, lambda: tk.messagebox.showerror( + "Auto Update Failed", + f"Failed to automatically update:\n{str(e)}\n\nPlease use 'Download Page' to update manually.", + parent=update_window + )) + + def download_page(): + """Open the release download page""" webbrowser.open(release_info['html_url']) - print("Please download and install the update, then restart the application.") + print("Please download and install the update manually, then restart the application.") root.quit() # Exit the entire application def exit_app(): @@ -2898,17 +3038,27 @@ def show_blocking_update_dialog(root, update_checker, release_info): print("Application cannot continue without updating.") root.quit() - # Download Update button (primary action) + # Auto Update button (primary action) + auto_btn = tk.Button(button_frame, + text="Auto Update", + command=auto_update, + bg='#4ecdc4', fg='white', + font=('Arial', 14, 'bold'), + padx=30, pady=10, + cursor='hand2') + auto_btn.pack(side='left', padx=10) + + # Download Page button (secondary action) download_btn = tk.Button(button_frame, - text="Download Update & Exit", - command=download_and_exit, - bg='#4ecdc4', fg='white', - font=('Arial', 14, 'bold'), - padx=30, pady=10, + text="Download Page", + command=download_page, + bg='#45b7d1', fg='white', + font=('Arial', 12), + padx=20, pady=10, cursor='hand2') download_btn.pack(side='left', padx=10) - # Exit button (secondary action) + # Exit button (tertiary action) exit_btn = tk.Button(button_frame, text="Exit Application", command=exit_app, @@ -2921,8 +3071,8 @@ def show_blocking_update_dialog(root, update_checker, release_info): # Handle window close (same as exit) update_window.protocol("WM_DELETE_WINDOW", exit_app) - # Focus on the download button - download_btn.focus_set() + # Focus on the auto update button + auto_btn.focus_set() print("Blocking update dialog shown - app will not continue until user updates") diff --git a/update_config.py b/update_config.py index 0e52a6b..cd1f386 100644 --- a/update_config.py +++ b/update_config.py @@ -5,7 +5,7 @@ Configuration settings for the update checker # Update checker configuration UPDATE_CONFIG = { # Current version of the application - "current_version": "0.0.1", + "current_version": "0.0.3", # Repository information "repo_owner": "HRiggs", @@ -21,6 +21,9 @@ UPDATE_CONFIG = { # Whether updates are required (blocks app if true) "updates_required": True, + # Whether to auto-restart after successful update + "auto_restart_after_update": True, + # Whether to include pre-releases in update checks "include_prereleases": True,