Skip to content

Commit 048282c

Browse files
committed
stable unsafe html: better implementation of clipping
1 parent 1bc8942 commit 048282c

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

src/packages/frontend/jupyter/cell-list.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { Cell } from "./cell";
3737
import HeadingTagComponent from "./heading-tag";
3838
interface StableHtmlContextType {
3939
cellListDivRef?: MutableRefObject<any>;
40-
iframeOnScrolls?: { [key: string]: () => void };
40+
htmlOnScrolls?: { [key: string]: () => void };
4141
}
4242
const StableHtmlContext = createContext<StableHtmlContextType>({});
4343
export const useStableHtmlContext: () => StableHtmlContextType = () => {
@@ -408,7 +408,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
408408
}
409409
}
410410

411-
function render_cell({
411+
function renderCell({
412412
id,
413413
isScrolling,
414414
index,
@@ -439,6 +439,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
439439
}}
440440
/>
441441
) : undefined;
442+
442443
return (
443444
<div key={id}>
444445
<Cell
@@ -505,8 +506,8 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
505506
...scrollState,
506507
id: cellListRef.current?.get(scrollState.index),
507508
};
508-
for (const key in iframeOnScrolls) {
509-
iframeOnScrolls[key]();
509+
for (const key in htmlOnScrolls) {
510+
htmlOnScrolls[key]();
510511
}
511512
},
512513
scrollerRef: handleCellListRef,
@@ -539,13 +540,13 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
539540
});
540541
}, [cell_list]);
541542

