Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions apps/web/app/components/layout/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useCallback, useMemo, useEffect } from "react";
import { useState, useCallback, useMemo } from "react";
import { Outlet, isRouteErrorResponse } from "react-router";
import { PlusIcon } from "lucide-react";
import { Button, cn } from "@kreozalabs/kei-ui";
Expand All @@ -12,6 +12,8 @@ import { useSettings } from "@/providers/SettingsContext";
import { MobileFABProvider, useMobileFAB } from "@/components/MobileFAB";
import { HeaderPortalContext } from "./HeaderPortalContext";
import { DbSyncStatus } from "./DbSyncStatus";
import { useFullscreen } from "@/hooks/useFullscreen";
import { useHotkeys } from "react-hotkeys-hook";

export interface AppLayoutContext {
isSidebarOpen: boolean;
Expand All @@ -35,13 +37,10 @@ function AppLayoutContent({ error }: { error?: unknown }) {
const [headerPortalRef, setHeaderPortalRef] = useState<HTMLElement | null>(null);

const toggleSidebar = useCallback(() => setIsSidebarOpen((prev) => !prev), []);
const { toggleFullscreen } = useFullscreen();

// Listen to global toggle-sidebar keyboard shortcuts.
useEffect(() => {
const handleToggle = () => toggleSidebar();
window.addEventListener("kei:toggle-sidebar", handleToggle);
return () => window.removeEventListener("kei:toggle-sidebar", handleToggle);
}, [toggleSidebar]);
useHotkeys("mod+b", toggleSidebar, { preventDefault: true });
useHotkeys("f", toggleFullscreen, { preventDefault: true });

const contextValue: AppLayoutContext = useMemo(
() => ({
Expand Down
5 changes: 2 additions & 3 deletions apps/web/app/components/settings/SystemSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// FIXME: Refactor !
import { useState, useEffect } from "react";
import { Link } from "react-router";
import { Button, cn, toast } from "@kreozalabs/kei-ui";
import { Button, cn, toast, GitHubIcon } from "@kreozalabs/kei-ui";
import { useP2P } from "@/providers/P2PProvider";
import { db } from "@/db";
import type { BenchmarkResult } from "@/db/webDatabaseAdapter";
Expand All @@ -15,7 +15,6 @@ import {
BellOff,
Layers,
Activity,
Github as GitHub,
ShieldCheck,
ShieldAlert,
} from "lucide-react";
Expand Down Expand Up @@ -367,7 +366,7 @@ export function SystemSettings() {
className="bg-background hover:bg-muted border-border/50 text-foreground h-9 w-full gap-1.5 rounded-xl px-3 text-xs font-semibold transition-all md:w-auto"
>
<Link to="https://github.com/kreozalabs/kei" target="_blank" rel="noopener noreferrer">
<GitHub className="size-3.5 shrink-0" />
<GitHubIcon className="size-3.5 shrink-0" />
<span>Source Code</span>
</Link>
</Button>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/config/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const navGroups: NavGroup[] = [
id: "days",
label: "Days",
icon: CalendarDaysIcon,
href: "/app",
href: "/app/calendar",
mobileVisible: true,
variant: "highlight",
},
Expand Down
24 changes: 0 additions & 24 deletions apps/web/app/hooks/useAppShortcuts.ts

This file was deleted.

80 changes: 0 additions & 80 deletions apps/web/app/hooks/useKeyboardShortcuts.ts

This file was deleted.

8 changes: 4 additions & 4 deletions apps/web/app/providers/ActionInputModalContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { createContext, useContext, useState, useCallback } from "react";
import React, { createContext, use, useState, useCallback } from "react";
import { AnimatePresence } from "framer-motion";
import { DragResizeWrapper } from "@/components/DragResizeWrapper";
import { ActionInput } from "@/components/action-input";
Expand Down Expand Up @@ -26,7 +26,7 @@ export function ActionInputModalProvider({ children }: { children: React.ReactNo
}, []);

return (
<ActionInputModalContext.Provider
<ActionInputModalContext
value={{
isActionInputOpen,
openActionInput,
Expand All @@ -45,12 +45,12 @@ export function ActionInputModalProvider({ children }: { children: React.ReactNo
</DragResizeWrapper>
)}
</AnimatePresence>
</ActionInputModalContext.Provider>
</ActionInputModalContext>
);
}

export function useActionInputModal() {
const context = useContext(ActionInputModalContext);
const context = use(ActionInputModalContext);
if (context === undefined) {
throw new Error("useActionInputModal must be used within an ActionInputModalProvider");
}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/providers/DbContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext } from "react";
import { createContext, use } from "react";

interface DbContextState {
isDbReady: boolean;
Expand All @@ -13,7 +13,7 @@ export const DbContext = createContext<DbContextState>({
});

export const useDb = () => {
const context = useContext(DbContext);
const context = use(DbContext);
if (context === undefined) {
throw new Error("useDb must be used within a DbProvider");
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/providers/DbProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ export function DbProvider({ children }: { children: React.ReactNode }) {
[isDbReady, dbError, isWriting]
);

return <DbContext.Provider value={value}>{children}</DbContext.Provider>;
return <DbContext value={value}>{children}</DbContext>;
}
8 changes: 4 additions & 4 deletions apps/web/app/providers/P2PProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// FIXME: Refactor !
/* eslint-disable react-refresh/only-export-components */
import React, { createContext, useContext, useState, useEffect, useRef, useCallback } from "react";
import React, { createContext, use, useState, useEffect, useRef, useCallback } from "react";
import { Button, toast } from "@kreozalabs/kei-ui";
import type { Event as DBEvent } from "@kreozalabs/kei-core";
import { getLocalWatermarks, getEventsSince } from "@/db/sync";
Expand Down Expand Up @@ -67,7 +67,7 @@ interface ChallengeResponseMessage {
const P2PContext = createContext<P2PContextType | undefined>(undefined);

export function useP2P() {
const context = useContext(P2PContext);
const context = use(P2PContext);
if (!context) {
throw new Error("useP2P must be used within a P2PProvider");
}
Expand Down Expand Up @@ -968,7 +968,7 @@ export function P2PProvider({ children }: { children: React.ReactNode }) {
};

return (
<P2PContext.Provider
<P2PContext
value={{
isPaired: !!pairingCode,
pairingCode,
Expand All @@ -981,6 +981,6 @@ export function P2PProvider({ children }: { children: React.ReactNode }) {
}}
>
{children}
</P2PContext.Provider>
</P2PContext>
);
}
4 changes: 2 additions & 2 deletions apps/web/app/providers/SettingsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext } from "react";
import { createContext, use } from "react";
import { DEFAULT_SETTINGS } from "@kreozalabs/kei-core";
import type { Settings } from "@kreozalabs/kei-core";

Expand All @@ -18,7 +18,7 @@ const initialState: SettingsProviderState = {
export const SettingsProviderContext = createContext<SettingsProviderState>(initialState);

export const useSettings = () => {
const context = useContext(SettingsProviderContext);
const context = use(SettingsProviderContext);
if (context === undefined) throw new Error("useSettings must be used within a SettingsProvider");
return context;
};
6 changes: 1 addition & 5 deletions apps/web/app/providers/SettingsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,5 @@ export function SettingsProvider({
[settings, updateSetting]
);

return (
<SettingsProviderContext.Provider {...props} value={value}>
{children}
</SettingsProviderContext.Provider>
);
return <SettingsProviderContext value={value}>{children}</SettingsProviderContext>;
}
23 changes: 17 additions & 6 deletions apps/web/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ScrollRestoration,
isRouteErrorResponse,
useRouteError,
useNavigate,
} from "react-router";

import { useEffect } from "react";
Expand All @@ -21,7 +22,7 @@ import { STORAGE_KEYS } from "@kreozalabs/kei-core";
import { registerPWA } from "./utils/pwa";
import { SyncListener } from "./components/SyncListener";
import { ActionInputModalProvider } from "./providers/ActionInputModalContext";
import { useAppShortcuts } from "./hooks/useAppShortcuts";
import { useHotkeys } from "react-hotkeys-hook";

export function Layout({ children }: { children: React.ReactNode }) {
useEffect(() => {
Expand Down Expand Up @@ -67,11 +68,21 @@ export function Layout({ children }: { children: React.ReactNode }) {
}

export default function App() {
useAppShortcuts({
toggleSidebar: () => {
window.dispatchEvent(new CustomEvent("kei:toggle-sidebar"));
},
});
const navigate = useNavigate();

// Navigation shortcuts
useHotkeys("g>s", () => navigate("/app/settings"), { preventDefault: true });
useHotkeys("g>d", () => navigate("/app/calendar/day"), { preventDefault: true });
useHotkeys("g>w", () => navigate("/app/calendar/week"), { preventDefault: true });
useHotkeys("g>m", () => navigate("/app/calendar/month"), { preventDefault: true });
useHotkeys("g>y", () => navigate("/app/calendar/year"), { preventDefault: true });
useHotkeys("g>i", () => navigate("/app/calendar/inbox"), { preventDefault: true });
useHotkeys("g>t", () => navigate("/app/calendar/day"), { preventDefault: true }); // TODO: Replace with TIMELINE !!!
useHotkeys("g>a", () => navigate("/app/calendar/agenda"), { preventDefault: true });
useHotkeys("g>l", () => navigate("/app/calendar/lists"), { preventDefault: true });

// Other shortcuts
useHotkeys("mod+k", () => console.log("Search..."), { preventDefault: true });

return (
<QueryProvider>
Expand Down
6 changes: 4 additions & 2 deletions apps/web/app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export default [
route("*", "routes/marketing/not-found.tsx"),
]),

// 2. Main App (Prefixed with /app or /dashboard)
// 2. Main App (Prefixed with /app)
route("app", "routes/app/_layout.tsx", [
index("routes/app/dashboard.tsx"),
route("settings", "routes/app/settings.tsx"),
index("routes/app/dashboard.tsx"),
route("calendar", "routes/app/dashboard.tsx", { id: "dashboard-calendar" }),
route("calendar/*", "routes/app/dashboard.tsx", { id: "dashboard-calendar-splat" }),
route("*", "routes/app/not-found.tsx"),
]),

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext } from "react";
import { createContext, use } from "react";
import type { Action } from "@kreozalabs/kei-core";
import type { ViewMode } from "../types";
import { useActionMutations } from "../hooks/useActionMutations";
Expand Down Expand Up @@ -44,7 +44,7 @@ export interface DashboardContextValue {
export const DashboardContext = createContext<DashboardContextValue | null>(null);

export function useDashboardContext() {
const context = useContext(DashboardContext);
const context = use(DashboardContext);
if (!context) {
throw new Error("useDashboardContext must be used within a DashboardProvider");
}
Expand Down
Loading