|
57 | 57 |
|
58 | 58 | </body> |
59 | 59 |
|
60 | | -<script type="module"> |
61 | | - if (!window.WebAssembly) { |
62 | | - alert("WebAssembly is not supported in your browser. Please use a modern browser."); |
63 | | - } |
64 | | - |
65 | | - const secretInput = document.getElementById('secretInput'); |
66 | | - const fileInput = document.getElementById('fileInput'); |
67 | | - const limitMaxSideInput = document.getElementById('limitMaxSide'); |
68 | | - const maxSideInput = document.getElementById('maxSide'); |
69 | | - const inputImgDiv = document.getElementById('inputImg'); |
70 | | - const outputDiv = document.getElementById('output'); |
71 | | - const hintLabel = document.getElementById('hint'); |
72 | | - const encodeButton = document.getElementById('encodeButton'); |
73 | | - const decodeButton = document.getElementById('decodeButton'); |
74 | | - const downloadBtnContainer = document.getElementById('downloadBtnContainer'); |
75 | | - const downloadBtn = document.getElementById('downloadBtn'); |
76 | | - const errorDiv = document.getElementById('error'); |
77 | | - const worker = new Worker('./worker.js', { type: 'module' }); |
78 | | - |
79 | | - const urlParams = new URLSearchParams(window.location.search); |
80 | | - const secretFromUrl = urlParams.get('secret') || urlParams.get('s'); |
81 | | - if (secretFromUrl) { |
82 | | - secretInput.value = decodeURIComponent(secretFromUrl); |
83 | | - } |
84 | | - |
85 | | - async function getInputBlob() { |
86 | | - const file = fileInput.files[0]; |
87 | | - const arrayBuffer = await file.arrayBuffer(); |
88 | | - return new Uint8Array(arrayBuffer); |
89 | | - } |
90 | | - |
91 | | - function checkInput() { |
92 | | - if (fileInput.files.length === 0) { |
93 | | - showError("No image file selected"); |
94 | | - throw new Error("No image file selected"); |
95 | | - } |
96 | | - if (secretInput.value.trim() === '') { |
97 | | - showError("Secret cannot be empty"); |
98 | | - throw new Error("Secret cannot be empty"); |
99 | | - } |
100 | | - } |
101 | | - |
102 | | - async function showError(msg) { |
103 | | - errorDiv.textContent = msg; |
104 | | - errorDiv.style.display = 'block'; |
105 | | - console.error(msg); |
106 | | - } |
107 | | - |
108 | | - function resetOutput() { |
109 | | - inputImgDiv.innerHTML = ''; |
110 | | - outputDiv.innerHTML = ''; |
111 | | - errorDiv.textContent = ''; |
112 | | - errorDiv.style.display = 'none'; |
113 | | - downloadBtnContainer.style.display = 'none'; |
114 | | - hintLabel.textContent = 'Enter a secret and select an image file to encode / decode'; |
115 | | - } |
116 | | - |
117 | | - async function showImage(imBlob) { |
118 | | - resetOutput(); |
119 | | - hintLabel.textContent = ''; |
120 | | - const blob = new Blob([imBlob], { type: 'image/png' }); |
121 | | - const url = URL.createObjectURL(blob); |
122 | | - |
123 | | - const imgElem = document.createElement('img'); |
124 | | - imgElem.src = url; |
125 | | - imgElem.alt = 'Image'; |
126 | | - outputDiv.appendChild(imgElem); |
127 | | - |
128 | | - downloadBtnContainer.style.display = 'block'; |
129 | | - downloadBtn.onclick = () => { |
130 | | - const a = document.createElement('a'); |
131 | | - a.href = url; |
132 | | - const timeName = new Date().toISOString().replace(/[:.]/g, '-'); |
133 | | - a.download = `img-${timeName}.png`; |
134 | | - document.body.appendChild(a); |
135 | | - a.click(); |
136 | | - document.body.removeChild(a); |
137 | | - }; |
138 | | - } |
139 | | - |
140 | | - async function encode_image() { |
141 | | - checkInput(); |
142 | | - resetOutput(); |
143 | | - const inputBlob = await getInputBlob(); |
144 | | - hintLabel.textContent = `Encoding...`; |
145 | | - worker.postMessage({ |
146 | | - type: 'encode', |
147 | | - buffer: inputBlob, |
148 | | - secret: secretInput.value, |
149 | | - maxSide: limitMaxSideInput.checked ? parseInt(maxSideInput.value) : -1 |
150 | | - }); |
151 | | - } |
152 | | - |
153 | | - async function decode_image() { |
154 | | - checkInput(); |
155 | | - resetOutput(); |
156 | | - const inputBlob = await getInputBlob(); |
157 | | - hintLabel.textContent = `Decoding...`; |
158 | | - worker.postMessage({ |
159 | | - type: 'decode', |
160 | | - buffer: inputBlob, |
161 | | - secret: secretInput.value, |
162 | | - maxSide: limitMaxSideInput.checked ? parseInt(maxSideInput.value) : -1 |
163 | | - }); |
164 | | - } |
165 | | - |
166 | | - worker.onmessage = async (event) => { |
167 | | - if (event.data.error) { |
168 | | - await showError(`Error decoding: ${event.data.error}`); |
169 | | - console.error(event.data.error); |
170 | | - return; |
171 | | - } |
172 | | - await showImage(event.data.buffer); |
173 | | - }; |
174 | | - |
175 | | - encodeButton.addEventListener('click', encode_image); |
176 | | - decodeButton.addEventListener('click', decode_image); |
177 | | - fileInput.addEventListener('change', ()=>{ |
178 | | - resetOutput(); |
179 | | - hintLabel.textContent += ' (Below is the selected image)'; |
180 | | - const file = fileInput.files[0]; |
181 | | - if (file) { |
182 | | - const imgElem = document.createElement('img'); |
183 | | - imgElem.src = URL.createObjectURL(file); |
184 | | - imgElem.alt = 'Selected Image'; |
185 | | - inputImgDiv.innerHTML = ''; |
186 | | - inputImgDiv.appendChild(imgElem); |
187 | | - } |
188 | | - }); |
189 | | - |
190 | | - // handle drag and drop |
191 | | - { |
192 | | - const dropZone = document.getElementById('drop-zone'); |
193 | | - let inDrag = false; |
194 | | - let taskId = null; |
195 | | - function hideDropZone() { |
196 | | - if (inDrag) return; |
197 | | - dropZone.style.display = 'none'; |
198 | | - } |
199 | | - window.addEventListener('dragover', (event) => { |
200 | | - event.preventDefault(); |
201 | | - dropZone.style.display = 'block'; |
202 | | - inDrag = true; |
203 | | - if (taskId) { window.clearTimeout(taskId); } |
204 | | - taskId = window.setTimeout(hideDropZone, 100); |
205 | | - }); |
206 | | - window.addEventListener('dragmove', (event) => { |
207 | | - event.preventDefault(); |
208 | | - dropZone.style.display = 'block'; |
209 | | - inDrag = true; |
210 | | - if (taskId) { window.clearTimeout(taskId); } |
211 | | - taskId = window.setTimeout(hideDropZone, 100); |
212 | | - }); |
213 | | - window.addEventListener('dragleave', (event) => { |
214 | | - event.preventDefault(); |
215 | | - inDrag = false; |
216 | | - if (taskId) { window.clearTimeout(taskId); } |
217 | | - taskId = window.setTimeout(hideDropZone, 100); |
218 | | - }); |
219 | | - dropZone.addEventListener('drop', (event) => { |
220 | | - event.preventDefault(); |
221 | | - if (event.dataTransfer.files.length > 0) { |
222 | | - fileInput.files = event.dataTransfer.files; |
223 | | - fileInput.dispatchEvent(new Event('change')); |
224 | | - } |
225 | | - inDrag = false; |
226 | | - dropZone.style.display = 'none'; |
227 | | - }); |
228 | | - } |
229 | | - |
230 | | -</script> |
| 60 | +<script src="./script.js" type="module"></script> |
231 | 61 | </html> |
0 commit comments