You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Dependency hell
This commit is contained in:
@@ -9,7 +9,7 @@ import _thread
|
||||
from mpos.apps import Activity, Intent
|
||||
from mpos.app import App
|
||||
import mpos.ui
|
||||
from mpos.package_manager import PackageManager
|
||||
from mpos.content.pm import PackageManager
|
||||
|
||||
|
||||
class AppStore(Activity):
|
||||
|
||||
@@ -14,7 +14,7 @@ import lvgl as lv
|
||||
|
||||
import mpos.apps
|
||||
import mpos.ui
|
||||
from mpos.package_manager import PackageManager
|
||||
from mpos.content.pm import PackageManager
|
||||
from mpos import Activity
|
||||
|
||||
class Launcher(Activity):
|
||||
|
||||
@@ -3,7 +3,7 @@ from .app.app import App
|
||||
from .app.activity import Activity
|
||||
from .content.intent import Intent
|
||||
from .navigator import ActivityNavigator
|
||||
from .package_manager import PackageManager
|
||||
from .content.pm import PackageManager
|
||||
|
||||
# Optional: re-export activities
|
||||
from .app.activities.chooser import ChooserActivity
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Import all activity modules → triggers self-registration
|
||||
from .chooser import ChooserActivity
|
||||
from .view import ViewActivity
|
||||
from .share import ShareActivity
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from ..activity import Activity
|
||||
# Chooser doesn't handle an action — it shows handlers
|
||||
# → No registration needed
|
||||
|
||||
import mpos.package_manager
|
||||
from ...content.pm import PackageManager
|
||||
|
||||
class ChooserActivity(Activity):
|
||||
def __init__(self):
|
||||
@@ -25,7 +27,7 @@ class ChooserActivity(Activity):
|
||||
self.setContentView(screen)
|
||||
|
||||
def _select_handler(self, handler_name, original_intent):
|
||||
for handler in mpos.package_manager.PackageManager.APP_REGISTRY.get(original_intent.action, []):
|
||||
for handler in PackageManager.APP_REGISTRY.get(original_intent.action, []):
|
||||
if handler.__name__ == handler_name:
|
||||
original_intent.activity_class = handler
|
||||
navigator.startActivity(original_intent)
|
||||
@@ -37,3 +39,5 @@ class ChooserActivity(Activity):
|
||||
print("Stopped for Chooser")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from ..activity import Activity
|
||||
from ...content.pm import PackageManager
|
||||
|
||||
class ShareActivity(Activity):
|
||||
def __init__(self):
|
||||
@@ -33,3 +34,5 @@ class ShareActivity(Activity):
|
||||
print("Stopped for Share")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
PackageManager.register_activity("share", ShareActivity)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from ..activity import Activity
|
||||
from ...content.pm import PackageManager
|
||||
|
||||
class ViewActivity(Activity):
|
||||
def __init__(self):
|
||||
@@ -25,3 +26,6 @@ class ViewActivity(Activity):
|
||||
print("Stopped for View")
|
||||
else:
|
||||
print("Stopped for other screen")
|
||||
|
||||
# Register this activity for "view" intents
|
||||
PackageManager.register_activity("view", ViewActivity)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from mpos.navigator import ActivityNavigator
|
||||
#from mpos.navigator import ActivityNavigator
|
||||
|
||||
import mpos.ui
|
||||
|
||||
@@ -26,7 +26,10 @@ class Activity:
|
||||
mpos.ui.setContentView(self, screen)
|
||||
|
||||
def startActivity(self, intent):
|
||||
ActivityNavigator.startActivity(intent)
|
||||
if not hasattr(self, 'app') or not self.app:
|
||||
print("ERROR: Activity has no .app – cannot startActivity")
|
||||
return
|
||||
self.app.start_activity(intent)
|
||||
|
||||
def startActivityForResult(self, intent, result_callback):
|
||||
ActivityNavigator.startActivityForResult(intent, result_callback)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ujson
|
||||
#from ..content.intent import Intent # optional, if App uses Intent
|
||||
|
||||
from ..navigator import ActivityNavigator
|
||||
|
||||
class App:
|
||||
def __init__(
|
||||
@@ -71,3 +71,7 @@ class App:
|
||||
activities=data.get("activities", default.activities),
|
||||
installed_path=appdir,
|
||||
)
|
||||
|
||||
def start_activity(self, intent):
|
||||
"""Android-like: App.startActivity(Intent)"""
|
||||
return ActivityNavigator.startActivity(intent)
|
||||
|
||||
@@ -11,7 +11,7 @@ import traceback
|
||||
import mpos.info
|
||||
import mpos.ui
|
||||
from mpos import Activity, Intent
|
||||
from mpos.package_manager import PackageManager
|
||||
from mpos.content.pm import PackageManager
|
||||
|
||||
def good_stack_size():
|
||||
stacksize = 24*1024
|
||||
@@ -21,7 +21,7 @@ def good_stack_size():
|
||||
return stacksize
|
||||
|
||||
# Run the script in the current thread:
|
||||
def execute_script(script_source, is_file, cwd=None, classname=None):
|
||||
def execute_script(script_source, is_file, cwd=None, classname=None, app=None):
|
||||
import utime # for timing read and compile
|
||||
thread_id = _thread.get_ident()
|
||||
compile_name = 'script' if not is_file else script_source
|
||||
@@ -63,7 +63,13 @@ def execute_script(script_source, is_file, cwd=None, classname=None):
|
||||
main_activity = script_globals.get(classname)
|
||||
if main_activity:
|
||||
start_time = utime.ticks_ms()
|
||||
Activity.startActivity(None, Intent(activity_class=main_activity))
|
||||
from mpos.app.activity import Activity as BaseActivity
|
||||
if app:
|
||||
dummy = BaseActivity()
|
||||
dummy.app = app
|
||||
returned_activity = dummy.startActivity(Intent(activity_class=main_activity))
|
||||
else:
|
||||
print("Warning: app not found in PackageManager")
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: Activity.startActivity took {end_time}ms")
|
||||
else:
|
||||
@@ -123,7 +129,7 @@ def start_app(fullname):
|
||||
print(f"WARNING: start_app can't start {fullname} because it doesn't have a main_launcher_activity")
|
||||
return
|
||||
start_script_fullpath = f"{app.installed_path}/{app.main_launcher_activity.get('entrypoint')}"
|
||||
execute_script(start_script_fullpath, True, app.installed_path + "/assets/", app.main_launcher_activity.get("classname"))
|
||||
execute_script(start_script_fullpath, True, app.installed_path + "/assets/", app.main_launcher_activity.get("classname"), app)
|
||||
# Launchers have the bar, other apps don't have it
|
||||
if app.is_valid_launcher():
|
||||
mpos.ui.topmenu.open_bar()
|
||||
@@ -137,7 +143,7 @@ def restart_launcher():
|
||||
print("restart_launcher")
|
||||
mpos.ui.empty_screen_stack()
|
||||
# No need to stop the other launcher first, because it exits after building the screen
|
||||
for app in mpos.package_manager.PackageManager.get_app_list():
|
||||
for app in PackageManager.get_app_list():
|
||||
if app.is_valid_launcher():
|
||||
print(f"Found launcher, starting {app.fullname}")
|
||||
start_app(app.fullname)
|
||||
|
||||
+20
-26
@@ -1,9 +1,5 @@
|
||||
import os
|
||||
|
||||
from mpos.app.app import App
|
||||
from mpos.app.activities.view import ViewActivity
|
||||
from mpos.app.activities.share import ShareActivity
|
||||
|
||||
try:
|
||||
import zipfile
|
||||
except ImportError:
|
||||
@@ -33,10 +29,25 @@ Question: does it make sense to cache the database?
|
||||
|
||||
class PackageManager:
|
||||
|
||||
APP_REGISTRY = {
|
||||
"view": [ViewActivity],
|
||||
"share": [ShareActivity]
|
||||
}
|
||||
_registry = {} # action → [ActivityClass, ...]
|
||||
|
||||
@classmethod
|
||||
def register_activity(cls, action, activity_cls):
|
||||
"""Called by each activity module to register itself."""
|
||||
if action not in cls._registry:
|
||||
cls._registry[action] = []
|
||||
if activity_cls not in cls._registry[action]:
|
||||
cls._registry[action].append(activity_cls)
|
||||
|
||||
@classmethod
|
||||
def resolve_activity(cls, intent):
|
||||
"""Return list of Activity classes that handle the intent.action."""
|
||||
return cls._registry.get(intent.action, [])
|
||||
|
||||
@classmethod
|
||||
def query_intent_activities(cls, intent):
|
||||
"""Same as resolve_activity – more Android-like name."""
|
||||
return cls.resolve_activity(intent)
|
||||
|
||||
"""Registry of all discovered apps.
|
||||
|
||||
@@ -45,49 +56,31 @@ class PackageManager:
|
||||
* PackageManager.get(fullname) -> App or None
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# internal storage
|
||||
# --------------------------------------------------------------------- #
|
||||
_app_list = [] # sorted by app.name
|
||||
_by_fullname = {} # fullname -> App
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# public list access (kept for backward compatibility)
|
||||
# --------------------------------------------------------------------- #
|
||||
@classmethod
|
||||
def get_app_list(cls):
|
||||
if not cls._app_list:
|
||||
cls.refresh_apps()
|
||||
return cls._app_list
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# dict-style lookup: PackageManager["com.example.myapp"]
|
||||
# --------------------------------------------------------------------- #
|
||||
def __class_getitem__(cls, fullname):
|
||||
try:
|
||||
return cls._by_fullname[fullname]
|
||||
except KeyError:
|
||||
raise KeyError("No app with fullname='{}'".format(fullname))
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# safe lookup: PackageManager.get("com.example.myapp") -> App or None
|
||||
# --------------------------------------------------------------------- #
|
||||
@classmethod
|
||||
def get(cls, fullname):
|
||||
return cls._by_fullname.get(fullname)
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# Clear everything – useful when you want to force a full rescan
|
||||
# --------------------------------------------------------------------- #
|
||||
@classmethod
|
||||
def clear(cls):
|
||||
"""Empty the internal caches. Call ``get_app_list()`` afterwards to repopulate."""
|
||||
cls._app_list = []
|
||||
cls._by_fullname = {}
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# discovery & population
|
||||
# --------------------------------------------------------------------- #
|
||||
@classmethod
|
||||
def refresh_apps(cls):
|
||||
print("PackageManager finding apps...")
|
||||
@@ -126,6 +119,7 @@ class PackageManager:
|
||||
|
||||
# ---- parse the manifest ---------------------------------
|
||||
try:
|
||||
from ..app.app import App
|
||||
app = App.from_manifest(full_path)
|
||||
except Exception as e:
|
||||
print("PackageManager: parsing {} failed: {}".format(full_path, e))
|
||||
@@ -1,11 +1,7 @@
|
||||
import utime
|
||||
from .content.intent import Intent
|
||||
|
||||
# circular import issue:
|
||||
#import mpos.package_manager
|
||||
#from .package_manager import PackageManager
|
||||
#from mpos import PackageManager
|
||||
#from mpos import *
|
||||
from .content.pm import PackageManager
|
||||
|
||||
import mpos.ui
|
||||
|
||||
@@ -17,14 +13,15 @@ class ActivityNavigator:
|
||||
if not isinstance(intent, Intent):
|
||||
raise ValueError("Must provide an Intent")
|
||||
if intent.action: # Implicit intent: resolve handlers
|
||||
#handlers = PackageManager.APP_REGISTRY.get(intent.action, [])
|
||||
handlers = PackageManager.resolve_activity(intent)
|
||||
if not handlers:
|
||||
print("No handler for action:", intent.action)
|
||||
return
|
||||
if len(handlers) == 1:
|
||||
intent.activity_class = handlers[0]
|
||||
ActivityNavigator._launch_activity(intent)
|
||||
elif handlers:
|
||||
ActivityNavigator._show_chooser(intent, handlers)
|
||||
else:
|
||||
raise ValueError(f"No handlers for action: {intent.action}")
|
||||
else:
|
||||
ActivityNavigator._launch_activity(intent)
|
||||
|
||||
@@ -34,15 +31,16 @@ class ActivityNavigator:
|
||||
if not isinstance(intent, Intent):
|
||||
raise ValueError("Must provide an Intent")
|
||||
if intent.action: # Implicit intent: resolve handlers
|
||||
#handlers = PackageManager.APP_REGISTRY.get(intent.action, [])
|
||||
handlers = PackageManager.resolve_activity(intent)
|
||||
if not handlers:
|
||||
print("No handler for action:", intent.action)
|
||||
return
|
||||
if len(handlers) == 1:
|
||||
intent.activity_class = handlers[0]
|
||||
return ActivityNavigator._launch_activity(intent, result_callback)
|
||||
elif handlers:
|
||||
ActivityNavigator._show_chooser(intent, handlers)
|
||||
return None # Chooser handles result forwarding
|
||||
else:
|
||||
raise ValueError(f"No handlers for action: {intent.action}")
|
||||
else:
|
||||
return ActivityNavigator._launch_activity(intent, result_callback)
|
||||
|
||||
@@ -64,4 +62,3 @@ class ActivityNavigator:
|
||||
chooser_intent = Intent(ChooserActivity, extras={"original_intent": intent, "handlers": [h.__name__ for h in handlers]})
|
||||
ActivityNavigator._launch_activity(chooser_intent)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user