Compare commits

..

No commits in common. "237909c164bce186a70582a21957b952ec353d39" and "35151b2c539cef498d03d7dd292c183d6f0ebcf7" have entirely different histories.

34 changed files with 567 additions and 682 deletions

View file

@ -1,19 +1,16 @@
// getLocalStorageData.ts // getLocalStorageData.ts
// Function to retrieve all items from localStorage
export const getAllLocalStorageItems = (): Record<string, string | null> => { export const getAllLocalStorageItems = (): Record<string, string | null> => {
const allData: Record<string, string | null> = {}; // Object to hold key-value pairs from localStorage const allData: Record<string, string | null> = {};
// Check if localStorage is available
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
// Iterate through all localStorage keys for (let i = 0; i < localStorage.length; i++) {
for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i);
const key = localStorage.key(i); // Get the key at the current index if (key) {
if (key) { const value = localStorage.getItem(key);
const value = localStorage.getItem(key); // Retrieve the value associated with the key allData[key] = value;
allData[key] = value; // Store the key-value pair in the allData object
}
} }
}
} }
return allData; // Return the object containing all localStorage items return allData;
}; };

View file

@ -9,7 +9,7 @@ import { getWeather } from "./weather";
import { changeHistory, getHistory } from "./database"; import { changeHistory, getHistory } from "./database";
const InputOutputBackend: React.FC = () => { const InputOutputBackend: React.FC = () => {
//#region variables // # variables
type Message = { type Message = {
role: string role: string
content: string content: string
@ -37,7 +37,7 @@ const InputOutputBackend: React.FC = () => {
} }
console.log(setSelectedIndex) console.log(setSelectedIndex)
//#region useEffect
useEffect(() => { useEffect(() => {
setMessages(chatHistory.chats[chatHistory.selectedIndex].messages) setMessages(chatHistory.chats[chatHistory.selectedIndex].messages)
}, [chatHistory.selectedIndex]) }, [chatHistory.selectedIndex])
@ -86,7 +86,6 @@ const InputOutputBackend: React.FC = () => {
} }
}, [chatHistory]) }, [chatHistory])
//#region functions
const getWeatherHere = async () => { const getWeatherHere = async () => {
setWeatherData(await getWeather({ "unit_type": preferredMeasurement, "city": localStorage.getItem("weatherInfo") || "New York" })) setWeatherData(await getWeather({ "unit_type": preferredMeasurement, "city": localStorage.getItem("weatherInfo") || "New York" }))
console.log("Got the Data!") console.log("Got the Data!")
@ -105,7 +104,7 @@ const InputOutputBackend: React.FC = () => {
} }
setChatHistoryTriggered(true) setChatHistoryTriggered(true)
} }
//#region system-prompt
useEffect(() => { useEffect(() => {
console.log("creating system prompt") console.log("creating system prompt")
console.log(weatherData) console.log(weatherData)
@ -134,7 +133,7 @@ const InputOutputBackend: React.FC = () => {
console.log(messages) console.log(messages)
}, [systemMessage]) }, [systemMessage])
//#region more variables and functions
const conversationRef = useRef<HTMLDivElement>(null) const conversationRef = useRef<HTMLDivElement>(null)
const [copyClicked, setCopyClicked] = useState(false) const [copyClicked, setCopyClicked] = useState(false)
const [accessToken, setAccessToken] = useState("") const [accessToken, setAccessToken] = useState("")
@ -145,7 +144,7 @@ const InputOutputBackend: React.FC = () => {
const [isRecording, setIsRecording] = useState(false) const [isRecording, setIsRecording] = useState(false)
const mediaRecorderRef = useRef<MediaRecorder | null>(null) const mediaRecorderRef = useRef<MediaRecorder | null>(null)
const audioChunks = useRef<Blob[]>([]) const audioChunks = useRef<Blob[]>([])
//#region chat functions
useEffect(() => { useEffect(() => {
getNewToken() getNewToken()
@ -267,7 +266,7 @@ const InputOutputBackend: React.FC = () => {
} }
} }
} }
//#region speech recognition
const startRecording = async (): Promise<string> => { const startRecording = async (): Promise<string> => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream); const mediaRecorder = new MediaRecorder(stream);
@ -310,7 +309,7 @@ const InputOutputBackend: React.FC = () => {
stopRecording(); stopRecording();
} }
}; };
//#region chat buttons
const handleStopClick = () => { const handleStopClick = () => {
endGetWorker() endGetWorker()
getNewToken() getNewToken()
@ -357,7 +356,7 @@ const InputOutputBackend: React.FC = () => {
setCopyClicked(false) setCopyClicked(false)
} }
//#region The "html" return
return ( return (
<> <>
<ConversationFrontend <ConversationFrontend

View file

@ -1,40 +1,55 @@
import axios from "axios"; import axios from "axios";
// Construct the base API URL based on the environment /*
const apiURL = new URL("http://localhost:5000/interstellar_ai/db"); This is the guide on how to user this function:
data should be the json containing everything relevant, the json can contain the following keys:
action -> contains the action you want to do, there are: create_account, change_password, get_data, change_data, check_credentials, delete_account
username -> contains the current username, required for create_account, but can be omitted in favor of email in other requests. Preffered over email authentication.
email -> contains the current email, required for create_account, but just like the username, it can be omitted, in favor of the other, sending both is possible too.
password -> contains the password, required for all requests.
new_password -> in the case you are changing your password, you will need to use this in addition to password, to specify the new password.
data -> data contains all the data you want to store, you have to always give the entire data, because the data you give here overwrites the data in the database,
so if you only give the chat history for example, all settings will be deleted, and if you only give settings, all chat histories will get deleted.
if all went well, you will get the status 200 in response.data.status
to check if the request was accepted or declined, check response.data.response, it will be either true or false depending on if it worked, or not.
*/
const apiURL = new URL("http://localhost:5000/interstellar_ai/db")
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Set hostname for browsers apiURL.hostname = window.location.hostname;
} else { } else {
apiURL.hostname = "localhost"; // Default to localhost for non-browser environments apiURL.hostname = "localhost"
} }
// Function to send data to the database and return a success status
export const sendToDatabase = async (data: object): Promise<boolean> => { export const sendToDatabase = async (data: object): Promise<boolean> => {
try { try {
const response = await axios.post(apiURL.href, data); const response = await axios.post(apiURL.href, data);
const status = response.data.status; const status = response.data.status;
const success = response.data.response; const success = response.data.response;
postMessage({ status, success }); // Send status back to the main thread postMessage({ status, success });
return success; // Return success status return success;
} catch (error) { } catch (error) {
postMessage({ status: 500, success: false }); // Handle errors postMessage({ status: 500, success: false });
console.log(error); console.log(error)
return false; // Return false on error return false;
} }
}; };
// Function to send data and get a string response
export const sendToDatabaseAndGetString = async (data: object): Promise<string> => { export const sendToDatabaseAndGetString = async (data: object): Promise<string> => {
try { try {
const response = await axios.post(apiURL.href, data); const response = await axios.post(apiURL.href, data);
const status = response.data.status; const status = response.data.status;
const success = response.data.response; const success = response.data.response;
postMessage({ status, success }); postMessage({ status, success });
return success; // Return response string return success;
} catch (error) { } catch (error) {
postMessage({ status: 500, success: false }); postMessage({ status: 500, success: false });
console.log(error); console.log(error)
return "false"; // Return "false" on error return "false";
} }
}; };
@ -46,7 +61,7 @@ export const createAccount = async (username: string, email: string, password: s
email: email, email: email,
password: password, password: password,
}; };
return await sendToDatabase(data); // Send account creation request return await sendToDatabase(data);
}; };
export const changePassword = async (usernameOrEmail: string, password: string, newPassword: string) => { export const changePassword = async (usernameOrEmail: string, password: string, newPassword: string) => {
@ -57,7 +72,7 @@ export const changePassword = async (usernameOrEmail: string, password: string,
password, password,
new_password: newPassword, new_password: newPassword,
}; };
return await sendToDatabase(data); // Send password change request return await sendToDatabase(data);
}; };
export const getSettings = async (usernameOrEmail: string, password: string) => { export const getSettings = async (usernameOrEmail: string, password: string) => {
@ -67,7 +82,7 @@ export const getSettings = async (usernameOrEmail: string, password: string) =>
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
return await sendToDatabaseAndGetString(data); // Get user settings return await sendToDatabaseAndGetString(data);
}; };
export const changeSettings = async (usernameOrEmail: string, password: string, newData: object) => { export const changeSettings = async (usernameOrEmail: string, password: string, newData: object) => {
@ -78,7 +93,7 @@ export const changeSettings = async (usernameOrEmail: string, password: string,
password, password,
data: newData, data: newData,
}; };
return await sendToDatabase(data); // Send settings change request return await sendToDatabase(data);
}; };
export const getHistory = async (usernameOrEmail: string, password: string) => { export const getHistory = async (usernameOrEmail: string, password: string) => {
@ -88,7 +103,7 @@ export const getHistory = async (usernameOrEmail: string, password: string) => {
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
return await sendToDatabaseAndGetString(data); // Get user history return await sendToDatabaseAndGetString(data);
}; };
export const changeHistory = async (usernameOrEmail: string, password: string, newData: object) => { export const changeHistory = async (usernameOrEmail: string, password: string, newData: object) => {
@ -99,7 +114,7 @@ export const changeHistory = async (usernameOrEmail: string, password: string, n
password, password,
data: newData, data: newData,
}; };
return await sendToDatabase(data); // Send history change request return await sendToDatabase(data);
}; };
export const getEmail = async (usernameOrEmail: string, password: string): Promise<string> => { export const getEmail = async (usernameOrEmail: string, password: string): Promise<string> => {
@ -109,7 +124,7 @@ export const getEmail = async (usernameOrEmail: string, password: string): Promi
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
return await sendToDatabaseAndGetString(data); // Get user email return await sendToDatabaseAndGetString(data);
}; };
export const getName = async (usernameOrEmail: string, password: string): Promise<string> => { export const getName = async (usernameOrEmail: string, password: string): Promise<string> => {
@ -119,9 +134,10 @@ export const getName = async (usernameOrEmail: string, password: string): Promis
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
return await sendToDatabaseAndGetString(data); // Get user name return await sendToDatabaseAndGetString(data);
}; };
export const checkCredentials = async (usernameOrEmail: string, password: string) => { export const checkCredentials = async (usernameOrEmail: string, password: string) => {
const data = { const data = {
action: "check_credentials", action: "check_credentials",
@ -129,16 +145,15 @@ export const checkCredentials = async (usernameOrEmail: string, password: string
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
const sendBack = await sendToDatabase(data); // Check user credentials const sendBack = await sendToDatabase(data);
if (sendBack) { if (sendBack) {
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
// Store user data in localStorage if credentials are valid localStorage.setItem("accountEmail", await getEmail(usernameOrEmail, password))
localStorage.setItem("accountEmail", await getEmail(usernameOrEmail, password)); localStorage.setItem("accountName", await getName(usernameOrEmail, password))
localStorage.setItem("accountName", await getName(usernameOrEmail, password)); localStorage.setItem("accountPassword", password)
localStorage.setItem("accountPassword", password);
} }
} }
return sendBack; // Return success status return sendBack
}; };
export const deleteAccount = async (usernameOrEmail: string, password: string) => { export const deleteAccount = async (usernameOrEmail: string, password: string) => {
@ -148,5 +163,5 @@ export const deleteAccount = async (usernameOrEmail: string, password: string) =
email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined, email: usernameOrEmail.includes('@') ? usernameOrEmail : undefined,
password, password,
}; };
return await sendToDatabase(data); // Send account deletion request return await sendToDatabase(data);
}; };

View file

