Skip to content

Commit 264128d

Browse files
authored
feat: 1-click plugin (#175)
1 parent dbb617f commit 264128d

File tree

24 files changed

+181
-1601
lines changed

24 files changed

+181
-1601
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ bin/
88
build
99
tlsn/
1010
zip
11+
.vscode

src/components/Menu/index.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import Icon from '../Icon';
99
import browser from 'webextension-polyfill';
1010
import classNames from 'classnames';
1111
import { useNavigate } from 'react-router';
12-
import PluginUploadInfo from '../PluginInfo';
1312

1413
export function MenuIcon(): ReactElement {
1514
const [opened, setOpen] = useState(false);
@@ -54,24 +53,34 @@ export default function Menu(props: {
5453
<div className="absolute top-[100%] right-0 rounded-md z-20">
5554
<div className="flex flex-col bg-slate-200 w-40 shadow rounded-md py">
5655
<MenuRow
57-
fa="fa-solid fa-plus"
56+
fa="fa-solid fa-hammer"
5857
className="relative"
5958
onClick={() => {
59+
navigate('/custom');
6060
props.setOpen(false);
6161
}}
6262
>
63-
<PluginUploadInfo onPluginInstalled={() => props.setOpen(false)} />
64-
<span>Install Plugin</span>
63+
<span>Custom</span>
6564
</MenuRow>
6665
<MenuRow
67-
fa="fa-solid fa-toolbox"
66+
fa="fa-solid fa-certificate"
67+
className="relative"
68+
onClick={() => {
69+
props.setOpen(false);
70+
navigate('/verify');
71+
}}
72+
>
73+
Verify
74+
</MenuRow>
75+
<MenuRow
76+
fa="fa-solid fa-network-wired"
6877
className="border-b border-slate-300"
6978
onClick={() => {
7079
props.setOpen(false);
71-
navigate('/plugins');
80+
navigate('/p2p');
7281
}}
7382
>
74-
Plugins
83+
P2P
7584
</MenuRow>
7685
<MenuRow
7786
className="lg:hidden"

src/components/PluginInfo/index.tsx

Lines changed: 1 addition & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
import React, {
2-
ChangeEvent,
3-
Children,
4-
MouseEventHandler,
5-
ReactElement,
6-
ReactNode,
7-
useCallback,
8-
useState,
9-
} from 'react';
10-
import { makePlugin, getPluginConfig } from '../../utils/misc';
11-
import { addPlugin } from '../../utils/rpc';
1+
import React, { Children, MouseEventHandler, ReactNode } from 'react';
122
import Modal, {
133
ModalHeader,
144
ModalContent,
@@ -22,77 +12,9 @@ import {
2212
MultipleParts,
2313
PermissionDescription,
2414
} from '../../utils/plugins';
25-
import { ErrorModal } from '../ErrorModal';
2615
import classNames from 'classnames';
2716
import DefaultPluginIcon from '../../assets/img/default-plugin-icon.png';
2817

29-
export default function PluginUploadInfo({
30-
onPluginInstalled,
31-
}: {
32-
onPluginInstalled?: () => void;
33-
}): ReactElement {
34-
const [error, showError] = useState('');
35-
const [pluginBuffer, setPluginBuffer] = useState<ArrayBuffer | any>(null);
36-
const [pluginContent, setPluginContent] = useState<PluginConfig | null>(null);
37-
38-
const onAddPlugin = useCallback(
39-
async (evt: React.MouseEvent<HTMLButtonElement>) => {
40-
try {
41-
await addPlugin(Buffer.from(pluginBuffer).toString('hex'));
42-
setPluginContent(null);
43-
onPluginInstalled?.();
44-
} catch (e: any) {
45-
showError(e?.message || 'Invalid Plugin');
46-
}
47-
},
48-
[pluginContent, pluginBuffer],
49-
);
50-
51-
const onPluginInfo = useCallback(
52-
async (evt: ChangeEvent<HTMLInputElement>) => {
53-
if (!evt.target.files) return;
54-
try {
55-
const [file] = evt.target.files;
56-
const arrayBuffer = await file.arrayBuffer();
57-
const plugin = await makePlugin(arrayBuffer);
58-
setPluginContent(await getPluginConfig(plugin));
59-
setPluginBuffer(arrayBuffer);
60-
} catch (e: any) {
61-
showError(e?.message || 'Invalid Plugin');
62-
} finally {
63-
evt.target.value = '';
64-
}
65-
},
66-
[setPluginContent, setPluginBuffer],
67-
);
68-
69-
const onClose = useCallback(() => {
70-
setPluginContent(null);
71-
setPluginBuffer(null);
72-
}, []);
73-
74-
return (
75-
<>
76-
<input
77-
className="opacity-0 absolute top-0 right-0 h-full w-full cursor-pointer"
78-
type="file"
79-
onChange={onPluginInfo}
80-
onClick={(e) => {
81-
e.stopPropagation();
82-
}}
83-
/>
84-
{error && <ErrorModal onClose={() => showError('')} message={error} />}
85-
{pluginContent && (
86-
<PluginInfoModal
87-
pluginContent={pluginContent}
88-
onClose={onClose}
89-
onAddPlugin={onAddPlugin}
90-
/>
91-
)}
92-
</>
93-
);
94-
}
95-
9618
export function PluginInfoModalHeader(props: {
9719
className?: string;
9820
children: ReactNode | ReactNode[];

src/components/PluginList/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
PluginInfoModalContent,
2424
PluginInfoModalHeader,
2525
} from '../PluginInfo';
26-
import { getPluginConfigByHash } from '../../entries/Background/db';
26+
import { getPluginConfigByUrl } from '../../entries/Background/db';
2727
import { SidePanelActionTypes } from '../../entries/SidePanel/types';
2828
import { openSidePanel } from '../../entries/utils';
2929

@@ -110,7 +110,7 @@ export function Plugin({
110110
if (hex) {
111111
setConfig(await getPluginConfig(hexToArrayBuffer(hex)));
112112
} else {
113-
setConfig(await getPluginConfigByHash(hash));
113+
setConfig(await getPluginConfigByUrl(hash));
114114
}
115115
})();
116116
}, [hash, hex]);

src/entries/Background/db.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -188,67 +188,70 @@ export async function getPluginHashes(): Promise<string[]> {
188188
return retVal;
189189
}
190190

191-
export async function getPluginByHash(hash: string): Promise<string | null> {
191+
export async function getPluginByUrl(url: string): Promise<string | null> {
192192
try {
193-
const plugin = await pluginDb.get(hash);
193+
const plugin = await pluginDb.get(url);
194194
return plugin;
195195
} catch (e) {
196196
return null;
197197
}
198198
}
199199

200-
export async function addPlugin(hex: string): Promise<string | null> {
200+
export async function addPlugin(
201+
hex: string,
202+
url: string,
203+
): Promise<string | null> {
201204
const hash = await sha256(hex);
202205

203-
if (await getPluginByHash(hash)) {
204-
return null;
206+
if (await getPluginByUrl(url)) {
207+
return url;
205208
}
206209

207-
await pluginDb.put(hash, hex);
210+
await pluginDb.put(url, hex);
208211
return hash;
209212
}
210213

211-
export async function removePlugin(hash: string): Promise<string | null> {
212-
const existing = await pluginDb.get(hash);
214+
export async function removePlugin(url: string): Promise<string | null> {
215+
const existing = await pluginDb.get(url);
213216

214217
if (!existing) return null;
215218

216-
await pluginDb.del(hash);
219+
await pluginDb.del(url);
217220

218-
return hash;
221+
return url;
219222
}
220223

221-
export async function getPluginConfigByHash(
222-
hash: string,
224+
export async function getPluginConfigByUrl(
225+
url: string,
223226
): Promise<PluginConfig | null> {
224227
try {
225-
const config = await pluginConfigDb.get(hash);
228+
const config = await pluginConfigDb.get(url);
226229
return config;
227230
} catch (e) {
228231
return null;
229232
}
230233
}
231234

232235
export async function addPluginConfig(
233-
hash: string,
236+
url: string,
234237
config: PluginConfig,
235238
): Promise<PluginConfig | null> {
236-
if (await getPluginConfigByHash(hash)) {
239+
if (await getPluginConfigByUrl(url)) {
237240
return null;
238241
}
239242

240-
await pluginConfigDb.put(hash, config);
243+
await pluginConfigDb.put(url, config);
241244
return config;
242245
}
243246

244247
export async function removePluginConfig(
245-
hash: string,
248+
url: string,
246249
): Promise<PluginConfig | null> {
247-
const existing = await pluginConfigDb.get(hash);
250+
const existing = await pluginConfigDb.get(url);
248251

249252
if (!existing) return null;
250253

251-
await pluginConfigDb.del(hash);
254+
await pluginConfigDb.del(url);
252255

253256
return existing;
254257
}
@@ -259,8 +262,8 @@ export async function getPlugins(): Promise<
259262
const hashes = await getPluginHashes();
260263
const ret: (PluginConfig & { hash: string; metadata: PluginMetadata })[] = [];
261264
for (const hash of hashes) {
262-
const config = await getPluginConfigByHash(hash);
263-
const metadata = await getPluginMetadataByHash(hash);
265+
const config = await getPluginConfigByUrl(hash);
266+
const metadata = await getPluginMetadataByUrl(hash);
264267
if (config) {
265268
ret.push({
266269
...config,
@@ -281,33 +284,33 @@ export async function getPlugins(): Promise<
281284
return ret;
282285
}
283286

284-
export async function getPluginMetadataByHash(
285-
hash: string,
287+
export async function getPluginMetadataByUrl(
288+
url: string,
286289
): Promise<PluginMetadata | null> {
287290
try {
288-
const metadata = await pluginMetadataDb.get(hash);
291+
const metadata = await pluginMetadataDb.get(url);
289292
return metadata;
290293
} catch (e) {
291294
return null;
292295
}
293296
}
294297

295298
export async function addPluginMetadata(
296-
hash: string,
299+
url: string,
297300
metadata: PluginMetadata,
298301
): Promise<PluginMetadata | null> {
299-
await pluginMetadataDb.put(hash, metadata);
302+
await pluginMetadataDb.put(url, metadata);
300303
return metadata;
301304
}
302305

303306
export async function removePluginMetadata(
304-
hash: string,
307+
url: string,
305308
): Promise<PluginMetadata | null> {
306-
const existing = await pluginMetadataDb.get(hash);
309+
const existing = await pluginMetadataDb.get(url);
307310

308311
if (!existing) return null;
309312

310-
await pluginMetadataDb.del(hash);
313+
await pluginMetadataDb.del(url);
311314

312315
return existing;
313316
}

src/entries/Background/plugins/utils.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,20 @@ import { addPlugin, addPluginConfig, addPluginMetadata } from '../db';
22
import { getPluginConfig } from '../../../utils/misc';
33

44
export async function installPlugin(
5-
urlOrBuffer: ArrayBuffer | string,
5+
url: string,
66
origin = '',
77
filePath = '',
88
metadata: {[key: string]: string} = {},
99
) {
10-
let arrayBuffer;
11-
12-
if (typeof urlOrBuffer === 'string') {
13-
const resp = await fetch(urlOrBuffer);
14-
arrayBuffer = await resp.arrayBuffer();
15-
} else {
16-
arrayBuffer = urlOrBuffer;
17-
}
10+
const resp = await fetch(url);
11+
const arrayBuffer = await resp.arrayBuffer();
1812

1913
const config = await getPluginConfig(arrayBuffer);
2014
const hex = Buffer.from(arrayBuffer).toString('hex');
21-
const hash = await addPlugin(hex);
22-
await addPluginConfig(hash!, config);
23-
await addPluginMetadata(hash!, {
15+
const hash = await addPlugin(hex, url);
16+
17+
await addPluginConfig(url, config);
18+
await addPluginMetadata(url, {
2419
...metadata,
2520
origin,
2621
filePath,

0 commit comments

Comments
 (0)