diff --git a/package-lock.json b/package-lock.json index 0870a25..4ec43b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6718,6 +6718,11 @@ } } }, + "node-lame": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-lame/-/node-lame-1.3.1.tgz", + "integrity": "sha512-MNt0XIpclhrU1rmGvD1az21UFeKhW4Ly7n4eogUQcIkGbRLrIArAqYRSe2p1fHJJKSRDqBymfr4j8xmCtzsWYQ==" + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -9953,11 +9958,6 @@ } } }, - "wavefile": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/wavefile/-/wavefile-11.0.0.tgz", - "integrity": "sha512-/OBiAALgWU24IG7sC84cDO/KfFuvajWc5Uec0oV2zrpOOZZDgGdOwHwgEzOrwh8jkubBk7PtZfQBIcI1OaE5Ng==" - }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index 536b8c6..ae17425 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "dependencies": { "electron-squirrel-startup": "^1.0.0", "music-metadata": "^7.8.3", - "node-id3": "^0.2.2", - "wavefile": "^11.0.0" + "node-id3": "^0.2.2" } } diff --git a/src/assets/context-menu.css b/src/assets/context-menu.css new file mode 100644 index 0000000..915537f --- /dev/null +++ b/src/assets/context-menu.css @@ -0,0 +1,53 @@ +#context-menu { + position: fixed; + + background: white; + box-shadow: 0 0 1rem rgba(0, 0, 0, 0.05); + + display: none; + flex-direction: column; + border-radius: 0.25rem; + overflow: hidden; +} +#context-menu button { + width: 20rem; + height: 4rem; + padding: 0 2rem; + /* padding-right: 6rem; */ + + color: #571be5; + + text-align: left; + font-weight: 700; +} + +#context-menu button:hover { + background: #571be5; + color: white; +} + +#context-menu button:active { + background: #7f48ff; + color: white; +} + +#context-menu button::after { + content: ""; + + width: calc(100% - 4rem); + height: 1px; + position: absolute; + bottom: 0px; + left: 0; + right: 0; + margin: 0 auto; + + background: #571be5; + opacity: 0.1; + + display: block; +} + +#context-menu button:last-child:after { + display: none; +} diff --git a/src/files.css b/src/assets/files.css similarity index 82% rename from src/files.css rename to src/assets/files.css index 5ec6ebb..afdf98d 100644 --- a/src/files.css +++ b/src/assets/files.css @@ -81,31 +81,6 @@ button#window-control-close:hover { cursor: pointer; } -/* #files-section .row.file-entry .name { - user-select: text; - cursor: text; - pointer-events: all; -} */ - -#files-section .row.file-entry .name .copy-name { - height: 1.5rem; - padding: 0 1rem; - position: absolute; - right: 0; - - background: #571be5; - color: white; - opacity: 0; - - border-radius: 0.75rem; - - pointer-events: all; -} - -#files-section .row.file-entry .name .copy-name:active { - background: #7f48ff; -} - #files-section .row.file-entry div { font-weight: 700; user-select: text; @@ -115,10 +90,6 @@ button#window-control-close:hover { color: #571be588; } -#files-section .row.file-entry:hover .name .copy-name { - opacity: 1; -} - #files-section .row.file-entry.selected { background: #571be508; } diff --git a/src/assets/icons/windows-close.svg b/src/assets/icons/windows-close.svg deleted file mode 100644 index dbaa39b..0000000 --- a/src/assets/icons/windows-close.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/assets/icons/windows-collapse.svg b/src/assets/icons/windows-collapse.svg deleted file mode 100644 index ebaa77e..0000000 --- a/src/assets/icons/windows-collapse.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/assets/icons/windows-maximize.svg b/src/assets/icons/windows-maximize.svg deleted file mode 100644 index aa0e478..0000000 --- a/src/assets/icons/windows-maximize.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/main.css b/src/assets/style.css similarity index 94% rename from src/main.css rename to src/assets/style.css index b895e85..a762db6 100644 --- a/src/main.css +++ b/src/assets/style.css @@ -62,8 +62,8 @@ button.begging:hover { transition: 100ms; } -/* body */ -body { +/* main-layout */ +#main-layout { height: 100vh; display: grid; grid-template-columns: 24em auto; @@ -122,11 +122,6 @@ h2 { /* height: 0.25rem; */ } -::-webkit-scrollbar-track, -::-webkit-scrollbar-thumb { - /* border-radius: 5px; */ -} - ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.05); } diff --git a/src/tags.css b/src/assets/tags.css similarity index 100% rename from src/tags.css rename to src/assets/tags.css diff --git a/src/common/IpcEvents.ts b/src/common/IpcEvents.ts index e3ed3d0..674d1ec 100644 --- a/src/common/IpcEvents.ts +++ b/src/common/IpcEvents.ts @@ -7,6 +7,7 @@ export const IpcEvents = { rendererAlbumArtReceived: "album-art-received", rendererFileReceived: "file-received", rendererRequestLoadMeta: "load-meta", + rendererRequestRemoveAlbumArt: "remove-album-art", rendererRequestSaveMeta: "save-meta", rendererWindowClose: "window-close", rendererWindowCollaps: "window-collapse", diff --git a/src/main.html b/src/main.html index 4b0ee08..c62dca8 100644 --- a/src/main.html +++ b/src/main.html @@ -9,73 +9,76 @@ - -
-
-

