Skip to content

Commit 99f1957

Browse files
committed
style improve; code orgnize
1 parent fb30c75 commit 99f1957

File tree

6 files changed

+112
-93
lines changed

6 files changed

+112
-93
lines changed

app/index.html

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,26 @@
77
</head>
88

99
<body>
10-
<title>Image encoder</title>
10+
<title>Image chiper</title>
11+
<div class="container">
12+
<h2>Image chiper</h2>
13+
<p>
14+
This app encode your image to pure noise,
15+
only person with the secret can decode it back.
16+
The code runs entirely in your browser,
17+
so your image and secret are always safe and private :)
18+
</p>
19+
</div>
1120

1221
<div id="input-container" class="container">
13-
<label>
14-
Select an image file and enter a secret to encode / decode
15-
</label>
22+
Select an image file and enter a secret to encode / decode.
1623
<div id="secret-container">
1724
<div id="drop-zone" style="display: none;">
1825
<p>Drag and drop an image file here.</p>
1926
<p>Supported formats: PNG, JPEG, BMP, ...</p>
2027
</div>
2128

22-
<input type="file" id="fileInput" accept="image/*" required>
29+
<input type="file" id="fileInput" accept="image/*" capture="environment" required>
2330
<br>
2431
<label for="secretInput">Secret:</label>
2532
<input id="secretInput" placeholder="Enter your secret here" autocomplete="off">
@@ -40,32 +47,27 @@
4047
<select id="imTypeSelect">
4148
<option value="png">PNG</option>
4249
<option value="jpeg">JPEG</option>
43-
</select>
50+
</select>
4451
</div>
4552
</div>
4653
</div>
4754

48-
<div id="output-container" class="container">
49-
<label id="hint"></label>
55+
<div id="output-container" class="container" style="opacity: 0;">
5056
<div id="error"></div>
51-
<div id="warning" style="display: none">
52-
Encode as JPEG will introduce noise to recovered image.
53-
</div>
5457
<div id="inputImg"></div>
5558
<div id="output"></div>
56-
<div id="downloadBtnContainer" style="display: none">
59+
<label id="hint"></label>
60+
<div id="downloadBtn-container" style="display: none">
5761
<button id="downloadBtn">Download Image</button>
5862
</div>
5963
</div>
6064

61-
<div id="footer">
62-
<p style="text-align: center; font-size: 0.75em; color: #666">
63-
The code runs entirely in your browser using WebAssembly.
64-
<br>
65+
<footer id="footer">
66+
<p style="text-align: center; font-size: 0.8rem;">
6567
The source code is available at
6668
<a href="https://github.com/MenxLi/chaotic-enc">menxli/chaotic-enc</a>.
6769
</p>
68-
</div>
70+
</footer>
6971

7072
</body>
7173

app/script.js

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ const outputDiv = document.getElementById('output');
1212
const hintLabel = document.getElementById('hint');
1313
const encodeButton = document.getElementById('encodeButton');
1414
const decodeButton = document.getElementById('decodeButton');
15-
const downloadBtnContainer = document.getElementById('downloadBtnContainer');
1615
const downloadBtn = document.getElementById('downloadBtn');
1716
const errorDiv = document.getElementById('error');
1817
const imTypeSelect = document.getElementById('imTypeSelect');
18+
const downloadBtnContainer = document.getElementById('downloadBtn-container');
19+
const outputContainer = document.getElementById('output-container');
20+
const footer = document.getElementById('footer');
21+
1922
const worker = new Worker('./worker.js', { type: 'module' });
2023

2124
const urlParams = new URLSearchParams(window.location.search);
@@ -42,22 +45,32 @@ function checkInput() {
4245
}
4346

4447
async function showError(msg) {
48+
ensureOutput();
4549
errorDiv.textContent = msg;
4650
errorDiv.style.display = 'block';
4751
console.error(msg);
4852
}
4953

54+
function ensureOutput() {
55+
outputContainer.style.opacity = '1';
56+
footer.style.top = '0';
57+
}
58+
5059
function resetOutput() {
60+
outputContainer.style.opacity = '0';
5161
inputImgDiv.innerHTML = '';
5262
outputDiv.innerHTML = '';
5363
errorDiv.textContent = '';
5464
errorDiv.style.display = 'none';
5565
downloadBtnContainer.style.display = 'none';
5666
hintLabel.textContent = '';
67+
footer.style.top = '-3rem';
5768
}
5869

