Skip to content

Commit 382a366

Browse files
AppStore app: add support for badgehub (disabled)
1 parent 658b999 commit 382a366

File tree

1 file changed

+183
-43
lines changed
  • internal_filesystem/builtin/apps/com.micropythonos.appstore/assets

1 file changed

+183
-43
lines changed

internal_filesystem/builtin/apps/com.micropythonos.appstore/assets/appstore.py

Lines changed: 183 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,28 @@
77
import time
88
import _thread
99

10-
1110
from mpos.apps import Activity, Intent
1211
from mpos.app import App
1312
from mpos import TaskManager
1413
import mpos.ui
1514
from mpos.content.package_manager import PackageManager
1615

17-
1816
class AppStore(Activity):
17+
18+
_BADGEHUB_API_BASE_URL = "https://badgehub.p1m.nl/api/v3"
19+
_BADGEHUB_LIST = "project-summaries?badge=fri3d_2024"
20+
_BADGEHUB_DETAILS = "projects"
21+
22+
_BACKEND_API_GITHUB = "github"
23+
_BACKEND_API_BADGEHUB = "badgehub"
24+
1925
apps = []
20-
app_index_url = "https://apps.micropythonos.com/app_index.json"
26+
# These might become configurations:
27+
#backend_api = _BACKEND_API_BADGEHUB
28+
backend_api = _BACKEND_API_GITHUB
29+
app_index_url_github = "https://apps.micropythonos.com/app_index.json"
30+
app_index_url_badgehub = _BADGEHUB_API_BASE_URL + "/" + _BADGEHUB_LIST
31+
app_detail_url_badgehub = _BADGEHUB_API_BASE_URL + "/" + _BADGEHUB_DETAILS
2132
can_check_network = True
2233
aiohttp_session = None # one session for the whole app is more performant
2334

@@ -48,7 +59,10 @@ def onResume(self, screen):
4859
if self.can_check_network and not network.WLAN(network.STA_IF).isconnected():
4960
self.please_wait_label.set_text("Error: WiFi is not connected.")
5061
else:
51-
TaskManager.create_task(self.download_app_index(self.app_index_url))
62+
if self.backend_api == self._BACKEND_API_BADGEHUB:
63+
TaskManager.create_task(self.download_app_index(self.app_index_url_badgehub))
64+
else:
65+
TaskManager.create_task(self.download_app_index(self.app_index_url_github))
5266

5367
def onDestroy(self, screen):
5468
await self.aiohttp_session.close()
@@ -60,9 +74,14 @@ async def download_app_index(self, json_url):
6074
return
6175
print(f"Got response text: {response[0:20]}")
6276
try:
63-
for app in json.loads(response):
77+
parsed = json.loads(response)
78+
print(f"parsed json: {parsed}")
79+
for app in parsed:
6480
try:
65-
self.apps.append(App(app["name"], app["publisher"], app["short_description"], app["long_description"], app["icon_url"], app["download_url"], app["fullname"], app["version"], app["category"], app["activities"]))
81+
if self.backend_api == self._BACKEND_API_BADGEHUB:
82+
self.apps.append(AppStore.badgehub_app_to_mpos_app(app))
83+
else:
84+
self.apps.append(App(app["name"], app["publisher"], app["short_description"], app["long_description"], app["icon_url"], app["download_url"], app["fullname"], app["version"], app["category"], app["activities"]))
6685
except Exception as e:
6786
print(f"Warning: could not add app from {json_url} to apps list: {e}")
6887
except Exception as e:
@@ -157,6 +176,7 @@ async def download_icons(self):
157176
def show_app_detail(self, app):
158177
intent = Intent(activity_class=AppDetail)
159178
intent.putExtra("app", app)
179+
intent.putExtra("appstore", self)
160180
self.startActivity(intent)
161181

162182
async def download_url(self, url):
@@ -170,6 +190,86 @@ async def download_url(self, url):
170190
except Exception as e:
171191
print(f"download_url got exception {e}")
172192

