a few homepage pages

This commit is contained in:
Tobias Merkle 2024-03-26 16:47:56 -04:00
parent 7d4fd2d664
commit a83f50b475
32 changed files with 7541 additions and 5267 deletions

View File

@ -4,11 +4,11 @@ type LoaderProps = {
msg: string
}
export default function Loader({ msg } : LoaderProps) {
export default function Loader({ msg }: LoaderProps) {
return (
<div id="loading" className="col center">
<div id="loading" className="flex flex-col text-center">
<h4>{msg}</h4>
<div id="loader"> <div/> <div/> <div/> <div/> </div>
<div id="loader"> <div /> <div /> <div /> <div /> </div>
</div>
)
}

View File

@ -90,7 +90,7 @@
</script>
<style>
:root {
/* :root {
--k-red: #a30101;
--k-darkred: #4d0c0c;
--k-lightred: #dd0207;
@ -291,7 +291,7 @@
font-size: 0.8em;
line-height: 1.5em;
margin-bottom: 1em;
}
} */
</style>
</body>

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
"name": "register",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8080",
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@ethersproject/hash": "^5.7.0",
@ -21,6 +20,7 @@
"@web3-react/walletconnect-connector": "^6.2.13",
"@web3-react/walletconnect-v2": "^8.5.1",
"buffer": "^6.0.3",
"classnames": "^2.5.1",
"eslint-config-react-app": "^7.0.1",
"eth-ens-namehash": "^2.0.8",
"ethers": "^5.7.2",
@ -29,9 +29,11 @@
"jazzicon": "^1.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^5.0.1",
"react-modal": "^3.16.1",
"react-router-dom": "^6.16.0",
"react-scripts": "5.0.1",
"tailwindcss": "^3.4.1",
"typechain": "^8.3.1",
"typescript": "^4.9.5"
},
@ -67,4 +69,4 @@
"@types/react-modal": "^3.16.2",
"inline-source-cli": "^2.0.0"
}
}
}

View File

