diff --git a/CHANGELOG.md b/CHANGELOG.md index 773dce9..391bb6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project partially follows [Semantic Versioning](https://semver.org/spec ### Added - Added support for touch-swipe and mouse-wheel gestures on the search engine icon to switch search engines when they are hidden ([@prem-k-r](https://github.com/prem-k-r)) ([#145](https://github.com/prem-k-r/MaterialYouNewTab/pull/145)) +- Added Google AI Studio to the AI Tools shortcuts ([#177](https://github.com/prem-k-r/MaterialYouNewTab/issues/177)) - Added support for custom shortcut icons via upload, URL, or pasted SVG ([@smurf11k](https://github.com/smurf11k)), ([@prem-k-r](https://github.com/prem-k-r)) ([#187](https://github.com/prem-k-r/MaterialYouNewTab/pull/187/)), ([#199](https://github.com/prem-k-r/MaterialYouNewTab/pull/199/)) - Added Daily Quote option to show one quote per day instead of refreshing on every new tab ([@KomeshBathula](https://github.com/KomeshBathula)) ([#141](https://github.com/prem-k-r/MaterialYouNewTab/pull/141)) diff --git a/index.html b/index.html index e138eb2..d22fdd7 100644 --- a/index.html +++ b/index.html @@ -1026,6 +1026,17 @@

Edit Bookmark

Gemini
+ +
+ + + + +
+
Google AI Studio
+
+
@@ -1966,4 +1977,4 @@

Material You New Tab

- \ No newline at end of file + diff --git a/locales/en.js b/locales/en.js index 0c62fa3..0e2cc2d 100644 --- a/locales/en.js +++ b/locales/en.js @@ -154,6 +154,7 @@ const en = { "ai_tools": "AI Tools", "chatGPT": "ChatGPT", "gemini": "Gemini", + "googleAIStudio": "Google AI Studio", "copilot": "Copilot", "claude": "Claude", "grok": "Grok", diff --git a/scripts/ai-tools.js b/scripts/ai-tools.js index d00972a..ab59a86 100644 --- a/scripts/ai-tools.js +++ b/scripts/ai-tools.js @@ -10,14 +10,15 @@ const aiToolsRaw = [ { id: "chatGPT", visible: true, order: 0 }, { id: "gemini", visible: true, order: 1 }, - { id: "copilot", visible: true, order: 2 }, - { id: "claude", visible: true, order: 3 }, - { id: "deepseek", visible: true, order: 4 }, - { id: "perplexity", visible: false, order: 5 }, - { id: "grok", visible: false, order: 6 }, - { id: "metaAI", visible: false, order: 7 }, - { id: "qwen", visible: false, order: 8 }, - { id: "firefly", visible: false, order: 9 } + { id: "googleAIStudio", visible: false, order: 2 }, + { id: "copilot", visible: true, order: 3 }, + { id: "claude", visible: true, order: 4 }, + { id: "deepseek", visible: true, order: 5 }, + { id: "perplexity", visible: false, order: 6 }, + { id: "grok", visible: false, order: 7 }, + { id: "metaAI", visible: false, order: 8 }, + { id: "qwen", visible: false, order: 9 }, + { id: "firefly", visible: false, order: 10 } ]; // Translations for AI tools const aiTools = aiToolsRaw.map(tool => ({ @@ -39,6 +40,35 @@ const aiToolsEditButton = document.getElementById("aiToolsEditButton"); const aiToolsCont = document.getElementById("aiToolsCont"); const aiToolsEditField = document.getElementById("aiToolsEditField"); +function createDefaultAIToolsSettings() { + return aiTools.map(tool => tool.visible ? tool.id : { [tool.id]: false }); +} + +function getAIToolId(settingItem) { + if (typeof settingItem === "string") return settingItem; + if (settingItem && typeof settingItem === "object") return Object.keys(settingItem)[0]; + return null; +} + +function mergeAIToolsSettings(savedSettings) { + const defaultSettings = createDefaultAIToolsSettings(); + if (!Array.isArray(savedSettings)) return defaultSettings; + + const validToolIds = new Set(aiToolsRaw.map(tool => tool.id)); + const normalizedSavedSettings = savedSettings.filter(settingItem => { + const toolId = getAIToolId(settingItem); + return toolId && validToolIds.has(toolId); + }); + + const savedToolIds = new Set(normalizedSavedSettings.map(getAIToolId)); + const missingSettings = defaultSettings.filter(settingItem => { + const toolId = getAIToolId(settingItem); + return toolId && !savedToolIds.has(toolId); + }); + + return [...normalizedSavedSettings, ...missingSettings]; +} + // Animation helper function function animateReorder(element1, element2, direction) { return new Promise((resolve) => { @@ -129,14 +159,10 @@ function saveAIToolsSettings() { // Function to apply saved settings (visibility and order) function applyAIToolsSettings() { const savedSettings = JSON.parse(localStorage.getItem("aiToolsSettings") || "null"); - let settingsToApply; + const settingsToApply = mergeAIToolsSettings(savedSettings); - if (!savedSettings || !Array.isArray(savedSettings)) { - // Initialize with default values if no settings exist - settingsToApply = aiTools.map(tool => tool.visible ? tool.id : { [tool.id]: false }); + if (JSON.stringify(savedSettings) !== JSON.stringify(settingsToApply)) { localStorage.setItem("aiToolsSettings", JSON.stringify(settingsToApply)); - } else { - settingsToApply = savedSettings; } // Create a map of current tool elements for quick lookup @@ -152,15 +178,9 @@ function applyAIToolsSettings() { // Append tools in order based on settings settingsToApply.forEach(item => { - let toolId, isVisible; - - if (typeof item === "string") { - toolId = item; - isVisible = true; - } else { - toolId = Object.keys(item)[0]; - isVisible = false; - } + const toolId = getAIToolId(item); + const isVisible = typeof item === "string"; + if (!toolId) return; const toolElement = toolElements.get(toolId); if (toolElement) { @@ -176,15 +196,9 @@ function generateAIToolsForm(settings) { // Create form elements settings.forEach((settingItem, index) => { - let toolId, isVisible; - - if (typeof settingItem === "string") { - toolId = settingItem; - isVisible = true; - } else { - toolId = Object.keys(settingItem)[0]; - isVisible = false; - } + const toolId = getAIToolId(settingItem); + const isVisible = typeof settingItem === "string"; + if (!toolId) return; const originalTool = aiTools.find(t => t.id === toolId); const toolLabel = originalTool?.label || toolId; @@ -244,19 +258,7 @@ function showAIToolsSettings() { // Load saved tool order and visibility or initialize from defaults let savedSettings = JSON.parse(localStorage.getItem("aiToolsSettings") || "null"); - - // If no settings exist, create from aiTools - if (!savedSettings || !Array.isArray(savedSettings)) { - savedSettings = aiTools.map(tool => { - if (tool.visible) { - return tool.id; - } else { - const hiddenTool = {}; - hiddenTool[tool.id] = false; - return hiddenTool; - } - }); - } + savedSettings = mergeAIToolsSettings(savedSettings); // Generate the form with the saved settings generateAIToolsForm(savedSettings); @@ -382,15 +384,7 @@ document.addEventListener("DOMContentLoaded", function () { // Reset button in settings modal resetAISettingsBtn.addEventListener("click", function () { // Create default settings - const defaultSettings = aiTools.map(tool => { - if (tool.visible) { - return tool.id; - } else { - const hiddenTool = {}; - hiddenTool[tool.id] = false; - return hiddenTool; - } - }); + const defaultSettings = createDefaultAIToolsSettings(); // Generate the form with default settings generateAIToolsForm(defaultSettings); diff --git a/scripts/languages.js b/scripts/languages.js index 2ba01e0..330464c 100644 --- a/scripts/languages.js +++ b/scripts/languages.js @@ -194,6 +194,7 @@ function applyLanguage(lang) { "quoraEngine", "chatGPT", "gemini", + "googleAIStudio", "copilot", "claude", "grok",