Skip to content

Commit 31ee6d9

Browse files
committed
[frontend] add html2canvas
1 parent 81b6467 commit 31ee6d9

File tree

5 files changed

+70
-28
lines changed

5 files changed

+70
-28
lines changed

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@mercuryworkshop/epoxy-transport": "^2.1.27",
1919
"@mercuryworkshop/scramjet": "workspace:scramjet",
2020
"dreamland": "workspace:dreamland",
21+
"html2canvas": "^1.4.1",
2122
"monaco-editor": "^0.52.2",
2223
"vite-plugin-static-copy": "^3.1.0"
2324
}

frontend/src/Tab.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class Tab extends StatefulClass {
1414
id: number;
1515
title: string | null;
1616
frame: ScramjetFrame;
17+
screenshot: string | null = null;
1718

1819
dragoffset: number;
1920
dragpos: number;

frontend/src/browser.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { createDelegate } from "dreamland/utils";
1212

1313
export const pushTab = createDelegate<Tab>();
1414
export const popTab = createDelegate<Tab>();
15+
export const forceScreenshot = createDelegate<Tab>();
1516

1617
export class Browser extends StatefulClass {
1718
built: boolean = false;

frontend/src/components/Shell.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { css, type Component } from "dreamland/core";
22
import { browser } from "../main";
3-
import { popTab, pushTab } from "../browser";
3+
import { forceScreenshot, popTab, pushTab } from "../browser";
44
import type { Tab } from "../Tab";
5+
import html2canvas from "html2canvas";
56

67
export const Shell: Component<{
78
tabs: Tab[];
@@ -12,6 +13,7 @@ export const Shell: Component<{
1213
cx.root.appendChild(
1314
<div
1415
class={`container ${cx.id}`}
16+
data-tab={tab.id}
1517
class:active={use(this.activetab).map((t) => t === tab)}
1618
class:showframe={use(tab.internalpage).map((t) => !t)}
1719
>
@@ -21,12 +23,20 @@ export const Shell: Component<{
2123
);
2224
});
2325
popTab.listen((tab) => {
24-
for (let el of cx.root.children) {
25-
if (el.children[0] == tab.frame.frame) {
26-
el.remove();
27-
break;
28-
}
29-
}
26+
const container = cx.root.querySelector(`[data-tab="${tab.id}"]`);
27+
if (!container) throw new Error(`No container found for tab ${tab.id}`);
28+
container.remove();
29+
});
30+
forceScreenshot.listen(async (tab) => {
31+
const container = cx.root.querySelector(
32+
`[data-tab="${tab.id}"]`
33+
) as HTMLElement;
34+
if (!container) throw new Error(`No container found for tab ${tab.id}`);
35+
36+
const canvas = await html2canvas(
37+
container.children[0].contentDocument.body
38+
);
39+
tab.screenshot = canvas.toDataURL();
3040
});
3141

3242
return <div class:unfocus={use(browser.unfocusframes)}></div>;

frontend/src/components/TabStrip.tsx

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import { Icon } from "./Icon";
1111
import { memoize } from "../memoize";
1212
import { IconButton } from "./IconButton";
1313
import type { Tab } from "../Tab";
14+
import html2canvas from "html2canvas";
1415

1516
export const DragTab: Component<{
1617
active: boolean;
1718
id: number;
18-
icon: string;
19-
title: string;
19+
tab: Tab;
2020
mousedown: (e: MouseEvent) => void;
2121
destroy: () => void;
2222
transitionend: () => void;
@@ -38,6 +38,10 @@ export const DragTab: Component<{
3838
this.transitionend();
3939
}}
4040
>
41+
<div class="tooltip">
42+
<span>{use(this.tab.title)}</span>
43+
<img src={use(this.tab.screenshot)} />
44+
</div>
4145
<div
4246
class="dragroot"
4347
style="position: unset;"
@@ -48,8 +52,8 @@ export const DragTab: Component<{
4852
}}
4953
>
5054
<div class={use(this.active).map((x) => `main ${x ? "active" : ""}`)}>
51-
<img src={use(this.icon)} />
52-
<span>{use(this.title)}</span>
55+
<img src={use(this.tab.icon)} />
56+
<span>{use(this.tab.title)}</span>
5357
<button
5458
class="close"
5559
on:click={(e) => {
@@ -78,6 +82,25 @@ DragTab.style = css`
7882
--tab-active-border-radius-neg: -10px;
7983
}
8084
85+
.tooltip {
86+
position: absolute;
87+
top: 5em;
88+
left: 0;
89+
z-index: 1000;
90+
background: var(--aboutbrowser-tooltip-bg);
91+
width: 20em;
92+
/* height: 10em; */
93+
flex-direction: column;
94+
display: none;
95+
border-radius: 4px;
96+
}
97+
:scope:hover .tooltip {
98+
display: flex;
99+
}
100+
.tooltip img {
101+
width: 100%;
102+
}
103+
81104
.main {
82105
height: 28px;
83106
min-width: 0;
@@ -109,17 +132,17 @@ DragTab.style = css`
109132
height: 14px;
110133
}
111134
.close {
112-
outline: none;
113-
border: none;
114-
background: none;
115-
cursor: pointer;
135+
outline: none;
136+
border: none;
137+
background: none;
138+
cursor: pointer;
116139
117-
display: flex;
118-
align-items: center;
119-
justify-content: center;
140+
display: flex;
141+
align-items: center;
142+
justify-content: center;
120143
121-
padding: 0;
122-
margin-left: 8px;
144+
padding: 0;
145+
margin-left: 8px;
123146
}
124147
125148
.main:not(.active):hover {
@@ -132,8 +155,6 @@ DragTab.style = css`
132155
.main.active {
133156
background: var(--aboutbrowser-active-tab-bg);
134157
color: var(--aboutbrowser-active-tab-fg);
135-
136-
# border-radius: 12px 12px 0 0;
137158
}
138159
139160
.belowcontainer {
@@ -147,8 +168,9 @@ DragTab.style = css`
147168
148169
background: var(--aboutbrowser-active-tab-bg);
149170
}
150-
.below::before, .below::after {
151-
content: '';
171+
.below::before,
172+
.below::after {
173+
content: "";
152174
position: absolute;
153175
bottom: 0;
154176
@@ -159,11 +181,19 @@ DragTab.style = css`
159181
}
160182
.below::before {
161183
left: var(--tab-active-border-radius-neg);
162-
mask-image: radial-gradient(circle at 0 0, transparent var(--tab-active-border-radius), black 0);
184+
mask-image: radial-gradient(
185+
circle at 0 0,
186+
transparent var(--tab-active-border-radius),
187+
black 0
188+
);
163189
}
164190
.below::after {
165191
right: var(--tab-active-border-radius-neg);
166-
mask-image: radial-gradient(circle at var(--tab-active-border-width) 0, transparent var(--tab-active-border-radius), black 0);
192+
mask-image: radial-gradient(
193+
circle at var(--tab-active-border-width) 0,
194+
transparent var(--tab-active-border-radius),
195+
black 0
196+
);
167197
}
168198
`;
169199

@@ -358,8 +388,7 @@ export const Tabs: Component<
358388
() => (
359389
<DragTab
360390
id={tab.id}
361-
title={use(tab.title)}
362-
icon={use(tab.icon)}
391+
tab={tab}
363392
active={use(this.activetab).map((x) => x === tab)}
364393
mousedown={(e) => mouseDown(e, tab)}
365394
destroy={() => {

0 commit comments

Comments
 (0)