mirror of
git://f0xx.org/android_cast
synced 2026-07-29 07:39:15 +03:00
next force snapshot
This commit is contained in:
@@ -11,33 +11,32 @@
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="/app/androidcast_project/crashes/assets/css/app.css">
|
||||
<link rel="stylesheet" href="hub.css?v=20260527v">
|
||||
<link rel="stylesheet" href="hub.css?v=20260529a">
|
||||
<link rel="stylesheet" href="hub-logo-layers.css">
|
||||
<script src="assets/analytics.config.js"></script>
|
||||
<script src="/app/androidcast_project/crashes/assets/js/analytics.js" defer></script>
|
||||
</head>
|
||||
<body class="hub-page">
|
||||
<div id="overtime-alphabet-host" hidden aria-hidden="true"></div>
|
||||
<div id="quartz-alphabet-host" hidden aria-hidden="true"></div>
|
||||
<div id="hub-logo-stage" class="hub-logo-stage" hidden aria-hidden="true"></div>
|
||||
<section class="hub-clock-widget" id="hub-clock-widget" aria-label="World clock widget">
|
||||
<div class="cw-row cw-row-main">
|
||||
<div class="cw-cell cw-main-cell">
|
||||
<div class="cw-line cw-line-time">
|
||||
<div class="cw-clock-inner">
|
||||
<div class="cw-primary-block">
|
||||
<div class="cw-line cw-row cw-row-clock cw-line-time">
|
||||
<strong class="cw-time-main">
|
||||
<span id="cw-hm-lcd" class="ot-lcd-line ot-lcd-bold" aria-label="Hours and minutes"></span>
|
||||
<span id="cw-ss-lcd" class="ot-lcd-line ot-lcd-sec ot-lcd-bold" aria-label="Seconds"></span>
|
||||
<span id="cw-tz-text" class="ot-lcd-line ot-lcd-tz ot-lcd-bold" aria-label="Timezone offset"></span>
|
||||
<span id="cw-hm-lcd" class="ot-lcd-line ot-lcd-bold cw-col-hm" aria-label="Hours and minutes"></span>
|
||||
<span id="cw-colon-lcd" class="ot-lcd-line ot-lcd-colon cw-colon-blink" aria-label="Separator"></span>
|
||||
<span id="cw-ss-lcd" class="ot-lcd-line ot-lcd-sec cw-col-ss" aria-label="Seconds"></span>
|
||||
<span id="cw-tz-text" class="ot-lcd-line ot-lcd-tz cw-col-tz" aria-label="Timezone offset"></span>
|
||||
</strong>
|
||||
</div>
|
||||
<div class="cw-line cw-line-region" id="cw-region">EUROPE/WARSAW</div>
|
||||
<div class="cw-line cw-line-date" id="cw-date-line">WED 27 MAY 2026</div>
|
||||
<div class="cw-line cw-row cw-row-tz cw-line-region ot-lcd-subline" id="cw-region">EUROPE/WARSAW</div>
|
||||
<div class="cw-line cw-row cw-row-date cw-line-date ot-lcd-subline" id="cw-date-line">WED 27 MAY 2026</div>
|
||||
</div>
|
||||
<div class="cw-separator" aria-hidden="true"></div>
|
||||
<div class="cw-world-section" id="cw-world-row"></div>
|
||||
</div>
|
||||
<div class="cw-row cw-row-mid">
|
||||
<div class="cw-cell"></div>
|
||||
<div class="cw-cell"></div>
|
||||
<div class="cw-cell"></div>
|
||||
<div class="cw-cell"></div>
|
||||
</div>
|
||||
<div class="cw-row cw-row-world" id="cw-world-row"></div>
|
||||
</section>
|
||||
<div id="hub-docs-modal" class="hub-docs-modal" hidden aria-hidden="true">
|
||||
<div class="hub-docs-backdrop" data-close-docs></div>
|
||||
@@ -59,7 +58,10 @@
|
||||
<header class="hub-header">
|
||||
<div class="hub-brand">
|
||||
<img class="hub-logo-mark" src="assets/hub-logo-transparent.svg" alt="" width="112" height="84" decoding="async">
|
||||
<h1 class="hub-title">Android Cast</h1>
|
||||
<div class="hub-title-with-thunder">
|
||||
<h1 class="hub-title">Android Cast</h1>
|
||||
<img class="hub-thunder" src="assets/hub-thunder.svg?v=20260527z" alt="" decoding="async">
|
||||
</div>
|
||||
</div>
|
||||
<p class="muted hub-subtitle">Project hub</p>
|
||||
<label class="toolbar-select hub-theme">
|
||||
@@ -114,7 +116,7 @@
|
||||
var supportsLayout = !!(window.CSS && CSS.supports && CSS.supports('object-fit', 'cover'));
|
||||
if (!supportsSvg || !supportsLayout) return;
|
||||
|
||||
var logoBuild = '20260527s';
|
||||
var logoBuild = '20260529a';
|
||||
var fragments = {
|
||||
space: 'assets/hub-logo-fragment-space.svg',
|
||||
globe: 'assets/hub-logo-fragment-globe.svg',
|
||||
@@ -464,12 +466,15 @@
|
||||
|
||||
var overtimeReady = false;
|
||||
var overtimeSymbolIds = {};
|
||||
var quartzReady = false;
|
||||
var quartzSymbolIds = {};
|
||||
|
||||
function overtimeSymbolId(ch) {
|
||||
if (ch >= '0' && ch <= '9') return 'ot-' + ch;
|
||||
if (ch === ':') return 'ot-colon';
|
||||
if (ch === '+') return 'ot-plus';
|
||||
if (ch === '-') return 'ot-minus';
|
||||
if (ch === '/') return 'ot-slash';
|
||||
if (ch === ' ') return 'ot-space';
|
||||
if (ch >= 'A' && ch <= 'Z') return 'ot-' + ch;
|
||||
return null;
|
||||
@@ -491,60 +496,96 @@
|
||||
.catch(function () { done(false); });
|
||||
}
|
||||
|
||||
function buildGlyphGrid(svg, vb) {
|
||||
function quartzSymbolId(ch) {
|
||||
if (ch >= '0' && ch <= '9') return 'qz-' + ch;
|
||||
if (ch === ':') return 'qz-colon';
|
||||
if (ch === '+') return 'qz-plus';
|
||||
if (ch === '-') return 'qz-minus';
|
||||
if (ch === '/') return 'qz-slash';
|
||||
if (ch === ' ') return 'qz-space';
|
||||
if (ch >= 'A' && ch <= 'Z') return 'qz-' + ch;
|
||||
return null;
|
||||
}
|
||||
|
||||
function loadQuartzAlphabet(done) {
|
||||
var host = document.getElementById('quartz-alphabet-host');
|
||||
if (!host) { done(false); return; }
|
||||
fetch('assets/quartz-alphabet.svg?v=' + logoBuild)
|
||||
.then(function (res) { return res.text(); })
|
||||
.then(function (svgText) {
|
||||
host.innerHTML = svgText;
|
||||
host.querySelectorAll('symbol').forEach(function (sym) {
|
||||
if (sym.id) quartzSymbolIds[sym.id] = sym;
|
||||
});
|
||||
quartzReady = true;
|
||||
done(true);
|
||||
})
|
||||
.catch(function () { done(false); });
|
||||
}
|
||||
|
||||
var OVERTIME_SEG_GRID = [
|
||||
[3, 1, 14, 3], [1, 4, 3, 11], [16, 4, 3, 11],
|
||||
[3, 15, 14, 3], [1, 17, 3, 11], [16, 17, 3, 11],
|
||||
[3, 28, 14, 3]
|
||||
];
|
||||
|
||||
function parseOvertimeRects(sym) {
|
||||
var rects = [];
|
||||
sym.querySelectorAll('rect').forEach(function (node) {
|
||||
rects.push({
|
||||
x: parseFloat(node.getAttribute('x') || 0),
|
||||
y: parseFloat(node.getAttribute('y') || 0),
|
||||
w: parseFloat(node.getAttribute('width') || 0),
|
||||
h: parseFloat(node.getAttribute('height') || 0)
|
||||
});
|
||||
});
|
||||
return rects;
|
||||
}
|
||||
|
||||
function overtimeSegMatchesRect(seg, rect) {
|
||||
var eps = 1.25;
|
||||
return Math.abs(rect.x - seg[0]) <= eps
|
||||
&& Math.abs(rect.y - seg[1]) <= eps
|
||||
&& Math.abs(rect.w - seg[2]) <= eps
|
||||
&& Math.abs(rect.h - seg[3]) <= eps;
|
||||
}
|
||||
|
||||
function overtimeSegIsLit(seg, activeRects) {
|
||||
for (var i = 0; i < activeRects.length; i++) {
|
||||
if (overtimeSegMatchesRect(seg, activeRects[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function buildOvertimeInactiveGrid(svg, sym, glyphW) {
|
||||
if (glyphW === 12 || glyphW === 8 || glyphW === 16) return;
|
||||
if (glyphW !== 20 && glyphW < 22) return;
|
||||
var activeRects = parseOvertimeRects(sym);
|
||||
var seg = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||
seg.setAttribute('class', 'ot-grid');
|
||||
var w = vb.width || 20;
|
||||
var h = vb.height || 32;
|
||||
var hPad = Math.max(1, w * 0.12);
|
||||
var topY = Math.max(1, h * 0.04);
|
||||
var midY = h * 0.47;
|
||||
var botY = h * 0.86;
|
||||
var segW = Math.max(6, w - hPad * 2);
|
||||
var segH = Math.max(2, h * 0.09);
|
||||
var vW = Math.max(2, w * 0.14);
|
||||
var vH = Math.max(6, h * 0.33);
|
||||
var leftX = Math.max(1, hPad * 0.45);
|
||||
var rightX = Math.max(leftX + vW + 1, w - leftX - vW);
|
||||
var upperY = topY + segH;
|
||||
var lowerY = midY + segH * 0.6;
|
||||
var defs = [
|
||||
[hPad, topY, segW, segH],
|
||||
[leftX, upperY, vW, vH],
|
||||
[rightX, upperY, vW, vH],
|
||||
[hPad, midY, segW, segH],
|
||||
[leftX, lowerY, vW, vH],
|
||||
[rightX, lowerY, vW, vH],
|
||||
[hPad, botY, segW, segH]
|
||||
];
|
||||
defs.forEach(function (d) {
|
||||
OVERTIME_SEG_GRID.forEach(function (d) {
|
||||
if (overtimeSegIsLit(d, activeRects)) return;
|
||||
var r = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
r.setAttribute('x', d[0].toFixed(2));
|
||||
r.setAttribute('y', d[1].toFixed(2));
|
||||
r.setAttribute('width', d[2].toFixed(2));
|
||||
r.setAttribute('height', d[3].toFixed(2));
|
||||
r.setAttribute('x', String(d[0]));
|
||||
r.setAttribute('y', String(d[1]));
|
||||
r.setAttribute('width', String(d[2]));
|
||||
r.setAttribute('height', String(d[3]));
|
||||
r.setAttribute('rx', '1');
|
||||
seg.appendChild(r);
|
||||
});
|
||||
if (w >= 22) {
|
||||
var d1 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
d1.setAttribute('x', (w * 0.34).toFixed(2));
|
||||
d1.setAttribute('y', (h * 0.15).toFixed(2));
|
||||
d1.setAttribute('width', Math.max(2, w * 0.10).toFixed(2));
|
||||
d1.setAttribute('height', Math.max(6, h * 0.34).toFixed(2));
|
||||
d1.setAttribute('rx', '1');
|
||||
d1.setAttribute('transform', 'rotate(22 ' + (w * 0.39).toFixed(2) + ' ' + (h * 0.32).toFixed(2) + ')');
|
||||
seg.appendChild(d1);
|
||||
var d2 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
d2.setAttribute('x', (w * 0.56).toFixed(2));
|
||||
d2.setAttribute('y', (h * 0.15).toFixed(2));
|
||||
d2.setAttribute('width', Math.max(2, w * 0.10).toFixed(2));
|
||||
d2.setAttribute('height', Math.max(6, h * 0.34).toFixed(2));
|
||||
d2.setAttribute('rx', '1');
|
||||
d2.setAttribute('transform', 'rotate(-22 ' + (w * 0.61).toFixed(2) + ' ' + (h * 0.32).toFixed(2) + ')');
|
||||
seg.appendChild(d2);
|
||||
}
|
||||
svg.appendChild(seg);
|
||||
if (seg.childNodes.length) svg.appendChild(seg);
|
||||
}
|
||||
|
||||
function cloneOvertimeSymbol(svg, sym) {
|
||||
sym.querySelectorAll('rect').forEach(function (node) {
|
||||
var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
['x', 'y', 'width', 'height', 'rx', 'transform'].forEach(function (attr) {
|
||||
var val = node.getAttribute(attr);
|
||||
if (val != null) rect.setAttribute(attr, val);
|
||||
});
|
||||
rect.setAttribute('class', 'ot-active');
|
||||
svg.appendChild(rect);
|
||||
});
|
||||
}
|
||||
|
||||
function renderOvertimeText(el, text, opts) {
|
||||
@@ -556,8 +597,21 @@
|
||||
return;
|
||||
}
|
||||
String(text).toUpperCase().split('').forEach(function (ch) {
|
||||
if (opts.forceFallback) {
|
||||
var forced = document.createElement('span');
|
||||
forced.className = 'ot-fallback-char' + (opts.bold ? ' ot-fallback-char--bold' : '');
|
||||
forced.textContent = ch === ' ' ? '\u00A0' : ch;
|
||||
el.appendChild(forced);
|
||||
return;
|
||||
}
|
||||
var sid = overtimeSymbolId(ch);
|
||||
if (!sid || !overtimeSymbolIds[sid]) return;
|
||||
if (!sid || !overtimeSymbolIds[sid]) {
|
||||
var fb = document.createElement('span');
|
||||
fb.className = 'ot-fallback-char' + (opts.bold ? ' ot-fallback-char--bold' : '');
|
||||
fb.textContent = ch === ' ' ? '\u00A0' : ch;
|
||||
el.appendChild(fb);
|
||||
return;
|
||||
}
|
||||
var wrap = document.createElement('span');
|
||||
wrap.className = 'ot-glyph-wrap' + (opts.bold ? ' ot-glyph-wrap--bold' : '');
|
||||
if (opts.blinkColon && ch === ':') wrap.className += ' ot-colon-blink';
|
||||
@@ -566,19 +620,82 @@
|
||||
var viewBox = sym.getAttribute('viewBox') || '0 0 20 32';
|
||||
svg.setAttribute('viewBox', viewBox);
|
||||
svg.setAttribute('class', 'ot-glyph');
|
||||
svg.setAttribute('aria-hidden', 'true');
|
||||
var vb = viewBox.split(/\s+/).map(function (v) { return Number(v) || 0; });
|
||||
buildGlyphGrid(svg, { width: vb[2] || 20, height: vb[3] || 32 });
|
||||
var glyphW = vb[2] || 20;
|
||||
if (opts.ghost !== false) buildOvertimeInactiveGrid(svg, sym, glyphW);
|
||||
cloneOvertimeSymbol(svg, sym);
|
||||
wrap.appendChild(svg);
|
||||
el.appendChild(wrap);
|
||||
});
|
||||
}
|
||||
|
||||
/* Clock digits: original Overtime path (<use> only, no ghost grid). */
|
||||
function renderOvertimeDigits(el, text, blinkColon, bold) {
|
||||
if (!el) return;
|
||||
el.innerHTML = '';
|
||||
if (!overtimeReady) {
|
||||
el.textContent = text;
|
||||
return;
|
||||
}
|
||||
text.split('').forEach(function (ch) {
|
||||
var sid = overtimeSymbolId(ch);
|
||||
if (!sid || !overtimeSymbolIds[sid]) {
|
||||
el.appendChild(document.createTextNode(ch));
|
||||
return;
|
||||
}
|
||||
var wrap = document.createElement('span');
|
||||
wrap.className = 'ot-glyph-wrap' + (bold ? ' ot-glyph-wrap--bold' : '');
|
||||
if (blinkColon && ch === ':') wrap.className += ' ot-colon-blink';
|
||||
var sym = overtimeSymbolIds[sid];
|
||||
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
svg.setAttribute('viewBox', sym.getAttribute('viewBox') || '0 0 20 32');
|
||||
svg.setAttribute('class', 'ot-glyph');
|
||||
var use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
|
||||
use.setAttribute('href', '#' + sid);
|
||||
use.setAttribute('class', 'ot-active');
|
||||
svg.appendChild(use);
|
||||
wrap.appendChild(svg);
|
||||
el.appendChild(wrap);
|
||||
});
|
||||
}
|
||||
|
||||
function renderOvertimeDigits(el, text, blinkColon, bold) {
|
||||
renderOvertimeText(el, text, { blinkColon: blinkColon, bold: bold });
|
||||
function renderQuartzText(el, text, opts) {
|
||||
opts = opts || {};
|
||||
if (!el) return;
|
||||
el.innerHTML = '';
|
||||
if (!quartzReady) {
|
||||
el.textContent = text;
|
||||
return;
|
||||
}
|
||||
String(text).toUpperCase().split('').forEach(function (ch) {
|
||||
var sid = quartzSymbolId(ch);
|
||||
if (!sid || !quartzSymbolIds[sid]) {
|
||||
var fb = document.createElement('span');
|
||||
fb.className = 'qz-fallback-char' + (opts.bold ? ' qz-fallback-char--bold' : '');
|
||||
fb.textContent = ch === ' ' ? '\u00A0' : ch;
|
||||
el.appendChild(fb);
|
||||
return;
|
||||
}
|
||||
var wrap = document.createElement('span');
|
||||
wrap.className = 'qz-glyph-wrap' + (opts.bold ? ' qz-glyph-wrap--bold' : '');
|
||||
if (opts.blinkColon && ch === ':') wrap.className += ' qz-colon-blink';
|
||||
var sym = quartzSymbolIds[sid];
|
||||
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
var viewBox = sym.getAttribute('viewBox') || '0 0 20 32';
|
||||
svg.setAttribute('viewBox', viewBox);
|
||||
svg.setAttribute('class', 'qz-glyph');
|
||||
var vb = viewBox.split(/\s+/).map(function (v) { return Number(v) || 0; });
|
||||
var use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
|
||||
use.setAttribute('href', '#' + sid);
|
||||
use.setAttribute('class', 'qz-active');
|
||||
svg.appendChild(use);
|
||||
wrap.appendChild(svg);
|
||||
el.appendChild(wrap);
|
||||
});
|
||||
}
|
||||
|
||||
function renderQuartzDigits(el, text, blinkColon, bold) {
|
||||
renderQuartzText(el, text, { blinkColon: blinkColon, bold: bold });
|
||||
}
|
||||
|
||||
function regionLabel(tz) {
|
||||
@@ -623,11 +740,12 @@
|
||||
function updateClockWidget() {
|
||||
var now = new Date();
|
||||
var p = timeParts(now, primaryTz);
|
||||
renderOvertimeDigits(document.getElementById('cw-hm-lcd'), p.hh + ':' + p.mm, false, true);
|
||||
renderOvertimeDigits(document.getElementById('cw-ss-lcd'), ':' + p.ss, true, true);
|
||||
renderOvertimeText(document.getElementById('cw-tz-text'), gmtOffsetLabel(now, primaryTz), { bold: true });
|
||||
document.getElementById('cw-region').textContent = regionLabel(primaryTz);
|
||||
document.getElementById('cw-date-line').textContent = formatDateLine(now, primaryTz);
|
||||
renderOvertimeDigits(document.getElementById('cw-hm-lcd'), p.hh + p.mm, false, false);
|
||||
renderOvertimeDigits(document.getElementById('cw-colon-lcd'), ':', false, false);
|
||||
renderOvertimeDigits(document.getElementById('cw-ss-lcd'), p.ss, false, false);
|
||||
renderOvertimeText(document.getElementById('cw-tz-text'), gmtOffsetLabel(now, primaryTz), { bold: false });
|
||||
renderOvertimeText(document.getElementById('cw-region'), regionLabel(primaryTz), { bold: false });
|
||||
renderOvertimeText(document.getElementById('cw-date-line'), formatDateLine(now, primaryTz), { bold: false });
|
||||
|
||||
secondary.forEach(function (clock) {
|
||||
var t = timeParts(now, clock.tz);
|
||||
@@ -651,12 +769,15 @@
|
||||
h.className = 'cw-resize-handle cw-resize-' + pos;
|
||||
h.dataset.resize = pos;
|
||||
h.setAttribute('aria-hidden', 'true');
|
||||
var visual = document.createElement('span');
|
||||
visual.className = 'cw-resize-handle-visual';
|
||||
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
svg.setAttribute('viewBox', '0 0 45.279 45.279');
|
||||
var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
path.setAttribute('d', arrowPath);
|
||||
svg.appendChild(path);
|
||||
h.appendChild(svg);
|
||||
visual.appendChild(svg);
|
||||
h.appendChild(visual);
|
||||
widget.appendChild(h);
|
||||
});
|
||||
|
||||
@@ -687,7 +808,7 @@
|
||||
widget.style.left = Math.max(0, ev.clientX - drag.dx) + 'px';
|
||||
widget.style.top = Math.max(0, ev.clientY - drag.dy) + 'px';
|
||||
} else {
|
||||
var minW = 1, minH = 1;
|
||||
var minW = 280, minH = 210;
|
||||
var dx = ev.clientX - drag.x;
|
||||
var dy = ev.clientY - drag.y;
|
||||
var left = drag.left, top = drag.top, width = drag.width, height = drag.height;
|
||||
@@ -704,7 +825,7 @@
|
||||
widget.style.left = Math.max(0, left) + 'px';
|
||||
widget.style.top = Math.max(0, top) + 'px';
|
||||
widget.style.width = width + 'px';
|
||||
widget.style.minWidth = '';
|
||||
widget.style.minWidth = width + 'px';
|
||||
widget.style.transform = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user