Handy/src/App.tsx
2025-09-09 18:59:09 -07:00

105 lines
3.3 KiB
TypeScript

import { invoke } from "@tauri-apps/api/core";
import { useEffect, useState } from "react";
import { Toaster } from "sonner";
import "./App.css";
import AccessibilityPermissions from "./components/AccessibilityPermissions";
import Footer from "./components/footer";
import HandyTextLogo from "./components/icons/HandyTextLogo";
import Onboarding from "./components/onboarding";
import { Sidebar, SidebarSection, SECTIONS_CONFIG } from "./components/Sidebar";
import { useSettings } from "./hooks/useSettings";
const renderSettingsContent = (section: SidebarSection) => {
const ActiveComponent =
SECTIONS_CONFIG[section]?.component || SECTIONS_CONFIG.general.component;
return <ActiveComponent />;
};
function App() {
const [showOnboarding, setShowOnboarding] = useState<boolean | null>(null);
const [currentSection, setCurrentSection] =
useState<SidebarSection>("general");
const { settings, updateSetting } = useSettings();
useEffect(() => {
checkOnboardingStatus();
}, []);
// Handle keyboard shortcuts for debug mode toggle
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
// Check for Ctrl+Shift+D (Windows/Linux) or Cmd+Shift+D (macOS)
const isDebugShortcut =
event.shiftKey &&
event.key.toLowerCase() === "d" &&
(event.ctrlKey || event.metaKey);
if (isDebugShortcut) {
event.preventDefault();
const currentDebugMode = settings?.debug_mode ?? false;
updateSetting("debug_mode", !currentDebugMode);
}
};
// Add event listener when component mounts
document.addEventListener("keydown", handleKeyDown);
// Cleanup event listener when component unmounts
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, [settings?.debug_mode, updateSetting]);
const checkOnboardingStatus = async () => {
try {
// Always check if they have any models available
const modelsAvailable: boolean = await invoke("has_any_models_available");
setShowOnboarding(!modelsAvailable);
} catch (error) {
console.error("Failed to check onboarding status:", error);
setShowOnboarding(true);
}
};
const handleModelSelected = () => {
// Transition to main app - user has started a download
setShowOnboarding(false);
};
if (showOnboarding) {
return (
<div className="h-screen flex flex-col">
<div className="flex-1 flex flex-col items-center justify-center p-4 gap-4">
<HandyTextLogo width={200} />
<Onboarding onModelSelected={handleModelSelected} />
</div>
</div>
);
}
return (
<div className="h-screen flex flex-col">
<Toaster />
{/* Main content area that takes remaining space */}
<div className="flex-1 flex overflow-hidden">
<Sidebar
activeSection={currentSection}
onSectionChange={setCurrentSection}
/>
{/* Scrollable content area */}
<div className="flex-1 flex flex-col overflow-hidden">
<div className="flex-1 overflow-y-auto">
<div className="flex flex-col items-center p-4 gap-4">
<AccessibilityPermissions />
{renderSettingsContent(currentSection)}
</div>
</div>
</div>
</div>
{/* Fixed footer at bottom */}
<Footer />
</div>
);
}
export default App;