From 8b24e294bf8143eee988f24bedc981386e70d7e7 Mon Sep 17 00:00:00 2001
From: Thisal Dilmith <93121062+Thisal-D@users.noreply.github.com>
Date: Sat, 30 Nov 2024 03:58:35 +0530
Subject: [PATCH 1/2] Add files via upload
---
PROJECT_STRUCTURE.md | 2 +-
app.py | 40 ++++++++++++-
contributors.txt | 3 +-
data/appearance.json | 8 +--
data/general.json | 2 +-
data/info.json | 2 +-
data/languages/en.json | 3 +-
data/languages/si.json | 3 +-
data/languages/zh.json | 3 +-
main.py | 11 +++-
utils/__init__.py | 2 +-
utils/data_retrive_utility.py | 67 ++++++++++++++++++++++
widgets/core_widgets/alert_window.py | 17 +++++-
widgets/setting_panels/about_panel.py | 13 +++--
widgets/setting_panels/appearance_panel.py | 4 +-
15 files changed, 156 insertions(+), 24 deletions(-)
create mode 100644 utils/data_retrive_utility.py
diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md
index 2f625e1..d4f2bf7 100644
--- a/PROJECT_STRUCTURE.md
+++ b/PROJECT_STRUCTURE.md
@@ -33,7 +33,7 @@ project_folder/
│ ├── \_\_init\_\_.py
│ ├── download_info_utility.py
│ ├── file_utility.py
- │ ├── git_hub_utility.py
+ │ ├── data_retrive_utility.py
│ ├── gui_utils.py
│ ├── image_utility.py
│ ├── json_utility.py
diff --git a/app.py b/app.py
index cc5c6a8..9fed86c 100644
--- a/app.py
+++ b/app.py
@@ -3,6 +3,7 @@
import tkinter as tk
import threading
import time
+import webbrowser
from typing import Literal
import pyautogui
from widgets import (
@@ -28,7 +29,9 @@
GeneralSettings,
)
from utils import (
- FileUtility
+ FileUtility,
+ DataRetriveUtility,
+ GuiUtils
)
@@ -1441,6 +1444,7 @@ def show_close_confirmation_dialog(self) -> None:
ok_button_callback=self.on_app_closing,
cancel_button_callback=self.cancel_app_closing,
callback=self.cancel_app_closing,
+ wait_for_previous=True,
width=int(450 * scale),
height=int(130 * scale),
)
@@ -1477,3 +1481,37 @@ def clear_temporally_saved_files(self) -> None:
Clears temporarily saved files, such as thumbnails.
"""
FileUtility.delete_files("temp\\thumbnails", ["this directory is necessary"])
+
+ def open_update_download_page(self) -> None:
+ """
+ Open website for download latest version
+ """
+ webbrowser.open("https://sourceforge.net/projects/pytube-downloader/files/latest/download")
+
+ def check_for_updates(self) -> None:
+ """
+ Update the version of the application.
+ """
+ # Check the app is updated or not
+ latest_version = DataRetriveUtility.get_latest_version()
+ current_version = DataRetriveUtility.get_current_version()
+ scale = AppearanceSettings.settings["scale_r"]
+ if latest_version is not None:
+ if latest_version != current_version:
+ AlertWindow(
+ master=self,
+ alert_msg="update_alert",
+ ok_button_display=True,
+ ok_button_callback=self.open_update_download_page,
+ cancel_button_display=True,
+ wait_for_previous=True,
+ width=int(450 * scale),
+ height=int(130 * scale)
+ )
+
+ def run_update_check(self):
+ """
+ Run the update check in a separate thread.
+ """
+ self.update_check_thread = threading.Thread(target=self.check_for_updates, daemon=True)
+ self.update_check_thread.start()
diff --git a/contributors.txt b/contributors.txt
index 4ccd47f..7bbe079 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -1,5 +1,4 @@
-CONTRIBUTORS INFO
https://github.com/Thisal-D@%@Thisal Dilmith
https://github.com/childeyouyu@%@youyu
https://github.com/Navindu21@%@Navindu Pahasara
-https://github.com/sooryasuraweera@%@Soorya Suraweera
+https://github.com/sooryasuraweera@%@Soorya Suraweera
\ No newline at end of file
diff --git a/data/appearance.json b/data/appearance.json
index 861bfb2..f366277 100644
--- a/data/appearance.json
+++ b/data/appearance.json
@@ -34,7 +34,7 @@
]
}
},
- "opacity": 100.0,
+ "opacity": 100,
"opacity_r": 1.0,
"radio_btn": {
"text_color": {
@@ -51,8 +51,8 @@
"root": {
"accent_color": {
"default": true,
- "hover": "#903efb",
- "normal": "#7a14ff"
+ "hover": "#5f4ff1",
+ "normal": "#412ff0"
},
"fg_color": {
"hover": [
@@ -258,4 +258,4 @@
]
}
}
-}
+}
\ No newline at end of file
diff --git a/data/general.json b/data/general.json
index 5bcafa8..a654746 100644
--- a/data/general.json
+++ b/data/general.json
@@ -16,4 +16,4 @@
"reload_automatically": false,
"update_delay": 0.5,
"window_geometry": "900x500+0+0"
-}
+}
\ No newline at end of file
diff --git a/data/info.json b/data/info.json
index bd51842..d357ded 100644
--- a/data/info.json
+++ b/data/info.json
@@ -3,4 +3,4 @@
"name": "PyTube Downloader",
"site": "https://github.com/Thisal-D/PyTube-Downloader",
"version": "2.0.2"
-}
+}
\ No newline at end of file
diff --git a/data/languages/en.json b/data/languages/en.json
index 718a1de..0e16037 100644
--- a/data/languages/en.json
+++ b/data/languages/en.json
@@ -85,5 +85,6 @@
"quick_exit": "Quick Exit",
"force_exit": "Force Exit",
"minimize_to_tray": "Minimize To Tray",
- "reset": "Reset"
+ "reset": "Reset",
+ "update_alert": "A new update is available! \nVisit the official website to download the \nlatest version."
}
diff --git a/data/languages/si.json b/data/languages/si.json
index 3cdeaa2..f44586b 100644
--- a/data/languages/si.json
+++ b/data/languages/si.json
@@ -85,6 +85,7 @@
"quick_exit": "ඉක්මන් පිටවීම",
"force_exit": "පිටවීම",
"minimize_to_tray": "ට්රේ එකට Minimize කරන්න",
- "reset": "නෑවත සකසන්න"
+ "reset": "නෑවත සකසන්න",
+ "update_alert": "නව අනුවාදයක් තිබේ!\nනවතම අනුවාදය බාගැනීමට කරුණාකර \nනිල වෙබ් අඩවියට පිවිසෙන්න."
}
\ No newline at end of file
diff --git a/data/languages/zh.json b/data/languages/zh.json
index 1912015..7dd537a 100644
--- a/data/languages/zh.json
+++ b/data/languages/zh.json
@@ -85,5 +85,6 @@
"quick_exit": "快速退出",
"force_exit": "强制退出",
"minimize_to_tray": "最小化到托盘",
- "reset": "重置"
+ "reset": "重置",
+ "update_alert": "有新版本可用!\n请访问官方网站下载最新版本。"
}
diff --git a/main.py b/main.py
index d6b9404..89a7e3d 100644
--- a/main.py
+++ b/main.py
@@ -13,7 +13,9 @@
LanguageManager,
VideoCountTracker
)
-from utils import FileUtility
+from utils import (
+ FileUtility
+)
# Initialize app.
@@ -80,5 +82,10 @@
app.bind_widgets_events()
# bind shortcut keys
app.bind_keyboard_shortcuts()
-# just rut the app
+# Check app updates
+app.run_update_check()
+# just run the app
app.run()
+
+# Codes under here will only execute when the app is closed
+
\ No newline at end of file
diff --git a/utils/__init__.py b/utils/__init__.py
index 2add71e..b35ddc4 100644
--- a/utils/__init__.py
+++ b/utils/__init__.py
@@ -1,6 +1,6 @@
from .download_info_utility import DownloadInfoUtility
from .file_utility import FileUtility
-from .git_hub_utility import GitHubUtility
+from .data_retrive_utility import DataRetriveUtility
from .json_utility import JsonUtility
from .image_utility import ImageUtility
from .settings_validate_utility import SettingsValidateUtility
diff --git a/utils/data_retrive_utility.py b/utils/data_retrive_utility.py
new file mode 100644
index 0000000..bb52a48
--- /dev/null
+++ b/utils/data_retrive_utility.py
@@ -0,0 +1,67 @@
+from urllib import request
+import requests
+from typing import List, Dict
+from .json_utility import JsonUtility
+
+
+class DataRetriveUtility:
+ CONTRIBUTORS_TEXT_URL = "https://raw.githubusercontent.com/Thisal-D/PyTube-Downloader/main/contributors.txt"
+ VERSION_FILE_URL = "https://raw.githubusercontent.com/Thisal-D/PyTube-Downloader/main/VERSION"
+
+ @staticmethod
+ def get_contributors_data() -> List[Dict]:
+ """
+ Retrieve contributors data from a GitHub repository.
+
+ Returns:
+ list: A list of dictionaries containing contributor information.
+ """
+ contributors = []
+ try:
+ data = requests.get(DataRetriveUtility.CONTRIBUTORS_TEXT_URL).text
+ for contributor_data in data.split("\n"):
+ try:
+ profile_url, username = contributor_data.split("@%@")
+ contributors.append({
+ "profile_url": profile_url,
+ "user_name": username,
+ })
+ except Exception as error:
+ print(f"data_retrive_utility.py L54 : {error}")
+ except Exception as error:
+ print(f"data_retrive_utility.py L43 : {error}")
+ return None
+
+ return contributors
+
+ @staticmethod
+ def get_latest_version():
+ """
+ Retrieve latest version from a GitHub repository.
+
+ Returns:
+ string: The latest version number.
+ """
+ try:
+ data = requests.get(DataRetriveUtility.VERSION_FILE_URL).text.strip()
+ # Extract the version number from the string "VERSION = '2.0.2'"
+ # Split at "=" and remove extra characters like spaces and quotes
+ version = data.split('=')[1].strip().strip("'")
+
+ except Exception as error:
+ print(f"data_retrive_utility.py L43 : {error}")
+ return None
+
+ return version
+
+ def get_current_version():
+ """
+ Read current version from info.json file.
+
+ return:
+ string: current version
+ """
+ version = JsonUtility.read_from_file("data\\info.json")["version"]
+ return version
+
+
\ No newline at end of file
diff --git a/widgets/core_widgets/alert_window.py b/widgets/core_widgets/alert_window.py
index a50c831..adc71b6 100644
--- a/widgets/core_widgets/alert_window.py
+++ b/widgets/core_widgets/alert_window.py
@@ -1,11 +1,16 @@
import customtkinter as ctk
+import time
from PIL import Image
from typing import Callable
from settings import AppearanceSettings
from services import LanguageManager
-
class AlertWindow(ctk.CTkToplevel):
+ """
+ Use to track any alert windows running or not
+ """
+ Running = False
+
def __init__(
self,
master: ctk.CTk = None,
@@ -15,6 +20,7 @@ def __init__(
cancel_button_display: bool = None,
cancel_button_callback: Callable = None,
callback: Callable = None,
+ wait_for_previous: bool = False,
width: int = 400,
height: int = 200):
@@ -24,6 +30,14 @@ def __init__(
width=width,
height=height)
+ # If ensure_previous_closed is true, wait until the previous alert window is closed
+ if wait_for_previous:
+ while AlertWindow.Running :
+ time.sleep(0.5)
+
+ # Start the alert window
+ AlertWindow.Running = True
+
scale = AppearanceSettings.settings["scale_r"]
self.master: ctk.CTk = master
@@ -106,6 +120,7 @@ def on_closing(self):
self.unbind("")
self.master.unbind("")
self.destroy()
+ AlertWindow.Running = False
if self.callback is not None:
self.callback()
diff --git a/widgets/setting_panels/about_panel.py b/widgets/setting_panels/about_panel.py
index 30a434e..756b40c 100644
--- a/widgets/setting_panels/about_panel.py
+++ b/widgets/setting_panels/about_panel.py
@@ -6,7 +6,7 @@
import customtkinter as ctk
from PIL import Image
from utils import (
- GitHubUtility,
+ DataRetriveUtility,
JsonUtility,
FileUtility,
ImageUtility,
@@ -100,13 +100,14 @@ def __init__(
scrollbar_fg_color=AppearanceSettings.settings["root"]["fg_color"]["normal"],
fg_color=AppearanceSettings.settings["root"]["fg_color"]["normal"]
)
-
+
self.disclaimer_label = ctk.CTkLabel(
master=self,
justify="left",
text="",
text_color=AppearanceSettings.settings["settings_panel"]["warning_color"]["normal"]
)
+
self.contribute_data_retrieve_status = None
self.app_info: Dict = JsonUtility.read_from_file("data\\info.json")
self.place_widgets()
@@ -144,7 +145,7 @@ def configure_contributors_info(self):
self.app_info["contributors"] = {}
# retrieve contributors data from GitHub repo as list[dict]
- contributors_data = GitHubUtility.get_contributors_data()
+ contributors_data = DataRetriveUtility.get_contributors_data()
# if it success -> return Dict
# if it fails -> return None
if contributors_data is not None:
@@ -280,13 +281,14 @@ def place_widgets(self):
self.contributors_title_label.grid(row=3, column=0, padx=(100, 0), pady=(pady, 0), sticky="nw")
self.dash4_label.grid(row=3, column=1, padx=(30, 30), pady=(pady, 0), sticky="nw")
self.contributors_status_label.grid(row=3, column=2, pady=(pady, 0), sticky="w")
+
self.disclaimer_label.place(x=100, rely=1, y=-60 * scale)
def set_widgets_sizes(self):
scale = AppearanceSettings.settings["scale_r"]
self.contributors_frame.configure(height=200 * scale, width=500 * scale)
self.contributors_frame._scrollbar.grid_forget()
-
+
def set_widgets_texts(self):
self.name_title_label.configure(text=LanguageManager.data["name"])
self.version_title_label.configure(text=LanguageManager.data["version"])
@@ -297,6 +299,7 @@ def set_widgets_texts(self):
elif self.contribute_data_retrieve_status is None:
self.contributors_status_label.configure(text=LanguageManager.data["loading"])
self.disclaimer_label.configure(text=" " + LanguageManager.data["disclaimer"])
+
def update_widgets_text(self):
self.set_widgets_texts()
@@ -320,5 +323,5 @@ def set_widgets_fonts(self):
self.dash4_label.configure(font=title_font)
self.contributors_status_label.configure(font=title_font)
- value_font = ("Segoe UI", 13 * scale, "normal")
+ value_font = ("Segoe UI", int(13 * scale), "normal")
self.disclaimer_label.configure(font=value_font)
diff --git a/widgets/setting_panels/appearance_panel.py b/widgets/setting_panels/appearance_panel.py
index 57f003b..1602981 100644
--- a/widgets/setting_panels/appearance_panel.py
+++ b/widgets/setting_panels/appearance_panel.py
@@ -201,8 +201,8 @@ def cancel_scale_settings_resetting(self):
self.scale_value_label.configure(text=f"{AppearanceSettings.settings["scale"]} %")
def reset_settings(self):
- self.apply_theme_mode("Dark")
- self.theme_combo_box.set("Dark")
+ self.apply_theme_mode(self.theme_combo_box.cget("values")[0])
+ self.theme_combo_box.set(self.theme_combo_box.cget("values")[0])
if not self.accent_color_buttons[0].pressed:
self.accent_color_buttons[0].on_mouse_enter_self('event')
From 050b4fb07891e6413a381698b08c8a23c1bcac66 Mon Sep 17 00:00:00 2001
From: Thisal Dilmith <93121062+Thisal-D@users.noreply.github.com>
Date: Sat, 30 Nov 2024 04:01:09 +0530
Subject: [PATCH 2/2] Update app.py
---
app.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app.py b/app.py
index 9fed86c..d66785b 100644
--- a/app.py
+++ b/app.py
@@ -30,8 +30,7 @@
)
from utils import (
FileUtility,
- DataRetriveUtility,
- GuiUtils
+ DataRetriveUtility
)