5970
async function showImage(imBlob) {
6071
resetOutput();
72+
ensureOutput();
73+
6174
hintLabel.textContent = '';
6275
const blob = new Blob([imBlob], { type: 'image/png' });
6376
const url = URL.createObjectURL(blob);
@@ -80,10 +93,13 @@ async function showImage(imBlob) {
8093
}
8194

8295
async function encode_image() {
83-
checkInput();
8496
resetOutput();
97+
checkInput();
98+
8599
const inputBlob = await getInputBlob();
86100
hintLabel.textContent = `Encoding...`;
101+
102+
ensureOutput();
87103
worker.postMessage({
88104
type: 'encode',
89105
buffer: inputBlob,
@@ -94,10 +110,13 @@ async function encode_image() {
94110
}
95111

96112
async function decode_image() {
97-
checkInput();
98113
resetOutput();
114+
checkInput();
115+
99116
const inputBlob = await getInputBlob();
100117
hintLabel.textContent = `Decoding...`;
118+
119+
ensureOutput();
101120
worker.postMessage({
102121
type: 'decode',
103122
buffer: inputBlob,
@@ -116,29 +135,34 @@ worker.onmessage = async (event) => {
116135
await showImage(event.data.buffer);
117136
};
118137

119-
encodeButton.addEventListener('click', encode_image);
120-
decodeButton.addEventListener('click', decode_image);
121-
imTypeSelect.addEventListener('change', () => {
122-
const warningDiv = document.getElementById('warning');
123-
if (imTypeSelect.value === 'jpeg') {
124-
warningDiv.style.display = 'block';
125-
}
126-
else {
127-
warningDiv.style.display = 'none';
128-
}
129-
});
130-
fileInput.addEventListener('change', ()=>{
131-
resetOutput();
132-
hintLabel.textContent += ' (Below is the selected image)';
133-
const file = fileInput.files[0];
134-
if (file) {
135-
const imgElem = document.createElement('img');
136-
imgElem.src = URL.createObjectURL(file);
137-
imgElem.alt = 'Selected Image';
138-
inputImgDiv.innerHTML = '';
139-
inputImgDiv.appendChild(imgElem);
140-
}
141-
});
138+
// Event listeners for inputs
139+
{
140+
encodeButton.addEventListener('click', encode_image);
141+
decodeButton.addEventListener('click', decode_image);
142+
143+
imTypeSelect.addEventListener('change', () => {
144+
if (imTypeSelect.value === 'jpeg') {
145+
encodeButton.disabled = true;
146+
}
147+
else {
148+
encodeButton.disabled = false;
149+
}
150+
});
151+
152+
fileInput.addEventListener('change', ()=>{
153+
resetOutput();
154+
hintLabel.textContent = '(The selected image)';
155+
const file = fileInput.files[0];
156+
if (file) {
157+
ensureOutput();
158+
const imgElem = document.createElement('img');
159+
imgElem.src = URL.createObjectURL(file);
160+
imgElem.alt = 'Selected Image';
161+
inputImgDiv.innerHTML = '';
162+
inputImgDiv.appendChild(imgElem);
163+
}
164+
});
165+
}
142166

143167
// handle drag and drop
144168
{
@@ -149,26 +173,30 @@ fileInput.addEventListener('change', ()=>{
149173
if (inDrag) return;
150174
dropZone.style.display = 'none';
151175
}
176+
152177
window.addEventListener('dragover', (event) => {
153178
event.preventDefault();
154179
dropZone.style.display = 'block';
155180
inDrag = true;
156-
if (taskId) { window.clearTimeout(taskId); }
181+
if (taskId) {window.clearTimeout(taskId); }
157182
taskId = window.setTimeout(hideDropZone, 100);
158183
});
184+
159185
window.addEventListener('dragmove', (event) => {
160186
event.preventDefault();
161187
dropZone.style.display = 'block';
162188
inDrag = true;
163189
if (taskId) { window.clearTimeout(taskId); }
164190
taskId = window.setTimeout(hideDropZone, 100);
165191
});
192+
166193
window.addEventListener('dragleave', (event) => {
167194
event.preventDefault();
168195
inDrag = false;
169196
if (taskId) { window.clearTimeout(taskId); }
170197
taskId = window.setTimeout(hideDropZone, 100);
171198
});
199+
172200
dropZone.addEventListener('drop', (event) => {
173201
event.preventDefault();
174202
if (event.dataTransfer.files.length > 0) {

app/style.css

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
body {
3-
font-family: Arial, sans-serif;
43
padding: 1rem;
54
margin-top: 1.5rem;
65
max-width: 800px;
@@ -47,6 +46,7 @@ div#output-container {
4746
justify-content: center;
4847
background-color: whitesmoke;
4948
gap: 0.25rem;
49+
transition: all 0.2s ease-in-out;
5050
}
5151

5252
div#button-container {
@@ -68,4 +68,17 @@ div#error {
6868
div#warning {
6969
color: orange;
7070
font-weight: bold;
71+
}
72+
73+
footer {
74+
font-family: Arial, sans-serif;
75+
position: relative;
76+
top: -3rem;
77+
78+
display: flex;
79+
flex-direction: column;
80+
justify-content: center;
81+
align-items: center;
82+
font-size: 0.75rem;
83+
color: #666;
7184
}

app/worker.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ await init();
44
self.onmessage = async function(event) {
55
const { type, buffer, secret, maxSide, outputAs } = event.data;
66

7-
console.log('Worker received message:', event.data);
7+
console.log(
8+
'Worker received args:',
9+
type, secret, maxSide, outputAs
10+
);
811

912
if (type === 'encode') {
1013
const encoded = encode(buffer, secret, maxSide, outputAs);

0 commit comments

Comments
 (0)