Removal OF files
This commit is contained in:
@@ -1,344 +0,0 @@
|
||||
"""
|
||||
Update Dialog for UmamusumeCardManager
|
||||
Provides a modal dialog for the update process.
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, messagebox, scrolledtext
|
||||
import threading
|
||||
import webbrowser
|
||||
from typing import Optional, Callable
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from updater.update_checker import check_for_updates, download_update, apply_update, get_current_version
|
||||
from gui.theme import (
|
||||
BG_DARK, BG_DARKEST, BG_MEDIUM, BG_LIGHT, BG_HIGHLIGHT,
|
||||
ACCENT_PRIMARY, ACCENT_SECONDARY, ACCENT_SUCCESS, ACCENT_ERROR,
|
||||
TEXT_PRIMARY, TEXT_SECONDARY, TEXT_MUTED,
|
||||
FONT_HEADER, FONT_SUBHEADER, FONT_BODY, FONT_BODY_BOLD, FONT_SMALL,
|
||||
create_styled_button
|
||||
)
|
||||
|
||||
|
||||
class UpdateDialog:
|
||||
"""Modal dialog for checking and applying updates."""
|
||||
|
||||
def __init__(self, parent: tk.Tk, on_close_callback: Optional[Callable] = None):
|
||||
self.parent = parent
|
||||
self.on_close_callback = on_close_callback
|
||||
self.update_info = None
|
||||
self.download_thread = None
|
||||
self.is_downloading = False
|
||||
|
||||
# Create the dialog window
|
||||
self.dialog = tk.Toplevel(parent)
|
||||
self.dialog.title("Check for Updates")
|
||||
self.dialog.geometry("520x600")
|
||||
self.dialog.resizable(True, True)
|
||||
self.dialog.minsize(480, 500)
|
||||
self.dialog.transient(parent)
|
||||
self.dialog.grab_set()
|
||||
|
||||
# Center on parent
|
||||
self.center_on_parent()
|
||||
|
||||
self.dialog.configure(bg=BG_DARK)
|
||||
|
||||
# Set up the UI
|
||||
self.setup_ui()
|
||||
|
||||
# Start checking for updates
|
||||
self.check_for_updates()
|
||||
|
||||
def center_on_parent(self):
|
||||
"""Center the dialog on the parent window."""
|
||||
self.dialog.update_idletasks()
|
||||
parent_x = self.parent.winfo_x()
|
||||
parent_y = self.parent.winfo_y()
|
||||
parent_w = self.parent.winfo_width()
|
||||
parent_h = self.parent.winfo_height()
|
||||
|
||||
dialog_w = 520
|
||||
dialog_h = 600
|
||||
|
||||
x = parent_x + (parent_w - dialog_w) // 2
|
||||
y = parent_y + (parent_h - dialog_h) // 2
|
||||
|
||||
self.dialog.geometry(f"{dialog_w}x{dialog_h}+{x}+{y}")
|
||||
|
||||
def setup_ui(self):
|
||||
"""Set up the dialog UI."""
|
||||
# Button frame (Create first to pack at bottom)
|
||||
self.button_frame = tk.Frame(self.dialog, bg=BG_DARK, pady=20, padx=20)
|
||||
self.button_frame.pack(side=tk.BOTTOM, fill=tk.X)
|
||||
|
||||
# Close button
|
||||
self.close_button = create_styled_button(
|
||||
self.button_frame,
|
||||
text="Close",
|
||||
command=self.close,
|
||||
style_type='default'
|
||||
)
|
||||
self.close_button.pack(side=tk.RIGHT)
|
||||
|
||||
# Update button (hidden initially)
|
||||
self.update_button = create_styled_button(
|
||||
self.button_frame,
|
||||
text="⬇️ Download & Install",
|
||||
command=self.start_download,
|
||||
style_type='accent'
|
||||
)
|
||||
# We don't pack it yet
|
||||
|
||||
# Main container
|
||||
main_frame = tk.Frame(self.dialog, bg=BG_DARK, padx=25, pady=20)
|
||||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# Title
|
||||
self.title_label = tk.Label(
|
||||
main_frame,
|
||||
text="🔄 Checking for Updates...",
|
||||
font=FONT_HEADER,
|
||||
bg=BG_DARK,
|
||||
fg=ACCENT_PRIMARY
|
||||
)
|
||||
self.title_label.pack(pady=(0, 10))
|
||||
|
||||
# Status message
|
||||
self.status_label = tk.Label(
|
||||
main_frame,
|
||||
text="Connecting to GitHub...",
|
||||
font=FONT_BODY,
|
||||
bg=BG_DARK,
|
||||
fg=TEXT_MUTED,
|
||||
wraplength=460
|
||||
)
|
||||
self.status_label.pack(pady=(0, 10))
|
||||
|
||||
# Version info frame
|
||||
self.version_frame = tk.Frame(main_frame, bg=BG_MEDIUM, padx=15, pady=10)
|
||||
self.version_frame.pack(fill=tk.X, pady=(0, 15))
|
||||
|
||||
self.current_version_label = tk.Label(
|
||||
self.version_frame,
|
||||
text=f"Current Version: v{get_current_version()}",
|
||||
font=FONT_BODY,
|
||||
bg=BG_MEDIUM,
|
||||
fg=TEXT_SECONDARY
|
||||
)
|
||||
self.current_version_label.pack(anchor='w')
|
||||
|
||||
self.new_version_label = tk.Label(
|
||||
self.version_frame,
|
||||
text="Latest Version: Checking...",
|
||||
font=FONT_BODY,
|
||||
bg=BG_MEDIUM,
|
||||
fg=TEXT_SECONDARY
|
||||
)
|
||||
self.new_version_label.pack(anchor='w')
|
||||
|
||||
# Release Notes Area
|
||||
self.notes_label = tk.Label(
|
||||
main_frame,
|
||||
text="What's New:",
|
||||
font=FONT_BODY_BOLD,
|
||||
bg=BG_DARK,
|
||||
fg=TEXT_PRIMARY
|
||||
)
|
||||
self.notes_label.pack(anchor='w', pady=(0, 5))
|
||||
|
||||
# Text box for release notes
|
||||
self.notes_text = scrolledtext.ScrolledText(
|
||||
main_frame,
|
||||
height=10,
|
||||
bg=BG_MEDIUM,
|
||||
fg=TEXT_SECONDARY,
|
||||
font=FONT_SMALL,
|
||||
borderwidth=0,
|
||||
highlightthickness=0,
|
||||
padx=10,
|
||||
pady=10
|
||||
)
|
||||
self.notes_text.pack(fill=tk.BOTH, expand=True, pady=(0, 15))
|
||||
self.notes_text.insert(tk.END, "Checking for release notes...")
|
||||
self.notes_text.config(state=tk.DISABLED)
|
||||
|
||||
# Progress bar (hidden initially)
|
||||
self.progress_frame = tk.Frame(main_frame, bg=BG_DARK)
|
||||
self.progress_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
self.progress_label = tk.Label(
|
||||
self.progress_frame,
|
||||
text="",
|
||||
font=FONT_SMALL,
|
||||
bg=BG_DARK,
|
||||
fg=TEXT_MUTED
|
||||
)
|
||||
self.progress_label.pack(anchor='w', pady=(0, 5))
|
||||
|
||||
self.progress_bar = ttk.Progressbar(
|
||||
self.progress_frame,
|
||||
mode='indeterminate',
|
||||
length=460
|
||||
)
|
||||
self.progress_bar.pack(fill=tk.X)
|
||||
self.progress_bar.start(10)
|
||||
|
||||
def check_for_updates(self):
|
||||
"""Check for updates in a background thread."""
|
||||
def check():
|
||||
self.update_info = check_for_updates()
|
||||
self.dialog.after(0, self.update_check_complete)
|
||||
|
||||
thread = threading.Thread(target=check, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def update_check_complete(self):
|
||||
"""Called when the update check is complete."""
|
||||
self.progress_bar.stop()
|
||||
self.progress_frame.pack_forget() # Hide progress bar when check is done
|
||||
|
||||
# Enable text box to update it
|
||||
self.notes_text.config(state=tk.NORMAL)
|
||||
self.notes_text.delete(1.0, tk.END)
|
||||
|
||||
if self.update_info:
|
||||
# Update available!
|
||||
self.title_label.config(text="🎉 Update Available!")
|
||||
self.status_label.config(
|
||||
text="A new version is available.",
|
||||
fg=ACCENT_SUCCESS
|
||||
)
|
||||
self.new_version_label.config(
|
||||
text=f"Latest Version: {self.update_info['new_version']}",
|
||||
fg=ACCENT_SUCCESS
|
||||
)
|
||||
|
||||
# Show Release Notes
|
||||
notes = self.update_info.get('release_notes', 'No release notes available.')
|
||||
self.notes_text.insert(tk.END, notes)
|
||||
|
||||
# Show update button
|
||||
self.update_button.pack(side=tk.RIGHT, padx=(0, 10))
|
||||
else:
|
||||
# Up to date or error
|
||||
self.title_label.config(text="✅ You're Up to Date!")
|
||||
self.status_label.config(
|
||||
text=f"You are running the latest version.",
|
||||
fg=TEXT_SECONDARY
|
||||
)
|
||||
self.new_version_label.config(
|
||||
text=f"Latest Version: v{get_current_version()}",
|
||||
fg=ACCENT_SUCCESS
|
||||
)
|
||||
self.notes_text.insert(tk.END, "You are using the latest version of Umamusume Support Card Manager.\n\nEnjoy!")
|
||||
|
||||
self.notes_text.config(state=tk.DISABLED)
|
||||
|
||||
def start_download(self):
|
||||
"""Start downloading the update."""
|
||||
if self.is_downloading or not self.update_info:
|
||||
return
|
||||
|
||||
self.is_downloading = True
|
||||
self.update_button.config(state=tk.DISABLED, text="Downloading...")
|
||||
self.close_button.config(state=tk.DISABLED)
|
||||
|
||||
self.title_label.config(text="⬇️ Downloading Update...")
|
||||
self.status_label.config(text="Please wait...", fg=TEXT_MUTED)
|
||||
|
||||
# Configure progress bar for determinate mode
|
||||
self.progress_frame.pack(fill=tk.X, pady=(0, 10)) # Show progress frame again
|
||||
self.progress_bar.config(mode='determinate', maximum=100)
|
||||
self.progress_bar.pack(fill=tk.X)
|
||||
self.progress_bar['value'] = 0
|
||||
|
||||
def download():
|
||||
def progress_callback(downloaded, total):
|
||||
if total > 0:
|
||||
percent = int((downloaded / total) * 100)
|
||||
mb_downloaded = downloaded / (1024 * 1024)
|
||||
mb_total = total / (1024 * 1024)
|
||||
self.dialog.after(0, lambda: self.update_progress(percent, mb_downloaded, mb_total))
|
||||
|
||||
download_path = download_update(self.update_info['download_url'], progress_callback)
|
||||
self.dialog.after(0, lambda: self.download_complete(download_path))
|
||||
|
||||
self.download_thread = threading.Thread(target=download, daemon=True)
|
||||
self.download_thread.start()
|
||||
|
||||
def update_progress(self, percent: int, downloaded_mb: float, total_mb: float):
|
||||
"""Update the progress bar."""
|
||||
self.progress_bar['value'] = percent
|
||||
self.progress_label.config(text=f"Downloaded: {downloaded_mb:.1f} MB / {total_mb:.1f} MB ({percent}%)")
|
||||
|
||||
def download_complete(self, download_path: Optional[str]):
|
||||
"""Called when the download is complete."""
|
||||
self.is_downloading = False
|
||||
|
||||
if download_path:
|
||||
self.title_label.config(text="✅ Download Complete!")
|
||||
self.status_label.config(
|
||||
text="Update ready to install.",
|
||||
fg=ACCENT_SUCCESS
|
||||
)
|
||||
|
||||
# Change button to install
|
||||
self.update_button.config(
|
||||
state=tk.NORMAL,
|
||||
text="🔄 Install & Restart",
|
||||
command=lambda: self.install_update(download_path)
|
||||
)
|
||||
self.close_button.config(state=tk.NORMAL)
|
||||
else:
|
||||
self.title_label.config(text="❌ Download Failed")
|
||||
self.status_label.config(
|
||||
text="Failed not download update.",
|
||||
fg=ACCENT_ERROR
|
||||
)
|
||||
self.update_button.config(state=tk.NORMAL, text="⬇️ Retry Download")
|
||||
self.close_button.config(state=tk.NORMAL)
|
||||
|
||||
def install_update(self, download_path: str):
|
||||
"""Install the downloaded update."""
|
||||
self.title_label.config(text="🔄 Installing Update...")
|
||||
self.status_label.config(text="Applying update...", fg=TEXT_MUTED)
|
||||
self.update_button.config(state=tk.DISABLED)
|
||||
self.close_button.config(state=tk.DISABLED)
|
||||
|
||||
if apply_update(download_path):
|
||||
# Exit the application - the updater script will restart it
|
||||
self.dialog.after(1000, lambda: self.parent.quit())
|
||||
else:
|
||||
messagebox.showinfo(
|
||||
"Manual Update Required",
|
||||
f"The update was downloaded but cannot be applied automatically.\n\n"
|
||||
f"Downloaded file location:\n{download_path}\n\n"
|
||||
f"Please replace the current executable manually.",
|
||||
parent=self.dialog
|
||||
)
|
||||
self.close()
|
||||
|
||||
|
||||
def close(self):
|
||||
"""Close the dialog."""
|
||||
if self.on_close_callback:
|
||||
self.on_close_callback()
|
||||
self.dialog.destroy()
|
||||
|
||||
|
||||
def show_update_dialog(parent: tk.Tk, on_close_callback: Optional[Callable] = None) -> UpdateDialog:
|
||||
"""
|
||||
Show the update dialog.
|
||||
|
||||
Args:
|
||||
parent: The parent Tk window
|
||||
on_close_callback: Optional callback when dialog is closed
|
||||
|
||||
Returns:
|
||||
The UpdateDialog instance
|
||||
"""
|
||||
return UpdateDialog(parent, on_close_callback)
|
||||
Reference in New Issue
Block a user