mirror of
https://github.com/DevJSTAR/JSTAR-Tab.git
synced 2025-04-18 17:35:26 +00:00
Add files via upload
This commit is contained in:
parent
383896b69d
commit
c8b5e54495
115
index.html
Normal file
115
index.html
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>New JSTAR Tab</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<div id="greeting"></div>
|
||||||
|
|
||||||
|
<!-- Search Bar -->
|
||||||
|
<div id="search-bar">
|
||||||
|
<input type="text" id="search" placeholder="Search Brave...">
|
||||||
|
<button id="search-btn"><i class="fas fa-search"></i></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Settings Icon at Bottom Right -->
|
||||||
|
<button id="settings-btn" class="settings-icon">
|
||||||
|
<i class="fas fa-cog"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Shortcuts Grid -->
|
||||||
|
<div id="shortcuts" class="grid-container"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Settings Modal -->
|
||||||
|
<div id="settings-modal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<h2>Settings</h2>
|
||||||
|
<div class="section">
|
||||||
|
<h3>Theme</h3>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" id="theme-switch">
|
||||||
|
<span class="slider round"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<h3>Shortcuts</h3>
|
||||||
|
<div class="button-group">
|
||||||
|
<button id="add-shortcut" class="icon-btn" data-tooltip="Add Shortcut">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
<button id="import-shortcuts" class="icon-btn" data-tooltip="Import Shortcuts">
|
||||||
|
<i class="fas fa-file-import"></i>
|
||||||
|
</button>
|
||||||
|
<button id="export-shortcuts" class="icon-btn" data-tooltip="Export Shortcuts">
|
||||||
|
<i class="fas fa-file-export"></i>
|
||||||
|
</button>
|
||||||
|
<button id="reset-shortcuts" class="icon-btn" data-tooltip="Reset Shortcuts">
|
||||||
|
<i class="fas fa-undo"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<h3>Tools</h3>
|
||||||
|
<div class="button-group">
|
||||||
|
<button id="open-calculator-btn" class="icon-btn" data-tooltip="Calculator">
|
||||||
|
<i class="fas fa-calculator"></i>
|
||||||
|
</button>
|
||||||
|
<button id="open-currency-converter" class="icon-btn" data-tooltip="Currency Converter">
|
||||||
|
<i class="fas fa-coins"></i>
|
||||||
|
</button>
|
||||||
|
<button id="anonymize-btn" class="icon-btn" data-tooltip="Anonymize">
|
||||||
|
<i class="fas fa-user-secret"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Calculator Modal -->
|
||||||
|
<div id="calculator-modal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close-btn" id="close-calculator-btn">×</span>
|
||||||
|
<div id="calculator">
|
||||||
|
<div id="calculator-display">0</div>
|
||||||
|
<div id="calculator-buttons">
|
||||||
|
<button data-value="7">7</button>
|
||||||
|
<button data-value="8">8</button>
|
||||||
|
<button data-value="9">9</button>
|
||||||
|
<button data-value="/">/</button>
|
||||||
|
<button data-value="4">4</button>
|
||||||
|
<button data-value="5">5</button>
|
||||||
|
<button data-value="6">6</button>
|
||||||
|
<button data-value="*">*</button>
|
||||||
|
<button data-value="1">1</button>
|
||||||
|
<button data-value="2">2</button>
|
||||||
|
<button data-value="3">3</button>
|
||||||
|
<button data-value="-">-</button>
|
||||||
|
<button data-value="0">0</button>
|
||||||
|
<button data-value="C">C</button>
|
||||||
|
<button data-value="=">=</button>
|
||||||
|
<button data-value="+">+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="context-menu">
|
||||||
|
<div id="edit-shortcut" class="context-menu-item" onclick="editShortcut()">
|
||||||
|
<i class="fas fa-pencil-alt"></i> Edit
|
||||||
|
</div>
|
||||||
|
<div id="delete-shortcut" class="context-menu-item delete" onclick="deleteShortcut()">
|
||||||
|
<i class="fas fa-trash-alt"></i> Delete
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
manifest.json
Normal file
13
manifest.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "JSTAR Tab",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "A sleek modern custom new tab with search, shortcuts, and settings.",
|
||||||
|
"chrome_url_overrides": {
|
||||||
|
"newtab": "index.html"
|
||||||
|
},
|
||||||
|
"permissions": ["storage"],
|
||||||
|
"action": {
|
||||||
|
"default_title": "New JSTAR Tab"
|
||||||
|
}
|
||||||
|
}
|
380
script.js
Normal file
380
script.js
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
applyTheme();
|
||||||
|
updateGreeting();
|
||||||
|
loadAnonymizationState(); // Load anonymization state on page load
|
||||||
|
loadShortcuts(); // Load shortcuts on page load
|
||||||
|
|
||||||
|
document.getElementById('theme-switch').addEventListener('change', toggleTheme);
|
||||||
|
document.getElementById('settings-btn').addEventListener('click', toggleSettings);
|
||||||
|
document.getElementById('search-btn').addEventListener('click', searchBrave);
|
||||||
|
document.getElementById('search').addEventListener('keypress', function(event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
searchBrave();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add event listener for the anonymize button
|
||||||
|
const anonymizeBtn = document.getElementById('anonymize-btn');
|
||||||
|
anonymizeBtn.addEventListener('click', toggleAnonymize);
|
||||||
|
|
||||||
|
const modal = document.getElementById('settings-modal');
|
||||||
|
modal.addEventListener('click', closeOnClickOutside);
|
||||||
|
document.querySelector('.close-btn').addEventListener('click', closeSettings);
|
||||||
|
|
||||||
|
// Add shortcut button listeners
|
||||||
|
document.getElementById('add-shortcut').addEventListener('click', addShortcut);
|
||||||
|
document.getElementById('import-shortcuts').addEventListener('click', importShortcuts);
|
||||||
|
document.getElementById('export-shortcuts').addEventListener('click', exportShortcuts);
|
||||||
|
document.getElementById('reset-shortcuts').addEventListener('click', resetShortcuts);
|
||||||
|
|
||||||
|
// Custom context menu for shortcuts
|
||||||
|
const contextMenu = document.createElement('div');
|
||||||
|
contextMenu.id = 'context-menu';
|
||||||
|
contextMenu.innerHTML = `
|
||||||
|
<button id="edit-shortcut">Edit</button>
|
||||||
|
<button id="delete-shortcut">Delete</button>
|
||||||
|
`;
|
||||||
|
contextMenu.style.display = 'none';
|
||||||
|
document.body.appendChild(contextMenu);
|
||||||
|
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
const contextMenu = document.getElementById('context-menu');
|
||||||
|
// Hide context menu if the click is outside of it
|
||||||
|
if (event.target !== contextMenu && !contextMenu.contains(event.target)) {
|
||||||
|
contextMenu.style.display = 'none'; // Hide menu on click outside
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close context menu on Escape key
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
contextMenu.style.display = 'none'; // Hide context menu
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Detect Shift + A to toggle anonymization, but ensure no other keys are pressed
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'A' && event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
||||||
|
toggleAnonymize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Detect Shift + T to toggle theme
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'T' && event.shiftKey) {
|
||||||
|
toggleThemeShortcut(); // Toggle theme when Shift + T is pressed
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Detect Shift + S to toggle settings menu
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'S' && event.shiftKey) {
|
||||||
|
toggleSettings(); // Open or close settings modal
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let isAnonymized = false; // Track the anonymization state
|
||||||
|
let currentShortcutIndex = -1; // To keep track of the current shortcut for editing or deleting
|
||||||
|
|
||||||
|
function updateGreeting() {
|
||||||
|
const greeting = document.getElementById('greeting');
|
||||||
|
const date = new Date();
|
||||||
|
const hours = date.getUTCHours() + 5; // Adjust for timezone
|
||||||
|
|
||||||
|
let message = `Good ${getTimeOfDay(hours)}, ${isAnonymized ? 'JSTAR' : 'Junaid'}!`;
|
||||||
|
greeting.textContent = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimeOfDay(hours) {
|
||||||
|
if (hours >= 5 && hours < 12) {
|
||||||
|
return "Morning";
|
||||||
|
} else if (hours >= 12 && hours < 17) {
|
||||||
|
return "Afternoon";
|
||||||
|
} else if (hours >= 17 && hours < 22) {
|
||||||
|
return "Evening";
|
||||||
|
} else {
|
||||||
|
return "Night";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchBrave() {
|
||||||
|
const query = document.getElementById('search').value.trim();
|
||||||
|
if (query) {
|
||||||
|
window.location.href = `https://search.brave.com/search?q=${encodeURIComponent(query)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
const isDark = document.getElementById('theme-switch').checked;
|
||||||
|
document.body.classList.toggle('dark-theme', isDark);
|
||||||
|
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
||||||
|
|
||||||
|
const modalContent = document.querySelector('.modal-content');
|
||||||
|
modalContent.style.backgroundColor = isDark ? '#1a1a1a' : 'white';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcut to toggle theme
|
||||||
|
function toggleThemeShortcut() {
|
||||||
|
const themeSwitch = document.getElementById('theme-switch');
|
||||||
|
themeSwitch.checked = !themeSwitch.checked;
|
||||||
|
toggleTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTheme() {
|
||||||
|
const savedTheme = localStorage.getItem('theme') || 'light';
|
||||||
|
document.body.classList.toggle('dark-theme', savedTheme === 'dark');
|
||||||
|
document.getElementById('theme-switch').checked = savedTheme === 'dark';
|
||||||
|
document.querySelector('.modal-content').style.backgroundColor = savedTheme === 'dark' ? '#1a1a1a' : 'white';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the anonymization state from localStorage
|
||||||
|
function loadAnonymizationState() {
|
||||||
|
const savedAnonymization = localStorage.getItem('anonymization');
|
||||||
|
isAnonymized = savedAnonymization === 'true'; // Convert string to boolean
|
||||||
|
|
||||||
|
updateAnonymizeButton();
|
||||||
|
updateGreeting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load shortcuts from localStorage and display them
|
||||||
|
function loadShortcuts() {
|
||||||
|
const shortcutsContainer = document.getElementById('shortcuts');
|
||||||
|
shortcutsContainer.innerHTML = ''; // Clear existing shortcuts
|
||||||
|
|
||||||
|
const savedShortcuts = JSON.parse(localStorage.getItem('shortcuts')) || [];
|
||||||
|
savedShortcuts.forEach((shortcut, index) => {
|
||||||
|
const shortcutButton = document.createElement('div');
|
||||||
|
shortcutButton.className = 'shortcut';
|
||||||
|
|
||||||
|
const favicon = document.createElement('img');
|
||||||
|
favicon.src = `https://www.google.com/s2/favicons?domain=${new URL(shortcut.url).hostname}`; // Fetch favicon
|
||||||
|
const shortcutName = document.createElement('span');
|
||||||
|
shortcutName.textContent = shortcut.name.length > 10 ? shortcut.name.slice(0, 10) + '...' : shortcut.name; // Truncate long names
|
||||||
|
|
||||||
|
// Add a click event to open the shortcut link
|
||||||
|
shortcutButton.addEventListener('click', (event) => {
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
window.open(shortcut.url, '_blank'); // Open in a new tab if Ctrl is held
|
||||||
|
} else {
|
||||||
|
window.location.href = shortcut.url; // Open in the same tab
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add context menu for right-click
|
||||||
|
shortcutButton.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
showContextMenu(event.clientX, event.clientY, index);
|
||||||
|
});
|
||||||
|
|
||||||
|
shortcutButton.appendChild(favicon);
|
||||||
|
shortcutButton.appendChild(shortcutName);
|
||||||
|
shortcutsContainer.appendChild(shortcutButton);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show custom context menu
|
||||||
|
function showContextMenu(x, y, index) {
|
||||||
|
currentShortcutIndex = index; // Store the index of the current shortcut
|
||||||
|
const contextMenu = document.getElementById('context-menu');
|
||||||
|
contextMenu.style.display = 'block';
|
||||||
|
contextMenu.style.left = `${x}px`;
|
||||||
|
contextMenu.style.top = `${y}px`;
|
||||||
|
|
||||||
|
// Clear previous event handlers (important to prevent multiple listeners)
|
||||||
|
const editButton = contextMenu.querySelector('#edit-shortcut');
|
||||||
|
const deleteButton = contextMenu.querySelector('#delete-shortcut');
|
||||||
|
|
||||||
|
if (editButton) {
|
||||||
|
editButton.onclick = () => {
|
||||||
|
editShortcut(); // Trigger edit shortcut
|
||||||
|
contextMenu.style.display = 'none'; // Hide context menu
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const editBtn = document.createElement('button');
|
||||||
|
editBtn.id = 'edit-shortcut';
|
||||||
|
editBtn.textContent = 'Edit';
|
||||||
|
editBtn.onclick = () => {
|
||||||
|
editShortcut(); // Trigger edit shortcut
|
||||||
|
contextMenu.style.display = 'none'; // Hide context menu
|
||||||
|
};
|
||||||
|
contextMenu.appendChild(editBtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteButton) {
|
||||||
|
deleteButton.onclick = () => {
|
||||||
|
deleteShortcut(); // Trigger delete shortcut
|
||||||
|
contextMenu.style.display = 'none'; // Hide context menu
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const deleteBtn = document.createElement('button');
|
||||||
|
deleteBtn.id = 'delete-shortcut';
|
||||||
|
deleteBtn.textContent = 'Delete';
|
||||||
|
deleteBtn.onclick = () => {
|
||||||
|
deleteShortcut(); // Trigger delete shortcut
|
||||||
|
contextMenu.style.display = 'none'; // Hide context menu
|
||||||
|
};
|
||||||
|
contextMenu.appendChild(deleteBtn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle anonymization state
|
||||||
|
function toggleAnonymize() {
|
||||||
|
isAnonymized = !isAnonymized; // Toggle the anonymized state
|
||||||
|
updateAnonymizeButton();
|
||||||
|
updateGreeting();
|
||||||
|
|
||||||
|
// Save the current anonymization state to localStorage
|
||||||
|
localStorage.setItem('anonymization', isAnonymized);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAnonymizeButton() {
|
||||||
|
const anonymizeBtn = document.getElementById('anonymize-btn');
|
||||||
|
if (isAnonymized) {
|
||||||
|
anonymizeBtn.classList.add('active');
|
||||||
|
anonymizeBtn.setAttribute('data-tooltip', 'Unanonymize');
|
||||||
|
anonymizeBtn.innerHTML = '<i class="fas fa-user"></i>'; // Change icon to un-anonymize
|
||||||
|
} else {
|
||||||
|
anonymizeBtn.classList.remove('active');
|
||||||
|
anonymizeBtn.setAttribute('data-tooltip', 'Anonymize');
|
||||||
|
anonymizeBtn.innerHTML = '<i class="fas fa-user-secret"></i>'; // Change icon to anonymize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSettings() {
|
||||||
|
const modal = document.getElementById('settings-modal');
|
||||||
|
modal.classList.contains('active') ? closeSettings() : openSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSettings() {
|
||||||
|
const modal = document.getElementById('settings-modal');
|
||||||
|
modal.style.display = 'flex';
|
||||||
|
setTimeout(() => {
|
||||||
|
modal.classList.add('active');
|
||||||
|
modal.querySelector('.modal-content').classList.add('active');
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSettings() {
|
||||||
|
const modal = document.getElementById('settings-modal');
|
||||||
|
modal.querySelector('.modal-content').classList.remove('active');
|
||||||
|
modal.classList.remove('active');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeOnClickOutside(event) {
|
||||||
|
const modal = document.getElementById('settings-modal');
|
||||||
|
if (event.target === modal) {
|
||||||
|
closeSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate if the URL is valid
|
||||||
|
function isValidURL(url) {
|
||||||
|
try {
|
||||||
|
new URL(url);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new shortcut
|
||||||
|
function addShortcut() {
|
||||||
|
const name = prompt("Enter the shortcut name:");
|
||||||
|
const url = prompt("Enter the shortcut URL:");
|
||||||
|
|
||||||
|
if (!name || !url || !isValidURL(url)) {
|
||||||
|
alert("Invalid input. Please provide a valid name and URL.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shortcuts = JSON.parse(localStorage.getItem('shortcuts')) || [];
|
||||||
|
shortcuts.push({ name, url });
|
||||||
|
localStorage.setItem('shortcuts', JSON.stringify(shortcuts));
|
||||||
|
loadShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit the current shortcut
|
||||||
|
function editShortcut() {
|
||||||
|
if (currentShortcutIndex < 0) return;
|
||||||
|
|
||||||
|
const shortcuts = JSON.parse(localStorage.getItem('shortcuts'));
|
||||||
|
const currentShortcut = shortcuts[currentShortcutIndex];
|
||||||
|
|
||||||
|
const newName = prompt("Edit the shortcut name:", currentShortcut.name);
|
||||||
|
const newUrl = prompt("Edit the shortcut URL:", currentShortcut.url);
|
||||||
|
|
||||||
|
if (!newName || !newUrl || !isValidURL(newUrl)) {
|
||||||
|
alert("Invalid input. Please provide a valid name and URL.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shortcuts[currentShortcutIndex] = { name: newName, url: newUrl };
|
||||||
|
localStorage.setItem('shortcuts', JSON.stringify(shortcuts));
|
||||||
|
loadShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the current shortcut
|
||||||
|
function deleteShortcut() {
|
||||||
|
if (currentShortcutIndex < 0) return;
|
||||||
|
|
||||||
|
const shortcuts = JSON.parse(localStorage.getItem('shortcuts'));
|
||||||
|
shortcuts.splice(currentShortcutIndex, 1);
|
||||||
|
localStorage.setItem('shortcuts', JSON.stringify(shortcuts));
|
||||||
|
loadShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import shortcuts from a JSON file
|
||||||
|
function importShortcuts() {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = '.json';
|
||||||
|
|
||||||
|
input.onchange = (event) => {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = (e) => {
|
||||||
|
try {
|
||||||
|
const shortcuts = JSON.parse(e.target.result);
|
||||||
|
if (Array.isArray(shortcuts)) {
|
||||||
|
localStorage.setItem('shortcuts', JSON.stringify(shortcuts));
|
||||||
|
loadShortcuts();
|
||||||
|
} else {
|
||||||
|
alert("Invalid file format. Please upload a valid JSON file.");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert("Error parsing JSON. Please ensure the file is valid.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export shortcuts to a JSON file
|
||||||
|
function exportShortcuts() {
|
||||||
|
const shortcuts = JSON.parse(localStorage.getItem('shortcuts')) || [];
|
||||||
|
const dataStr = JSON.stringify(shortcuts, null, 2);
|
||||||
|
const blob = new Blob([dataStr], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = 'shortcuts.json';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset shortcuts to the default state
|
||||||
|
function resetShortcuts() {
|
||||||
|
if (confirm("Are you sure you want to reset the shortcuts? This action cannot be undone.")) {
|
||||||
|
localStorage.removeItem('shortcuts');
|
||||||
|
loadShortcuts();
|
||||||
|
}
|
||||||
|
}
|
399
style.css
Normal file
399
style.css
Normal file
|
@ -0,0 +1,399 @@
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
background-color: #ffffff; /* Light mode background */
|
||||||
|
color: #000000; /* Light mode text color */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#greeting {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background-color: #f0f0f0; /* Light mode input background */
|
||||||
|
border-radius: 30px;
|
||||||
|
padding: 5px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-bar input {
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 400px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
outline: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #000000; /* Light mode input text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-bar button {
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #000; /* Light mode icon color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #e0e0e0; /* Light mode button background */
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut img {
|
||||||
|
width: 24px; /* Size of favicon */
|
||||||
|
height: 24px; /* Size of favicon */
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut:hover {
|
||||||
|
background-color: #ccc; /* Light mode button hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-icon {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #000000; /* Light mode settings icon color */
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.8); /* Modal background color */
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: #1A1A1A; /* Dark mode modal background */
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
width: 400px;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
top: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #000000; /* Close button color in dark mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 60px;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #ccc; /* Light mode toggle background */
|
||||||
|
transition: 0.4s;
|
||||||
|
border-radius: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
left: 4px;
|
||||||
|
bottom: 4px;
|
||||||
|
background-color: white; /* Light mode toggle circle color */
|
||||||
|
transition: 0.4s;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider {
|
||||||
|
background-color: rgb(100, 100, 100); /* Light mode toggle active color */
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider:before {
|
||||||
|
background-color: rgb(133, 133, 133);
|
||||||
|
transform: translateX(26px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme {
|
||||||
|
background-color: #000000; /* Dark mode background */
|
||||||
|
color: #ffffff; /* Dark mode text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme #search-bar {
|
||||||
|
background-color: #111111; /* Dark mode input background */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme #search-bar input {
|
||||||
|
color: #ffffff; /* Dark mode input text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .settings-icon {
|
||||||
|
color: #ffffff; /* Dark mode settings icon color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .modal-content {
|
||||||
|
background-color: #1A1A1A; /* Dark mode modal background */
|
||||||
|
color: #ffffff; /* Dark mode modal text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .close-btn {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme #search-bar button {
|
||||||
|
color: #ffffff; /* Dark mode button text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme #search-bar button:hover {
|
||||||
|
color: #ffffff; /* Dark mode button hover color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #000000; /* Light mode heading color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme h2, body.dark-theme h3 {
|
||||||
|
color: #ffffff; /* Dark mode heading color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 15px;
|
||||||
|
border: none;
|
||||||
|
background-color: #e0e0e0; /* Light mode button background */
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #000000; /* Light mode button text color */
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn:hover {
|
||||||
|
background-color: #ccc; /* Light mode button hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .icon-btn {
|
||||||
|
background-color: #333333; /* Dark mode button background */
|
||||||
|
color: #ffffff; /* Dark mode button text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .icon-btn:hover {
|
||||||
|
background-color: #444444; /* Dark mode button hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn[data-tooltip]::after {
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% + 6px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease-in;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn[data-tooltip]:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.active {
|
||||||
|
display: flex;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content.hide {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.hide {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional styles for the shortcut buttons */
|
||||||
|
.shortcut {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #e0e0e0; /* Light mode button background */
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut img {
|
||||||
|
width: 24px; /* Size of favicon */
|
||||||
|
height: 24px; /* Size of favicon */
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut:hover {
|
||||||
|
background-color: #ccc; /* Light mode button hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode styles for shortcuts */
|
||||||
|
body.dark-theme .shortcut {
|
||||||
|
background-color: #444; /* Dark mode button background */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .shortcut:hover {
|
||||||
|
background-color: #555; /* Dark mode button hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom context menu styles */
|
||||||
|
#context-menu {
|
||||||
|
position: absolute;
|
||||||
|
background-color: #fff; /* Light mode menu background */
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
|
||||||
|
z-index: 1000;
|
||||||
|
padding: 0; /* Remove padding from menu itself */
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
width: 150px; /* Set width for the context menu */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px; /* Increased padding for larger button size */
|
||||||
|
color: #000; /* Default text color */
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid #fff; /* Divider between items */
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
width: 100%; /* Full width buttons */
|
||||||
|
text-align: left; /* Align text to the left */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item i {
|
||||||
|
margin-right: 8px; /* Space between icon and text */
|
||||||
|
font-size: 16px; /* Icon size */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item:last-child {
|
||||||
|
border-bottom: none; /* No divider after last item */
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item:hover {
|
||||||
|
background-color: #f0f0f0; /* Menu item hover background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item.delete {
|
||||||
|
color: #000; /* Set delete button text color to red */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-menu-item.delete:hover {
|
||||||
|
color: red; /* Set delete button text color to red */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme #context-menu {
|
||||||
|
background-color: #222; /* Dark mode menu background */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .context-menu-item {
|
||||||
|
color: #ffffff; /* Dark mode menu text color */
|
||||||
|
border-bottom: 1px solid #222222;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .context-menu-item.delete {
|
||||||
|
color: #fff; /* Dark mode delete text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .context-menu-item.delete:hover {
|
||||||
|
color: red; /* Dark mode delete text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme .context-menu-item:hover {
|
||||||
|
background-color: #333; /* Dark mode item hover background */
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user