|
1 | | -import { Menu, MenuItem, clipboard } from "electron"; |
| 1 | +import { Menu, MenuItem, clipboard, nativeImage, dialog } from "electron"; |
2 | 2 | import WindowManager from "./window-manager.js"; |
| 3 | +import path from "path"; |
3 | 4 |
|
4 | 5 | const isMac = process.platform === "darwin"; |
5 | 6 |
|
@@ -157,6 +158,81 @@ export function attachContextMenus(browserWindow, windowManager) { |
157 | 158 | }) |
158 | 159 | ); |
159 | 160 |
|
| 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 | + |
160 | 236 | // Link handling |
161 | 237 | if (params.linkURL) { |
162 | 238 | menu.append( |
|
0 commit comments