소스 검색

allow dynamically adding dependencies

Falko Schindler 2 년 전
부모
커밋
108dc48aaf
2개의 변경된 파일38개의 추가작업 그리고 20개의 파일을 삭제
  1. 0 2
      nicegui/nicegui.py
  2. 38 18
      nicegui/routes.py

+ 0 - 2
nicegui/nicegui.py

@@ -11,7 +11,6 @@ if True:  # NOTE: prevent formatter from mixing up these lines
 
 from . import binding, globals
 from .elements.page import create_page_routes, init_auto_index_page
-from .routes import serve_dependencies
 from .task_logger import create_task
 from .timer import Timer
 
@@ -30,7 +29,6 @@ async def patched_justpy_startup():
 async def startup():
     init_auto_index_page()
     await create_page_routes()
-    serve_dependencies()
     globals.tasks.extend(create_task(t.coro, name=t.name) for t in Timer.prepared_coroutines)
     Timer.prepared_coroutines.clear()
     globals.tasks.extend(create_task(t, name='startup task')

+ 38 - 18
nicegui/routes.py

@@ -1,3 +1,4 @@
+import asyncio
 import inspect
 import os.path
 from functools import wraps
@@ -10,7 +11,9 @@ from starlette.routing import BaseRoute, Mount, Route
 from starlette.staticfiles import StaticFiles
 
 from . import globals
+from .elements.page import Page, get_current_view
 from .helpers import is_coroutine
+from .task_logger import create_task
 
 
 def add_route(self, route: BaseRoute) -> None:
@@ -60,24 +63,41 @@ def get(self, path: str):
 
 
 def add_dependencies(py_filepath: str, dependencies: List[str] = []) -> None:
+    if py_filepath in globals.dependencies:
+        return
     globals.dependencies[py_filepath] = dependencies
 
+    new_dependencies: List[str] = []
 
-def serve_dependencies() -> None:
-    for py_filepath, dependencies in globals.dependencies.items():
-        vue_filepath = os.path.splitext(os.path.realpath(py_filepath))[0] + '.js'
-
-        for dependency in dependencies:
-            is_remote = dependency.startswith('http://') or dependency.startswith('https://')
-            src = dependency if is_remote else f'lib/{dependency}'
-            if src not in jp.component_file_list:
-                jp.component_file_list += [src]
-                if not is_remote:
-                    filepath = f'{os.path.dirname(vue_filepath)}/{src}'
-                    route = Route(f'/{src}', lambda _, filepath=filepath: FileResponse(filepath))
-                    jp.app.routes.insert(0, route)
-
-        if vue_filepath not in jp.component_file_list:
-            filename = os.path.basename(vue_filepath)
-            jp.app.routes.insert(0, Route(f'/{filename}', lambda _: FileResponse(vue_filepath)))
-            jp.component_file_list += [filename]
+    vue_filepath = os.path.splitext(os.path.realpath(py_filepath))[0] + '.js'
+    if vue_filepath not in jp.component_file_list:
+        filename = os.path.basename(vue_filepath)
+        jp.app.routes.insert(0, Route(f'/{filename}', lambda _: FileResponse(vue_filepath)))
+        jp.component_file_list += [filename]
+        new_dependencies.append(filename)
+
+    for dependency in dependencies:
+        is_remote = dependency.startswith('http://') or dependency.startswith('https://')
+        src = dependency if is_remote else f'lib/{dependency}'
+        if src not in jp.component_file_list:
+            jp.component_file_list += [src]
+            if not is_remote:
+                filepath = f'{os.path.dirname(vue_filepath)}/{src}'
+                route = Route(f'/{src}', lambda _, filepath=filepath: FileResponse(filepath))
+                jp.app.routes.insert(0, route)
+            new_dependencies.append(src)
+
+    if asyncio.get_event_loop().is_running():
+        create_task(inject_dependencies(new_dependencies))
+
+
+async def inject_dependencies(dependencies: List[str]) -> None:
+    for page in get_current_view().pages.values():
+        assert isinstance(page, Page)
+        for src in dependencies:
+            await page.await_javascript(f'''
+            let script = document.createElement("script");
+            script.src = "{src}";
+            document.body.append(script);
+            ''')
+        await page.update()