99from mpos import TaskManager , DownloadManager
1010import mpos .ui
1111from mpos .content .package_manager import PackageManager
12+ from mpos .config import SharedPreferences
1213
1314class AppStore (Activity ):
1415
15- _BADGEHUB_API_BASE_URL = "https://badgehub.p1m.nl/api/v3"
16+ PACKAGE = "com.micropythonos.appstore"
17+
18+ _GITHUB_PROD_BASE_URL = "https://apps.micropythonos.com"
19+ _GITHUB_LIST = "/app_index.json"
20+
21+ _BADGEHUB_TEST_BASE_URL = "https://badgehub.p1m.nl/api/v3"
22+ _BADGEHUB_PROD_BASE_URL = "https://badge.why2025.org/api/v3"
1623 _BADGEHUB_LIST = "project-summaries?badge=fri3d_2024"
1724 _BADGEHUB_DETAILS = "projects"
1825
1926 _BACKEND_API_GITHUB = "github"
2027 _BACKEND_API_BADGEHUB = "badgehub"
2128
2229 apps = []
23- # These might become configurations:
24- #backend_api = _BACKEND_API_BADGEHUB
25- backend_api = _BACKEND_API_GITHUB
26- app_index_url_github = "https://apps.micropythonos.com/app_index.json"
27- app_index_url_badgehub = _BADGEHUB_API_BASE_URL + "/" + _BADGEHUB_LIST
28- app_detail_url_badgehub = _BADGEHUB_API_BASE_URL + "/" + _BADGEHUB_DETAILS
30+
31+ _DEFAULT_BACKEND = 0
32+ _ICON_SIZE = 64
33+
34+ # Hardcoded list for now:
35+ backends = [
36+ ("MPOS GitHub" , _BACKEND_API_GITHUB , _GITHUB_PROD_BASE_URL , _GITHUB_LIST , None ),
37+ ("BadgeHub Test" , _BACKEND_API_BADGEHUB , _BADGEHUB_TEST_BASE_URL , _BADGEHUB_LIST , _BADGEHUB_DETAILS ),
38+ ("BadgeHub Prod" , _BACKEND_API_BADGEHUB , _BADGEHUB_PROD_BASE_URL , _BADGEHUB_LIST , _BADGEHUB_DETAILS )
39+ ]
40+
41+ @staticmethod
42+ def get_backend_urls (index ):
43+ backend_info = AppStore .backends [index ]
44+ if backend_info :
45+ api = backend_info [1 ]
46+ base_url = backend_info [2 ]
47+ list_suffix = backend_info [3 ]
48+ details_suffix = backend_info [4 ]
49+ if api == AppStore ._BACKEND_API_GITHUB :
50+ return (base_url + "/" + list_suffix , None )
51+ else :
52+ return (base_url + "/" + list_suffix , base_url + "/" + details_suffix )
53+
54+ @staticmethod
55+ def get_backend_type (index ):
56+ backend_info = AppStore .backends [index ]
57+ if backend_info :
58+ return backend_info [1 ]
59+
60+ def get_backend_urls_from_settings (self ):
61+ return AppStore .get_backend_urls (self .prefs .get_int ("backend" , self ._DEFAULT_BACKEND ))
62+
63+ def get_backend_list_url_from_settings (self ):
64+ return self .get_backend_urls_from_settings ()[0 ]
65+
66+ def get_backend_details_url_from_settings ():
67+ return self .get_backend_urls_from_settings ()[1 ]
68+
2969 can_check_network = True
70+ prefs = None
3071
3172 # Widgets:
3273 main_screen = None
@@ -35,29 +76,63 @@ class AppStore(Activity):
3576 install_label = None
3677 please_wait_label = None
3778 progress_bar = None
79+ settings_button = None
3880
3981 def onCreate (self ):
4082 self .main_screen = lv .obj ()
4183 self .please_wait_label = lv .label (self .main_screen )
4284 self .please_wait_label .set_text ("Downloading app index..." )
4385 self .please_wait_label .center ()
86+ self .settings_button = lv .button (self .main_screen )
87+ settings_margin = 15
88+ settings_size = self ._ICON_SIZE - settings_margin
89+ self .settings_button .set_size (settings_size , settings_size )
90+ self .settings_button .align (lv .ALIGN .TOP_RIGHT , - settings_margin , 10 )
91+ self .settings_button .add_event_cb (self .settings_button_tap ,lv .EVENT .CLICKED ,None )
92+ #self.settings_button.add_flag(lv.obj.FLAG.HIDDEN) # hide because not functional for now
93+ settings_label = lv .label (self .settings_button )
94+ settings_label .set_text (lv .SYMBOL .SETTINGS )
95+ settings_label .set_style_text_font (lv .font_montserrat_24 , 0 )
96+ settings_label .center ()
4497 self .setContentView (self .main_screen )
4598
4699 def onResume (self , screen ):
47100 super ().onResume (screen )
101+ # This gets called at startup and also after closing AppStoreSettings
48102 if len (self .apps ):
49- return # already downloaded them
103+ return # already have the list (if refresh after settings is needed, finished_settings_callback will do it)
104+ if self .prefs : # prefs is abused to distinguish between a fresh start and a return after AppStoreSettings
105+ return # prefs is set so it's not a fresh start - it's a return after after AppStoreSettings
106+ print ("It's a fresh start; loading preferences and refreshing list..." )
107+ self .prefs = SharedPreferences (self .PACKAGE )
108+ self .refresh_list ()
109+
110+ def refresh_list (self ):
50111 try :
51112 import network
52113 except Exception as e :
53114 self .can_check_network = False
54115 if self .can_check_network and not network .WLAN (network .STA_IF ).isconnected ():
116+ self .please_wait_label .remove_flag (lv .obj .FLAG .HIDDEN ) # make sure it's visible
55117 self .please_wait_label .set_text ("Error: WiFi is not connected." )
56118 else :
57- if self .backend_api == self ._BACKEND_API_BADGEHUB :
58- TaskManager .create_task (self .download_app_index (self .app_index_url_badgehub ))
59- else :
60- TaskManager .create_task (self .download_app_index (self .app_index_url_github ))
119+ TaskManager .create_task (self .download_app_index (self .get_backend_list_url_from_settings ()))
120+
121+ def settings_button_tap (self , event ):
122+ print ("Settings button clicked" )
123+ # Handle traditional settings (existing code)
124+ intent = Intent (activity_class = AppStoreSettings )
125+ intent .putExtra ("prefs" , self .prefs )
126+ intent .putExtra ("setting" , {"title" : "Backend" , "key" : "backend" , "value_label" : None , "cont" : None , "ui" : "radiobuttons" , "ui_options" : [(backend [0 ], None ) for backend in AppStore .backends ]},)
127+ self .startActivityForResult (intent , self .finished_settings_callback )
128+
129+ def finished_settings_callback (self , result ):
130+ print (f"finished_settings_callback result: { result } " )
131+ if result .get ("result_code" ) is True :
132+ print ("Settings updated, reloading app list..." )
133+ self .refresh_list ()
134+ else :
135+ print ("Settings not updated, nothing to do." )
61136
62137 async def download_app_index (self , json_url ):
63138 try :
@@ -75,7 +150,8 @@ async def download_app_index(self, json_url):
75150 print (f"parsed json: { parsed } " )
76151 for app in parsed :
77152 try :
78- if self .backend_api == self ._BACKEND_API_BADGEHUB :
153+ backend_type = AppStore .get_backend_type (self .prefs .get_int ("backend" , self ._DEFAULT_BACKEND ))
154+ if backend_type == self ._BACKEND_API_BADGEHUB :
79155 self .apps .append (AppStore .badgehub_app_to_mpos_app (app ))
80156 else :
81157 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" ]))
@@ -110,7 +186,7 @@ def create_apps_list(self):
110186 print ("create_apps_list iterating" )
111187 for app in self .apps :
112188 print (app )
113- item = apps_list .add_button (None , "Test " )
189+ item = apps_list .add_button (None , "" )
114190 item .set_style_pad_all (0 , 0 )
115191 item .set_size (lv .pct (100 ), lv .SIZE_CONTENT )
116192 item .add_event_cb (lambda e , a = app : self .show_app_detail (a ), lv .EVENT .CLICKED , None )
@@ -123,7 +199,7 @@ def create_apps_list(self):
123199 cont .set_style_radius (0 , 0 )
124200 cont .add_event_cb (lambda e , a = app : self .show_app_detail (a ), lv .EVENT .CLICKED , None )
125201 icon_spacer = lv .image (cont )
126- icon_spacer .set_size (64 , 64 )
202+ icon_spacer .set_size (self . _ICON_SIZE , self . _ICON_SIZE )
127203 icon_spacer .set_src (lv .SYMBOL .REFRESH )
128204 icon_spacer .add_event_cb (lambda e , a = app : self .show_app_detail (a ), lv .EVENT .CLICKED , None )
129205 app .image_icon_widget = icon_spacer # save it so it can be later set to the actual image
@@ -141,7 +217,9 @@ def create_apps_list(self):
141217 desc_label .set_text (app .short_description )
142218 desc_label .set_style_text_font (lv .font_montserrat_12 , 0 )
143219 desc_label .add_event_cb (lambda e , a = app : self .show_app_detail (a ), lv .EVENT .CLICKED , None )
144- print ("create_apps_list app done" )
220+ print ("create_apps_list done" )
221+ # Settings button needs to float in foreground:
222+ self .settings_button .move_to_index (- 1 )
145223
146224 async def download_icons (self ):
147225 print ("Downloading icons..." )
@@ -201,7 +279,7 @@ def badgehub_app_to_mpos_app(bhapp):
201279 return App (name , publisher , short_description , long_description , icon_url , download_url , fullname , version , category , activities )
202280
203281 async def fetch_badgehub_app_details (self , app_obj ):
204- details_url = self .app_detail_url_badgehub + "/" + app_obj . fullname
282+ details_url = self .get_backend_details_url_from_settings ()
205283 try :
206284 response = await DownloadManager .download_url (details_url )
207285 except Exception as e :
@@ -356,7 +434,8 @@ def onCreate(self):
356434 self .setContentView (app_detail_screen )
357435
358436 def onResume (self , screen ):
359- if self .appstore .backend_api == self .appstore ._BACKEND_API_BADGEHUB :
437+ backend_type = AppStore .get_backend_type (self .prefs .get_int ("backend" , self ._DEFAULT_BACKEND ))
438+ if backend_type == self .appstore ._BACKEND_API_BADGEHUB :
360439 TaskManager .create_task (self .fetch_and_set_app_details ())
361440 else :
362441 print ("No need to fetch app details as the github app index already contains all the app data." )
@@ -524,3 +603,17 @@ async def download_and_install(self, app_obj, dest_folder):
524603 self .progress_bar .set_value (0 , False )
525604 self .set_install_label (app_fullname )
526605 self .install_button .remove_state (lv .STATE .DISABLED )
606+
607+
608+ class AppStoreSettings (Activity ):
609+ prefs = None
610+
611+ def onCreate (self ):
612+ self .prefs = self .getIntent ().extras .get ("prefs" )
613+ # Create main screen
614+ screen = lv .obj ()
615+ screen .set_size (lv .pct (100 ), lv .pct (100 ))
616+ screen .set_style_pad_all (1 , 0 )
617+ label = lv .label (screen )
618+ label .set_text ("AppStoreSettings should go here." )
619+ self .setContentView (screen )
0 commit comments