You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Piggy: use Intents to start new Activities
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from mpos.apps import Activity
|
||||
from mpos.apps import Activity, Intent
|
||||
import mpos.config
|
||||
import mpos.ui
|
||||
|
||||
@@ -10,6 +10,7 @@ class MainActivity(Activity):
|
||||
def __init__(self):
|
||||
self.wallet = None
|
||||
self.receive_qr_data = None
|
||||
self.destination = None
|
||||
# widgets
|
||||
self.balance_label = None
|
||||
self.receive_qr = None
|
||||
@@ -84,8 +85,9 @@ class MainActivity(Activity):
|
||||
self.payments_label.set_text(f"Could not start {wallet_type} backend.")
|
||||
|
||||
def onStop(self, main_screen):
|
||||
if self.wallet:
|
||||
if self.wallet and self.destination != FullscreenQR:
|
||||
self.wallet.stop()
|
||||
self.destination = None
|
||||
|
||||
def redraw_balance_cb(self):
|
||||
# this gets called from another thread (the wallet) so make sure it happens in the LVGL thread using lv.async_call():
|
||||
@@ -95,30 +97,20 @@ class MainActivity(Activity):
|
||||
# this gets called from another thread (the wallet) so make sure it happens in the LVGL thread using lv.async_call():
|
||||
lv.async_call(lambda l: self.payments_label.set_text(str(self.wallet.payment_list)), None)
|
||||
|
||||
|
||||
def settings_button_tap(self, event):
|
||||
settings_activity = SettingsActivity()
|
||||
settings_activity.onCreate()
|
||||
self.startActivity(Intent(activity_class=SettingsActivity))
|
||||
|
||||
def main_ui_set_defaults(self):
|
||||
self.balance_label.set_text(lv.SYMBOL.REFRESH)
|
||||
self.payments_label.set_text(lv.SYMBOL.REFRESH)
|
||||
self.receive_qr.update("EMPTY", len("EMPTY"))
|
||||
self.receive_qr.update("EMPTY PLACEHOLDER", len("EMPTY PLACEHOLDER"))
|
||||
|
||||
def qr_clicked_cb(self, event):
|
||||
print("QR clicked")
|
||||
if not self.receive_qr_data:
|
||||
return
|
||||
print("QR clicked")
|
||||
qr_screen = lv.obj()
|
||||
big_receive_qr = lv.qrcode(qr_screen)
|
||||
big_receive_qr.set_size(240) # TODO: make this dynamic
|
||||
big_receive_qr.set_dark_color(lv.color_black())
|
||||
big_receive_qr.set_light_color(lv.color_white())
|
||||
big_receive_qr.center()
|
||||
big_receive_qr.set_style_border_color(lv.color_white(), 0)
|
||||
big_receive_qr.set_style_border_width(3, 0);
|
||||
big_receive_qr.update(self.receive_qr_data, len(self.receive_qr_data))
|
||||
mpos.ui.load_screen(qr_screen)
|
||||
self.destination = FullscreenQR
|
||||
self.startActivity(Intent(activity_class=FullscreenQR).putExtra("receive_qr_data", self.receive_qr_data))
|
||||
|
||||
# Used to list and edit all settings:
|
||||
class SettingsActivity(Activity):
|
||||
@@ -190,18 +182,19 @@ class SettingsActivity(Activity):
|
||||
setting["cont"].remove_flag(lv.obj.FLAG.HIDDEN)
|
||||
|
||||
def startSettingActivity(self, setting):
|
||||
sa = SettingActivity(setting)
|
||||
sa.onCreate()
|
||||
|
||||
intent = Intent(activity_class=SettingActivity)
|
||||
intent.putExtra("setting", setting)
|
||||
self.startActivity(intent)
|
||||
|
||||
# Used to edit one setting:
|
||||
class SettingActivity(Activity):
|
||||
def __init__(self, setting):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.prefs = mpos.config.SharedPreferences("com.lightningpiggy.displaywallet")
|
||||
self.setting = setting
|
||||
self.setting = None
|
||||
|
||||
def onCreate(self):
|
||||
setting = self.getIntent().extras.get("setting")
|
||||
settings_screen_detail = lv.obj()
|
||||
settings_screen_detail.set_style_pad_all(10, 0)
|
||||
settings_screen_detail.set_flex_flow(lv.FLEX_FLOW.COLUMN)
|
||||
@@ -214,7 +207,7 @@ class SettingActivity(Activity):
|
||||
top_cont.set_style_flex_main_place(lv.FLEX_ALIGN.SPACE_BETWEEN, 0)
|
||||
|
||||
setting_label = lv.label(top_cont)
|
||||
setting_label.set_text(self.setting["title"])
|
||||
setting_label.set_text(setting["title"])
|
||||
setting_label.align(lv.ALIGN.TOP_LEFT,0,0)
|
||||
setting_label.set_style_text_font(lv.font_montserrat_22, 0)
|
||||
|
||||
@@ -226,7 +219,7 @@ class SettingActivity(Activity):
|
||||
cambuttonlabel.center()
|
||||
cambutton.add_event_cb(self.cambutton_cb, lv.EVENT.CLICKED, None)
|
||||
|
||||
if self.setting["key"] == "wallet_type":
|
||||
if setting["key"] == "wallet_type":
|
||||
cambutton.add_flag(lv.obj.FLAG.HIDDEN)
|
||||
# Create container for radio buttons
|
||||
self.radio_container = lv.obj(settings_screen_detail)
|
||||
@@ -249,7 +242,7 @@ class SettingActivity(Activity):
|
||||
self.textarea = lv.textarea(settings_screen_detail)
|
||||
self.textarea.set_width(lv.pct(100))
|
||||
self.textarea.set_height(lv.SIZE_CONTENT)
|
||||
self.textarea.set_text(self.prefs.get_string(self.setting["key"], ""))
|
||||
self.textarea.set_text(self.prefs.get_string(setting["key"], ""))
|
||||
self.textarea.add_event_cb(self.show_keyboard, lv.EVENT.CLICKED, None)
|
||||
self.textarea.add_event_cb(self.show_keyboard, lv.EVENT.FOCUSED, None)
|
||||
self.textarea.add_event_cb(self.hide_keyboard, lv.EVENT.DEFOCUSED, None)
|
||||
@@ -275,7 +268,7 @@ class SettingActivity(Activity):
|
||||
save_label = lv.label(save_btn)
|
||||
save_label.set_text("Save")
|
||||
save_label.center()
|
||||
save_btn.add_event_cb(lambda e, s=self.setting: self.save_setting(s), lv.EVENT.CLICKED, None)
|
||||
save_btn.add_event_cb(lambda e, s=setting: self.save_setting(s), lv.EVENT.CLICKED, None)
|
||||
# Cancel button
|
||||
cancel_btn = lv.button(btn_cont)
|
||||
cancel_btn.set_size(lv.pct(45), lv.SIZE_CONTENT)
|
||||
@@ -354,3 +347,18 @@ class SettingActivity(Activity):
|
||||
setting["value_label"].set_text(new_value if new_value else "Not set")
|
||||
self.finish()
|
||||
|
||||
|
||||
class FullscreenQR(Activity):
|
||||
|
||||
def onCreate(self):
|
||||
receive_qr_data = self.getIntent().extras.get("receive_qr_data")
|
||||
qr_screen = lv.obj()
|
||||
big_receive_qr = lv.qrcode(qr_screen)
|
||||
big_receive_qr.set_size(240) # TODO: make this dynamic
|
||||
big_receive_qr.set_dark_color(lv.color_black())
|
||||
big_receive_qr.set_light_color(lv.color_white())
|
||||
big_receive_qr.center()
|
||||
big_receive_qr.set_style_border_color(lv.color_white(), 0)
|
||||
big_receive_qr.set_style_border_width(3, 0);
|
||||
big_receive_qr.update(receive_qr_data, len(receive_qr_data))
|
||||
self.setContentView(qr_screen)
|
||||
|
||||
@@ -193,6 +193,12 @@ def auto_connect():
|
||||
|
||||
class Activity:
|
||||
|
||||
def __init__(self):
|
||||
self.intent = None # Store the intent that launched this activity
|
||||
|
||||
def getIntent(self):
|
||||
return self.intent
|
||||
|
||||
def onCreate(self):
|
||||
pass
|
||||
def onStart(self, screen):
|
||||
@@ -211,3 +217,153 @@ class Activity:
|
||||
|
||||
def finish(self):
|
||||
mpos.ui.back_screen()
|
||||
|
||||
def startActivity(self, intent):
|
||||
ActivityNavigator.startActivity(intent)
|
||||
|
||||
class Intent:
|
||||
def __init__(self, activity_class=None, action=None, data=None, extras=None):
|
||||
self.activity_class = activity_class # Explicit target (e.g., SettingsActivity)
|
||||
self.action = action # Action string (e.g., "view", "share")
|
||||
self.data = data # Single data item (e.g., URL)
|
||||
self.extras = extras or {} # Dictionary for additional data
|
||||
self.flags = {} # Simplified flags: {"clear_top": bool, "no_history": bool, "no_animation": bool}
|
||||
|
||||
def addFlag(self, flag, value=True):
|
||||
self.flags[flag] = value
|
||||
return self
|
||||
|
||||
def putExtra(self, key, value):
|
||||
self.extras[key] = value
|
||||
return self
|
||||
|
||||
|
||||
class ActivityNavigator:
|
||||
|
||||
def startActivity(intent):
|
||||
if not isinstance(intent, Intent):
|
||||
raise ValueError("Must provide an Intent")
|
||||
if intent.action: # Implicit intent: resolve handlers
|
||||
handlers = APP_REGISTRY.get(intent.action, [])
|
||||
if len(handlers) == 1:
|
||||
intent.activity_class = handlers[0]
|
||||
ActivityNavigator._launch_activity(intent)
|
||||
elif handlers:
|
||||
_show_chooser(intent, handlers)
|
||||
else:
|
||||
raise ValueError(f"No handlers for action: {intent.action}")
|
||||
else:
|
||||
# Explicit intent
|
||||
ActivityNavigator._launch_activity(intent)
|
||||
|
||||
def _launch_activity(intent):
|
||||
activity = intent.activity_class()
|
||||
activity.intent = intent
|
||||
activity.onCreate()
|
||||
|
||||
def _show_chooser(intent, handlers):
|
||||
chooser_intent = Intent(ChooserActivity, extras={"original_intent": intent, "handlers": [h.__name__ for h in handlers]})
|
||||
_launch_activity(chooser_intent)
|
||||
|
||||
|
||||
class ChooserActivity(Activity):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def onCreate(self):
|
||||
screen = lv.obj()
|
||||
# Get handlers from intent extras
|
||||
original_intent = self.getIntent().extras.get("original_intent")
|
||||
handlers = self.getIntent().extras.get("handlers", [])
|
||||
label = lv.label(screen)
|
||||
label.set_text("Choose an app")
|
||||
label.set_pos(10, 10)
|
||||
|
||||
for i, handler_name in enumerate(handlers):
|
||||
btn = lv.btn(screen)
|
||||
btn.set_user_data(f"handler_{i}")
|
||||
btn_label = lv.label(btn)
|
||||
btn_label.set_text(handler_name)
|
||||
btn.set_pos(10, 50 * (i + 1) + 10)
|
||||
btn.add_event_cb(lambda e, h=handler_name, oi=original_intent: self._select_handler(h, oi), lv.EVENT.CLICKED)
|
||||
self.setContentView(screen)
|
||||
|
||||
def _select_handler(self, handler_name, original_intent):
|
||||
for handler in APP_REGISTRY.get(original_intent.action, []):
|
||||
if handler.__name__ == handler_name:
|
||||
original_intent.activity_class = handler
|
||||
navigator.startActivity(original_intent)
|
||||
break
|
||||
navigator.finish() # Close chooser
|
||||
|
||||
def onStop(self, screen):
|
||||
if self.getIntent() and self.getIntent().getStringExtra("destination") == "ChooserActivity":
|
||||
print("Stopped for Chooser")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
|
||||
class ViewActivity(Activity):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def onCreate(self):
|
||||
screen = lv.obj()
|
||||
# Get content from intent (prefer extras.url, fallback to data)
|
||||
content = self.getIntent().extras.get("url", self.getIntent().data or "No content")
|
||||
label = lv.label(screen)
|
||||
label.set_user_data("content_label")
|
||||
label.set_text(f"Viewing: {content}")
|
||||
label.center()
|
||||
self.setContentView(screen)
|
||||
|
||||
def onStart(self, screen):
|
||||
content = self.getIntent().extras.get("url", self.getIntent().data or "No content")
|
||||
for i in range(screen.get_child_cnt()):
|
||||
if screen.get_child(i).get_user_data() == "content_label":
|
||||
screen.get_child(i).set_text(f"Viewing: {content}")
|
||||
|
||||
def onStop(self, screen):
|
||||
if self.getIntent() and self.getIntent().getStringExtra("destination") == "ViewActivity":
|
||||
print("Stopped for View")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
class ShareActivity(Activity):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def onCreate(self):
|
||||
screen = lv.obj()
|
||||
# Get text from intent (prefer extras.text, fallback to data)
|
||||
text = self.getIntent().extras.get("text", self.getIntent().data or "No text")
|
||||
label = lv.label(screen)
|
||||
label.set_user_data("share_label")
|
||||
label.set_text(f"Share: {text}")
|
||||
label.set_pos(10, 10)
|
||||
|
||||
btn = lv.btn(screen)
|
||||
btn.set_user_data("share_btn")
|
||||
btn_label = lv.label(btn)
|
||||
btn_label.set_text("Share")
|
||||
btn.set_pos(10, 50)
|
||||
btn.add_event_cb(lambda e: self._share_content(text), lv.EVENT.CLICKED)
|
||||
self.setContentView(screen)
|
||||
|
||||
def _share_content(self, text):
|
||||
# Dispatch to another app (e.g., MessagingActivity) or simulate sharing
|
||||
print(f"Sharing: {text}") # Placeholder for actual sharing
|
||||
# Example: Launch another share handler
|
||||
navigator.startActivity(Intent(action="share", data=text))
|
||||
navigator.finish() # Close ShareActivity
|
||||
|
||||
def onStop(self, screen):
|
||||
if self.getIntent() and self.getIntent().getStringExtra("destination") == "ShareActivity":
|
||||
print("Stopped for Share")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
APP_REGISTRY = { # This should be handled by a new class PackageManager:
|
||||
"view": [ViewActivity], # Hypothetical activities
|
||||
"share": [ShareActivity]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user