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