@ -1,32 +1,37 @@
import axios from "axios"; import axios from "axios";
let windownameGlobal = ""; // Global variable to hold the window name let windownameGlobal = ""
let accesstoken = ""; // Variable to store the access token
let accesstoken = ""
onmessage = (event) => { onmessage = (event) => {
const { action, access_token, windowname } = event.data; const { action, access_token, windowname } = event.data
accesstoken = access_token; accesstoken = access_token
windownameGlobal = windowname;
windownameGlobal = windowname
if (action === "start") { if (action === "start") {
fetchData(); // Start fetching data on 'start' action fetchData()
} else if (action === "terminate") {
} }
} }
const fetchData = () => {
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_get?access_token=" + accesstoken);
apiURL.hostname = windownameGlobal; // Set the hostname
console.log(apiURL.href); // Log the constructed URL const fetchData = () => {
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_get?access_token=" + accesstoken)
apiURL.hostname = windownameGlobal;
console.log(apiURL.href)
axios.get(apiURL.href) axios.get(apiURL.href)
.then(response => { .then(response => {
postMessage(response.data); // Send data back on success const data = response.data
setTimeout(fetchData, 100); // Schedule next fetch postMessage(data)
setTimeout(fetchData, 100)
}) })
.catch(error => { .catch(error => {
console.log('Error fetching data:', error); console.log('Error fetching data:', error);
postMessage({ error: "failed fetching data" }); // Send error message postMessage({ error: "failed fetching data" })
setTimeout(() => fetchData(), 1000); // Retry after 1 second setTimeout(() => fetchData(), 1000)
}); })
} }

View file

@ -1,32 +1,31 @@
import axios from "axios"; import axios from "axios";
// Event listener for incoming messages
onmessage = (e) => { onmessage = (e) => {
const { messages, ai_model, model_type, access_token, api_key, windowname } = e.data; const { messages, ai_model, model_type, access_token, api_key, windowname } = e.data
// Construct the message object to send to the API
const Message = { const Message = {
messages: messages, messages: messages,
ai_model: ai_model, ai_model: ai_model,
model_type: model_type, model_type: model_type,
access_token: access_token, access_token: access_token,
api_key: api_key api_key: api_key
}; }
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_send"); const apiURL = new URL("http://localhost:5000/interstellar_ai/api/ai_send")
console.log(windowname); // Log the window name console.log(windowname)
apiURL.hostname = windowname; // Set the hostname for the API request apiURL.hostname = windowname;
console.log(apiURL.href); // Log the constructed API URL console.log(apiURL.href)
// Make a POST request to the API with the message object
axios.post(apiURL.href, Message) axios.post(apiURL.href, Message)
.then(response => { .then(response => {
const status = response.data.status; const status = response.data.status
postMessage({ status }); // Send the response status back postMessage({ status })
}) })
.catch(error => { .catch(error => {
console.log("Error calling API:", error); console.log("Error calling API:", error)
postMessage({ status: 500 }); // Send error status if API call fails postMessage({ status: 500 })
}); })
} }

View file

@ -1,26 +1,24 @@
import axios from "axios"; import axios from "axios";
export const sendToVoiceRecognition = (audio_data: Blob): Promise<string> => { export const sendToVoiceRecognition = (audio_data: Blob): Promise<string> => {
// Create a new FormData instance to send the audio file
const formdata = new FormData();
formdata.append("audio", audio_data); // Append the audio data to the FormData
// Set the API URL dynamically based on the environment const formdata = new FormData()
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/voice_recognition"); formdata.append("audio", audio_data)
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/voice_recognition")
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Use the current hostname in the browser apiURL.hostname = window.location.hostname;
} else { } else {
apiURL.hostname = "localhost"; // Fallback for server-side apiURL.hostname = "localhost"
} }
// Send the audio data to the API using POST request
return axios.post(apiURL.href, formdata) return axios.post(apiURL.href, formdata)
.then((response) => { .then((response) => {
return response.data.response; // Return the response from the API return response.data.response
}) })
.catch(error => { .catch(error => {
console.log("Error calling API:", error); // Log any error that occurs console.log("Error calling API:", error)
postMessage({ status: 500 }); // Indicate an error status to the worker postMessage({ status: 500 })
return "Error"; // Return a fallback error message return "Error"
}); })
}; }

View file

@ -1,29 +1,23 @@
import axios from "axios"; import axios from "axios";
// Initialize the API URL for the weather service const apiURL = new URL("http://localhost:5000/interstellar_ai/api/weather")
const apiURL = new URL("http://localhost:5000/interstellar_ai/api/weather");
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
apiURL.hostname = window.location.hostname; // Use current hostname in the browser apiURL.hostname = window.location.hostname;
} else { } else {
apiURL.hostname = "localhost"; // Fallback for server-side apiURL.hostname = "localhost"
} }
// Function to get weather data
export const getWeather = async (data: object): Promise<string> => { export const getWeather = async (data: object): Promise<string> => {
try { try {
// Make a POST request to the weather API with the provided data
const response = await axios.post(apiURL.href, data); const response = await axios.post(apiURL.href, data);
const status = response.data.status; // Extract the status from the response const status = response.data.status;
const success = response.data.response; // Extract the actual weather data from the response const success = response.data.response;
// Send the status and success response back to the worker
postMessage({ status, success }); postMessage({ status, success });
console.log(JSON.stringify(success)); // Log the successful response for debugging console.log(JSON.stringify(success))
return JSON.stringify(success); // Return the weather data as a JSON string return JSON.stringify(success);
} catch (error) { } catch (error) {
// Handle any errors that occur during the request
postMessage({ status: 500, success: false }); postMessage({ status: 500, success: false });
console.log(error); // Log the error for debugging console.log(error)
return ""; // Return an empty string in case of an error return "";
} }
}; };

View file

