flet-web 0.29.0.dev5035__py3-none-any.whl → 0.70.0.dev5066__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. flet_web/__init__.py +8 -1
  2. flet_web/fastapi/__init__.py +2 -0
  3. flet_web/fastapi/app.py +44 -17
  4. flet_web/fastapi/flet_app.py +195 -288
  5. flet_web/fastapi/flet_app_manager.py +41 -64
  6. flet_web/fastapi/flet_oauth.py +2 -1
  7. flet_web/fastapi/flet_static_files.py +54 -50
  8. flet_web/fastapi/serve_fastapi_web_app.py +30 -27
  9. flet_web/patch_index.py +35 -35
  10. flet_web/version.py +1 -1
  11. flet_web/web/assets/NOTICES +1815 -3803
  12. flet_web/web/assets/fonts/roboto.woff2 +0 -0
  13. flet_web/web/assets/packages/media_kit/assets/web/hls1.4.10.js +2 -2
  14. flet_web/web/canvaskit/canvaskit.js +192 -0
  15. flet_web/web/canvaskit/canvaskit.js.symbols +12098 -0
  16. flet_web/web/canvaskit/canvaskit.wasm +0 -0
  17. flet_web/web/canvaskit/chromium/canvaskit.js +192 -0
  18. flet_web/web/canvaskit/chromium/canvaskit.js.symbols +11050 -0
  19. flet_web/web/canvaskit/chromium/canvaskit.wasm +0 -0
  20. flet_web/web/canvaskit/skwasm.js +137 -0
  21. flet_web/web/canvaskit/skwasm.js.symbols +12073 -0
  22. flet_web/web/canvaskit/skwasm.wasm +0 -0
  23. flet_web/web/flutter.js +30 -2
  24. flet_web/web/flutter.js.map +3 -3
  25. flet_web/web/flutter_bootstrap.js +50 -10
  26. flet_web/web/flutter_service_worker.js +23 -21
  27. flet_web/web/index.html +56 -11
  28. flet_web/web/main.dart.js +170402 -167642
  29. flet_web/web/main.dart.mjs +44188 -0
  30. flet_web/web/main.dart.wasm +0 -0
  31. flet_web/web/pyodide/ffi.d.ts +10 -1
  32. flet_web/web/pyodide/micropip-0.8.0-py3-none-any.whl +14 -0
  33. flet_web/web/pyodide/package.json +2 -2
  34. flet_web/web/pyodide/packaging-24.2-py3-none-any.whl +0 -0
  35. flet_web/web/pyodide/pyodide-lock.json +1 -1
  36. flet_web/web/pyodide/pyodide.asm.js +1 -1
  37. flet_web/web/pyodide/pyodide.asm.wasm +0 -0
  38. flet_web/web/pyodide/pyodide.d.ts +15 -3
  39. flet_web/web/pyodide/pyodide.js +1 -1
  40. flet_web/web/pyodide/pyodide.mjs +2 -2
  41. flet_web/web/pyodide/python_stdlib.zip +0 -0
  42. flet_web/web/python-worker.js +75 -24
  43. flet_web/web/python.js +62 -20
  44. {flet_web-0.29.0.dev5035.dist-info → flet_web-0.70.0.dev5066.dist-info}/METADATA +3 -3
  45. flet_web-0.70.0.dev5066.dist-info/RECORD +71 -0
  46. flet_web-0.29.0.dev5035.dist-info/RECORD +0 -57
  47. {flet_web-0.29.0.dev5035.dist-info → flet_web-0.70.0.dev5066.dist-info}/WHEEL +0 -0
  48. {flet_web-0.29.0.dev5035.dist-info → flet_web-0.70.0.dev5066.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,14 @@
1
1
  import asyncio
2
2
  import logging
3
3
  import shutil
4
- import threading
5
4
  import traceback
6
5
  from concurrent.futures import ThreadPoolExecutor
7
6
  from datetime import datetime, timezone
8
7
  from typing import Optional
9
8
 
10
- from flet.core.connection import Connection
11
- from flet.core.locks import NopeLock
12
- from flet.core.page import Page
13
- from flet.core.pubsub.pubsub_hub import PubSubHub
14
- from flet.utils import is_pyodide
9
+ from flet.messaging.connection import Connection
10
+ from flet.messaging.session import Session
11
+ from flet.pubsub.pubsub_hub import PubSubHub
15
12
 
16
13
  import flet_web.fastapi as flet_fastapi
17
14
  from flet_web.fastapi.oauth_state import OAuthState
@@ -25,15 +22,12 @@ class FletAppManager:
25
22
  """
26
23
 
27
24
  def __init__(self):
28
- self.__sessions_lock = asyncio.Lock()
29
- self.__sessions: dict[str, Page] = {}
25
+ self.__sessions: dict[str, Session] = {}
30
26
  self.__evict_sessions_task = None
31
27
  self.__states: dict[str, OAuthState] = {}
32
- self.__states_lock = threading.Lock() if not is_pyodide() else NopeLock()
33
28
  self.__evict_oauth_states_task = None
34
29
  self.__temp_dirs = {}
35
30
  self.__executor = ThreadPoolExecutor(thread_name_prefix="flet_fastapi")
36
- self.__pubsubhubs_lock = threading.Lock() if not is_pyodide() else NopeLock()
37
31
  self.__pubsubhubs = {}
38
32
 
39
33
  @property
@@ -43,19 +37,19 @@ class FletAppManager:
43
37
  def get_pubsubhub(
44
38
  self, session_handler, loop: Optional[asyncio.AbstractEventLoop] = None
45
39
  ):
46
- with self.__pubsubhubs_lock:
47
- psh = self.__pubsubhubs.get(session_handler, None)
48
- if psh is None:
49
- psh = PubSubHub(
50
- loop=loop or asyncio.get_running_loop(),
51
- executor=self.__executor,
52
- )
53
- self.__pubsubhubs[session_handler] = psh
54
- return psh
40
+ psh = self.__pubsubhubs.get(session_handler, None)
41
+ if psh is None:
42
+ psh = PubSubHub(
43
+ loop=loop or asyncio.get_running_loop(),
44
+ executor=self.__executor,
45
+ )
46
+ self.__pubsubhubs[session_handler] = psh
47
+ return psh
55
48
 
56
49
  async def start(self):
57
50
  """
58
- Background task evicting expired app data. Must be called at FastAPI application startup.
51
+ Background task evicting expired app data. Must be called at FastAPI
52
+ application startup.
59
53
  """
60
54
  if not self.__evict_sessions_task:
61
55
  logger.info("Starting up Flet App Manager")
@@ -77,44 +71,31 @@ class FletAppManager:
77
71
  if self.__evict_oauth_states_task:
78
72
  self.__evict_oauth_states_task.cancel()
79
73
 
80
- async def get_session(self, session_id: str) -> Optional[Page]:
81
- async with self.__sessions_lock:
82
- return self.__sessions.get(session_id)
74
+ async def get_session(self, session_id: str) -> Optional[Session]:
75
+ return self.__sessions.get(session_id)
83
76
 
84
- async def add_session(self, session_id: str, conn: Page):
85
- async with self.__sessions_lock:
86
- self.__sessions[session_id] = conn
87
- logger.info(
88
- f"New session created ({len(self.__sessions)} total): {session_id}"
89
- )
77
+ async def add_session(self, session_id: str, session: Session):
78
+ self.__sessions[session_id] = session
79
+ logger.info(f"New session created ({len(self.__sessions)} total): {session_id}")
90
80
 
91
81
  async def reconnect_session(self, session_id: str, conn: Connection):
92
82
  logger.info(f"Session reconnected: {session_id}")
93
- async with self.__sessions_lock:
94
- if session_id in self.__sessions:
95
- page = self.__sessions[session_id]
96
- old_conn = page.connection
97
- await page._connect(conn)
98
- if old_conn:
99
- old_conn.dispose()
83
+ if session_id in self.__sessions:
84
+ session = self.__sessions[session_id]
85
+ await session.connect(conn)
100
86
 
101
87
  async def disconnect_session(self, session_id: str, session_timeout_seconds: int):
102
88
  logger.info(f"Session disconnected: {session_id}")
103
- async with self.__sessions_lock:
104
- if session_id in self.__sessions:
105
- await self.__sessions[session_id]._disconnect(session_timeout_seconds)
89
+ if session_id in self.__sessions:
90
+ await self.__sessions[session_id].disconnect(session_timeout_seconds)
106
91
 
107
92
  async def delete_session(self, session_id: str):
108
- async with self.__sessions_lock:
109
- page = self.__sessions.pop(session_id, None)
110
- total = len(self.__sessions)
111
- if page is not None:
93
+ session = self.__sessions.pop(session_id, None)
94
+ total = len(self.__sessions)
95
+ if session is not None:
112
96
  logger.info(f"Delete session ({total} left): {session_id}")
113
97
  try:
114
- old_conn = page.connection
115
- page._close()
116
- if old_conn:
117
- old_conn.dispose()
98
+ session.close()
118
99
  except Exception as e:
119
100
  logger.error(
120
101
  f"Error deleting expired session: {e} {traceback.format_exc()}"
@@ -122,12 +103,10 @@ class FletAppManager:
122
103
 
123
104
  def store_state(self, state_id: str, state: OAuthState):
124
105
  logger.info(f"Store oauth state: {state_id}")
125
- with self.__states_lock:
126
- self.__states[state_id] = state
106
+ self.__states[state_id] = state
127
107
 
128
108
  def retrieve_state(self, state_id: str) -> Optional[OAuthState]:
129
- with self.__states_lock:
130
- return self.__states.pop(state_id, None)
109
+ return self.__states.pop(state_id, None)
131
110
 
132
111
  def add_temp_dir(self, temp_dir: str):
133
112
  self.__temp_dirs[temp_dir] = True
@@ -136,30 +115,28 @@ class FletAppManager:
136
115
  while True:
137
116
  await asyncio.sleep(10)
138
117
  session_ids = []
139
- async with self.__sessions_lock:
140
- for session_id, page in self.__sessions.items():
141
- if page.expires_at and datetime.now(timezone.utc) > page.expires_at:
142
- session_ids.append(session_id)
118
+ for session_id, session in self.__sessions.items():
119
+ if (
120
+ session.expires_at
121
+ and datetime.now(timezone.utc) > session.expires_at
122
+ ):
123
+ session_ids.append(session_id)
143
124
  for session_id in session_ids:
144
125
  await self.delete_session(session_id)
145
126
 
146
127
  async def __evict_expired_oauth_states(self):
147
128
  while True:
148
129
  await asyncio.sleep(10)
149
- with self.__states_lock:
150
- ids = []
151
- for id, state in self.__states.items():
152
- if (
153
- state.expires_at
154
- and datetime.now(timezone.utc) > state.expires_at
155
- ):
156
- ids.append(id)
130
+ ids = []
131
+ for id, state in self.__states.items():
132
+ if state.expires_at and datetime.now(timezone.utc) > state.expires_at:
133
+ ids.append(id)
157
134
  for id in ids:
158
135
  logger.info(f"Delete expired oauth state: {id}")
159
136
  self.retrieve_state(id)
160
137
 
161
138
  def delete_temp_dirs(self):
162
- for temp_dir in self.__temp_dirs.keys():
139
+ for temp_dir in self.__temp_dirs:
163
140
  logger.info(f"Deleting temp dir: {temp_dir}")
164
141
  shutil.rmtree(temp_dir, ignore_errors=True)
165
142
 
@@ -1,5 +1,6 @@
1
1
  from fastapi import HTTPException, Request
2
2
  from fastapi.responses import HTMLResponse, RedirectResponse
3
+
3
4
  from flet_web.fastapi.flet_app_manager import app_manager
4
5
 
5
6
 
@@ -33,7 +34,7 @@ class FletOAuth:
33
34
  if not session:
34
35
  raise HTTPException(status_code=500, detail="Session not found")
35
36
 
36
- await session._authorize_callback_async(
37
+ await session.page._authorize_callback_async(
37
38
  {
38
39
  "state": state_id,
39
40
  "code": request.query_params.get("code"),
@@ -3,16 +3,22 @@ import os
3
3
  import shutil
4
4
  import tempfile
5
5
  from pathlib import Path
6
- from typing import Optional, Tuple
6
+ from typing import Optional
7
7
 
8
- import flet_web.fastapi as flet_fastapi
9
8
  from fastapi.staticfiles import StaticFiles
10
- from flet.core.types import WebRenderer
9
+ from flet.controls.types import RouteUrlStrategy, WebRenderer
11
10
  from flet.utils import Once, get_bool_env_var
12
- from flet_web import get_package_web_dir, patch_index_html, patch_manifest_json
13
- from flet_web.fastapi.flet_app_manager import app_manager
14
11
  from starlette.types import Receive, Scope, Send
15
12
 
13
+ import flet_web.fastapi as flet_fastapi
14
+ from flet_web import (
15
+ get_package_web_dir,
16
+ patch_font_manifest_json,
17
+ patch_index_html,
18
+ patch_manifest_json,
19
+ )
20
+ from flet_web.fastapi.flet_app_manager import app_manager
21
+
16
22
  logger = logging.getLogger(flet_fastapi.__name__)
17
23
 
18
24
 
@@ -27,10 +33,11 @@ class FletStaticFiles(StaticFiles):
27
33
  * `app_name` (str, optional) - PWA application name.
28
34
  * `app_short_name` (str, optional) - PWA application short name.
29
35
  * `app_description` (str, optional) - PWA application description.
30
- * `web_renderer` (WebRenderer) - web renderer defaulting to `WebRenderer.CANVAS_KIT`.
31
- * `use_color_emoji` (bool) - whether to load a font with color emoji. Default is `False`.
36
+ * `web_renderer` (WebRenderer) - web renderer defaulting to `WebRenderer.AUTO`.
32
37
  * `route_url_strategy` (str) - routing URL strategy: `path` (default) or `hash`.
33
- * `websocket_endpoint_path` (str, optional) - absolute URL of Flet app WebSocket handler. Default is `{app_mount_path}/ws`.
38
+ * `no_cdn` - do not load CanvasKit, Pyodide and fonts from CDN
39
+ * `websocket_endpoint_path` (str, optional) - absolute URL of Flet app
40
+ WebSocket handler. Default is `{app_mount_path}/ws`.
34
41
  """
35
42
 
36
43
  def __init__(
@@ -40,21 +47,22 @@ class FletStaticFiles(StaticFiles):
40
47
  app_name: Optional[str] = None,
41
48
  app_short_name: Optional[str] = None,
42
49
  app_description: Optional[str] = None,
43
- web_renderer: WebRenderer = WebRenderer.CANVAS_KIT,
44
- use_color_emoji: bool = False,
45
- route_url_strategy: str = "path",
50
+ web_renderer: WebRenderer = WebRenderer.AUTO,
51
+ route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH,
52
+ no_cdn: bool = False,
46
53
  websocket_endpoint_path: Optional[str] = None,
47
54
  ) -> None:
48
- self.index = "index.html"
49
- self.manifest_json = "manifest.json"
55
+ self.index = ["index.html"]
56
+ self.manifest_json = ["manifest.json"]
57
+ self.font_manifest_json = ["assets", "FontManifest.json"]
50
58
  self.__proxy_path = proxy_path
51
59
  self.__assets_dir = assets_dir
52
60
  self.__app_name = app_name
53
61
  self.__app_short_name = app_short_name
54
62
  self.__app_description = app_description
55
63
  self.__web_renderer = web_renderer
56
- self.__use_color_emoji = use_color_emoji
57
64
  self.__route_url_strategy = route_url_strategy
65
+ self.__no_cdn = no_cdn
58
66
  self.__websocket_endpoint_path = websocket_endpoint_path
59
67
  self.__once = Once()
60
68
 
@@ -62,23 +70,23 @@ class FletStaticFiles(StaticFiles):
62
70
  if env_web_renderer:
63
71
  self.__web_renderer = WebRenderer(env_web_renderer)
64
72
 
65
- env_use_color_emoji = get_bool_env_var("FLET_WEB_USE_COLOR_EMOJI")
66
- if env_use_color_emoji is not None:
67
- self.__use_color_emoji = env_use_color_emoji
68
-
69
73
  env_route_url_strategy = os.getenv("FLET_WEB_ROUTE_URL_STRATEGY")
70
74
  if env_route_url_strategy:
71
- self.__route_url_strategy = env_route_url_strategy
75
+ self.__route_url_strategy = RouteUrlStrategy(env_route_url_strategy)
76
+
77
+ env_no_cdn = get_bool_env_var("FLET_WEB_NO_CDN")
78
+ if env_no_cdn is not None:
79
+ self.__no_cdn = env_no_cdn
72
80
 
73
81
  logger.info(f"Web renderer configured: {self.__web_renderer}")
74
- logger.info(f"Use color emoji: {self.__use_color_emoji}")
75
82
  logger.info(f"Route URL strategy configured: {self.__route_url_strategy}")
83
+ logger.info(f"No CDN configured: {self.__no_cdn}")
76
84
 
77
85
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
78
86
  await self.__once.do(self.__config, scope["root_path"])
79
87
  await super().__call__(scope, receive, send)
80
88
 
81
- def lookup_path(self, path: str) -> Tuple[str, Optional[os.stat_result]]:
89
+ def lookup_path(self, path: str) -> tuple[str, Optional[os.stat_result]]:
82
90
  """Returns the index file when no match is found.
83
91
 
84
92
  Args:
@@ -92,7 +100,7 @@ class FletStaticFiles(StaticFiles):
92
100
 
93
101
  # if a file cannot be found
94
102
  if stat_result is None:
95
- return super().lookup_path(self.index)
103
+ return super().lookup_path(self.index[0])
96
104
 
97
105
  return full_path, stat_result
98
106
 
@@ -125,33 +133,22 @@ class FletStaticFiles(StaticFiles):
125
133
 
126
134
  logger.info(f"Assets dir: {self.__assets_dir}")
127
135
 
136
+ def copy_temp_web_file(paths: list[str]):
137
+ if self.__assets_dir and os.path.exists(
138
+ p := os.path.join(self.__assets_dir, *paths)
139
+ ):
140
+ src_path = p
141
+ else:
142
+ src_path = os.path.join(web_dir, *paths)
143
+ dst_path = os.path.join(temp_dir, *paths)
144
+ Path(dst_path).parent.mkdir(parents=True, exist_ok=True)
145
+ shutil.copyfile(src_path, dst_path)
146
+
128
147
  # copy index.html from assets_dir or web_dir
129
- if self.__assets_dir and os.path.exists(
130
- os.path.join(self.__assets_dir, self.index)
131
- ):
132
- shutil.copyfile(
133
- os.path.join(self.__assets_dir, self.index),
134
- os.path.join(temp_dir, self.index),
135
- )
136
- else:
137
- shutil.copyfile(
138
- os.path.join(web_dir, self.index),
139
- os.path.join(temp_dir, self.index),
140
- )
148
+ copy_temp_web_file(self.index)
141
149
 
142
150
  # copy manifest.json from assets_dir or web_dir
143
- if self.__assets_dir and os.path.exists(
144
- os.path.join(self.__assets_dir, self.manifest_json)
145
- ):
146
- shutil.copyfile(
147
- os.path.join(self.__assets_dir, self.manifest_json),
148
- os.path.join(temp_dir, self.manifest_json),
149
- )
150
- else:
151
- shutil.copyfile(
152
- os.path.join(web_dir, self.manifest_json),
153
- os.path.join(temp_dir, self.manifest_json),
154
- )
151
+ copy_temp_web_file(self.manifest_json)
155
152
 
156
153
  ws_path = self.__websocket_endpoint_path
157
154
  if not ws_path:
@@ -160,23 +157,30 @@ class FletStaticFiles(StaticFiles):
160
157
 
161
158
  # replace variables in index.html and manifest.json
162
159
  patch_index_html(
163
- index_path=os.path.join(temp_dir, self.index),
160
+ index_path=os.path.join(temp_dir, *self.index),
164
161
  base_href=self.__app_mount_path,
165
162
  websocket_endpoint_path=ws_path,
166
163
  app_name=self.__app_name,
167
164
  app_description=self.__app_description,
168
- web_renderer=WebRenderer(self.__web_renderer),
169
- use_color_emoji=self.__use_color_emoji,
165
+ web_renderer=self.__web_renderer,
170
166
  route_url_strategy=self.__route_url_strategy,
167
+ no_cdn=self.__no_cdn,
171
168
  )
172
169
 
173
170
  patch_manifest_json(
174
- manifest_path=os.path.join(temp_dir, self.manifest_json),
171
+ manifest_path=os.path.join(temp_dir, *self.manifest_json),
175
172
  app_name=self.__app_name,
176
173
  app_short_name=self.__app_short_name,
177
174
  app_description=self.__app_description,
178
175
  )
179
176
 
177
+ if self.__no_cdn:
178
+ # copy FontManifest.json from assets_dir or web_dir
179
+ copy_temp_web_file(self.font_manifest_json)
180
+ patch_font_manifest_json(
181
+ manifest_path=os.path.join(temp_dir, *self.font_manifest_json)
182
+ )
183
+
180
184
  # set html=True to resolve the index even when no
181
185
  # the base path is passed in
182
186
  super().__init__(directory=temp_dir, packages=None, html=True, check_dir=True)
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
2
  import logging
3
- from typing import Optional
3
+ from typing import Any, Optional, Union
4
4
 
5
5
  import uvicorn
6
- from flet.core.types import WebRenderer
6
+ from flet.controls.types import RouteUrlStrategy, WebRenderer
7
7
 
8
8
  import flet_web.fastapi
9
9
  import flet_web.fastapi as flet_fastapi
@@ -22,25 +22,27 @@ class WebServerHandle:
22
22
 
23
23
 
24
24
  def get_fastapi_web_app(
25
- session_handler,
25
+ main,
26
+ before_main,
26
27
  page_name: str,
27
- assets_dir,
28
- upload_dir,
29
- web_renderer: Optional[WebRenderer],
30
- use_color_emoji,
31
- route_url_strategy,
28
+ assets_dir: str,
29
+ upload_dir: str,
30
+ web_renderer: WebRenderer = WebRenderer.AUTO,
31
+ route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH,
32
+ no_cdn: bool = False,
32
33
  ):
33
34
  web_path = f"/{page_name.strip('/')}"
34
35
  app = flet_web.fastapi.FastAPI()
35
36
  app.mount(
36
37
  web_path,
37
38
  flet_web.fastapi.app(
38
- session_handler,
39
+ main,
40
+ before_main=before_main,
39
41
  upload_dir=upload_dir,
40
42
  assets_dir=assets_dir,
41
- web_renderer=web_renderer if web_renderer else WebRenderer.AUTO,
42
- use_color_emoji=use_color_emoji,
43
+ web_renderer=web_renderer,
43
44
  route_url_strategy=route_url_strategy,
45
+ no_cdn=no_cdn,
44
46
  ),
45
47
  )
46
48
 
@@ -48,21 +50,21 @@ def get_fastapi_web_app(
48
50
 
49
51
 
50
52
  async def serve_fastapi_web_app(
51
- session_handler,
52
- host,
53
- url_host,
54
- port,
53
+ main,
54
+ before_main,
55
+ host: str,
56
+ url_host: str,
57
+ port: int,
55
58
  page_name: str,
56
- assets_dir,
57
- upload_dir,
58
- web_renderer: Optional[WebRenderer],
59
- use_color_emoji,
60
- route_url_strategy,
61
- blocking,
62
- on_startup,
63
- log_level,
59
+ assets_dir: str,
60
+ upload_dir: str,
61
+ web_renderer: WebRenderer = WebRenderer.AUTO,
62
+ route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH,
63
+ no_cdn: bool = False,
64
+ blocking: bool = False,
65
+ on_startup: Optional[Any] = None,
66
+ log_level: Optional[Union[str, int]] = None,
64
67
  ):
65
-
66
68
  web_path = f"/{page_name.strip('/')}"
67
69
  page_url = f"http://{url_host}:{port}{web_path if web_path != '/' else ''}"
68
70
 
@@ -75,12 +77,13 @@ async def serve_fastapi_web_app(
75
77
  app.mount(
76
78
  web_path,
77
79
  flet_web.fastapi.app(
78
- session_handler,
80
+ main,
81
+ before_main=before_main,
79
82
  upload_dir=upload_dir,
80
83
  assets_dir=assets_dir,
81
- web_renderer=web_renderer if web_renderer else WebRenderer.AUTO,
82
- use_color_emoji=use_color_emoji,
84
+ web_renderer=web_renderer,
83
85
  route_url_strategy=route_url_strategy,
86
+ no_cdn=no_cdn,
84
87
  ),
85
88
  )
86
89
  config = uvicorn.Config(app, host=host, port=port, log_level=log_level)
flet_web/patch_index.py CHANGED
@@ -3,7 +3,7 @@ import re
3
3
  from pathlib import Path
4
4
  from typing import Optional
5
5
 
6
- from flet.core.types import WebRenderer
6
+ from flet.controls.types import RouteUrlStrategy, WebRenderer
7
7
 
8
8
 
9
9
  def patch_index_html(
@@ -16,64 +16,54 @@ def patch_index_html(
16
16
  pyodide_pre: bool = False,
17
17
  pyodide_script_path: str = "",
18
18
  web_renderer: WebRenderer = WebRenderer.AUTO,
19
- use_color_emoji: bool = False,
20
- route_url_strategy: str = "path",
19
+ route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH,
20
+ no_cdn: bool = False,
21
21
  ):
22
- with open(index_path, "r", encoding="utf-8") as f:
22
+ with open(index_path, encoding="utf-8") as f:
23
23
  index = f.read()
24
24
 
25
+ app_config = []
26
+
25
27
  if pyodide and pyodide_script_path:
26
28
  module_name = Path(pyodide_script_path).stem
27
- pyodideCode = f"""
28
- <script>
29
- var micropipIncludePre = {str(pyodide_pre).lower()};
30
- var pythonModuleName = "{module_name}";
31
- </script>
32
- <script src="python.js"></script>
33
- """
34
- index = index.replace("<!-- pyodideCode -->", pyodideCode)
35
- index = index.replace("%FLET_WEB_PYODIDE%", str(pyodide).lower())
36
- index = index.replace(
37
- "<!-- webRenderer -->",
38
- f'<script>webRenderer="{web_renderer.value}";</script>',
39
- )
29
+ app_config.append("flet.pyodide = true;")
30
+ app_config.append(f"flet.micropipIncludePre = {str(pyodide_pre).lower()};")
31
+ app_config.append(f'flet.pythonModuleName = "{module_name}";')
32
+
33
+ app_config.append(f"flet.noCdn={str(no_cdn).lower()};")
34
+ app_config.append(f'flet.webRenderer="{web_renderer.value}";')
35
+ app_config.append(f'flet.routeUrlStrategy="{route_url_strategy.value}";')
36
+
37
+ if websocket_endpoint_path:
38
+ app_config.append(f'flet.webSocketEndpoint="{websocket_endpoint_path}";')
39
+
40
40
  index = index.replace(
41
- "<!-- useColorEmoji -->",
42
- f"<script>useColorEmoji={str(use_color_emoji).lower()};</script>",
41
+ "<!-- fletAppConfig -->",
42
+ "<script>\n{}\n</script>".format("\n".join(app_config)),
43
43
  )
44
- index = index.replace("%FLET_ROUTE_URL_STRATEGY%", route_url_strategy)
45
44
 
46
45
  if base_href:
47
46
  base_url = base_href.strip("/").strip()
48
47
  index = index.replace(
49
48
  '<base href="/">',
50
- '<base href="{}">'.format(
51
- "/" if base_url == "" else "/{}/".format(base_url)
52
- ),
53
- )
54
- if websocket_endpoint_path:
55
- index = re.sub(
56
- r"\<meta name=\"flet-websocket-endpoint-path\" content=\"(.+)\">",
57
- r'<meta name="flet-websocket-endpoint-path" content="{}">'.format(
58
- websocket_endpoint_path
59
- ),
60
- index,
49
+ '<base href="{}">'.format("/" if base_url == "" else f"/{base_url}/"),
61
50
  )
51
+
62
52
  if app_name:
63
53
  index = re.sub(
64
54
  r"\<meta name=\"apple-mobile-web-app-title\" content=\"(.+)\">",
65
- r'<meta name="apple-mobile-web-app-title" content="{}">'.format(app_name),
55
+ rf'<meta name="apple-mobile-web-app-title" content="{app_name}">',
66
56
  index,
67
57
  )
68
58
  index = re.sub(
69
59
  r"\<title>(.+)</title>",
70
- r"<title>{}</title>".format(app_name),
60
+ rf"<title>{app_name}</title>",
71
61
  index,
72
62
  )
73
63
  if app_description:
74
64
  index = re.sub(
75
65
  r"\<meta name=\"description\" content=\"(.+)\">",
76
- r'<meta name="description" content="{}">'.format(app_description),
66
+ rf'<meta name="description" content="{app_description}">',
77
67
  index,
78
68
  )
79
69
 
@@ -89,7 +79,7 @@ def patch_manifest_json(
89
79
  background_color: Optional[str] = None,
90
80
  theme_color: Optional[str] = None,
91
81
  ):
92
- with open(manifest_path, "r", encoding="utf-8") as f:
82
+ with open(manifest_path, encoding="utf-8") as f:
93
83
  manifest = json.loads(f.read())
94
84
 
95
85
  if app_name:
@@ -110,3 +100,13 @@ def patch_manifest_json(
110
100
 
111
101
  with open(manifest_path, "w", encoding="utf-8") as f:
112
102
  f.write(json.dumps(manifest, indent=2))
103
+
104
+
105
+ def patch_font_manifest_json(manifest_path: str):
106
+ with open(manifest_path, encoding="utf-8") as f:
107
+ manifest = json.loads(f.read())
108
+
109
+ manifest.append({"family": "Roboto", "fonts": [{"asset": "fonts/roboto.woff2"}]})
110
+
111
+ with open(manifest_path, "w", encoding="utf-8") as f:
112
+ f.write(json.dumps(manifest, indent=2))
flet_web/version.py CHANGED
@@ -1 +1 @@
1
- version = "0.29.0.dev5035"
1
+ version = "0.70.0.dev5066"