feat: OpenAI compatibility improvements & build fixes
- Fix hydration mismatches and initialization errors - Add /v1/models endpoint for OpenAI clients - Add Codex response translator (Responses → OpenAI) - Fix circular dependencies and PropTypes - Add Material Symbols font and CSS fixes - Update README with deployment guide Co-merged from PR #18 (14/15 commits, skipped debug)
This commit is contained in:
parent
0848dd5d13
commit
d9b8e48725
15 changed files with 762 additions and 171 deletions
|
|
@ -1,31 +1,60 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
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;
|
||||
|
||||
// Listen for system theme changes
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const handleChange = () => {
|
||||
if (theme === "system") {
|
||||
initTheme();
|
||||
}
|
||||
};
|
||||
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: theme === "dark" || (theme === "system" && typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches),
|
||||
isDark,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue