diff --git a/manifest(firefox).json b/manifest(firefox).json
index e8971292..8fb2d6b6 100644
--- a/manifest(firefox).json
+++ b/manifest(firefox).json
@@ -10,7 +10,7 @@
"https://search.brave.com/api/suggest*"
],
"background": {
- "scripts": ["background.js"],
+ "scripts": ["scripts/background.js"],
"persistent": true
},
"icons": {
diff --git a/scripts/ai-tools.js b/scripts/ai-tools.js
index 4c10e2f7..3e5fac67 100644
--- a/scripts/ai-tools.js
+++ b/scripts/ai-tools.js
@@ -6,7 +6,7 @@
* If not, see
.
*/
-// when User click on "AI-Tools"
+// When User click on "AI-Tools"
const element = document.getElementById("toolsCont");
const shortcuts = document.getElementById("shortcutsContainer");
@@ -68,11 +68,9 @@ document.addEventListener("click", (event) => {
}
});
-document.getElementById("0NIHK").onclick = toggleShortcuts;
-
-//
-
+document.getElementById("aiToolsIcon").onclick = toggleShortcuts;
+// Save and load checkbox state
document.addEventListener("DOMContentLoaded", function () {
const aiToolsCont = document.getElementById("aiToolsCont");
const aiToolsCheckbox = document.getElementById("aiToolsCheckbox");
diff --git a/scripts/background.js b/scripts/background.js
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/scripts/background.js
@@ -0,0 +1 @@
+
diff --git a/scripts/backup-restore.js b/scripts/backup-restore.js
index c85e50af..1d06607f 100644
--- a/scripts/backup-restore.js
+++ b/scripts/backup-restore.js
@@ -189,4 +189,4 @@ resetbtn.addEventListener("click", () => {
localStorage.clear();
location.reload();
}
-});
+});
\ No newline at end of file
diff --git a/scripts/bookmarks.js b/scripts/bookmarks.js
index 3a79c947..723c7387 100644
--- a/scripts/bookmarks.js
+++ b/scripts/bookmarks.js
@@ -279,9 +279,9 @@ document.addEventListener("DOMContentLoaded", function () {
// Open in a new tab
event.preventDefault();
if (isFirefox) {
- browser.tabs.create({url: node.url, active: false});
- } else if (isChrome) {
- chrome.tabs.create({url: node.url, active: false});
+ browser.tabs.create({ url: node.url, active: false });
+ } else if (isChromiumBased) {
+ chrome.tabs.create({ url: node.url, active: false });
} else {
window.open(node.url, "_blank");
}
@@ -289,9 +289,9 @@ document.addEventListener("DOMContentLoaded", function () {
// Open in the current tab
event.preventDefault();
if (isFirefox) {
- browser.tabs.update({url: node.url});
- } else if (isChrome) {
- chrome.tabs.update({url: node.url}, function () {
+ browser.tabs.update({ url: node.url });
+ } else if (isChromiumBased) {
+ chrome.tabs.update({ url: node.url }, function () {
});
} else {
window.location.href = node.url;
@@ -312,6 +312,7 @@ document.addEventListener("DOMContentLoaded", function () {
// ------------------------ End of Bookmark System -----------------------------------
+// Save and load the state of the bookmarks toggle
document.addEventListener("DOMContentLoaded", function () {
const bookmarksCheckbox = document.getElementById("bookmarksCheckbox");
const bookmarkGridCheckbox = document.getElementById("bookmarkGridCheckbox");
@@ -320,7 +321,7 @@ document.addEventListener("DOMContentLoaded", function () {
let bookmarksPermission;
if (isFirefox && browser.permissions) {
bookmarksPermission = browser.permissions;
- } else if (isChrome || isEdge || isBrave && chrome.permissions) {
+ } else if (isChromiumBased && chrome.permissions) {
bookmarksPermission = chrome.permissions;
} else {
alert(translations[currentLanguage]?.UnsupportedBrowser || translations["en"].UnsupportedBrowser);
@@ -380,6 +381,7 @@ document.addEventListener("DOMContentLoaded", function () {
loadCheckboxState("bookmarkGridCheckboxState", bookmarkGridCheckbox);
})
+// Keyboard shortcut for bookmarks
document.addEventListener("keydown", function (event) {
if (event.key === "ArrowRight" && event.target.tagName !== "INPUT" && event.target.tagName !== "TEXTAREA" && event.target.isContentEditable !== true) {
if (bookmarksCheckbox.checked) {
diff --git a/scripts/browser-utils.js b/scripts/browser-utils.js
new file mode 100644
index 00000000..b3f124a9
--- /dev/null
+++ b/scripts/browser-utils.js
@@ -0,0 +1,36 @@
+/*
+ * Material You NewTab
+ * Copyright (c) 2023-2025 XengShi
+ * Licensed under the GNU General Public License v3.0 (GPL-3.0)
+ * You should have received a copy of the GNU General Public License along with this program.
+ * If not, see
.
+ */
+
+// Constants to detect the browser and platform details
+
+// Check if the browser is Firefox
+const isFirefox = typeof browser !== "undefined" || navigator.userAgent.toLowerCase().includes("firefox");
+
+// Check if the browser is Chromium-based
+const isChromiumBased = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime) && !isFirefox;
+
+// Check if the browser is Edge
+const isEdge = /Edg/.test(navigator.userAgent);
+
+// Check if the browser is Brave
+const isBrave = !!(navigator.brave && navigator.brave.isBrave());
+
+// Check if the browser is Opera
+const isOpera = /OPR/.test(navigator.userAgent);
+
+// Check if the browser is Chrome
+const isChrome = (/Chrome|CriOS/.test(navigator.userAgent)) && /Google Inc/.test(navigator.vendor) && !isEdge && !isBrave && !isOpera;
+
+// Check if the browser is Safari
+const isSafari = /Safari/.test(navigator.userAgent) && !isChromiumBased && /Apple Computer/.test(navigator.vendor);
+
+// Check if the operating system is macOS
+const isMac = /Macintosh|MacIntel|MacPPC|Mac68K/.test(navigator.platform);
+
+// Check if the device is a desktop (not mobile)
+const isDesktop = !/Android|iPhone|iPad|iPod/.test(navigator.userAgent);
diff --git a/scripts/clock.js b/scripts/clock.js
index 6117d577..a146e2a3 100644
--- a/scripts/clock.js
+++ b/scripts/clock.js
@@ -318,6 +318,7 @@ document.addEventListener("DOMContentLoaded", function () {
// ----------------------- End of clock display -------------------------
+// Save and load toggle state
document.addEventListener("DOMContentLoaded", function () {
const timeformatField = document.getElementById("timeformatField");
const hourcheckbox = document.getElementById("12hourcheckbox");
@@ -376,4 +377,4 @@ document.addEventListener("DOMContentLoaded", function () {
loadCheckboxState("hourcheckboxState", hourcheckbox);
loadActiveStatus("timeformatField", timeformatField);
loadActiveStatus("greetingField", greetingField);
-});
+});
\ No newline at end of file
diff --git a/scripts/custom-text.js b/scripts/custom-text.js
new file mode 100644
index 00000000..9ece7390
--- /dev/null
+++ b/scripts/custom-text.js
@@ -0,0 +1,58 @@
+/*
+ * Material You NewTab
+ * Copyright (c) 2023-2025 XengShi
+ * Licensed under the GNU General Public License v3.0 (GPL-3.0)
+ * You should have received a copy of the GNU General Public License along with this program.
+ * If not, see
.
+ */
+
+// Custom text
+document.addEventListener("DOMContentLoaded", () => {
+ const userTextDiv = document.getElementById("userText");
+ const userTextCheckbox = document.getElementById("userTextCheckbox");
+
+ // Load and apply the checkbox state
+ const isUserTextVisible = localStorage.getItem("userTextVisible") !== "false";
+ userTextCheckbox.checked = isUserTextVisible;
+ userTextDiv.style.display = isUserTextVisible ? "block" : "none";
+
+ // Toggle userText display based on checkbox state
+ userTextCheckbox.addEventListener("change", () => {
+ const isVisible = userTextCheckbox.checked;
+ userTextDiv.style.display = isVisible ? "block" : "none";
+ localStorage.setItem("userTextVisible", isVisible);
+ });
+
+ // Set the default language to English if no language is saved
+ const savedLang = localStorage.getItem("selectedLanguage") || "en";
+ applyLanguage(savedLang);
+
+ // Load the stored text if it exists
+ const storedValue = localStorage.getItem("userText");
+ if (storedValue) {
+ userTextDiv.textContent = storedValue;
+ } else {
+ // Fallback to the placeholder based on the selected language
+ const placeholder = userTextDiv.dataset.placeholder || translations["en"].userText; // Fallback to English
+ userTextDiv.textContent = placeholder;
+ }
+
+ // Handle input event
+ userTextDiv.addEventListener("input", function () {
+ localStorage.setItem("userText", userTextDiv.textContent);
+ });
+
+ // Remove placeholder text when the user starts editing
+ userTextDiv.addEventListener("focus", function () {
+ if (userTextDiv.textContent === userTextDiv.dataset.placeholder) {
+ userTextDiv.textContent = ""; // Clear the placeholder when focused
+ }
+ });
+
+ // Restore placeholder if the user leaves the div empty after editing
+ userTextDiv.addEventListener("blur", function () {
+ if (userTextDiv.textContent === "") {
+ userTextDiv.textContent = userTextDiv.dataset.placeholder; // Show the placeholder again if empty
+ }
+ });
+});
\ No newline at end of file
diff --git a/scripts/google-app-menu.js b/scripts/google-apps.js
similarity index 98%
rename from scripts/google-app-menu.js
rename to scripts/google-apps.js
index 86db9337..a34177e2 100644
--- a/scripts/google-app-menu.js
+++ b/scripts/google-apps.js
@@ -39,8 +39,7 @@ document.addEventListener("click", function (event) {
});
// ------------------------End of Google App Menu Setup-----------------------------------
-// Toggle
-
+// Save and load toggle state
document.addEventListener("DOMContentLoaded", function () {
const googleAppsCont = document.getElementById("googleAppsCont");
@@ -56,4 +55,4 @@ document.addEventListener("DOMContentLoaded", function () {
});
loadCheckboxState("googleAppsCheckboxState", googleAppsCheckbox);
loadDisplayStatus("googleAppsDisplayStatus", googleAppsCont);
-});
+});
\ No newline at end of file
diff --git a/scripts/languages.js b/scripts/languages.js
index 2be2fd7d..a8e2e409 100644
--- a/scripts/languages.js
+++ b/scripts/languages.js
@@ -9,7 +9,7 @@
// Translation data
const translations = {
en: en, // English
- pt: pt, // Portuguese-BR
+ pt: pt, // Portuguese-BR (Brazil)
zh: zh, // Chinese (Simplified)
hi: hi, // Hindi
hu: hu, // Hungarian
diff --git a/scripts/preload.js b/scripts/preload.js
index 200fcc64..d7f1030c 100644
--- a/scripts/preload.js
+++ b/scripts/preload.js
@@ -1,2 +1,10 @@
+/*
+ * Material You NewTab
+ * Copyright (c) 2023-2025 XengShi
+ * Licensed under the GNU General Public License v3.0 (GPL-3.0)
+ * You should have received a copy of the GNU General Public License along with this program.
+ * If not, see
.
+ */
+
// Set Loading Screen Color before Everything Loads
-document.documentElement.style.setProperty('--Loading-Screen-Color',localStorage.getItem('LoadingScreenColor') || "#bbd6fd");
+document.documentElement.style.setProperty('--Loading-Screen-Color', localStorage.getItem('LoadingScreenColor') || "#bbd6fd");
diff --git a/scripts/script.js b/scripts/script.js
index 5b3554e1..e455cc26 100644
--- a/scripts/script.js
+++ b/scripts/script.js
@@ -6,80 +6,31 @@
* If not, see
.
*/
-// Function to detect which browser is being used
-const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
-const isFirefox = typeof browser !== "undefined";
-// const isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
-const isEdge = /Edg/.test(navigator.userAgent);
-const isBrave = navigator.brave && navigator.brave.isBrave; // Detect Brave
-const isDesktop = !/Android|iPhone|iPad|iPod/.test(navigator.userAgent); // Check if the device is not mobile
-
-let proxyurl;
// TODO: Move all the CSS in a file called `theme/theme.css` (theme is the folder name)
// TODO: Move all the SVG icons in files called `svgs/icon-name.svg` (svgs is the folder name, it already exists)
-// TODO: Move all the to-do stuff in a file called `to-do.js` or `todo.js` or `todo-list.js`
-// TODO: Move all the weather stuff in a file called `weather.js`
// TODO: Move all the clock display stuff in a file called `clock-display.js` - can also be divided in two: `clock-default.js` and `clock-analog.js`
-// TODO: Move all the voice search stuff in a file called `voice-search.js`
// TODO: Move all the theme functions stuff in a file called `theme.js`
-// TODO: Move all the BG Image stuff in a file called `background-images.js`
// TODO: Move all the settings in a file called `settings.js`
// TODO: Move all the search suggestions stuff in a file called `search-suggestions.js`
// TODO: Move all the shortcut stuff in a file called `shortcut.js` (Difficult)
-// TODO: Move into file called `browser-utils.js` with isChrome, isFirefox, etc.
-// TODO: Move into file called `backup.js` or `backup-system.js`
// TODO: Move into file called `welcome-greeting.js`(?)
// TODO: Move into file called `animations.js`(?)
-// TODO: @Migua-RC, can you move all the proxy stuff in a file called `proxy.js`?
-window.addEventListener("DOMContentLoaded", async () => {
- // Cache DOM elements
- const userAPIInput = document.getElementById("userAPI");
- const userLocInput = document.getElementById("userLoc");
+let proxyurl;
+window.addEventListener("DOMContentLoaded", () => {
const userProxyInput = document.getElementById("userproxy");
- const saveAPIButton = document.getElementById("saveAPI");
- const saveLocButton = document.getElementById("saveLoc");
- const useGPSButton = document.getElementById("useGPS");
const saveProxyButton = document.getElementById("saveproxy");
-
- // Load saved data from localStorage
- const savedApiKey = localStorage.getItem("weatherApiKey");
- const savedLocation = localStorage.getItem("weatherLocation");
const savedProxy = localStorage.getItem("proxy");
- // Pre-fill input fields with saved data
- if (savedLocation) userLocInput.value = savedLocation;
- if (savedApiKey) userAPIInput.value = savedApiKey;
-
const defaultProxyURL = "https://mynt-proxy.rhythmcorehq.com"; //Default proxy url
if (savedProxy && savedProxy !== defaultProxyURL) {
userProxyInput.value = savedProxy;
}
- // Function to simulate button click on Enter key press
- function handleEnterPress(event, buttonId) {
- if (event.key === "Enter") {
- document.getElementById(buttonId).click();
- }
- }
-
- // Add event listeners for handling Enter key presses
- userAPIInput.addEventListener("keydown", (event) => handleEnterPress(event, "saveAPI"));
- userLocInput.addEventListener("keydown", (event) => handleEnterPress(event, "saveLoc"));
userProxyInput.addEventListener("keydown", (event) => handleEnterPress(event, "saveproxy"));
- // Save API key to localStorage
- saveAPIButton.addEventListener("click", () => {
- const apiKey = userAPIInput.value.trim();
- localStorage.setItem("weatherApiKey", apiKey);
- userAPIInput.value = "";
- location.reload();
- });
-
- const currentLanguage = getLanguageStatus("selectedLanguage") || "en";
-
// Save the proxy to localStorage
saveProxyButton.addEventListener("click", () => {
let proxyurl = userProxyInput.value.trim();
@@ -105,292 +56,11 @@ window.addEventListener("DOMContentLoaded", async () => {
location.reload();
});
- // Default Weather API key
- const weatherApiKeys = [
- "d36ce712613d4f21a6083436240910",
- "db0392b338114f208ee135134240312",
- "de5f7396db034fa2bf3140033240312",
- "c64591e716064800992140217240312",
- "9b3204c5201b4b4d8a2140330240312",
- "eb8a315c15214422b60140503240312",
- "cd148ebb1b784212b74140622240312",
- "7ae67e219af54df2840140801240312",
- "0a6bc8a404224c8d89953341241912",
- "f59e58d7735d4739ae953115241912"
- ];
- const defaultApiKey = weatherApiKeys[Math.floor(Math.random() * weatherApiKeys.length)];
-
- // Determine API key and proxy URL to use
- const apiKey = savedApiKey || defaultApiKey;
+ // Determine which proxy URL to use
proxyurl = savedProxy || defaultProxyURL;
-
- // Determine the location to use
- let currentUserLocation = savedLocation;
-
- // Flag indicating whether to use GPS
- const useGPS = JSON.parse(localStorage.getItem("useGPS"));
-
- // Fetch weather data based on a location
- async function fetchWeather(location) {
- const currentLanguage = getLanguageStatus("selectedLanguage") || "en";
- try {
- let parsedData = JSON.parse(localStorage.getItem("weatherParsedData"));
- const weatherParsedTime = parseInt(localStorage.getItem("weatherParsedTime"));
- const weatherParsedLocation = localStorage.getItem("weatherParsedLocation");
- const weatherParsedLang = localStorage.getItem("weatherParsedLang");
-
- const retentionTime = savedApiKey ? 120000 : 960000; // 2 min for user-entered API key, 16 min otherwise
-
- if (!parsedData || ((Date.now() - weatherParsedTime) > retentionTime) || (weatherParsedLocation !== currentUserLocation) || (weatherParsedLang !== currentLanguage)) {
- // Fetch weather data using Weather API
- let weatherApi = `https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${currentUserLocation}&aqi=no&lang=${currentLanguage}`;
- let data = await fetch(weatherApi);
- parsedData = await data.json();
- if (!parsedData.error) {
- // Extract only the necessary fields before saving
- const filteredData = {
- location: {
- name: parsedData.location.name,
- },
- current: {
- condition: {
- text: parsedData.current.condition.text,
- icon: parsedData.current.condition.icon,
- },
- temp_c: parsedData.current.temp_c,
- temp_f: parsedData.current.temp_f,
- humidity: parsedData.current.humidity,
- feelslike_c: parsedData.current.feelslike_c,
- feelslike_f: parsedData.current.feelslike_f,
- },
- };
-
- // Save filtered weather data to localStorage
- localStorage.setItem("weatherParsedData", JSON.stringify(filteredData));
- localStorage.setItem("weatherParsedTime", Date.now()); // Save time of last fetching
- localStorage.setItem("weatherParsedLocation", currentUserLocation); // Save user location
- localStorage.setItem("weatherParsedLang", currentLanguage); // Save language preference
- }
- UpdateWeather();
- } else {
- setTimeout(UpdateWeather, 25);
- }
-
- function UpdateWeather() {
- // Weather data
- const conditionText = parsedData.current.condition.text;
- const tempCelsius = Math.round(parsedData.current.temp_c);
- const tempFahrenheit = Math.round(parsedData.current.temp_f);
- const humidity = parsedData.current.humidity;
- const feelsLikeCelsius = parsedData.current.feelslike_c;
- const feelsLikeFahrenheit = parsedData.current.feelslike_f;
-
- // Update DOM elements with the weather data
- document.getElementById("conditionText").textContent = conditionText;
-
- // Localize and display temperature and humidity
- const localizedHumidity = localizeNumbers(humidity.toString(), currentLanguage);
- const localizedTempCelsius = localizeNumbers(tempCelsius.toString(), currentLanguage);
- const localizedFeelsLikeCelsius = localizeNumbers(feelsLikeCelsius.toString(), currentLanguage);
- const localizedTempFahrenheit = localizeNumbers(tempFahrenheit.toString(), currentLanguage);
- const localizedFeelsLikeFahrenheit = localizeNumbers(feelsLikeFahrenheit.toString(), currentLanguage);
-
- // Set humidity level
- const humidityLabel = translations[currentLanguage]?.humidityLevel || translations["en"].humidityLevel; // Fallback to English if translation is missing
- document.getElementById("humidityLevel").textContent = `${humidityLabel} ${localizedHumidity}%`;
-
- // Event Listener for the Fahrenheit toggle
- const fahrenheitCheckbox = document.getElementById("fahrenheitCheckbox");
- const updateTemperatureDisplay = () => {
- const tempElement = document.getElementById("temp");
- const feelsLikeElement = document.getElementById("feelsLike");
- const feelsLikeLabel = translations[currentLanguage]?.feelsLike || translations["en"].feelsLike;
-
- if (fahrenheitCheckbox.checked) {
- // Update temperature
- tempElement.textContent = localizedTempFahrenheit;
- const tempUnitF = document.createElement("span");
- tempUnitF.className = "tempUnit";
- tempUnitF.textContent = "°F";
- tempElement.appendChild(tempUnitF);
-
- // TODO: Change, it's hard-coded for cs language
- // Update feels like
- const feelsLikeFUnit = currentLanguage === 'cs' ? ' °F' : '°F';
- feelsLikeElement.textContent = `${feelsLikeLabel} ${localizedFeelsLikeFahrenheit}${feelsLikeFUnit}`;
- } else {
- // Update temperature
- tempElement.textContent = localizedTempCelsius;
- const tempUnitC = document.createElement("span");
- tempUnitC.className = "tempUnit";
- tempUnitC.textContent = "°C";
- tempElement.appendChild(tempUnitC);
-
- // TODO: Change, it's hard-coded for cs language
- // Update feels like
- const feelsLikeCUnit = currentLanguage === 'cs' ? ' °C' : '°C';
- feelsLikeElement.textContent = `${feelsLikeLabel} ${localizedFeelsLikeCelsius}${feelsLikeCUnit}`;
- }
- };
- updateTemperatureDisplay();
-
- // Setting weather Icon
- const newWIcon = parsedData.current.condition.icon;
- const weatherIcon = newWIcon.replace("//cdn", "https://cdn");
- document.getElementById("wIcon").src = weatherIcon;
-
- // TODO: Change, it's hard-coded for only few languages
- // Define minimum width for the slider based on the language
- const humidityMinWidth = {
- idn: "47%",
- hu: "48%",
- en: "42%", // Default for English and others
- };
- const slider = document.getElementById("slider");
- slider.style.minWidth = humidityMinWidth[currentLanguage] || humidityMinWidth["en"];
-
- // Set slider width based on humidity
- if (humidity > 40) {
- slider.style.width = `calc(${humidity}% - 60px)`;
- }
-
- // Update location
- var city = parsedData.location.name;
- // var city = "Thiruvananthapuram";
- var maxLength = 10;
- var limitedText = city.length > maxLength ? city.substring(0, maxLength) + "..." : city;
- document.getElementById("location").textContent = limitedText;
-
- }
- } catch (error) {
- console.error("Error fetching weather data:", error);
- }
- }
-
- // Function to fetch GPS-based location
- async function fetchGPSLocation() {
- try {
- const getLocationFromGPS = () => {
- return new Promise((resolve, reject) => {
- navigator.geolocation.getCurrentPosition(
- (position) => {
- resolve({
- latitude: position.coords.latitude,
- longitude: position.coords.longitude,
- });
- },
- (error) => reject(error),
- { timeout: 4000 }
- );
- });
- };
-
- const { latitude, longitude } = await getLocationFromGPS();
- return `${latitude},${longitude}`;
- } catch (error) {
- console.error("GPS Location retrieval failed: ", error);
- }
- }
-
- // Fetch location dynamically based on user preference
- await (async function initializeLocation() {
- try {
- if (useGPS) {
- try {
- // Use GPS for dynamic location
- currentUserLocation = await fetchGPSLocation();
- } catch {
- // Silent failover
- }
- }
-
- if (!currentUserLocation) {
- // Fallback to IP-based location if no manual input
- const geoLocation = "https://ipinfo.io/json/";
- const locationData = await fetch(geoLocation);
- const parsedLocation = await locationData.json();
- currentUserLocation = parsedLocation.loc;
- }
-
- // Fetch weather data
- fetchWeather(currentUserLocation);
- } catch (error) {
- console.error("Failed to determine location:", error);
- currentUserLocation = "auto:ip";
- fetchWeather(currentUserLocation);
- }
- })();
-
- // Handle "Use GPS" button click
- useGPSButton.addEventListener("click", () => {
- // Set the flag to use GPS dynamically and remove manual location
- localStorage.setItem("useGPS", true);
- localStorage.removeItem("weatherLocation");
- location.reload();
- });
-
- // Handle manual location input
- saveLocButton.addEventListener("click", () => {
- const userLocation = userLocInput.value.trim();
- localStorage.setItem("weatherLocation", userLocation);
- localStorage.setItem("useGPS", false);
- userLocInput.value = "";
- fetchWeather(userLocation);
- location.reload();
- });
});
-// ---------------------------end of weather stuff--------------------
-
-
-document.addEventListener("DOMContentLoaded", () => {
- const userTextDiv = document.getElementById("userText");
- const userTextCheckbox = document.getElementById("userTextCheckbox");
-
- // Load and apply the checkbox state
- const isUserTextVisible = localStorage.getItem("userTextVisible") !== "false";
- userTextCheckbox.checked = isUserTextVisible;
- userTextDiv.style.display = isUserTextVisible ? "block" : "none";
-
- // Toggle userText display based on checkbox state
- userTextCheckbox.addEventListener("change", () => {
- const isVisible = userTextCheckbox.checked;
- userTextDiv.style.display = isVisible ? "block" : "none";
- localStorage.setItem("userTextVisible", isVisible);
- });
-
- // Set the default language to English if no language is saved
- const savedLang = localStorage.getItem("selectedLanguage") || "en";
- applyLanguage(savedLang);
-
- // Load the stored text if it exists
- const storedValue = localStorage.getItem("userText");
- if (storedValue) {
- userTextDiv.textContent = storedValue;
- } else {
- // Fallback to the placeholder based on the selected language
- const placeholder = userTextDiv.dataset.placeholder || translations["en"].userText; // Fallback to English
- userTextDiv.textContent = placeholder;
- }
-
- // Handle input event
- userTextDiv.addEventListener("input", function () {
- localStorage.setItem("userText", userTextDiv.textContent);
- });
-
- // Remove placeholder text when the user starts editing
- userTextDiv.addEventListener("focus", function () {
- if (userTextDiv.textContent === userTextDiv.dataset.placeholder) {
- userTextDiv.textContent = ""; // Clear the placeholder when focused
- }
- });
- // Restore placeholder if the user leaves the div empty after editing
- userTextDiv.addEventListener("blur", function () {
- if (userTextDiv.textContent === "") {
- userTextDiv.textContent = userTextDiv.dataset.placeholder; // Show the placeholder again if empty
- }
- });
-});
+// --------------------------- Search Bar ------------------------------------
// Showing border or outline when you click on the searchbar
const searchbar = document.getElementById("searchbar");
@@ -1023,14 +693,11 @@ const applySelectedTheme = (colorValue) => {
// Function to update the extension icon based on browser
const updateExtensionIcon = (colorValue) => {
- if (typeof browser !== "undefined" && browser.browserAction) {
- // Firefox
+ if (isFirefox) {
browser.browserAction.setIcon({ path: iconPaths[colorValue] });
- } else if (typeof chrome !== "undefined" && chrome.action) {
- // Chromium-based: Chrome, Edge, Brave
+ } else if (isChromiumBased) {
chrome.action.setIcon({ path: iconPaths[colorValue] });
- } else if (typeof safari !== "undefined") {
- // Safari
+ } else if (isSafari) {
safari.extension.setToolbarIcon({ path: iconPaths[colorValue] });
}
};
@@ -1265,23 +932,13 @@ document.getElementById("searchQ").addEventListener("keydown", function (e) {
}
});
+// Check for different browsers and return the corresponding client parameter
function getClientParam() {
- const userAgent = navigator.userAgent.toLowerCase();
-
- // Check for different browsers and return the corresponding client parameter
- if (userAgent.includes("firefox")) {
- return "firefox";
- } else if (userAgent.includes("chrome") || userAgent.includes("crios")) {
- return "chrome";
- } else if (userAgent.includes("safari")) {
- return "safari";
- } else if (userAgent.includes("edge") || userAgent.includes("edg")) {
- return "firefox";
- } else if (userAgent.includes("opera") || userAgent.includes("opr")) {
- return "opera";
- } else {
- return "firefox"; // Default to Firefox client if the browser is not recognized
- }
+ if (isFirefox) return "firefox";
+ if (isChromiumBased && !isOpera) return "chrome";
+ if (isOpera) return "opera";
+ if (isSafari) return "safari";
+ return "firefox"; // Default to Firefox if the browser is not recognized
}
async function getAutocompleteSuggestions(query) {
@@ -1500,15 +1157,10 @@ document.addEventListener("DOMContentLoaded", function () {
const shortcuts = document.getElementById("shortcuts-section");
const shortcutsCheckbox = document.getElementById("shortcutsCheckbox");
- const proxybypassField = document.getElementById("proxybypassField");
- const proxyinputField = document.getElementById("proxyField");
- const useproxyCheckbox = document.getElementById("useproxyCheckbox");
const searchsuggestionscheckbox = document.getElementById("searchsuggestionscheckbox");
const shortcutEditField = document.getElementById("shortcutEditField");
const adaptiveIconField = document.getElementById("adaptiveIconField");
const adaptiveIconToggle = document.getElementById("adaptiveIconToggle");
- const hideWeatherCheckbox = document.getElementById("hideWeatherCheckbox");
- const fahrenheitCheckbox = document.getElementById("fahrenheitCheckbox");
const shortcutEditButton = document.getElementById("shortcutEditButton");
const backButton = document.getElementById("backButton");
const shortcutSettingsContainer = document.getElementById("shortcutList"); // shortcuts in settings
@@ -1518,6 +1170,10 @@ document.addEventListener("DOMContentLoaded", function () {
const iconStyle = document.getElementById("iconStyle");
const enableDarkModeCheckbox = document.getElementById("enableDarkModeCheckbox");
+ const proxybypassField = document.getElementById("proxybypassField");
+ const proxyinputField = document.getElementById("proxyField");
+ const useproxyCheckbox = document.getElementById("useproxyCheckbox");
+
// const flexMonitor = document.getElementById("flexMonitor"); // monitors whether shortcuts have flex-wrap flexed
// const defaultHeight = document.getElementById("defaultMonitor").clientHeight; // used to compare to previous element
@@ -2058,14 +1714,6 @@ document.addEventListener("DOMContentLoaded", function () {
saveCheckboxState("enableDarkModeCheckboxState", enableDarkModeCheckbox);
});
- hideWeatherCheckbox.addEventListener("change", function () {
- saveCheckboxState("hideWeatherCheckboxState", hideWeatherCheckbox);
- });
-
- fahrenheitCheckbox.addEventListener("change", function () {
- saveCheckboxState("fahrenheitCheckboxState", fahrenheitCheckbox);
- });
-
newShortcutButton.addEventListener("click", () => newShortcut());
resetShortcutsButton.addEventListener("click", () => resetShortcuts());
@@ -2129,9 +1777,7 @@ document.addEventListener("DOMContentLoaded", function () {
loadCheckboxState("useproxyCheckboxState", useproxyCheckbox);
loadActiveStatus("proxyinputField", proxyinputField);
loadActiveStatus("proxybypassField", proxybypassField);
- loadCheckboxState("hideWeatherCheckboxState", hideWeatherCheckbox);
loadDisplayStatus("shortcutsDisplayStatus", shortcuts);
- loadCheckboxState("fahrenheitCheckboxState", fahrenheitCheckbox);
loadCheckboxState("enableDarkModeCheckboxState", enableDarkModeCheckbox);
loadShortcuts();
});
diff --git a/scripts/voice-search.js b/scripts/voice-search.js
index 9c41c47d..85bf0f14 100644
--- a/scripts/voice-search.js
+++ b/scripts/voice-search.js
@@ -133,4 +133,4 @@ function initializeSpeechRecognition() {
if (!micIconCheckbox.checked) {
initializeSpeechRecognition();
}
-// -----------End of Voice Search------------
+// -----------End of Voice Search------------
\ No newline at end of file
diff --git a/scripts/wallpaper.js b/scripts/wallpaper.js
index d0834cc9..bad36d82 100644
--- a/scripts/wallpaper.js
+++ b/scripts/wallpaper.js
@@ -6,6 +6,9 @@
* If not, see
.
*/
+// Get the current language from localStorage
+const currentLanguage = localStorage.getItem("selectedLanguage") || "en";
+
// -------------------------- Wallpaper -----------------------------
const dbName = "ImageDB";
const storeName = "backgroundImages";
@@ -100,7 +103,6 @@ document.getElementById("imageUpload").addEventListener("change", function (even
// Fetch and apply random image as background
const RANDOM_IMAGE_URL = "https://picsum.photos/1920/1080";
-const currentLanguage = getLanguageStatus("selectedLanguage") || "en";
async function applyRandomImage(showConfirmation = true) {
if (showConfirmation && !confirm(translations[currentLanguage]?.confirmWallpaper || translations["en"].confirmWallpaper)) {
@@ -222,4 +224,4 @@ document.getElementById("randomImageTrigger").addEventListener("click", applyRan
// Start image check on page load
checkAndUpdateImage();
-// ------------------------ End of BG Image --------------------------
+// ------------------------ End of BG Image --------------------------
\ No newline at end of file
diff --git a/scripts/weather.js b/scripts/weather.js
new file mode 100644
index 00000000..2daf2f15
--- /dev/null
+++ b/scripts/weather.js
@@ -0,0 +1,293 @@
+/*
+ * Material You NewTab
+ * Copyright (c) 2023-2025 XengShi
+ * Licensed under the GNU General Public License v3.0 (GPL-3.0)
+ * You should have received a copy of the GNU General Public License along with this program.
+ * If not, see
.
+ */
+
+window.addEventListener("DOMContentLoaded", async () => {
+ // Cache DOM elements
+ const userAPIInput = document.getElementById("userAPI");
+ const userLocInput = document.getElementById("userLoc");
+ const saveAPIButton = document.getElementById("saveAPI");
+ const saveLocButton = document.getElementById("saveLoc");
+ const useGPSButton = document.getElementById("useGPS");
+
+ // Load saved data from localStorage
+ const savedApiKey = localStorage.getItem("weatherApiKey");
+ const savedLocation = localStorage.getItem("weatherLocation");
+
+ // Pre-fill input fields with saved data
+ if (savedLocation) userLocInput.value = savedLocation;
+ if (savedApiKey) userAPIInput.value = savedApiKey;
+
+ // Function to simulate button click on Enter key press
+ function handleEnterPress(event, buttonId) {
+ if (event.key === "Enter") {
+ document.getElementById(buttonId).click();
+ }
+ }
+
+ // Add event listeners for handling Enter key presses
+ userAPIInput.addEventListener("keydown", (event) => handleEnterPress(event, "saveAPI"));
+ userLocInput.addEventListener("keydown", (event) => handleEnterPress(event, "saveLoc"));
+
+ // Save API key to localStorage
+ saveAPIButton.addEventListener("click", () => {
+ const apiKey = userAPIInput.value.trim();
+ localStorage.setItem("weatherApiKey", apiKey);
+ userAPIInput.value = "";
+ location.reload();
+ });
+
+ // Default Weather API key
+ const weatherApiKeys = [
+ "d36ce712613d4f21a6083436240910",
+ "db0392b338114f208ee135134240312",
+ "de5f7396db034fa2bf3140033240312",
+ "c64591e716064800992140217240312",
+ "9b3204c5201b4b4d8a2140330240312",
+ "eb8a315c15214422b60140503240312",
+ "cd148ebb1b784212b74140622240312",
+ "7ae67e219af54df2840140801240312",
+ "0a6bc8a404224c8d89953341241912",
+ "f59e58d7735d4739ae953115241912"
+ ];
+ const defaultApiKey = weatherApiKeys[Math.floor(Math.random() * weatherApiKeys.length)];
+
+ // Determine which API key to use
+ const apiKey = savedApiKey || defaultApiKey;
+
+ // Determine the location to use
+ let currentUserLocation = savedLocation;
+
+ // Flag indicating whether to use GPS
+ const useGPS = JSON.parse(localStorage.getItem("useGPS"));
+
+ // Fetch weather data based on a location
+ async function fetchWeather() {
+ try {
+ let parsedData = JSON.parse(localStorage.getItem("weatherParsedData"));
+ const weatherParsedTime = parseInt(localStorage.getItem("weatherParsedTime"));
+ const weatherParsedLocation = localStorage.getItem("weatherParsedLocation");
+ const weatherParsedLang = localStorage.getItem("weatherParsedLang");
+
+ const retentionTime = savedApiKey ? 120000 : 960000; // 2 min for user-entered API key, 16 min otherwise
+
+ if (!parsedData || ((Date.now() - weatherParsedTime) > retentionTime) || (weatherParsedLocation !== currentUserLocation) || (weatherParsedLang !== currentLanguage)) {
+ // Fetch weather data using Weather API
+ let weatherApi = `https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${currentUserLocation}&aqi=no&lang=${currentLanguage}`;
+ let data = await fetch(weatherApi);
+ parsedData = await data.json();
+ if (!parsedData.error) {
+ // Extract only the necessary fields before saving
+ const filteredData = {
+ location: {
+ name: parsedData.location.name,
+ },
+ current: {
+ condition: {
+ text: parsedData.current.condition.text,
+ icon: parsedData.current.condition.icon,
+ },
+ temp_c: parsedData.current.temp_c,
+ temp_f: parsedData.current.temp_f,
+ humidity: parsedData.current.humidity,
+ feelslike_c: parsedData.current.feelslike_c,
+ feelslike_f: parsedData.current.feelslike_f,
+ },
+ };
+
+ // Save filtered weather data to localStorage
+ localStorage.setItem("weatherParsedData", JSON.stringify(filteredData));
+ localStorage.setItem("weatherParsedTime", Date.now()); // Save time of last fetching
+ localStorage.setItem("weatherParsedLocation", currentUserLocation); // Save user location
+ localStorage.setItem("weatherParsedLang", currentLanguage); // Save language preference
+ }
+ UpdateWeather();
+ } else {
+ setTimeout(UpdateWeather, 50);
+ }
+
+ function UpdateWeather() {
+ // Weather data
+ const conditionText = parsedData.current.condition.text;
+ const tempCelsius = Math.round(parsedData.current.temp_c);
+ const tempFahrenheit = Math.round(parsedData.current.temp_f);
+ const humidity = parsedData.current.humidity;
+ const feelsLikeCelsius = parsedData.current.feelslike_c;
+ const feelsLikeFahrenheit = parsedData.current.feelslike_f;
+
+ // Update DOM elements with the weather data
+ document.getElementById("conditionText").textContent = conditionText;
+
+ // Localize and display temperature and humidity
+ const localizedHumidity = localizeNumbers(humidity.toString(), currentLanguage);
+ const localizedTempCelsius = localizeNumbers(tempCelsius.toString(), currentLanguage);
+ const localizedFeelsLikeCelsius = localizeNumbers(feelsLikeCelsius.toString(), currentLanguage);
+ const localizedTempFahrenheit = localizeNumbers(tempFahrenheit.toString(), currentLanguage);
+ const localizedFeelsLikeFahrenheit = localizeNumbers(feelsLikeFahrenheit.toString(), currentLanguage);
+
+ // Set humidity level
+ const humidityLabel = translations[currentLanguage]?.humidityLevel || translations["en"].humidityLevel; // Fallback to English if translation is missing
+ document.getElementById("humidityLevel").textContent = `${humidityLabel} ${localizedHumidity}%`;
+
+ // Event Listener for the Fahrenheit toggle
+ const fahrenheitCheckbox = document.getElementById("fahrenheitCheckbox");
+ const updateTemperatureDisplay = () => {
+ const tempElement = document.getElementById("temp");
+ const feelsLikeElement = document.getElementById("feelsLike");
+ const feelsLikeLabel = translations[currentLanguage]?.feelsLike || translations["en"].feelsLike;
+
+ // List of languages where a space before °F or °C is required
+ const langWithSpaceBeforeDegree = ['cs'];
+
+ if (fahrenheitCheckbox.checked) {
+ // Update temperature
+ tempElement.textContent = localizedTempFahrenheit;
+ const tempUnitF = document.createElement("span");
+ tempUnitF.className = "tempUnit";
+ tempUnitF.textContent = "°F";
+ tempElement.appendChild(tempUnitF);
+
+ // Update feels like
+ const feelsLikeFUnit = langWithSpaceBeforeDegree.includes(currentLanguage) ? ' °F' : '°F';
+ feelsLikeElement.textContent = `${feelsLikeLabel} ${localizedFeelsLikeFahrenheit}${feelsLikeFUnit}`;
+ } else {
+ // Update temperature
+ tempElement.textContent = localizedTempCelsius;
+ const tempUnitC = document.createElement("span");
+ tempUnitC.className = "tempUnit";
+ tempUnitC.textContent = "°C";
+ tempElement.appendChild(tempUnitC);
+
+ // Update feels like
+ const feelsLikeCUnit = langWithSpaceBeforeDegree.includes(currentLanguage) ? ' °C' : '°C';
+ feelsLikeElement.textContent = `${feelsLikeLabel} ${localizedFeelsLikeCelsius}${feelsLikeCUnit}`;
+ }
+ };
+ updateTemperatureDisplay();
+
+ // Setting weather Icon
+ const newWIcon = parsedData.current.condition.icon;
+ const weatherIcon = newWIcon.replace("//cdn", "https://cdn");
+ document.getElementById("wIcon").src = weatherIcon;
+
+ // Define minimum width for the slider based on the language
+ const humidityMinWidth = {
+ idn: "47%",
+ hu: "48%",
+ en: "42%", // Default for English and others
+ };
+ const slider = document.getElementById("slider");
+ slider.style.minWidth = humidityMinWidth[currentLanguage] || humidityMinWidth["en"];
+
+ // Set slider width based on humidity
+ if (humidity > 40) {
+ slider.style.width = `calc(${humidity}% - 60px)`;
+ }
+
+ // Update location
+ var city = parsedData.location.name;
+ // var city = "Thiruvananthapuram";
+ var maxLength = 10;
+ var limitedText = city.length > maxLength ? city.substring(0, maxLength) + "..." : city;
+ document.getElementById("location").textContent = limitedText;
+
+ }
+ } catch (error) {
+ console.error("Error fetching weather data:", error);
+ }
+ }
+
+ // Function to fetch GPS-based location
+ async function fetchGPSLocation() {
+ try {
+ const getLocationFromGPS = () => {
+ return new Promise((resolve, reject) => {
+ navigator.geolocation.getCurrentPosition(
+ (position) => {
+ resolve({
+ latitude: position.coords.latitude,
+ longitude: position.coords.longitude,
+ });
+ },
+ (error) => reject(error),
+ { timeout: 4000 }
+ );
+ });
+ };
+
+ const { latitude, longitude } = await getLocationFromGPS();
+ return `${latitude},${longitude}`;
+ } catch (error) {
+ console.error("GPS Location retrieval failed: ", error);
+ }
+ }
+
+ // Fetch location dynamically based on user preference
+ await (async function initializeLocation() {
+ try {
+ if (useGPS) {
+ try {
+ // Use GPS for dynamic location
+ currentUserLocation = await fetchGPSLocation();
+ } catch {
+ console.log("Failed to use GPS for location:", error);
+ }
+ }
+
+ if (!currentUserLocation) {
+ // Fallback to IP-based location if no manual input
+ const geoLocation = "https://ipinfo.io/json/";
+ const locationData = await fetch(geoLocation);
+ const parsedLocation = await locationData.json();
+ currentUserLocation = parsedLocation.loc;
+ }
+
+ // Fetch weather data
+ fetchWeather(currentUserLocation);
+ } catch (error) {
+ console.error("Failed to determine location:", error);
+ currentUserLocation = "auto:ip";
+ fetchWeather(currentUserLocation);
+ }
+ })();
+
+ // Handle "Use GPS" button click
+ useGPSButton.addEventListener("click", () => {
+ // Set the flag to use GPS dynamically and remove manual location
+ localStorage.setItem("useGPS", true);
+ localStorage.removeItem("weatherLocation");
+ location.reload();
+ });
+
+ // Handle manual location input
+ saveLocButton.addEventListener("click", () => {
+ const userLocation = userLocInput.value.trim();
+ localStorage.setItem("weatherLocation", userLocation);
+ localStorage.setItem("useGPS", false);
+ userLocInput.value = "";
+ fetchWeather(userLocation);
+ location.reload();
+ });
+});
+
+
+// Save and load toggle state
+document.addEventListener("DOMContentLoaded", function () {
+ const hideWeatherCheckbox = document.getElementById("hideWeatherCheckbox");
+ const fahrenheitCheckbox = document.getElementById("fahrenheitCheckbox");
+
+ hideWeatherCheckbox.addEventListener("change", function () {
+ saveCheckboxState("hideWeatherCheckboxState", hideWeatherCheckbox);
+ });
+
+ fahrenheitCheckbox.addEventListener("change", function () {
+ saveCheckboxState("fahrenheitCheckboxState", fahrenheitCheckbox);
+ });
+
+ loadCheckboxState("hideWeatherCheckboxState", hideWeatherCheckbox);
+ loadCheckboxState("fahrenheitCheckboxState", fahrenheitCheckbox);
+});
\ No newline at end of file