Skip to content

Commit

Permalink
Support URL API (#72)
Browse files Browse the repository at this point in the history
* Support URL API

* Drop blitz dep
  • Loading branch information
tmcw committed May 26, 2024
1 parent a77fd50 commit 24fbf52
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 23 deletions.
3 changes: 0 additions & 3 deletions packages/play/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const config = require("@blitzjs/next/eslint");

module.exports = {
...config,
env: {
browser: true,
es2021: true,
Expand Down
87 changes: 85 additions & 2 deletions packages/play/app/components/placemark_play.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import React, {
Suspense,
useCallback,
useContext,
useEffect,
useLayoutEffect,
useRef,
useState,
Expand All @@ -38,8 +39,8 @@ import {
ViewHorizontalIcon,
} from "@radix-ui/react-icons";
import { Button, StyledTooltipArrow, TContent } from "./elements";
import { atom, useAtom, useAtomValue } from "jotai";
import { splitsAtom, tabAtom, TabOption } from "state/jotai";
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
import { dialogAtom, splitsAtom, tabAtom, TabOption } from "state/jotai";
import clsx from "clsx";
import {
DndContext,
Expand All @@ -51,6 +52,11 @@ import {
import { restrictToWindowEdges } from "@dnd-kit/modifiers";
import debounce from "lodash/debounce";
import { useAtomCallback } from "jotai/utils";
import { useSearchParams } from "next/navigation";
import { useImportFile, useImportString } from "app/hooks/use_import";
import toast from "react-hot-toast";
import { DEFAULT_IMPORT_OPTIONS, detectType } from "app/lib/convert";
import { match } from "ts-pattern";

type ResolvedLayout = "HORIZONTAL" | "VERTICAL" | "FLOATING";

Expand All @@ -64,6 +70,82 @@ const persistentTransformAtom = atom<Transform>({
y: 5,
});

function UrlAPI() {
const doImportString = useImportString();
const setDialogState = useSetAtom(dialogAtom);
const doImportFile = useImportFile();
const searchParams = useSearchParams();
const load = searchParams?.get("load");
const done = useRef<boolean>(false);

useEffect(() => {
if (load && !done.current) {
done.current = true;
(async () => {
try {
const url = new URL(load);
if (url.protocol === "https:") {
const res = await fetch(url);
const buffer = await res.arrayBuffer();
const file = new File(
[buffer],
url.pathname.split("/").pop() || "",
{
type: res.headers.get("Content-Type") || "",
}
);
const options = (await detectType(file)).unsafeCoerce();
doImportFile(file, options, () => {});
} else if (url.protocol === "data:") {
console.log(url);
const [description, ...parts] = url.pathname.split(",");
const data = parts.join(",");
const [type, encoding] = description.split(";", 2) as [
string,
string | undefined
];

let decoded = match(encoding)
.with(undefined, () => decodeURIComponent(data))
.with("base64", () => atob(data))
.otherwise(() => {
throw new Error("Unknown encoding in data url");
});

if (type === "application/json") {
doImportString(
decoded,
{
...DEFAULT_IMPORT_OPTIONS,
type: "geojson",
},
(...args) => {
console.log(args);
}
);
} else {
setDialogState({
type: "load_text",
initialValue: decoded,
});
}
} else {
toast.error(
"Couldn’t handle this ?load argument - urls and data urls are supported"
);
}
} catch (e) {
toast.error(
e instanceof Error ? e.message : "Failed to load data from URL"
);
}
})();
}
}, [load, doImportString, doImportFile]);

return null;
}

export function PlacemarkPlay() {
const [map, setMap] = useState<PMap | null>(null);
useWindowResizeSplits();
Expand Down Expand Up @@ -171,6 +253,7 @@ export function PlacemarkPlay() {
) : null}
</div>
<Drop />
<UrlAPI />
<Dialogs />
<Suspense fallback={null}>
<Keybindings />
Expand Down
38 changes: 20 additions & 18 deletions packages/play/app/hooks/use_import.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,26 @@ export function useImportString() {
name: string = "Imported text",
existingFolderId?: string
) => {
return (
await stringToGeoJSON(text, options, Comlink.proxy(progress))
).map(async (result) => {
await transact(
resultToTransact({
result,
file: { name },
track: [
"import-string",
{
format: "geojson",
},
],
existingFolderId,
})
);
return result;
});
return (await stringToGeoJSON(text, options, Comlink.proxy(progress)))
.map(async (result) => {
await transact(
resultToTransact({
result,
file: { name },
track: [
"import-string",
{
format: "geojson",
},
],
existingFolderId,
})
);
return result;
})
.mapLeft((e) => {
console.error(e);
});
},
[transact]
);
Expand Down

0 comments on commit 24fbf52

Please sign in to comment.