Skip to content

Commit f167c33

Browse files
committed
feat(main): added sharp to cache thumbnails
Previously there was an issue of slow loading. Now, the thumbnails are cached, so that problem is gone
1 parent 18942c2 commit f167c33

5 files changed

Lines changed: 593 additions & 59 deletions

File tree

main.js

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@ const {
77
} = require("electron");
88
const path = require("path");
99
const fs = require("fs/promises");
10+
const fsSync = require("fs"); // Use sync version for setup
1011
const { exec } = require("child_process");
1112
const os = require("os");
13+
const sharp = require("sharp"); // Import the sharp library
1214

13-
// Make mainWindow a global variable so we can access it everywhere.
1415
let mainWindow = null;
1516

16-
// Promisified exec for running osascript commands
17+
// --- App Setup: Create Thumbnail Cache Directory ---
18+
const cacheDir = path.join(app.getPath("userData"), "thumbnails");
19+
if (!fsSync.existsSync(cacheDir)) {
20+
fsSync.mkdirSync(cacheDir, { recursive: true });
21+
}
22+
1723
const run = (cmd) =>
1824
new Promise((resolve, reject) => {
1925
exec(cmd, { maxBuffer: 1024 * 1024 * 10 }, (error, stdout, stderr) => {
@@ -23,14 +29,12 @@ const run = (cmd) =>
2329
});
2430
});
2531

26-
// A dedicated function to set the wallpaper using AppleScript
2732
async function setWallpaper(imagePath) {
2833
const script = `osascript -e 'tell application "System Events" to tell every desktop to set picture to (POSIX file "${imagePath}")'`;
2934
return run(script);
3035
}
3136

3237
function createWindow() {
33-
// **FIX:** Get the display that currently has focus.
3438
const currentDisplay = screen.getDisplayNearestPoint(
3539
screen.getCursorScreenPoint()
3640
);
@@ -42,7 +46,6 @@ function createWindow() {
4246
mainWindow = new BrowserWindow({
4347
width: windowWidth,
4448
height: windowHeight,
45-
// Center the window on the currently active screen
4649
x: Math.round(currentDisplay.bounds.x + (width - windowWidth) / 2),
4750
y: Math.round(currentDisplay.bounds.y + (height - windowHeight) / 2),
4851
webPreferences: {
@@ -52,8 +55,8 @@ function createWindow() {
5255
},
5356
frame: false,
5457
transparent: true,
55-
show: false, // Start hidden and show when ready
56-
vibrancy: "ultra-dark", // This provides the blurred transparency
58+
show: false,
59+
vibrancy: "ultra-dark",
5760
alwaysOnTop: true,
5861
level: "floating",
5962
visibleOnAllWorkspaces: true,
@@ -67,22 +70,17 @@ function createWindow() {
6770

6871
mainWindow.loadFile(path.join(__dirname, "dist/index.html"));
6972

70-
// Show the window gracefully when the content is ready.
7173
mainWindow.once("ready-to-show", () => {
7274
mainWindow.show();
7375
});
7476

75-
// When the window is closed, set its variable to null.
76-
// This is crucial for our open/close logic.
7777
mainWindow.on("closed", () => {
7878
mainWindow = null;
7979
});
8080
}
8181

8282
app.whenReady().then(() => {
83-
// Set up the global shortcut to toggle the window's visibility.
8483
globalShortcut.register("CommandOrControl+Shift+P", () => {
85-
// If the window exists, close it. Otherwise, create it.
8684
if (mainWindow) {
8785
mainWindow.close();
8886
} else {
@@ -91,11 +89,7 @@ app.whenReady().then(() => {
9189
});
9290
});
9391

94-
// **FIX:** Prevent the app from quitting when all windows are closed.
95-
// This allows the background process to persist.
9692
app.on("window-all-closed", () => {
97-
// On macOS, it's common for applications to stay active until the user
98-
// explicitly quits. This line prevents the default quit behavior.
9993
if (process.platform !== "darwin") {
10094
app.quit();
10195
}
@@ -114,9 +108,7 @@ ipcMain.handle("get-wallpapers", async () => {
114108
return files.filter((file) => /\.(jpg|jpeg|png|heic|webp)$/i.test(file));
115109
} catch (error) {
116110
console.error(`Error reading wallpaper directory: ${wallpaperDir}`, error);
117-
throw new Error(
118-
`Could not read wallpapers from: ~/wallpapers. Please make sure this folder exists and isn't empty.`
119-
);
111+
throw new Error(`Could not read wallpapers from: ~/wallpapers.`);
120112
}
121113
});
122114

@@ -142,24 +134,47 @@ ipcMain.handle("get-current-wallpaper", async () => {
142134
}
143135
});
144136

145-
ipcMain.handle("get-image-as-base64", async (event, fileIdentifier) => {
146-
let filePath;
147-
if (path.isAbsolute(fileIdentifier)) {
148-
filePath = fileIdentifier;
149-
} else {
150-
filePath = path.join(os.homedir(), "wallpapers", fileIdentifier);
151-
}
152-
137+
// This handler is now only for the full-resolution initial background
138+
ipcMain.handle("get-image-as-base64", async (event, fullPath) => {
153139
try {
154-
const data = await fs.readFile(filePath);
140+
const data = await fs.readFile(fullPath);
155141
return data.toString("base64");
156142
} catch (error) {
157-
console.error(`Failed to read file: ${filePath}`, error);
143+
console.error(`Failed to read file: ${fullPath}`, error);
158144
throw error;
159145
}
160146
});
161147

162-
// This handler now closes the window instead of just hiding it.
148+
// **NEW**: Handler to get a cached thumbnail, creating it if it doesn't exist.
149+
ipcMain.handle("get-thumbnail", async (event, imageName) => {
150+
const sourcePath = path.join(os.homedir(), "wallpapers", imageName);
151+
const thumbPath = path.join(cacheDir, imageName);
152+
153+
try {
154+
// Try to read from cache first
155+
await fs.access(thumbPath);
156+
const data = await fs.readFile(thumbPath);
157+
return data.toString("base64");
158+
} catch {
159+
// If cache miss, generate a new thumbnail
160+
try {
161+
const buffer = await sharp(sourcePath)
162+
.resize({ width: 400 }) // Resize to 400px wide, maintaining aspect ratio
163+
.toBuffer();
164+
165+
// Save the new thumbnail to the cache for next time
166+
await fs.writeFile(thumbPath, buffer);
167+
return buffer.toString("base64");
168+
} catch (generationError) {
169+
console.error(
170+
`Failed to generate thumbnail for ${imageName}:`,
171+
generationError
172+
);
173+
throw generationError;
174+
}
175+
}
176+
});
177+
163178
ipcMain.on("hide-window", () => {
164179
if (mainWindow) {
165180
mainWindow.close();

0 commit comments

Comments
 (0)