Skip to content

Commit 1d641d1

Browse files
committed
[frontend] separate browser logic and root component
1 parent 311a592 commit 1d641d1

File tree

8 files changed

+93
-98
lines changed

8 files changed

+93
-98
lines changed

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"html-to-image": "^1.11.13",
2222
"html2canvas": "^1.4.1",
2323
"monaco-editor": "^0.52.2",
24+
"tlds": "^1.259.0",
2425
"vite-plugin-static-copy": "^3.1.0"
2526
}
2627
}

frontend/src/App.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { Component } from "dreamland/core";
2+
import { Omnibox } from "./components/Omnibox";
3+
import { Tabs } from "./components/TabStrip";
4+
import { ThemeVars } from "./theme";
5+
import { config } from "./Browser";
6+
import { browser } from "./main";
7+
import type { Tab } from "./Tab";
8+
9+
export const App: Component = function (cx) {
10+
return (
11+
<div id="app">
12+
<ThemeVars colors={use(config.theme)} />
13+
<Tabs
14+
tabs={use(browser.tabs).bind()}
15+
activetab={use(browser.activetab).bind()}
16+
addTab={() => {
17+
browser.newTab();
18+
}}
19+
destroyTab={(tab: Tab) => {
20+
browser.destroyTab(tab);
21+
}}
22+
/>
23+
<Omnibox tab={use(browser.activetab).bind()} />
24+
{cx.children}
25+
</div>
26+
);
27+
};

frontend/src/browser.tsx renamed to frontend/src/Browser.tsx

Lines changed: 35 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,54 @@ export const forceScreenshot = createDelegate<Tab>();
1717

1818
export const saveBrowserState = createDelegate<void>();
1919

20+
export const config = createState({
21+
theme: {
22+
frame_bg: [231, 238, 245],
23+
toolbar_bg: [211, 218, 255],
24+
toolbar_button_fg: [65, 72, 76],
25+
toolbar_fg: [65, 72, 76],
26+
27+
inactive_tab_bg: [40, 40, 40],
28+
inactive_tab_fg: [95, 92, 96],
29+
active_tab_fg: [65, 72, 76],
30+
31+
button_bg: [231, 238, 0],
32+
33+
ntp_bg: [231, 238, 0],
34+
ntp_fg: [232, 234, 237],
35+
ntp_link_fg: [138, 180, 248],
36+
37+
omnibox_bg: [221, 228, 235],
38+
omnibox_fg: [227, 227, 227],
39+
40+
bookmark_fg: [199, 199, 199],
41+
},
42+
});
43+
2044
export type SerializedBrowser = {
2145
tabs: SerializedTab[];
2246
activetab: number;
2347
};
2448

