Skip to content

Commit abc535d

Browse files
committed
Support binary
1 parent 5235799 commit abc535d

File tree

8 files changed

+170
-24
lines changed

8 files changed

+170
-24
lines changed

src/components/Main.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import MarkdownToHtml from './md-to-html/MarkdownToHtml';
55
import UnixTimestamp from './unix-timestamp/UnixTimestamp';
66
import HtmlPreview from './html-preview/HtmlPreview';
77
import QrCode from './qrcode/QrCode';
8+
import Base64 from './base64/Base64';
89

910
const Main = () => {
1011
const routes = [
@@ -32,6 +33,12 @@ const Main = () => {
3233
name: 'QRCode Generator',
3334
Component: QrCode,
3435
},
36+
{
37+
icon: <FontAwesomeIcon icon="code" />,
38+
path: '/base64',
39+
name: 'Base64 Encoder',
40+
Component: Base64,
41+
},
3542
];
3643

3744
return (

src/components/base64/Base64.tsx

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { ipcRenderer, clipboard } from 'electron';
3+
4+
const Base64 = () => {
5+
const [input, setInput] = useState('Raw data');
6+
const [encode, setEncode] = useState(true);
7+
const [string, setString] = useState(true);
8+
const [output, setOutput] = useState(btoa('Raw data'));
9+
const [opening, setOpening] = useState(false);
10+
11+
const handleChangeInput = (evt: { target: { value: string } }) =>
12+
setInput(evt.target.value);
13+
14+
const handleOpenInput = async () => {
15+
setOpening(true);
16+
const content = await ipcRenderer.invoke('open-file', []);
17+
if (string) {
18+
setInput(Buffer.from(content).toString());
19+
} else {
20+
setInput(content);
21+
}
22+
setOpening(false);
23+
};
24+
25+
const handleClipboardInput = () => {
26+
setInput(clipboard.readText());
27+
};
28+
29+
const handleCopyOutput = () => {
30+
clipboard.write({ text: output });
31+
};
32+
33+
useEffect(() => {
34+
try {
35+
if (encode) {
36+
setOutput(Buffer.from(input).toString('base64'));
37+
} else {
38+
setOutput(Buffer.from(input, 'base64').toString());
39+
}
40+
} catch (e) {
41+
setOutput(e.message);
42+
}
43+
}, [input, encode]);
44+
45+
return (
46+
<div className="min-h-full flex flex-col">
47+
<div className="flex justify-between mb-1">
48+
<span className="flex space-x-2">
49+
<button type="button" className="btn" onClick={handleClipboardInput}>
50+
Clipboard
51+
</button>
52+
<button
53+
type="button"
54+
className="btn"
55+
onClick={handleOpenInput}
56+
disabled={opening}
57+
>
58+
Open...
59+
</button>
60+
<div className="flex space-x-4 items-center">
61+
<label htmlFor="string" className="flex items-center space-x-2">
62+
<input
63+
type="radio"
64+
className="btn"
65+
name="string"
66+
id="string"
67+
checked={string}
68+
onChange={() => setString(true)}
69+
/>
70+
<p>Text</p>
71+
</label>
72+
<label htmlFor="raw" className="flex items-center space-x-2">
73+
<input
74+
type="radio"
75+
className="btn"
76+
name="string"
77+
id="raw"
78+
checked={!string}
79+
onChange={() => setString(false)}
80+
/>
81+
<p>Binary</p>
82+
</label>
83+
</div>
84+
</span>
85+
<span className="flex space-x-4">
86+
<div className="flex space-x-4 items-center">
87+
<label htmlFor="encoder" className="flex items-center space-x-2">
88+
<input
89+
type="radio"
90+
className="btn"
91+
name="encode"
92+
id="encoder"
93+
checked={encode}
94+
onChange={() => setEncode(true)}
95+
/>
96+
<p>Encode</p>
97+
</label>
98+
<label htmlFor="decoder" className="flex items-center space-x-2">
99+
<input
100+
type="radio"
101+
className="btn"
102+
name="encode"
103+
id="decoder"
104+
checked={!encode}
105+
onChange={() => setEncode(false)}
106+
/>
107+
<p>Decode</p>
108+
</label>
109+
</div>
110+
<button type="button" className="btn" onClick={handleCopyOutput}>
111+
Copy
112+
</button>
113+
</span>
114+
</div>
115+
<div className="flex min-h-full flex-1">
116+
<textarea
117+
onChange={handleChangeInput}
118+
className="flex-1 min-h-full bg-white p-4 rounded-md"
119+
value={input}
120+
disabled={opening}
121+
/>
122+
<div className="mx-1" />
123+
<textarea
124+
className="flex-1 min-h-full bg-blue-100 p-4 rounded-md"
125+
value={output}
126+
readOnly
127+
/>
128+
</div>
129+
</div>
130+
);
131+
};
132+
133+
export default Base64;

src/components/html-preview/HtmlPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const HtmlPreview = () => {
1515
setOpening(true);
1616
const filters = [{ name: 'HTML Files', extensions: ['htm', 'html'] }];
1717
const content = await ipcRenderer.invoke('open-file', filters);
18-
setHtml(content);
18+
setHtml(Buffer.from(content).toString());
1919
setOpening(false);
2020
};
2121

src/components/md-to-html/MarkdownToHtml.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Md2Html = () => {
1717
{ name: 'Markdown Files', extensions: ['md', 'markdown', 'txt'] },
1818
];
1919
const content = await ipcRenderer.invoke('open-file', filters);
20-
setMd(content);
20+
setMd(Buffer.from(content).toString());
2121
setOpening(false);
2222
};
2323

src/components/qrcode/QrCode.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const HtmlPreview = () => {
2727
setOpening(true);
2828
const filters = [{ name: 'Text Files', extensions: ['txt'] }];
2929
const data = await ipcRenderer.invoke('open-file', filters);
30-
setContent(data);
30+
setContent(Buffer.from(data).toString());
3131
setOpening(false);
3232
};
3333

src/components/unix-timestamp/UnixTimestamp.tsx

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,7 @@ const UnixTimestampConverter = () => {
6464

6565
return (
6666
<div className="min-h-full flex flex-col">
67-
<section className="mb-4 space-y-1 flex items-center space-x-2 border-b pb-4">
68-
<p>The current Unix epoch time is</p>
69-
<span className="text-base bg-blue-200 px-2 py-1 rounded font-mono">
70-
{date.unix()}
71-
</span>
72-
<button
73-
type="button"
74-
className="btn"
75-
onClick={handleCopy}
76-
disabled={copied}
77-
>
78-
Copy
79-
</button>
80-
</section>
81-
8267
<section className="flex justify-start space-x-2 mb-4">
83-
<p>Input:</p>
8468
<button type="button" className="btn" onClick={handleClipboard}>
8569
Clipboard
8670
</button>
@@ -120,7 +104,7 @@ const UnixTimestampConverter = () => {
120104
</label>
121105
</section>
122106

123-
<section className="flex flex-col space-y-4 w-full p-4 pb-8 rounded-md bg-gray-200 border">
107+
<section className="flex flex-col space-y-4 w-full p-4 pb-8 rounded-md bg-gray-200 border mb-4">
124108
<section className="flex items-center justify-between space-x-4">
125109
<label htmlFor="local" className="flex-1">
126110
<span>Local:</span>
@@ -188,6 +172,20 @@ const UnixTimestampConverter = () => {
188172
</label>
189173
</section>
190174
</section>
175+
<section className="mt-4 pt-4 space-y-1 flex items-center border-t space-x-2 pb-4">
176+
<p>The current Unix epoch time is</p>
177+
<span className="bg-blue-200 px-2 py-0.5 rounded font-mono">
178+
{date.unix()}
179+
</span>
180+
<button
181+
type="button"
182+
className="btn"
183+
onClick={handleCopy}
184+
disabled={copied}
185+
>
186+
Copy
187+
</button>
188+
</section>
191189
</div>
192190
);
193191
};

src/helpers/fontAwesome.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { library } from '@fortawesome/fontawesome-svg-core';
22
import { fab, faMarkdown, faHtml5 } from '@fortawesome/free-brands-svg-icons';
3-
import { faClock, faCopy, faQrcode } from '@fortawesome/free-solid-svg-icons';
3+
import {
4+
faClock,
5+
faCode,
6+
faCopy,
7+
faQrcode,
8+
} from '@fortawesome/free-solid-svg-icons';
49

5-
library.add(fab, faMarkdown, faClock, faHtml5, faQrcode, faCopy);
10+
library.add(fab, faMarkdown, faClock, faHtml5, faQrcode, faCopy, faCode);

src/main.dev.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ const createWindow = async () => {
118118
/**
119119
* Handlers events from React
120120
*/
121+
122+
// This method return a Buffer, if you want to convert to string
123+
// use Buffer.from(buffer).toString()
121124
ipcMain.handle(
122125
'open-file',
123126
async (_event: IpcMainInvokeEvent, filters: FileFilter[]) => {
@@ -126,10 +129,10 @@ ipcMain.handle(
126129
filters,
127130
});
128131

129-
let content = '';
132+
let content;
130133
if (files) {
131134
const buffer = await promisify(fs.readFile)(files.filePaths[0]);
132-
content = buffer.toString();
135+
content = buffer;
133136
}
134137
return content;
135138
}

0 commit comments

Comments
 (0)