mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 12:52:11 +03:00
OmniRoute is an intelligent API gateway that unifies 20+ AI providers behind a single OpenAI-compatible endpoint. Features include intelligent routing with 6 strategies, multi-format translation (OpenAI/Claude/Gemini/Responses API), circuit breakers, semantic caching, combo fallback chains, real-time health monitoring, and a full dashboard with provider management, analytics, and CLI tool integration. Key highlights: - 20+ providers (Claude Code, Codex, Gemini CLI, GitHub Copilot, iFlow, Qwen, Kiro, etc.) - 6 routing strategies (Fill First, Round Robin, P2C, Random, Least Used, Cost Optimized) - Export/Import database backup with full archive support - Translator Playground with 4 modes (Playground, Chat Tester, Test Bench, Live Monitor) - 100% TypeScript across src/ and open-sse/ - Docker support with multi-stage builds - Comprehensive documentation and 9 dashboard screenshots
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
import useThemeStore from "@/store/themeStore";
|
|
|
|
// Subscribe to system theme changes
|
|
function subscribeToSystemTheme(callback) {
|
|
if (typeof window === "undefined") return () => {};
|
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
mediaQuery.addEventListener("change", callback);
|
|
return () => mediaQuery.removeEventListener("change", callback);
|
|
}
|
|
|
|
// Get current system theme preference
|
|
function getSystemThemeSnapshot() {
|
|
if (typeof window === "undefined") return false;
|
|
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
}
|
|
|
|
// Server snapshot always returns false
|
|
function getServerSnapshot() {
|
|
return false;
|
|
}
|
|
|
|
export function useTheme() {
|
|
const { theme, setTheme, toggleTheme, initTheme } = useThemeStore();
|
|
|
|
// Use useSyncExternalStore to safely subscribe to system theme
|
|
const systemPrefersDark = useSyncExternalStore(
|
|
subscribeToSystemTheme,
|
|
getSystemThemeSnapshot,
|
|
getServerSnapshot
|
|
);
|
|
|
|
useEffect(() => {
|
|
initTheme();
|
|
}, [initTheme]);
|
|
|
|
// Listen for system theme changes when theme is "system"
|
|
useEffect(() => {
|
|
if (theme !== "system") return;
|
|
|
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
const handleChange = () => initTheme();
|
|
|
|
mediaQuery.addEventListener("change", handleChange);
|
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
}, [theme, initTheme]);
|
|
|
|
// Compute isDark from current state (no effect needed)
|
|
const isDark = theme === "dark" || (theme === "system" && systemPrefersDark);
|
|
|
|
return {
|
|
theme,
|
|
setTheme,
|
|
toggleTheme,
|
|
isDark,
|
|
};
|
|
}
|