49+
export type GlobalHistoryEntry = {
50+
timestamp: number;
51+
url: string;
52+
title: string;
53+
favicon?: string;
54+
};
55+
2556
export class Browser extends StatefulClass {
2657
built: boolean = false;
2758

28-
theme: Theme;
2959
tabs: Tab[] = [];
3060
activetab: Tab;
3161

32-
unfocusframes: boolean = false;
33-
34-
constructor(state: Stateful<any>) {
35-
super(state);
36-
37-
this.theme = {
38-
frame_bg: [231, 238, 245],
39-
toolbar_bg: [211, 218, 255],
40-
toolbar_button_fg: [65, 72, 76],
41-
toolbar_fg: [65, 72, 76],
42-
43-
inactive_tab_bg: [40, 40, 40],
44-
inactive_tab_fg: [95, 92, 96],
45-
active_tab_fg: [65, 72, 76],
46-
47-
button_bg: [231, 238, 0],
62+
globalhistory: string[];
4863

49-
ntp_bg: [231, 238, 0],
50-
ntp_fg: [232, 234, 237],
51-
ntp_link_fg: [138, 180, 248],
52-
53-
omnibox_bg: [221, 228, 235],
54-
omnibox_fg: [227, 227, 227],
64+
unfocusframes: boolean = false;
5565

56-
bookmark_fg: [199, 199, 199],
57-
};
66+
constructor() {
67+
super(createState(Object.create(Browser.prototype)));
5868
}
5969

6070
serialize(): SerializedBrowser {
@@ -126,55 +136,6 @@ export class Browser extends StatefulClass {
126136
this.activetab.pushNavigate(new URL(search));
127137
}
128138
}
129-
130-
build(): HTMLElement {
131-
let shell = <Shell tabs={use(this.tabs)} activetab={use(this.activetab)} />;
132-
133-
let de = localStorage["browserstate"];
134-
if (de) {
135-
browser.deserialize(JSON.parse(de));
136-
} else {
137-
let tab = this.newTab();
138-
this.activetab = tab;
139-
}
140-
141-
if (this.built) throw new Error("already built");
142-
this.built = true;
143-
144-
return (
145-
<div>
146-
<ThemeVars colors={use(this.theme)} />
147-
<Tabs
148-
tabs={use(this.tabs).bind()}
149-
activetab={use(this.activetab).bind()}
150-
destroyTab={(tab) => this.destroyTab(tab)}
151-
addTab={() => this.newTab()}
152-
/>
153-
<Omnibox
154-
tabUrl={use(this.activetab.url)}
155-
canGoBack={use(this.activetab.canGoBack)}
156-
canGoForwards={use(this.activetab.canGoForward)}
157-
goBack={() => {
158-
this.activetab.back();
159-
}}
160-
goForwards={() => {
161-
this.activetab.forward();
162-
}}
163-
refresh={() => {
164-
this.activetab.frame.reload();
165-
}}
166-
/>
167-
{shell}
168-
</div>
169-
);
170-
}
171-
}
172-
173-
export function createBrowser(): Browser {
174-
let browser = new Browser(createState({}));
175-
Object.setPrototypeOf(browser, Browser.prototype);
176-
177-
return browser;
178139
}
179140

180141
saveBrowserState.listen(() => {
File renamed without changes.

frontend/src/Tab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
History,
77
injectHistoryEmulation,
88
type SerializedHistory,
9-
} from "./history";
9+
} from "./History";
1010
import { NewTab } from "./pages/NewTab";
1111
import { Playground } from "./pages/Playground";
1212
import { createMenu } from "./components/Menu";

frontend/src/components/Omnibox.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { createMenu, setContextMenu } from "./Menu";
1111
import { browser, client } from "../main";
1212
import { IconButton } from "./IconButton";
1313
import { createDelegate, type Delegate } from "dreamland/core";
14+
import type { Tab } from "../Tab";
1415

1516
export const Spacer: Component = function (cx) {
1617
return <div></div>;
@@ -247,12 +248,7 @@ UrlInput.style = css`
247248
`;
248249

249250
export const Omnibox: Component<{
250-
tabUrl: URL;
251-
goBack: () => void;
252-
goForwards: () => void;
253-
refresh: () => void;
254-
canGoBack: boolean;
255-
canGoForwards: boolean;
251+
tab: Tab;
256252
}> = function (cx) {
257253
const selectContent = createDelegate<void>();
258254
cx.mount = () => {
@@ -268,20 +264,23 @@ export const Omnibox: Component<{
268264
return (
269265
<div>
270266
<IconButton
271-
active={use(this.canGoBack)}
272-
click={this.goBack}
267+
active={use(this.tab.canGoBack)}
268+
click={() => this.tab.back()}
273269
icon={iconBack}
274270
></IconButton>
275271
<IconButton
276-
active={use(this.canGoForwards)}
277-
click={this.goForwards}
272+
active={use(this.tab.canGoForward)}
273+
click={() => this.tab.forward()}
278274
icon={iconForwards}
279275
></IconButton>
280-
<IconButton click={this.refresh} icon={iconRefresh}></IconButton>
276+
<IconButton
277+
click={() => this.tab.reload()}
278+
icon={iconRefresh}
279+
></IconButton>
281280
<Spacer></Spacer>
282281
<UrlInput
283282
selectContent={selectContent}
284-
tabUrl={use(this.tabUrl)}
283+
tabUrl={use(this.tab.url)}
285284
></UrlInput>
286285
<Spacer></Spacer>
287286
<IconButton icon={iconExtension}></IconButton>

frontend/src/components/Shell.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import { css, type Component } from "dreamland/core";
22
import { browser } from "../main";
3-
import { forceScreenshot, popTab, pushTab } from "../browser";
3+
import { forceScreenshot, popTab, pushTab } from "../Browser";
44
import type { Tab } from "../Tab";
55
import { toBlob } from "html-to-image";
66

7-
export const Shell: Component<{
8-
tabs: Tab[];
9-
activetab: Tab;
10-
}> = function (cx) {
7+
export const Shell: Component = function (cx) {
118
pushTab.listen((tab) => {
129
// paint the iframes
1310
tab.frame.frame.classList.add(cx.id);
@@ -21,7 +18,7 @@ export const Shell: Component<{
2118
class="container"
2219
data-tab={tab.id}
2320
id={"tab" + tab.id}
24-
class:active={use(this.activetab).map((t) => t === tab)}
21+
class:active={use(browser.activetab).map((t) => t === tab)}
2522
class:showframe={use(tab.internalpage).map((t) => !t)}
2623
>
2724
<div

frontend/src/main.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import "./style.css";
33
// temp fix for vite not working
44
import.meta.hot?.accept(() => location.reload());
55

6-
import { createBrowser } from "./browser";
6+
import { Browser } from "./Browser";
77
import { createMenu } from "./components/Menu";
88
let app = document.getElementById("app")!;
99
import { BareMuxConnection, BareClient } from "@mercuryworkshop/bare-mux";
10+
import { Shell } from "./components/Shell";
11+
import { App } from "./App";
1012

1113
let connection = new BareMuxConnection("/baremux/worker.js");
1214
connection.setTransport("/epoxy/index.mjs", [{ wisp: "wss://anura.pro" }]);
@@ -37,13 +39,21 @@ export const scramjet = new ScramjetController({
3739
scramjet.init();
3840
navigator.serviceWorker.register("./sw.js");
3941

40-
export let browser = createBrowser();
41-
(self as any).browser = browser;
42+
export let browser: Browser;
4243

4344
try {
44-
let built = browser.build();
45-
built.id = "app";
45+
let shell = <Shell></Shell>;
46+
browser = new Browser();
47+
let de = localStorage["browserstate"];
48+
if (de) {
49+
browser.deserialize(JSON.parse(de));
50+
} else {
51+
let tab = browser.newTab();
52+
browser.activetab = tab;
53+
}
4654

55+
(self as any).browser = browser;
56+
let built = <App>{shell}</App>;
4757
app.replaceWith(built);
4858
built.addEventListener("contextmenu", (e) => {
4959
e.preventDefault();

0 commit comments

Comments
 (0)