Skip to content

Commit

Permalink
fix bug in readonly view (via timetravel) of countdown timer.
Browse files Browse the repository at this point in the history
  • Loading branch information
williamstein committed Feb 14, 2022
1 parent 95d8ae6 commit 871ab65
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 84 deletions.
7 changes: 4 additions & 3 deletions src/packages/frontend/editors/stopwatch/stopwatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface StopwatchProps {
total?: number; // total time accumulated before entering current state
style?: CSSProperties;
timeStyle?: CSSProperties;
readOnly?: boolean; // can't change, and won't display something when timer goes off!
}

export default function Stopwatch(props: StopwatchProps) {
Expand Down Expand Up @@ -223,7 +224,7 @@ export default function Stopwatch(props: StopwatchProps) {
: undefined),
}}
/>
{props.countdown && amount == 0 && (
{props.countdown && amount == 0 && !props.readOnly && (
<Modal
title={
<>
Expand Down Expand Up @@ -378,7 +379,7 @@ export default function Stopwatch(props: StopwatchProps) {
{renderLabel()}
</Col>
</Row>
{!props.noButtons && (
{!props.noButtons && !props.readOnly && (
<Row style={{ marginTop: "5px" }}>
<Col md={24}>{renderButtons()}</Col>
</Row>
Expand All @@ -391,7 +392,7 @@ export default function Stopwatch(props: StopwatchProps) {
return (
<div style={{ display: "flex" }}>
{renderTime()}
{!props.noButtons && (
{!props.noButtons && !props.readOnly && (
<div style={{ marginTop: "3px", marginLeft: "5px" }}>
{renderButtons()}
</div>
Expand Down
17 changes: 7 additions & 10 deletions src/packages/frontend/frame-editors/whiteboard-editor/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
CodeEditorState,
} from "../code-editor/actions";
import { Tool } from "./tools/spec";
import { Element, Elements, Point } from "./types";
import { Element, Elements, Point, Rect } from "./types";
import { uuid } from "@cocalc/util/misc";
import {
DEFAULT_WIDTH,
Expand Down Expand Up @@ -269,17 +269,14 @@ export class Actions extends BaseActions<State> {
this.set_frame_tree({ id, hideMap: !node.get("hideMap") });
}

// TODO: serious concern -- this visibleWindow stuff is getting persisted
// to localStorage, but doesn't need to be, which is a waste.
saveVisibleWindow(
id: string,
visibleWindow: { xMin: number; yMin: number; xMax: number; yMax: number }
): void {
this.set_frame_tree({ id, visibleWindow });
// The viewport = exactly the part of the canvas that is VISIBLE to the user
// in data coordinates, of course, like everything here.
saveViewport(id: string, viewport: Rect): void {
this.set_frame_tree({ id, viewport });
}

setVisibleWindowCenter(id: string, center: { x: number; y: number }) {
this.set_frame_tree({ id, visibleWindowCenter: center });
setViewportCenter(id: string, center: { x: number; y: number }) {
this.set_frame_tree({ id, viewportCenter: center });
}

saveCenter(id: string, center: { x: number; y: number }) {
Expand Down
126 changes: 56 additions & 70 deletions src/packages/frontend/frame-editors/whiteboard-editor/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import { useFrameContext } from "./hooks";
import usePinchToZoom from "@cocalc/frontend/frame-editors/frame-tree/pinch-to-zoom";
import Grid from "./elements/grid";
import {
centerOfRect,
compressPath,
fontSizeToZoom,
ZOOM100,
Expand Down Expand Up @@ -160,35 +161,27 @@ export default function Canvas({

// Whenever the scale changes, make sure the current center of the screen
// is preserved.
const [lastScale, setLastScale] = useState<number>(canvasScale);
const lastViewport = useRef<Rect | undefined>(undefined);
useEffect(() => {
if (isNavigator) return;
if (canvasScale == lastScale) return;
const ctr = getCenterPositionWindow();
if (ctr == null) return;
const { x, y } = ctr;
const new_x = (lastScale / canvasScale) * x;
const new_y = (lastScale / canvasScale) * y;
const delta_x = x - new_x;
const delta_y = y - new_y;
const c = canvasRef.current;
if (c == null) return;
c.scrollLeft += delta_x;
c.scrollTop += delta_y;
setLastScale(canvasScale);
}, [canvasScale]);

useEffect(() => {
const { current } = canvasRef;
if (current != null) {
const scaledMargin = (margin ?? 0) * canvasScale;
current.scrollTop = scaledMargin;
current.scrollLeft = scaledMargin;
const viewport = getViewportData();
if (lastViewport.current != null && viewport != null) {
const last = centerOfRect(lastViewport.current);
const cur = centerOfRect(viewport);
const tx = last.x - cur.x;
const ty = last.y - cur.y;
const c = canvasRef.current;
if (c == null) return;
c.scrollLeft += tx * canvasScale;
c.scrollTop += ty * canvasScale;
}
}, []);
lastViewport.current = viewport;
}, [canvasScale, margin]);

// maintain state about the viewport so it can be displayed
// in the navmap, and also restored later.
useEffect(() => {
updateVisibleWindow();
updateViewport();
}, [font_size, scale, transforms.width, transforms.height]);

const frame = useFrameContext();
Expand All @@ -197,10 +190,10 @@ export default function Canvas({
const restoring = useRef<boolean>(true);
useEffect(() => {
if (isNavigator || restoring.current) return;
const center = frame.desc.get("visibleWindowCenter")?.toJS();
const center = frame.desc.get("viewportCenter")?.toJS();
if (center == null) return;
setCenterPositionData(center);
}, [frame.desc.get("visibleWindowCenter")]);
}, [frame.desc.get("viewportCenter")]);

useEffect(() => {
if (isNavigator) return;
Expand Down Expand Up @@ -272,24 +265,31 @@ export default function Canvas({
c.scrollTop = scrollTopGoal;
}

// when fitToScreen is true, compute data then set font_size to get zoom (plus offset) to
// everything is visible properly on the page; also set fitToScreen back to false in
// when fitToScreen is true, compute data then set font_size to
// get zoom (plus offset) to everything is visible properly
// on the page; also set fitToScreen back to false in
// frame tree data
useEffect(() => {
if (frame.desc.get("fitToScreen") && !isNavigator) {
try {
const viewport = getViewportData();
if (viewport == null) return;
const rect = rectSpan(elements);
const { scale } = fitRectToRect(rect, viewport);
frame.actions.set_font_size(frame.id, (font_size ?? ZOOM100) * scale);
setCenterPositionData({
x: rect.x + rect.w / 2,
y: rect.y + rect.h / 2,
});
} finally {
frame.actions.fitToScreen(frame.id, false);
if (isNavigator || !frame.desc.get("fitToScreen")) return;
try {
const viewport = getViewportData();
if (viewport == null) return;
const rect = rectSpan(elements);
setCenterPositionData({
x: rect.x + rect.w / 2,
y: rect.y + rect.h / 2,
});
const { scale } = fitRectToRect(rect, viewport);
if (scale != 1) {
// ensure lastViewport is up to date before zooming.
lastViewport.current = getViewportData();
frame.actions.set_font_size(
frame.id,
Math.round((font_size ?? ZOOM100) * scale)
);
}
} finally {
frame.actions.fitToScreen(frame.id, false);
}
}, [frame.desc.get("fitToScreen")]);

Expand Down Expand Up @@ -326,6 +326,7 @@ export default function Canvas({
element={element}
focused={focused}
canvasScale={canvasScale}
readOnly={readOnly}
/>
);
if (!isNavRectangle && (element.style || selected || isNavigator)) {
Expand Down Expand Up @@ -450,9 +451,8 @@ export default function Canvas({

if (isNavigator) {
// The navigator rectangle
const visible = frame.desc.get("visibleWindow")?.toJS();
const visible = frame.desc.get("viewport")?.toJS();
if (visible) {
const { xMin, yMin, xMax, yMax } = visible;
v.unshift(
<Draggable
key="nav"
Expand All @@ -467,14 +467,11 @@ export default function Canvas({
onStop={(data: MouseEvent) => {
if (!navDrag.current) return;
const { x0, y0 } = navDrag.current;
const visible = frame.desc.get("visibleWindow")?.toJS();
const visible = frame.desc.get("viewport")?.toJS();
if (visible == null) return;
const ctr = {
x: (visible.xMax + visible.xMin) / 2,
y: (visible.yMax + visible.yMin) / 2,
};
const ctr = centerOfRect(visible);
const { x, y } = data;
frame.actions.setVisibleWindowCenter(frame.id, {
frame.actions.setViewportCenter(frame.id, {
x: ctr.x + (x - x0) / canvasScale,
y: ctr.y + (y - y0) / canvasScale,
});
Expand All @@ -484,10 +481,7 @@ export default function Canvas({
{processElement(
{
id: "nav-frame",
x: xMin,
y: yMin,
w: xMax - xMin,
h: yMax - yMin,
...visible,
z: MAX_ELEMENTS + 1,
type: "frame",
data: { color: "#888", radius: 0.5 },
Expand Down Expand Up @@ -615,25 +609,17 @@ export default function Canvas({
}
}

const updateVisibleWindow = isNavigator
const updateViewport = isNavigator
? () => {}
: useMemo(() => {
return throttle(() => {
const elt = canvasRef.current;
if (!elt) return;
// upper left corner of visible window
const { scrollLeft, scrollTop } = elt;
// width and height of visible window
const { width, height } = elt.getBoundingClientRect();
const { x: xMin, y: yMin } = transforms.windowToDataNoScale(
scrollLeft / canvasScale,
scrollTop / canvasScale
);
const xMax = xMin + width / canvasScale;
const yMax = yMin + height / canvasScale;
frame.actions.saveVisibleWindow(frame.id, { xMin, yMin, xMax, yMax });
const viewport = getViewportData();
if (viewport) {
frame.actions.saveViewport(frame.id, viewport);
lastViewport.current = viewport;
}
}, 50);
}, [transforms, canvasScale]);
}, [transforms, canvasScale, margin]);

const onMouseDown = (e) => {
if (selectedTool == "select" || selectedTool == "frame") {
Expand Down Expand Up @@ -816,15 +802,15 @@ export default function Canvas({
navDrag.current = null;
return;
}
frame.actions.setVisibleWindowCenter(frame.id, evtToData(e));
frame.actions.setViewportCenter(frame.id, evtToData(e));
return;
}
if (!readOnly) {
handleClick(e);
}
}}
onScroll={() => {
updateVisibleWindow();
updateViewport();
saveCenterPosition();
}}
onMouseDown={onMouseDown}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface Props {
element: Element;
focused: boolean;
canvasScale: number;
readOnly?: boolean;
}

export default function Render(props: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import type { Element } from "../types";
interface Props {
element: Element;
focused?: boolean;
readOnly?: boolean;
}

function getTime(): number {
return webapp_client.server_time() - 0;
}

export default function Stopwatch({ element, focused }: Props) {
export default function Stopwatch({ element, focused, readOnly }: Props) {
const { actions } = useFrameContext();
const eltRef = useRef<Element>(element);
eltRef.current = element;
Expand All @@ -37,6 +38,7 @@ export default function Stopwatch({ element, focused }: Props) {
return (
<>
<StopwatchEditor
readOnly={readOnly}
noLabel
noDelete
compact
Expand Down

0 comments on commit 871ab65

Please sign in to comment.