diff --git a/src/app.tsx b/src/app.tsx
index c07db22ca..562e914fc 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -79,6 +79,7 @@ import TransformNoteView from "./views/tools/transform-note";
import SatelliteCDNView from "./views/tools/satellite-cdn";
import OtherStuffView from "./views/other-stuff";
import { RouteProviders } from "./providers/route";
+import LaunchpadView from "./views/launchpad";
const UserTracksTab = lazy(() => import("./views/user/tracks"));
const ToolsHomeView = lazy(() => import("./views/tools"));
@@ -200,6 +201,14 @@ const router = createHashRouter([
path: "map",
element: ,
},
+ {
+ path: "launchpad",
+ element: (
+
+
+
+ ),
+ },
{
path: "/",
element: ,
diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx
index b0ac07a6c..08b9dd484 100644
--- a/src/components/layout/index.tsx
+++ b/src/components/layout/index.tsx
@@ -1,6 +1,5 @@
-import React, { useEffect } from "react";
-import { Box, Container, Flex, Spacer, useDisclosure } from "@chakra-ui/react";
-import { useKeyPressEvent } from "react-use";
+import React from "react";
+import { Box, Container, Flex, Spacer } from "@chakra-ui/react";
import { ErrorBoundary } from "../error-boundary";
import { ReloadPrompt } from "../reload-prompt";
@@ -10,25 +9,10 @@ import useSubject from "../../hooks/use-subject";
import accountService from "../../services/account";
import GhostToolbar from "./ghost-toolbar";
import { useBreakpointValue } from "../../providers/global/breakpoint-provider";
-import SearchModal from "../search-modal";
-import { useLocation } from "react-router-dom";
export default function Layout({ children }: { children: React.ReactNode }) {
const isMobile = useBreakpointValue({ base: true, md: false });
const isGhost = useSubject(accountService.isGhost);
- const searchModal = useDisclosure();
-
- useKeyPressEvent("k", (e) => {
- if (e.ctrlKey) {
- e.preventDefault();
- searchModal.onOpen();
- }
- });
-
- const location = useLocation();
- useEffect(() => {
- searchModal.onClose();
- }, [location.pathname]);
return (
<>
@@ -64,7 +48,6 @@ export default function Layout({ children }: { children: React.ReactNode }) {
{isGhost && }
- {searchModal.isOpen && }
>
);
}
diff --git a/src/components/layout/nav-items.tsx b/src/components/layout/nav-items.tsx
index 1ceb19082..1b2077e90 100644
--- a/src/components/layout/nav-items.tsx
+++ b/src/components/layout/nav-items.tsx
@@ -1,4 +1,5 @@
-import { Box, Button, ButtonProps, Link, Text, useDisclosure } from "@chakra-ui/react";
+import { useRef } from "react";
+import { Box, Button, ButtonProps, Code, Link, Text, useDisclosure } from "@chakra-ui/react";
import { Link as RouterLink, useLocation } from "react-router-dom";
import { nip19 } from "nostr-tools";
import dayjs from "dayjs";
@@ -19,10 +20,31 @@ import {
} from "../icons";
import useCurrentAccount from "../../hooks/use-current-account";
import accountService from "../../services/account";
-import { useLocalStorage } from "react-use";
+import { useKeyPressEvent, useLocalStorage } from "react-use";
import ZapModal from "../event-zap-modal";
import PuzzlePiece01 from "../icons/puzzle-piece-01";
import Package from "../icons/package";
+import Rocket02 from "../icons/rocket-02";
+import { useBreakpointValue } from "../../providers/global/breakpoint-provider";
+
+function KBD({ letter }: { letter: string }) {
+ const ref = useRef(null);
+ useKeyPressEvent(
+ (e) => e.ctrlKey && e.key === letter,
+ (e) => {
+ if (ref.current?.parentElement) {
+ e.preventDefault();
+ ref.current.parentElement.click();
+ }
+ },
+ );
+
+ return (
+
+ ⌘{letter}
+
+ );
+}
export default function NavItems() {
const location = useLocation();
@@ -31,6 +53,8 @@ export default function NavItems() {
const donateModal = useDisclosure();
const [lastDonate, setLastDonate] = useLocalStorage("last-donate");
+ const showShortcuts = useBreakpointValue({ base: false, md: true });
+
const buttonProps: ButtonProps = {
py: "2",
justifyContent: "flex-start",
@@ -39,6 +63,7 @@ export default function NavItems() {
let active = "notes";
if (location.pathname.startsWith("/notifications")) active = "notifications";
+ else if (location.pathname.startsWith("/launchpad")) active = "launchpad";
else if (location.pathname.startsWith("/dvm")) active = "dvm";
else if (location.pathname.startsWith("/dm")) active = "dm";
else if (location.pathname.startsWith("/streams")) active = "streams";
@@ -69,6 +94,16 @@ export default function NavItems() {
return (
<>
+ }
+ colorScheme={active === "launchpad" ? "primary" : undefined}
+ {...buttonProps}
+ >
+ Launchpad
+ {showShortcuts && }
+
>
)}
@@ -117,6 +154,7 @@ export default function NavItems() {
{...buttonProps}
>
Search
+ {showShortcuts && }
{account?.pubkey && (