193+
@staticmethod
194+
def badgehub_app_to_mpos_app(bhapp):
195+
#print(f"Converting {bhapp} to MPOS app object...")
196+
name = bhapp.get("name")
197+
print(f"Got app name: {name}")
198+
publisher = None
199+
short_description = bhapp.get("description")
200+
long_description = None
201+
try:
202+
icon_url = bhapp.get("icon_map").get("64x64").get("url")
203+
except Exception as e:
204+
icon_url = None
205+
print("Could not find icon_map 64x64 url")
206+
download_url = None
207+
fullname = bhapp.get("slug")
208+
version = None
209+
try:
210+
category = bhapp.get("categories")[0]
211+
except Exception as e:
212+
category = None
213+
print("Could not parse category")
214+
activities = None
215+
return App(name, publisher, short_description, long_description, icon_url, download_url, fullname, version, category, activities)
216+
217+
async def fetch_badgehub_app_details(self, app_obj):
218+
details_url = self.app_detail_url_badgehub + "/" + app_obj.fullname
219+
response = await self.download_url(details_url)
220+
if not response:
221+
print(f"Could not download app details from from\n{details_url}")
222+
return
223+
print(f"Got response text: {response[0:20]}")
224+
try:
225+
parsed = json.loads(response)
226+
print(f"parsed json: {parsed}")
227+
print("Using short_description as long_description because backend doesn't support it...")
228+
app_obj.long_description = app_obj.short_description
229+
print("Finding version number...")
230+
try:
231+
version = parsed.get("version")
232+
except Exception as e:
233+
print(f"Could not get version object from appdetails: {e}")
234+
return
235+
print(f"got version object: {version}")
236+
# Find .mpk download URL:
237+
try:
238+
files = version.get("files")
239+
for file in files:
240+
print(f"parsing file: {file}")
241+
ext = file.get("ext").lower()
242+
print(f"file has extension: {ext}")
243+
if ext == ".mpk":
244+
app_obj.download_url = file.get("url")
245+
break # only one .mpk per app is supported
246+
except Exception as e:
247+
print(f"Could not get files from version: {e}")
248+
try:
249+
app_metadata = version.get("app_metadata")
250+
except Exception as e:
251+
print(f"Could not get app_metadata object from version object: {e}")
252+
return
253+
try:
254+
author = app_metadata.get("author")
255+
print("Using author as publisher because that's all the backend supports...")
256+
app_obj.publisher = author
257+
except Exception as e:
258+
print(f"Could not get author from version object: {e}")
259+
try:
260+
app_version = app_metadata.get("version")
261+
print(f"what: {version.get('app_metadata')}")
262+
print(f"app has app_version: {app_version}")
263+
app_obj.version = app_version
264+
except Exception as e:
265+
print(f"Could not get version from app_metadata: {e}")
266+
except Exception as e:
267+
err = f"ERROR: could not parse app details JSON: {e}"
268+
print(err)
269+
self.please_wait_label.set_text(err)
270+
return
271+
272+
173273
class AppDetail(Activity):
174274

175275
action_label_install = "Install"
@@ -182,10 +282,19 @@ class AppDetail(Activity):
182282
update_button = None
183283
progress_bar = None
184284
install_label = None
285+
long_desc_label = None
286+
version_label = None
287+
buttoncont = None
288+
publisher_label = None
289+
290+
# Received from the Intent extras:
291+
app = None
292+
appstore = None
185293