@ -5,7 +5,6 @@ import InputOutputBackend from '../backend/InputOutputHandler';
const AI: React.FC = () => { const AI: React.FC = () => {
return ( return (
<div className="ai-container"> <div className="ai-container">
{/* Render the InputOutputBackend component for AI input/output handling */}
<InputOutputBackend /> <InputOutputBackend />
</div> </div>
); );

View file

@ -1,45 +1,24 @@
import React from 'react'; import React from 'react';
// Main Credits Component
const Credits: React.FC = () => ( const Credits: React.FC = () => (
<div className="credits-container"> <div className="credits-container">
<section id="credits" className="credits-section"> <section id="credits" className="credits-section">
<h1 className="title">Credits</h1> <h1 className="title">Credits</h1>
<h2 className="subtitle">Icons</h2> <h2 className="subtitle">Icons</h2>
<p className="paragraph">This project utilizes the following icon resources:</p> <p className="paragraph">This project utilizes the following icon resources:</p>
<CreditLink href="https://fontawesome.com/v4/license/" label="FontAwesome" /> <CreditLink href="https://fontawesome.com/v4/license/" label="fontawesome" />
<h2 className="subtitle">Fonts</h2> <h2 className="subtitle">Fonts</h2>
<p className="paragraph">The fonts used in this project are provided by:</p> <p className="paragraph">The fonts used in this project are provided by:</p>
<CreditLink href="https://github.com/itfoundry/Poppins" label="Poppins" /> <CreditLink href="https://github.com/itfoundry/Poppins" label="Poppins" />
<CreditLink <CreditLink href="https://openfontlicense.org" label="Inconsolata, Merriweather, Noto Sans, Noto Serif, Playfair Display, Bangers, Caveat, Frederika the Great, Sofadi One, Zilla Slab Highlight" />
href="https://openfontlicense.org" <CreditLink href="http://www.apache.org/licenses/LICENSE-2.0" label="Roboto, Rock Salt" />
label="Inconsolata, Merriweather, Noto Sans, Noto Serif, Playfair Display, Bangers, Caveat, Frederika the Great, Sofadi One, Zilla Slab Highlight"
/>
<CreditLink
href="http://www.apache.org/licenses/LICENSE-2.0"
label="Roboto, Rock Salt"
/>
<CreditLink href="https://ubuntu.com/legal/font-licence" label="Ubuntu" /> <CreditLink href="https://ubuntu.com/legal/font-licence" label="Ubuntu" />
</section> </section>
</div> </div>
); );
// CreditLink Component for rendering individual credit links const CreditLink = ({ href, label }: { href: string; label: string }) => (
const CreditLink: React.FC<{ href: string; label: string }> = ({ href, label }) => ( <a href={href} className="credit-btn" target="_blank" rel="noopener noreferrer">{label}</a>
<a
href={href}
className="credit-btn"
target="_blank"
rel="noopener noreferrer"
aria-label={`Visit ${label} license page`} // Improve accessibility
>
{label}
</a>
); );
export default Credits; export default Credits;
// also thank you Leart and Tristan without you two we would not have come this far
// and a special thanks and why are you so annoying to Eslint

View file

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
// Documentation Component const Documentation = () => {
const Documentation: React.FC = () => {
return ( return (
<section id="documentation" className="documentation-section"> <section id="documentation" className="documentation-section">
<div className='docDiv'> <div className='docDiv'>

View file

@ -1,62 +1,107 @@
import React from 'react'; import React from 'react';
// FAQ Component
const FAQ: React.FC = () => { const FAQ: React.FC = () => {
return ( return (
<section id="faq"> {/* Main section for FAQs */} <section id="faq">
<h2>Frequently Asked Questions</h2> {/* Title for the FAQ section */} <h2>Frequently Asked Questions</h2>
<div className="faq-item"> <div className="faq-item">
<h3>Why doesn't my selection in the category dropdown menu apply?</h3> <h3>What is this AI assistant for?</h3>
<p>Currently, the dropdown menu for selecting AI models does not retain your choice after a website refresh.</p> <p>This AI assistant helps you with various tasks such as answering questions, generating text, and even helping with code or writing tasks.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Why is the AI suddenly talking about the weather when I didn't select that option?</h3> <h3>How does the AI assistant work?</h3>
<p>The AI is programmed to provide weather information even if you haven't specifically selected the weather option.</p> <p>The assistant uses machine learning algorithms to understand your input and provide contextually relevant answers or generate content based on the task you&apos;ve described.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Why isn't the online API working?</h3> <h3>Can I trust the answers given by the AI assistant?</h3>
<p>At the moment, the online APIs for Google and La Plateforme are not operational. However, the OpenAI and Anthropic APIs may still function.</p> <p>While the AI strives to give accurate and helpful answers, it is important to verify critical information, especially for complex or sensitive queries.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Why is the AI discussing unrelated topics?</h3> <h3>What kind of questions can I ask?</h3>
<p>Try disabling the AI system prompt settings, as the AI sometimes tends to focus on those topics excessively.</p> <p>You can ask a wide range of questions from simple factual queries to more complex requests like generating creative writing or code snippets.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Why isn't the AI responding in the format I specified in the settings?</h3> <h3>Is my data secure when using the AI assistant?</h3>
<p>Please check if the system prompt settings are enabled. If the issue persists, it may be because the AI is unable to fully adhere to the command.</p> <p>We take privacy seriously. Your data is handled according to our privacy policy, ensuring that any personal information shared is securely processed and not misused.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Does this AI have the ability to know my location or search the web?</h3> <h3>How can I provide feedback about the AI assistant?</h3>
<p>No, this AI does not possess any capabilities to access your location or browse the web.</p> <p>Feedback can be provided through our feedback form, available on our website. We appreciate your input and use it to improve the AI assistant&apos;s performance.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Does the AI really work offline?</h3> <h3>Can I customize the AI assistant&apos;s responses?</h3>
<p>Yes! Once you download the necessary models, it can operate fully offline, with the exception of the weather API.</p> <p>Customization options are limited in the current version, but we are working on features that will allow users to tailor responses to better suit their needs.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Are my messages encrypted?</h3> <h3>How frequently is the AI assistant updated?</h3>
<p>Unfortunately, not at this time. We recommend keeping your messages as anonymous as possible.</p> <p>The AI assistant is updated regularly to improve its functionality and incorporate new features. Stay tuned to our update logs for information on the latest improvements.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Where is my data saved?</h3> <h3>What should I do if the AI assistant is not working properly?</h3>
<p>All data, including accounts, settings, and chats, is stored locally on your computer.</p> <p>If you encounter any issues with the AI assistant, please contact our support team for assistance. Provide details about the problem to help us resolve it quickly.</p>
</div> </div>
<div className="faq-item"> <div className="faq-item">
<h3>Is this a virus?</h3> <h3>Will the AI assistant be available in multiple languages?</h3>
<p>No, this is not a virus. The warning appears because the application is not officially signed.</p> <p>Yes, the AI assistant is designed to support multiple languages. You can specify your language preference in the settings to receive responses in your chosen language.</p>
</div> </div>
<div className="faq-item">
<h3>How can I integrate the AI assistant into my own application?</h3>
<p>Integration guidelines are available in our developer documentation. Follow the instructions to incorporate the AI assistant into your application via our API.</p>
</div>
<div className="faq-item">
<h3>Is there a mobile version of the AI assistant?</h3>
<p>Currently, the AI assistant is optimized for desktop use. We are working on a mobile version to provide a seamless experience on smartphones and tablets.</p>
</div>
<div className="faq-item">
<h3>Can the AI assistant handle multiple simultaneous conversations?</h3>
<p>Yes, the AI assistant is capable of managing multiple conversations at once, ensuring that each interaction is handled efficiently.</p>
</div>
<div className="faq-item">
<h3>What are the system requirements to use the AI assistant?</h3>
<p>The AI assistant can be accessed through most modern web browsers. Ensure your browser is up-to-date for the best experience.</p>
</div>
<div className="faq-item">
<h3>How can I access previous conversations?</h3>
<p>Previous conversations can be accessed through the chat history feature available in the assistant&apos;s interface.</p>
</div>
<div className="faq-item">
<h3>What are the limitations of the current AI assistant?</h3>
<p>The AI assistant may have limitations in understanding highly specialized or nuanced topics. We are continuously working to expand its capabilities.</p>
</div>
<div className="faq-item">
<h3>How do I update my profile or settings?</h3>
<p>Profile and settings updates can be made through the account management section of the application. Ensure you save your changes before exiting.</p>
</div>
<div className="faq-item">
<h3>Can the AI assistant be used offline?</h3>
<p>Currently, the AI assistant requires an internet connection to function. Offline capabilities are being explored for future updates.</p>
</div>
<div className="faq-item">
<h3>Who can I contact for technical support?</h3>
<p>Technical support can be reached through our support contact page on the website. Our team is available to help with any technical issues you may encounter.</p>
</div>
</section> </section>
); );
}; };
export default FAQ; // Exporting the FAQ component export default FAQ;

View file

@ -1,13 +1,12 @@
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import Login from './Login'; // Importing the Login component import Login from './Login';
// Define the props for the Header component
interface HeaderProps { interface HeaderProps {
onViewChange: (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => void; // Function to change views onViewChange: (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => void;
showDivs: boolean; // State to show/hide divs showDivs: boolean;
toggleDivs: () => void; // Function to toggle divs toggleDivs: () => void;
showHistoryModelsToggle: boolean; // State to show/hide history models showHistoryModelsToggle: boolean;
showToggle: boolean; // State to show/hide toggle button showToggle: boolean;
} }
const Header: React.FC<HeaderProps> = ({ const Header: React.FC<HeaderProps> = ({
@ -17,53 +16,50 @@ const Header: React.FC<HeaderProps> = ({
showHistoryModelsToggle, showHistoryModelsToggle,
showToggle, showToggle,
}) => { }) => {
// State to manage menu open/closed state
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement | null>(null); // Ref for dropdown menu const dropdownRef = useRef<HTMLDivElement | null>(null);
const toggleRef = useRef<HTMLDivElement | null>(null); // Ref for hamburger toggle const toggleRef = useRef<HTMLDivElement | null>(null);
// Pages to be displayed in the navigation menu // Pages that will be displayed in the menu
const pages: ('AI' | 'FAQ' | 'Documentation' | 'Credits')[] = ['AI', 'FAQ', 'Documentation', 'Credits']; const pages: ('AI' | 'FAQ' | 'Documentation' | 'Credits')[] = ['AI', 'FAQ', 'Documentation', 'Credits'];
// Function to toggle the dropdown menu state // Toggle menu state
const toggleMenu = () => { const toggleMenu = () => {
setMenuOpen((prevMenuOpen) => !prevMenuOpen); setMenuOpen((prevMenuOpen) => !prevMenuOpen);
}; };
// Function to handle view change when a menu item is clicked // Handle button click
const handleViewChange = (page: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => { const handleViewChange = (page: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => {
onViewChange(page); // Call the onViewChange function with the selected page onViewChange(page);
setMenuOpen(false); // Close the menu after selection setMenuOpen(false); // Close the menu when a button is clicked
}; };
// Effect to handle clicks outside the dropdown to close it // Effect to handle clicks outside of the dropdown
useEffect(() => { useEffect(() => {
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
// Check if the click is outside the dropdown and toggle elements
if ( if (
dropdownRef.current && dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node) && !dropdownRef.current.contains(event.target as Node) &&
toggleRef.current && toggleRef.current &&
!toggleRef.current.contains(event.target as Node) !toggleRef.current.contains(event.target as Node)
) { ) {
setMenuOpen(false); // Close the menu if the click is outside setMenuOpen(false);
} }
}; };
document.addEventListener('mousedown', handleClickOutside); // Listen for clicks document.addEventListener('mousedown', handleClickOutside);
return () => { return () => {
document.removeEventListener('mousedown', handleClickOutside); // Cleanup listener on unmount document.removeEventListener('mousedown', handleClickOutside);
}; };
}, []); }, []);
return ( return (
<> <>
<header> <header>
{/* Show the toggle button for divs if conditions are met */}
{showToggle && showHistoryModelsToggle && ( {showToggle && showHistoryModelsToggle && (
<button onClick={toggleDivs} className="nav-btn show-hide-btn"> <button onClick={toggleDivs} className="nav-btn show-hide-btn">
{showDivs ? ( // Conditional rendering of icon based on showDivs state {showDivs ? (
<> <>
<svg style={{ fill: "var(--text-color)" }} width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"> <svg style={{ fill: "var(--text-color)" }} width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z"/> <path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c8.4-19.3 10.6-41.4 4.8-63.3c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zM373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5L373 389.9z"/>
@ -78,32 +74,27 @@ const Header: React.FC<HeaderProps> = ({
)} )}
</button> </button>
)} )}
{/* Navigation menu */}
<nav ref={dropdownRef} className={`nav-links ${menuOpen ? "active" : ""}`}> <nav ref={dropdownRef} className={`nav-links ${menuOpen ? "active" : ""}`}>
{pages.map(page => ( // Map through pages to create buttons {pages.map(page => (
<button key={page} onClick={() => handleViewChange(page)} className="nav-btn"> <button key={page} onClick={() => handleViewChange(page)} className="nav-btn">
{page} {page}
</button> </button>
))} ))}
</nav> </nav>
{/* Hamburger menu toggle */}
<div ref={toggleRef} className={`hamburger ${menuOpen ? "open" : ""}`} onClick={toggleMenu}> <div ref={toggleRef} className={`hamburger ${menuOpen ? "open" : ""}`} onClick={toggleMenu}>
<span></span> {/* Top bar of the hamburger */} <span></span>
<span></span> {/* Middle bar of the hamburger */} <span></span>
<span></span> {/* Bottom bar of the hamburger */} <span></span>
</div> </div>
<div className="header-logo"> <div className="header-logo">
{/* Placeholder for AI logo or text */} {/* AI logo or text */}
</div> </div>
<div className="login-button-container"> <div className="login-button-container">
<Login /> {/* Include the Login component */} <Login />
</div> </div>
</header> </header>
</> </>
); );
}; };
export default Header; // Exporting the Header component export default Header;

View file

@ -1,114 +1,96 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useChatHistory } from '../hooks/useChatHistory'; // Importing the custom hook for chat history import { useChatHistory } from '../hooks/useChatHistory';
const History: React.FC = () => { const History: React.FC = () => {
// Destructuring values from the useChatHistory hook const [chatHistory, setSelectedIndex, setChatHistory] = useChatHistory()
const [chatHistory, setSelectedIndex, setChatHistory] = useChatHistory(); const [isEditing, setIsEditing] = useState(false);
const [isEditing, setIsEditing] = useState(false); // State to manage edit mode const [inputValue, setInputValue] = useState<string>('');
const [inputValue, setInputValue] = useState<string>(''); // State for input field const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null); // State to track hovered chat index
// Function to activate editing mode
const handleEditButtonClick = () => { const handleEditButtonClick = () => {
setIsEditing(true); setIsEditing(true);
}; };
// Function to update input value as the user types
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value); setInputValue(e.target.value);
}; };
// Function to save the new chat
const handleSaveButtonClick = () => { const handleSaveButtonClick = () => {
setIsEditing(false); // Exit edit mode setIsEditing(false);
// Add a new chat entry to the history chatHistory.chats.push({ name: inputValue, messages: [], timestamp: 5 })
chatHistory.chats.push({ name: inputValue, messages: [], timestamp: 5 }); setInputValue("")
setInputValue(''); // Reset input value
}; };
// Function to select a chat from the history
const handleHistoryClick = (index: number) => { const handleHistoryClick = (index: number) => {
setSelectedIndex(index); // Set the selected index to the clicked chat setSelectedIndex(index)
console.log("index", index); console.log("index",index);
}; }
// Function to handle hover over a chat entry const handleHistoryHover = (index:number) => {
const handleHistoryHover = (index: number) => { setHoveredIndex(index)
setHoveredIndex(index); // Set hovered index }
};
// Function to reset hovered index when not hovering
const handleHistoryNotHover = () => { const handleHistoryNotHover = () => {
setHoveredIndex(null); // Reset hovered index setHoveredIndex(null)
}; }
// Debugging information for chat history length and selected index console.log("chat length",chatHistory.chats.length)
console.log("chat length", chatHistory.chats.length); console.log("index",chatHistory.selectedIndex)
console.log("index", chatHistory.selectedIndex);
// Function to delete a chat entry
const handleHistoryDeletion = (index: number) => { const handleHistoryDeletion = (index: number) => {
const currentIndex = chatHistory.selectedIndex; // Get the currently selected index const currentIndex = chatHistory.selectedIndex;
// Create a new copy of the chat history // Create a new copy of the current chat history
const copyChats = { ...chatHistory }; const copyChats = { ...chatHistory };
copyChats.chats = [...chatHistory.chats]; copyChats.chats = [...chatHistory.chats]
// Remove the chat at the specified index // Remove the chat at the specified index
copyChats.chats.splice(index, 1); copyChats.chats.splice(index,1)
// Determine the new selectedIndex // Determine new selectedIndex
let newSelectedIndex = currentIndex; let newSelectedIndex = currentIndex;
// Adjust selectedIndex based on the deletion // Adjust selectedIndex based on the deletion
if (index === currentIndex) { if (index === currentIndex) {
// If the deleted index is currently selected, reset the selected index // If the deleted index is the currently selected one, reset the selected index
newSelectedIndex = copyChats.chats.length > 0 ? (index > 0 ? index - 1 : 0) : -1; // Set to previous or first chat or -1 if no chats left newSelectedIndex = copyChats.chats.length > 0 ? (index > 0 ? index - 1 : 0) : -1; // Set to previous or first chat or -1 if no chats left
} else if (index < currentIndex) { } else if (index < currentIndex) {
// If the deleted chat is before the current selected index, decrement the selected index // If the deleted chat is before the current selected index, decrement the selected index
newSelectedIndex = currentIndex - 1; newSelectedIndex = currentIndex - 1;
} }
copyChats.selectedIndex = newSelectedIndex; // Update the selected index copyChats.selectedIndex = newSelectedIndex
// Debugging information to inspect the modified chat history console.log(copyChats)
console.log(copyChats);
// Set the updated chat history // Set the updated chat history
setChatHistory(copyChats); setChatHistory(copyChats);
}; };
return ( return (
<div className="history-background"> <div className="history-background">
<div className="history"> <div className="history">
<ul> <ul>
{/* Render chat history items */} {/* Populate with history items */}
{chatHistory.chats.map((chat, index) => ( {chatHistory.chats.map((chats, index) => (
<li key={index} onMouseOver={() => handleHistoryHover(index)} onMouseOut={handleHistoryNotHover}> <li key={index} onMouseOver={()=>handleHistoryHover(index)} onMouseOut={handleHistoryNotHover} >
<a <a href="#" onClick={() => handleHistoryClick(index)} style={{
href="#" backgroundColor: chatHistory.selectedIndex == index ? "var(--input-button-color)" : "",
onClick={() => handleHistoryClick(index)} // Handle click to select chat borderRadius: "5px",
style={{ width: index==hoveredIndex && chatHistory.chats.length >1 ? "85%":"100%"
backgroundColor: chatHistory.selectedIndex === index ? "var(--input-button-color)" : "", }}>
borderRadius: "5px", {chatHistory.chats[index].name}
width: index === hoveredIndex && chatHistory.chats.length > 1 ? "85%" : "100%"
}}
>
{chat.name} {/* Display chat name */}
</a> </a>
<button <button id="delete-chat-button"
id="delete-chat-button" onClick={()=>handleHistoryDeletion(index)}
onClick={() => handleHistoryDeletion(index)} // Handle chat deletion disabled={(index == hoveredIndex && chatHistory.chats.length >1) ? false : true}
disabled={!(index === hoveredIndex && chatHistory.chats.length > 1)} // Disable if not hovered
style={{ style={{
width: index === hoveredIndex && chatHistory.chats.length > 1 ? "15%" : "0", width: index == hoveredIndex && chatHistory.chats.length >1 ? "15%" : "0",
visibility: index === hoveredIndex && chatHistory.chats.length > 1 ? "visible" : "hidden", visibility: index == hoveredIndex && chatHistory.chats.length >1 ? "visible" : "hidden",
marginLeft: index === hoveredIndex && chatHistory.chats.length > 1 ? "0.5em" : 0 marginLeft: index == hoveredIndex && chatHistory.chats.length >1? "0.5em":0
}} }}>
> <svg viewBox="0 0 448 512"><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>
<svg viewBox="0 0 448 512">
<path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z" />
</svg>
</button> </button>
</li> </li>
))} ))}
@ -118,17 +100,17 @@ const History: React.FC = () => {
<input <input
type="text" type="text"
value={inputValue} value={inputValue}
onChange={handleInputChange} // Update input value as user types onChange={handleInputChange}
placeholder="Enter text" placeholder="Enter text"
className="chat-input" className="chat-input"
/> />
<button onClick={handleSaveButtonClick} className="save-btn"> <button onClick={handleSaveButtonClick} className="save-btn">
Save {/* Button to save new chat */} Save
</button> </button>
</div> </div>
) : ( ) : (
<button onClick={handleEditButtonClick} className="newChat-btn"> <button onClick={handleEditButtonClick} className="newChat-btn">
New Chat {/* Button to initiate a new chat */} New Chat
</button> </button>
)} )}
</li> </li>
@ -138,4 +120,4 @@ const History: React.FC = () => {
); );
} }
export default History; // Exporting the History component export default History;