Tags

- -
-
-
- - - -
+
+ +
+
+

Tags

+ +
+
+
+ + + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- Album art -
-
-
-
+
+ Album art +
+
+
+
- -
-
-

Files

-
Beta build
-
- - - -
-
+ +
+
+

Files

+
Beta build
+
+ + + +
+
-
-
-
-
Name
-
Type
-
Location
- +
+
+
+
Name
+
Type
+
Location
+ +
-
-
-
+ +
+ +
diff --git a/src/main.ts b/src/main.ts index 0e6a684..24484e5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,7 @@ import { app, BrowserWindow, ipcMain } from "electron"; // eslint-disable-next-line import/no-unresolved import { IpcMainEvent } from "electron/main"; import path from "path"; +// import fs from "fs"; import * as mm from "music-metadata"; import * as NodeID3 from "node-id3"; import { IpcEvents } from "./common/IpcEvents"; @@ -128,7 +129,7 @@ ipcMain.on(IpcEvents.rendererRequestLoadMeta, (event: IpcMainEvent, filePath: st } as NodeID3Image; } else currentMeta.image = getNewFrontCover(); - event.sender.send(IpcEvents.mainRequestRenderMeta, currentMeta); + event.sender.send(IpcEvents.mainRequestRenderMeta, currentMeta, value); }) .catch((error: Error) => { event.sender.send(IpcEvents.mainRequestRenderError, error); @@ -171,7 +172,7 @@ ipcMain.on(IpcEvents.rendererRequestSaveMeta, (event: IpcMainEvent, meta) => { event.sender.send(IpcEvents.mainRequestRenderError, result as Error); } } else if (currentFileFormat == SupportedFormat.WAV) { - event.sender.send(IpcEvents.mainRequestRenderError, new Error("Saving WAV is not supperted yet")); + event.sender.send(IpcEvents.mainRequestRenderError, new Error("Saving WAVs is not supported and there currently is no plan to add support for that. Please encode your music in MP3")); } }); @@ -188,7 +189,12 @@ ipcMain.on(IpcEvents.rendererAlbumArtReceived, (event: IpcMainEvent, name: strin frontCover.imageBuffer = Buffer.from(buffer); currentMeta.image = frontCover; - event.sender.send(IpcEvents.mainRequestRenderAlbumArt, frontCover.mime, frontCover.imageBuffer); + event.sender.send(IpcEvents.mainRequestRenderAlbumArt, frontCover); +}); + +ipcMain.on(IpcEvents.rendererRequestRemoveAlbumArt, (event: IpcMainEvent) => { + const frontCover = getNewFrontCover(); + event.sender.send(IpcEvents.mainRequestRenderAlbumArt, frontCover); }); function getNewMeta(): NodeID3.Tags { diff --git a/src/renderer.ts b/src/renderer.ts index 196172b..5b8fa89 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -1,6 +1,7 @@ -import "./main.css"; -import "./tags.css"; -import "./files.css"; +import "./assets/style.css"; +import "./assets/tags.css"; +import "./assets/files.css"; +import "./assets/context-menu.css"; import { clipboard, ipcRenderer, IpcRendererEvent } from "electron"; import $ from "jquery"; import * as NodeID3 from "node-id3"; @@ -8,6 +9,7 @@ import { IpcEvents } from "./common/IpcEvents"; import { NodeID3Image } from "./common/NodeID3Image"; const ui = { + document: $(document), windowControls: { close: $("#window-control-close"), toggleSize: $("#window-control-toggle-size"), @@ -28,6 +30,7 @@ const ui = { albumArt: $("#album-art-input"), }, fileList: $("#file-list"), + contextMenu: $("#context-menu"), }; // @@ -55,17 +58,14 @@ ui.selctions.files.on("drop", (event) => { // Window controls ui.windowControls.collapse.on("click", (e) => { e.preventDefault(); - e.stopPropagation(); ipcRenderer.send(IpcEvents.rendererWindowCollaps); }); ui.windowControls.toggleSize.on("click", (e) => { e.preventDefault(); - e.stopPropagation(); ipcRenderer.send(IpcEvents.rendererWindowToggleSize); }); ui.windowControls.close.on("click", (e) => { e.preventDefault(); - e.stopPropagation(); ipcRenderer.send(IpcEvents.rendererWindowClose); }); @@ -74,7 +74,6 @@ ui.windowControls.close.on("click", (e) => { // Tag UI ui.saveButton.on("click", (e) => { e.preventDefault(); - e.stopPropagation(); ipcRenderer.send(IpcEvents.rendererRequestSaveMeta, { title: ui.tagFileds.trackTitle.val(), @@ -86,10 +85,34 @@ ui.saveButton.on("click", (e) => { }); }); +ui.tagFileds.albumArt.on("mouseup", (event: JQuery.MouseUpEvent) => { + if (event.which == 3) { + event.stopPropagation(); + openContextMenu(event.pageX, event.pageY, [ + { + name: "Paste", + click() { + const availableFormats = clipboard.availableFormats(); + if (availableFormats.includes("image/png") || availableFormats.includes("image/jpeg")) { + ipcRenderer.send(IpcEvents.rendererAlbumArtReceived, ".png", clipboard.readImage().toPNG()); + } + }, + }, + { + name: "Remove", + click() { + ipcRenderer.send(IpcEvents.rendererRequestRemoveAlbumArt); + }, + }, + ]); + } +}); + ui.tagFileds.albumArt.on("dragenter dragover", (event: JQuery.DragEvent) => { event.preventDefault(); event.stopPropagation(); }); + ui.tagFileds.albumArt.on("drop", (event: JQuery.DropEvent) => { event.preventDefault(); event.stopPropagation(); @@ -99,18 +122,10 @@ ui.tagFileds.albumArt.on("drop", (event: JQuery.DropEvent) => { ipcRenderer.send(IpcEvents.rendererAlbumArtReceived, file.name, buffer); }); }); -ui.tagFileds.albumArt.on("mouseup", (event: JQuery.MouseUpEvent) => { - if (event.which == 3) { - event.stopPropagation(); - const availableFormats = clipboard.availableFormats(); - if (availableFormats.includes("image/png") || availableFormats.includes("image/jpeg")) { - ipcRenderer.send(IpcEvents.rendererAlbumArtReceived, ".png", clipboard.readImage().toPNG()); - } - } -}); +ipcRenderer.on(IpcEvents.mainRequestRenderMeta, (event: IpcRendererEvent, meta: NodeID3.Tags, mmTags) => { + console.log(mmTags); -ipcRenderer.on(IpcEvents.mainRequestRenderMeta, (event: IpcRendererEvent, meta: NodeID3.Tags) => { ui.tagFileds.trackTitle.val(meta.title); ui.tagFileds.trackArtist.val(meta.artist); ui.tagFileds.trackNumber.val(meta.trackNumber); @@ -124,10 +139,14 @@ ipcRenderer.on(IpcEvents.mainRequestRenderMeta, (event: IpcRendererEvent, meta: setAlbumArt(`data:${albumCover.mime};base64,${base64String}`); } else ui.tagFileds.albumArt.html(""); }); -ipcRenderer.on(IpcEvents.mainRequestRenderAlbumArt, (event: IpcRendererEvent, mime: string, buffer: Buffer) => { - const base64String = _arrayBufferToBase64(buffer); - setAlbumArt(`data:${mime};base64,${base64String}`); + +ipcRenderer.on(IpcEvents.mainRequestRenderAlbumArt, (event: IpcRendererEvent, albumArt: NodeID3Image) => { + if (albumArt.imageBuffer) { + const base64String = _arrayBufferToBase64(albumArt.imageBuffer); + setAlbumArt(`data:${albumArt.mime};base64,${base64String}`); + } else ui.tagFileds.albumArt.html(""); }); + function setAlbumArt(src: string) { ui.tagFileds.albumArt.html(`Album art`); } @@ -138,7 +157,7 @@ function setAlbumArt(src: string) { ipcRenderer.on(IpcEvents.mainFileApproved, (event: IpcRendererEvent, file) => { const fileEntry = $(`
-
${file.name}
+
${file.name}
${file.type}
${file.location}
@@ -146,25 +165,34 @@ ipcRenderer.on(IpcEvents.mainFileApproved, (event: IpcRendererEvent, file) => { `); ui.fileList.append(fileEntry); - fileEntry.on("click", onFileEntryClicked); - fileEntry - .children(".name") - .children(".copy-name") - .on("click", (event: JQuery.ClickEvent) => { - event.stopPropagation(); - clipboard.writeText(file.name); - }); + fileEntry.on("mouseup", onFileEntryClicked); }); -function onFileEntryClicked(e: JQuery.ClickEvent) { - //e.isPropagationStopped(false); +function onFileEntryClicked(event: JQuery.MouseUpEvent) { + let element = event.target; + if (!$(event.target).hasClass("file-entry")) element = element.parentElement; - let element = e.target; - if (!$(e.target).hasClass("file-entry")) element = element.parentElement; - - $(".file-entry").removeClass("selected"); - $(element).addClass("selected"); - ipcRenderer.send(IpcEvents.rendererRequestLoadMeta, $(element).children().eq(3).text()); + if (event.which == 1) { + $(".file-entry").removeClass("selected"); + $(element).addClass("selected"); + ipcRenderer.send(IpcEvents.rendererRequestLoadMeta, $(element).children().eq(3).text()); + } else if (event.which == 3) { + event.stopPropagation(); + openContextMenu(event.pageX, event.pageY, [ + { + name: "Copy name", + click() { + clipboard.writeText($(element).children(".name").html()); + }, + }, + { + name: "Remove", + click() { + $(element).remove(); + }, + }, + ]); + } } function _arrayBufferToBase64(buffer: Buffer): string { @@ -177,6 +205,45 @@ function _arrayBufferToBase64(buffer: Buffer): string { return window.btoa(binary); } +// +// +// Context menu +let isContextMenuOpen = false; + +function openContextMenu(x: number, y: number, options: Array) { + closeContextMenu(); + ui.contextMenu.css({ + left: `calc(${x}px - 2rem)`, + top: `calc(${y}px - 2rem)`, + // top: y, + display: "flex", + }); + isContextMenuOpen = true; + + options.forEach((element) => { + const optionButton = $(` + + `); + optionButton.on("mouseup", element.click); + ui.contextMenu.append(optionButton); + }); +} + +function closeContextMenu() { + if (isContextMenuOpen) { + ui.contextMenu.css({ display: "none" }); + ui.contextMenu.children().each((index, element) => { + $(element).off("mouseup"); + $(element).remove(); + }); + isContextMenuOpen = false; + } +} + +ui.document.on("mouseup", closeContextMenu); + // // // Popups @@ -185,6 +252,6 @@ ipcRenderer.on(IpcEvents.mainRequestRenderError, (event: IpcRendererEvent, error Error: ${error.name}\n ${error.message}\n \n - Please send a screenshot of this to Herman + Consider sending a screenshot of this to Herman `); });