186294
def onCreate(self):
187295
print("Creating app detail screen...")
188-
app = self.getIntent().extras.get("app")
296+
self.app = self.getIntent().extras.get("app")
297+
self.appstore = self.getIntent().extras.get("appstore")
189298
app_detail_screen = lv.obj()
190299
app_detail_screen.set_style_pad_all(5, 0)
191300
app_detail_screen.set_size(lv.pct(100), lv.pct(100))
@@ -200,10 +309,10 @@ def onCreate(self):
200309
headercont.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
201310
icon_spacer = lv.image(headercont)
202311
icon_spacer.set_size(64, 64)
203-
if app.icon_data:
312+
if self.app.icon_data:
204313
image_dsc = lv.image_dsc_t({
205-
'data_size': len(app.icon_data),
206-
'data': app.icon_data
314+
'data_size': len(self.app.icon_data),
315+
'data': self.app.icon_data
207316
})
208317
icon_spacer.set_src(image_dsc)
209318
else:
@@ -216,54 +325,80 @@ def onCreate(self):
216325
detail_cont.set_size(lv.pct(75), lv.SIZE_CONTENT)
217326
detail_cont.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
218327
name_label = lv.label(detail_cont)
219-
name_label.set_text(app.name)
328+
name_label.set_text(self.app.name)
220329
name_label.set_style_text_font(lv.font_montserrat_24, 0)
221-
publisher_label = lv.label(detail_cont)
222-
publisher_label.set_text(app.publisher)
223-
publisher_label.set_style_text_font(lv.font_montserrat_16, 0)
330+
self.publisher_label = lv.label(detail_cont)
331+
if self.app.publisher:
332+
self.publisher_label.set_text(self.app.publisher)
333+
else:
334+
self.publisher_label.set_text("Unknown publisher")
335+
self.publisher_label.set_style_text_font(lv.font_montserrat_16, 0)
224336

225337
self.progress_bar = lv.bar(app_detail_screen)
226338
self.progress_bar.set_width(lv.pct(100))
227339
self.progress_bar.set_range(0, 100)
228340
self.progress_bar.add_flag(lv.obj.FLAG.HIDDEN)
229341
# Always have this button:
230-
buttoncont = lv.obj(app_detail_screen)
231-
buttoncont.set_style_border_width(0, 0)
232-
buttoncont.set_style_radius(0, 0)
233-
buttoncont.set_style_pad_all(0, 0)
234-
buttoncont.set_flex_flow(lv.FLEX_FLOW.ROW)
235-
buttoncont.set_size(lv.pct(100), lv.SIZE_CONTENT)
236-
buttoncont.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
237-
print(f"Adding (un)install button for url: {app.download_url}")
342+
self.buttoncont = lv.obj(app_detail_screen)
343+
self.buttoncont.set_style_border_width(0, 0)
344+
self.buttoncont.set_style_radius(0, 0)
345+
self.buttoncont.set_style_pad_all(0, 0)
346+
self.buttoncont.set_flex_flow(lv.FLEX_FLOW.ROW)
347+
self.buttoncont.set_size(lv.pct(100), lv.SIZE_CONTENT)
348+
self.buttoncont.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
349+
self.add_action_buttons(self.buttoncont, self.app)
350+
# version label:
351+
self.version_label = lv.label(app_detail_screen)
352+
self.version_label.set_width(lv.pct(100))
353+
if self.app.version:
354+
self.version_label.set_text(f"Latest version: {self.app.version}") # would be nice to make this bold if this is newer than the currently installed one
355+
else:
356+
self.version_label.set_text(f"Unknown version")
357+
self.version_label.set_style_text_font(lv.font_montserrat_12, 0)
358+
self.version_label.align_to(self.install_button, lv.ALIGN.OUT_BOTTOM_MID, 0, lv.pct(5))
359+
self.long_desc_label = lv.label(app_detail_screen)
360+
self.long_desc_label.align_to(self.version_label, lv.ALIGN.OUT_BOTTOM_MID, 0, lv.pct(5))
361+
if self.app.long_description:
362+
self.long_desc_label.set_text(self.app.long_description)
363+
else:
364+
self.long_desc_label.set_text(self.app.short_description)
365+
self.long_desc_label.set_style_text_font(lv.font_montserrat_12, 0)
366+
self.long_desc_label.set_width(lv.pct(100))
367+
print("Loading app detail screen...")
368+
self.setContentView(app_detail_screen)
369+
370+
def onResume(self, screen):
371+
if self.appstore.backend_api == self.appstore._BACKEND_API_BADGEHUB:
372+
TaskManager.create_task(self.fetch_and_set_app_details())
373+
else:
374+
print("No need to fetch app details as the github app index already contains all the app data.")
375+
376+
def add_action_buttons(self, buttoncont, app):
377+
buttoncont.clean()
378+
print(f"Adding (un)install button for url: {self.app.download_url}")
238379
self.install_button = lv.button(buttoncont)
239-
self.install_button.add_event_cb(lambda e, d=app.download_url, f=app.fullname: self.toggle_install(d,f), lv.EVENT.CLICKED, None)
380+
self.install_button.add_event_cb(lambda e, a=self.app: self.toggle_install(a), lv.EVENT.CLICKED, None)
240381
self.install_button.set_size(lv.pct(100), 40)
241382
self.install_label = lv.label(self.install_button)
242383
self.install_label.center()
243-
self.set_install_label(app.fullname)
244-
if PackageManager.is_update_available(app.fullname, app.version):
384+
self.set_install_label(self.app.fullname)
385+
if app.version and PackageManager.is_update_available(self.app.fullname, app.version):
245386
self.install_button.set_size(lv.pct(47), 40) # make space for update button
246387
print("Update available, adding update button.")
247388
self.update_button = lv.button(buttoncont)
248389
self.update_button.set_size(lv.pct(47), 40)
249-
self.update_button.add_event_cb(lambda e, d=app.download_url, f=app.fullname: self.update_button_click(d,f), lv.EVENT.CLICKED, None)
390+
self.update_button.add_event_cb(lambda e, a=self.app: self.update_button_click(a), lv.EVENT.CLICKED, None)
250391
update_label = lv.label(self.update_button)
251392
update_label.set_text("Update")
252393
update_label.center()
253-
# version label:
254-
version_label = lv.label(app_detail_screen)
255-
version_label.set_width(lv.pct(100))
256-
version_label.set_text(f"Latest version: {app.version}") # make this bold if this is newer than the currently installed one
257-
version_label.set_style_text_font(lv.font_montserrat_12, 0)
258-
version_label.align_to(self.install_button, lv.ALIGN.OUT_BOTTOM_MID, 0, lv.pct(5))
259-
long_desc_label = lv.label(app_detail_screen)
260-
long_desc_label.align_to(version_label, lv.ALIGN.OUT_BOTTOM_MID, 0, lv.pct(5))
261-
long_desc_label.set_text(app.long_description)
262-
long_desc_label.set_style_text_font(lv.font_montserrat_12, 0)
263-
long_desc_label.set_width(lv.pct(100))
264-
print("Loading app detail screen...")
265-
self.setContentView(app_detail_screen)
266-
394+
395+
async def fetch_and_set_app_details(self):
396+
await self.appstore.fetch_badgehub_app_details(self.app)
397+
print(f"app has version: {self.app.version}")
398+
self.version_label.set_text(self.app.version)
399+
self.long_desc_label.set_text(self.app.long_description)
400+
self.publisher_label.set_text(self.app.publisher)
401+
self.add_action_buttons(self.buttoncont, self.app)
267402

