From a2bcf72c7668a6baf330b53b3cb3e97ab5784b8d Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Wed, 7 May 2025 19:52:39 +0200 Subject: [PATCH] appstore: add update button (non-functional) --- .../com.example.appstore/assets/appstore.py | 42 +++++++++++++++++-- .../com.example.launcher/assets/launcher.py | 4 +- internal_filesystem/main.py | 42 ++++++++++++++----- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/internal_filesystem/builtin/apps/com.example.appstore/assets/appstore.py b/internal_filesystem/builtin/apps/com.example.appstore/assets/appstore.py index b8f1cb85..6e197137 100644 --- a/internal_filesystem/builtin/apps/com.example.appstore/assets/appstore.py +++ b/internal_filesystem/builtin/apps/com.example.appstore/assets/appstore.py @@ -33,6 +33,33 @@ class App: self.image = None self.image_dsc = None +def compare_versions(ver1: str, ver2: str) -> bool: + """Compare two version numbers (e.g., '1.2.3' vs '4.5.6'). + Returns True if ver1 is greater than ver2, False otherwise.""" + print(f"Comparing versions: {ver1} vs {ver2}") + v1_parts = [int(x) for x in ver1.split('.')] + v2_parts = [int(x) for x in ver2.split('.')] + print(f"Version 1 parts: {v1_parts}") + print(f"Version 2 parts: {v2_parts}") + for i in range(max(len(v1_parts), len(v2_parts))): + v1 = v1_parts[i] if i < len(v1_parts) else 0 + v2 = v2_parts[i] if i < len(v2_parts) else 0 + print(f"Comparing part {i}: {v1} vs {v2}") + if v1 > v2: + print(f"{ver1} is greater than {ver2}") + return True + if v1 < v2: + print(f"{ver1} is less than {ver2}") + return False + print(f"Versions are equal or {ver1} is not greater than {ver2}") + return False + + +def update_available(app_fullname, new_version): + installed_app = parse_manifest(f"/apps/{app_fullname}/META-INF/MANIFEST.JSON") + if installed_app.version == "0.0.0": # special case, if the installed app doesn't have a version number (maybe MANIFEST.JSON doesn't exist?) then there's no update + return False + return compare_versions(new_version, installed_app.version) def is_installed_by_path(dir_path): try: @@ -290,10 +317,17 @@ def show_app_detail(app): action_label = action_label_install install_label.set_text(action_label) install_label.center() - if is_installed: # and newer_version_available(app.fullname) - install_button.set_size(lv.pct(45), 40) + if is_installed and update_available(app.fullname, app.version): + install_button.set_size(lv.pct(45), 40) # make space for update button print("Update available, adding update button.") - else + update_button = lv.button(cont) + update_button.set_size(lv.pct(45), 40) + update_button.align_to(install_button, lv.ALIGN.OUT_RIGHT_MID, 0, lv.pct(5)) + update_button.add_event_cb(lambda e, d=app.download_url, f=app.fullname: update_button_click(d,f), lv.EVENT.CLICKED, None) + update_label = lv.label(update_button) + update_label.set_text("Update") + update_label.center() + else: install_button.set_size(lv.pct(100), 40) version_label = lv.label(cont) version_label.set_width(lv.pct(100)) @@ -326,6 +360,8 @@ def toggle_install(download_url, fullname): except Exception as e: print("Could not start download_and_unzip thread: ", e) +def update_button_click(download_url, fullname): + print(f"Update button clicked for {download_url} and fullname {fullname}") def back_to_main(event): global app_detail_screen diff --git a/internal_filesystem/builtin/apps/com.example.launcher/assets/launcher.py b/internal_filesystem/builtin/apps/com.example.launcher/assets/launcher.py index 523c70d0..40b544bd 100644 --- a/internal_filesystem/builtin/apps/com.example.launcher/assets/launcher.py +++ b/internal_filesystem/builtin/apps/com.example.launcher/assets/launcher.py @@ -62,7 +62,7 @@ for dir_path in [apps_dir, apps_dir_builtin]: # Should we skip 'Launcher' apps from the list here? for app_dir_fullpath in app_dirs: - app_name, main_script = parse_manifest(f"{app_dir_fullpath}/META-INF/MANIFEST.JSON") + app = parse_manifest(f"{app_dir_fullpath}/META-INF/MANIFEST.JSON") # Create a container for each app (icon + label) app_cont = lv.obj(cont) app_cont.set_size(iconcont_width, iconcont_height) @@ -85,7 +85,7 @@ for app_dir_fullpath in app_dirs: image.set_size(icon_size, icon_size) # Create label label = lv.label(app_cont) - label.set_text(app_name) + label.set_text(app.name) label.set_long_mode(lv.label.LONG.WRAP) label.set_width(iconcont_width) label.align(lv.ALIGN.BOTTOM_MID, 0, 0) diff --git a/internal_filesystem/main.py b/internal_filesystem/main.py index da4338ab..d474f31d 100644 --- a/internal_filesystem/main.py +++ b/internal_filesystem/main.py @@ -258,18 +258,38 @@ def is_launcher(app_name): return "launcher" in app_name def parse_manifest(manifest_path): - name = "Unknown" - start_script = "assets/start.py" + # Default values for App object + default_app = App( + name="Unknown", + publisher="Unknown", + short_description="", + long_description="", + icon_url="", + download_url="", + fullname="Unknown", + version="0.0.0", + entrypoint="assets/start.py", + category="" + ) try: - with open(manifest_path,'r') as f: - app_info=ujson.load(f) - name = app_info.get("name") - start_script = app_info.get("entrypoint") - #print(f"parse_manifest: got app_info: {app_info}") + with open(manifest_path, 'r') as f: + app_info = ujson.load(f) + # Create App object with values from manifest, falling back to defaults + return App( + name=app_info.get("name", default_app.name), + publisher=app_info.get("publisher", default_app.publisher), + short_description=app_info.get("short_description", default_app.short_description), + long_description=app_info.get("long_description", default_app.long_description), + icon_url=app_info.get("icon_url", default_app.icon_url), + download_url=app_info.get("download_url", default_app.download_url), + fullname=app_info.get("fullname", default_app.fullname), + version=app_info.get("version", default_app.version), + entrypoint=app_info.get("entrypoint", default_app.entrypoint), + category=app_info.get("category", default_app.category) + ) except OSError: - access_points={} print(f"parse_manifest: error loading manifest_path: {manifest_path}") - return name, start_script + return default_app def long_path_to_filename(path): try: @@ -367,8 +387,8 @@ def start_app(app_dir, is_launcher=False): global foreground_app_name foreground_app_name = app_dir # would be better to store only the app name... manifest_path = f"{app_dir}/META-INF/MANIFEST.JSON" - app_name, start_script = parse_manifest(manifest_path) - start_script_fullpath = f"{app_dir}/{start_script}" + app = parse_manifest(manifest_path) + start_script_fullpath = f"{app_dir}/{app.entrypoint}" execute_script_new_thread(start_script_fullpath, True, is_launcher, True) # Launchers have the bar, other apps don't have it if is_launcher: