1<!DOCTYPE html> 2<html> 3 4<head> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 7 <title id="page-title"></title> 8 <base href="/" /> 9 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> 10 <link href="css/app.css" rel="stylesheet" /> 11 <link href="manifest.json" rel="manifest" /> 12 <link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" /> 13 14 <!-- Global site tag (gtag.js) - Google Analytics -->
vendor: 69 bytes, lines 14-15
14 15 <script async src="https://www.googletagmanager.com/gtag/js?id=
15G-R5DM63ZGX6
vendor: 17 bytes, lines 15-16
15"></script> 16
16<script> 17
vendor: 159 bytes, lines 17-21
17window.dataLayer = window.dataLayer || []; 18 function gtag() { dataLayer.push(arguments); } 19 gtag('js', new Date()); 20 21 gtag('config', '
21G-R5DM63ZGX6
vendor: 9 bytes, lines 21-22
21'); 22
22</script>
22 23</head> 24 25<body> 26 <app> 27 <div class="d-flex justify-content-center"> 28 <div class="d-flex flex-column"> 29 <div class="d-flex justify-content-center m-5"> 30 <div class="spinner-border" role="status"></div> 31 </div> 32 <a href='#' onclick="return window.onPlayStoreClick();"><img style="width: 300px;" src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' /></a> 33 </div> 34 </div> 35 </app> 36 37 <!-- Don't put javascript in href. If the function returns any explicit value (ex: return null;, but not return;), 38 this will have unintended consequences in some browsers, such as FireFox. 39 The page will have all content replaced with the returned value in string format --> 40 <div id="blazor-error-ui"> 41 <span id="reload-error-text">We can't connect to the service right now. Check your cellular data or Wi-Fi connection.</span> 42 <a id="reload-error-button" href="#" onclick="return window.onUnhandledException();">Refresh</a> 43 <a class="dismiss close">×</a> 44 </div> 45
45<script src="_framework/blazor.webassembly.js"></script>
45 46
46<script>navigator.serviceWorker.register('service-worker.js');</script>
46 47 48
48<script src="ytplayerv5.js"></script>
48 49
49<script src="howlerplayer.js"></script>
49 50
50<script> 51 window.getMobileOperatingSystem = () => { 52 var userAgent = navigator.userAgent || navigator.vendor || window.opera; 53 54 // Windows Phone must come first because its UA also contains "Android" 55 if (/windows phone/i.test(userAgent)) { 56 return "Windows Phone"; 57 } 58 59 if (/android/i.test(userAgent)) { 60 return "Android"; 61 } 62 63 // iOS detection from: http://stackoverflow.com/a/9039885/177710 64 if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) { 65 return "iOS"; 66 } 67 68 return "unknown"; 69 } 70 71 window.playErrorSound = () => { 72 new Howl({ 73 src: ['error.wav'], 74 autoplay: true, 75 html5: true, 76 }); 77 } 78 79 window.onAndroidBridgeJobCompleted = (sessionId, result) => { 80 DotNet.invokeMethodAsync("Music.Web", "onAndroidBridgeJobCompleted", sessionId, result); 81 } 82 83 window.initYtPlayer = () => { 84 var found = document.getElementById("youtube-iframe-api"); 85 if (found) { 86 found.remove(); 87 } 88 89 var tag = document.createElement('script'); 90 tag.setAttribute("id", "youtube-iframe-api"); 91 tag.src = "https://www.youtube.com/iframe_api"; 92 var firstScriptTag = document.getElementsByTagName('script')[0]; 93 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 94 } 95 96 // https://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-mobile-device 97 window.isMobile = () => { 98 // Both phone portrait and landscape. 99 return window.matchMedia('only screen and (max-width: 767.98px)').matches; 100 } 101 102 // https://stackoverflow.com/questions/7852986/javascript-scroll-to-nth-row-in-a-table 103 window.scrollToRow = (row) => { 104 var rows = document.querySelectorAll('#mainTable tr'); 105 var r = rows[row]; 106 if (r) { 107 var rect = r.getBoundingClientRect(); 108 if (rect.top < 0 || rect.bottom > window.innerHeight) { 109 r.scrollIntoView({ block: 'center' }); 110 } 111 } 112 } 113 114 // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share 115 window.shareWebApi = (title, text, url) => { 116 if (navigator.share) { 117 navigator.share({ 118 title: title, 119 text: text, 120 url: url, 121 }); 122 return true; 123 } 124 else { 125 return false; 126 } 127 } 128 129 window.showDropdown = () => { 130 $('#staticDropdown').dropdown('toggle'); 131 } 132 133 window.launchModal = (sessionId) => { 134 // make sure to use one() not on() since we want to run once. 135 // https://www.w3schools.com/jquery/event_on.asp 136 $('#staticBackdrop').one('hidden.bs.modal', function (e) { 137 DotNet.invokeMethodAsync("Music.Web", "onModalHidden", sessionId); 138 }); 139 140 $('#staticBackdrop').one('shown.bs.modal', function () { 141 DotNet.invokeMethodAsync("Music.Web", "onModalShown", sessionId); 142 143 if (document.getElementById('recipient-name')) { 144 $('#recipient-name').trigger('select'); 145 $('#recipient-name').trigger('focus'); // optional 146 } 147 }); 148 149 $('#staticBackdrop').modal(); 150 } 151 152 window.hideModal = () => { 153 $('#staticBackdrop').modal('hide'); 154 } 155 156 window.showToast = (sessionId) => { 157 // workaround for bug: toast timer doesn't start if next one is shown too quick. 158 // https://github.com/twbs/bootstrap/issues/28164 159 $('#mainToast').toast('dispose'); 160 161 $('#mainToast').one('hidden.bs.toast', function () { 162 DotNet.invokeMethodAsync("Music.Web", "onToastHidden", sessionId); 163 }); 164 165 $('#mainToast').toast('show'); 166 } 167 168 window.hideToast = () => { 169 $('#mainToast').toast('hide'); 170 } 171 172 window.hasAndroidBridge = () => { 173 if (window.AndroidBridge) { 174 return true; 175 } else { 176 return false; 177 } 178 } 179 180 var load_end = false; 181 var startTime = performance.now(); 182 183 function getLogInfo() { return window.isMobile() + "/" + window.hasAndroidBridge() + "/" + window.getMobileOperatingSystem(); } 184 function getElapsedSeconds() {
185 var elapsed = performance.now() - startTime; // in ms 186 return Math.round(elapsed / 1000); 187 } 188 189 gtag('event', 'load_start', { 'mobile/bridge/os': getLogInfo() }); 190 191 window.setLocalizedStrings = (appName, reloadErrorText, reloadErrorbutton) => { 192 load_end = true; 193 gtag('event', 'load_end', { 'elapsed': getElapsedSeconds() }); 194 195 document.getElementById("page-title").innerHTML = appName; 196 document.getElementById("reload-error-text").innerHTML = reloadErrorText; 197 document.getElementById("reload-error-button").innerHTML = reloadErrorbutton; 198 } 199 200 window.onUnhandledException = () => { 201 if (load_end) { 202 gtag('event', 'reload_end', { 'mobile/bridge': getLogInfo() }); 203 } else { 204 gtag('event', 'reload_start', { 'mobile/bridge': getLogInfo() }); 205 } 206 207 if (window.AndroidBridge) { 208 window.AndroidBridge.reload(); 209 } else { 210 window.location.reload(); 211 } 212 213 // If onclick returns false the default browser behaviour is cancelled. 214 return false; 215 } 216 217 window.onPlayStoreClick = () => { 218 if (window.AndroidBridge) { 219 gtag('event', 'install_prompt', { 'elapsed': getElapsedSeconds() }); 220 window.AndroidBridge.showInstallPrompt(); 221 } else { 222 gtag('event', 'play_store', { 'elapsed': getElapsedSeconds() }); 223 window.open("https://play.google.com/store/apps/details?id=www.whimmusic.info", "_blank"); 224 } 225 226 // If onclick returns false the default browser behaviour is cancelled. 227 return false; 228 } 229 </script>
229 230 231
231<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.1/howler.core.min.js" integrity="sha512-wzeZyTAYqFv+VKD/mGwXREXBIzy4pE3E617SBskkLFuYcPQgX6px2Il3gwZwXb9DuyjYPIsbTEO/6c3+mUvoPA==" crossorigin="anonymous"></script>
231 232
232<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
232 233
233<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
233 234</body> 235 236</html>
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.