bm-bmt/App.vue

272 lines
5.9 KiB
Vue

<script>
import {
getCurrentWebviewUrl,
refreshCurrentWebviewToken,
} from "./utils/webview-token";
let numberFontSupportPromise = null;
let numberFontSupportState = null;
function hasBrowserDom() {
return typeof window !== "undefined" && typeof document !== "undefined";
}
function toggleNumberFontReadyClass(enabled) {
if (!hasBrowserDom() || !document.documentElement) {
return;
}
document.documentElement.classList.toggle(
"asset-din-font-ready",
Boolean(enabled),
);
}
function waitForBodyReady() {
return new Promise((resolve) => {
if (!hasBrowserDom() || document.body) {
resolve();
return;
}
const finish = () => resolve();
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", finish, {
once: true,
});
return;
}
setTimeout(finish, 0);
});
}
function createMeasureNode(fontFamily) {
const node = document.createElement("span");
node.textContent = "0123456789";
node.style.position = "absolute";
node.style.left = "-99999px";
node.style.top = "-99999px";
node.style.visibility = "hidden";
node.style.whiteSpace = "nowrap";
node.style.fontSize = "32px";
node.style.fontWeight = "800";
node.style.fontFamily = fontFamily;
return node;
}
function verifyDinFontRender() {
if (!hasBrowserDom() || !document.body) {
return false;
}
const container = document.createElement("div");
container.style.position = "absolute";
container.style.left = "-99999px";
container.style.top = "-99999px";
container.style.visibility = "hidden";
container.style.pointerEvents = "none";
const fallbackFamilies = ["monospace", "sans-serif", "serif"];
const loadedWidths = [];
const fallbackWidths = [];
fallbackFamilies.forEach((family) => {
const fallbackNode = createMeasureNode(family);
const loadedNode = createMeasureNode('"DIN-Bold", ' + family);
container.appendChild(fallbackNode);
container.appendChild(loadedNode);
});
document.body.appendChild(container);
Array.prototype.forEach.call(container.childNodes, (node, index) => {
const width = node.getBoundingClientRect().width;
if (index % 2 === 0) {
fallbackWidths.push(width);
return;
}
loadedWidths.push(width);
});
const isFontAvailable = fallbackWidths.some((width, index) => {
return Math.abs(loadedWidths[index] - width) > 0.1;
});
document.body.removeChild(container);
return isFontAvailable;
}
async function ensureNumberFontSupport() {
if (!hasBrowserDom()) {
return false;
}
if (!document.fonts || typeof document.fonts.load !== "function") {
return false;
}
await waitForBodyReady();
const loadSucceeded = await Promise.race([
document.fonts
.load('800 32px "DIN-Bold"', "0123456789")
.then((fonts) => Array.isArray(fonts) ? fonts.length > 0 : true)
.catch(() => false),
new Promise((resolve) => {
setTimeout(() => resolve(false), 2500);
}),
]);
if (
!loadSucceeded ||
!document.fonts.check('800 32px "DIN-Bold"', "0123456789")
) {
return false;
}
return verifyDinFontRender();
}
export default {
onLaunch: function () {
console.log("App Launch");
this.logCurrentWebviewToken("launch");
this.syncNumberFontSupport();
},
onShow: function () {
console.log("App Show");
this.logCurrentWebviewToken("show");
this.syncNumberFontSupport();
},
onHide: function () {
console.log("App Hide");
},
methods: {
logCurrentWebviewToken(scene) {
const currentUrl = getCurrentWebviewUrl();
const token = refreshCurrentWebviewToken(currentUrl);
if (token) {
console.log("[webview-token][" + scene + "]", token);
return;
}
console.log("[webview-token][" + scene + "] token not found", currentUrl);
},
async syncNumberFontSupport() {
if (!hasBrowserDom()) {
return;
}
if (numberFontSupportState !== null) {
toggleNumberFontReadyClass(numberFontSupportState);
return;
}
if (!numberFontSupportPromise) {
numberFontSupportPromise = ensureNumberFontSupport()
.then((result) => {
numberFontSupportState = Boolean(result);
return numberFontSupportState;
})
.catch(() => {
numberFontSupportState = false;
return false;
});
}
const canUseDinFont = await numberFontSupportPromise;
toggleNumberFontReadyClass(canUseDinFont);
},
},
};
</script>
<style lang="scss">
@import "./styles/tokens.scss";
@font-face {
font-family: "DIN-Bold";
src:
local("DIN-Bold"),
local("DIN Bold"),
local("DIN Alternate Bold"),
url("/static/fonts/din-bold-2.ttf") format("truetype"),
url("https://imgs.agrimedia.cn/din-bold-2.ttf") format("truetype");
font-style: normal;
font-weight: 800;
font-display: optional;
}
:root {
--asset-number-font-family:
"Helvetica Neue",
Arial,
"PingFang SC",
sans-serif;
--asset-number-font-family-din:
"DIN-Bold",
DIN,
"DIN Alternate",
"Helvetica Neue",
Arial,
"PingFang SC",
sans-serif;
}
.asset-din-font-ready {
--asset-number-font-family: var(--asset-number-font-family-din);
}
.asset-number-font {
font-family: var(--asset-number-font-family) !important;
font-variant-numeric: tabular-nums;
}
html,
body,
#app {
min-height: 100%;
margin: 0;
background: #191e32;
}
uni-page,
uni-page-wrapper,
uni-page-body {
min-height: 100%;
background: #191e32;
}
page {
min-height: 100%;
background: #191e32;
color: $asset-text-main;
font-family: "PingFang SC", "Helvetica Neue", Arial, sans-serif;
}
view,
text,
button,
input,
textarea,
scroll-view {
box-sizing: border-box;
}
.asset-theme {
--asset-accent: #4cc9ff;
--asset-accent-strong: #5a71ff;
--asset-success: #5ad7a1;
--asset-danger: #ff7285;
--asset-text-main: #ffffff;
--asset-text-muted: rgba(255, 255, 255, 0.78);
--asset-text-dark: #112446;
}
</style>