Skip to content

Commit

Permalink
add hash sharing
Browse files Browse the repository at this point in the history
  • Loading branch information
arlyon committed Jun 10, 2024
1 parent cb3ac9c commit 7926516
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 3 deletions.
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion site/components/plugin-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { SVGProps } from "react";
import { AddButton } from "./add-button";
import { SchemaEditor } from "./shema-editor";
import { Button } from "./ui/button";
import { ShareButton } from "./share-button";

export type Plugin = {
title: string;
Expand Down Expand Up @@ -129,7 +130,7 @@ export function PluginPage(
</div>
<h3 className="text-lg font-medium flex items-end justify-between">
<span>Configuration</span>
<Button variant="ghost">Share</Button>
<ShareButton />
</h3>
<SchemaEditor id={id} schema={props.configSchema} />
</div>
Expand Down
12 changes: 12 additions & 0 deletions site/components/share-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"use client";

import { Button } from "./ui/button";

export const ShareButton = () => (
<Button
variant="ghost"
onClick={() => navigator.clipboard.writeText(window.location.toString())}
>
Share
</Button>
);
36 changes: 34 additions & 2 deletions site/components/shema-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"use client";

import Ajv from "ajv";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import z from "zod";
import { CopyBox } from "./copy-box";
import { Input } from "./ui/input";
import { useRouter } from "next/navigation";
import { useHashState } from "@/hooks/use-hash";

const configSchema = (name: string) =>
z.object({
Expand All @@ -25,9 +27,21 @@ const configSchema = (name: string) =>
});

export const SchemaEditor = ({ id, schema: schemaString }) => {
const page = useRouter();
const [hash, setHash] = useHashState({});

let defaultData = {};
if (hash) {
try {
defaultData = JSON.parse(window.atob(hash)).instance;
} catch (e) {
setHash(null);
}
}

const form = useForm({
defaultValues: {
config: {},
config: defaultData,
plugin: id,
},
});
Expand All @@ -47,6 +61,24 @@ export const SchemaEditor = ({ id, schema: schemaString }) => {
);
const [addCommand, setAddCommand] = useState<string | null>(null);

useEffect(() => {
if (addCommand) {
setHash(addCommand);
}
}, [addCommand]);

useEffect(() => {
if (hash) {
try {
const data = JSON.parse(window.atob(hash));
const dataInner = data.instance;
form.setValue("config", dataInner);
} catch (e) {
// no-op
}
}
}, [hash]);

const schemaData = JSON.parse(schemaString);
const schema = configSchema(id).safeParse(schemaData);
if (!schema.success) {
Expand Down
50 changes: 50 additions & 0 deletions site/hooks/use-hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";

import { useEffect, useMemo, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import queryString from "query-string";

// How do I get the pathname with hash.
// source: https://github.com/vercel/next.js/discussions/49465
export const useHashState = ({ scroll }: { scroll?: boolean }) => {
const getCurrentHash = useMemo(
() => () =>
typeof window !== "undefined"
? window.location.hash.replace(/^#!?/, "")
: "",
[],
);
const router = useRouter();
const params = useParams();
const [hash, _setHash] = useState<string | null>(getCurrentHash());

const setHash = (newHash: string | null) => {
let updatedUrl = window.location.href;
updatedUrl = queryString.stringifyUrl({
url: updatedUrl.split("#")[0],
fragmentIdentifier: newHash,
});

_setHash(newHash);
router.replace(updatedUrl, { scroll });
};
useEffect(() => {
const currentHash = getCurrentHash();
_setHash(currentHash);
}, [params]);

const handleHashChange = () => {
const currentHash = getCurrentHash();
_setHash(currentHash);
};

useEffect(() => {
window.addEventListener("hashchange", handleHashChange);

return () => {
window.removeEventListener("hashchange", handleHashChange);
};
}, []);

return [hash, setHash] as const;
};
1 change: 1 addition & 0 deletions site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"next": "^15.0.0-rc.0",
"next-axiom": "^1.2.0",
"next-themes": "^0.3.0",
"query-string": "^9.0.0",
"react": "19.0.0-rc-f994737d14-20240522",
"react-dom": "19.0.0-rc-f994737d14-20240522",
"react-hook-form": "^7.51.4",
Expand Down

0 comments on commit 7926516

Please sign in to comment.