|
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 |
|
17 | | -const color = document.getElementById('color') as HTMLInputElement; |
18 | | -const lucky = document.getElementById('lucky') as HTMLInputElement; |
| 17 | +import tinycolor from 'tinycolor2'; |
| 18 | + |
| 19 | +const colorInput = document.getElementById('color') as HTMLInputElement; |
| 20 | +const luckyInput = document.getElementById('lucky') as HTMLInputElement; |
19 | 21 | const cf = document.getElementById('cf') as ControlledFrame; |
20 | | -const controls = document.getElementById('controls') as HTMLFormElement; |
21 | | - |
22 | | -controls.addEventListener('submit', (e) => { |
23 | | - e.preventDefault(); |
24 | | -}); |
25 | | - |
26 | | -color.addEventListener('change', () => { |
27 | | - const c = color.value; |
28 | | - const css = `body { background: ${c} !important; }`; |
29 | | - console.log(css); |
30 | | - cf.insertCSS({ |
31 | | - code: css, |
32 | | - }); |
33 | | -}); |
34 | | - |
35 | | -lucky.addEventListener('change', () => { |
36 | | - cf.executeScript({ |
37 | | - code: ` |
38 | | - document.querySelector(\`[aria-label="I'm Feeling Lucky"][role="button"]\`).value = "I'm Feeling ${lucky.value}"; |
39 | | - `, |
40 | | - }); |
41 | | -}); |
| 22 | +const controlsForm = document.getElementById('controls') as HTMLFormElement; |
| 23 | + |
| 24 | +/** |
| 25 | + * Updates the background color of the controlled frame. |
| 26 | + * @param color The CSS color value. |
| 27 | + */ |
| 28 | +function updateControlledFrameBackgroundColor(color: string) { |
| 29 | + const css = `body { background: ${color} !important; }`; |
| 30 | + console.log(`Updating color to: ${color}`); |
| 31 | + cf.insertCSS({ code: css }); |
| 32 | +} |
| 33 | + |
| 34 | +/** |
| 35 | + * Updates the text of the "lucky" button inside the controlled frame. |
| 36 | + * @param text The new text to display. |
| 37 | + */ |
| 38 | +function updateControlledFrameLuckyButtonText(text: string) { |
| 39 | + console.log(`Updating text to: "I'm Feeling ${text}"`); |
| 40 | + // Selects both English and Dutch buttons in a single query. |
| 41 | + // The selector string uses backticks to avoid issues with single and double quotes. |
| 42 | + const script = ` |
| 43 | + document.querySelectorAll(\`[aria-label="I'm Feeling Lucky"], [aria-label="Ik doe een gok"]\`).forEach(button => { |
| 44 | + button.value = "I'm Feeling ${text}"; |
| 45 | + }); |
| 46 | + `; |
| 47 | + cf.executeScript({ code: script }); |
| 48 | +} |
| 49 | + |
| 50 | +/** |
| 51 | + * Handles incoming launch parameters from the launch queue. |
| 52 | + * @param launchParams The launch parameters provided by the system. |
| 53 | + */ |
| 54 | +function handleLaunch(launchParams: LaunchParams) { |
| 55 | + if (!launchParams.targetURL) { |
| 56 | + return; |
| 57 | + } |
| 58 | + console.log(`Received launch with targetURL: ${launchParams.targetURL}`); |
| 59 | + |
| 60 | + // The targetURL contains a 'params' query parameter, which is itself a URL. |
| 61 | + // We need to parse this nested URL to get the actual values. |
| 62 | + const outerParams = new URL(launchParams.targetURL).searchParams; |
| 63 | + const innerUrlString = outerParams.get('params'); |
| 64 | + |
| 65 | + if (!innerUrlString) { |
| 66 | + console.warn("No 'params' found in launch URL."); |
| 67 | + return; |
| 68 | + } |
| 69 | + |
| 70 | + try { |
| 71 | + const innerParams = new URL(innerUrlString).searchParams; |
| 72 | + const textParam = innerParams.get('text'); |
| 73 | + const colorParam = innerParams.get('color'); |
| 74 | + |
| 75 | + let parsedColor = null; |
| 76 | + if (colorParam) { |
| 77 | + const realColor = tinycolor(colorParam); |
| 78 | + if (!realColor.isValid()) { |
| 79 | + throw new Error(`${colorParam} does not name a valid color`); |
| 80 | + } |
| 81 | + parsedColor = realColor.toHexString(); |
| 82 | + colorInput.value = parsedColor; |
| 83 | + } |
| 84 | + |
| 85 | + if (textParam) { |
| 86 | + luckyInput.value = textParam; |
| 87 | + } |
| 88 | + |
| 89 | + // Wait for the controlled frame to finish loading before applying changes. |
| 90 | + cf.onloadstop = () => { |
| 91 | + if (textParam) { |
| 92 | + updateControlledFrameLuckyButtonText(textParam); |
| 93 | + } |
| 94 | + if (parsedColor) { |
| 95 | + updateControlledFrameBackgroundColor(parsedColor); |
| 96 | + } |
| 97 | + }; |
| 98 | + } catch (error) { |
| 99 | + console.error("Failed to parse inner URL from 'params':", error); |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +controlsForm.addEventListener('submit', (e) => e.preventDefault()); |
| 104 | + |
| 105 | +colorInput.addEventListener('change', () => |
| 106 | + updateControlledFrameBackgroundColor(colorInput.value), |
| 107 | +); |
| 108 | +luckyInput.addEventListener('change', () => |
| 109 | + updateControlledFrameLuckyButtonText(luckyInput.value), |
| 110 | +); |
| 111 | + |
| 112 | +// Set up the launch queue consumer to handle protocol-launched events. |
| 113 | +window.launchQueue.setConsumer(handleLaunch); |
0 commit comments