Skip to content

Commit b367d90

Browse files
committed
feat:add copy and download options for image
1 parent 1dc88aa commit b367d90

File tree

1 file changed

+77
-1
lines changed

1 file changed

+77
-1
lines changed

src/context-menu.js

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { Menu, MenuItem, clipboard } from "electron";
1+
import { Menu, MenuItem, clipboard, nativeImage, dialog } from "electron";
22
import WindowManager from "./window-manager.js";
3+
import path from "path";
34

45
const isMac = process.platform === "darwin";
56

@@ -157,6 +158,81 @@ export function attachContextMenus(browserWindow, windowManager) {
157158
})
158159
);
159160

161+
// Image handling features (copy, copy address, save as)
162+
if (params.mediaType === "image" && params.srcURL) {
163+
menu.append(
164+
new MenuItem({
165+
label: "Copy Image",
166+
click: async () => {
167+
try {
168+
// Use copyImageAt for best quality
169+
const img = webContents.copyImageAt(params.x, params.y);
170+
if (img && !img.isEmpty()) {
171+
clipboard.writeImage(img);
172+
}
173+
} catch (e) {
174+
console.error("Copy Image failed:", e);
175+
}
176+
},
177+
})
178+
);
179+
menu.append(
180+
new MenuItem({
181+
label: "Copy Image Address",
182+
click: () => clipboard.writeText(params.srcURL),
183+
})
184+
);
185+
menu.append(
186+
new MenuItem({
187+
label: "Save Image As...",
188+
click: async () => {
189+
try {
190+
// Extract filename from URL
191+
const urlPath = new URL(params.srcURL).pathname;
192+
const defaultName = path.basename(urlPath) || "image.png";
193+
194+
// Show save dialog
195+
const result = await dialog.showSaveDialog(browserWindow, {
196+
title: "Save Image",
197+
defaultPath: defaultName,
198+
filters: [
199+
{ name: "Images", extensions: ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg"] },
200+
{ name: "All Files", extensions: ["*"] },
201+
],
202+
});
203+
204+
if (!result.canceled && result.filePath) {
205+
// Download the image using webContents session
206+
webContents.session.downloadURL(params.srcURL);
207+
208+
// Listen for the download and move it to the chosen location
209+
webContents.session.once("will-download", (event, item) => {
210+
item.setSavePath(result.filePath);
211+
212+
item.on("updated", (event, state) => {
213+
if (state === "interrupted") {
214+
console.error("Download interrupted");
215+
}
216+
});
217+
218+
item.once("done", (event, state) => {
219+
if (state === "completed") {
220+
console.log("Image saved successfully to:", result.filePath);
221+
} else {
222+
console.error("Download failed:", state);
223+
}
224+
});
225+
});
226+
}
227+
} catch (e) {
228+
console.error("Save Image failed:", e);
229+
}
230+
},
231+
})
232+
);
233+
menu.append(new MenuItem({ type: "separator" }));
234+
}
235+
160236
// Link handling
161237
if (params.linkURL) {
162238
menu.append(

0 commit comments

Comments
 (0)