Spaces:
Running
Running
Add mobile warning message + secure context check.
#4
by
MoosHM
- opened
- index.html +28 -17
- script.js +30 -3
- style.css +54 -1
index.html
CHANGED
|
@@ -20,23 +20,34 @@
|
|
| 20 |
<div class="background-blob-3"></div>
|
| 21 |
</div>
|
| 22 |
<div class="container">
|
| 23 |
-
<
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
<
|
| 27 |
-
|
| 28 |
-
<
|
| 29 |
-
<
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
</div>
|
| 37 |
-
<div
|
| 38 |
-
<
|
| 39 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
</div>
|
| 41 |
</div>
|
| 42 |
<div class="footer">
|
|
@@ -49,4 +60,4 @@
|
|
| 49 |
<script type="module" src="script.js"></script>
|
| 50 |
</body>
|
| 51 |
|
| 52 |
-
</html>
|
|
|
|
| 20 |
<div class="background-blob-3"></div>
|
| 21 |
</div>
|
| 22 |
<div class="container">
|
| 23 |
+
<div id="main-container">
|
| 24 |
+
<h1 class="google-sans-medium">Emoji generator</h1>
|
| 25 |
+
<p class="text-cta">Translate text to fun combinations of emoji with your own Gemma model ✨</p>
|
| 26 |
+
<div class="input-container">
|
| 27 |
+
<input type="text" id="prompt-input" aria-label="Type any phrase and get suggestions" placeholder="Type any phrase and get suggestions">
|
| 28 |
+
<button disabled type="submit" id="generate-btn" aria-label="Generate emojis">
|
| 29 |
+
<svg class="arrow" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16">
|
| 30 |
+
<path d="M.59 14.59 2 16l8-8-8-8L.59 1.41 7.17 8" fill="#fff" />
|
| 31 |
+
</svg>
|
| 32 |
+
<svg class="loader" width="18" height="18" viewBox="0 0 18 18" fill="none"
|
| 33 |
+
xmlns="http://www.w3.org/2000/svg">
|
| 34 |
+
<circle cx="9" cy="9" r="8" stroke="white" stroke-width="2" />
|
| 35 |
+
</svg>
|
| 36 |
+
</button>
|
| 37 |
+
</div>
|
| 38 |
+
<div class="output-container">
|
| 39 |
+
<div id="response-output" class="response-box"></div>
|
| 40 |
+
<div id="status-message">Loading model...</div>
|
| 41 |
+
</div>
|
| 42 |
</div>
|
| 43 |
+
<div id="warning-message-mobile" style="display: none;">
|
| 44 |
+
<h3 class="google-sans-medium">Emoji generator</h3>
|
| 45 |
+
<p class="warning-message-cta">This demo may not
|
| 46 |
+
load correctly on
|
| 47 |
+
mobile devices.</p>
|
| 48 |
+
<p class="warning-message-cta-alt">Please open it on desktop 💻</p>
|
| 49 |
+
<p class="warning-message-cta-alt">or</p>
|
| 50 |
+
<a class="warning-message-cta-alt" id="proceed-anyway-btn">proceed anyway.</a>
|
| 51 |
</div>
|
| 52 |
</div>
|
| 53 |
<div class="footer">
|
|
|
|
| 60 |
<script type="module" src="script.js"></script>
|
| 61 |
</body>
|
| 62 |
|
| 63 |
+
</html>
|
script.js
CHANGED
|
@@ -3,6 +3,8 @@ const generateBtn = document.getElementById("generate-btn");
|
|
| 3 |
const promptInput = document.getElementById("prompt-input");
|
| 4 |
const responseOutput = document.getElementById("response-output");
|
| 5 |
const statusMessageContainer = document.getElementById("status-message");
|
|
|
|
|
|
|
| 6 |
|
| 7 |
const workerPath = './worker.js';
|
| 8 |
let worker;
|
|
@@ -26,11 +28,20 @@ function createEmojiButton(result) {
|
|
| 26 |
// Check for WebGPU availability and displays an error message if it's not available
|
| 27 |
function checkWebGPU() {
|
| 28 |
if (!navigator.gpu) {
|
| 29 |
-
|
| 30 |
This application requires WebGPU to run the model in your browser.
|
| 31 |
Please update your browser to enable WebGPU support, try a different browser (like Chrome or Edge, version 113+), or ensure your GPU drivers are up to date.</br></br>
|
| 32 |
-
For more details, read the <a href="https://github.com/gpuweb/gpuweb/wiki/Implementation-Status" target="_blank" style="
|
| 33 |
`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
generateBtn.disabled = true;
|
| 35 |
return false;
|
| 36 |
}
|
|
@@ -72,6 +83,7 @@ async function initializeModelInWorker() {
|
|
| 72 |
generateBtn.disabled = false; // Enable the generation button upon model load
|
| 73 |
setTimeout(() => {
|
| 74 |
statusMessageContainer.innerHTML = ``; // Then empty status message
|
|
|
|
| 75 |
}, 500);
|
| 76 |
break;
|
| 77 |
|
|
@@ -121,6 +133,10 @@ function responseComplete() {
|
|
| 121 |
}
|
| 122 |
}
|
| 123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
function resetUI() {
|
| 125 |
console.log("[UI] Resetting UI state.");
|
| 126 |
generateBtn.classList.add('generating');
|
|
@@ -154,7 +170,18 @@ async function generateResponse() {
|
|
| 154 |
async function initializeAndAttachListeners() {
|
| 155 |
console.log("[UI] Starting initialization and attaching listeners.");
|
| 156 |
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
generateBtn.addEventListener("click", generateResponse);
|
| 160 |
|
|
|
|
| 3 |
const promptInput = document.getElementById("prompt-input");
|
| 4 |
const responseOutput = document.getElementById("response-output");
|
| 5 |
const statusMessageContainer = document.getElementById("status-message");
|
| 6 |
+
const warningMessageContainerForMobile = document.getElementById("warning-message-mobile");
|
| 7 |
+
const mainContainer = document.getElementById("main-container");
|
| 8 |
|
| 9 |
const workerPath = './worker.js';
|
| 10 |
let worker;
|
|
|
|
| 28 |
// Check for WebGPU availability and displays an error message if it's not available
|
| 29 |
function checkWebGPU() {
|
| 30 |
if (!navigator.gpu) {
|
| 31 |
+
let message = `
|
| 32 |
This application requires WebGPU to run the model in your browser.
|
| 33 |
Please update your browser to enable WebGPU support, try a different browser (like Chrome or Edge, version 113+), or ensure your GPU drivers are up to date.</br></br>
|
| 34 |
+
For more details, read the <a href="https://github.com/gpuweb/gpuweb/wiki/Implementation-Status" target="_blank" style="color: #286aac">WebGPU Implementation Status</a>.
|
| 35 |
`;
|
| 36 |
+
|
| 37 |
+
if (!window.isSecureContext) {
|
| 38 |
+
message += `
|
| 39 |
+
<br/><br/>
|
| 40 |
+
<strong>Note:</strong> WebGPU requires a secure context. Please access this page over HTTPS or from 'localhost'. Accessing a local server via its IP address also requires an HTTPS setup in many instances (e.g. iOS26 Safari).
|
| 41 |
+
`;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
statusMessageContainer.innerHTML = message;
|
| 45 |
generateBtn.disabled = true;
|
| 46 |
return false;
|
| 47 |
}
|
|
|
|
| 83 |
generateBtn.disabled = false; // Enable the generation button upon model load
|
| 84 |
setTimeout(() => {
|
| 85 |
statusMessageContainer.innerHTML = ``; // Then empty status message
|
| 86 |
+
warningMessageContainerForMobile.innerHTML = ``; // Then empty warning message
|
| 87 |
}, 500);
|
| 88 |
break;
|
| 89 |
|
|
|
|
| 133 |
}
|
| 134 |
}
|
| 135 |
|
| 136 |
+
function isMobile() {
|
| 137 |
+
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
function resetUI() {
|
| 141 |
console.log("[UI] Resetting UI state.");
|
| 142 |
generateBtn.classList.add('generating');
|
|
|
|
| 170 |
async function initializeAndAttachListeners() {
|
| 171 |
console.log("[UI] Starting initialization and attaching listeners.");
|
| 172 |
|
| 173 |
+
if (isMobile()) {
|
| 174 |
+
mainContainer.style.display = 'none';
|
| 175 |
+
warningMessageContainerForMobile.style.display = '';
|
| 176 |
+
const proceedButton = document.getElementById('proceed-anyway-btn');
|
| 177 |
+
proceedButton.addEventListener('click', async () => {
|
| 178 |
+
mainContainer.style.display = '';
|
| 179 |
+
warningMessageContainerForMobile.style.display = 'none';
|
| 180 |
+
await initializeModelInWorker();
|
| 181 |
+
});
|
| 182 |
+
} else {
|
| 183 |
+
await initializeModelInWorker();
|
| 184 |
+
}
|
| 185 |
|
| 186 |
generateBtn.addEventListener("click", generateResponse);
|
| 187 |
|
style.css
CHANGED
|
@@ -72,6 +72,15 @@ body,html {
|
|
| 72 |
margin: auto 0;
|
| 73 |
}
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
h1 {
|
| 76 |
margin-top: 0;
|
| 77 |
font-size: 51px;
|
|
@@ -174,7 +183,7 @@ h2 {
|
|
| 174 |
transform: scale(1);
|
| 175 |
}
|
| 176 |
}
|
| 177 |
-
#status-message {
|
| 178 |
text-align: center;
|
| 179 |
}
|
| 180 |
/* Button styles for the generate button */
|
|
@@ -418,4 +427,48 @@ p {
|
|
| 418 |
font-size: 24px;
|
| 419 |
}
|
| 420 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
}
|
|
|
|
| 72 |
margin: auto 0;
|
| 73 |
}
|
| 74 |
|
| 75 |
+
#main-container {
|
| 76 |
+
display: flex;
|
| 77 |
+
flex-direction: column;
|
| 78 |
+
align-items: center;
|
| 79 |
+
justify-content: center;
|
| 80 |
+
width: 100%;
|
| 81 |
+
box-sizing: border-box;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
h1 {
|
| 85 |
margin-top: 0;
|
| 86 |
font-size: 51px;
|
|
|
|
| 183 |
transform: scale(1);
|
| 184 |
}
|
| 185 |
}
|
| 186 |
+
#status-message, #warning-message {
|
| 187 |
text-align: center;
|
| 188 |
}
|
| 189 |
/* Button styles for the generate button */
|
|
|
|
| 427 |
font-size: 24px;
|
| 428 |
}
|
| 429 |
}
|
| 430 |
+
|
| 431 |
+
#warning-message-mobile {
|
| 432 |
+
display: flex;
|
| 433 |
+
flex-direction: column;
|
| 434 |
+
align-items: center;
|
| 435 |
+
justify-content: center;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
#warning-message-mobile h3 {
|
| 439 |
+
font-family: 'Google Sans';
|
| 440 |
+
font-style: normal;
|
| 441 |
+
font-weight: 500;
|
| 442 |
+
font-size: 24px;
|
| 443 |
+
line-height: 100%;
|
| 444 |
+
text-align: center;
|
| 445 |
+
letter-spacing: -1.30014px;
|
| 446 |
+
color: #1064D3;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
#warning-message-mobile .warning-message-cta {
|
| 450 |
+
font-family: 'Google Sans';
|
| 451 |
+
font-style: normal;
|
| 452 |
+
font-weight: 500;
|
| 453 |
+
font-size: 32px;
|
| 454 |
+
line-height: 100%;
|
| 455 |
+
text-align: center;
|
| 456 |
+
letter-spacing: -1.30014px;
|
| 457 |
+
color: #000000;
|
| 458 |
+
margin-top: 6px;
|
| 459 |
+
max-width: 320px;
|
| 460 |
+
margin-bottom: 50px;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
#warning-message-mobile .warning-message-cta-alt {
|
| 464 |
+
font-family: 'Google Sans';
|
| 465 |
+
font-style: normal;
|
| 466 |
+
font-weight: 400;
|
| 467 |
+
font-size: 16px;
|
| 468 |
+
line-height: 140%;
|
| 469 |
+
text-align: center;
|
| 470 |
+
color: #327AC3;
|
| 471 |
+
}
|
| 472 |
+
a.warning-message-cta-alt {
|
| 473 |
+
text-decoration: underline;
|
| 474 |
}
|