542-
const iframeOnScrolls = useMemo(() => {
543+
const htmlOnScrolls = useMemo(() => {
543544
return {};
544545
}, []);
545546
useEffect(() => {
546547
if (!use_windowed_list) return;
547-
for (const key in iframeOnScrolls) {
548-
iframeOnScrolls[key]();
548+
for (const key in htmlOnScrolls) {
549+
htmlOnScrolls[key]();
549550
}
550551
}, [cells]);
551552

@@ -557,7 +558,9 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
557558
const virtuosoHeightsRef = useRef<{ [index: number]: number }>({});
558559
if (use_windowed_list) {
559560
body = (
560-
<StableHtmlContext.Provider value={{ cellListDivRef, iframeOnScrolls }}>
561+
<StableHtmlContext.Provider
562+
value={{ cellListDivRef, htmlOnScrolls }}
563+
>
561564
<div ref={cellListDivRef} className="smc-vfill">
562565
<Virtuoso
563566
ref={virtuosoRef}
@@ -593,7 +596,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
593596
if (id == null) return null;
594597
const h = virtuosoHeightsRef.current[index];
595598
if (actions == null) {
596-
return render_cell({
599+
return renderCell({
597600
id,
598601
isScrolling: false,
599602
index,
@@ -602,7 +605,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
602605
return (
603606
<SortableItem id={id} key={id}>
604607
<DivTempHeight height={h ? `${h}px` : undefined}>
605-
{render_cell({
608+
{renderCell({
606609
id,
607610
isScrolling: false,
608611
index,
@@ -631,7 +634,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
631634
cell_list.forEach((id: string) => {
632635
v.push(
633636
<SortableItem id={id} key={id}>
634-
{render_cell({
637+
{renderCell({
635638
id,
636639
isScrolling: false,
637640
index,
@@ -681,7 +684,7 @@ export const CellList: React.FC<CellListProps> = (props: CellListProps) => {
681684
fontSize: `${font_size}px`,
682685
}}
683686
>
684-
{render_cell({ id })}
687+
{renderCell({ id })}
685688
</div>
686689
)}
687690
onDragStart={(id) => {

src/packages/frontend/jupyter/cell-output.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ export function CellOutput({
7979
...style,
8080
}}
8181
cocalc-test="cell-output"
82+
className={
83+
"cocalc-output-div" /* used by stable unsafe html for clipping */
84+
}
8285
>
8386
{!hidePrompt && <ControlColumn cell={cell} actions={actions} id={id} />}
8487
<OutputColumn
@@ -193,11 +196,7 @@ function ControlColumn({ actions, cell, id }) {
193196
}
194197
if (actions != null) {
195198
return (
196-
<OutputToggle
197-
actions={actions}
198-
id={id}
199-
scrolled={cell.get("scrolled")}
200-
>
199+
<OutputToggle actions={actions} id={id} scrolled={cell.get("scrolled")}>
201200
{prompt}
202201
</OutputToggle>
203202
);

src/packages/frontend/jupyter/cell.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ interface Props {
6060
isLast?: boolean;
6161
dragHandle?: JSX.Element;
6262
read_only?: boolean;
63-
outputDivRef?;
6463
}
6564

6665
function areEqual(props: Props, nextProps: Props): boolean {
@@ -165,7 +164,6 @@ export const Cell: React.FC<Props> = React.memo((props: Props) => {
165164
trust={props.trust}
166165
complete={props.is_current && props.complete != null}
167166
llmTools={props.llmTools}
168-
divRef={props.outputDivRef}
169167
/>
170168
);
171169
}

src/packages/frontend/jupyter/output-messages/stable-unsafe-html.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export default function StableUnsafeHtml({
7979
zIndex = Z_INDEX, // todo: support changing?
8080
}: Props) {
8181
const divRef = useRef<any>(null);
82+
const cellOutputDivRef = useRef<any>(null);
8283
const intervalRef = useRef<any>(null);
8384
const { isVisible, project_id, path, id } = useFrameContext();
8485
const stableHtmlContext = useStableHtmlContext();
@@ -131,15 +132,11 @@ export default function StableUnsafeHtml({
131132
parentRect.right - SCROLL_WIDTH - eltRect.left,
132133
);
133134

134-
// .closest('.a');
135-
//const bottom = Math.min(eltRect.height, parentRect.bottom - eltRect.top);
136-
// We do this so that if the output is COLLAPSED, then the html doesn't
135+
// The bottom is complicated because if the output is COLLAPSED, then the html doesn't
137136
// go outside the shortened div. We do not do anything regarding making
138137
// scroll work in there though -- if you want to see the whole thing, you
139138
// must not collapse it.
140-
const containerRect = $(divRef.current)
141-
.closest(".cocalc-output-div")[0]
142-
?.getBoundingClientRect();
139+
const containerRect = cellOutputDivRef.current?.getBoundingClientRect();
143140
const bottom = Math.max(
144141
top,
145142
Math.min(
@@ -221,8 +218,8 @@ export default function StableUnsafeHtml({
221218
position,
222219
POSITION_WHEN_MOUNTED_INTERVAL_MS,
223220
);
224-
if (stableHtmlContext.iframeOnScrolls != null) {
225-
stableHtmlContext.iframeOnScrolls[globalKey] = async () => {
221+
if (stableHtmlContext.htmlOnScrolls != null) {
222+
stableHtmlContext.htmlOnScrolls[globalKey] = async () => {
226223
position();
227224
await new Promise(requestAnimationFrame);
228225
position();
@@ -232,12 +229,22 @@ export default function StableUnsafeHtml({
232229
setTimeout(position, 0);
233230

234231
return () => {
235-
delete stableHtmlContext.iframeOnScrolls?.[globalKey];
232+
delete stableHtmlContext.htmlOnScrolls?.[globalKey];
236233
if (intervalRef.current) {
237234
clearInterval(intervalRef.current);
238235
}
239236
};
240237
}, []);
241238

239+
useEffect(() => {
240+
// This is "ugly jquery"... but I did try passing this info
241+
// down via stableHtmlContext and it gets REALLY complicated.
242+
// Also this only happens once on mount, so it's not a problem
243+
// regarding efficiency.
244+
cellOutputDivRef.current = $(divRef.current).closest(
245+
".cocalc-output-div",
246+
)[0];
247+
}, []);
248+
242249
return <div ref={divRef} style={STYLE}></div>;
243250
}

0 commit comments

Comments
 (0)