diff --git a/package.json b/package.json
index fd5b388..5d0dbcc 100644
--- a/package.json
+++ b/package.json
@@ -11,5 +11,17 @@
"packageManager": "yarn@3.2.3",
"resolutions": {
"zk-regex-sdk": "portal:/Users/savitar/Projects/opensource/proof-of-twitter/packages/app/zk-regex-sdk"
+ },
+ "devDependencies": {
+ "autoprefixer": "^10.4.19",
+ "postcss": "^8.4.40",
+ "react-router-dom": "^6.26.0",
+ "tailwindcss": "^3.4.7"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.13.0",
+ "@emotion/styled": "^11.13.0",
+ "@mui/icons-material": "^5.16.6",
+ "@mui/material": "^5.16.6"
}
}
diff --git a/packages/app/index.css b/packages/app/index.css
index 4bf1c5d..7d348f2 100644
--- a/packages/app/index.css
+++ b/packages/app/index.css
@@ -2,11 +2,15 @@
@tailwind components;
@tailwind utilities;
+:root {
+ font-family: "Space Grotesk", sans-serif;
+ background-color: #ffbfbf;
+ background: radial-gradient(70.71% 70.71% at 50% 50%, #FFF 19%, rgba(255, 255, 255, 0.00) 61%), linear-gradient(38deg, rgba(255, 255, 255, 0.00) 60%, rgba(255, 255, 255, 0.69) 100%), linear-gradient(45deg, #FFF 10%, rgba(255, 255, 255, 0.00) 23.5%), linear-gradient(36deg, #FFF 12.52%, rgba(255, 255, 255, 0.00) 76.72%), linear-gradient(214deg, rgba(255, 255, 255, 0.00) 0%, rgba(255, 220, 234, 0.40) 37.53%, rgba(255, 255, 255, 0.00) 71%), linear-gradient(212deg, rgba(255, 255, 255, 0.00) 15%, #E4F1FE 72.5%, rgba(255, 255, 255, 0.00) 91.5%);
+}
+
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
+ font-family: "Space Grotesk", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
diff --git a/packages/app/index.html b/packages/app/index.html
index 10746d0..a9cc814 100644
--- a/packages/app/index.html
+++ b/packages/app/index.html
@@ -39,6 +39,17 @@
window.process = process;
window.setImmediate = setImmediate;
+
+
+
+
+
+
+
+
+
diff --git a/packages/app/proofWorker.js b/packages/app/proofWorker.js
new file mode 100644
index 0000000..025b29f
--- /dev/null
+++ b/packages/app/proofWorker.js
@@ -0,0 +1,19 @@
+// src/proofWorker.js
+
+import { generateProof } from "@zk-email/helpers/dist/zkp";
+
+self.onmessage = async (e) => {
+ const { input, circuitArtifactsUrl, circuitName } = e.data;
+
+ try {
+ const { proof, publicSignals } = await generateProof(
+ input,
+ circuitArtifactsUrl,
+ circuitName
+ );
+
+ self.postMessage({ proof, publicSignals });
+ } catch (error) {
+ self.postMessage({ error: error.message });
+ }
+};
diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index 29676be..34703f8 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -1,4 +1,82 @@
+// import { MainPage } from "./pages/MainPage";
+// import "./styles.css";
+// import {
+// BrowserRouter as Router,
+// Route,
+// Routes,
+// Link,
+// } from "react-router-dom";
+// import { useLocation } from "react-use";
+// import styled from "styled-components";
+// import { ConnectButton } from "@rainbow-me/rainbowkit";
+
+// const NavSection = () => {
+// const { pathname } = useLocation();
+
+// return (
+//
+// );
+// };
+
+// const App = () => {
+// return (
+//
+//
+//
+
+//
+// } />
+// Not found>} />
+//
+//
+//
+// );
+// };
+
+// export default App;
+
+// const Logo = styled(Link)`
+// text-transform: uppercase;
+// letter-spacing: 0.04em;
+// color: #fff;
+// text-decoration: none;
+// font-size: 1.2rem;
+// `;
+
+// const Nav = styled.nav`
+// display: flex;
+// align-items: center;
+// justify-content: space-between;
+// margin: 12px;
+// `;
+
+// const DocsLink = styled.a`
+// color: rgba(255, 255, 255, 0.8);
+// text-decoration: none;
+// underline: none;
+// transition: all 0.2s ease-in-out;
+// &:hover {
+// color: rgba(255, 255, 255, 1);
+// }
+// `;
+
+
import { MainPage } from "./pages/MainPage";
+import AboutPage from "./pages/AboutPage";
import "./styles.css";
import {
BrowserRouter as Router,
@@ -10,36 +88,16 @@ import { useLocation } from "react-use";
import styled from "styled-components";
import { ConnectButton } from "@rainbow-me/rainbowkit";
-const NavSection = () => {
- const { pathname } = useLocation();
-
- return (
-
- );
-};
const App = () => {
+ const { pathname } = useLocation();
return (
-
} />
+ } />
Not found>} />
@@ -49,27 +107,3 @@ const App = () => {
export default App;
-const Logo = styled(Link)`
- text-transform: uppercase;
- letter-spacing: 0.04em;
- color: #fff;
- text-decoration: none;
- font-size: 1.2rem;
-`;
-
-const Nav = styled.nav`
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin: 12px;
-`;
-
-const DocsLink = styled.a`
- color: rgba(255, 255, 255, 0.8);
- text-decoration: none;
- underline: none;
- transition: all 0.2s ease-in-out;
- &:hover {
- color: rgba(255, 255, 255, 1);
- }
-`;
diff --git a/packages/app/src/components/Accordion.tsx b/packages/app/src/components/Accordion.tsx
new file mode 100644
index 0000000..f179332
--- /dev/null
+++ b/packages/app/src/components/Accordion.tsx
@@ -0,0 +1,97 @@
+import React, { FC } from 'react';
+import {
+ Accordion as MuiAccordion,
+ AccordionSummary,
+ AccordionDetails,
+ Typography,
+ styled,
+} from '@mui/material';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+
+// Define the props types
+interface AccordionProps {
+ title: string;
+ contents: string;
+ alignment?: 'left' | 'right';
+}
+
+const CustomAccordion = styled(MuiAccordion)(({ theme }) => ({
+ marginBottom: theme.spacing(2),
+ '&:before': {
+ display: 'none',
+ },
+ background: 'inherit',
+ boxShadow: 'none',
+ borderBottom: '1px solid rgba(0, 0, 0, 0.12)',
+ '& .MuiAccordionSummary-root': {
+ backgroundColor: 'rgba(0, 0, 0, 0)',
+ '&:hover .MuiAccordionSummary-expandIconWrapper': {
+ color: theme.palette.secondary.main,
+ },
+ },
+ '& .MuiAccordionSummary-content': {
+ margin: 0,
+ display: 'flex',
+ alignItems: 'center',
+ width: '100%',
+ },
+ '& .MuiAccordionSummary-expandIconWrapper': {
+ marginRight: theme.spacing(1),
+ transition: 'transform 0.2s',
+ },
+ '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': {
+ transform: 'rotate(180deg)',
+ },
+ '& .MuiAccordionDetails-root': {
+ padding: theme.spacing(2),
+ },
+}));
+
+const Accordion: FC = ({ title, contents, alignment = 'left' }) => {
+ return (
+
+ }
+ aria-controls="panel-content"
+ id="panel-header"
+ sx={{
+ flexDirection: alignment === 'right' ? 'row-reverse' : 'row',
+ justifyContent: alignment === 'right' ? 'space-between' : 'flex-start',
+ '& .MuiAccordionSummary-expandIconWrapper': {
+ order: alignment === 'right' ? 2 : 1,
+ marginRight: alignment === 'right' ? 0 : 1,
+ marginLeft: alignment === 'right' ? 1 : 0,
+ },
+ width: '100%',
+ }}
+ >
+
+ {title}
+
+
+
+
+ {contents}
+
+
+
+ );
+};
+
+export default Accordion;
\ No newline at end of file
diff --git a/packages/app/src/components/Button.tsx b/packages/app/src/components/Button.tsx
index 385498f..a2922e8 100644
--- a/packages/app/src/components/Button.tsx
+++ b/packages/app/src/components/Button.tsx
@@ -1,10 +1,99 @@
+// import styled from "styled-components";
+
+// export const Button = styled.button`
+// padding: 0 14px;
+// border-radius: 4px;
+// background: #8272e4;
+// border: none;
+// display: flex;
+// align-items: center;
+// justify-content: center;
+// font-weight: 600;
+// font-size: 0.9rem;
+// letter-spacing: -0.02em;
+// color: #fff;
+// cursor: pointer;
+// height: 48px;
+// width: 100%;
+// min-width: 32px;
+// transition: all 0.2s ease-in-out;
+// &:hover {
+// background: #9b8df2;
+// }
+// &:disabled {
+// opacity: 0.5;
+// cursor: not-allowed;
+// }
+// `;
+
+// export const OutlinedButton = styled.button`
+// padding: 0 14px;
+// border-radius: 4px;
+// border: none;
+// display: flex;
+// align-items: center;
+// justify-content: center;
+// font-weight: 500;
+// font-size: 0.9rem;
+// letter-spacing: -0.02em;
+// color: #8272e4;
+// cursor: pointer;
+// height: 48px;
+// width: 100%;
+// min-width: 32px;
+// transition: all 0.2s ease-in-out;
+// background: transparent;
+// border: 1px solid #8272e4;
+// &:hover {
+// background: #9b8df2;
+// color: white;
+// }
+// &:disabled {
+// opacity: 0.5;
+// cursor: not-allowed;
+// }
+// `;
+
+
+// export const TextButton = styled.button`
+// width: fit-content;
+// background: transparent;
+// border: none;
+// color: white;
+// font-weight: 500;
+// padding: 4px 16px;
+// border-radius: 4px;
+// &:hover {
+// background: #00000020;
+// color: white;
+// }
+// &:disabled {
+// opacity: 0.5;
+// cursor: not-allowed;
+// }
+// `;
+
+
+
+
+import React from 'react';
import styled from "styled-components";
+import { useTheme, Button as MuiButton } from "@mui/material";
+
+interface ButtonProps {
+ highlighted?: boolean;
+ disabled?: boolean;
+ onClick?: () => void;
+ children: React.ReactNode;
+ endIcon?: React.ReactNode;
+ href?: string;
+ target?: string;
+}
-export const Button = styled.button`
+const StyledButton = styled(MuiButton)<{ highlighted: boolean }>`
padding: 0 14px;
- border-radius: 4px;
- background: #8272e4;
- border: none;
+ text-transform: none;
+ border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
@@ -17,58 +106,175 @@ export const Button = styled.button`
width: 100%;
min-width: 32px;
transition: all 0.2s ease-in-out;
+ background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')};
+
&:hover {
- background: #9b8df2;
+ background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')};
+ opacity: 0.5;
}
+
&:disabled {
opacity: 0.5;
cursor: not-allowed;
+ color: ${({ highlighted, theme }) => (highlighted ? '#ffffff' : 'grey')};
+ }
+
+ @media (max-width: 600px) {
+ font-size: 0.8rem;
+ padding: 0 12px;
+ }
+
+ @media (max-width: 400px) {
+ font-size: 0.6rem;
+ padding: 0 5px;
+ height: 42px;
}
`;
-export const OutlinedButton = styled.button`
+const StyledOutlinedButton = styled(MuiButton)<{ highlighted: boolean }>`
padding: 0 14px;
- border-radius: 4px;
- border: none;
+ border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 0.9rem;
letter-spacing: -0.02em;
- color: #8272e4;
+ text-transform: none;
cursor: pointer;
height: 48px;
width: 100%;
min-width: 32px;
transition: all 0.2s ease-in-out;
- background: transparent;
- border: 1px solid #8272e4;
+ background: '#ffffff';
+ border: 1px solid ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')};
+ color: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')};
+
&:hover {
- background: #9b8df2;
+ background: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : '#1C1C1C')};
color: white;
}
+
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
+
+ @media (max-width: 600px) {
+ font-size: 0.8rem;
+ padding: 0 12px;
+ }
+
+ @media (max-width: 400px) {
+ font-size: 0.6rem;
+ padding: 0 5px;
+ height: 42px;
+ }
`;
+const StyledTextButton = styled(MuiButton)<{ highlighted: boolean }>`
+ width: fit-content;
+ background: '#ffffff';
+ border: none;
+ color: ${({ highlighted, theme }) => (highlighted ? theme.palette.accent.main : theme.palette.secondary.main)};
+ font-weight: 500;
+ padding: 4px 16px;
+ border-radius: 9px;
-export const TextButton = styled.button`
-width: fit-content;
-background: transparent;
-border: none;
-color: white;
-font-weight: 500;
-padding: 4px 16px;
-border-radius: 4px;
&:hover {
- background: #00000020;
- color: white;
+ color: theme.palette.secondary.main;
}
+
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
+
+ @media (max-width: 600px) {
+ font-size: 0.8rem;
+ padding: 2px 12px;
+ }
+
+ @media (max-width: 400px) {
+ font-size: 0.6rem;
+ padding: 2px 10px;
+ height: 42px;
+ }
`;
+
+export const Button: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => {
+ const theme = useTheme();
+
+ const handleClick = (e: React.MouseEvent) => {
+ if (disabled) return;
+ if (href) {
+ window.open(href, target);
+ } else if (onClick) {
+ onClick();
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const OutlinedButton: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => {
+ const theme = useTheme();
+
+ const handleClick = (e: React.MouseEvent) => {
+ if (disabled) return;
+ if (href) {
+ window.open(href, target);
+ } else if (onClick) {
+ onClick();
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const TextButton: React.FC = ({ highlighted = false, disabled, onClick, children, endIcon, href, target }) => {
+ const theme = useTheme();
+
+ const handleClick = (e: React.MouseEvent) => {
+ if (disabled) return;
+ if (href) {
+ window.open(href, target);
+ } else if (onClick) {
+ onClick();
+ }
+ };
+
+ return (
+
+ {children}
+ {endIcon && {endIcon}}
+
+ );
+};
+
diff --git a/packages/app/src/components/DragAndDropTextBox.tsx b/packages/app/src/components/DragAndDropTextBox.tsx
index 9f51137..8ef5525 100644
--- a/packages/app/src/components/DragAndDropTextBox.tsx
+++ b/packages/app/src/components/DragAndDropTextBox.tsx
@@ -1,20 +1,80 @@
+// import React from "react";
+// import styled from 'styled-components';
+// import { useDragAndDrop } from '../hooks/useDragAndDrop';
+
+// const DragAndDropTextBoxWrapper = styled.div`
+// display: flex;
+// flex-direction: column;
+// align-items: center;
+// border: 2px dashed #ccc;
+// padding: 20px;
+// `;
+
+// type Props = {
+// onFileDrop: (file: File) => void;
+// };
+
+// const DragAndDropTextBox: React.FC = ({onFileDrop}) => {
+// const {
+// dragging,
+// handleDragEnter,
+// handleDragLeave,
+// handleDragOver,
+// handleDrop,
+// handleDragEnd,
+// } = useDragAndDrop();
+
+// return (
+// handleDrop(e, onFileDrop)}
+// >
+// {dragging ? (
+// Drop here
+// ) : (
+// Drop .eml file here
+// )}
+//
+// );
+// };
+
+// export default DragAndDropTextBox;
+
+
+
+
+
import React from "react";
-import styled from 'styled-components';
+import styled, { css, ThemeProvider } from 'styled-components';
+import { useTheme } from "@mui/material/styles";
import { useDragAndDrop } from '../hooks/useDragAndDrop';
+import { Typography } from "@mui/material";
-const DragAndDropTextBoxWrapper = styled.div`
+const DragAndDropTextBoxWrapper = styled.div<{ highlighted: boolean }>`
display: flex;
flex-direction: column;
align-items: center;
border: 2px dashed #ccc;
padding: 20px;
+ ${({ highlighted, theme }) =>
+ highlighted
+ ? css`
+ border-color: ${theme.palette.accent.main};
+ color: ${theme.palette.accent.main}
+ `
+ : ''}
`;
type Props = {
onFileDrop: (file: File) => void;
+ highlighted?: boolean;
};
-const DragAndDropTextBox: React.FC = ({onFileDrop}) => {
+const DragAndDropTextBox: React.FC = ({ onFileDrop, highlighted = false }) => {
+ const theme = useTheme();
const {
dragging,
handleDragEnter,
@@ -25,20 +85,24 @@ const DragAndDropTextBox: React.FC = ({onFileDrop}) => {
} = useDragAndDrop();
return (
- handleDrop(e, onFileDrop)}
- >
- {dragging ? (
- Drop here
- ) : (
- Drop .eml file here
- )}
-
+
+ handleDrop(e, onFileDrop)}
+ >
+ {dragging ? (
+ Drop here
+ ) : (
+ Drop .eml file here
+ )}
+
+
);
};
export default DragAndDropTextBox;
+
diff --git a/packages/app/src/components/EmailInputMethod.tsx b/packages/app/src/components/EmailInputMethod.tsx
index 851b661..38f3ff0 100644
--- a/packages/app/src/components/EmailInputMethod.tsx
+++ b/packages/app/src/components/EmailInputMethod.tsx
@@ -1,12 +1,55 @@
-import { useState } from "react";
+// import { useState } from "react";
+// import { Button, OutlinedButton } from "./Button";
+
+// const EmailInputMethod = ({
+// onClickGoogle,
+// onClickEMLFile,
+// }: {
+// onClickGoogle: () => void;
+// onClickEMLFile: () => void;
+// }) => {
+// return (
+//
+//
+// or
+// {
+// onClickEMLFile();
+// }}
+// >
+// Upload email .eml file{" "}
+//
+//
+// );
+// };
+
+// export default EmailInputMethod;
+
+
+
import { Button, OutlinedButton } from "./Button";
-const EmailInputMethod = ({
- onClickGoogle,
- onClickEMLFile,
-}: {
+interface EmailInputMethodProps {
onClickGoogle: () => void;
onClickEMLFile: () => void;
+ highlighted?: boolean;
+ disabled?: boolean; // Optional disabled prop
+}
+
+const EmailInputMethod: React.FC = ({
+ onClickGoogle,
+ onClickEMLFile,
+ highlighted = false,
+ disabled = false, // Default value set to false
}) => {
return (
-
- or
- {
- onClickEMLFile();
- }}
- >
- Upload email .eml file{" "}
-
+
+ {!disabled && (
+ <>
+ or
+
+ Upload email .eml file{" "}
+
+ >
+ )}
);
};
diff --git a/packages/app/src/components/LabeledTextArea.tsx b/packages/app/src/components/LabeledTextArea.tsx
index 66112c6..2c72e2b 100644
--- a/packages/app/src/components/LabeledTextArea.tsx
+++ b/packages/app/src/components/LabeledTextArea.tsx
@@ -1,7 +1,110 @@
+// import _ from "lodash";
+// import React, { CSSProperties } from "react";
+// import styled from "styled-components";
+// import { Col } from "./Layout";
+
+// export const LabeledTextArea: React.FC<{
+// style?: CSSProperties;
+// className?: string;
+// label: string;
+// value: string;
+// warning?: string;
+// warningColor?: string;
+// disabled?: boolean;
+// disabledReason?: string;
+// secret?: boolean;
+// onChange?: React.ChangeEventHandler;
+// }> = ({
+// style,
+// warning,
+// warningColor,
+// disabled,
+// disabledReason,
+// label,
+// value,
+// onChange,
+// className,
+// secret,
+// }) => {
+// return (
+//
+//
+// {warning && (
+//
+// {warning}
+//
+// )}
+//
+
+// {secret && (
+// Hover to reveal public info sent to chain
+// )}
+//
+// );
+// };
+
+// const Label = styled.label`
+// color: rgba(255, 255, 255, 0.8);
+// `;
+
+// const LabeledTextAreaContainer = styled(Col)`
+// height: 15vh;
+// border-radius: 4px;
+// position: relative;
+// gap: 8px;
+// & .warning {
+// color: #bd3333;
+// font-size: 80%;
+// }
+// .secret {
+// position: absolute;
+// width: 100%;
+// height: 100%;
+// background: #171717;
+// border: 1px dashed rgba(255, 255, 255, 0.5);
+// color: rgba(255, 255, 255, 0.8);
+// user-select: none;
+// pointer-events: none;
+// opacity: 0.95;
+// justify-content: center;
+// display: flex;
+// align-items: center;
+// transition: opacity 0.3s ease-in-out;
+// }
+// &:hover .secret,
+// & :focus + .secret {
+// opacity: 0;
+// }
+// `;
+
+// const TextArea = styled.textarea`
+// border: 1px solid rgba(255, 255, 255, 0.3);
+// background: rgba(0, 0, 0, 0.3);
+// border-radius: 4px;
+// height: 480px;
+// padding: 16px;
+// transition: all 0.2s ease-in-out;
+// resize: none;
+// &:hover {
+// border: 1px solid rgba(255, 255, 255, 0.8);
+// `;
+
+
+
import _ from "lodash";
import React, { CSSProperties } from "react";
-import styled from "styled-components";
+import styled, { ThemeProvider, css } from "styled-components";
import { Col } from "./Layout";
+import { Box, Typography, useTheme } from "@mui/material";
export const LabeledTextArea: React.FC<{
style?: CSSProperties;
@@ -14,55 +117,61 @@ export const LabeledTextArea: React.FC<{
disabledReason?: string;
secret?: boolean;
onChange?: React.ChangeEventHandler;
+ highlighted?: boolean;
}> = ({
style,
warning,
warningColor,
- disabled,
+ disabled = false, // Default value set to false
disabledReason,
label,
value,
onChange,
className,
secret,
+ highlighted = false,
}) => {
+
+ const theme = useTheme();
+
return (
-
-
- {warning && (
-
- {warning}
-
- )}
-
-
- {secret && (
- Hover to reveal public info sent to chain
- )}
-
+
+
+ {label}
+
+ {warning && (
+
+ {warning}
+
+ )}
+
+
+
+ {secret && (
+ Hover to reveal public info sent to chain
+ )}
+
+
);
};
-const Label = styled.label`
- color: rgba(255, 255, 255, 0.8);
-`;
-
const LabeledTextAreaContainer = styled(Col)`
height: 15vh;
border-radius: 4px;
position: relative;
gap: 8px;
& .warning {
- color: #bd3333;
font-size: 80%;
}
.secret {
@@ -86,14 +195,34 @@ const LabeledTextAreaContainer = styled(Col)`
}
`;
-const TextArea = styled.textarea`
- border: 1px solid rgba(255, 255, 255, 0.3);
- background: rgba(0, 0, 0, 0.3);
- border-radius: 4px;
+const TextArea = styled.textarea<{ highlighted: boolean }>`
+ border: 0px solid #1C1C1C;
+ background: #F3F2F2;
+ border-radius: 10px;
+ color: ${({ theme }) => theme.palette.secondary.main};
height: 480px;
- padding: 16px;
- transition: all 0.2s ease-in-out;
- resize: none;
- &:hover {
- border: 1px solid rgba(255, 255, 255, 0.8);
+ padding: 16px;
+ transition: all 0.2s ease-in-out;
+ resize: none;
+ outline: none;
+
+ ${({ highlighted, theme }) =>
+ highlighted
+ ? css`
+ border: 2px solid ${theme.palette.accent.main};
+ &:hover {
+ border: 2px solid ${theme.palette.accent.main};
+ }
+ &:focus {
+ border: 1px solid ${theme.palette.accent.main};
+ box-shadow: 0 0 0 2px ${theme.palette.accent.main};
+ }
+ `
+ : css`
+ &:focus {
+ border: 2px solid #1C1C1C;
+ }
+ `}
`;
+
+export default LabeledTextArea;
diff --git a/packages/app/src/components/Nav.tsx b/packages/app/src/components/Nav.tsx
new file mode 100644
index 0000000..2972c73
--- /dev/null
+++ b/packages/app/src/components/Nav.tsx
@@ -0,0 +1,147 @@
+
+import { Box, Typography, useTheme } from "@mui/material";
+import { ConnectButton } from "@rainbow-me/rainbowkit";
+import PropTypes from 'prop-types';
+import { Link } from 'react-router-dom';
+import React from 'react';
+
+// Define the types for the props
+interface CustomConnectButtonProps {
+ splitscreen?: boolean;
+}
+
+interface NavProps {
+ splitscreen?: boolean;
+}
+
+/* STYLED CONNECT WALLET BUTTON */
+const CustomConnectButton: React.FC = ({ splitscreen = false }) => {
+ const theme = useTheme();
+ return (
+
+ {({
+ account,
+ chain,
+ openAccountModal,
+ openChainModal,
+ openConnectModal,
+ mounted,
+ }) => {
+ const ready = mounted;
+ const connected = ready && account && chain;
+
+ return (
+ {
+ if (!ready) {
+ openConnectModal();
+ } else if (connected) {
+ openAccountModal();
+ } else {
+ openConnectModal();
+ }
+ }}
+ sx={{
+ fontSize: { xs: '12px', md: '14px' },
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: !connected ? theme.palette.accent.main : '#1f1f1f',
+ color: '#ffffff',
+ padding: { xs: '7px 10px', sm: '10px 16px', md: splitscreen ? '8px 12px' : '10px 16px' },
+ borderRadius: '10px',
+ cursor: 'pointer',
+ '&:hover': {
+ backgroundColor: !connected ? theme.palette.accent.main : '#333333',
+ opacity: !connected ? '95%' : '100%'
+ },
+ }}
+ >
+ {(() => {
+ if (!ready) {
+ return 'Loading...';
+ }
+ if (!connected) {
+ return 'Connect Wallet';
+ }
+ return (
+
+
+ {account.displayBalance ? `${account.displayBalance} ` : ''}
+
+
+
+
+ {account.displayName}
+
+
+
+ );
+ })()}
+
+ );
+ }}
+
+ );
+};
+
+/* THE NAV COMPONENT ITSELF THAT USED THE ABOVE CONNECT BUTTON */
+const Nav: React.FC = ({ splitscreen = false }) => {
+ return (
+
+
+
+ PROOF OF TWITTER
+
+
+
+
+ Docs
+
+
+ Explore
+
+
+
+
+
+ );
+};
+
+Nav.propTypes = {
+ splitscreen: PropTypes.bool,
+};
+
+Nav.defaultProps = {
+ splitscreen: false,
+};
+
+CustomConnectButton.propTypes = {
+ splitscreen: PropTypes.bool,
+};
+
+CustomConnectButton.defaultProps = {
+ splitscreen: false,
+};
+
+export default Nav;
diff --git a/packages/app/src/components/SingleLineInput.tsx b/packages/app/src/components/SingleLineInput.tsx
index f2c7f91..aa9572d 100644
--- a/packages/app/src/components/SingleLineInput.tsx
+++ b/packages/app/src/components/SingleLineInput.tsx
@@ -1,40 +1,124 @@
+// import styled from "styled-components";
+// import { Col } from "./Layout";
+
+// export const SingleLineInput: React.FC<{
+// label: string;
+// value: any;
+// onChange: (e: any) => void;
+// }> = ({ label, onChange, value }) => {
+// return (
+//
+//
+//
+//
+// );
+// };
+
+// const InputContainer = styled(Col)`
+// gap: 8px;
+// `;
+
+// const Input = styled.input`
+// border: 1px solid rgba(255, 255, 255, 0.4);
+// background: rgba(0, 0, 0, 0.3);
+// border-radius: 4px;
+// padding: 8px;
+// height: 32px;
+// display: flex;
+// align-items: center;
+// color: #fff;
+// transition: all 0.2s ease-in-out;
+// &:hover {
+// border: 1px solid rgba(255, 255, 255, 0.8);
+// }
+// `;
+
+
+import React from 'react';
import styled from "styled-components";
-import { Col } from "./Layout";
+import { useTheme, TextField, Box, Typography } from "@mui/material";
-export const SingleLineInput: React.FC<{
+interface SingleLineInputProps {
label: string;
value: any;
onChange: (e: any) => void;
-}> = ({ label, onChange, value }) => {
+ highlighted?: boolean;
+ disabled?: boolean; // Optional disabled prop
+}
+
+export const SingleLineInput: React.FC = ({
+ label,
+ onChange,
+ value,
+ highlighted = false,
+ disabled = false, // Default value set to false
+}) => {
+
+ const theme = useTheme();
+
return (
-
-
-
-
+
+
+
);
};
-
-const InputContainer = styled(Col)`
- gap: 8px;
-`;
-
-const Input = styled.input`
- border: 1px solid rgba(255, 255, 255, 0.4);
- background: rgba(0, 0, 0, 0.3);
- border-radius: 4px;
- padding: 8px;
- height: 32px;
- display: flex;
- align-items: center;
- color: #fff;
- transition: all 0.2s ease-in-out;
- &:hover {
- border: 1px solid rgba(255, 255, 255, 0.8);
- }
-`;
diff --git a/packages/app/src/components/StatusTag.tsx b/packages/app/src/components/StatusTag.tsx
new file mode 100644
index 0000000..72136e5
--- /dev/null
+++ b/packages/app/src/components/StatusTag.tsx
@@ -0,0 +1,35 @@
+// StatusTag.tsx
+import React from 'react';
+import { Typography, Box } from '@mui/material';
+
+interface StatusTagProps {
+ statusMessage: string;
+ statusPassed: boolean;
+}
+
+const StatusTag: React.FC = ({ statusMessage, statusPassed }) => {
+ return (
+
+ {statusMessage}
+
+ );
+};
+
+export default StatusTag;
diff --git a/packages/app/src/components/Stepper.tsx b/packages/app/src/components/Stepper.tsx
new file mode 100644
index 0000000..3f9fdee
--- /dev/null
+++ b/packages/app/src/components/Stepper.tsx
@@ -0,0 +1,741 @@
+// import React, { useState } from 'react';
+// import { Stepper, Step, StepLabel, Button, Box } from '@mui/material';
+
+// const steps = [
+// 'Send Reset Email',
+// 'Copy/Paste DKIM Sig',
+// 'Add Address',
+// 'Prove',
+// 'Verify & Mint'
+// ];
+
+// const StepperComponent: React.FC = () => {
+// const [activeStep, setActiveStep] = useState(0);
+
+// const handleNext = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep + 1);
+// };
+
+// const handleBack = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep - 1);
+// };
+
+// const handleStep = (step: number) => () => {
+// setActiveStep(step);
+// };
+
+// return (
+//
+//
+// {steps.map((label, index) => (
+//
+// {label}
+//
+// ))}
+//
+//
+// {activeStep === steps.length ? (
+//
+//
All steps completed
+//
+//
+// ) : (
+//
+//
+//
+//
+//
+//
+// )}
+//
+//
+// );
+// };
+
+// export default StepperComponent;
+
+
+
+
+
+
+
+
+
+// import React, { useState } from 'react';
+// import { Stepper, Step, StepLabel, Button, Box, Typography } from '@mui/material';
+// import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// const steps = [
+// 'Send Reset Email',
+// 'Copy/Paste DKIM Sig',
+// 'Add Address',
+// 'Prove',
+// 'Verify & Mint'
+// ];
+
+// const StepperComponent: React.FC = () => {
+// const [activeStep, setActiveStep] = useState(0);
+
+// const handleNext = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep + 1);
+// };
+
+// const handleBack = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep - 1);
+// };
+
+// const handleStep = (step: number) => () => {
+// setActiveStep(step);
+// };
+
+// return (
+//
+//
+// {steps.map((label, index) => (
+//
+//
+//
+// {label}
+//
+//
+// {index < steps.length - 1 && }
+//
+// ))}
+//
+//
+// {activeStep === steps.length ? (
+//
+//
All steps completed
+//
+//
+// ) : (
+//
+//
+//
+//
+//
+//
+// )}
+//
+//
+// );
+// };
+
+// export default StepperComponent;
+
+
+
+
+
+
+
+
+// import React, { useState } from 'react';
+// import { Box, Typography, IconButton } from '@mui/material';
+// import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// const steps = [
+// 'Send Reset Email',
+// 'Copy/Paste DKIM Sig',
+// 'Add Address',
+// 'Prove',
+// 'Verify & Mint'
+// ];
+
+// const StepperComponent: React.FC = () => {
+// const [activeStep, setActiveStep] = useState(0);
+
+// const handleStep = (step: number) => () => {
+// setActiveStep(step);
+// };
+
+// return (
+//
+// {steps.map((label, index) => (
+//
+//
+//
+// {label}
+//
+//
+// {index < steps.length - 1 && (
+//
+// )}
+//
+// ))}
+//
+// );
+// };
+
+// export default StepperComponent;
+
+
+
+
+// import React, { useState } from 'react';
+// import { Box, Typography } from '@mui/material';
+// import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// const steps = [
+// 'SEND RESET EMAIL',
+// 'COPY/PASTE DKIM SIG',
+// 'ADD ADDRESS',
+// 'PROVE',
+// 'VERIFY & MINT'
+// ];
+
+// const StepperComponent: React.FC = () => {
+// const [activeStep, setActiveStep] = useState(0);
+
+// const handleStep = (step: number) => () => {
+// setActiveStep(step);
+// };
+
+// return (
+//
+// {/* Light grey bar */}
+//
+
+//
+// {steps.map((label, index) => (
+//
+//
+//
+// {label}
+//
+//
+// {index < steps.length - 1 && (
+//
+// )}
+//
+// ))}
+//
+//
+// );
+// };
+
+// export default StepperComponent;
+
+
+
+
+
+
+
+
+
+
+
+
+// import React, { ReactNode } from 'react';
+// import { Box, Typography, Button } from '@mui/material';
+// import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// interface StepperComponentProps {
+// children: ReactNode;
+// steps: string[];
+// activeStep: number;
+// setActiveStep: (step: number) => void;
+// }
+
+// const StepperComponent: React.FC = ({
+// children,
+// steps,
+// activeStep,
+// setActiveStep
+// }) => {
+// const handleStep = (step: number) => () => {
+// setActiveStep(step);
+// };
+
+// const handleNext = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep + 1);
+// };
+
+// const handleBack = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep - 1);
+// };
+
+// return (
+//
+//
+// {/* Light grey bar */}
+//
+// {steps.map((label, index) => (
+//
+//
+//
+// {label}
+//
+//
+// {index < steps.length - 1 && (
+//
+// )}
+//
+// ))}
+//
+
+//
+// {children}
+//
+
+//
+// {activeStep !== 0 && (
+//
+// )}
+
+
+// {activeStep !== 4 && (
+//
+// )}
+//
+//
+// );
+// };
+
+// export default StepperComponent;
+
+
+
+
+
+
+// import React, { useState, ReactNode } from 'react';
+// import { Box, Typography, Button } from '@mui/material';
+// import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// interface StepperComponentProps {
+// children: ReactNode;
+// steps: string[];
+// activeStep: number;
+// setActiveStep: (step: number) => void;
+// }
+
+// const StepperComponent: React.FC = ({
+// children,
+// steps,
+// activeStep,
+// setActiveStep
+// }) => {
+// const [completedSteps, setCompletedSteps] = useState(new Array(steps.length).fill(false));
+
+// const handleStep = (step: number) => () => {
+// if (step <= activeStep || completedSteps[step - 1]) {
+// setActiveStep(step);
+// }
+// };
+
+// const handleNext = () => {
+// if (activeStep < steps.length - 1 && completedSteps.slice(0, activeStep).every(completed => completed)) {
+// setCompletedSteps((prevCompletedSteps) => {
+// const newCompletedSteps = [...prevCompletedSteps];
+// newCompletedSteps[activeStep] = true;
+// return newCompletedSteps;
+// });
+// setActiveStep((prevActiveStep) => prevActiveStep + 1);
+// }
+// };
+
+// const handleBack = () => {
+// setActiveStep((prevActiveStep) => prevActiveStep - 1);
+// };
+
+// return (
+//
+//
+// {/* Light grey bar */}
+//
+// {steps.map((label, index) => {
+// const isStepDisabled = !(index <= activeStep || completedSteps[index - 1]);
+// return (
+//
+//
+//
+// {label}
+//
+//
+// {index < steps.length - 1 && (
+//
+// )}
+//
+// );
+// })}
+//
+
+//
+// {children}
+//
+
+//
+// {activeStep !== 0 && (
+//
+// )}
+
+
+// {activeStep !== steps.length - 1 && (
+//
+// )}
+//
+//
+// );
+// };
+
+// export default StepperComponent;
+
+import React, { ReactNode } from 'react';
+import { Box, Typography, Button, useTheme } from '@mui/material';
+import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
+
+// Define the types for the props
+interface StepperComponentProps {
+ children: ReactNode;
+ steps: [string, 'completed' | 'uncompleted'][];
+ activeStep: number;
+ setActiveStep: (step: number) => void;
+}
+
+const StepperComponent: React.FC = ({
+ children,
+ steps,
+ activeStep,
+ setActiveStep
+}) => {
+ const theme = useTheme();
+
+ const handleStep = (step: number) => () => {
+ if (step <= activeStep || steps.slice(0, step).every(s => s[1] === 'completed')) {
+ setActiveStep(step);
+ }
+ };
+
+ const handleNext = () => {
+ if (
+ activeStep < steps.length - 1 &&
+ steps.slice(0, activeStep + 1).every(step => step[1] === 'completed')
+ ) {
+ setActiveStep(activeStep + 1);
+ }
+ };
+
+ const handleBack = () => {
+ setActiveStep(activeStep - 1);
+ };
+
+ return (
+
+
+
+ {steps.map((step, index) => {
+ const isStepDisabled = !steps.slice(0, index).every(s => s[1] === 'completed');
+ return (
+
+
+
+ {step[0]}
+
+
+ {index < steps.length - 1 && (
+
+ )}
+
+ );
+ })}
+
+
+
+ {children}
+
+
+
+ {activeStep !== 0 && (
+
+ )}
+
+ {activeStep !== steps.length - 1 && (
+
+ )}
+
+
+ );
+};
+
+export default StepperComponent;
diff --git a/packages/app/src/components/Video.tsx b/packages/app/src/components/Video.tsx
new file mode 100644
index 0000000..69c3f16
--- /dev/null
+++ b/packages/app/src/components/Video.tsx
@@ -0,0 +1,52 @@
+/* LOCAL VIDEO VERSION BELOW */
+import React from 'react';
+import { Box } from '@mui/material';
+
+const Video: React.FC = () => {
+ return (
+
+
+
+ );
+}
+
+export default Video;
+
+
+
+
+
+/* YOUTUBE VIDEO VERSION BELOW */
+
+
+
+
+
+// import React from 'react';
+// import { Box } from '@mui/material';
+
+// const Video: React.FC = () => {
+// return (
+//
+//
+//
+// );
+// }
+
+// export default Video;
\ No newline at end of file
diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx
index d50683d..53222f2 100644
--- a/packages/app/src/index.tsx
+++ b/packages/app/src/index.tsx
@@ -16,6 +16,9 @@ import { GoogleOAuthProvider } from "@react-oauth/google";
import { GoogleAuthProvider } from "./contexts/GoogleAuth";
import { ZkRegexProvider } from "../zk-regex-sdk";
+import { ThemeProvider, CssBaseline } from '@mui/material';
+import theme from './theme';
+
const { connectors } = getDefaultWallets({
appName: "ZK Email - Twitter Verifier",
chains: [sepolia],
@@ -34,22 +37,24 @@ const config = createConfig({
if (import.meta.env.VITE_GOOGLE_CLIENT_ID) {
ReactDOM.render(
-
-
-
-
-
-
-
-
-
- {" "}
-
+
+
+
+
+
+
+
+
+
+
+ {" "}
+
+
,
document.getElementById("root")
);
diff --git a/packages/app/src/pages/AboutPage.tsx b/packages/app/src/pages/AboutPage.tsx
new file mode 100644
index 0000000..919b8d9
--- /dev/null
+++ b/packages/app/src/pages/AboutPage.tsx
@@ -0,0 +1,186 @@
+import React from 'react';
+import Nav from '../components/Nav';
+import { Container, Typography, Box, Grid, Stack, useTheme } from '@mui/material';
+import { Button, OutlinedButton } from '../components/Button';
+import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward';
+import Accordion from '../components/Accordion';
+import { Link } from 'react-router-dom';
+import { useMediaQuery } from "@mui/material";
+
+import LockResetIcon from '@mui/icons-material/LockReset';
+import MailOutlineIcon from '@mui/icons-material/MailOutline';
+import FingerprintIcon from '@mui/icons-material/Fingerprint';
+import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
+import RefreshIcon from '@mui/icons-material/Refresh';
+import ContentPasteIcon from '@mui/icons-material/ContentPaste';
+import DraftsOutlinedIcon from "@mui/icons-material/DraftsOutlined";
+
+import Video from '../components/Video';
+
+const AboutPage: React.FC = () => {
+ const theme = useTheme();
+ const isXs = useMediaQuery(theme.breakpoints.down('xs'));
+ const isSm = useMediaQuery(theme.breakpoints.down('sm'));
+ const isMd = useMediaQuery(theme.breakpoints.down('md'));
+
+ const faqs = [
+ {
+ title: 'How do you selectively reveal content in an email ?',
+ contents: 'We can hide any information or selectively reveal any text, wether that’s the sender, receiver, subject, body etc using Regex. Regex is short for regular expression, this term represents sequence of characters that forms a search pattern, commonly used for string matching within text. It consists of a sequence of characters that define a search pattern, enabling complex searches, substitutions, and string manipulations. For example, in programming and text processing, regex can identify, extract, or replace specific text patterns, such as email addresses, dates, or phone numbers, by defining these patterns through a combination of literal characters and special symbols. In the context of ZK Email it is used to parse email headers and extract relevant information.'
+ },
+ {
+ title: 'How can I do this anonymously',
+ contents: 'ZK Email leverages the principles of Zero Knowledge proofs and serverless execution within the browser to provide a verifiable yet anonymous way to confirm an emails contents and recipents . Zero Knowledge proofs allow provers to prove that they know or possess certain information without revealing the information itself to a verifer. In ZK Email, this technology is used to verify user identity and email content without exposing sensitive data to a server or other users. The serverless architecture means that all proof generation is executed entirely within the user`s browser.'
+ },
+ {
+ title: 'Why don’t I need to trust you?',
+ contents: 'The DKIM email signitures do not contain information we can use to sign other emails, all our code is open source and being audited'
+ },
+ {
+ title: 'How do you verify the email contents and recipents',
+ contents: 'We use the existing DKIM Signiture, almost all emails are signed by the sending domain server using an algorithm called DKIM. It can be summarized as this rsa_sign(sha256(from:..., to:..., subject:..., ,...), private key). Every time an email is sent we can verify the sender, receiver, the subject, the body by checking if the corresponding public key of the email address applied on the DKIM signiture returns the sha256(from:..., to:..., subject:..., ,...) a hash of the from, to subject, email details which we can check by rehashing'
+ },
+ ];
+
+ return (
+
+
+ );
+};
+
+export default AboutPage;
diff --git a/packages/app/src/pages/MainPage.tsx b/packages/app/src/pages/MainPage.tsx
index 9f295fc..88ded67 100644
--- a/packages/app/src/pages/MainPage.tsx
+++ b/packages/app/src/pages/MainPage.tsx
@@ -33,6 +33,14 @@ import EmailInputMethod from "../components/EmailInputMethod";
import { useZkRegex } from "../../zk-regex-sdk";
import { randomUUID } from "crypto";
+import { Box, Grid, Typography } from "@mui/material";
+import Stepper from '../components/Stepper'
+import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward';
+import Video from "../components/Video";
+import Nav from "../components/Nav";
+import {useTheme} from "@mui/material";
+import StatusTag from "../components/StatusTag";
+
const CIRCUIT_NAME = "twitter";
export const MainPage: React.FC<{}> = (props) => {
@@ -121,7 +129,7 @@ export const MainPage: React.FC<{}> = (props) => {
if (address) {
setEthereumAddress(address);
} else {
- setEthereumAddress("");
+ // setEthereumAddress("");
}
}, [address]);
@@ -307,283 +315,465 @@ export const MainPage: React.FC<{}> = (props) => {
console.log(inputWorkers);
+
+
+
+ const theme = useTheme()
+
+ const [counter, setCounter] = useState(0);
+
+ const [steps, setSteps] = useState<[string, 'completed' | 'uncompleted'][]>([
+ ['SEND RESET EMAIL', 'completed'],
+ ['COPY/PASTE DKIM SIG', 'uncompleted'],
+ ['ADD ADDRESS', 'uncompleted'],
+ ['PROVE', 'uncompleted'],
+ ['VERIFY & MINT', 'uncompleted']
+ ]);
+
+ const [activeStep, setActiveStep] = useState(0);
+
+ const markStepCompleted = (index: number) => {
+ setSteps(prevSteps => {
+ const newSteps = [...prevSteps];
+ newSteps[index][1] = 'completed';
+ return newSteps;
+ });
+ };
+
+ const markStepUncompleted = (index: number) => {
+ setSteps(prevSteps => {
+ const newSteps = [...prevSteps];
+ newSteps[index][1] = 'uncompleted';
+ return newSteps;
+ });
+ };
+
+
+ useEffect(() => {
+ let interval: NodeJS.Timeout;
+ if (status === 'generating-proof') {
+ interval = setInterval(() => {
+ setCounter(prevCounter => prevCounter + 1);
+ }, 1000);
+ } else {
+ setCounter(0);
+ }
+ return () => clearInterval(interval);
+ }, [status]);
+
+
+ useEffect(() => {
+ // i'm not sure if this if statement check is correct, after the &&
+ // i want to make sure the user actually put something in the 'Full Email with Headers' section OR if they logged in with Google they actually selected an email and it's not the default localStorage.emailFull=DOMException
+ // this code works but there's probably a better check?
+ if (emailFull != '' && emailFull != 'DOMException') {
+ markStepCompleted(1); // Mark 'COPY/PASTE DKIM SIG' step as completed
+ } else {
+ markStepUncompleted(1); // Mark 'COPY/PASTE DKIM SIG' step as uncompleted
+ }
+ }, [emailFull]);
+
+
+ useEffect(() => {
+ if (ethereumAddress != '') {
+ markStepCompleted(2); // Mark 'ADD ADDRESS' step as completed
+ } else {
+ markStepUncompleted(2); // Mark 'ADD ADDRESS' step as uncompleted
+ }
+ }, [ethereumAddress]);
+
+
+ useEffect(() => {
+ if (status === 'done' ) {
+ markStepCompleted(3); // Mark 'PROVE' step as completed
+ } else {
+ // markStepUncompleted(3); // Mark 'PROVE' step as uncompleted
+ }
+ }, [status]);
+
+
+ const [isOverlayVisible, setIsOverlayVisible] = useState(false);
+
+ useEffect(() => {
+ if (status === 'generating-proof') {
+ setIsOverlayVisible(true);
+ } else {
+ setIsOverlayVisible(false);
+ }
+ }, [status]);
+
+
+
+ //
+ const [message, setMessage] = useState("just a test: testing web worker");
+
+ useEffect(() => {
+ const worker = new Worker(new URL('../testWorker.js', import.meta.url));
+
+ worker.onmessage = (e) => {
+ setMessage(e.data);
+ worker.terminate();
+ };
+
+ worker.postMessage({});
+ }, []);
+
+
+
+
+
+
return (
-
+
+ {isOverlayVisible && Generating Proof... Reload page if Unresponsive after 6 Minutes }
{showBrowserWarning && (
)}
-
- Proof of Twitter: ZK Email Demo
-
-
-
+