@ -32,7 +32,7 @@ import ClaimOsInvite from "./pages/ClaimKnsInvite";
import SetPassword from "./pages/SetPassword";
import Login from './pages/Login'
import Reset from './pages/ResetKnsName'
import OsHome from "./pages/KinodeHome"
import KinodeHome from "./pages/KinodeHome"
import ResetNode from "./pages/ResetNode";
import ImportKeyfile from "./pages/ImportKeyfile";
import { UnencryptedIdentity } from "./lib/types";
@ -233,7 +233,7 @@ function App() {
<Routes>
<Route path="/" element={navigateToLogin
? <Navigate to="/login" replace />
: <OsHome {...props} />
: <KinodeHome {...props} />
} />
<Route path="/claim-invite" element={<ClaimOsInvite {...props} />} />
<Route path="/register-name" element={<RegisterOsName {...props} />} />

View File

@ -1,18 +1,4 @@
<svg width="580" height="72" viewBox="0 0 580 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6_641)">
<path d="M0.824922 1.07031L0.794922 70.0703H14.7949L14.8049 1.07031H0.824922Z" fill="#FFF5D9"/>
<path d="M16.5947 36.8803L41.2547 1.07031H58.2447L33.1647 36.8803L61.2447 70.0703H42.9947L16.5947 36.8803Z" fill="#FFF5D9"/>
<path d="M119.885 1.07031H105.765V70.0703H119.885V1.07031Z" fill="#FFF5D9"/>
<path d="M173.185 1.07031V70.0703H186.775V26.8303L224.045 70.0703H234.825V1.07031H221.325V45.6803L183.445 1.07031H173.185Z" fill="#FFF5D9"/>
<path d="M342.465 8.86C333.025 0.15 321.645 0 318.535 0C315.475 0 303.575 0.22 294.005 9.52C283.845 19.4 283.805 32.24 283.795 35.66C283.785 39.3 283.895 49.03 290.805 57.99C300.855 71.02 316.695 71.31 318.535 71.32C321.375 71.32 334.185 71 343.965 60.66C353.065 51.04 353.265 39.4 353.275 35.66C353.275 32.49 353.305 18.86 342.455 8.86H342.465ZM318.435 58.01C307.095 58.01 297.895 47.95 297.895 35.54C297.895 23.13 307.085 13.07 318.435 13.07C329.785 13.07 338.975 23.13 338.975 35.54C338.975 47.95 329.785 58.01 318.435 58.01Z" fill="#FFF5D9"/>
<path d="M450.495 12.0802C444.975 5.46023 437.135 0.990234 427.955 0.990234C417.555 0.990234 405.295 1.07023 402.295 1.07023V69.9802C405.285 69.9802 417.555 70.0602 427.955 70.0602C445.525 70.0602 458.445 53.4102 459.065 36.8602C459.395 28.0102 456.185 18.9002 450.495 12.0802ZM440.085 49.9502C436.895 53.8702 432.705 56.6902 427.665 57.5602C424.025 58.1902 420.095 57.8302 416.405 57.8302C416.405 50.4002 416.405 42.9802 416.405 35.5502V13.2202C423.795 13.2202 430.525 12.7002 436.605 17.6002C440.275 20.5602 442.925 24.7102 444.165 29.2402C444.525 30.5402 444.765 31.8802 444.875 33.2302C445.395 39.3702 443.995 45.1402 440.085 49.9502Z" fill="#FFF5D9"/>
<path d="M508.135 0.990234V70.0602H552.715V57.9302H522.035V40.4202H547.125V28.0702H521.995V13.3202H552.715V0.990234H508.135Z" fill="#FFF5D9"/>
<path d="M574.835 66.0398H572.745L571.015 63.0698H569.845V66.0398H567.805V57.5498H571.765C572.845 57.5498 573.865 57.9298 574.425 58.9398C575.205 60.3698 574.665 62.3798 573.105 63.0298C573.725 64.1198 574.225 64.9498 574.845 66.0398H574.835ZM570.375 61.0798H570.845C571.335 61.0798 572.365 61.0798 572.365 60.2898C572.365 59.5598 571.335 59.5598 570.845 59.5598H570.375V61.0798Z" fill="#FFF5D9"/>
<path d="M570.964 69.0002C574.913 69.0002 578.114 65.799 578.114 61.8502C578.114 57.9014 574.913 54.7002 570.964 54.7002C567.016 54.7002 563.814 57.9014 563.814 61.8502C563.814 65.799 567.016 69.0002 570.964 69.0002Z" stroke="#FFF5D9" stroke-width="2.2" stroke-miterlimit="10"/>
</g>
<defs>
<clipPath id="clip0_6_641">
<rect width="578.41" height="71.32" fill="white" transform="translate(0.794922)"/>
</clipPath>
</defs>
<svg width="779" height="514" viewBox="0 0 779 514" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M753.092 5.91932C756.557 5.09976 755.962 -0.00012207 752.401 -0.00012207H426.001C424.755 -0.00012207 423.639 0.77027 423.197 1.93535L236.968 492.6C235.729 495.865 240.123 498.255 242.191 495.441L569.357 50.1132C569.778 49.5392 570.391 49.1339 571.084 48.97L753.092 5.91932Z" fill="#FFF5D9"/>
<path d="M11.9665 40.2288C9.10949 38.777 10.2135 34.4583 13.4167 34.5557L404.273 46.4367C406.334 46.4993 407.719 48.5749 406.986 50.5023L347.438 206.981C346.804 208.647 344.865 209.396 343.275 208.588L11.9665 40.2288Z" fill="#FFF5D9"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 644 B

View File

@ -69,28 +69,35 @@ function ChainInfo({
}, [chainId, networkName])
return (
<div style={{ display: "flex", gap: 10, maxWidth: 500 }}>
<div
className='flex gap-4'
>
{/* TODO: prompt to change address */}
<button
onClick={changeConnectedAccount}
className="chain-button monospace"
className="font-mono alt flex place-items-center max-w-1/3"
>
<Jazzicon
address={account || ""}
diameter={24}
style={{ marginRight: "0.5em" }}
className='mr-4'
/>{" "}
{formatAddress(account || "")}
</button>
<button
onClick={changeToNodeChain}
className="chain-button"
style={{ maxWidth: "27%" }}
className="alt max-w-1/3"
>
{generateNetworkIcon(networkName)} {networkName}
{generateNetworkIcon(networkName)}
<div className='ml-2'>
{networkName}
</div>
</button>
{/* TODO: show KNS contract ID in modal */}
<button onClick={showKnsAddress} className="chain-button" style={{ maxWidth: "27%" }}>
<button
onClick={showKnsAddress}
className="alt max-w-1/3"
>
KNS Contract
</button>
</div>

View File

@ -1,3 +1,6 @@
import { DirectTooltip } from "./DirectTooltip";
import { Tooltip } from "./Tooltip";
interface Props {
direct: boolean;
setDirect: (direct: boolean) => void;
@ -5,8 +8,8 @@ interface Props {
export default function DirectCheckbox({ direct, setDirect }: Props) {
return (
<div className="row">
<div style={{ position: "relative" }}>
<div className="flex place-items-center">
<div className="relative flex place-items-center mr-2">
<input
type="checkbox"
id="direct"
@ -16,23 +19,21 @@ export default function DirectCheckbox({ direct, setDirect }: Props) {
autoFocus
/>
{direct && (
<span onClick={() => setDirect(false)} className="checkmark">
<span
onClick={() => setDirect(false)}
className="checkmark"
>
&#10003;
</span>
)}
</div>
<label htmlFor="direct" className="direct-node-message">
<label
htmlFor="direct"
className="flex place-items-center cursor-pointer"
>
Register as a direct node. If you are unsure leave unchecked.
</label>
<div className="tooltip-container">
<div className="tooltip-button">&#8505;</div>
<div className="tooltip-content">
A direct node publishes its own networking information on-chain: IP,
port, so on. An indirect node relies on the service of routers, which
are themselves direct nodes. Only register a direct node if you know
what youre doing and have a public, static IP address.
</div>
</div>
<DirectTooltip />
</div>
);
}

View File

@ -0,0 +1,3 @@
import { Tooltip } from "./Tooltip";
export const DirectTooltip: React.FC = () => <Tooltip text={`A direct node publishes its own networking information on-chain: IP, port, so on. An indirect node relies on the service of routers, which are themselves direct nodes. Only register a direct node if you know what youre doing and have a public, static IP address.`} />

View File

@ -90,8 +90,8 @@ function EnterOsName({
&& setName(e.target.value)
return (
<div className="col" style={{ width: '100%' }}>
<div className="row" style={{ width: '100%' }}>
<div className="flex flex-col w-full place-items-center place-content-center">
<div className="flex w-full place-items-center">
<input
value={name}
onChange={noDots}
@ -99,10 +99,11 @@ function EnterOsName({
required
name="dot-os-name"
placeholder="e.g. myname"
className="grow"
/>
<div className="os">.os</div>
<div className="ml-2 text-lg">.os</div>
</div>
{nameValidities.map((x, i) => <div key={i}><br /><span className="name-validity">{x}</span></div>)}
{nameValidities.map((x, i) => <div key={i}><br /><span className="text-red-500">{x}</span></div>)}
</div>
)

View File

@ -8,6 +8,7 @@ import { OPTIMISM_OPT_HEX, SEPOLIA_OPT_HEX } from "../constants/chainId";
import sepoliaLogo from "../assets/sepolia.png";
import optimismLogo from "../assets/optimism.png";
import { Tooltip } from "./Tooltip";
const { useIsActivating, useChainId } = hooks;
@ -20,7 +21,7 @@ type OsHeaderProps = {
hideConnect?: boolean;
};
function OsHeader({
function KinodeHeader({
header,
openConnect,
nameLogo = false,
@ -40,7 +41,7 @@ function OsHeader({
const connectWallet = useCallback(async () => {
closeConnect();
await metaMask.activate().catch(() => {});
await metaMask.activate().catch(() => { });
try {
setChain(nodeChainId);
@ -71,61 +72,36 @@ function OsHeader({
alert("You can change your connected account in your wallet.");
}, []);
// <div style={{ textAlign: 'center', lineHeight: 1.5 }}> Connected as {account?.slice(0,6) + '...' + account?.slice(account.length - 6)}</div>
return (
<>
<div id="signup-form-header" className="col">
<div id="signup-form-header" className="flex flex-col">
{(nodeChainId === SEPOLIA_OPT_HEX ||
nodeChainId === OPTIMISM_OPT_HEX) && (
<div
className="tooltip-container"
style={{ position: "absolute", top: 32, right: 32 }}
>
<div className="tooltip-button chain">
{nodeChainId === SEPOLIA_OPT_HEX ? (
<img alt="sepolia" src={sepoliaLogo} className="sepolia" />
<Tooltip
button={nodeChainId === SEPOLIA_OPT_HEX ? (
<img
alt="sepolia"
src={sepoliaLogo}
/>
) : nodeChainId === OPTIMISM_OPT_HEX ? (
<img alt="optimism" src={optimismLogo} />
<img
alt="optimism"
src={optimismLogo}
/>
) : null}
</div>
<div className="tooltip-content left">
{nodeChainId === SEPOLIA_OPT_HEX ? (
<div
style={{
textAlign: "center",
lineHeight: "1.5em",
maxWidth: 450,
}}
>
Your Kinode is currently pointed at Sepolia. To point at
Optimism, boot without the "--testnet" flag.
</div>
) : nodeChainId === OPTIMISM_OPT_HEX ? (
<div
style={{
textAlign: "center",
lineHeight: "1.5em",
maxWidth: 450,
}}
>
Your Kinode is currently pointed at Optimism. To point at
Sepolia, boot with the "--testnet" flag.
</div>
) : null}
</div>
</div>
)}
<div className="col" style={{ gap: 16, marginBottom: 32 }}>
text={nodeChainId === SEPOLIA_OPT_HEX
? `Your Kinode is currently pointed at Sepolia. To point at Optimism, boot without the "--testnet" flag.`
: nodeChainId === OPTIMISM_OPT_HEX
? `Your Kinode is currently pointed at Optimism. To point at Sepolia, boot with the "--testnet" flag.`
: ''}
/>
)}
<div className="flex flex-col gap-4">
{header}
</div>
{!hideConnect && (
<div
style={{
minWidth: "50vw",
width: 400,
justifyContent: "center",
display: "flex",
}}
className="flex place-items-center place-content-center max-w-[50vw]"
>
{isActive && account ? (
<ChainInfo
@ -135,11 +111,10 @@ function OsHeader({
changeConnectedAccount={changeConnectedAccount}
/>
) : (
<div className="col" style={{ gap: 32, marginTop: 16 }}>
<h5 style={{ textAlign: "center", lineHeight: "1.5em" }}>
<div className="flex flex-col gap-8 mt-4">
<h5 className="text-center max-w-[450px] leading-6">
You must connect to a browser wallet to continue
</h5>
{/* <div style={{ textAlign: 'center', lineHeight: '1.5em' }}>We recommend <a href="https://metamask.io/download.html" target="_blank" rel="noreferrer">MetaMask</a></div> */}
{isActivating ? (
<Loader msg="Approve connection in your wallet" />
) : (
@ -147,11 +122,7 @@ function OsHeader({
)}
{nodeChainId === SEPOLIA_OPT_HEX && (
<h5
style={{
textAlign: "center",
lineHeight: "1.5em",
maxWidth: 450,
}}
className="text-center max-w-[450px] leading-6"
>
Kinode is currently on the Sepolia Testnet, if you need
testnet ETH, you can get some from the{" "}
@ -173,4 +144,4 @@ function OsHeader({
);
}
export default OsHeader;
export default KinodeHeader;

View File

@ -2,11 +2,11 @@ type LoaderProps = {
msg: string
}
export default function Loader({ msg } : LoaderProps) {
export default function Loader({ msg }: LoaderProps) {
return (
<div id="loading" className="col">
<div id="loading" className="flex flex-col text-center">
<h3>{msg}</h3>
<div id="loader"> <div/> <div/> <div/> <div/> </div>
<div id="loader"> <div /> <div /> <div /> <div /> </div>
</div>
)
}

View File

@ -0,0 +1,26 @@
import { useState } from "react"
import classNames from 'classnames'
import { FaQuestion } from 'react-icons/fa6'
interface TooltipProps {
text: string
button?: React.ReactNode
}
export const Tooltip: React.FC<TooltipProps> = ({ text, button }) => {
const [showTooltip, setShowTooltip] = useState(false)
return <div className="flex place-items-center place-content-center text-sm relative">
<div onClick={() => setShowTooltip(!showTooltip)}>
{button || <button
className="icon ml-4"
type='button'
>
<FaQuestion />
</button>}
</div>
<div className={classNames('absolute top-16 rounded bg-black p-2 min-w-[200px] z-10', { "hidden": !showTooltip })}>
{text}
</div>
</div>
}

View File

@ -1,93 +0,0 @@
Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,9 @@ const root = ReactDOM.createRoot(
root.render(
<React.StrictMode>
<Web3ReactProvider connectors={connectors}>
<div id="signup-page" className="col">
<App />
</div>
<div id="signup-page" className="flex flex-col place-items-center place-content-center h-screen w-screen">
<App />
</div>
</Web3ReactProvider>
</React.StrictMode>
);

View File

@ -0,0 +1,146 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'Futura';
src: url('./assets/fonts/Futura-Heavy.ttf');
}
@font-face {
font-family: 'OpenSans';
src: url('./assets/fonts/OpenSans-CondBold.ttf');
}
@font-face {
font-family: 'Barlow';
src: url('./assets/fonts/BarlowCondensed-Black.ttf');
}
@layer components {
.heading {
font-family: OpenSans;
letter-spacing: -0.01em;
@apply leading-6 m-0;
}
.display {
font-family: Futura;
letter-spacing: 0.25em;
text-transform: uppercase;
}
h1,
h2,
h3,
h4,
h5,
h6 {
@apply heading;
}
h1 {
@apply text-3xl;
}
h2 {
@apply text-2xl;
}
h3 {
@apply text-xl;
}
h4 {
@apply text-lg;
}
h6 {
@apply text-sm;
}
.button {
@apply flex m-0 py-2 px-6 rounded border-orange bg-orange border-2 cursor-pointer place-items-center place-content-center text-center rounded-lg heading transition ease-in-out duration-100 hover:bg-black hover:text-white;
}
button {
@apply button;
}
.clear {
@apply bg-transparent border-transparent font-bold hover:bg-white/25 font-['Barlow'];
}
.alt {
@apply bg-white text-black border-white;
}
.thin {
@apply px-0 border-none;
}
.icon {
@apply flex items-center place-content-center bg-transparent w-11 p-3 text-[14px] rounded-full border-white/25;
}
.icon.alt {
@apply border-black/25 hover:border-white/25
}
}
body {
@apply bg-[url('./assets/background.jpg')] bg-cover bg-no-repeat bg-center bg-fixed text-white;
}
input {
all: unset;
}
select,
input[type="text"],
input[type="password"],
input[type="checkbox"] {
@apply px-4 py-2 rounded-lg bg-orange bg-opacity-25 text-white border border-orange border-2;
}
input[type="checkbox"] {
@apply w-2 h-2 cursor-pointer p-2;
}
input[type="checkbox"]:checked {
@apply bg-orange;
}
.checkmark {
@apply absolute left-1 text-xl -top-1 cursor-pointer;
}
::placeholder,
::-webkit-input-placeholder::placeholder,
::-moz-placeholder::placeholder,
::-ms-input-placeholder {
@apply !text-white;
}
select {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23ffffff" d="M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6-6-6z"/></svg>');
background-repeat: no-repeat;
background-position: right 1.25rem center;
@apply appearance-none pr-16;
}
button:hover {
@apply opacity-90 shadow-none;
}
button:disabled {
@apply opacity-70 cursor-not-allowed bg-gray border-gray;
}
.obox {
@apply rounded-lg p-4 bg-orange/25;
}
.network-icon {
@apply h-8 w-8;
}

View File

@ -3,7 +3,7 @@ import { hooks } from "../connectors/metamask";
import { Link, useNavigate } from "react-router-dom";
import EnterOsName from "../components/EnterKnsName";
import Loader from "../components/Loader";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import DirectCheckbox from "../components/DirectCheckbox";
@ -168,7 +168,7 @@ function ClaimOsInvite({
return (
<>
<OsHeader
<KinodeHeader
header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Claim
<NameLogo style={{ height: 28, width: "auto", margin: "0 16px -3px" }} />

View File

@ -7,7 +7,7 @@ import React, {
} from "react";
import { useNavigate } from "react-router-dom";
import { utils } from "ethers";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { PageProps } from "../lib/types";
import Loader from "../components/Loader";
@ -185,8 +185,8 @@ function ImportKeyfile({
return (
<>
<OsHeader
header={<h3>Import Keyfile</h3>}
<KinodeHeader
header={<h1>Import Keyfile</h1>}
openConnect={openConnect}
closeConnect={closeConnect}
hideConnect
@ -195,22 +195,16 @@ function ImportKeyfile({
{loading ? (
<Loader msg="Setting up node..." />
) : (
<form id="signup-form" className="col" onSubmit={handleImportKeyfile}>
<form id="signup-form" className="flex flex-col max-w-[450px]" onSubmit={handleImportKeyfile}>
<div
style={{
alignSelf: "flex-start",
display: "flex",
flexDirection: "column",
justifyContent: "center",
width: "100%",
}}
className="flex flex-col self-start place-content-center w-full"
>
<h4 className="login-row row" style={{ marginBottom: "0.5em" }}>
<h4 className="my-2 flex">
{" "}
1. Upload Keyfile{" "}
</h4>
{Boolean(localKeyFileName) && (
<h5 style={{ textDecoration: "underline", marginBottom: "0.5em" }}>
<h5 className="underline mb-2">
{" "}
{localKeyFileName ? localKeyFileName : ".keyfile"}{" "}
</h5>
@ -220,20 +214,19 @@ function ImportKeyfile({
</button>
<input
ref={keyfileInputRef}
style={{ display: "none" }}
className="hidden"
type="file"
onChange={handleKeyfile}
/>
</div>
<div className="col" style={{ width: "100%" }}>
<h4 className="login-row row" style={{ marginBottom: "0.5em" }}>
<div className="flex flex-col w-full">
<h4 className="my-2 flex">
{" "}
2. Enter Password{" "}
</h4>
<input
style={{ width: "100%" }}
type="password"
id="password"
required
@ -242,23 +235,24 @@ function ImportKeyfile({
placeholder="Min 6 characters"
value={pw}
onChange={(e) => setPw(e.target.value)}
className="mb-1"
/>
{pwErr && (
<div className="row">
<div className="flex">
{" "}
<p style={{ color: "red" }}> {pwErr} </p>{" "}
<p className="text-red-500"> {pwErr} </p>{" "}
</div>
)}
{pwDebounced && !pwVet && 6 <= pw.length && (
<div className="row">
<div className="flex">
{" "}
<p style={{ color: "red" }}> Password is incorrect </p>{" "}
<p className="text-red-500"> Password is incorrect </p>{" "}
</div>
)}
</div>
<div className="col" style={{ width: "100%" }}>
<div className="flex flex-col w-full mb-2">
{keyErrs.map((x, i) => (
<span key={i} className="key-err">
{x}
@ -266,7 +260,7 @@ function ImportKeyfile({
))}
<button type="submit"> Import Keyfile </button>
</div>
<p style={{ lineHeight: "1.25em", fontFamily: "Helvetica" }}>
<p className="text-sm">
Please note: if the original node was booted as a direct node
(static IP), then you must run this node from the same IP. If not,
you will have networking issues. If you need to change the network

View File

@ -1,8 +1,8 @@
import { useEffect } from "react"
import { useNavigate } from "react-router-dom"
import OsHeader from "../components/KnsHeader"
import {ReactComponent as Logo} from "../assets/logo.svg";
import {ReactComponent as NameLogo} from "../assets/kinode.svg"
import KinodeHeader from "../components/KnsHeader"
import { ReactComponent as Logo } from "../assets/logo.svg";
import { ReactComponent as NameLogo } from "../assets/kinode.svg"
import { OPTIMISM_OPT_HEX } from "../constants/chainId";
type OsHomeProps = {
@ -13,7 +13,7 @@ type OsHomeProps = {
nodeChainId: string
}
function OsHome({ openConnect, knsName, provider, closeConnect, nodeChainId }: OsHomeProps) {
function KinodeHome({ openConnect, knsName, provider, closeConnect, nodeChainId }: OsHomeProps) {
const navigate = useNavigate()
const inviteRedir = () => navigate('/claim-invite')
const registerEthRedir = () => navigate('/register-eth-name')
@ -32,26 +32,60 @@ function OsHome({ openConnect, knsName, provider, closeConnect, nodeChainId }: O
return (
<>
<OsHeader header={<>
<h3>Welcome to</h3>
<NameLogo style={{ height: 36 }} />
<Logo style={{ height: 42, marginTop: 8 }} />
</>} openConnect={openConnect} closeConnect={closeConnect} hideConnect nodeChainId={nodeChainId} nameLogo />
<div className="col" style={{ maxWidth: 'calc(100vw - 32px)', width: 460, gap: 20 }}>
<KinodeHeader header={<div className="flex flex-col place-items-center self-stretch mt-8">
<h1>Welcome to</h1>
<h1 className="display mt-8 text-6xl relative">
Kinode
<span className="text-[8px] absolute bottom-2">&reg;</span>
</h1>
</div>} openConnect={openConnect} closeConnect={closeConnect} hideConnect nodeChainId={nodeChainId} nameLogo />
<div className="flex flex-col max-w-[460px] w-full gap-4 mt-8">
{previouslyBooted ? (
<button onClick={loginRedir}> Login </button>
) : (
<>
{!hasNetwork && <h4 style={{ alignSelf: 'flex-start' }}>
{!hasNetwork && <h4 className="self-start mx-auto">
You must install a Web3 wallet extension like Metamask in order to register or reset a username.
</h4>}
{hasNetwork && <h4 style={{ alignSelf: 'flex-start' }}>New here? Register a username to get started</h4>}
<button disabled={!hasNetwork} onClick={registerRedir} className="alt"> Register Kinode Name </button>
<h4 style={{ alignSelf: 'flex-start' }}>Other options</h4>
{nodeChainId !== OPTIMISM_OPT_HEX && <button disabled={!hasNetwork} onClick={registerEthRedir} className="alt"> Register ENS Name </button>}
<button disabled={!hasNetwork} onClick={inviteRedir} className="alt"> Claim Kinode Invite </button>
<button disabled={!hasNetwork} onClick={resetRedir} className="alt"> Reset Kinode Name </button>
<button onClick={importKeyfileRedir}> Import Keyfile </button>
{hasNetwork && <h4 className="self-start mx-auto">
New here? Register a username to get started
</h4>}
<button
disabled={!hasNetwork}
onClick={registerRedir}
className="alt"
>
Register Kinode Name
</button>
<h4 className="self-start mx-auto">
Other options
</h4>
{nodeChainId !== OPTIMISM_OPT_HEX && <button
disabled={!hasNetwork}
onClick={registerEthRedir}
className="alt"
>
Register ENS Name
</button>}
<button
disabled={!hasNetwork}
onClick={inviteRedir}
className="alt"
>
Claim Kinode Invite
</button>
<button
disabled={!hasNetwork}
onClick={resetRedir}
className="alt"
>
Reset Kinode Name
</button>
<button
onClick={importKeyfileRedir}
>
Import Keyfile
</button>
</>
)}
</div>
@ -59,4 +93,4 @@ function OsHome({ openConnect, knsName, provider, closeConnect, nodeChainId }: O
)
}
export default OsHome
export default KinodeHome

View File

@ -2,14 +2,13 @@ import React, { FormEvent, useCallback, useEffect, useState } from "react";
import { namehash } from "ethers/lib/utils";
import { BytesLike, utils } from "ethers";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps, UnencryptedIdentity } from "../lib/types";
import Loader from "../components/Loader";
import { hooks } from "../connectors/metamask";
import { ipToNumber } from "../utils/ipToNumber";
import { downloadKeyfile } from "../utils/download-keyfile";
import DirectCheckbox from "../components/DirectCheckbox";
import { ReactComponent as NameLogo } from "../assets/kinode.svg"
import { useNavigate } from "react-router-dom";
const { useProvider } = hooks;
@ -186,11 +185,8 @@ function Login({
return (
<>
<OsHeader
header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Login to
<NameLogo style={{ height: 28, width: "auto", margin: "0 0 -3px 16px" }} />
</h3>}
<KinodeHeader
header={<h1>Login to Kinode</h1>}
openConnect={openConnect}
closeConnect={closeConnect}
hideConnect={!showReset}

View File

@ -5,7 +5,7 @@ import { toDNSWireFormat } from "../utils/dnsWire";
import { BytesLike, utils } from "ethers";
import EnterEthName from "../components/EnterEthName";
import Loader from "../components/Loader";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
@ -177,7 +177,7 @@ function RegisterEthName({
return (
<>
<OsHeader
<KinodeHeader
header={
<h3
className="row"

View File

@ -5,12 +5,13 @@ import { toDNSWireFormat } from "../utils/dnsWire";
import { BytesLike, utils } from 'ethers';
import EnterOsName from "../components/EnterKnsName";
import Loader from "../components/Loader";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { ReactComponent as NameLogo } from "../assets/kinode.svg"
import DirectCheckbox from "../components/DirectCheckbox";
import { Tooltip } from "../components/Tooltip";
const {
useAccounts,
@ -110,31 +111,44 @@ function RegisterOsName({
return (
<>
<OsHeader header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Register
<NameLogo style={{ height: 28, width: "auto", margin: "0 16px -3px" }} />
Name
</h3>} openConnect={openConnect} closeConnect={closeConnect} nodeChainId={nodeChainId} />
{Boolean(provider) && <form id="signup-form" className="col" onSubmit={handleRegister}>
<KinodeHeader header={<h1
className="flex place-content-center place-items-center mb-4"
>
Register Kinode Name
</h1>}
openConnect={openConnect}
closeConnect={closeConnect}
nodeChainId={nodeChainId}
/>
{Boolean(provider) && <form
id="signup-form"
className="flex flex-col w-full max-w-[450px]"
onSubmit={handleRegister}
>
{loading ? (
<Loader msg={loading} />
) : (
<>
<div style={{ width: '100%' }}>
<label className="login-row row" style={{ lineHeight: 1.5 }}>
Set up your Kinode with a .os name
<div className="tooltip-container" style={{ marginTop: -4 }}>
<div className="tooltip-button">&#8505;</div>
<div className="tooltip-content">Kinodes use a .os name in order to identify themselves to other nodes in the network</div>
</div>
<h3 className="flex flex-col w-full place-items-center my-8">
<label className="flex leading-6 place-items-center mt-2 cursor-pointer mb-2">
Choose a name for your kinode
<Tooltip text={`Kinodes use a .os name in order to identify themselves to other nodes in the network.`} />
</label>
<EnterOsName {...enterOsNameProps} />
</div>
</h3>
<DirectCheckbox {...{ direct, setDirect }} />
<button disabled={nameValidities.length !== 0} type="submit">
<button
disabled={nameValidities.length !== 0}
type="submit"
className="mt-2"
>
Register .os name
</button>
<Link to="/reset">already have an dot-os-name?</Link>
<Link to="/reset" className="flex self-stretch mt-2">
<button className="clear grow">
already have a dot-os-name?
</button>
</Link>
</>
)}
</form>}

View File

@ -12,11 +12,15 @@ import { toAscii } from "idna-uts46-hx";
import { hash } from "eth-ens-namehash";
import isValidDomain from "is-valid-domain";
import Loader from "../components/Loader";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { ReactComponent as NameLogo } from "../assets/kinode.svg"
import { Tooltip } from "../components/Tooltip";
import { DirectTooltip } from "../components/DirectTooltip";
import DirectCheckbox from "../components/DirectCheckbox";
import EnterOsName from "../components/EnterKnsName";
const NAME_INVALID_PUNY = "Unsupported punycode character";
const NAME_NOT_OWNER = "Name does not belong to this wallet";
@ -51,6 +55,7 @@ function Reset({
const chainName = getNetworkName(nodeChainId);
const [name, setName] = useState<string>(knsName.slice(0, -3));
const [nameVets, setNameVets] = useState<string[]>([]);
const [nameValidities, setNameValidities] = useState<string[]>([])
const [loading, setLoading] = useState<string>("");
const [triggerNameCheck, setTriggerNameCheck] = useState<boolean>(false);
@ -209,93 +214,30 @@ function Reset({
return (
<>
<OsHeader header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Reset
<NameLogo style={{ height: 28, width: "auto", margin: "0 16px -3px" }} />
Name
</h3>}
<KinodeHeader header={<h1 className="flex place-content-center place-items-center mb-4">
Reset Kinode Name
</h1>}
openConnect={openConnect}
closeConnect={closeConnect}
nodeChainId={nodeChainId}
/>
{Boolean(provider) && (
<form id="signup-form" className="col" onSubmit={handleResetRecords}>
<form id="signup-form" className="flex flex-col" onSubmit={handleResetRecords}>
{loading ? (
<Loader msg={loading} />
) : (
<>
<div className="col" style={{ width: "100%" }}>
<h5 className="login-row row" style={{ marginBottom: 8 }}>
Enter .os Name
<div className="tooltip-container">
<div className="tooltip-button">&#8505;</div>
<div className="tooltip-content" style={{ fontSize: 16 }}>
Kinodes use a .os name in order to identify themselves to
other nodes in the network
</div>
</div>
</h5>
<div
style={{
display: "flex",
alignItems: "center",
width: "100%",
marginBottom: "0.5em",
}}
>
<input
value={name}
onChange={(e) => setName(e.target.value)}
type="text"
required
name="dot-os-name"
placeholder="e.g. myname"
style={{ width: "100%", marginRight: 8 }}
/>
.os
</div>
{nameVets.map((x, i) => (
<span key={i} className="name-err">
{x}
</span>
))}
</div>
<div className="row">
<div style={{ position: "relative" }}>
<input
type="checkbox"
id="direct"
name="direct"
checked={direct}
onChange={(e) => setDirect(e.target.checked)}
autoFocus
/>
{direct && (
<span
onClick={() => setDirect(false)}
className="checkmark"
>
&#10003;
</span>
)}
</div>
<label htmlFor="direct" className="direct-node-message">
Register as a direct node. If you are unsure leave unchecked.
<h3 className="flex flex-col w-full place-items-center my-8">
<label className="flex leading-6 place-items-center mt-2 cursor-pointer mb-2">
Choose a name for your kinode
<Tooltip text={`Kinodes use a .os name in order to identify themselves to other nodes in the network.`} />
</label>
<div className="tooltip-container">
<div className="tooltip-button">&#8505;</div>
<div className="tooltip-content">
A direct node publishes its own networking information
on-chain: IP, port, so on. An indirect node relies on the
service of routers, which are themselves direct nodes. Only
register a direct node if you know what youre doing and
have a public, static IP address.
</div>
</div>
</div>
<EnterOsName {...{ name, setName, nameVets, dotOs, triggerNameCheck, nameValidities, setNameValidities }} />
</h3>
<button type="submit"> Reset Node </button>
<DirectCheckbox {...{ direct, setDirect }} />
<button type="submit" className="mt-2"> Reset Node </button>
</>
)}
</form>

View File

@ -12,11 +12,13 @@ import { toAscii } from "idna-uts46-hx";
import { hash } from "eth-ens-namehash";
import isValidDomain from "is-valid-domain";
import Loader from "../components/Loader";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { ReactComponent as NameLogo } from "../assets/kinode.svg"
import { Tooltip } from "../components/Tooltip";
import { DirectTooltip } from "../components/DirectTooltip";
const { useAccounts, useProvider } = hooks;
@ -144,7 +146,7 @@ function ResetNode({
return (
<>
<OsHeader header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
<KinodeHeader header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Reset
<NameLogo style={{ height: 28, width: "auto", margin: "0 16px -3px" }} />
Name
@ -187,16 +189,7 @@ function ResetNode({
<label htmlFor="direct" className="direct-node-message">
Register as a direct node. If you are unsure leave unchecked.
</label>
<div className="tooltip-container">
<div className="tooltip-button">&#8505;</div>
<div className="tooltip-content">
A direct node publishes its own networking information
on-chain: IP, port, so on. An indirect node relies on the
service of routers, which are themselves direct nodes. Only
register a direct node if you know what youre doing and
have a public, static IP address.
</div>
</div>
<DirectTooltip />
</div>
<button type="submit"> Reset Node </button>

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, FormEvent, useCallback } from "react";
import OsHeader from "../components/KnsHeader";
import KinodeHeader from "../components/KnsHeader";
import Loader from "../components/Loader";
import { utils, providers } from "ethers";
import { downloadKeyfile } from "../utils/download-keyfile";
@ -110,7 +110,7 @@ function SetPassword({
return (
<>
<OsHeader
<KinodeHeader
header={<h3 className="row" style={{ justifyContent: "center", alignItems: "center" }}>
Set
<NameLogo style={{ height: 28, width: "auto", margin: "0 16px -3px" }} />

View File

@ -0,0 +1,23 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{html,js,tsx}"],
theme: {
extend: {
colors: {
'white': '#FFF5D9',
'black': '#22211F',
'orange': '#F35422',
'transparent': 'transparent',
'gray': '#7E7E7E'
}
},
fontFamily: {
'sans': ['Barlow', '"Inter var"', 'ui-sans-serif', 'system-ui', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', '"Noto Sans"', 'sans-serif', '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"', '"Noto Color Emoji"'],
'serif': ['ui-serif', 'Georgia', 'Cambria', '"Times New Roman"', 'Times', 'serif'],
'mono': ['ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', '"Liberation Mono"', '"Courier New"', 'monospace'],
'heading': ['OpenSans', 'ui-sans-serif', 'system-ui', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', '"Noto Sans"', 'sans-serif', '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"', '"Noto Color Emoji"'],
'display': ['Futura', 'ui-sans-serif', 'system-ui', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', '"Noto Sans"', 'sans-serif', '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"', '"Noto Color Emoji"'],
},
},
plugins: [],
}

File diff suppressed because it is too large Load Diff