Qdpie's picture
Upload 74 files
09472e9 verified
Raw
History Blame Contribute Delete
5.9 kB
() => {
/**
* Dual-skin boot: pick desktop vs phone layout, keep a single set of IDs in the DOM.
*
* Rules (first match wins for force flags):
* ?ui=phone | ?ui=mobile → phone
* ?ui=desktop | ?ui=pc → desktop
* Mobile / phone UA → phone (HF embeds often report a WIDE iframe width)
* max-width ≤ 768px → phone
* else → desktop
*
* Unused skin is removed so getElementById stays unambiguous for gallery.js.
*/
function wantPhoneUI() {
try {
var q = new URLSearchParams(window.location.search || "");
var force = (q.get("ui") || "").toLowerCase();
if (force === "phone" || force === "mobile") return true;
if (force === "desktop" || force === "pc") return false;
} catch (e) {}
// Real phones/tablets in portrait-ish embeds: don't trust iframe CSS width alone
try {
var ua = navigator.userAgent || "";
if (/Android.+Mobile|iPhone|iPod|webOS|BlackBerry|IEMobile|Opera Mini/i.test(ua)) {
return true;
}
// iPad / Android tablet — treat as phone layout (single column)
if (/iPad|Android(?!.*Mobile)|Tablet/i.test(ua)) {
return true;
}
if (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) {
return true; // iPadOS desktop UA
}
} catch (e2) {}
try {
if (window.matchMedia("(max-width: 768px)").matches) return true;
// Very short + narrow-ish viewport (mobile browser chrome)
if (window.matchMedia("(max-width: 900px) and (max-height: 900px) and (pointer: coarse)").matches) {
return true;
}
} catch (e3) {
if ((window.innerWidth || 1024) <= 768) return true;
}
return false;
}
/**
* Gradio / Spaces often inject maximum-scale=1 or user-scalable=no, which kills
* pinch-zoom. Restore a viewport that allows zoom (a11y + your request).
*/
function ensureZoomableViewport() {
try {
var allow =
"width=device-width, initial-scale=1, viewport-fit=cover, " +
"minimum-scale=0.5, maximum-scale=5, user-scalable=yes";
var metas = document.querySelectorAll('meta[name="viewport"]');
if (!metas || !metas.length) {
var m = document.createElement("meta");
m.setAttribute("name", "viewport");
m.setAttribute("content", allow);
(document.head || document.documentElement).appendChild(m);
return;
}
for (var i = 0; i < metas.length; i++) {
metas[i].setAttribute("content", allow);
}
} catch (e) {}
}
/**
* HF / Gradio wrap the app in transformed/overflow ancestors, so position:fixed
* on .phone-run is relative to that box (often off-screen). Moving the bar to
* document.body makes fixed = real viewport. Embeds often don't have those
* ancestors — which is why floating Edit already worked there.
*/
function pinPhoneRunBar() {
try {
if (window.__qwenUiSkin !== "phone") return;
var bar = document.querySelector(".phone-run");
if (!bar || !document.body) return;
if (bar.parentNode === document.body) {
bar.classList.add("phone-run--ported");
return;
}
// Marker so we can leave a spacer if needed (stack already has padding-bottom)
bar.setAttribute("data-ported", "1");
bar.classList.add("phone-run--ported");
document.body.appendChild(bar);
} catch (e) {}
}
function activate() {
var phone = wantPhoneUI();
var desktop = document.getElementById("skin-desktop");
var phoneEl = document.getElementById("skin-phone");
// Skins not in DOM yet
if (!desktop && !phoneEl) return false;
// Always allow pinch/zoom — do not lock scale on phone or desktop
ensureZoomableViewport();
if (phone) {
if (desktop && desktop.parentNode) desktop.parentNode.removeChild(desktop);
if (phoneEl) {
phoneEl.hidden = false;
phoneEl.removeAttribute("hidden");
phoneEl.style.display = "";
}
document.documentElement.setAttribute("data-ui-skin", "phone");
try { document.body && document.body.setAttribute("data-ui-skin", "phone"); } catch (e4) {}
window.__qwenUiSkin = "phone";
pinPhoneRunBar();
// DOM may still be settling on HF
setTimeout(pinPhoneRunBar, 100);
setTimeout(pinPhoneRunBar, 500);
setTimeout(pinPhoneRunBar, 1500);
} else {
// If we previously ported the bar, remove orphan
try {
var orphan = document.querySelector("body > .phone-run");
if (orphan) orphan.parentNode.removeChild(orphan);
} catch (e6) {}
if (phoneEl && phoneEl.parentNode) phoneEl.parentNode.removeChild(phoneEl);
if (desktop) {
desktop.hidden = false;
desktop.removeAttribute("hidden");
desktop.style.display = "";
}
document.documentElement.setAttribute("data-ui-skin", "desktop");
try { document.body && document.body.setAttribute("data-ui-skin", "desktop"); } catch (e5) {}
window.__qwenUiSkin = "desktop";
}
return true;
}
// Expose for gallery.js / lora_demo.js if boot load order is flaky
window.__qwenActivateUiSkin = activate;
window.__qwenWantPhoneUI = wantPhoneUI;
window.__qwenEnsureZoomableViewport = ensureZoomableViewport;
window.__qwenPinPhoneRunBar = pinPhoneRunBar;
function tryActivate(n) {
// Fix zoom even before skins appear (Gradio may set a locked viewport early)
ensureZoomableViewport();
if (activate()) {
// Gradio sometimes rewrites viewport after load — re-assert zoom a few times
setTimeout(ensureZoomableViewport, 200);
setTimeout(ensureZoomableViewport, 1000);
setTimeout(ensureZoomableViewport, 3000);
return;
}
if (n < 60) setTimeout(function () { tryActivate(n + 1); }, 50);
}
tryActivate(0);
}