268403
def set_install_label(self, app_fullname):
269404
# Figure out whether to show:
@@ -292,8 +427,11 @@ def set_install_label(self, app_fullname):
292427
action_label = self.action_label_install
293428
self.install_label.set_text(action_label)
294429

295-
def toggle_install(self, download_url, fullname):
296-
print(f"Install button clicked for {download_url} and fullname {fullname}")
430+
def toggle_install(self, app_obj):
431+
print(f"Install button clicked for {app_obj}")
432+
download_url = app_obj.download_url
433+
fullname = app_obj.fullname
434+
print(f"With {download_url} and fullname {fullname}")
297435
label_text = self.install_label.get_text()
298436
if label_text == self.action_label_install:
299437
try:
@@ -309,7 +447,9 @@ def toggle_install(self, download_url, fullname):
309447
except Exception as e:
310448
print("Could not start uninstall_app thread: ", e)
311449

312-
def update_button_click(self, download_url, fullname):
450+
def update_button_click(self, app_obj):
451+
download_url = app_obj.download_url
452+
fullname = app_obj.fullname
313453
print(f"Update button clicked for {download_url} and fullname {fullname}")
314454
self.update_button.add_flag(lv.obj.FLAG.HIDDEN)
315455
self.install_button.set_size(lv.pct(100), 40)

0 commit comments

Comments
 (0)