Fix direct Gradio static asset routing
Browse files- app.py +5 -4
- src/time_machine/ui/assets/cockpit.js +2 -2
- src/time_machine/ui/gradio_app.py +5 -11
app.py
CHANGED
|
@@ -33,11 +33,12 @@ from time_machine.ui.gradio_app import create_app
|
|
| 33 |
from time_machine.ui.realtime import realtime_voice_socket
|
| 34 |
|
| 35 |
import gradio as gr
|
| 36 |
-
from fastapi import FastAPI, WebSocket
|
| 37 |
from fastapi.responses import JSONResponse, RedirectResponse, Response
|
| 38 |
-
from fastapi.staticfiles import StaticFiles
|
| 39 |
-
|
| 40 |
-
|
|
|
|
| 41 |
container = create_container()
|
| 42 |
demo = create_app(container)
|
| 43 |
fastapi_app = FastAPI(title="AI Time Machine")
|
|
|
|
| 33 |
from time_machine.ui.realtime import realtime_voice_socket
|
| 34 |
|
| 35 |
import gradio as gr
|
| 36 |
+
from fastapi import FastAPI, WebSocket
|
| 37 |
from fastapi.responses import JSONResponse, RedirectResponse, Response
|
| 38 |
+
from fastapi.staticfiles import StaticFiles
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
gr.set_static_paths([ROOT / "static"])
|
| 42 |
container = create_container()
|
| 43 |
demo = create_app(container)
|
| 44 |
fastapi_app = FastAPI(title="AI Time Machine")
|
src/time_machine/ui/assets/cockpit.js
CHANGED
|
@@ -283,7 +283,7 @@ function createAudioManager() {
|
|
| 283 |
}
|
| 284 |
this.manifestLoaded = true;
|
| 285 |
try {
|
| 286 |
-
const response = await fetch("/static/asset_manifest.json", { cache: "force-cache" });
|
| 287 |
this.manifest = response.ok ? await response.json() : null;
|
| 288 |
} catch {
|
| 289 |
this.manifest = null;
|
|
@@ -296,7 +296,7 @@ function createAudioManager() {
|
|
| 296 |
if (!raw) {
|
| 297 |
return "";
|
| 298 |
}
|
| 299 |
-
return raw.indexOf("static/") === 0 ? `/${raw}` : raw;
|
| 300 |
},
|
| 301 |
preloadSfx() {
|
| 302 |
const sfx = (this.manifest && this.manifest.audio && this.manifest.audio.sfx) || {};
|
|
|
|
| 283 |
}
|
| 284 |
this.manifestLoaded = true;
|
| 285 |
try {
|
| 286 |
+
const response = await fetch("/gradio_api/file=static/asset_manifest.json", { cache: "force-cache" });
|
| 287 |
this.manifest = response.ok ? await response.json() : null;
|
| 288 |
} catch {
|
| 289 |
this.manifest = null;
|
|
|
|
| 296 |
if (!raw) {
|
| 297 |
return "";
|
| 298 |
}
|
| 299 |
+
return raw.indexOf("static/") === 0 ? `/gradio_api/file=${raw}` : raw;
|
| 300 |
},
|
| 301 |
preloadSfx() {
|
| 302 |
const sfx = (this.manifest && this.manifest.audio && this.manifest.audio.sfx) || {};
|
src/time_machine/ui/gradio_app.py
CHANGED
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
| 3 |
from pathlib import Path
|
| 4 |
import base64
|
| 5 |
import inspect
|
| 6 |
-
import mimetypes
|
| 7 |
import re
|
| 8 |
|
| 9 |
import gradio as gr
|
|
@@ -27,10 +26,10 @@ def create_app(container: AppContainer) -> gr.Blocks:
|
|
| 27 |
if bg_path.exists():
|
| 28 |
bg_b64 = base64.b64encode(bg_path.read_bytes()).decode("utf-8")
|
| 29 |
css = css.replace("url('bg.png')", f"url('data:image/png;base64,{bg_b64}')")
|
| 30 |
-
css =
|
| 31 |
|
| 32 |
-
cockpit_html =
|
| 33 |
-
intro_html =
|
| 34 |
intro_js = (ASSET_DIR / "intro.js").read_text(encoding="utf-8")
|
| 35 |
cockpit_js = (ASSET_DIR / "cockpit.js").read_text(encoding="utf-8")
|
| 36 |
|
|
@@ -161,15 +160,10 @@ def create_app(container: AppContainer) -> gr.Blocks:
|
|
| 161 |
return demo.queue()
|
| 162 |
|
| 163 |
|
| 164 |
-
def
|
| 165 |
return re.sub(r"(?P<quote>['\"])/static/(?P<path>[^'\")]+)(?P=quote)", _replace_static_url, text)
|
| 166 |
|
| 167 |
|
| 168 |
def _replace_static_url(match: re.Match[str]) -> str:
|
| 169 |
relative_path = match.group("path")
|
| 170 |
-
|
| 171 |
-
if not file_path.exists() or not file_path.is_file():
|
| 172 |
-
return match.group(0)
|
| 173 |
-
mime_type = mimetypes.guess_type(file_path.name)[0] or "application/octet-stream"
|
| 174 |
-
encoded = base64.b64encode(file_path.read_bytes()).decode("ascii")
|
| 175 |
-
return f"{match.group('quote')}data:{mime_type};base64,{encoded}{match.group('quote')}"
|
|
|
|
| 3 |
from pathlib import Path
|
| 4 |
import base64
|
| 5 |
import inspect
|
|
|
|
| 6 |
import re
|
| 7 |
|
| 8 |
import gradio as gr
|
|
|
|
| 26 |
if bg_path.exists():
|
| 27 |
bg_b64 = base64.b64encode(bg_path.read_bytes()).decode("utf-8")
|
| 28 |
css = css.replace("url('bg.png')", f"url('data:image/png;base64,{bg_b64}')")
|
| 29 |
+
css = _route_static_urls(css)
|
| 30 |
|
| 31 |
+
cockpit_html = _route_static_urls((ASSET_DIR / "cockpit.html").read_text(encoding="utf-8"))
|
| 32 |
+
intro_html = _route_static_urls((ASSET_DIR / "intro.html").read_text(encoding="utf-8"))
|
| 33 |
intro_js = (ASSET_DIR / "intro.js").read_text(encoding="utf-8")
|
| 34 |
cockpit_js = (ASSET_DIR / "cockpit.js").read_text(encoding="utf-8")
|
| 35 |
|
|
|
|
| 160 |
return demo.queue()
|
| 161 |
|
| 162 |
|
| 163 |
+
def _route_static_urls(text: str) -> str:
|
| 164 |
return re.sub(r"(?P<quote>['\"])/static/(?P<path>[^'\")]+)(?P=quote)", _replace_static_url, text)
|
| 165 |
|
| 166 |
|
| 167 |
def _replace_static_url(match: re.Match[str]) -> str:
|
| 168 |
relative_path = match.group("path")
|
| 169 |
+
return f"{match.group('quote')}/gradio_api/file=static/{relative_path}{match.group('quote')}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|