parent
efa765ea84
commit
a1d42fa9fb
@ -8,6 +8,7 @@ import { RootState } from "State/Store";
|
|||||||
import { HexKey, RawEvent, u256, UserMetadata, Lists } from "Nostr";
|
import { HexKey, RawEvent, u256, UserMetadata, Lists } from "Nostr";
|
||||||
import { bech32ToHex } from "Util"
|
import { bech32ToHex } from "Util"
|
||||||
import { DefaultRelays, HashtagRegex } from "Const";
|
import { DefaultRelays, HashtagRegex } from "Const";
|
||||||
|
import { RelaySettings } from "Nostr/Connection";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -27,7 +28,7 @@ export default function useEventPublisher() {
|
|||||||
const pubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
const pubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
||||||
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
|
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
|
||||||
const follows = useSelector<RootState, HexKey[]>(s => s.login.follows);
|
const follows = useSelector<RootState, HexKey[]>(s => s.login.follows);
|
||||||
const relays = useSelector<RootState>(s => s.login.relays);
|
const relays = useSelector((s: RootState) => s.login.relays);
|
||||||
const hasNip07 = 'nostr' in window;
|
const hasNip07 = 'nostr' in window;
|
||||||
|
|
||||||
async function signEvent(ev: NEvent): Promise<NEvent> {
|
async function signEvent(ev: NEvent): Promise<NEvent> {
|
||||||
@ -221,11 +222,11 @@ export default function useEventPublisher() {
|
|||||||
return await signEvent(ev);
|
return await signEvent(ev);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addFollow: async (pkAdd: HexKey | HexKey[]) => {
|
addFollow: async (pkAdd: HexKey | HexKey[], newRelays?: Record<string, RelaySettings>) => {
|
||||||
if (pubKey) {
|
if (pubKey) {
|
||||||
let ev = NEvent.ForPubKey(pubKey);
|
let ev = NEvent.ForPubKey(pubKey);
|
||||||
ev.Kind = EventKind.ContactList;
|
ev.Kind = EventKind.ContactList;
|
||||||
ev.Content = JSON.stringify(relays);
|
ev.Content = JSON.stringify(newRelays ?? relays);
|
||||||
let temp = new Set(follows);
|
let temp = new Set(follows);
|
||||||
if (Array.isArray(pkAdd)) {
|
if (Array.isArray(pkAdd)) {
|
||||||
pkAdd.forEach(a => temp.add(a));
|
pkAdd.forEach(a => temp.add(a));
|
||||||
|
@ -20,6 +20,7 @@ import { db } from "Db";
|
|||||||
import { bech32ToHex } from "Util";
|
import { bech32ToHex } from "Util";
|
||||||
import { NoteCreator } from "Element/NoteCreator";
|
import { NoteCreator } from "Element/NoteCreator";
|
||||||
import Plus from "Icons/Plus";
|
import Plus from "Icons/Plus";
|
||||||
|
import { RelaySettings } from "Nostr/Connection";
|
||||||
|
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
@ -101,6 +102,8 @@ export default function Layout() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function handleNewUser() {
|
async function handleNewUser() {
|
||||||
|
let newRelays: Record<string, RelaySettings> | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let rsp = await fetch("https://api.nostr.watch/v1/online");
|
let rsp = await fetch("https://api.nostr.watch/v1/online");
|
||||||
if (rsp.ok) {
|
if (rsp.ok) {
|
||||||
@ -108,8 +111,9 @@ export default function Layout() {
|
|||||||
let pickRandom = online.sort((a, b) => Math.random() >= 0.5 ? 1 : -1).slice(0, 4); // pick 4 random relays
|
let pickRandom = online.sort((a, b) => Math.random() >= 0.5 ? 1 : -1).slice(0, 4); // pick 4 random relays
|
||||||
|
|
||||||
let relayObjects = pickRandom.map(a => [a, { read: true, write: true }]);
|
let relayObjects = pickRandom.map(a => [a, { read: true, write: true }]);
|
||||||
|
newRelays = Object.fromEntries(relayObjects);
|
||||||
dispatch(setRelays({
|
dispatch(setRelays({
|
||||||
relays: Object.fromEntries(relayObjects),
|
relays: newRelays!,
|
||||||
createdAt: 1
|
createdAt: 1
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -117,7 +121,7 @@ export default function Layout() {
|
|||||||
console.warn(e);
|
console.warn(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ev = await pub.addFollow(bech32ToHex(SnortPubKey));
|
const ev = await pub.addFollow(bech32ToHex(SnortPubKey), newRelays);
|
||||||
pub.broadcast(ev);
|
pub.broadcast(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
import { ApiHost, RecommendedFollows } from "Const";
|
|
||||||
import AsyncButton from "Element/AsyncButton";
|
|
||||||
import FollowListBase from "Element/FollowListBase";
|
|
||||||
import ProfilePreview from "Element/ProfilePreview";
|
|
||||||
import { HexKey } from "Nostr";
|
|
||||||
import { useMemo, useState } from "react";
|
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { RootState } from "State/Store";
|
|
||||||
import { bech32ToHex } from "Util";
|
|
||||||
|
|
||||||
const TwitterFollowsApi = `${ApiHost}/api/v1/twitter/follows-for-nostr`;
|
|
||||||
|
|
||||||
export default function NewUserPage() {
|
|
||||||
const [twitterUsername, setTwitterUsername] = useState<string>("");
|
|
||||||
const [follows, setFollows] = useState<string[]>([]);
|
|
||||||
const currentFollows = useSelector<RootState, HexKey[]>(s => s.login.follows);
|
|
||||||
const [error, setError] = useState<string>("");
|
|
||||||
|
|
||||||
const sortedReccomends = useMemo(() => {
|
|
||||||
return RecommendedFollows
|
|
||||||
.sort(a => Math.random() >= 0.5 ? -1 : 1);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const sortedTwitterFollows = useMemo(() => {
|
|
||||||
return follows.map(a => bech32ToHex(a))
|
|
||||||
.sort((a, b) => currentFollows.includes(a) ? 1 : -1);
|
|
||||||
}, [follows, currentFollows]);
|
|
||||||
|
|
||||||
async function loadFollows() {
|
|
||||||
setFollows([]);
|
|
||||||
setError("");
|
|
||||||
try {
|
|
||||||
let rsp = await fetch(`${TwitterFollowsApi}?username=${twitterUsername}`);
|
|
||||||
let data = await rsp.json();
|
|
||||||
if (rsp.ok) {
|
|
||||||
if (Array.isArray(data) && data.length === 0) {
|
|
||||||
setError(`No nostr users found for "${twitterUsername}"`);
|
|
||||||
} else {
|
|
||||||
setFollows(data);
|
|
||||||
}
|
|
||||||
} else if ("error" in data) {
|
|
||||||
setError(data.error);
|
|
||||||
} else {
|
|
||||||
setError("Failed to load follows, please try again later");
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
setError("Failed to load follows, please try again later");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function followSomebody() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h2>Follow some popular accounts</h2>
|
|
||||||
{sortedReccomends.map(a => <ProfilePreview key={a} pubkey={a.toLowerCase()} />)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function importTwitterFollows() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h2>Import twitter follows</h2>
|
|
||||||
<p>Find your twitter follows on nostr (Data provided by <a href="https://nostr.directory" target="_blank" rel="noreferrer">nostr.directory</a>)</p>
|
|
||||||
<div className="flex">
|
|
||||||
<input type="text" placeholder="Twitter username.." className="f-grow mr10" value={twitterUsername} onChange={e => setTwitterUsername(e.target.value)} />
|
|
||||||
<AsyncButton onClick={loadFollows}>Check</AsyncButton>
|
|
||||||
</div>
|
|
||||||
{error.length > 0 && <b className="error">{error}</b>}
|
|
||||||
{sortedTwitterFollows.length > 0 && (<FollowListBase pubkeys={sortedTwitterFollows} />)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="main-content">
|
|
||||||
{importTwitterFollows()}
|
|
||||||
{followSomebody()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
26
src/Pages/new/DiscoverFollows.tsx
Normal file
26
src/Pages/new/DiscoverFollows.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { RecommendedFollows } from "Const";
|
||||||
|
import FollowListBase from "Element/FollowListBase";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function DiscoverFollows() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const sortedReccomends = useMemo(() => {
|
||||||
|
return RecommendedFollows
|
||||||
|
.sort(a => Math.random() >= 0.5 ? -1 : 1);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2>Follow some popular accounts</h2>
|
||||||
|
<button onClick={() => navigate("/")}>
|
||||||
|
Skip
|
||||||
|
</button>
|
||||||
|
{sortedReccomends.length > 0 && (<FollowListBase pubkeys={sortedReccomends} />)}
|
||||||
|
<button onClick={() => navigate("/")}>
|
||||||
|
Done!
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
67
src/Pages/new/ImportFollows.tsx
Normal file
67
src/Pages/new/ImportFollows.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import { ApiHost } from "Const";
|
||||||
|
import AsyncButton from "Element/AsyncButton";
|
||||||
|
import FollowListBase from "Element/FollowListBase";
|
||||||
|
import { RootState } from "State/Store";
|
||||||
|
import { bech32ToHex } from "Util";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
const TwitterFollowsApi = `${ApiHost}/api/v1/twitter/follows-for-nostr`;
|
||||||
|
|
||||||
|
export default function ImportFollows() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const currentFollows = useSelector((s: RootState) => s.login.follows);
|
||||||
|
const [twitterUsername, setTwitterUsername] = useState<string>("");
|
||||||
|
const [follows, setFollows] = useState<string[]>([]);
|
||||||
|
const [error, setError] = useState<string>("");
|
||||||
|
|
||||||
|
|
||||||
|
const sortedTwitterFollows = useMemo(() => {
|
||||||
|
return follows.map(a => bech32ToHex(a))
|
||||||
|
.sort((a, b) => currentFollows.includes(a) ? 1 : -1);
|
||||||
|
}, [follows, currentFollows]);
|
||||||
|
|
||||||
|
async function loadFollows() {
|
||||||
|
setFollows([]);
|
||||||
|
setError("");
|
||||||
|
try {
|
||||||
|
let rsp = await fetch(`${TwitterFollowsApi}?username=${twitterUsername}`);
|
||||||
|
let data = await rsp.json();
|
||||||
|
if (rsp.ok) {
|
||||||
|
if (Array.isArray(data) && data.length === 0) {
|
||||||
|
setError(`No nostr users found for "${twitterUsername}"`);
|
||||||
|
} else {
|
||||||
|
setFollows(data);
|
||||||
|
}
|
||||||
|
} else if ("error" in data) {
|
||||||
|
setError(data.error);
|
||||||
|
} else {
|
||||||
|
setError("Failed to load follows, please try again later");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
setError("Failed to load follows, please try again later");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2>Import Twitter Follows</h2>
|
||||||
|
<p>
|
||||||
|
Find your twitter follows on nostr (Data provided by <a href="https://nostr.directory" target="_blank" rel="noreferrer">nostr.directory</a>)
|
||||||
|
</p>
|
||||||
|
<div className="flex">
|
||||||
|
<input type="text" placeholder="Twitter username.." className="f-grow mr10" value={twitterUsername} onChange={e => setTwitterUsername(e.target.value)} />
|
||||||
|
<AsyncButton onClick={loadFollows}>Check</AsyncButton>
|
||||||
|
</div>
|
||||||
|
{error.length > 0 && <b className="error">{error}</b>}
|
||||||
|
{sortedTwitterFollows.length > 0 && (<FollowListBase pubkeys={sortedTwitterFollows} />)}
|
||||||
|
|
||||||
|
<button onClick={() => navigate("/new/discover")}>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
15
src/Pages/new/NewProfile.tsx
Normal file
15
src/Pages/new/NewProfile.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import ProfileSettings from "Pages/settings/Profile";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function NewUserProfile() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Setup your Profile</h1>
|
||||||
|
<ProfileSettings privateKey={false} banner={false} />
|
||||||
|
<button onClick={() => navigate("/new/import")}>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
86
src/Pages/new/index.tsx
Normal file
86
src/Pages/new/index.tsx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { RouteObject, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import Copy from "Element/Copy";
|
||||||
|
import { RootState } from "State/Store";
|
||||||
|
import { hexToBech32 } from "Util";
|
||||||
|
import NewUserProfile from "Pages/new//NewProfile";
|
||||||
|
import ImportFollows from "Pages/new/ImportFollows";
|
||||||
|
import DiscoverFollows from "Pages/new/DiscoverFollows";
|
||||||
|
|
||||||
|
export const NewUserRoutes: RouteObject[] = [
|
||||||
|
{
|
||||||
|
path: "/new",
|
||||||
|
element: <NewUserFlow />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/new/profile",
|
||||||
|
element: <NewUserProfile />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/new/import",
|
||||||
|
element: <ImportFollows />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/new/discover",
|
||||||
|
element: <DiscoverFollows />
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function NewUserFlow() {
|
||||||
|
const { privateKey } = useSelector((s: RootState) => s.login);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Welcome to Snort!</h1>
|
||||||
|
<p>
|
||||||
|
Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing "notes".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Notes hold text content, the most popular usage of these notes is to store "tweet like" messages.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Snort is designed to have a similar experience to Twitter.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Keys</h2>
|
||||||
|
<p>
|
||||||
|
Nostr uses digital signature technology to provide tamper proof notes which can safely
|
||||||
|
be replicated to many relays to provide redundant storage of your content.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This means that nobody can modify notes which you have created
|
||||||
|
and everybody can easily verify that the notes they are reading are created by you.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This is the same technology which is used by Bitcoin and has been proven to be extremely secure.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Your Key</h2>
|
||||||
|
<p>
|
||||||
|
When you want to author new notes you need to sign them with your private key,
|
||||||
|
as with Bitcoin private keys these need to be kept secure.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please now copy your private key and save it somewhere secure:
|
||||||
|
</p>
|
||||||
|
<div className="card">
|
||||||
|
<Copy text={hexToBech32("nsec", privateKey ?? "")} />
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
It is also recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://getalby.com/" target="_blank" rel="noreferrer">Alby</a></li>
|
||||||
|
<li><a href="https://github.com/fiatjaf/nos2x" target="_blank" rel="noreferrer">nos2x</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
You can also use these extensions to login to most Nostr sites.
|
||||||
|
</p>
|
||||||
|
<button onClick={() => navigate("/new/profile")}>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -9,14 +9,19 @@ import { faShop } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import useEventPublisher from "Feed/EventPublisher";
|
import useEventPublisher from "Feed/EventPublisher";
|
||||||
import { useUserProfile } from "Feed/ProfileFeed";
|
import { useUserProfile } from "Feed/ProfileFeed";
|
||||||
import LogoutButton from "Element/LogoutButton";
|
|
||||||
import { hexToBech32, openFile } from "Util";
|
import { hexToBech32, openFile } from "Util";
|
||||||
import Copy from "Element/Copy";
|
import Copy from "Element/Copy";
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import { HexKey } from "Nostr";
|
import { HexKey } from "Nostr";
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "Upload";
|
||||||
|
|
||||||
export default function ProfileSettings() {
|
export interface ProfileSettingsProps {
|
||||||
|
avatar?: boolean,
|
||||||
|
banner?: boolean,
|
||||||
|
privateKey?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const id = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
const id = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
||||||
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
|
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
|
||||||
@ -145,7 +150,6 @@ export default function ProfileSettings() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<div>
|
<div>
|
||||||
<LogoutButton />
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button type="button" onClick={() => saveProfile()}>Save</button>
|
<button type="button" onClick={() => saveProfile()}>Save</button>
|
||||||
@ -160,18 +164,18 @@ export default function ProfileSettings() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex f-center image-settings">
|
<div className="flex f-center image-settings">
|
||||||
<div>
|
{(props.avatar ?? true) && (<div>
|
||||||
<h2>Avatar</h2>
|
<h2>Avatar</h2>
|
||||||
<div style={{ backgroundImage: `url(${avatarPicture})` }} className="avatar">
|
<div style={{ backgroundImage: `url(${avatarPicture})` }} className="avatar">
|
||||||
<div className="edit" onClick={() => setNewAvatar()}>Edit</div>
|
<div className="edit" onClick={() => setNewAvatar()}>Edit</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>)}
|
||||||
<div>
|
{(props.banner ?? true) && (<div>
|
||||||
<h2>Header</h2>
|
<h2>Header</h2>
|
||||||
<div style={{ backgroundImage: `url(${(banner?.length ?? 0) === 0 ? Nostrich : banner})` }} className="banner">
|
<div style={{ backgroundImage: `url(${(banner?.length ?? 0) === 0 ? Nostrich : banner})` }} className="banner">
|
||||||
<div className="edit" onClick={() => setNewBanner()}>Edit</div>
|
<div className="edit" onClick={() => setNewBanner()}>Edit</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>)}
|
||||||
</div>
|
</div>
|
||||||
{editor()}
|
{editor()}
|
||||||
</>
|
</>
|
||||||
@ -180,9 +184,9 @@ export default function ProfileSettings() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settings">
|
<div className="settings">
|
||||||
<h3>Profile</h3>
|
<h3>Edit Profile</h3>
|
||||||
{settings()}
|
{settings()}
|
||||||
{privKey && (<div className="flex f-col bg-grey">
|
{privKey && (props.privateKey ?? true) && (<div className="flex f-col bg-grey">
|
||||||
<div>
|
<div>
|
||||||
<h4>Your Private Key Is (do not share this with anyone):</h4>
|
<h4>Your Private Key Is (do not share this with anyone):</h4>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,7 +19,6 @@ import LoginPage from 'Pages/Login';
|
|||||||
import ProfilePage from 'Pages/ProfilePage';
|
import ProfilePage from 'Pages/ProfilePage';
|
||||||
import RootPage from 'Pages/Root';
|
import RootPage from 'Pages/Root';
|
||||||
import NotificationsPage from 'Pages/Notifications';
|
import NotificationsPage from 'Pages/Notifications';
|
||||||
import NewUserPage from 'Pages/NewUserPage';
|
|
||||||
import SettingsPage, { SettingsRoutes } from 'Pages/SettingsPage';
|
import SettingsPage, { SettingsRoutes } from 'Pages/SettingsPage';
|
||||||
import ErrorPage from 'Pages/ErrorPage';
|
import ErrorPage from 'Pages/ErrorPage';
|
||||||
import VerificationPage from 'Pages/Verification';
|
import VerificationPage from 'Pages/Verification';
|
||||||
@ -29,6 +28,7 @@ import DonatePage from 'Pages/DonatePage';
|
|||||||
import HashTagsPage from 'Pages/HashTagsPage';
|
import HashTagsPage from 'Pages/HashTagsPage';
|
||||||
import SearchPage from 'Pages/SearchPage';
|
import SearchPage from 'Pages/SearchPage';
|
||||||
import HelpPage from 'Pages/HelpPage';
|
import HelpPage from 'Pages/HelpPage';
|
||||||
|
import { NewUserRoutes } from 'Pages/new';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP query provider
|
* HTTP query provider
|
||||||
@ -66,10 +66,6 @@ export const router = createBrowserRouter([
|
|||||||
path: "/notifications",
|
path: "/notifications",
|
||||||
element: <NotificationsPage />
|
element: <NotificationsPage />
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/new",
|
|
||||||
element: <NewUserPage />
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
element: <SettingsPage />,
|
element: <SettingsPage />,
|
||||||
@ -98,7 +94,8 @@ export const router = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
path: "/search/:keyword?",
|
path: "/search/:keyword?",
|
||||||
element: <SearchPage />
|
element: <SearchPage />
|
||||||
}
|
},
|
||||||
|
...NewUserRoutes
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
Loading…
Reference in New Issue
Block a user