Skip to content

Commit 3b50548

Browse files
committed
fetch repl
1 parent eab598f commit 3b50548

File tree

18 files changed

+168
-154
lines changed

18 files changed

+168
-154
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@rollup/plugin-json": "^4.1.0",
3131
"@rollup/plugin-node-resolve": "^13.3.0",
3232
"@rollup/plugin-replace": "^4.0.0",
33+
"@solid-primitives/debounce": "^1.3.0",
3334
"@types/babel__standalone": "^7.1.4",
3435
"@types/dedent": "^0.7.0",
3536
"@types/fs-extra": "^9.0.13",
@@ -57,10 +58,10 @@
5758
"@amoutonbrady/lz-string": "^0.0.1",
5859
"@babel/preset-typescript": "^7.17.12",
5960
"@babel/standalone": "^7.18.1",
61+
"@solid-primitives/throttle": "^1.2.0",
6062
"babel-preset-solid": "1.4.2",
6163
"dedent": "^0.7.0",
6264
"jszip": "^3.10.0",
63-
"mitt": "^3.0.0",
6465
"monaco-editor-textmate": "^3.0.0",
6566
"monaco-textmate": "^3.0.1",
6667
"onigasm": "^2.2.5",

playground/app.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Show, onCleanup, createEffect, createSignal, JSX } from 'solid-js';
2-
import { Routes, Route } from 'solid-app-router';
3-
import { eventBus } from './utils/eventBus';
1+
import { Show, createEffect, createSignal, JSX, on } from 'solid-js';
2+
import { Routes, Route, useSearchParams } from 'solid-app-router';
3+
import { eventBus } from './utils/serviceWorker';
44
import { Update } from './components/update';
55
import { Header } from './components/header';
66
import { useZoom } from '../src/hooks/useZoom';
@@ -9,19 +9,15 @@ import { Edit } from './pages/edit';
99
import { Home } from './pages/home';
1010
import { Login } from './pages/login';
1111

12-
let swUpdatedBeforeRender = false;
13-
eventBus.on('sw-update', () => (swUpdatedBeforeRender = true));
14-
1512
export const App = (): JSX.Element => {
1613
/**
1714
* Those next three lines are useful to display a popup
1815
* if the client code has been updated. This trigger a signal
1916
* via an EventBus initiated in the service worker and
2017
* the couple line above.
2118
*/
22-
const [newUpdate, setNewUpdate] = createSignal(swUpdatedBeforeRender);
23-
eventBus.on('sw-update', () => setNewUpdate(true));
24-
onCleanup(() => eventBus.all.clear());
19+
const [newUpdate, setNewUpdate] = createSignal(eventBus() != undefined);
20+
on(eventBus, () => setNewUpdate(true));
2521

2622
const [dark, setDark] = createSignal(isDarkTheme());
2723
createEffect(() => document.body.classList.toggle('dark', dark()));
@@ -40,6 +36,8 @@ export const App = (): JSX.Element => {
4036
}
4137
});
4238

39+
const [searchParams] = useSearchParams();
40+
4341
return (
4442
<div class="relative flex bg-white dark:bg-solid-darkbg dark:text-white text-black h-screen overflow-hidden text-slate-900 dark:text-slate-50 font-sans flex-col">
4543
<Header
@@ -53,7 +51,10 @@ export const App = (): JSX.Element => {
5351
/>
5452

5553
<Routes>
56-
<Route path="/:user/:repl" element={<Edit dark={dark()} />} />
54+
<Route
55+
path="/:user/:repl"
56+
element={<Edit dark={dark()} horizontal={searchParams.isHorizontal != undefined} />}
57+
/>
5758
<Route path="/:user" element={<Home />} />
5859
<Route path="/" element={<Home />} />
5960
<Route path="/login" element={<Login />} />

playground/context.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createContext, createResource, createSignal, ParentComponent, Resource,
22

33
interface AppContextType {
44
token: string;
5-
user: Resource<{ display: any; avatar: any } | undefined>;
5+
user: Resource<{ display: string; avatar: string } | undefined>;
66
}
77

88
const AppContext = createContext<AppContextType>();

playground/pages/edit.tsx

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
22
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
33
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
4-
import { parseHash } from '../utils/parseHash';
5-
import { isValidUrl } from '../utils/isValidUrl';
6-
74
import CompilerWorker from '../../src/workers/compiler?worker';
85
import FormatterWorker from '../../src/workers/formatter?worker';
9-
import { createTabList, defaultTabs, processImport, Tab } from '../../src';
10-
import { createSignal, lazy, Suspense } from 'solid-js';
6+
import { createTabList } from '../../src';
7+
import { createEffect, createResource, createSignal, lazy, Suspense } from 'solid-js';
8+
import { useParams } from 'solid-app-router';
9+
import { API, useAppContext } from '../context';
10+
import createDebounce from '@solid-primitives/debounce';
11+
import type { APIRepl } from './home';
1112

1213
const Repl = lazy(() => import('../../src/components/repl'));
1314

@@ -25,26 +26,54 @@ const Repl = lazy(() => import('../../src/components/repl'));
2526
},
2627
};
2728

