François Pachet commited on
Commit
7a29cd5
·
1 Parent(s): 4b17f2c

Make phone layout load reliably

Browse files
Files changed (4) hide show
  1. README.md +6 -4
  2. backend/app/main.py +4 -1
  3. frontend/app.js +4 -0
  4. frontend/index.html +18 -2
README.md CHANGED
@@ -86,10 +86,12 @@ The UX principle is to keep the performance flow visible at all times and hide l
86
  Phones use the same application and backend as desktop browsers. A compact,
87
  touch-oriented layout is selected from viewport and pointer capabilities rather
88
  than device names. Detection combines the current viewport, mobile browser
89
- client hints, touch-pointer capability, and physical CSS screen dimensions so
90
- Android phones still select the phone surface when the browser reports a
91
- desktop-sized viewport. The phone surface contains only the virtual keyboard,
92
- a small live-status message, and the captured/generated piano rolls.
 
 
93
  Configuration, accounts, memory inspection, hardware MIDI, and device routing
94
  remain available in the unchanged desktop/tablet layout.
95
 
 
86
  Phones use the same application and backend as desktop browsers. A compact,
87
  touch-oriented layout is selected from viewport and pointer capabilities rather
88
  than device names. Detection combines the current viewport, mobile browser
89
+ client hints, phone browser identification, touch-pointer capability, and
90
+ physical CSS screen dimensions so Android phones still select the phone surface
91
+ when the browser reports a desktop-sized viewport. The layout class is applied
92
+ before styles load to avoid briefly showing the full desktop controls. The phone
93
+ surface contains only the virtual keyboard, a small live-status message, and the
94
+ captured/generated piano rolls.
95
  Configuration, accounts, memory inspection, hardware MIDI, and device routing
96
  remain available in the unchanged desktop/tablet layout.
97
 
backend/app/main.py CHANGED
@@ -105,7 +105,10 @@ def require_current_user(
105
 
106
  @app.get("/", include_in_schema=False)
107
  def read_index() -> FileResponse:
108
- return FileResponse(settings.frontend_dir / "index.html")
 
 
 
109
 
110
 
111
  @app.get("/health", tags=["system"])
 
105
 
106
  @app.get("/", include_in_schema=False)
107
  def read_index() -> FileResponse:
108
+ return FileResponse(
109
+ settings.frontend_dir / "index.html",
110
+ headers={"Cache-Control": "no-cache, must-revalidate"},
111
+ )
112
 
113
 
114
  @app.get("/health", tags=["system"])
frontend/app.js CHANGED
@@ -1626,6 +1626,9 @@ function isPhoneLayout() {
1626
  window.matchMedia?.(PHONE_LAYOUT_MEDIA_QUERY).matches,
1627
  );
1628
  const mobileClientHint = navigator.userAgentData?.mobile === true;
 
 
 
1629
  const coarseTouch =
1630
  Boolean(window.matchMedia?.("(pointer: coarse)").matches) ||
1631
  navigator.maxTouchPoints > 0;
@@ -1639,6 +1642,7 @@ function isPhoneLayout() {
1639
  return (
1640
  responsiveMatch ||
1641
  mobileClientHint ||
 
1642
  (coarseTouch && compactPhysicalScreen)
1643
  );
1644
  }
 
1626
  window.matchMedia?.(PHONE_LAYOUT_MEDIA_QUERY).matches,
1627
  );
1628
  const mobileClientHint = navigator.userAgentData?.mobile === true;
1629
+ const phoneUserAgent = /Android.+Mobile|iPhone|iPod/i.test(
1630
+ navigator.userAgent || "",
1631
+ );
1632
  const coarseTouch =
1633
  Boolean(window.matchMedia?.("(pointer: coarse)").matches) ||
1634
  navigator.maxTouchPoints > 0;
 
1642
  return (
1643
  responsiveMatch ||
1644
  mobileClientHint ||
1645
+ phoneUserAgent ||
1646
  (coarseTouch && compactPhysicalScreen)
1647
  );
1648
  }
frontend/index.html CHANGED
@@ -6,7 +6,23 @@
6
  <meta name="color-scheme" content="only light" />
7
  <meta name="theme-color" content="#071217" />
8
  <title>Web Continuator</title>
9
- <link rel="stylesheet" href="/assets/styles.css?v=20260729-phone5" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  </head>
11
  <body>
12
  <div class="page-aura"></div>
@@ -1198,6 +1214,6 @@
1198
  </section>
1199
  </main>
1200
 
1201
- <script type="module" src="/assets/app.js?v=20260729-phone4"></script>
1202
  </body>
1203
  </html>
 
6
  <meta name="color-scheme" content="only light" />
7
  <meta name="theme-color" content="#071217" />
8
  <title>Web Continuator</title>
9
+ <script>
10
+ (() => {
11
+ const requestedLayout = new URLSearchParams(window.location.search).get("layout");
12
+ const phoneUserAgent = /Android.+Mobile|iPhone|iPod/i.test(
13
+ navigator.userAgent || "",
14
+ );
15
+ const narrowViewport = window.matchMedia?.("(max-width: 700px)").matches;
16
+ const phoneLayout =
17
+ requestedLayout === "phone" ||
18
+ (requestedLayout !== "desktop" &&
19
+ (phoneUserAgent ||
20
+ navigator.userAgentData?.mobile === true ||
21
+ narrowViewport));
22
+ document.documentElement.classList.toggle("phone-layout", phoneLayout);
23
+ })();
24
+ </script>
25
+ <link rel="stylesheet" href="/assets/styles.css?v=20260729-phone6" />
26
  </head>
27
  <body>
28
  <div class="page-aura"></div>
 
1214
  </section>
1215
  </main>
1216
 
1217
+ <script type="module" src="/assets/app.js?v=20260729-phone6"></script>
1218
  </body>
1219
  </html>