1/* 2 * ui-scale.js â UI scale compensation for the Tesla in-car browser. 3 * 4 * The browser's effective page zoom changed, so the same CSS px now covers more of 5 * the panel and the whole UI reads oversized. We counter it by shrinking the root, 6 * which hands the layout back the CSS width it used to have. 7 * 8 * scale k -> effective layout size = innerWidth / k x innerHeight / k 9 * 10 * Modes: 11 * zoom CSS zoom on <html>. Layout-correct, position:fixed unaffected. Spec-compliant 12 * zoom (Chrome 128+) multiplies computed font-size, so if a minimum font size 13 * floor is in play, small text stops scaling with everything else. 14 * transform scale() on <body>. Computed font sizes untouched, so immune to that clamping, 15 * at the cost of reparenting fixed positioning to <body>. 16 * 17 * Anything that sizes against window.innerWidth/innerHeight must divide by the active 18 * scale, because those report the OUTER viewport while the layout now lives in the 19 * inner (scaled) coordinate space. Use CCFIX.viewportWidth()/viewportHeight(). 20 * 21 * Overrides: ?uiscale=0.8 ?uimode=transform (persisted to cookies) 22 * 23 * No dependencies â this loads before utils.js/cookies.js so it reads params and 24 * cookies itself. 25 */ 26var CCFIX = (function () { 27 'use strict'; 28 29 var STEP = 0.05, MIN = 0.4, MAX = 2.0; 30 // Auto is a hypothesis (devicePixelRatio moves with zoom but also with genuine hiDPI), 31 // not a measurement, so it gets a tighter floor than a manual setting. 32 var AUTO_MIN = 0.65; 33 34 var scale = 1, mode = 'zoom', auto = true; 35 36 function param(name) { 37 var m = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)').exec(window.location.href); 38 if (!m) return null; 39 return m[2] ? decodeURIComponent(m[2].replace(/\+/g, ' ')) : ''; 40 } 41 42 function readCookie(name) { 43 var m = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)')); 44 return m ? decodeURIComponent(m[1]) : null; 45 } 46 47 function writeCookie(name, value) { 48 try { 49 document.cookie = name + '=' + encodeURIComponent(value) + '; path=/; max-age=' + (60 * 60 * 24 * 365); 50 } catch (e) { /* private mode */ } 51 } 52 53 function clamp(k, lo) { 54 return Math.min(MAX, Math.max(lo === undefined ? MIN : lo, k)); 55 } 56 57 function suggested() { 58 var dpr = window.devicePixelRatio || 1; 59 return clamp(Math.round((1 / dpr) / STEP) * STEP, AUTO_MIN); 60 } 61 62 function injectStyle() { 63 if (document.getElementById('ccfix-style')) return; 64 var css = 65 'html{-webkit-text-size-adjust:none !important;text-size-adjust:none !important;}' + 66 'html.ccfix-zoom{zoom:var(--ccfix-scale,1);}
66' + 67 'html.ccfix-transform{overflow:hidden !important;width:100% !important;height:100% !important;}' + 68 'html.ccfix-transform > body{' + 69 'transform:scale(var(--ccfix-scale,1)) !important;transform-origin:0 0 !important;' + 70 'width:calc(100% / var(--ccfix-scale,1)) !important;' + 71 'height:calc(100% / var(--ccfix-scale,1)) !important;}' + 72 /* styles.less uses viewport units in three places. Viewport units do not rescale 73 with zoom or transform, so without these the full-screen overlay and the pairing 74 pane would be left at the wrong size. Percentage-based rules self-correct. */ 75 'html.ccfix-active body .overlay{' + 76 'width:calc(100vw / var(--ccfix-scale,1)) !important;' + 77 'height:calc(100vh / var(--ccfix-scale,1)) !important;}' + 78 'html.ccfix-active body article.pairing,' + 79 'html.ccfix-active body article.paired,' + 80 'html.ccfix-active body article.journey,' + 81 'html.ccfix-active body article.disclaimer{' + 82 'height:calc((100vh / var(--ccfix-scale,1)) - var(--footer-h, 84px)) !important;}'; 83 84 var style = document.createElement('style'); 85 style.id = 'ccfix-style'; 86 style.appendChild(document.createTextNode(css)); 87 (document.head || document.documentElement).appendChild(style); 88 } 89 90 function apply() { 91 var html = document.documentElement; 92 var active = Math.abs(scale - 1) > 0.0005; 93 94 html.style.setProperty('--ccfix-scale', String(scale)); 95 html.classList.toggle('ccfix-active', active); 96 html.classList.toggle('ccfix-zoom', active && mode === 'zoom'); 97 html.classList.toggle('ccfix-transform', active && mode === 'transform'); 98 99 writeCookie('ccfixScale', String(scale)); 100 writeCookie('ccfixMode', mode); 101 writeCookie('ccfixAuto', auto ? '1' : '0'); 102 103 if (typeof window.onCCFixChange === 'function') { 104 try { window.onCCFixChange(scale, mode); } catch (e) { } 105 } 106 } 107 108 function relayout() { 109 // Anything sized off the viewport has to be recomputed in the new coordinate space. 110 if (typeof setDeviceMode === 'function' && typeof currentDisplayMode !== 'undefined' && currentDisplayMode) { 111 try { setDeviceMode(currentDisplayMode); } catch (e) { } 112 } 113 } 114 115 function set(k, isAuto) { 116 auto = !!isAuto; 117 scale = clamp(Math.round(k / 0.001) * 0.001); 118 apply(); 119 relayout(); 120 return scale; 121 } 122 123 function init() { 124 var qMode = param('uimode'); 125 if (qMode === 'zoom' || qMode === 'transform') mode = qMode; 126 else if (readCookie('ccfixMode') === 'transform') mode = 'transform'; 127 128 var qScale = param('uiscale'); 129 if (qScale !== null && qScale !== '' && isFinite(parseFloat(qScale))) { 130 scale = clamp(parseFloat(qScale)); 131 auto = false; 132 } else { 133 var ck = readCookie('ccfixScale'); 134 if (ck !== null && isFinite(parseFloat(ck)) && readCookie('ccfixAuto') === '0') { 135 scale = clamp(parseFloat(ck)); 136 auto = false; 137 } else { 138 scale = suggested(); 139 auto = true; 140 } 141 } 142 143 injectStyle(); 144 apply(); 145 146 window.addEventListener('resize', function () { 147 if (auto) { 148 var next = suggested(); 149 if (Math.abs(next - scale) > 0.0005) { 150 scale = next; 151 apply(); 152 } 153 } 154 relayout(); 155 }); 156 } 157 158 init(); 159 160 return { 161 // effective layout viewport â use these instead of window.innerWidth/innerHeight 162 viewportWidth: function () { return window.innerWidth / scale; }, 163 viewportHeight: function () { return window.innerHeight / scale; }, 164 get scale() { return scale; }, 165 get mode() { return mode; }, 166 get auto() { return auto; }, 167 get active() { return Math.abs(scale - 1) > 0.0005; }, 168 suggested: suggested, 169 step: STEP, 170 setScale: function (k) { return set(k, false); }, 171 setAuto: function () { return set(suggested(), true); }, 172 setMode: function (m) { 173 if (m !== 'zoom' && m !== 'transform') return mode; 174 mode = m; 175 apply(); 176 relayout(); 177 return mode; 178 } 179 }; 180})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.