add create and edit pages, create Waku provider

This commit is contained in:
Sasha 2023-11-17 10:25:38 +03:00
parent 1abf528f75
commit 63f222d3cc
No known key found for this signature in database
8 changed files with 189 additions and 47 deletions

View File

@ -0,0 +1,51 @@
"use client";
import React from "react";
import { waku, Waku, WakuEvents } from "@/services/waku";
type WakuContextProps = {
status: string;
};
const WakuContext = React.createContext<WakuContextProps>({
status: "",
});
type WakuProviderProps = {
children: React.ReactNode;
};
export const useWaku = () => {
const { status } = React.useContext(WakuContext);
return { status };
};
export const WakuProvider = (props: WakuProviderProps) => {
const wakuRef = React.useRef<Waku>();
const [status, setStatus] = React.useState<string>("");
React.useEffect(() => {
if (wakuRef.current) {
return;
}
const statusListener = (event: CustomEvent) => {
setStatus(event.detail);
};
waku.addEventListener(WakuEvents.Status, statusListener);
waku.init().then(() => {
wakuRef.current = waku;
});
return () => {
waku.removeEventListener(WakuEvents.Status, statusListener);
};
}, [wakuRef, setStatus]);
return (
<WakuContext.Provider value={{ status }}>
{props.children}
</WakuContext.Provider>
);
};

View File

@ -0,0 +1,12 @@
"use client";
import { useWaku } from "@/app/WakuProvider";
export default function Create() {
const { status } = useWaku();
return (
<div>
<p>{status}</p>
</div>
);
}

View File

@ -0,0 +1,48 @@
"use client";
import React from "react";
import Markdown from "react-markdown";
import { useRouter } from "next/navigation";
import { useNoteHash } from "@/hooks/useNoteHash";
const t = `
### Problem
Cannot read data returned from REST API in browser if request is done with CORS violation.
# Impact
Prevents browsers from querying REST API.
### To reproduce
0. Run nwaku REST API
1. Copy https://github.com/waku-org/waku-frontend/tree/weboko/follow-up
5. Wait for 10 seconds and see in console following error:
It happens even though the request succeds.
### Expected behavior
Error should not happen.
### Additional context
What happens is that browser implements Fetch API in the manner that when request is made to resource with CORS violation then even if it would succeed - client won't be able to read response data.
Spec of the Fetch API - https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
### The fix
Considering we expect REST API to be run only on localhost we should add following HTTP header to allow web apps run on different port to be able to talk to the API.
`;
const View = () => {
const router = useRouter();
const noteHash = useNoteHash();
React.useEffect(() => {
if (!noteHash) {
router.replace("/404");
}
}, [noteHash]);
return <Markdown>{t}</Markdown>;
};
export default View;

View File

@ -1,14 +1,12 @@
import type { Metadata } from "next";
"use client";
import React from "react";
import { Inter } from "next/font/google";
import { WakuProvider } from "@/app/WakuProvider";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Flush notes",
description: "An app to share notes",
};
export default function RootLayout({
children,
}: {
@ -16,7 +14,9 @@ export default function RootLayout({
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={inter.className}>
<WakuProvider>{children}</WakuProvider>
</body>
</html>
);
}

View File

@ -1,32 +1,22 @@
import Markdown from "react-markdown";
"use client";
const t = `
### Problem
Cannot read data returned from REST API in browser if request is done with CORS violation.
# Impact
Prevents browsers from querying REST API.
### To reproduce
0. Run nwaku REST API
1. Copy https://github.com/waku-org/waku-frontend/tree/weboko/follow-up
5. Wait for 10 seconds and see in console following error:
It happens even though the request succeds.
### Expected behavior
Error should not happen.
### Additional context
What happens is that browser implements Fetch API in the manner that when request is made to resource with CORS violation then even if it would succeed - client won't be able to read response data.
Spec of the Fetch API - https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
### The fix
Considering we expect REST API to be run only on localhost we should add following HTTP header to allow web apps run on different port to be able to talk to the API.
`;
import { useWaku } from "@/app/WakuProvider";
import { useRouter } from "next/navigation";
export default function Home() {
return <Markdown>{t}</Markdown>;
const { status } = useWaku();
const router = useRouter();
return (
<div>
<p>{status}</p>
<button
onClick={() => {
router.push("/create");
}}
>
Create new
</button>
<button>Edit existing</button>
</div>
);
}

View File

@ -3,7 +3,7 @@
import React from "react";
import Markdown from "react-markdown";
import { useRouter } from "next/navigation";
import { useViewHash } from "@/hooks/useViewHash";
import { useNoteHash } from "@/hooks/useNoteHash";
const t = `
### Problem
@ -34,7 +34,7 @@ Considering we expect REST API to be run only on localhost we should add followi
const View = () => {
const router = useRouter();
const noteHash = useViewHash();
const noteHash = useNoteHash();
React.useEffect(() => {
if (!noteHash) {

View File

@ -1,6 +1,6 @@
import { usePathname } from "next/navigation";
export const useViewHash = (): undefined | string => {
export const useNoteHash = (): undefined | string => {
const pathname = usePathname();
const segments = pathname.split("/");
const viewIndex = segments.indexOf("view");

View File

@ -1,18 +1,59 @@
import { LightNode, createLightNode } from "@waku/sdk";
"use client";
type WakuOptions = {
node: LightNode;
};
import { LightNode, createLightNode, waitForRemotePeer } from "@waku/sdk";
type EventListener = (event: CustomEvent) => void;
export enum WakuEvents {
Status = "status",
}
export class Waku {
private node: undefined | LightNode;
private constructor(options: WakuOptions) {
this.node = options.node;
private emitter = new EventTarget();
private initialized: boolean = false;
private initializing: boolean = false;
constructor() {}
public async init(): Promise<void> {
if (this.initialized || this.initializing) {
return;
}
this.initializing = true;
console.log("Waku");
try {
this.emitStatusEvent("Initializing...");
const node = await createLightNode({ defaultBootstrap: true });
await node.start();
this.emitStatusEvent("Waiting for peers...");
await waitForRemotePeer(node);
this.node = node;
this.initialized = true;
this.emitStatusEvent("Connected");
} catch (error) {
console.error("Failed to initialize Waku node:", error);
this.emitStatusEvent("Failed to initialize(see logs)");
}
this.initializing = false;
}
public static async init(): Promise<Waku> {
const node = await createLightNode({ defaultBootstrap: true });
return new Waku({ node });
public addEventListener(event: WakuEvents, fn: EventListener) {
return this.emitter.addEventListener(event, fn as any);
}
public removeEventListener(event: WakuEvents, fn: EventListener) {
return this.emitter.removeEventListener(event, fn as any);
}
private emitStatusEvent(payload: string) {
console.log(payload);
this.emitter.dispatchEvent(
new CustomEvent(WakuEvents.Status, { detail: payload })
);
}
}
export const waku = new Waku();