Add mobile warning message + secure context check.

#4
Files changed (3) hide show
  1. index.html +28 -17
  2. script.js +30 -3
  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
- <h1 class="google-sans-medium">Emoji generator</h1>
24
- <p class="text-cta">Translate text to fun combinations of emoji with your own Gemma model ✨</p>
25
- <div class="input-container">
26
- <input type="text" id="prompt-input" aria-label="Type any phrase and get suggestions" placeholder="Type any phrase and get suggestions">
27
- <button disabled type="submit" id="generate-btn" aria-label="Generate emojis">
28
- <svg class="arrow" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16">
29
- <path d="M.59 14.59 2 16l8-8-8-8L.59 1.41 7.17 8" fill="#fff" />
30
- </svg>
31
- <svg class="loader" width="18" height="18" viewBox="0 0 18 18" fill="none"
32
- xmlns="http://www.w3.org/2000/svg">
33
- <circle cx="9" cy="9" r="8" stroke="white" stroke-width="2" />
34
- </svg>
35
- </button>
 
 
 
 
 
 
36
  </div>
37
- <div class="output-container">
38
- <div id="response-output" class="response-box"></div>
39
- <div id="status-message">Loading model...</div>
 
 
 
 
 
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
- statusMessageContainer.innerHTML = `
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="f; color: #286aac">WebGPU Implementation Status</a>.
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
- await initializeModelInWorker();
 
 
 
 
 
 
 
 
 
 
 
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
  }