28-
export const Edit = (props: { dark: boolean }) => {
29+
export const Edit = (props: { dark: boolean; horizontal: boolean }) => {
2930
const compiler = new CompilerWorker();
3031
const formatter = new FormatterWorker();
3132

32-
const url = new URL(location.href);
33-
const initialTabs = parseHash<Tab[]>(url.hash && url.hash.slice(1)) || defaultTabs;
34-
35-
const [tabs, setTabs] = createTabList(initialTabs);
36-
const [current, setCurrent] = createSignal('main.tsx');
37-
38-
const params = Object.fromEntries(url.searchParams.entries());
33+
const params = useParams();
34+
const context = useAppContext()!;
35+
const [fetchedTabs] = createResource<APIRepl, string>(params.repl, (repl) =>
36+
fetch(`${API}/repl/${repl}`).then((r) => r.json()),
37+
);
3938

40-
if (params.data && isValidUrl(params.data)) {
41-
fetch(params.data)
42-
.then((r) => r.json())
43-
.then((data) => setTabs(processImport(data)))
44-
.catch((e) => console.error('Failed to import browser data', e));
45-
}
39+
const [tabs, setTabs] = createTabList([]);
40+
const [current, setCurrent] = createSignal<string>();
41+
createEffect(() => {
42+
const myRepl = fetchedTabs();
43+
if (!myRepl) return;
44+
setTabs(
45+
myRepl.files.map((x) => {
46+
let dot = x.name.lastIndexOf('.');
47+
return { name: x.name.slice(0, dot), type: x.name.slice(dot + 1), source: x.content.join('\n') };
48+
}),
49+
);
50+
setCurrent(myRepl.files[0].name);
51+
});
4652

47-
const isHorizontal = 'isHorizontal' in params;
53+
const tabMapper = () => tabs().map((x) => ({ name: `${x.name}.${x.type}`, content: x.source.split('\n') }));
54+
const updateRepl = createDebounce(() => {
55+
const repl = fetchedTabs();
56+
const tabs = tabMapper();
57+
if (!repl || !tabs.length) return;
58+
fetch(`${API}/repl/${repl.id}`, {
59+
method: 'PUT',
60+
headers: {
61+
authorization: `Bearer ${context.token}`,
62+
'Content-Type': 'application/json',
63+
},
64+
body: JSON.stringify({
65+
title: repl.title,
66+
version: repl.version,
67+
public: repl.public,
68+
labels: repl.labels,
69+
files: tabs,
70+
}),
71+
});
72+
}, 1000);
73+
createEffect(() => {
74+
tabMapper();
75+
updateRepl();
76+
});
4877

4978
return (
5079
<Suspense
@@ -67,7 +96,7 @@ export const Edit = (props: { dark: boolean }) => {
6796
<Repl
6897
compiler={compiler}
6998
formatter={formatter}
70-
isHorizontal={isHorizontal}
99+
isHorizontal={props.horizontal}
71100
dark={props.dark}
72101
tabs={tabs()}
73102
setTabs={setTabs}

playground/pages/home.tsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,24 @@ import { createResource, For, Suspense } from 'solid-js';
55
import { defaultTabs } from '../../src';
66
import { API, useAppContext } from '../context';
77

8+
export interface ReplFile {
9+
name: string;
10+
content: string[];
11+
}
12+
export interface APIRepl {
13+
id: string;
14+
title: string;
15+
labels: string[];
16+
files: ReplFile[];
17+
version: string;
18+
public: boolean;
19+
size: number;
20+
created_at: string;
21+
updated_at?: string;
22+
}
823
interface Repls {
924
total: number;
10-
list: {
11-
id: string;
12-
title: string;
13-
labels: string[];
14-
files: unknown;
15-
version: string;
16-
public: boolean;
17-
size: number;
18-
created_at: string;
19-
updated_at?: string;
20-
}[];
25+
list: APIRepl[];
2126
}
2227

2328
export const Home = () => {
@@ -26,10 +31,9 @@ export const Home = () => {
2631
const navigate = useNavigate();
2732
const user = () => params.user || context.user()?.display;
2833

29-
const [repls] = createResource(user, async (user) => {
34+
const [repls] = createResource<Repls, string>(user, async (user) => {
3035
if (!user) return { total: 0, list: [] };
31-
const result = await fetch(`${API}/repl/${user}/list`);
32-
return (await result.json()) as Repls;
36+
return await fetch(`${API}/repl/${user}/list`).then((r) => r.json());
3337
});
3438

3539
return (

playground/utils/eventBus.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

playground/utils/parseHash.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

playground/utils/serviceWorker.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { register } from 'register-service-worker';
2-
import { eventBus } from './eventBus';
2+
import { createSignal } from 'solid-js';
33

4-
export function registerServiceWorker(): void {
4+
const [eventBus, setEventBus] = createSignal();
5+
6+
function registerServiceWorker(): void {
57
if ('serviceWorker' in navigator && import.meta.env.PROD) {
68
window.addEventListener('load', () => {
79
register('/sw.js', {
810
updated(registration) {
9-
eventBus.emit('sw-update', registration);
11+
setEventBus(registration);
1012
},
1113
});
1214
});
1315
}
1416
}
17+
18+
export { eventBus, registerServiceWorker };

playground/utils/isValidUrl.ts renamed to playground/utils/url.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { decompressFromURL as decompress } from '@amoutonbrady/lz-string';
2+
13
/**
24
* Validate that a string is a valid URL
35
*
@@ -11,3 +13,11 @@ export function isValidUrl(url: string): boolean {
1113
return false;
1214
}
1315
}
16+
17+
export function parseHash<T>(hash: string): T | undefined {
18+
try {
19+
return JSON.parse(decompress(hash)!);
20+
} catch {
21+
return;
22+
}
23+
}

pnpm-lock.yaml

Lines changed: 24 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)