Skip to content

Commit

Permalink
Merge pull request #67 from emfcamp/app-store
Browse files Browse the repository at this point in the history
Initial app store
  • Loading branch information
tomsci authored Jun 4, 2022
2 parents 7422ee5 + e188ee2 commit 6456da6
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 19 deletions.
1 change: 1 addition & 0 deletions modules/app_launcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def list_user_apps(self):

def list_core_apps(self):
core_app_info = [
("App store", "app_store", "Store"),
("USB Keyboard", "hid", "USBKeyboard"),
("Name Badge", "hello", "Hello"),
("Torch", "torch", "Torch"),
Expand Down
134 changes: 134 additions & 0 deletions modules/app_store/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
from app import MenuApp, Menu
from buttons import Buttons
from textwindow import TextWindow
from scheduler import get_scheduler
import time
import tidal
from dashboard.resources import woezel_repo
import woezel


class UpdateProgress(TextWindow):

def progress(self, text, error=False, wifi=False):
for line in self.flow_lines(text):
if error:
self.println(line, fg=tidal.WHITE, bg=tidal.ADDITIONAL_RED)
elif wifi:
self.println(line, fg=tidal.BRAND_CYAN)
else:
self.println(line)

def redraw(self):
super().redraw()
if not woezel_repo.load():
try:
woezel_repo.update(_showProgress=self.progress)
except:
time.sleep(2)
time.sleep(3)
self.return_back()

class InstallProgress(TextWindow):

def redraw(self):
self.cls()
self.println("Checking...")

def progress(self, text, *args, **kwargs):
for line in self.flow_lines(text):
self.println(line)
self.println("")

class AppList(Menu):

def __init__(self, title, slug, bg, fg, focus_bg, focus_fg, font, buttons, push_window, pop_window):
self.category = slug
self.push_window = push_window
self.pop_window = pop_window
super().__init__(bg, fg, focus_bg, focus_fg, title, self._choices, font, buttons)

def return_back(self):
self.pop_window()
self.redraw()

def installer(self, slug):
print(f"Install option for {slug}")
def do_install():
print(f"installing {slug}")
sub_buttons = Buttons()
progress = InstallProgress(self.return_back, buttons=sub_buttons)
progress.bg = self.bg
progress.fg = self.fg
self.push_window(progress)
try:
woezel.install(slug, progress=progress.progress)
except:
pass
sub_buttons.on_press(tidal.BUTTON_FRONT, self.pop_window, autorepeat=False)
sub_buttons.on_press(tidal.BUTTON_A, self.pop_window, autorepeat=False)
progress.progress("Press [A] to return to menu")
return do_install

def make_choice(self, item):
return item['name'], self.installer(item['slug'])

@property
def _choices(self):
return [
self.make_choice(application)
for application in woezel_repo.getCategory(self.category)
] + [("Back...", self.pop_window)]

class Store(MenuApp):
APP_ID = "store"
TITLE = "App store"

@property
def choices(self):
# Note, the text for each choice needs to be <= 16 characters in order to fit on screen
choices = [self.make_choice(choice) for choice in woezel_repo.categories]
choices = choices + [("Refresh...", self.trigger_update)]
return choices

def make_choice(self, choice):
return (choice['name'], self.launch_app_list(choice))

def launch_app_list(self, choice):
def do_launch():
sub_buttons = Buttons()
sub_buttons.on_press(tidal.BUTTON_FRONT, self.return_back, autorepeat=False)
menu = AppList(
choice['name'],
choice['slug'],
self.window.bg,
self.window.fg,
self.window.focus_bg,
self.window.focus_fg,
self.window.font,
sub_buttons,
self.push_window,
self.pop_window
)
print(f"Pushing {menu}")
self.push_window(menu)
return do_launch

def on_activate(self):
super().on_activate()
self.trigger_update(force=False)

def trigger_update(self, force=True):
if force:
woezel_repo.updatedThisBoot = False
update = UpdateProgress(buttons=Buttons())
update.buttons.on_press(tidal.BUTTON_FRONT, self.pop_window, autorepeat=False)
update.return_back = self.return_back
self.push_window(update)

def return_back(self):
self.pop_window()
self.refresh()

def refresh(self):
self.window.set_choices(self.choices)
12 changes: 6 additions & 6 deletions modules/dashboard/resources/woezel_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
path = "/cache/woezel"
categories = []
lastUpdate = 0
updatedThisBoot = False

try:
uos.mkdir("/cache")
Expand All @@ -26,7 +27,7 @@ def setPath(newPath="/cache/woezel"):
except:
pass

def _showProgress(msg, error=False, icon_wifi=False):
def showProgress(msg, error=False, icon_wifi=False):
term.header(True, "Installer")
print(msg)
icon = "/media/busy.png"
Expand All @@ -36,8 +37,8 @@ def _showProgress(msg, error=False, icon_wifi=False):
icon = "/media/wifi.png"
#easydraw.messageCentered(msg, False, icon)

def update():
global path, categories, lastUpdate
def update(_showProgress=showProgress):
global path, categories, lastUpdate, updatedThisBoot
if not wifi.status():
_showProgress("Connecting to WiFi...", False, True)
wifi.connect()
Expand Down Expand Up @@ -66,6 +67,7 @@ def update():
f.write(str(lastUpdate))
f.close()
_showProgress("Done!")
updatedThisBoot = True
gc.collect()
return True
except BaseException as e:
Expand All @@ -85,18 +87,16 @@ def load():
categories = json.loads(f.read())
f.close()
gc.collect()
if (lastUpdate + 900) < time.time() or time.time() < 900 or time.time() < lastUpdate:
if (lastUpdate + 900) < time.time() or not updatedThisBoot:
# Refresh the cash if it's been at least 15 minutes since the last refresh
# or if we're in the first 15 minutes of all time ;)
# or if the last update is in the future
# - We don't have RTC set up so the clock resets on each boot
print("Current repository cache is too old!", lastUpdate + 900, "<", int(time.time()))
#time.sleep(2)
return False
return True
except BaseException as e:
sys.print_exception(e)
time.sleep(2)
return False

def getCategory(slug):
Expand Down
32 changes: 19 additions & 13 deletions modules/woezel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import consts
gc.collect()

print_progress = print
debug = False
# install_path = None
install_path = "/apps" # TiDAL change
Expand Down Expand Up @@ -173,25 +174,27 @@ def search_pkg_list(query):
f.close()

def fatal(msg, exc=None):
print("Error:", msg)
print_progress("Error:", msg)
if exc and debug:
raise exc
sys.exit(1)
else:
raise ValueError(msg)
#sys.exit(1)

def install_pkg(pkg_spec, install_path, force_reinstall):
def install_pkg(pkg_spec, install_path, force_reinstall, progress=print):
data = get_pkg_metadata(pkg_spec)
already_installed = False
try:
os.stat("%s%s/" % (install_path, pkg_spec))
except OSError as e:
if e.args[0] == errno.EINVAL:
print("Package %s already installed" % (pkg_spec))
progress("Package %s already installed" % (pkg_spec))
already_installed = True
else:
print("Package %s not yet installed" % (pkg_spec))
progress("Installing %s..." % (pkg_spec))
else:
# fallback for unix version
print("Package %s already installed" % (pkg_spec))
progress("Package %s already installed" % (pkg_spec))
already_installed = True
latest_ver = data["info"]["version"]
verf = "%s%s/version" % (install_path, pkg_spec)
Expand All @@ -200,13 +203,13 @@ def install_pkg(pkg_spec, install_path, force_reinstall):
with open(verf, "r") as fver:
old_ver = fver.read()
except:
print("No version file found")
progress("No version file found")
else:
if old_ver == latest_ver:
if not force_reinstall:
raise LatestInstalledError("Latest version installed")
else:
print("Removing previous rev. %s" % old_ver)
progress("Removing previous rev. %s" % old_ver)
for rm_file in os.listdir("%s%s" % (install_path, pkg_spec)):
os.remove("%s%s/%s" % (install_path, pkg_spec, rm_file))
packages = data["releases"][latest_ver]
Expand All @@ -231,9 +234,11 @@ def install_pkg(pkg_spec, install_path, force_reinstall):
gc.collect()
return meta

def install(to_install, install_path=None, force_reinstall=False):
def install(to_install, install_path=None, force_reinstall=False, progress=print):
# Calculate gzip dictionary size to use
global gzdict_sz
global print_progress
print_progress = progress
sz = gc.mem_free() + gc.mem_alloc()
if sz <= 65536:
# this will probably give errors with some packages, but we
Expand All @@ -246,17 +251,17 @@ def install(to_install, install_path=None, force_reinstall=False):
install_path += "/"
if not isinstance(to_install, list):
to_install = [to_install]
print("Installing to: " + install_path)
progress("Installation root: " + install_path)
# sets would be perfect here, but don't depend on them
installed = []
try:
while to_install:
if debug:
print("Queue:", to_install)
progress("Queue:", to_install)
pkg_spec = to_install.pop(0)
if pkg_spec in installed:
continue
meta = install_pkg(pkg_spec, install_path, force_reinstall)
meta = install_pkg(pkg_spec, install_path, force_reinstall, progress=progress)
installed.append(pkg_spec)
if debug:
print(meta)
Expand All @@ -265,10 +270,11 @@ def install(to_install, install_path=None, force_reinstall=False):
deps = deps.decode("utf-8").split("\n")
to_install.extend(deps)
except Exception as e:
print("Error installing '{}': {}, packages may be partially installed".format(
progress("'{}' not installed: {}".format(
pkg_spec, e),
file=sys.stderr)
raise e
progress(f"Installed: {"\n ".join(installed)}")

def display_pkg(packages):
for package in packages:
Expand Down

0 comments on commit 6456da6

Please sign in to comment.