The following problem needs to be solved: when you drag shortcuts to the container, they are duplicated and their image is not displayed.
const { ipcRenderer, shell } = require('electron');
const path = require('path');
const fs = require('fs');
async function addDropdown(containerId) {
const container = document.getElementById(containerId);
const dropdown = document.createElement('div');
dropdown.className = 'dropdown';
dropdown.setAttribute('data-container-id', containerId);
const button = document.createElement('button');
button.textContent = `+`;
button.className = 'addApp';
dropdown.appendChild(button);
container.appendChild(dropdown);
button.addEventListener('click', async (event) => {
let paths = await ipcRenderer.invoke('select-file');
if (paths.length > 0) {
await createShortcut(paths[0], 'file', null, containerId);
}
});
container.addEventListener('dragover', (event) => {
event.preventDefault();
container.classList.add('drag-over');
});
container.addEventListener('dragleave', () => {
container.classList.remove('drag-over');
});
container.addEventListener('drop', async (event) => {
event.preventDefault();
container.classList.remove('drag-over');
const files = Array.from(event.dataTransfer.files);
if (files.length > 0) {
for (const file of files) {
await createShortcut(file.path, 'file', null, container.id);
}
}
});
}
async function saveShortcuts() {
const shortcuts = [];
document.querySelectorAll('.container').forEach(container => {
const containerId = container.id;
container.querySelectorAll('.shortcut').forEach(el => {
shortcuts.push({
path: el.getAttribute('data-path'),
type: el.getAttribute('data-type'),
name: el.getAttribute('data-name'),
containerId: containerId
});
});
});
await ipcRenderer.invoke('save-shortcuts', shortcuts);
}
async function loadShortcuts() {
const shortcuts = await ipcRenderer.invoke('load-shortcuts');
document.querySelectorAll('.container').forEach(container => {
container.innerHTML = ''; // Очистка контейнерів перед завантаженням
});
const existingPaths = new Set();
shortcuts.forEach(shortcut => {
if (!existingPaths.has(shortcut.path)) {
createShortcut(shortcut.path, shortcut.type, shortcut.name, shortcut.containerId);
existingPaths.add(shortcut.path);
}
});
document.querySelectorAll('.container').forEach(container => {
addDropdown(container.id);
});
}
async function createShortcut(filePath, type = 'file', displayName = null, containerId) {
const container = document.getElementById(containerId);
const existingShortcut = document.querySelector(`.shortcut[data-path="${filePath}"]`);
if (existingShortcut) {
console.warn(`Shortcut for ${filePath} already exists.`);
return;
}
const shortcut = document.createElement('div');
shortcut.className = 'shortcut';
shortcut.setAttribute('data-path', filePath);
shortcut.setAttribute('data-type', type);
let name = displayName || (type === 'web' ? filePath : path.basename(filePath, path.extname(filePath)));
shortcut.setAttribute('data-name', name);
console.log(`Creating shortcut for: ${filePath} with type: ${type}`);
if (type !== 'web') {
try {
const iconDataURL = await ipcRenderer.invoke('get-file-icon', filePath);
console.log(`Received icon data URL for: ${filePath} - ${iconDataURL}`);
if (iconDataURL) {
const iconImg = document.createElement('img');
iconImg.src = iconDataURL;
shortcut.appendChild(iconImg);
} else {
console.warn(`Icon data URL not available for: ${filePath}`);
const iconImg = document.createElement('img');
iconImg.src = 'path/to/default-icon.png'; // Шлях до альтернативної іконки
shortcut.appendChild(iconImg);
}
} catch (error) {
console.error(`Error getting icon for: ${filePath}`, error);
const iconImg = document.createElement('img');
iconImg.src = 'path/to/default-icon.png'; // Шлях до альтернативної іконки
shortcut.appendChild(iconImg);
}
} else {
const iconImg = document.createElement('img');
iconImg.src = 'path/to/web-icon.png'; // Змініть шлях на реальний шлях до іконки веб-лінку
shortcut.appendChild(iconImg);
}
const shortcutName = document.createElement('div');
shortcutName.className = 'shortcut-name';
shortcutName.textContent = name;
shortcut.appendChild(shortcutName);
shortcut.addEventListener('click', () => {
if (type === 'web') {
shell.openExternal(filePath);
} else {
shell.openPath(filePath);
}
});
shortcut.addEventListener('contextmenu', (event) => {
event.preventDefault();
const menu = document.createElement('div');
menu.className = 'context-menu';
menu.style.position = 'absolute';
menu.style.left = `${event.pageX}px`;
menu.style.top = `${event.pageY}px`;
menu.style.backgroundColor = '#fff';
menu.style.border = '1px solid #ddd';
menu.style.padding = '5px';
menu.style.zIndex = 1000;
const removeItem = document.createElement('div');
removeItem.textContent = 'Remove';
removeItem.style.cursor = 'pointer';
removeItem.addEventListener('click', () => {
shortcut.remove();
menu.remove();
saveShortcuts();
});
menu.appendChild(removeItem);
document.body.appendChild(menu);
document.addEventListener('click', () => menu.remove(), { once: true });
});
container.insertBefore(shortcut, container.querySelector('.dropdown'));
await saveShortcuts();
}
document.querySelectorAll('.container').forEach(container => {
addDropdown(container.id);
});
document.addEventListener('DOMContentLoaded', () => {
loadShortcuts();
});
// Додаємо функціонал пошуку з Google
const googleSearchInput = document.getElementById('googleSearchInput');
googleSearchInput.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
const query = googleSearchInput.value;
if (query) {
const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}`;
shell.openExternal(searchUrl);
}
}
});
// Додаємо функціонал локального пошуку на ПК
const localSearchInput = document.getElementById('localSearchInput');
localSearchInput.addEventListener('keypress', async (event) => {
if (event.key === 'Enter') {
const query = localSearchInput.value;
if (query) {
try {
const result = await ipcRenderer.invoke('select-directory');
if (result && result.length > 0) {
const directoryPath = result[0];
searchLocally(directoryPath, query);
}
} catch (error) {
console.error('Error selecting directory:', error);
}
}
}
});
document.getElementById('transparency').addEventListener('input', (event) => {
const transparency = event.target.value;
const backgroundLayer = document.getElementById('backgroundLayer');
backgroundLayer.style.background = `rgba(255, 255, 255, ${transparency})`;
});
async function searchLocally(directoryPath, query) {
console.log(`Searching locally in directory: ${directoryPath} for: ${query}`);
try {
const files = await recursiveSearch(directoryPath, query);
console.log('Found files:', files);
// Process found files as needed
} catch (error) {
console.error('Error searching locally:', error);
}
}
async function openExplorerWithSearch(directory, query) {
try {
const result = await dialog.showOpenDialog(mainWindow, {
defaultPath: directory,
properties: ['openDirectory', 'multiSelections']
});
if (!result.canceled && result.filePaths.length > 0) {
const selectedPaths = result.filePaths;
const foundFiles = [];
for (const selectedPath of selectedPaths) {
const files = await recursiveSearch(selectedPath, query);
foundFiles.push(...files);
}
console.log('Found files:', foundFiles);
// Handle found files as needed
} else {
console.log('Dialog was canceled or no paths selected.');
}
} catch (error) {
console.error('Error opening explorer with search:', error);
}
}
async function recursiveSearch(directory, query) {
const entries = await fs.promises.readdir(directory, { withFileTypes: true });
let foundFiles = [];
for (const entry of entries) {
const fullPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
const nestedFiles = await recursiveSearch(fullPath, query);
foundFiles = foundFiles.concat(nestedFiles);
} else if (entry.isFile()) {
if (entry.name.toLowerCase().includes(query.toLowerCase())) {
foundFiles.push(fullPath);
}
}
}
return foundFiles;
}
Here is the terminal log:
Getting icon for file: C:UsersPublicDesktopOracle VM VirtualBox.lnk
Getting icon for file: C:UsersPublicDesktopOracle VM VirtualBox.lnk
Icon data URL: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB4UlEQVRYhe2WSy8DURTH/72aaT3STpUYFmJlbSFBPBKJxEYkFj4AibXx1pGmRFp2KrHyOcRWgpBYsZWgiY3Qqk
qKauceCw01GZnpmIlN/5ubnHPPOb9z7p0H8M9y6RmXF2ZvXIy1WUlInCfe8nwsHo+fWwYILc3T2nrMSn1Ewgq8Xs9TOpMdNAPBLFUx0MTklBjw1x7IstzxLwBSc4tpCEcAyoFwDMAshKMAZiDcdhcURRGRsKLrEoSqAwABRwFm5
hZ/9UXCiqi1OX4ERqoAVAAqABUA9919ZgsuyAQARCAARISHdBZEBCKA8LmCCLXVHvjqPPYBEEiWGvymA65vk7YCME5UVgDn3LbiAOBWNQmf3znG9++Ref8EK+Q5upsE7Aw1FgHKAzYE0Cb0CQw9zV5kcir2LrNIZVXkXgpffi3w
X8X0OlrtEiEJDMnnPGqII/eqfvnsngDT62jzNI3oUQqLXQEMt1ajkCsFcHgCGyePiB4msdwdQKi3Hj6Bwe/5fl2odt+B0gnEjlOIHqag9AWh9AcBAFsjEp7evvc4OoHEYx6h3nqsDAR/bBK9Dk6gtKPdUckwwPbHsNyOOOe//fUaijhPaG2us4urOGNV09pvAVFxLbEXAbb7O9tlSwQ6+gBeLeaCGOTlRQAAAABJRU5ErkJggg==
Icon data URL: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB4UlEQVRYhe2WSy8DURTH/72aaT3STpUYFmJlbSFBPBKJxEYkFj4AibXx1pGmRFp2KrHyOcRWgpBYsZWgiY3Qqk
qKauceCw01GZnpmIlN/5ubnHPPOb9z7p0H8M9y6RmXF2ZvXIy1WUlInCfe8nwsHo+fWwYILc3T2nrMSn1Ewgq8Xs9TOpMdNAPBLFUx0MTklBjw1x7IstzxLwBSc4tpCEcAyoFwDMAshKMAZiDcdhcURRGRsKLrEoSqAwABRwFm5
hZ/9UXCiqi1OX4ERqoAVAAqABUA9919ZgsuyAQARCAARISHdBZEBCKA8LmCCLXVHvjqPPYBEEiWGvymA65vk7YCME5UVgDn3LbiAOBWNQmf3znG9++Ref8EK+Q5upsE7Aw1FgHKAzYE0Cb0CQw9zV5kcir2LrNIZVXkXgpffi3w
X8X0OlrtEiEJDMnnPGqII/eqfvnsngDT62jzNI3oUQqLXQEMt1ajkCsFcHgCGyePiB4msdwdQKi3Hj6Bwe/5fl2odt+B0gnEjlOIHqag9AWh9AcBAFsjEp7evvc4OoHEYx6h3nqsDAR/bBK9Dk6gtKPdUckwwPbHsNyOOOe//fUaijhPaG2us4urOGNV09pvAVFxLbEXAbb7O9tlSwQ6+gBeLeaCGOTlRQAAAABJRU5ErkJggg==