feat: goose windows (#880)
Co-authored-by: Ryan Versaw <ryan@versaw.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ScrollArea } from '../ui/scroll-area';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Settings as SettingsType } from './types';
|
||||
import {
|
||||
@@ -15,6 +14,7 @@ import { ConfigureBuiltInExtensionModal } from './extensions/ConfigureBuiltInExt
|
||||
import BackButton from '../ui/BackButton';
|
||||
import { RecentModelsRadio } from './models/RecentModels';
|
||||
import { ExtensionItem } from './extensions/ExtensionItem';
|
||||
import type { View } from '../../ChatWindow';
|
||||
|
||||
const EXTENSIONS_DESCRIPTION =
|
||||
'The Model Context Protocol (MCP) is a system that allows AI models to securely connect with local or remote resources using standard server setups. It works like a client-server setup and expands AI capabilities using three main components: Prompts, Resources, and Tools.';
|
||||
@@ -46,9 +46,18 @@ const DEFAULT_SETTINGS: SettingsType = {
|
||||
extensions: BUILT_IN_EXTENSIONS,
|
||||
};
|
||||
|
||||
export default function Settings() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
// We'll accept two props:
|
||||
// onClose: to go back to chat
|
||||
// setView: to switch to moreModels, configureProviders, etc.
|
||||
export default function Settings({
|
||||
onClose,
|
||||
setView,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
setView: (view: View) => void;
|
||||
}) {
|
||||
// We'll read query params from window.location instead of react-router's useLocation
|
||||
const [searchParams] = useState(() => new URLSearchParams(window.location.search));
|
||||
|
||||
const [settings, setSettings] = React.useState<SettingsType>(() => {
|
||||
const saved = localStorage.getItem('user_settings');
|
||||
@@ -96,9 +105,8 @@ export default function Settings() {
|
||||
|
||||
// Handle URL parameters for auto-opening extension configuration
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const extensionId = params.get('extensionId');
|
||||
const showEnvVars = params.get('showEnvVars');
|
||||
const extensionId = searchParams.get('extensionId');
|
||||
const showEnvVars = searchParams.get('showEnvVars');
|
||||
|
||||
if (extensionId && showEnvVars === 'true') {
|
||||
// Find the extension in settings
|
||||
@@ -113,7 +121,9 @@ export default function Settings() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [location.search, settings.extensions]);
|
||||
// We only run this once on load
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [settings.extensions]);
|
||||
|
||||
const handleExtensionToggle = async (extensionId: string) => {
|
||||
// Find the extension to get its current state
|
||||
@@ -160,28 +170,11 @@ export default function Settings() {
|
||||
extensions: prev.extensions.filter((ext) => ext.id !== extensionBeingConfigured.id),
|
||||
}));
|
||||
setExtensionBeingConfigured(null);
|
||||
navigate('/settings', { replace: true });
|
||||
}
|
||||
};
|
||||
|
||||
const handleNavClick = (section: string, e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
const scrollArea = document.querySelector('[data-radix-scroll-area-viewport]');
|
||||
const element = document.getElementById(section.toLowerCase());
|
||||
|
||||
if (scrollArea && element) {
|
||||
const topPos = element.offsetTop;
|
||||
scrollArea.scrollTo({
|
||||
top: topPos,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleExtensionConfigSubmit = () => {
|
||||
setExtensionBeingConfigured(null);
|
||||
// Clear the URL parameters after configuration
|
||||
navigate('/settings', { replace: true });
|
||||
};
|
||||
|
||||
const isBuiltIn = (extensionId: string) => {
|
||||
@@ -197,7 +190,8 @@ export default function Settings() {
|
||||
<div className="px-8 pt-6 pb-4">
|
||||
<BackButton
|
||||
onClick={() => {
|
||||
navigate('/chat/1', { replace: true });
|
||||
// Instead of navigate('/chat/1', { replace: true });
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
<h1 className="text-3xl font-medium text-textStandard mt-1">Settings</h1>
|
||||
@@ -210,7 +204,10 @@ export default function Settings() {
|
||||
<div className="flex justify-between items-center mb-6 border-b border-borderSubtle px-8">
|
||||
<h2 className="text-xl font-medium text-textStandard">Models</h2>
|
||||
<button
|
||||
onClick={() => navigate('/settings/more-models')}
|
||||
onClick={() => {
|
||||
// Instead of navigate('/settings/more-models'):
|
||||
setView('moreModels');
|
||||
}}
|
||||
className="text-indigo-500 hover:text-indigo-600 text-sm"
|
||||
>
|
||||
Browse
|
||||
@@ -230,7 +227,6 @@ export default function Settings() {
|
||||
className="text-indigo-500 hover:text-indigo-600 text-sm"
|
||||
title="Add Manually"
|
||||
>
|
||||
{/* <Plus className="h-4 w-4" /> */}
|
||||
Add
|
||||
</button>
|
||||
|
||||
@@ -255,7 +251,7 @@ export default function Settings() {
|
||||
<ExtensionItem
|
||||
key={ext.id}
|
||||
{...ext}
|
||||
canConfigure={true} // Ensure gear icon always appears
|
||||
canConfigure={true}
|
||||
onToggle={handleExtensionToggle}
|
||||
onConfigure={(extension) => setExtensionBeingConfigured(extension)}
|
||||
/>
|
||||
@@ -273,7 +269,6 @@ export default function Settings() {
|
||||
isOpen={!!extensionBeingConfigured && isBuiltIn(extensionBeingConfigured.id)}
|
||||
onClose={() => {
|
||||
setExtensionBeingConfigured(null);
|
||||
navigate('/settings', { replace: true });
|
||||
}}
|
||||
extension={extensionBeingConfigured}
|
||||
onSubmit={handleExtensionConfigSubmit}
|
||||
@@ -283,8 +278,6 @@ export default function Settings() {
|
||||
isOpen={!!extensionBeingConfigured}
|
||||
onClose={() => {
|
||||
setExtensionBeingConfigured(null);
|
||||
// Clear URL parameters when closing manually
|
||||
navigate('/settings', { replace: true });
|
||||
}}
|
||||
extension={extensionBeingConfigured}
|
||||
onSubmit={handleExtensionConfigSubmit}
|
||||
|
||||
@@ -6,25 +6,27 @@ import BackButton from '../../ui/BackButton';
|
||||
import { SearchBar } from './Search';
|
||||
import { useModel } from './ModelContext';
|
||||
import { AddModelInline } from './AddModelInline';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
// Removed react-router-dom usage
|
||||
// import { useNavigate } from 'react-router-dom';
|
||||
import { ScrollArea } from '../../ui/scroll-area';
|
||||
import type { View } from '../../../ChatWindow';
|
||||
|
||||
export default function MoreModelsPage() {
|
||||
export default function MoreModelsPage({
|
||||
onClose,
|
||||
setView,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
setView: (view: View) => void;
|
||||
}) {
|
||||
const { currentModel } = useModel();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full">
|
||||
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
||||
|
||||
<ScrollArea className="h-full w-full">
|
||||
{/*
|
||||
Instead of forcing one row, allow the layout
|
||||
to stack vertically on small screens:
|
||||
*/}
|
||||
|
||||
<div className="px-8 pt-6 pb-4">
|
||||
<BackButton />
|
||||
<BackButton onClick={onClose} />
|
||||
<h1 className="text-3xl font-medium text-textStandard mt-1">Browse models</h1>
|
||||
</div>
|
||||
|
||||
@@ -34,7 +36,7 @@ export default function MoreModelsPage() {
|
||||
<div className="flex justify-between items-center mb-6 border-b border-borderSubtle px-8">
|
||||
<h2 className="text-xl font-medium text-textStandard">Models</h2>
|
||||
<button
|
||||
onClick={() => navigate('/settings/configure-providers')}
|
||||
onClick={() => setView('configureProviders')}
|
||||
className="text-indigo-500 hover:text-indigo-600 text-sm"
|
||||
>
|
||||
Configure
|
||||
|
||||
@@ -2,15 +2,22 @@ import React from 'react';
|
||||
import { ScrollArea } from '../../ui/scroll-area';
|
||||
import BackButton from '../../ui/BackButton';
|
||||
import { ConfigureProvidersGrid } from './ConfigureProvidersGrid';
|
||||
import type { View } from '../../../ChatWindow';
|
||||
|
||||
export default function ConfigureProviders() {
|
||||
export default function ConfigureProviders({
|
||||
onClose,
|
||||
setView,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
setView?: (view: View) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="h-screen w-full">
|
||||
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
||||
|
||||
<ScrollArea className="h-full w-full">
|
||||
<div className="px-8 pt-6 pb-4">
|
||||
<BackButton />
|
||||
<BackButton onClick={onClose} />
|
||||
<h1 className="text-3xl font-medium text-textStandard mt-1">Configure</h1>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user