107 lines
3.7 KiB
TypeScript
107 lines
3.7 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { invoke } from '@tauri-apps/api/core';
|
|
|
|
interface SettingsProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
apiKey: string;
|
|
onApiKeyChange: (key: string) => void;
|
|
}
|
|
|
|
const DEFAULT_API_KEY = 'AIzaSyAF825tPTh77oL0knsGFEyvsN0iPUO_bXc';
|
|
|
|
export const Settings: React.FC<SettingsProps> = ({ isOpen, onClose, apiKey, onApiKeyChange }) => {
|
|
const [testing, setTesting] = useState(false);
|
|
const [testResult, setTestResult] = useState<string | null>(null);
|
|
|
|
const handleApiKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
onApiKeyChange(e.target.value);
|
|
};
|
|
|
|
const resetToDefault = () => {
|
|
onApiKeyChange(DEFAULT_API_KEY);
|
|
};
|
|
|
|
const testApiKey = async () => {
|
|
setTesting(true);
|
|
setTestResult(null);
|
|
try {
|
|
await invoke('test_gemini_api', { apiKey });
|
|
setTestResult('API key is valid');
|
|
} catch (error) {
|
|
setTestResult(`Error: ${error}`);
|
|
} finally {
|
|
setTesting(false);
|
|
}
|
|
};
|
|
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
<div className="bg-white rounded-lg p-6 w-[500px] max-w-full">
|
|
<div className="flex justify-between items-center mb-4">
|
|
<h2 className="text-xl font-semibold">Settings</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-gray-500 hover:text-gray-700"
|
|
>
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label htmlFor="apiKey" className="block text-sm font-medium text-gray-700 mb-1">
|
|
Gemini API Key
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="apiKey"
|
|
value={apiKey}
|
|
onChange={handleApiKeyChange}
|
|
className="w-full px-3 py-2 rounded-md border border-gray-300 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
placeholder="Enter your Gemini API key"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex space-x-3">
|
|
<button
|
|
onClick={testApiKey}
|
|
disabled={testing}
|
|
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
|
|
>
|
|
{testing ? 'Testing...' : 'Test API Key'}
|
|
</button>
|
|
|
|
{apiKey !== DEFAULT_API_KEY && (
|
|
<button
|
|
onClick={resetToDefault}
|
|
className="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md shadow-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
Reset to Default
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{testResult && (
|
|
<div className={`text-sm ${testResult.startsWith('Error') ? 'text-red-600' : 'text-green-600'}`}>
|
|
{testResult}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-6 flex justify-end">
|
|
<button
|
|
onClick={onClose}
|
|
className="px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|