diff --git a/app/components/Models.tsx b/app/components/Models.tsx index 7647753..15b3bc8 100644 --- a/app/components/Models.tsx +++ b/app/components/Models.tsx @@ -1,148 +1,104 @@ import React, { useState, useEffect } from 'react'; // Define the available model options -const offlineModels = [ - 'Offline Fast', - 'Offline Fast (FOSS)', - 'Offline Slow', - 'Offline Slow (FOSS)', -]; +const modelDropdown = { + offlineModels: [ + 'Offline Fast', + 'Offline Fast (FOSS)', + 'Offline Slow', + 'Offline Slow (FOSS)', + ], -const onlineModels = [ - 'Online (La Plateforme)', - 'Online (FOSS) (La Plateforme)', - 'Online Cheap (OpenAI)', - 'Online Expensive (OpenAI)', - 'Online Cheap (Anthropic)', - 'Online Expensive (Anthropic)', - 'Online Cheap (Google)', - 'Online Expensive (Google)', -]; + onlineModels: [ + 'Online (La Plateforme)', + 'Online (FOSS) (La Plateforme)', + 'Online Cheap (OpenAI)', + 'Online Expensive (OpenAI)', + 'Online Cheap (Anthropic)', + 'Online Expensive (Anthropic)', + 'Online Cheap (Google)', + 'Online Expensive (Google)', + ], -const fossModels = [ - 'Offline Fast (FOSS)', - 'Offline Slow (FOSS)', - 'Online (FOSS) (La Plateforme)', -]; + fossModels: [ + 'Offline Fast (FOSS)', + 'Offline Slow (FOSS)', + 'Online (FOSS) (La Plateforme)', + ], +}; -// Define the properties passed to the Models component -interface ModelsProps { - selectedOption: string; // Privacy setting: "Offline", "AI Online", "None" -} +const Models: React.FC = () => { + // Initialize state with value from localStorage or default to '' + const [radioSelection, setRadioSelection] = useState(() => localStorage.getItem('radioSelection') || ''); -const Models: React.FC<ModelsProps> = ({ selectedOption }) => { - const [selectedModel, setSelectedModel] = useState<string>(() => { - return localStorage.getItem('selectedModel') || 'Offline Fast'; - }); + useEffect(() => { + const handleStorageChange = () => { + setRadioSelection(localStorage.getItem('radioSelection') || ''); + }; + + // Update dropdown immediately when localStorage changes internally or externally + window.addEventListener('storage', handleStorageChange); + + // Cleanup listener on component unmount + return () => { + window.removeEventListener('storage', handleStorageChange); + }; + }, []); const handleModelChange = (event: React.ChangeEvent<HTMLSelectElement>) => { const newModel = event.target.value; - setSelectedModel(newModel); + setRadioSelection(newModel); + localStorage.setItem('radioSelection', newModel); // Update localStorage directly }; - const isOfflineModel = (model: string) => offlineModels.includes(model); - const isOnlineModel = (model: string) => onlineModels.includes(model); - const isFossModel = (model: string) => fossModels.includes(model); - - useEffect(() => { - localStorage.setItem('selectedModel', selectedModel); - }, [selectedModel]); - + // Determine the filtered models based on current radioSelection const filteredModels = (() => { - switch (selectedOption) { + switch (radioSelection) { case 'Offline': - return offlineModels; // Show only offline models + return modelDropdown.offlineModels; // Show only offline models case 'AI Online': - return onlineModels; // Show only online models + return modelDropdown.onlineModels; // Show only online models + case 'FOSS': + return modelDropdown.fossModels; // Show only FOSS models default: - return [...offlineModels, ...onlineModels]; // Show all models + return [...modelDropdown.offlineModels, ...modelDropdown.onlineModels, ...modelDropdown.fossModels]; // Show all models if nothing matches } })(); + const isOfflineModel = (model: string) => modelDropdown.offlineModels.includes(model); + return ( <div className="model-background"> - <div className="models"> - <div className="title"> - <h3>Different AI models</h3> - </div> + <div className="models"> + <div className="title"> + <h3>Different AI Models</h3> + </div> - {/* Model Selection Dropdown */} - <div className="model-dropdown"> - <label htmlFor="model-select">Select AI Model:</label> - <select id="model-select" value={selectedModel} onChange={handleModelChange}> - {filteredModels.map((model) => ( - <option key={model} value={model}> - {model} - </option> - ))} - </select> - </div> + {/* Model Selection Dropdown */} + <div className="model-dropdown"> + <label htmlFor="model-select">Select AI Model:</label> + <select id="model-select" value={radioSelection} onChange={handleModelChange}> + {filteredModels.map((model) => ( + <option key={model} value={model}> + {model} + </option> + ))} + </select> + </div> - {/* Model Grid with Cards */} - <div className="grid"> - <button className="code-model model-box"> + {/* Model Grid with Cards */} + <div className="grid"> + {['Code', 'Math', 'Language', 'Character', 'Finance', 'Weather', 'Time', 'Image', 'Custom1', 'Custom2'].map((category) => ( + <button key={category} className={`${category.toLowerCase()}-model model-box`}> <div className="overlay"> - <h3>Code</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} + <h3>{category}</h3> + {isOfflineModel(radioSelection) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} </div> </button> - <button className="math-model model-box"> - <div className="overlay"> - <h3>Math</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="language-model model-box"> - <div className="overlay"> - <h3>Language</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="character-model model-box"> - <div className="overlay"> - <h3>Character</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="financial-model model-box"> - <div className="overlay"> - <h3>Finance</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="weather-model model-box"> - <div className="overlay"> - <h3>Weather</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="time-planner-model model-box"> - <div className="overlay"> - <h3>Time</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="image-model model-box"> - <div className="overlay"> - <h3>Image</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="default-model model-box"> - <div className="overlay"> - <h3>Custom1</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - <button className="default-model model-box"> - <div className="overlay"> - <h3>Custom2</h3> - {isOfflineModel(selectedModel) && <img src="/img/nowifi.svg" alt="No Wi-Fi" />} - </div> - </button> - </div> + ))} </div> </div> + </div> ); }; diff --git a/app/components/Settings.tsx b/app/components/Settings.tsx index 631a19e..3a86df3 100644 --- a/app/components/Settings.tsx +++ b/app/components/Settings.tsx @@ -398,30 +398,36 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = ( return ( <div className="settings-section"> <h2>Privacy Settings</h2> - {/* AI Mode Radio Options */} <div className="settings-option"> <p>Disable Options:</p> <div className="slider"> <div - className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''}`} - onClick={() => handleRadioChange('Offline')} // Handle selection + className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''} ${openSourceMode ? 'disabled' : ''}`} + onClick={() => !openSourceMode && handleRadioChange('Offline')} // Handle selection only if not in open source mode > Offline tools </div> <div - className={`slider-option ${selectedOption === 'AI Online' ? 'active' : ''}`} - onClick={() => handleRadioChange('AI Online')} + className={`slider-option ${selectedOption === 'AI Online' ? 'active' : ''} ${openSourceMode ? 'disabled' : ''}`} + onClick={() => !openSourceMode && handleRadioChange('AI Online')} > Online tools </div> <div - className={`slider-option ${selectedOption === 'None' ? 'active' : ''}`} - onClick={() => handleRadioChange('None')} + className={`slider-option ${selectedOption === 'None' ? 'active' : ''} ${openSourceMode ? 'disabled' : ''}`} + onClick={() => !openSourceMode && handleRadioChange('None')} > None </div> </div> + <br /> + {openSourceMode && ( + <p style={{ color: 'grey' }}>These options are deactivated because you are in FOSS mode.</p> + )} + <p> + After changing the preferred settings, please reload the website so it can update itself properly. + </p> </div> {/* Disable Chat History Checkbox */} @@ -450,6 +456,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = ( </div> ); + case 'theme': return ( <div className="settings-section"> @@ -778,22 +785,34 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = ( ); - case 'foss': - return ( - <div className="settings-section"> - <h2>Open Source Settings</h2> - <div className="settings-option"> - <label> - <input - type="checkbox" - checked={openSourceMode} - onChange={() => setOpenSourceMode(!openSourceMode)} - /> - Enable Open Source Mode - </label> - </div> - </div> - ); + case 'foss': + return ( + <div className="settings-section"> + <h2>Open Source Settings</h2> + <div className="settings-option"> + <label> + <input + type="checkbox" + checked={openSourceMode} + onChange={() => { + const newValue = !openSourceMode; + setOpenSourceMode(newValue); + // Update radio selection based on the new openSourceMode value + if (newValue) { + setSelectedOption('FOSS'); // Set to FOSS if enabling open source mode + localStorage.setItem('radioSelection', 'FOSS'); // Update localStorage + } else { + setSelectedOption('None'); // Or any other default value when disabling + localStorage.setItem('radioSelection', 'None'); // Update localStorage + } + }} + /> + Enable Open Source Mode + </label> + </div> + </div> + ); + case 'account': return ( diff --git a/app/styles/Settings.css b/app/styles/Settings.css index b840248..89c9ea7 100644 --- a/app/styles/Settings.css +++ b/app/styles/Settings.css @@ -183,5 +183,10 @@ input[type="radio"] { display: none; /* Hide the default radio buttons */ - } +} + +.slider-option.disabled { + opacity: 0.5; /* Make the option appear greyed out */ + pointer-events: none; /* Prevent clicks */ +} \ No newline at end of file diff --git a/app/styles/history.css b/app/styles/history.css index 83e5271..7bc9bcd 100644 --- a/app/styles/history.css +++ b/app/styles/history.css @@ -1,7 +1,7 @@ .history-background { grid-column: 1/2; grid-row: 1/2; - height: 45vh; + height: 40vh; overflow: hidden; background-color: var(--history-background-color); padding: 1em; diff --git a/app/styles/models.css b/app/styles/models.css index e2d01ec..0706c93 100644 --- a/app/styles/models.css +++ b/app/styles/models.css @@ -1,19 +1,20 @@ .model-background { - grid-column: 1 / 2; - grid-row: 2 / 5; - overflow-y: scroll; - background-color: var(--models-background-color); /* Ensure this variable is defined */ - border-radius: 2em; + grid-column: 1/2; + grid-row: 1/2; + height: 45vh; + overflow: hidden; + background-color: var(--history-background-color); padding: 1em; - margin-left: 1em; - height: 40vh; - box-sizing: border-box; + margin: 1em; + margin-right: 0; + border-radius: 2em; } .models { display: flex; flex-direction: column; height: 100%; + overflow-y: scroll; } .models .titel { @@ -47,7 +48,7 @@ justify-content: center; color: var(--text-color); /* Use variable for text color */ border-radius: 5%; - overflow: hidden; + overflow: scroll; position: relative; height: 18vh; width: 18vh; @@ -116,7 +117,7 @@ background-position: center; } -.financial-model { +.finance-model { background-image: url(/img/financial.jpg); background-color: #72cce4; background-repeat: no-repeat; @@ -132,7 +133,7 @@ background-position: center; } -.time-planner-model { +.time-model { background-image: url(/img/time.jpg); background-color: #72cce4; background-repeat: no-repeat; @@ -148,7 +149,8 @@ background-position: center; } -.default-model { +.custom1-model, +.custom2-model { background-image: url(/img/default.jpg); background-repeat: no-repeat; background-size: cover;