[debug] 2

arnost/scroll-in-read-only-links
dwelle 1 year ago
parent 72de65e482
commit d5f55aba44

@ -27,6 +27,7 @@ import {
LiveCollaborationTrigger,
TTDDialog,
TTDDialogTrigger,
getCommonBounds,
} from "../packages/excalidraw/index";
import {
AppState,
@ -35,6 +36,7 @@ import {
BinaryFiles,
ExcalidrawInitialDataState,
UIAppState,
ScrollConstraints,
} from "../packages/excalidraw/types";
import {
debounce,
@ -98,15 +100,161 @@ import { useAtomWithInitialValue } from "../packages/excalidraw/jotai";
import { appJotaiStore } from "./app-jotai";
import "./index.scss";
import { ResolutionType } from "../packages/excalidraw/utility-types";
import { Merge, ResolutionType } from "../packages/excalidraw/utility-types";
import { ShareableLinkDialog } from "../packages/excalidraw/components/ShareableLinkDialog";
import { openConfirmModal } from "../packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "../packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm";
import Trans from "../packages/excalidraw/components/Trans";
import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog";
import { getSelectedElements } from "../packages/excalidraw/scene";
polyfill();
type DebugScrollConstraints = Merge<
ScrollConstraints,
{ viewportZoomFactor: number; enabled: boolean }
>;
const ConstraintsSettings = ({
initialConstraints,
excalidrawAPI,
}: {
initialConstraints: DebugScrollConstraints;
excalidrawAPI: ExcalidrawImperativeAPI;
}) => {
const [constraints, setConstraints] =
useState<DebugScrollConstraints>(initialConstraints);
useEffect(() => {
// add JSON-stringified constraints into url hash for easy sharing
const hash = new URLSearchParams(window.location.hash.slice(1));
hash.set(
"constraints",
encodeURIComponent(
window.btoa(JSON.stringify(constraints)).replace(/=+/, ""),
),
);
window.location.hash = decodeURIComponent(hash.toString());
}, [constraints]);
const [selection, setSelection] = useState<ExcalidrawElement[]>([]);
useEffect(() => {
return excalidrawAPI.onChange((elements, appState) => {
setSelection(getSelectedElements(elements, appState));
});
}, [excalidrawAPI]);
return (
<div
style={{
display: "flex",
position: "fixed",
bottom: 10,
left: "calc(50%)",
transform: "translateX(-50%)",
gap: "0.6rem",
zIndex: 999999,
}}
>
enabled:{" "}
<input
type="checkbox"
defaultChecked={!!constraints.enabled}
onChange={(e) =>
setConstraints((s) => ({ ...s, enabled: e.target.checked }))
}
/>
x:{" "}
<input
placeholder="x"
size={4}
value={constraints.x.toString()}
onChange={(e) =>
setConstraints((s) => ({
...s,
x: parseInt(e.target.value) ?? 0,
}))
}
/>
y:{" "}
<input
placeholder="y"
size={4}
value={constraints.y.toString()}
onChange={(e) =>
setConstraints((s) => ({
...s,
y: parseInt(e.target.value) ?? 0,
}))
}
/>
w:{" "}
<input
placeholder="width"
size={4}
value={constraints.width.toString()}
onChange={(e) =>
setConstraints((s) => ({
...s,
x: parseInt(e.target.value) ?? 200,
}))
}
/>
h:{" "}
<input
placeholder="height"
size={4}
value={constraints.height.toString()}
onChange={(e) =>
setConstraints((s) => ({
...s,
x: parseInt(e.target.value) ?? 200,
}))
}
/>
zoomFactor:
<input
placeholder="height"
type="number"
min="0.1"
max="1"
step="0.1"
value={constraints.viewportZoomFactor.toString()}
onChange={(e) =>
setConstraints((s) => ({
...s,
viewportZoomFactor: parseFloat(e.target.value.toString()) ?? 0.7,
}))
}
/>
lockZoom:{" "}
<input
type="checkbox"
defaultChecked={!!constraints.lockZoom}
onChange={(e) =>
setConstraints((s) => ({ ...s, lockZoom: e.target.checked }))
}
/>
{selection.length > 0 && (
<button
onClick={() => {
const bbox = getCommonBounds(selection);
setConstraints((s) => ({
...s,
x: Math.round(bbox[0]),
y: Math.round(bbox[1]),
width: Math.round(bbox[2] - bbox[0]),
height: Math.round(bbox[3] - bbox[1]),
}));
}}
>
use selection
</button>
)}
</div>
);
};
window.EXCALIDRAW_THROTTLE_RENDER = true;
let isSelfEmbedding = false;
@ -151,10 +299,22 @@ const initializeScene = async (opts: {
)
> => {
const searchParams = new URLSearchParams(window.location.search);
const hashParams = new URLSearchParams(window.location.hash.slice(1));
const id = searchParams.get("id");
const jsonBackendMatch = window.location.hash.match(
/^#json=([a-zA-Z0-9_-]+),([a-zA-Z0-9_-]+)$/,
);
const shareableLink = hashParams.get("json")?.split(",");
if (shareableLink) {
hashParams.delete("json");
const hash = `#${decodeURIComponent(hashParams.toString())}`;
window.history.replaceState(
{},
APP_NAME,
`${window.location.origin}${hash}`,
);
}
console.log({ shareableLink });
const externalUrlMatch = window.location.hash.match(/^#url=(.*)$/);
const localDataState = importFromLocalStorage();
@ -164,7 +324,7 @@ const initializeScene = async (opts: {
} = await loadScene(null, null, localDataState);
let roomLinkData = getCollaborationLinkData(window.location.href);
const isExternalScene = !!(id || jsonBackendMatch || roomLinkData);
const isExternalScene = !!(id || shareableLink || roomLinkData);
if (isExternalScene) {
if (
// don't prompt if scene is empty
@ -174,16 +334,17 @@ const initializeScene = async (opts: {
// otherwise, prompt whether user wants to override current scene
(await openConfirmModal(shareableLinkConfirmDialog))
) {
if (jsonBackendMatch) {
if (shareableLink) {
scene = await loadScene(
jsonBackendMatch[1],
jsonBackendMatch[2],
shareableLink[0],
shareableLink[1],
localDataState,
);
console.log(">>>>", scene);
}
scene.scrollToContent = true;
if (!roomLinkData) {
window.history.replaceState({}, APP_NAME, window.location.origin);
// window.history.replaceState({}, APP_NAME, window.location.origin);
}
} else {
// https://github.com/excalidraw/excalidraw/issues/1919
@ -200,7 +361,7 @@ const initializeScene = async (opts: {
}
roomLinkData = null;
window.history.replaceState({}, APP_NAME, window.location.origin);
// window.history.replaceState({}, APP_NAME, window.location.origin);
}
} else if (externalUrlMatch) {
window.history.replaceState({}, APP_NAME, window.location.origin);
@ -261,12 +422,12 @@ const initializeScene = async (opts: {
key: roomLinkData.roomKey,
};
} else if (scene) {
return isExternalScene && jsonBackendMatch
return isExternalScene && shareableLink
? {
scene,
isExternalScene,
id: jsonBackendMatch[1],
key: jsonBackendMatch[2],
id: shareableLink[0],
key: shareableLink[1],
}
: { scene, isExternalScene: false };
}
@ -672,6 +833,31 @@ const ExcalidrawWrapper = () => {
[setShareDialogState],
);
const [constraints] = useState<DebugScrollConstraints>(() => {
const stored = new URLSearchParams(location.hash.slice(1)).get(
"constraints",
);
let storedConstraints = {};
if (stored) {
try {
storedConstraints = JSON.parse(window.atob(stored));
} catch {}
}
return {
x: 0,
y: 0,
width: document.body.clientWidth,
height: document.body.clientHeight,
lockZoom: false,
viewportZoomFactor: 0.7,
enabled: true,
...storedConstraints,
};
});
console.log(constraints);
// browsers generally prevent infinite self-embedding, there are
// cases where it still happens, and while we disallow self-embedding
// by not whitelisting our own origin, this serves as an additional guard
@ -753,14 +939,14 @@ const ExcalidrawWrapper = () => {
/>
);
}}
scrollConstraints={{
x: 0,
y: 0,
width: 2560,
height: 1300,
lockZoom: false,
}}
scrollConstraints={constraints.enabled ? constraints : undefined}
>
{excalidrawAPI && (
<ConstraintsSettings
excalidrawAPI={excalidrawAPI}
initialConstraints={constraints}
/>
)}
<AppMainMenu
onCollabDialogOpen={onCollabDialogOpen}
isCollaborating={isCollaborating}

@ -77,7 +77,7 @@ const calculateZoomLevel = (
width: AppState["width"],
height: AppState["height"],
) => {
const DEFAULT_VIEWPORT_ZOOM_FACTOR = 0.7;
const DEFAULT_VIEWPORT_ZOOM_FACTOR = 0.2;
const viewportZoomFactor = scrollConstraints.viewportZoomFactor
? Math.min(1, Math.max(scrollConstraints.viewportZoomFactor, 0.1))

Loading…
Cancel
Save