View file

@ -2,7 +2,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
// Define all models that should be available. // Define all models that should be available.
//#region modelist
const modelList = { const modelList = {
'Offline Fast': { 'Offline Fast': {
model_type: 'local', model_type: 'local',
@ -113,7 +112,7 @@ const selectedAIFunction = [
'Language', 'Language',
'Weather' 'Weather'
] ]
//#region variables
const ModelSection: React.FC = () => { const ModelSection: React.FC = () => {
// Initialize state with value from localStorage or default to '' // Initialize state with value from localStorage or default to ''
const [selectedModelDropdown, setSelectedModelDropdown] = useState(''); const [selectedModelDropdown, setSelectedModelDropdown] = useState('');
@ -121,7 +120,7 @@ const ModelSection: React.FC = () => {
const [activeSelectedAIFunction, setActiveSelectedAIFunction] = useState(''); const [activeSelectedAIFunction, setActiveSelectedAIFunction] = useState('');
const [currentSelectedAIFunction, setCurrentSelectedAIFunction] = useState<string | null>(""); const [currentSelectedAIFunction, setCurrentSelectedAIFunction] = useState<string | null>("");
const [isOpenSourceMode, setIsOpenSourceMode] = useState<string|null>("false") const [isOpenSourceMode, setIsOpenSourceMode] = useState<string|null>("false")
//#region functions
useEffect(() => { useEffect(() => {
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
const defaultValues = { const defaultValues = {
@ -176,7 +175,7 @@ const ModelSection: React.FC = () => {
modelClicked(model) modelClicked(model)
} }
}; };
//#region dropdown
// Determine the filtered models based on current radioSelection // Determine the filtered models based on current radioSelection
const filteredModels = (() => { const filteredModels = (() => {
let models = []; let models = [];
@ -242,7 +241,7 @@ const ModelSection: React.FC = () => {
localStorage.setItem("type", modelList[selectedAIFunction]['model_type' as keyof typeof modelList[typeof selectedAIFunction]]) localStorage.setItem("type", modelList[selectedAIFunction]['model_type' as keyof typeof modelList[typeof selectedAIFunction]])
} }
} }
//#region return "html"
return ( return (
<div className="model-background"> <div className="model-background">
<div className="models"> <div className="models">

View file

@ -1,19 +1,17 @@
import React from 'react'; import React from 'react';
// Define the props for the ButtonSetting component
interface ButtonSettingProps { interface ButtonSettingProps {
label: string; // The label to display on the button label: string; // The label to display on the button
onClick: () => void; // The function to call when the button is clicked onClick: () => void; // The function to call when the button is clicked
className?: string; // Optional additional classes for styling className?: string; // Optional additional classes for styling
} }
// Functional component definition const ButtonSetting: React.FC<ButtonSettingProps> = ({ label, onClick }) => {
const ButtonSetting: React.FC<ButtonSettingProps> = ({ label, onClick, className }) => {
return ( return (
<div className="settings-option"> {/* Container for the button */} <div className="settings-option">
<button <button
onClick={onClick} // Call the onClick function when the button is clicked onClick={onClick} // Call the onClick function when the button is clicked
className={`export-button ${className || ''}`} // Apply any additional classes, default to empty if not provided className={"export-button"} // Apply any additional classes
> >
{label} {/* Display the label on the button */} {label} {/* Display the label on the button */}
</button> </button>

View file

@ -1,28 +1,25 @@
import React from 'react'; import React from 'react';
// Define the props for the CheckboxSetting component
interface CheckboxSettingProps { interface CheckboxSettingProps {
label: string; // The label to display label: string; // The label to display
checked: boolean; // The checked state of the checkbox checked: boolean; // The checked state of the checkbox
setChecked: (value: boolean) => void; // Method to update the state setChecked: (value: boolean) => void; // Method to update the state
} }
// Functional component definition
const CheckboxSetting: React.FC<CheckboxSettingProps> = ({ label, checked, setChecked }) => { const CheckboxSetting: React.FC<CheckboxSettingProps> = ({ label, checked, setChecked }) => {
// Handler to toggle the checkbox state
const handleCheckboxChange = () => { const handleCheckboxChange = () => {
setChecked(!checked); // Toggle the checked state setChecked(!checked);
}; };
return ( return (
<div className="settings-option"> {/* Container for the checkbox setting */} <div className="settings-option">
<label> <label>
<input <input
type="checkbox" // Checkbox input type type="checkbox"
checked={checked} // Set the checked state based on the prop checked={checked}
onChange={handleCheckboxChange} // Call the handler on change onChange={handleCheckboxChange}
/> />
{label} {/* Display the label next to the checkbox */} {label}
</label> </label>
</div> </div>
); );

View file

@ -1,32 +1,29 @@
import React from 'react'; import React from 'react';
// Define the props for the ColorSetting component interface ColorSettingProps {
interface ColorSettingProps {
name: string; // The name to display in the <p> tag name: string; // The name to display in the <p> tag
value: string; // The current color value value: string; // The current color value
setValue: (newColor: string) => void; // The method to update the state setValue: (newColor: string) => void; // The method to update the state
cssVariable: string; // The CSS variable name to set cssVariable: string; // The CSS variable name to set
} }
// Functional component definition const ColorSetting: React.FC<ColorSettingProps> = ({ name, value, setValue, cssVariable }) => {
const ColorSetting: React.FC<ColorSettingProps> = ({ name, value, setValue, cssVariable }) => {
// Handler to change the color value
const handleColorChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newColor = e.target.value; // Get the new color from the input const newColor = e.target.value;
setValue(newColor); // Update the state with the new color setValue(newColor);
document.documentElement.style.setProperty(cssVariable, newColor); // Set the CSS variable document.documentElement.style.setProperty(cssVariable, newColor);
}; };
return ( return (
<div className="settings-option"> {/* Container for the color setting */} <div className="settings-option">
<p>{name}</p> {/* Display the name */} <p>{name}</p>
<input <input
type="color" // Input type for color picker type="color"
value={value} // Set the input value to the current color value={value}
onChange={handleColorChange} // Call the handler on change onChange={handleColorChange}
/> />
</div> </div>
); );
}; };
export default ColorSetting; export default ColorSetting;

View file

@ -1,39 +1,35 @@
import React from 'react'; import React from 'react';
// Define the structure of each option in the dropdown
interface Option { interface Option {
value: string; // The actual value to be used value: string; // The actual value to be used
label: string; // The label to display for the option label: string; // The label to display for the option
} }
// Define the props for the DropdownSetting component
interface DropdownSettingProps { interface DropdownSettingProps {
label: string; // The label to display above the dropdown label: string; // The label to display
value: string; // The currently selected value value: string; // The current selected value
setValue: (newValue: string) => void; // Method to update the state with the new value setValue: (newValue: string) => void; // The method to update the state
options: Option[]; // List of options for the dropdown options: Option[]; // List of options for the dropdown
} }
// Functional component definition
const DropdownSetting: React.FC<DropdownSettingProps> = ({ label, value, setValue, options }) => { const DropdownSetting: React.FC<DropdownSettingProps> = ({ label, value, setValue, options }) => {
// Handler to change the selected option const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => { const newValue = e.target.value;
const newValue = e.target.value; // Get the new selected value setValue(newValue);
setValue(newValue); // Update the state with the new value };
};
return ( return (
<div className="settings-option"> {/* Container for the dropdown setting */} <div className="settings-option">
<label>{label}</label> {/* Display the label */} <label>{label}</label>
<select value={value} onChange={handleSelectChange}> {/* Dropdown selection */} <select value={value} onChange={handleSelectChange}>
{options.map((option) => ( // Map through options to create <option> elements {options.map((option) => (
<option key={option.value} value={option.value}> <option key={option.value} value={option.value}>
{option.label} {/* Display the label for the option */} {option.label}
</option> </option>
))} ))}
</select> </select>
</div> </div>
); );
}; };
export default DropdownSetting; export default DropdownSetting;

View file

@ -2,10 +2,9 @@
import React from 'react'; import React from 'react';
const ThemeDropdown: React.FC<{ const ThemeDropdown: React.FC<{
selectedTheme: string; // Currently selected theme selectedTheme: string;
setSelectedTheme: (theme: string) => void; // Function to update the selected theme setSelectedTheme: (theme: string) => void;
}> = ({ selectedTheme, setSelectedTheme }) => { }> = ({ selectedTheme, setSelectedTheme }) => {
// Define available theme options
const themeOptions = [ const themeOptions = [
{ value: 'IOMARKET', label: 'IOMARKET' }, { value: 'IOMARKET', label: 'IOMARKET' },
{ value: 'WHITE', label: 'WHITE' }, { value: 'WHITE', label: 'WHITE' },
@ -15,22 +14,22 @@ const ThemeDropdown: React.FC<{
]; ];
return ( return (
<div className="settings-option"> {/* Container for the dropdown */} <div className="settings-option">
<p>Select Theme</p> {/* Label for the dropdown */} <p>Select Theme</p>
<select <select
value={selectedTheme} // Current selected theme value={selectedTheme}
onChange={(e) => { // Handler for dropdown changes onChange={(e) => {
const theme = e.target.value; // Get the selected value const theme = e.target.value;
if (theme !== 'default' && typeof localStorage !== 'undefined') { if (theme !== 'default' && typeof localStorage !== 'undefined') {
setSelectedTheme(theme); // Update the selected theme state setSelectedTheme(theme);
localStorage.setItem('selectedTheme', theme); // Save the theme to localStorage localStorage.setItem('selectedTheme', theme);
} }
}} }}
> >
<option value="default">Select your style...</option> {/* Default option */} <option value="default">Select your style...</option>
{themeOptions.map((option) => ( // Map through theme options to create <option> elements {themeOptions.map((option) => (
<option key={option.value} value={option.value}> <option key={option.value} value={option.value}>
{option.label} {/* Display the label for the option */} {option.label}
</option> </option>
))} ))}
</select> </select>

View file

@ -2,29 +2,28 @@
import React from 'react'; import React from 'react';
interface FontSizeSettingProps { interface FontSizeSettingProps {
fontSize: string; // The current font size as a string (e.g., "16px") fontSize: string; // The current font size
setFontSize: (newSize: string) => void; // Function to update the font size setFontSize: (newSize: string) => void; // Function to update the font size
} }
const FontSizeSetting: React.FC<FontSizeSettingProps> = ({ fontSize, setFontSize }) => { const FontSizeSetting: React.FC<FontSizeSettingProps> = ({ fontSize, setFontSize }) => {
// Handle changes to the font size input
const handleFontSizeChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleFontSizeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newSize = `${e.target.value}px`; // Create the new font size string const newSize = `${e.target.value}px`;
setFontSize(newSize); // Update the font size state setFontSize(newSize);
document.documentElement.style.setProperty('--font-size', newSize); // Update the CSS variable document.documentElement.style.setProperty('--font-size', newSize);
}; };
return ( return (
<div className="settings-option"> {/* Container for the font size setting */} <div className="settings-option">
<p>Font Size</p> {/* Label for the setting */} <p>Font Size</p>
<input <input
type="range" // Range input for selecting font size type="range"
min="12" // Minimum font size min="12"
max="30" // Maximum font size max="30"
value={parseInt(fontSize, 10)} // Ensure value is a number for the slider value={parseInt(fontSize, 10)} // Ensure value is a number
onChange={handleFontSizeChange} // Update font size on change onChange={handleFontSizeChange}
/> />
<span>{fontSize}</span> {/* Display the current font size */} <span>{fontSize}</span>
</div> </div>
); );
}; };

View file

@ -12,26 +12,25 @@ const OpenSourceModeToggle: React.FC<OpenSourceModeToggleProps> = ({
setOpenSourceMode, setOpenSourceMode,
setSelectedOption setSelectedOption
}) => { }) => {
// Handle toggle change event
const handleToggleChange = () => { const handleToggleChange = () => {
const newValue = !openSourceMode; // Toggle the current state const newValue = !openSourceMode;
setOpenSourceMode(newValue); // Update the open source mode state setOpenSourceMode(newValue);
// Update radio selection based on the new openSourceMode value // Update radio selection based on the new openSourceMode value
if (newValue) { if (newValue) {
setSelectedOption('FOSS'); // Set to FOSS if enabling open source mode setSelectedOption('FOSS'); // Set to FOSS if enabling open source mode
} else { } else {
setSelectedOption('None'); // Set to a default value when disabling setSelectedOption('None'); // Or any other default value when disabling
} }
}; };
return ( return (
<div className="settings-option"> {/* Container for the toggle setting */} <div className="settings-option">
<label> <label>
<input <input
type="checkbox" // Checkbox for toggling open source mode type="checkbox"
checked={openSourceMode} // Check if the mode is currently enabled checked={openSourceMode}
onChange={handleToggleChange} // Handle changes to the checkbox onChange={handleToggleChange}
/> />
Enable Open Source Mode Enable Open Source Mode
</label> </label>

View file

@ -14,28 +14,28 @@ const PrivacySettings: React.FC<PrivacySettingsProps> = ({ selectedOption, handl
<div className="settings-option"> <div className="settings-option">
<p>Disable Options:</p> <p>Disable Options:</p>
<div className="slider"> <div className="slider">
{/* Offline Option */} {/* Offline */}
<div <div
className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''}`} // Active class based on selection className={`slider-option ${selectedOption === 'Offline' ? 'active' : ''}`}
onClick={() => handleRadioChange('Offline')} // Handle selection change onClick={() => handleRadioChange('Offline')} // Allow selection only if not in open-source mode
> >
Offline tools{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */} Offline tools{openSourceMode ? ' (FOSS)' : ''}
</div> </div>
{/* Online Option */} {/* Online */}
<div <div
className={`slider-option ${selectedOption === 'Online' ? 'active' : ''}`} // Active class based on selection className={`slider-option ${selectedOption === 'Online' ? 'active' : ''}`}
onClick={() => handleRadioChange('Online')} // Handle selection change onClick={() => handleRadioChange('Online')}
> >
Online tools{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */} Online tools{openSourceMode ? ' (FOSS)' : ''}
</div> </div>
{/* None Option */} {/* None */}
<div <div
className={`slider-option ${selectedOption === 'None' ? 'active' : ''}`} // Active class based on selection className={`slider-option ${selectedOption === 'None' ? 'active' : ''}`}
onClick={() => handleRadioChange('None')} // Handle selection change onClick={() => handleRadioChange('None')}
> >
None{openSourceMode ? ' (FOSS)' : ''} {/* Display FOSS label if applicable */} None{openSourceMode ? ' (FOSS)' : ''}
</div> </div>
</div> </div>
<br /> <br />

View file

@ -65,7 +65,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
// Measurement setting // Measurement setting
const [preferredMeasurement, setPreferredMeasurement] = useState(() => localStorage.getItem('preferredMeasurement') || 'Metric'); const [preferredMeasurement, setPreferredMeasurement] = useState(() => localStorage.getItem('preferredMeasurement') || 'Metric');
//#region Theme settings // Theme settings
const [backgroundColor, setBackgroundColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--background-color').trim()); const [backgroundColor, setBackgroundColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--background-color').trim());
const [headerBackground, setHeaderBackground] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--header-background-color').trim()); const [headerBackground, setHeaderBackground] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--header-background-color').trim());
const [textColor, setTextColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim()); const [textColor, setTextColor] = useState(() => getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim());
@ -122,7 +122,6 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
const [google, setGoogle] = useState(localStorage.getItem('google') || ""); const [google, setGoogle] = useState(localStorage.getItem('google') || "");
const [myBoolean, setMyBoolean] = useState<boolean>(() => getItemFromLocalStorage('myBoolean')); const [myBoolean, setMyBoolean] = useState<boolean>(() => getItemFromLocalStorage('myBoolean'));
//#region Json
const settings = { const settings = {
userPreferences: { userPreferences: {
activeSection, activeSection,
@ -186,7 +185,6 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
}, },
}; };
//#region color settings
const colorSettings = [ const colorSettings = [
{ name: "Background Color", value: backgroundColor, setValue: setBackgroundColor, cssVariable: "--background-color" }, { name: "Background Color", value: backgroundColor, setValue: setBackgroundColor, cssVariable: "--background-color" },
{ name: "Header Background Color", value: headerBackground, setValue: setHeaderBackground, cssVariable: "--header-background-color" }, { name: "Header Background Color", value: headerBackground, setValue: setHeaderBackground, cssVariable: "--header-background-color" },
@ -221,7 +219,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ name: "Burger Menu Background Color", value: burgerMenuBackgroundColor, setValue: setBurgerMenuBackgroundColor, cssVariable: "--burger-menu-background-color" }, { name: "Burger Menu Background Color", value: burgerMenuBackgroundColor, setValue: setBurgerMenuBackgroundColor, cssVariable: "--burger-menu-background-color" },
]; ];
//#region time settings
const timeZoneOptions = [ const timeZoneOptions = [
{ value: 'GMT', label: 'GMT' }, { value: 'GMT', label: 'GMT' },
{ value: 'EST', label: 'EST' }, { value: 'EST', label: 'EST' },
@ -235,7 +233,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: 'JST', label: 'JST' }, { value: 'JST', label: 'JST' },
]; ];
//#region language settings
const languageOptions = [ const languageOptions = [
{ code: 'en', name: 'English' }, { code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish' }, { code: 'es', name: 'Spanish' },
@ -248,7 +246,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ code: 'ru', name: 'Russian' }, { code: 'ru', name: 'Russian' },
{ code: 'ar', name: 'Arabic' }, { code: 'ar', name: 'Arabic' },
]; ];
//#region currency settings
const currencyOptions = [ const currencyOptions = [
{ code: 'usd', name: 'USD' }, { code: 'usd', name: 'USD' },
{ code: 'eur', name: 'EUR' }, { code: 'eur', name: 'EUR' },
@ -260,7 +258,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ code: 'cny', name: 'CNY' }, { code: 'cny', name: 'CNY' },
{ code: 'inr', name: 'INR' }, { code: 'inr', name: 'INR' },
]; ];
//#region date settings
const dateFormatOptions = [ const dateFormatOptions = [
{ value: 'mm/dd/yyyy', label: 'MM/DD/YYYY' }, { value: 'mm/dd/yyyy', label: 'MM/DD/YYYY' },
{ value: 'dd/mm/yyyy', label: 'DD/MM/YYYY' }, { value: 'dd/mm/yyyy', label: 'DD/MM/YYYY' },
@ -278,7 +276,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: 'Metric', label: 'Metric' }, { value: 'Metric', label: 'Metric' },
{ value: 'Imperial', label: 'Imperial' }, { value: 'Imperial', label: 'Imperial' },
]; ];
//#region text settings
const fontOptions = [ const fontOptions = [
{ value: "'Poppins', sans-serif", label: 'Poppins' }, { value: "'Poppins', sans-serif", label: 'Poppins' },
{ value: "'Inconsolata', monospace", label: 'Inconsolata' }, { value: "'Inconsolata', monospace", label: 'Inconsolata' },
@ -296,7 +294,7 @@ const Settings: React.FC<{ closeSettings: () => void; accountName: string }> = (
{ value: "'Zilla Slab Highlight', serif", label: 'Zilla Slab Highlight' }, { value: "'Zilla Slab Highlight', serif", label: 'Zilla Slab Highlight' },
]; ];
//#region Function //#region Start of the code
const handleLogout = () => { const handleLogout = () => {
localStorage.clear(); localStorage.clear();
alert('Successfully logged out!'); alert('Successfully logged out!');

View file

@ -10,7 +10,6 @@ export function exportSettings(): string {
for (let i = 0; i < localStorage.length; i++) { for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i); const key = localStorage.key(i);
if (key) { if (key) {
// Exclude sensitive information
if (key !== "accountName" && key !== "accountPassword" && key !== "accountEmail") { if (key !== "accountName" && key !== "accountPassword" && key !== "accountEmail") {
settings[key] = localStorage.getItem(key) || ""; settings[key] = localStorage.getItem(key) || "";
} }
@ -40,28 +39,25 @@ export function importSettings(jsonData: string): void {
} }
} }
// Send current settings to the database
export const sendToDatabase = async () => { export const sendToDatabase = async () => {
const useName = localStorage.getItem("accountName"); const useName = localStorage.getItem("accountName")
const usePassword = localStorage.getItem("accountPassword"); const usePassword = localStorage.getItem("accountPassword")
if (useName && usePassword) { if (useName && usePassword) {
const result = await changeSettings(useName, usePassword, JSON.parse(exportSettings())); const result = await changeSettings(useName, usePassword, JSON.parse(exportSettings()))
if (result === true) { if (result == true) {
// Only reload if the settings change was successful
window.location.reload(); window.location.reload();
} }
} }
window.location.reload();
}; };
// Import settings from the database based on username and password
export const importDatabase = async (useName: string, usePassword: string) => { export const importDatabase = async (useName: string, usePassword: string) => {
const databaseSettings = await getSettings(useName, usePassword); const databaseSettings = await getSettings(useName, usePassword);
// Ensure user settings exist before flattening and storing // Ensure user settings exist before flattening and storing
if (typeof databaseSettings === 'object' && databaseSettings) { if (typeof databaseSettings == 'object' && databaseSettings) {
importSettings(JSON.stringify(databaseSettings, null, 2)); // Pass only the current user's settings importSettings(JSON.stringify(databaseSettings, null, 2)); // Pass only the current user's settings
} else { } else {
console.error('Database settings are not in the expected format.'); console.error('Database settings are not in the expected format.');
} }
}; }

View file

@ -1,4 +1,3 @@
//#region IOMARKET
export const applyIOMarketTheme = () => { export const applyIOMarketTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#7e7e7e'); document.documentElement.style.setProperty('--header-background-color', '#7e7e7e');
document.documentElement.style.setProperty('--header-text-color', '#ffffff'); document.documentElement.style.setProperty('--header-text-color', '#ffffff');
@ -36,7 +35,7 @@ export const applyIOMarketTheme = () => {
document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'"); document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'");
document.documentElement.style.setProperty('--font-size', '16px'); document.documentElement.style.setProperty('--font-size', '16px');
}; };
//#region WHITE
export const applyWhiteTheme = () => { export const applyWhiteTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#f0f0f0'); // Lighter header background document.documentElement.style.setProperty('--header-background-color', '#f0f0f0'); // Lighter header background
document.documentElement.style.setProperty('--header-text-color', '#333'); // Dark text for contrast document.documentElement.style.setProperty('--header-text-color', '#333'); // Dark text for contrast
@ -74,7 +73,7 @@ export const applyWhiteTheme = () => {
document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'"); // Same font family document.documentElement.style.setProperty('--font-family', "'Poppins', 'sans-serif'"); // Same font family
document.documentElement.style.setProperty('--font-size', '16px'); // Same font size document.documentElement.style.setProperty('--font-size', '16px'); // Same font size
}; };
//#region BLACK
export const applyBlackTheme = () => { export const applyBlackTheme = () => {
document.documentElement.style.setProperty('--header-background-color', '#1a1a1a'); // Dark header background document.documentElement.style.setProperty('--header-background-color', '#1a1a1a'); // Dark header background
document.documentElement.style.setProperty('--header-text-color', '#ffffff'); // White text for header document.documentElement.style.setProperty('--header-text-color', '#ffffff'); // White text for header
@ -113,7 +112,7 @@ export const applyBlackTheme = () => {
document.documentElement.style.setProperty('--font-size', '16px'); // Font size document.documentElement.style.setProperty('--font-size', '16px'); // Font size
}; };
//#region CUSTOM
export const applyCustomTheme = () => { export const applyCustomTheme = () => {
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
const themeVariables = { const themeVariables = {
@ -192,8 +191,6 @@ export const applyCustomTheme = () => {
}; };
} }
//#region BASIC-CUSTOM
// TypeScript types for color parameters // TypeScript types for color parameters
type Color = string; type Color = string;
@ -280,7 +277,6 @@ const lightenColor = (color: Color, percent: number): Color => {
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
}; };
//#region APPLY-THEME
// This is the new function that calls the appropriate theme application // This is the new function that calls the appropriate theme application
export const applyTheme = (theme: string, primary: string, secondary: string, accent: string, background: string, text: string) => { export const applyTheme = (theme: string, primary: string, secondary: string, accent: string, background: string, text: string) => {
switch (theme) { switch (theme) {

View file

@ -1,98 +1,68 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react"
// Define the structure of a Message
interface Message { interface Message {
role: string; // The role of the message sender (e.g., system, user, assistant) role: string
content: string; // The content of the message content:string
} }
// Define the structure for each chat session
interface ChatMessages { interface ChatMessages {
name: string; // The name or title of the chat name: string
messages: Message[]; // Array of messages in the chat messages: Message[]
timestamp: number; // Timestamp for the chat session timestamp: number
} }
// Define the structure for the global chat history
interface GlobalChatHistory { interface GlobalChatHistory {
chats: ChatMessages[]; // Array of chat sessions chats: ChatMessages[]
selectedIndex: number; // Index of the currently selected chat selectedIndex: number
} }
// Initial global chat history state
let globalChatHistory: GlobalChatHistory = { let globalChatHistory: GlobalChatHistory = {
chats: [ chats: [
{ { name: "Welcome!", messages: [{role:"system",content:"you are a helpful assistant"},{role:"assistant",content:"Hello! How can I help you?"}], timestamp: 4 },
name: "Welcome!",
messages: [
{ role: "system", content: "you are a helpful assistant" },
{ role: "assistant", content: "Hello! How can I help you?" }
],
timestamp: 4
},
], ],
selectedIndex: 0 selectedIndex:0
}; }
let listeners: ((state: GlobalChatHistory) => void)[] = []
// Listeners for state changes
let listeners: ((state: GlobalChatHistory) => void)[] = [];
// Function to set a new global state and notify listeners
const setGlobalState = (newState: GlobalChatHistory): void => { const setGlobalState = (newState: GlobalChatHistory): void => {
globalChatHistory = newState; // Update the global state globalChatHistory = newState;
listeners.forEach((listener) => listener(globalChatHistory)); // Notify all listeners listeners.forEach((listener) => listener(globalChatHistory))
} }
// Custom hook to manage chat history export const useChatHistory = (): [GlobalChatHistory, (index:number)=>void, (newState:GlobalChatHistory) => void,(messageIndex: number, newContent:string)=> void] => {
export const useChatHistory = (): [ const [state, setState] = useState<GlobalChatHistory>(globalChatHistory)
GlobalChatHistory, // Current state
(index: number) => void, // Function to set selected index
(newState: GlobalChatHistory) => void, // Function to set global state
(messageIndex: number, newContent: string) => void // Function to update a message
] => {
const [state, setState] = useState<GlobalChatHistory>(globalChatHistory); // Local state initialized with global state
useEffect(() => { useEffect(() => {
// Log the initial state for debugging console.log("help", globalChatHistory);
console.log("Current global chat history:", globalChatHistory);
// Listener to update local state when global state changes
const listener = (newState: GlobalChatHistory) => { const listener = (newState: GlobalChatHistory) => {
setState(newState); setState(newState)
}; }
listeners.push(listener); // Add the listener to the array listeners.push(listener)
// Cleanup function to remove the listener when the component unmounts
return () => { return () => {
listeners = listeners.filter((l) => l !== listener); listeners = listeners.filter((l) => l!== listener)
}; }
}, []); }, [])
// Function to set the selected chat index
const setSelectedIndex = (index: number) => { const setSelectedIndex = (index: number) => {
setGlobalState({ ...state, selectedIndex: index }); // Update the global state setGlobalState({...state,selectedIndex:index})
} }
// Function to update a specific message in the current chat
const updateMessage = (messageIndex: number, newContent: string) => { const updateMessage = (messageIndex: number, newContent: string) => {
const updatedChats = [...state.chats]; // Make a copy of the current chats const updatedChats = [...state.chats]
const chatIndex = globalChatHistory.selectedIndex; // Get the currently selected chat index const chatIndex = globalChatHistory.selectedIndex
// Check if the selected chat index is valid
if (chatIndex >= 0 && chatIndex < updatedChats.length) { if (chatIndex >= 0 && chatIndex < updatedChats.length) {
const updatedMessages = [...updatedChats[chatIndex].messages]; // Copy messages of the selected chat const updatedMessages = [...updatedChats[chatIndex].messages]
// Check if the message index is valid
if (messageIndex >= 0 && messageIndex < updatedMessages.length) { if (messageIndex >= 0 && messageIndex < updatedMessages.length) {
// Update the content of the specified message updatedMessages[messageIndex] = { ...updatedMessages[messageIndex], content: newContent }
updatedMessages[messageIndex] = { ...updatedMessages[messageIndex], content: newContent }; updatedChats[chatIndex] = { ...updatedChats[chatIndex], messages: updatedMessages }
updatedChats[chatIndex] = { ...updatedChats[chatIndex], messages: updatedMessages }; // Update the chat with new messages setGlobalState({...state, chats: updatedChats})
setGlobalState({ ...state, chats: updatedChats }); // Set the updated global state
} }
} }
} }
// Return the current state and action functions return [state, setSelectedIndex, setGlobalState, updateMessage]
return [state, setSelectedIndex, setGlobalState, updateMessage];
} }

View file

@ -1,23 +1,24 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
// Metadata for the application, used for SEO and page information
export const metadata = { export const metadata = {
title: 'AI Assistant | Interstellar Development', // Title of the page title: 'AI Assistant | Interstellar Development',
description: 'A little AI chat that is able to assist you in little tasks', // Description of the page description: 'A little AI chat that is able to assist you in little tasks',
}; };
// RootLayout component definition
export default function RootLayout({ children }: { children: ReactNode }) { export default function RootLayout({ children }: { children: ReactNode }) {
return ( return (
<html lang="en"> {/* Set the language of the document */} <html lang="en">
<head> <head>
<title>{metadata.title}</title> {/* Set the page title */} <title>{metadata.title}</title>
<meta name="description" content={metadata.description} /> {/* Set the page description for SEO */} <meta name="description" content={metadata.description} />
{/* Link to the favicon for the site */} {/* Tried adding the favicon here */}
<link rel="icon" href="./favicon.ico" type="image/x-icon" /> <link rel="icon" href="./favicon.ico" type="image/x-icon" />
</head> </head>
<body> <body>
<main>{children}</main> {/* Render the child components inside the main element */} <main>{children}</main>
</body> </body>
</html> </html>
); );

View file

@ -7,30 +7,21 @@ import Documentation from './components/Documentation'; // Ensure the import pat
import History from './components/History'; import History from './components/History';
import Models from './components/Models'; import Models from './components/Models';
import Credits from './components/Credits'; import Credits from './components/Credits';
import { import { applyIOMarketTheme, applyWhiteTheme, applyBlackTheme, applyCustomTheme, applyBasicCustomTheme } from './components/settings/theme';
applyIOMarketTheme,
applyWhiteTheme,
applyBlackTheme,
applyCustomTheme,
applyBasicCustomTheme
} from './components/settings/theme';
import './styles/master.css'; import './styles/master.css';
const LandingPage: React.FC = () => { const LandingPage: React.FC = () => {
// State to control visibility of the left panels
const [showDivs, setShowDivs] = useState(true); const [showDivs, setShowDivs] = useState(true);
// State to track which view is currently displayed
const [view, setView] = useState<'AI' | 'FAQ' | 'Documentation' | 'Credits'>('AI'); const [view, setView] = useState<'AI' | 'FAQ' | 'Documentation' | 'Credits'>('AI');
const conversationRef = useRef<HTMLDivElement>(null); const conversationRef = useRef<HTMLDivElement>(null);
// State for theme colors const [primaryColor, setPrimaryColor] = useState("#fefefe");
const [primaryColor, setPrimaryColor] = useState("#fefefe"); const [secondaryColor, setSecondaryColor] = useState("#fefefe");
const [secondaryColor, setSecondaryColor] = useState("#fefefe"); const [accentColor, setAccentColor] = useState("#fefefe");
const [accentColor, setAccentColor] = useState("#fefefe"); const [basicBackgroundColor, setBasicBackgroundColor] = useState("#fefefe");
const [basicBackgroundColor, setBasicBackgroundColor] = useState("#fefefe"); const [basicTextColor, setBasicTextColor] = useState("#fefefe");
const [basicTextColor, setBasicTextColor] = useState("#fefefe");
// Synchronize theme colors with local storage on component mount // Synchronize state with local storage on mount
useEffect(() => { useEffect(() => {
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
setPrimaryColor(localStorage.getItem("primaryColor") || "#fefefe"); setPrimaryColor(localStorage.getItem("primaryColor") || "#fefefe");
@ -41,21 +32,18 @@ const LandingPage: React.FC = () => {
} }
}, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]); }, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]);
// Toggle visibility of the left panels
const toggleDivs = () => { const toggleDivs = () => {
setShowDivs(prevState => !prevState); setShowDivs(prevState => !prevState);
}; };
// Change the current view based on user selection
const handleViewChange = (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => { const handleViewChange = (view: 'AI' | 'FAQ' | 'Documentation' | 'Credits') => {
setView(view); setView(view);
// Hide left panels if the selected view is not 'AI'
if (view !== 'AI') { if (view !== 'AI') {
setShowDivs(false); setShowDivs(false);
} }
}; };
// Apply the selected theme and color settings based on local storage // Apply theme based on selectedTheme and color settings
useEffect(() => { useEffect(() => {
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
const savedTheme = localStorage.getItem('selectedTheme'); const savedTheme = localStorage.getItem('selectedTheme');
@ -64,8 +52,8 @@ const LandingPage: React.FC = () => {
case 'IOMARKET': case 'IOMARKET':
applyIOMarketTheme(); applyIOMarketTheme();
break; break;
case 'WHITE': case 'WHITE':
applyWhiteTheme(); applyWhiteTheme();
break; break;
case 'BLACK': case 'BLACK':
applyBlackTheme(); applyBlackTheme();
@ -73,8 +61,8 @@ const LandingPage: React.FC = () => {
case 'CUSTOM': case 'CUSTOM':
applyCustomTheme(); applyCustomTheme();
break; break;
case 'BASIC-CUSTOM': case 'BASIC-CUSTOM':
applyBasicCustomTheme( applyBasicCustomTheme(
primaryColor, primaryColor,
secondaryColor, secondaryColor,
accentColor, accentColor,
@ -83,16 +71,15 @@ const LandingPage: React.FC = () => {
); );
break; break;
default: default:
applyIOMarketTheme(); // Fallback theme applyIOMarketTheme();
break; break;
} }
} }
} }
}, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]); // Apply themes whenever color states change }, [primaryColor, secondaryColor, accentColor, basicBackgroundColor, basicTextColor]); // Watch color states and apply themes accordingly
return ( return (
<> <>
{/* Header component with props for toggling and view change */}
<Header <Header
toggleDivs={toggleDivs} toggleDivs={toggleDivs}
showDivs={showDivs} showDivs={showDivs}
@ -104,14 +91,12 @@ const LandingPage: React.FC = () => {
<div className={`left-panel ${showDivs ? 'visible' : 'hidden'}`}> <div className={`left-panel ${showDivs ? 'visible' : 'hidden'}`}>
{showDivs && ( {showDivs && (
<div className="history-models"> <div className="history-models">
{/* Show History and Models components if left panels are visible */}
<History /> <History />
<Models /> <Models />
</div> </div>
)} )}
</div> </div>
<div className={`conversation-container ${showDivs ? 'collapsed' : 'expanded'}`} ref={conversationRef}> <div className={`conversation-container ${showDivs ? 'collapsed' : 'expanded'}`} ref={conversationRef}>
{/* Render the selected view based on the current state */}
{view === 'AI' && <AI />} {view === 'AI' && <AI />}
{view === 'FAQ' && <FAQ />} {view === 'FAQ' && <FAQ />}
{view === 'Documentation' && <Documentation />} {view === 'Documentation' && <Documentation />}

View file

@ -4,11 +4,10 @@ import google.generativeai as genai
import anthropic import anthropic
import ollama import ollama
class AI: class AI:
@staticmethod @staticmethod
def process_local(model, messages, return_class, access_token): def process_local(model, messages, return_class, access_token):
"""Process chat messages using the Ollama model locally."""
# Stream the chat response from the Ollama model
stream = ollama.chat( stream = ollama.chat(
model=model, model=model,
messages=messages, messages=messages,
@ -16,61 +15,50 @@ class AI:
options={"temperature": 0.5}, options={"temperature": 0.5},
) )
# Initialize the AI response for the given access token
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] = "" return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream: for chunk in stream:
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk["message"]["content"] return_class.ai_response[access_token] += chunk["message"]["content"]
@staticmethod @staticmethod
def process_mistralai(model, messages, return_class, access_token, api_key): def process_mistralai(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Mistral AI model."""
client = Mistral(api_key=api_key) client = Mistral(api_key=api_key)
# Stream the chat response from the Mistral model
stream_response = client.chat.stream(model=model, messages=messages) stream_response = client.chat.stream(model=model, messages=messages)
# Initialize the AI response for the given access token
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] = "" return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream_response: for chunk in stream_response:
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk.data.choices[0].delta.content return_class.ai_response[access_token] += chunk.data.choices[
0
].delta.content
@staticmethod @staticmethod
def process_openai(model, messages, return_class, access_token, api_key): def process_openai(model, messages, return_class, access_token, api_key):
"""Process chat messages using the OpenAI model."""
client = OpenAI(api_key=api_key) client = OpenAI(api_key=api_key)
# Stream the chat response from the OpenAI model
stream_response = client.chat.completions.create( stream_response = client.chat.completions.create(
model=model, messages=messages, stream=True model=model, messages=messages, stream=True
) )
# Initialize the AI response for the given access token
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] = "" return_class.ai_response[access_token] = ""
# Collect the response chunks and append to the response for the given access token
for chunk in stream_response: for chunk in stream_response:
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] += chunk.choices[0].delta.content return_class.ai_response[access_token] += chunk.choices[0].delta.content
@staticmethod @staticmethod
def process_anthropic(model, messages, return_class, access_token, api_key): def process_anthropic(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Anthropic model."""
client = anthropic.Anthropic(api_key=api_key) client = anthropic.Anthropic(api_key=api_key)
# Initialize the AI response for the given access token
with return_class.ai_response_lock: with return_class.ai_response_lock:
return_class.ai_response[access_token] = "" return_class.ai_response[access_token] = ""
# Stream the chat response from the Anthropic model
with client.messages.stream( with client.messages.stream(
max_tokens=1024, max_tokens=1024,
model=model, model=model,
@ -82,27 +70,24 @@ class AI:
@staticmethod @staticmethod
def process_google(model, messages, return_class, access_token, api_key): def process_google(model, messages, return_class, access_token, api_key):
"""Process chat messages using the Google Generative AI model.""" message = messages[-1]["content"]
message = messages[-1]["content"] # Get the latest message content messages.pop()
messages.pop() # Remove the latest message from the list
# Prepare messages for the Google Generative AI format
for msg in messages: for msg in messages:
msg["parts"] = msg.pop()["content"] msg["parts"] = msg.pop()["content"]
# Change 'assistant' role to 'model' for compatibility
for msg in messages: for msg in messages:
if msg["role"] == "assistant": if msg["role"] == "assistant":
msg["role"] = "model" msg["role"] = "model"
# Configure the Google Generative AI client
genai.configure(api_key=api_key) genai.configure(api_key=api_key)
# Start a chat session with the specified model and message history
model = genai.GenerativeModel(model) model = genai.GenerativeModel(model)
chat = model.start_chat(history=messages)
# Send the message and stream the response chat = model.start_chat(
history=messages,
)
response = chat.send_message(message, stream=True) response = chat.send_message(message, stream=True)
for chunk in response: for chunk in response:
return_class.ai_response[access_token] += chunk.text return_class.ai_response[access_token] += chunk.text

122
py/api.py
View file

@ -1,4 +1,5 @@
from time import sleep from time import sleep
from flask import Flask, request, jsonify from flask import Flask, request, jsonify
from flask_cors import CORS from flask_cors import CORS
import secrets import secrets
@ -12,58 +13,53 @@ from tts import TTS
class API: class API:
def __init__(self): def __init__(self):
# Initialize the API class with necessary components and configurations self.crypt_size = 64
self.crypt_size = 64 # Size for generating secure tokens self.app = Flask(__name__)
self.app = Flask(__name__) # Create a Flask app instance self.ai_response = {}
self.ai_response = {} # Dictionary to store AI responses keyed by access token self.ai = AI()
self.ai = AI() # AI processing instance self.db = DB()
self.db = DB() # Database instance self.weather = Weather()
self.weather = Weather() # Weather data retrieval instance self.voice = VoiceRecognition()
self.voice = VoiceRecognition() # Voice recognition instance self.tts = TTS()
self.tts = TTS() # Text-to-Speech instance self.db.load_database()
self.db.load_database() # Load the database on startup self.ai_response_lock = threading.Lock()
self.ai_response_lock = threading.Lock() # Lock for thread-safe access to AI responses CORS(self.app)
CORS(self.app) # Enable Cross-Origin Resource Sharing
def run(self): def run(self):
# Route to create a new AI session
@self.app.route("/interstellar_ai/api/ai_create", methods=["GET"]) @self.app.route("/interstellar_ai/api/ai_create", methods=["GET"])
def create_ai(): def create_ai():
access_token = secrets.token_urlsafe(self.crypt_size) # Generate a secure access token access_token = secrets.token_urlsafe(self.crypt_size)
# Ensure the access token is unique
while access_token in self.ai_response: while access_token in self.ai_response:
access_token = secrets.token_urlsafe(self.crypt_size) access_token = secrets.token_urlsafe(self.crypt_size)
self.ai_response[access_token] = "" # Initialize the response for the new session self.ai_response[access_token] = ""
return jsonify({"status": 200, "access_token": access_token}) return jsonify({"status": 200, "access_token": access_token})
# Route to send messages to the AI
@self.app.route("/interstellar_ai/api/ai_send", methods=["POST"]) @self.app.route("/interstellar_ai/api/ai_send", methods=["POST"])
def send_ai(): def send_ai():
data = request.get_json() # Get JSON data from the request data = request.get_json()
messages = data.get("messages") # Extract messages messages = data.get("messages")
model_type = data.get("model_type") # Extract model type model_type = data.get("model_type")
ai_model = data.get("ai_model") # Extract AI model name ai_model = data.get("ai_model")
access_token = data.get("access_token") # Extract access token access_token = data.get("access_token")
print(model_type) # Debugging output print(model_type)
if access_token not in self.ai_response: if access_token not in self.ai_response:
return jsonify({"status": 401, "error": "Invalid access token"}) # Token validation return jsonify({"status": 401, "error": "Invalid access token"})
# Start a new thread to process AI requests based on the model type
if model_type == "local": if model_type == "local":
thread = threading.Thread( thread = threading.Thread(
target=self.ai.process_local, target=self.ai.process_local,
args=(ai_model, messages, self, access_token), args=(ai_model, messages, self, access_token),
) )
thread.start() thread.start()
thread.join() # Wait for the thread to complete thread.join()
sleep(0.5) # Sleep for a short duration sleep(0.5)
return jsonify({"status": 200}) return jsonify({"status": 200})
elif model_type == "mistral": elif model_type == "mistral":
print(model_type) # Debugging output print(model_type)
api_key = data.get("api_key") # Get API key api_key = data.get("api_key")
thread = threading.Thread( thread = threading.Thread(
target=self.ai.process_mistralai, target=self.ai.process_mistralai,
args=(ai_model, messages, self, access_token, api_key), args=(ai_model, messages, self, access_token, api_key),
@ -73,7 +69,7 @@ class API:
sleep(0.5) sleep(0.5)
return jsonify({"status": 200}) return jsonify({"status": 200})
elif model_type == "openai": elif model_type == "openai":
api_key = data.get("api_key") # Get API key api_key = data.get("api_key")
thread = threading.Thread( thread = threading.Thread(
target=self.ai.process_openai, target=self.ai.process_openai,
args=(ai_model, messages, self, access_token, api_key), args=(ai_model, messages, self, access_token, api_key),
@ -83,7 +79,7 @@ class API:
sleep(0.5) sleep(0.5)
return jsonify({"status": 200}) return jsonify({"status": 200})
elif model_type == "anthropic": elif model_type == "anthropic":
api_key = data.get("api_key") # Get API key api_key = data.get("api_key")
thread = threading.Thread( thread = threading.Thread(
target=self.ai.process_anthropic, target=self.ai.process_anthropic,
args=(ai_model, messages, self, access_token, api_key), args=(ai_model, messages, self, access_token, api_key),
@ -93,7 +89,7 @@ class API:
sleep(0.5) sleep(0.5)
return jsonify({"status": 200}) return jsonify({"status": 200})
elif model_type == "google": elif model_type == "google":
api_key = data.get("api_key") # Get API key api_key = data.get("api_key")
thread = threading.Thread( thread = threading.Thread(
target=self.ai.process_google, target=self.ai.process_google,
args=(ai_model, messages, self, access_token, api_key), args=(ai_model, messages, self, access_token, api_key),
@ -103,85 +99,79 @@ class API:
sleep(0.5) sleep(0.5)
return jsonify({"status": 200}) return jsonify({"status": 200})
return jsonify({"status": 401, "error": "Invalid AI model type"}) # Model type validation return jsonify({"status": 401, "error": "Invalid AI model type"})
# Route to retrieve AI response based on access token
@self.app.route("/interstellar_ai/api/ai_get", methods=["GET"]) @self.app.route("/interstellar_ai/api/ai_get", methods=["GET"])
def get_ai(): def get_ai():
data = request.args.get("access_token") # Get access token from query parameters data = request.args.get("access_token")
if data not in self.ai_response: if data not in self.ai_response:
return jsonify({"status": 401, "error": "Invalid access token"}) # Token validation return jsonify({"status": 401, "error": "Invalid access token"})
return jsonify({"status": 200, "response": self.ai_response[data]}) # Return AI response return jsonify({"status": 200, "response": self.ai_response[data]})
# Route for database operations
@self.app.route("/interstellar_ai/db", methods=["POST"]) @self.app.route("/interstellar_ai/db", methods=["POST"])
def db_manipulate(): def db_manipulate():
sent_data = request.get_json() # Get JSON data from the request sent_data = request.get_json()
action = sent_data.get("action") # Extract action type action = sent_data.get("action")
if action == "create_account": if action == "create_account":
return jsonify({"status": 200, "response": self.db.add_user(sent_data)}) # Add user return jsonify({"status": 200, "response": self.db.add_user(sent_data)})
elif action == "change_password": elif action == "change_password":
return jsonify( return jsonify(
{"status": 200, "response": self.db.update_password(sent_data)} # Update password {"status": 200, "response": self.db.update_password(sent_data)}
) )
elif action == "get_settings": elif action == "get_settings":
return jsonify( return jsonify(
{"status": 200, "response": self.db.get_settings(sent_data)} # Get user settings {"status": 200, "response": self.db.get_settings(sent_data)}
) )
elif action == "change_settings": elif action == "change_settings":
return jsonify( return jsonify(
{"status": 200, "response": self.db.change_settings(sent_data)} # Change user settings {"status": 200, "response": self.db.change_settings(sent_data)}
) )
elif action == "get_history": elif action == "get_history":
return jsonify( return jsonify(
{"status": 200, "response": self.db.get_history(sent_data)} # Get user history {"status": 200, "response": self.db.get_history(sent_data)}
) )
elif action == "change_history": elif action == "change_history":
return jsonify( return jsonify(
{"status": 200, "response": self.db.change_history(sent_data)} # Change user history {"status": 200, "response": self.db.change_history(sent_data)}
) )
elif action == "check_credentials": elif action == "check_credentials":
return jsonify( return jsonify(
{"status": 200, "response": self.db.check_credentials(sent_data)} # Check user credentials {"status": 200, "response": self.db.check_credentials(sent_data)}
) )
elif action == "delete_account": elif action == "delete_account":
return jsonify( return jsonify(
{"status": 200, "response": self.db.delete_user(sent_data)} # Delete user account {"status": 200, "response": self.db.delete_user(sent_data)}
) )
elif action == "get_email": elif action == "get_email":
return jsonify( return jsonify(
{"status": 200, "response": self.db.get_email(sent_data)} # Get user email {"status": 200, "response": self.db.get_email(sent_data)}
) )
elif action == "get_name": elif action == "get_name":
return jsonify({"status": 200, "response": self.db.get_name(sent_data)}) # Get user name return jsonify({"status": 200, "response": self.db.get_name(sent_data)})
return jsonify({"status": 401, "response": "Invalid action"}) # Action validation return jsonify({"status": 401, "response": "Invalid action"})
# Route for voice recognition
@self.app.route("/interstellar_ai/api/voice_recognition", methods=["POST"]) @self.app.route("/interstellar_ai/api/voice_recognition", methods=["POST"])
def voice_recognition(): def voice_recognition():
audio = request.files.get("audio") # Get audio file from request audio = request.files.get("audio")
text = self.voice.recognition(audio) # Perform voice recognition text = self.voice.recognition(audio)
return jsonify({"status": 200, "response": text}) # Return recognized text return jsonify({"status": 200, "response": text})
# Route for weather information retrieval
@self.app.route("/interstellar_ai/api/weather", methods=["POST"]) @self.app.route("/interstellar_ai/api/weather", methods=["POST"])
def get_weather(): def get_weather():
sent_data = request.get_json() # Get JSON data from the request sent_data = request.get_json()
unit_type = sent_data.get("unit_type") # Extract unit type (metric, imperial) unit_type = sent_data.get("unit_type")
city = sent_data.get("city") # Extract city name city = sent_data.get("city")
weather_data = self.weather.getweather(unit_type, city) # Get weather data weather_data = self.weather.getweather(unit_type, city)
return jsonify({"status": 200, "response": weather_data}) # Return weather data return jsonify({"status": 200, "response": weather_data})
self.app.run(debug=True, host="0.0.0.0", port=5000) # Start the Flask app self.app.run(debug=True, host="0.0.0.0", port=5000)
# Route for Text-to-Speech conversion
@self.app.route("/interstellar_ai/api/tts", methods=["POST"]) @self.app.route("/interstellar_ai/api/tts", methods=["POST"])
def tts(): def tts():
text = request.args.get("text") # Get text from query parameters text = request.args.get("text")
return jsonify({"status": 200, "response": self.tts.gen_tts(text)}) # Generate TTS and return response return jsonify({"status": 200, "response": self.tts.gen_tts(text)})
# Initialize the API class and run the application
api = API() api = API()
api.run() api.run()

View file

@ -3,13 +3,12 @@ import json
import os import os
import pycouchdb import pycouchdb
class DB: class DB:
def __init__(self): def __init__(self):
# Initialize the database dictionary to store user data
self.database = {} self.database = {}
def ensure_username(self, data): def ensure_username(self, data):
# Ensure a username can be retrieved either from username or email
if "username" in data: if "username" in data:
return data.get("username") return data.get("username")
elif "email" in data: elif "email" in data:
@ -19,17 +18,15 @@ class DB:
@staticmethod @staticmethod
def hash_password(password): def hash_password(password):
# Hash the password with a salt for secure storage salt = "your_secret_salt"
salt = "your_secret_salt" # Consider using a secure random salt
hashed_password = hashlib.sha256((password + salt).encode()).hexdigest() hashed_password = hashlib.sha256((password + salt).encode()).hexdigest()
return hashed_password return hashed_password
def add_user(self, data): def add_user(self, data):
# Add a new user to the database if username is unique
username = data.get("username") username = data.get("username")
password = data.get("password") password = data.get("password")
email = data.get("email") email = data.get("email")
hashed_password = self.hash_password(password) # Hash the password hashed_password = self.hash_password(password)
user_data = { user_data = {
"hashed_password": hashed_password, "hashed_password": hashed_password,
"email": email, "email": email,
@ -38,123 +35,112 @@ class DB:
} }
if username not in self.database: if username not in self.database:
self.database[username] = user_data self.database[username] = user_data
self.save_database() # Save changes to the database self.save_database()
return True return True
return False # User already exists return False
def delete_user(self, data): def delete_user(self, data):
# Delete a user from the database if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return False # Invalid credentials return False
del self.database[username] # Remove user from database del self.database[username]
self.save_database() # Save changes self.save_database()
return True return True
def update_password(self, data): def update_password(self, data):
# Update the user's password if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
new_password = data.get("new_password") new_password = data.get("new_password")
if not self.check_credentials(data): if not self.check_credentials(data):
return False # Invalid credentials return False
hashed_new_password = self.hash_password(new_password) # Hash the new password hashed_new_password = self.hash_password(new_password)
self.database[username].update({"hashed_password": hashed_new_password}) self.database[username].update({"hashed_password": hashed_new_password})
self.save_database() # Save changes self.save_database()
return True return True
def check_credentials(self, data): def check_credentials(self, data):
# Verify if provided credentials match stored data
username = self.ensure_username(data) username = self.ensure_username(data)
password = data.get("password") password = data.get("password")
if username not in self.database: if username not in self.database:
return False # User not found return False
stored_hashed_password = self.database[username]["hashed_password"] stored_hashed_password = self.database[username]["hashed_password"]
entered_hashed_password = self.hash_password(password) entered_hashed_password = self.hash_password(password)
return stored_hashed_password == entered_hashed_password # Check hashed password return stored_hashed_password == entered_hashed_password
def change_settings(self, data): def change_settings(self, data):
# Change user settings if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return False # Invalid credentials return False
self.database[username]["settings"] = data.get("data") # Update settings self.database[username]["settings"] = data.get("data")
self.save_database() # Save changes self.save_database()
return True return True
def get_settings(self, data): def get_settings(self, data):
# Retrieve user settings if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return None # Invalid credentials return None
send_back = self.database[username].get("settings") # Get settings send_back = self.database[username].get("settings")
return send_back return send_back
def change_history(self, data): def change_history(self, data):
# Change user history if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return False # Invalid credentials return False
self.database[username]["history"] = data.get("data") # Update history self.database[username]["history"] = data.get("data")
self.save_database() # Save changes self.save_database()
return True return True
def get_history(self, data): def get_history(self, data):
# Retrieve user history if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return None # Invalid credentials return None
send_back = self.database[username].get("history") # Get history send_back = self.database[username].get("history")
return send_back return send_back
def get_email(self, data): def get_email(self, data):
# Retrieve user email if credentials are valid
username = self.ensure_username(data) username = self.ensure_username(data)
if not self.check_credentials(data): if not self.check_credentials(data):
return None # Invalid credentials return None
send_back = self.database[username].get("email") # Get email send_back = self.database[username].get("email")
return send_back return send_back
def get_name(self, data): def get_name(self, data):
# Retrieve username if credentials are valid
if not self.check_credentials(data): if not self.check_credentials(data):
return None # Invalid credentials return None
send_back = self.ensure_username(data) # Get username send_back = self.ensure_username(data)
return send_back return send_back
def save_database(self): def save_database(self):
# Save the database to the specified storage (CouchDB or JSON file)
if os.environ.get("PRODUCTION") == "YES": if os.environ.get("PRODUCTION") == "YES":
server = pycouchdb.Server("http://admin:admin@localhost:5984/") server = pycouchdb.Server("http://admin:admin@localhost:5984/")
db = server.database("interstellar_ai") db = server.database("interstellar_ai")
db.save(self.database) # Save to CouchDB db.save(self.database)
else: else:
with open("database.json", "w") as file: with open("database.json", "w") as file:
json.dump(self.database, file) # Save to JSON file json.dump(self.database, file)
def load_database(self): def load_database(self):
# Load the database from the specified storage (CouchDB or JSON file)
if os.environ.get("PRODUCTION") == "YES": if os.environ.get("PRODUCTION") == "YES":
server = pycouchdb.Server("http://admin:admin@localhost:5984/") server = pycouchdb.Server("http://admin:admin@localhost:5984/")
db = server.database("interstellar_ai") db = server.database("interstellar_ai")
if db: if db:
self.database = db # Load from CouchDB self.database = db
else: else:
server.create("interstellar_ai") # Create database if it doesn't exist server.create("interstellar_ai")
db = server.database("interstellar_ai") db = server.database("interstellar_ai")
db.save(self.database) # Save initial empty database db.save(self.database)
else: else:
try: try:
with open("database.json", "r") as file: with open("database.json", "r") as file:
self.database = json.load(file) # Load from JSON file self.database = json.load(file)
except FileNotFoundError: except FileNotFoundError:
pass # File not found, do nothing pass

View file

@ -1,5 +1,6 @@
import pyttsx3 import pyttsx3
class TTS: class TTS:
@staticmethod @staticmethod
def gen_tts(text): def gen_tts(text):

View file

@ -6,28 +6,20 @@ from pydub import AudioSegment
class VoiceRecognition: class VoiceRecognition:
@staticmethod @staticmethod
def recognition(audio): def recognition(audio):
# Read the audio file into a BytesIO buffer
audio_buffer = io.BytesIO(audio.read()) audio_buffer = io.BytesIO(audio.read())
# Load the audio file using pydub
audio_segment = AudioSegment.from_file(audio_buffer, format="ogg") audio_segment = AudioSegment.from_file(audio_buffer, format="ogg")
# Export the audio to a WAV format in a BytesIO buffer
wav_io = io.BytesIO() wav_io = io.BytesIO()
audio_segment.export(wav_io, format="wav") audio_segment.export(wav_io, format="wav")
wav_io.seek(0) # Reset the buffer pointer to the start wav_io.seek(0)
# Load the Whisper model model_size = "base"
model_size = "base" # Specify the model size
model = WhisperModel(model_size, device="cpu", compute_type="int8") model = WhisperModel(model_size, device="cpu", compute_type="int8")
# Transcribe the audio
segments, _ = model.transcribe(wav_io) segments, _ = model.transcribe(wav_io)
transcription = "" transcription = ""
# Combine the transcribed segments into a single string
for segment in segments: for segment in segments:
transcription += segment.text + " " transcription += segment.text + " "
result = transcription.strip()
result = transcription.strip() # Strip any leading/trailing whitespace
return result return result

View file

@ -15,7 +15,6 @@ class Weather:
async with python_weather.Client(unit=unit_type) as client: async with python_weather.Client(unit=unit_type) as client:
weather = await client.get(city) weather = await client.get(city)
# Collect weather data
data = { data = {
"temperature": weather.temperature, "temperature": weather.temperature,
"humidity": weather.humidity, "humidity": weather.humidity,