Files
kima-hub/frontend/lib/features-context.tsx
Your Name 977e94582a fix: onboarding validation rejects disabled integrations, hide audiobooks when disabled (#162)
- Backend: conditional URL validation -- skip format check when integration is disabled
- Frontend: send clean payloads for disabled integrations during onboarding
- Sidebar: hide Audiobooks nav item when Audiobookshelf is not enabled
- Feature detection: expose audiobookshelfEnabled flag via /system/features
- Audiobooks: use refetchQueries instead of invalidateQueries after sync for immediate UI update
2026-03-23 16:53:50 -05:00

67 lines
1.9 KiB
TypeScript

"use client";
import { createContext, useContext, useEffect, useState, useMemo, ReactNode } from "react";
import { api } from "./api";
import { useAuth } from "./auth-context";
interface FeaturesState {
musicCNN: boolean;
vibeEmbeddings: boolean;
audiobookshelfEnabled: boolean;
loading: boolean;
}
const defaultState: FeaturesState = {
musicCNN: false,
vibeEmbeddings: false,
audiobookshelfEnabled: false,
loading: true,
};
const FeaturesContext = createContext<FeaturesState | undefined>(undefined);
export function FeaturesProvider({ children }: { children: ReactNode }) {
const { isAuthenticated } = useAuth();
const [state, setState] = useState<FeaturesState>(defaultState);
useEffect(() => {
if (!isAuthenticated) return;
const fetchFeatures = () => {
api.getFeatures()
.then((features) => {
setState({
musicCNN: features.musicCNN,
vibeEmbeddings: features.vibeEmbeddings,
audiobookshelfEnabled: features.audiobookshelfEnabled,
loading: false,
});
})
.catch((error) => {
console.error("Failed to fetch features:", error);
setState((prev) => ({ ...prev, loading: false }));
});
};
fetchFeatures();
const interval = setInterval(fetchFeatures, 60000);
return () => clearInterval(interval);
}, [isAuthenticated]);
const value = useMemo(() => state, [state]);
return (
<FeaturesContext.Provider value={value}>
{children}
</FeaturesContext.Provider>
);
}
export function useFeatures(): FeaturesState {
const context = useContext(FeaturesContext);
if (!context) {
throw new Error("useFeatures must be used within FeaturesProvider");
}
return context;
}