Size
12.4 KB
Version
1.0.1
Created
Dec 16, 2025
Updated
about 2 months ago
1// ==UserScript==
2// @name Blockaid Monitors Wizard
3// @description Interactive wizard to guide users to the Monitors tab
4// @version 1.0.1
5// @match https://*.app.blockaid.io/*
6// @icon https://app.blockaid.io/blockaid_favicon.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // Wizard state management
12 let wizardActive = false;
13
14 // Create wizard overlay
15 function createWizardOverlay() {
16 const overlay = document.createElement('div');
17 overlay.id = 'blockaid-wizard-overlay';
18 overlay.style.cssText = `
19 position: fixed;
20 top: 0;
21 left: 0;
22 width: 100%;
23 height: 100%;
24 background: rgba(0, 0, 0, 0.7);
25 z-index: 999999;
26 display: flex;
27 align-items: center;
28 justify-content: center;
29 `;
30 return overlay;
31 }
32
33 // Create tooltip pointing to monitors tab
34 function createTooltip() {
35 const tooltip = document.createElement('div');
36 tooltip.id = 'blockaid-wizard-tooltip';
37 tooltip.style.cssText = `
38 position: fixed;
39 background: white;
40 border-radius: 12px;
41 padding: 24px;
42 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
43 z-index: 1000000;
44 max-width: 350px;
45 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
46 `;
47
48 tooltip.innerHTML = `
49 <div style="margin-bottom: 16px;">
50 <h2 style="margin: 0 0 12px 0; font-size: 20px; font-weight: 600; color: #1a1a1a;">
51 Welcome to Blockaid! 👋
52 </h2>
53 <p style="margin: 0; font-size: 14px; line-height: 1.6; color: #666;">
54 Let me guide you to the <strong>Monitors</strong> tab where you can manage and view your security monitors.
55 </p>
56 </div>
57 <div style="margin-bottom: 16px; padding: 12px; background: #f0f9ff; border-radius: 8px; border-left: 3px solid #0ea5e9;">
58 <p style="margin: 0; font-size: 13px; color: #0369a1;">
59 <strong>Step 1:</strong> Click on the Monitors icon in the left sidebar
60 </p>
61 </div>
62 <div style="display: flex; gap: 8px; justify-content: flex-end;">
63 <button id="wizard-skip-btn" style="
64 padding: 8px 16px;
65 border: 1px solid #e5e7eb;
66 background: white;
67 border-radius: 6px;
68 cursor: pointer;
69 font-size: 14px;
70 color: #666;
71 transition: all 0.2s;
72 ">Skip</button>
73 <button id="wizard-got-it-btn" style="
74 padding: 8px 16px;
75 border: none;
76 background: #0ea5e9;
77 color: white;
78 border-radius: 6px;
79 cursor: pointer;
80 font-size: 14px;
81 font-weight: 500;
82 transition: all 0.2s;
83 ">Got it!</button>
84 </div>
85 `;
86
87 return tooltip;
88 }
89
90 // Create arrow pointing to monitors tab
91 function createArrow() {
92 const arrow = document.createElement('div');
93 arrow.id = 'blockaid-wizard-arrow';
94 arrow.style.cssText = `
95 position: fixed;
96 width: 0;
97 height: 0;
98 border-top: 15px solid transparent;
99 border-bottom: 15px solid transparent;
100 border-right: 20px solid #0ea5e9;
101 z-index: 1000001;
102 animation: pulse 1.5s ease-in-out infinite;
103 `;
104
105 // Add pulse animation
106 const style = document.createElement('style');
107 style.textContent = `
108 @keyframes pulse {
109 0%, 100% { transform: translateX(0); opacity: 1; }
110 50% { transform: translateX(-10px); opacity: 0.7; }
111 }
112 `;
113 document.head.appendChild(style);
114
115 return arrow;
116 }
117
118 // Create spotlight effect on monitors tab
119 function createSpotlight() {
120 const spotlight = document.createElement('div');
121 spotlight.id = 'blockaid-wizard-spotlight';
122 spotlight.style.cssText = `
123 position: fixed;
124 border: 3px solid #0ea5e9;
125 border-radius: 8px;
126 z-index: 999998;
127 pointer-events: none;
128 box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 20px #0ea5e9;
129 animation: glow 2s ease-in-out infinite;
130 `;
131
132 const style = document.createElement('style');
133 style.textContent = `
134 @keyframes glow {
135 0%, 100% { box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 20px #0ea5e9; }
136 50% { box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 30px #0ea5e9, 0 0 40px #0ea5e9; }
137 }
138 `;
139 document.head.appendChild(style);
140
141 return spotlight;
142 }
143
144 // Position elements relative to monitors tab
145 function positionWizardElements() {
146 const monitorsLink = document.querySelector('a[href="/monitors"]');
147
148 if (!monitorsLink) {
149 console.error('Monitors link not found');
150 return false;
151 }
152
153 const rect = monitorsLink.getBoundingClientRect();
154 const tooltip = document.getElementById('blockaid-wizard-tooltip');
155 const arrow = document.getElementById('blockaid-wizard-arrow');
156 const spotlight = document.getElementById('blockaid-wizard-spotlight');
157
158 if (tooltip && arrow && spotlight) {
159 // Position spotlight on monitors tab
160 spotlight.style.left = `${rect.left - 5}px`;
161 spotlight.style.top = `${rect.top - 5}px`;
162 spotlight.style.width = `${rect.width + 10}px`;
163 spotlight.style.height = `${rect.height + 10}px`;
164
165 // Position tooltip to the right of the sidebar
166 tooltip.style.left = `${rect.right + 60}px`;
167 tooltip.style.top = `${rect.top - 50}px`;
168
169 // Position arrow between tooltip and monitors tab
170 arrow.style.left = `${rect.right + 30}px`;
171 arrow.style.top = `${rect.top + rect.height / 2 - 15}px`;
172 }
173
174 return true;
175 }
176
177 // Start the wizard
178 async function startWizard() {
179 // Check if wizard was already shown
180 const wizardShown = await GM.getValue('blockaid_wizard_shown', false);
181
182 if (wizardShown) {
183 console.log('Wizard already shown, skipping');
184 return;
185 }
186
187 wizardActive = true;
188
189 // Wait for page to be fully loaded
190 setTimeout(() => {
191 const tooltip = createTooltip();
192 const arrow = createArrow();
193 const spotlight = createSpotlight();
194
195 document.body.appendChild(spotlight);
196 document.body.appendChild(arrow);
197 document.body.appendChild(tooltip);
198
199 // Position elements
200 if (!positionWizardElements()) {
201 closeWizard();
202 return;
203 }
204
205 // Reposition on window resize
206 window.addEventListener('resize', positionWizardElements);
207
208 // Add event listeners to buttons
209 document.getElementById('wizard-skip-btn').addEventListener('click', async () => {
210 await GM.setValue('blockaid_wizard_shown', true);
211 closeWizard();
212 });
213
214 document.getElementById('wizard-got-it-btn').addEventListener('click', () => {
215 closeWizard();
216 // Highlight the monitors tab for user to click
217 const monitorsLink = document.querySelector('a[href="/monitors"]');
218 if (monitorsLink) {
219 monitorsLink.style.transition = 'all 0.3s';
220 monitorsLink.style.transform = 'scale(1.1)';
221 setTimeout(() => {
222 monitorsLink.style.transform = 'scale(1)';
223 }, 300);
224 }
225 });
226
227 // Watch for navigation to monitors page
228 const monitorsLink = document.querySelector('a[href="/monitors"]');
229 if (monitorsLink) {
230 monitorsLink.addEventListener('click', async () => {
231 await GM.setValue('blockaid_wizard_shown', true);
232 closeWizard();
233 showSuccessMessage();
234 });
235 }
236
237 console.log('Blockaid Monitors Wizard started');
238 }, 1000);
239 }
240
241 // Close wizard
242 function closeWizard() {
243 wizardActive = false;
244
245 const tooltip = document.getElementById('blockaid-wizard-tooltip');
246 const arrow = document.getElementById('blockaid-wizard-arrow');
247 const spotlight = document.getElementById('blockaid-wizard-spotlight');
248
249 if (tooltip) tooltip.remove();
250 if (arrow) arrow.remove();
251 if (spotlight) spotlight.remove();
252
253 window.removeEventListener('resize', positionWizardElements);
254 }
255
256 // Show success message when user reaches monitors page
257 function showSuccessMessage() {
258 const successMsg = document.createElement('div');
259 successMsg.style.cssText = `
260 position: fixed;
261 top: 20px;
262 right: 20px;
263 background: #10b981;
264 color: white;
265 padding: 16px 24px;
266 border-radius: 8px;
267 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
268 z-index: 1000000;
269 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
270 font-size: 14px;
271 font-weight: 500;
272 animation: slideIn 0.3s ease-out;
273 `;
274 successMsg.textContent = '✓ Great! You\'ve reached the Monitors page';
275
276 const style = document.createElement('style');
277 style.textContent = `
278 @keyframes slideIn {
279 from { transform: translateX(400px); opacity: 0; }
280 to { transform: translateX(0); opacity: 1; }
281 }
282 `;
283 document.head.appendChild(style);
284
285 document.body.appendChild(successMsg);
286
287 setTimeout(() => {
288 successMsg.style.transition = 'all 0.3s';
289 successMsg.style.opacity = '0';
290 successMsg.style.transform = 'translateX(400px)';
291 setTimeout(() => successMsg.remove(), 300);
292 }, 3000);
293 }
294
295 // Add a button to restart wizard (for testing/demo purposes)
296 function addRestartButton() {
297 setTimeout(() => {
298 const restartBtn = document.createElement('button');
299 restartBtn.id = 'restart-wizard-btn';
300 restartBtn.textContent = '🧙 Start Wizard';
301 restartBtn.style.cssText = `
302 position: fixed;
303 bottom: 20px;
304 right: 20px;
305 padding: 12px 20px;
306 background: #8b5cf6;
307 color: white;
308 border: none;
309 border-radius: 8px;
310 cursor: pointer;
311 font-size: 14px;
312 font-weight: 500;
313 box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
314 z-index: 999997;
315 transition: all 0.2s;
316 `;
317
318 restartBtn.addEventListener('mouseenter', () => {
319 restartBtn.style.transform = 'translateY(-2px)';
320 restartBtn.style.boxShadow = '0 6px 16px rgba(139, 92, 246, 0.4)';
321 });
322
323 restartBtn.addEventListener('mouseleave', () => {
324 restartBtn.style.transform = 'translateY(0)';
325 restartBtn.style.boxShadow = '0 4px 12px rgba(139, 92, 246, 0.3)';
326 });
327
328 restartBtn.addEventListener('click', async () => {
329 await GM.setValue('blockaid_wizard_shown', false);
330 location.reload();
331 });
332
333 document.body.appendChild(restartBtn);
334 }, 1500);
335 }
336
337 // Initialize
338 function init() {
339 console.log('Blockaid Monitors Wizard extension loaded');
340
341 // Start wizard when page loads
342 if (document.readyState === 'loading') {
343 document.addEventListener('DOMContentLoaded', () => {
344 startWizard();
345 addRestartButton();
346 });
347 } else {
348 startWizard();
349 addRestartButton();
350 }
351 }
352
353 init();
354})();