|
4 | 4 | <meta charset="UTF-8" /> |
5 | 5 | <link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
6 | 6 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
7 | | - <title>OneSignal Dev</title> |
| 7 | + <title>OneSignal Dev — SDK-4180 Safari VAPID Test</title> |
8 | 8 | <style> |
9 | 9 | .in-app-notification { |
10 | 10 | position: fixed; |
|
20 | 20 | animation: slideIn 0.3s ease-out; |
21 | 21 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
22 | 22 | } |
23 | | - .in-app-notification h4 { |
24 | | - margin: 0 0 8px 0; |
25 | | - font-size: 16px; |
| 23 | + * { |
| 24 | + box-sizing: border-box; |
26 | 25 | } |
27 | | - .in-app-notification p { |
28 | | - margin: 0; |
29 | | - font-size: 14px; |
30 | | - opacity: 0.9; |
| 26 | + body { |
| 27 | + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
| 28 | + max-width: 720px; |
| 29 | + margin: 40px auto; |
| 30 | + padding: 0 20px; |
| 31 | + color: #1a1a2e; |
31 | 32 | } |
32 | | - .in-app-notification .close-btn { |
33 | | - position: absolute; |
34 | | - top: 8px; |
35 | | - right: 12px; |
36 | | - background: none; |
37 | | - border: none; |
38 | | - color: white; |
39 | | - font-size: 20px; |
40 | | - cursor: pointer; |
41 | | - opacity: 0.7; |
| 33 | + h1 { |
| 34 | + font-size: 22px; |
| 35 | + margin-bottom: 4px; |
42 | 36 | } |
43 | | - .in-app-notification .close-btn:hover { |
44 | | - opacity: 1; |
| 37 | + .subtitle { |
| 38 | + color: #666; |
| 39 | + margin-bottom: 24px; |
45 | 40 | } |
46 | | - @keyframes slideIn { |
47 | | - from { |
48 | | - transform: translateX(100%); |
49 | | - opacity: 0; |
50 | | - } |
51 | | - to { |
52 | | - transform: translateX(0); |
53 | | - opacity: 1; |
54 | | - } |
| 41 | + .card { |
| 42 | + background: #f8f9fa; |
| 43 | + border: 1px solid #e0e0e0; |
| 44 | + border-radius: 10px; |
| 45 | + padding: 20px; |
| 46 | + margin-bottom: 16px; |
55 | 47 | } |
56 | | - .demo-section { |
57 | | - margin: 20px 0; |
58 | | - padding: 16px; |
59 | | - background: #f5f5f5; |
60 | | - border-radius: 8px; |
61 | | - } |
62 | | - .demo-section h3 { |
| 48 | + .card h3 { |
63 | 49 | margin-top: 0; |
64 | 50 | } |
65 | | - .toggle-btn { |
| 51 | + button { |
66 | 52 | padding: 10px 20px; |
67 | 53 | font-size: 14px; |
68 | 54 | cursor: pointer; |
69 | 55 | border: none; |
70 | 56 | border-radius: 6px; |
71 | | - margin-right: 10px; |
| 57 | + margin-right: 8px; |
| 58 | + margin-bottom: 8px; |
| 59 | + } |
| 60 | + .btn-primary { |
| 61 | + background: #e63946; |
| 62 | + color: white; |
| 63 | + } |
| 64 | + .btn-primary:hover { |
| 65 | + background: #c1121f; |
72 | 66 | } |
73 | | - .toggle-btn.active { |
74 | | - background: #667eea; |
| 67 | + .btn-secondary { |
| 68 | + background: #457b9d; |
75 | 69 | color: white; |
76 | 70 | } |
77 | | - .toggle-btn:not(.active) { |
78 | | - background: #ddd; |
79 | | - color: #333; |
| 71 | + .btn-secondary:hover { |
| 72 | + background: #1d3557; |
| 73 | + } |
| 74 | + #log { |
| 75 | + background: #1a1a2e; |
| 76 | + color: #a8dadc; |
| 77 | + font-family: 'SF Mono', 'Menlo', 'Monaco', monospace; |
| 78 | + font-size: 12px; |
| 79 | + padding: 16px; |
| 80 | + border-radius: 8px; |
| 81 | + max-height: 300px; |
| 82 | + overflow-y: auto; |
| 83 | + white-space: pre-wrap; |
| 84 | + word-break: break-all; |
| 85 | + } |
| 86 | + #log .error { |
| 87 | + color: #e63946; |
| 88 | + } |
| 89 | + #log .success { |
| 90 | + color: #2a9d8f; |
| 91 | + } |
| 92 | + #log .info { |
| 93 | + color: #e9c46a; |
| 94 | + } |
| 95 | + table { |
| 96 | + width: 100%; |
| 97 | + border-collapse: collapse; |
| 98 | + font-size: 14px; |
| 99 | + } |
| 100 | + td { |
| 101 | + padding: 6px 0; |
| 102 | + } |
| 103 | + td:first-child { |
| 104 | + font-weight: 600; |
| 105 | + width: 200px; |
| 106 | + } |
| 107 | + .tag { |
| 108 | + display: inline-block; |
| 109 | + padding: 2px 8px; |
| 110 | + border-radius: 4px; |
| 111 | + font-size: 12px; |
| 112 | + font-weight: 600; |
| 113 | + } |
| 114 | + .tag-legacy { |
| 115 | + background: #ffc9c9; |
| 116 | + color: #c92a2a; |
| 117 | + } |
| 118 | + .tag-vapid { |
| 119 | + background: #b2f2bb; |
| 120 | + color: #2b8a3e; |
| 121 | + } |
| 122 | + .tag-unknown { |
| 123 | + background: #e0e0e0; |
| 124 | + color: #666; |
80 | 125 | } |
81 | 126 | </style> |
82 | 127 | <script> |
|
86 | 131 |
|
87 | 132 | window.OneSignalDeferred = window.OneSignalDeferred || []; |
88 | 133 | OneSignalDeferred.push(async function (OneSignal) { |
89 | | - // for testing consent required |
90 | 134 | OneSignal.Debug.setLogLevel('trace'); |
91 | | - // OneSignal.setConsentRequired(true); |
92 | | - |
93 | | - // for testing, normally this is set on (temporary) in the database client |
94 | 135 | OneSignal._isNewVisitor = true; |
95 | 136 |
|
96 | 137 | OneSignal.init({ |
|
99 | 140 | notifyButton: { |
100 | 141 | enable: true, |
101 | 142 | prenotify: true, |
102 | | - showBadgeAfter: 0, // show immediately instead of waiting 300ms |
| 143 | + showBadgeAfter: 0, |
103 | 144 | }, |
104 | 145 | }); |
105 | | - |
106 | | - // OneSignal.setConsentRequired(true); |
107 | 146 | }); |
108 | 147 | </script> |
109 | 148 | </head> |
110 | 149 | <body> |
| 150 | + <div class="card"> |
| 151 | + <h3>Browser & Safari Push Info</h3> |
| 152 | + <table> |
| 153 | + <tr> |
| 154 | + <td>User Agent</td> |
| 155 | + <td id="ua">—</td> |
| 156 | + </tr> |
| 157 | + <tr> |
| 158 | + <td>window.safari exists</td> |
| 159 | + <td id="safari-exists">—</td> |
| 160 | + </tr> |
| 161 | + <tr> |
| 162 | + <td>Legacy permission state</td> |
| 163 | + <td id="legacy-perm">—</td> |
| 164 | + </tr> |
| 165 | + <tr> |
| 166 | + <td>Legacy deviceToken</td> |
| 167 | + <td id="legacy-token">—</td> |
| 168 | + </tr> |
| 169 | + <tr> |
| 170 | + <td>Notification.permission</td> |
| 171 | + <td id="notif-perm">—</td> |
| 172 | + </tr> |
| 173 | + <tr> |
| 174 | + <td>PushSubscriptionOptions</td> |
| 175 | + <td id="vapid-support">—</td> |
| 176 | + </tr> |
| 177 | + <tr> |
| 178 | + <td>Expected push path</td> |
| 179 | + <td id="push-path">—</td> |
| 180 | + </tr> |
| 181 | + </table> |
| 182 | + </div> |
| 183 | + |
| 184 | + <div class="card"> |
| 185 | + <h3>Actions</h3> |
| 186 | + <button class="btn-primary" id="request-perm">Request Permission</button> |
| 187 | + <button class="btn-secondary" id="refresh-info">Refresh Info</button> |
| 188 | + </div> |
| 189 | + |
| 190 | + <div class="card"> |
| 191 | + <h3>Log</h3> |
| 192 | + <div id="log"></div> |
| 193 | + </div> |
| 194 | + |
111 | 195 | <script type="module" src="/src/entries/pageSdkInit.ts" defer></script> |
112 | | - <!-- <h1>OneSignal Dev</h1> --> |
| 196 | + <script> |
| 197 | + const $ = (id) => document.getElementById(id); |
| 198 | + const log = (msg, cls = '') => { |
| 199 | + const el = $('log'); |
| 200 | + const span = document.createElement('span'); |
| 201 | + if (cls) span.className = cls; |
| 202 | + span.textContent = `[${new Date().toLocaleTimeString()}] ${msg}\n`; |
| 203 | + el.appendChild(span); |
| 204 | + el.scrollTop = el.scrollHeight; |
| 205 | + }; |
| 206 | + |
| 207 | + function refreshInfo() { |
| 208 | + $('ua').textContent = navigator.userAgent; |
| 209 | + |
| 210 | + const hasSafari = |
| 211 | + typeof window.safari !== 'undefined' && |
| 212 | + typeof window.safari.pushNotification !== 'undefined'; |
| 213 | + $('safari-exists').textContent = hasSafari ? 'Yes' : 'No'; |
| 214 | + |
| 215 | + if (hasSafari) { |
| 216 | + try { |
| 217 | + const safariWebId = |
| 218 | + OneSignal?.config?.safariWebId || |
| 219 | + 'web.onesignal.auto.6187ce57-f346-4a86-93e4-7d70d494c000'; |
| 220 | + const perm = window.safari.pushNotification.permission(safariWebId); |
| 221 | + $('legacy-perm').textContent = perm.permission; |
| 222 | + $('legacy-token').textContent = perm.deviceToken || '(null)'; |
| 223 | + |
| 224 | + if (perm.permission === 'granted' && perm.deviceToken) { |
| 225 | + $('push-path').innerHTML = |
| 226 | + '<span class="tag tag-legacy">Legacy Safari Push</span> (existing subscriber)'; |
| 227 | + } else { |
| 228 | + $('push-path').innerHTML = |
| 229 | + '<span class="tag tag-vapid">Standard VAPID Push</span> (new user)'; |
| 230 | + } |
| 231 | + } catch (e) { |
| 232 | + $('legacy-perm').textContent = 'Error: ' + e.message; |
| 233 | + $('legacy-token').textContent = '—'; |
| 234 | + } |
| 235 | + } else { |
| 236 | + $('legacy-perm').textContent = 'N/A (not Safari)'; |
| 237 | + $('legacy-token').textContent = 'N/A'; |
| 238 | + const isVapid = typeof PushSubscriptionOptions !== 'undefined'; |
| 239 | + $('push-path').innerHTML = isVapid |
| 240 | + ? '<span class="tag tag-vapid">Standard VAPID Push</span>' |
| 241 | + : '<span class="tag tag-unknown">Push not supported</span>'; |
| 242 | + } |
| 243 | + |
| 244 | + const vapidSupport = typeof PushSubscriptionOptions !== 'undefined'; |
| 245 | + $('vapid-support').textContent = vapidSupport ? 'Supported' : 'Not available'; |
| 246 | + $('notif-perm').textContent = |
| 247 | + typeof Notification !== 'undefined' ? Notification.permission : 'N/A'; |
| 248 | + } |
| 249 | + |
| 250 | + $('request-perm').addEventListener('click', async () => { |
| 251 | + log('Requesting push permission...', 'info'); |
| 252 | + try { |
| 253 | + await OneSignal.Notifications.requestPermission(); |
| 254 | + log('Permission granted!', 'success'); |
| 255 | + } catch (e) { |
| 256 | + log('Error: ' + e.message, 'error'); |
| 257 | + } |
| 258 | + refreshInfo(); |
| 259 | + }); |
| 260 | + |
| 261 | + $('refresh-info').addEventListener('click', refreshInfo); |
| 262 | + |
| 263 | + window.OneSignalDeferred = window.OneSignalDeferred || []; |
| 264 | + OneSignalDeferred.push(() => { |
| 265 | + log('OneSignal initialized', 'success'); |
| 266 | + refreshInfo(); |
| 267 | + }); |
| 268 | + |
| 269 | + // Initial info on page load |
| 270 | + setTimeout(refreshInfo, 500); |
| 271 | + </script> |
113 | 272 | </body> |
114 | 273 | </html> |
0 commit comments