diff --git a/src/app.css b/src/app.css index 5b139a2..baae9c0 100644 --- a/src/app.css +++ b/src/app.css @@ -8,12 +8,20 @@ body { margin: 0px; overflow: hidden; background-color: #212121; + font-family: "Arial"; } -.controls { +section { position: fixed; + z-index: 2; + pointer-events: none; +} + +.controls { + z-index: 3; display: flex; justify-content: space-between; + pointer-events: auto; } .controls button { @@ -25,7 +33,6 @@ body { margin: 0px; background-color: transparent; font-size: 3em; - font-family: "Arial"; transition: background-color .2s, filter .2s; cursor: pointer; filter: opacity(5%); @@ -38,4 +45,34 @@ body { img { object-fit: contain; -} \ No newline at end of file + filter: drop-shadow(0px 0px 10px #000); +} + +.background { + filter: blur(15px); + z-index: 1; +} + +.background img { + object-fit: cover; +} + +.info[data-show="false"] { + display: none; +} + +.info { + bottom: 0px; + z-index: 4; + width: auto; + height: auto; + margin: 10px; +} + +.info p { + margin: 0px; + padding: 5px; + color: white; + background-color: rgba(0, 0, 0, 0.50); +} + diff --git a/src/app.html b/src/app.html index 2f15eb2..1241a33 100644 --- a/src/app.html +++ b/src/app.html @@ -3,21 +3,31 @@ - Manga Reader + MangaReader +
+

+

+
+
- - + +
+
+ +
+ + \ No newline at end of file diff --git a/src/app.js b/src/app.js index 6223bfc..f2ca71b 100644 --- a/src/app.js +++ b/src/app.js @@ -1,64 +1,16 @@ /* - App code + Main code used for the viewer + All the components take cares of themselves, no need for extra code here By Zoey Désautels */ -// Some imports lol +// Imports const remote = require('electron').remote; -const {dialog, BrowserWindow} = remote; -const fs = require('fs'); - -// Some variables -let AppWindow = remote.getCurrentWindow(); -let files = []; -let index = 0; - -// Load/set the picture -function setPicture() { - document.querySelector("#image").src = files[index]; -} - -function setupKeys() { - document.addEventListener("keydown", (event) => { - let key = event.key; - if(key == "ArrowLeft") previousFile(); - if(key == "ArrowRight") nextFile(); - if(key == "p") openFolder(); - if(key == "f") toggleFullscreen(); - }); -} - -function toggleFullscreen() { - AppWindow.isFullScreen() ? AppWindow.setFullScreen(false) : AppWindow.setFullScreen(true); -} - -function nextFile() { - index = files.length == index + 1 ? 0 : index + 1; - setPicture(); -} - -function previousFile() { - index = -1 == index - 1 ? files.length - 1 : index - 1; - setPicture(); -} - -// Open a folder -function openFolder() { - index = 0; - files = []; - dialog.showOpenDialog(AppWindow, { - properties: ["openDirectory"] - }, (filePaths, bookmarks) => { - fs.readdir(filePaths[0], (err, _files) => { - for(let file of _files) { - files.push(`${filePaths[0]}/${file}`); - } - _files.length == 0 ? openFolder() : setPicture(); - }); - }); -} - -document.addEventListener('DOMContentLoaded', () => { - openFolder(); - setupKeys(); -}); \ No newline at end of file +const {dialog, BrowserWindow, shell, clipboard} = remote; +const fs = require('fs'), path = require('path'); + +// Load the components +const Window = new (require('./components/Window.js')); +const ImageViewer = new (require('./components/ImageViewer.js')); +const ControlsBox = new (require('./components/ControlsBox.js')); +const InfoBox = new (require('./components/InfoBox.js')); \ No newline at end of file diff --git a/src/components/ControlsBox.js b/src/components/ControlsBox.js new file mode 100644 index 0000000..52e7acc --- /dev/null +++ b/src/components/ControlsBox.js @@ -0,0 +1,8 @@ +module.exports = class ControlsBox { + constructor() { + let controlsContainer = document.querySelector('.controls'); + + controlsContainer.querySelector('.left').addEventListener('click', () => ImageViewer.loadPreviousPage()); + controlsContainer.querySelector('.right').addEventListener('click', () => ImageViewer.loadNextPage()); + } +} \ No newline at end of file diff --git a/src/components/ImageViewer.js b/src/components/ImageViewer.js new file mode 100644 index 0000000..beb24fa --- /dev/null +++ b/src/components/ImageViewer.js @@ -0,0 +1,91 @@ +/* + ImageViewer component + By Zoey Désautels, 2018 +*/ + +module.exports = class ImageViewer { + constructor() { + // The two containers we use + this.viewer = document.querySelector("#image"); + this.background = document.querySelector("#blur"); + + // Variables + this.index; + this.files; + this.folder; + } + + // Load the image file + loadPage() { + this.viewer.src = this.files[this.index]; + this.background.src = this.files[this.index]; + + InfoBox.setInfo(); + Window.setTitle(); + } + + // Load the next page + loadNextPage() { + this.index = this.files.length == this.index + 1 ? 0 : this.index + 1; + this.loadPage(); + } + + // Load the previous page + loadPreviousPage() { + this.index = -1 == this.index - 1 ? this.files.length - 1 : this.index - 1; + this.loadPage(); + } + + // Load a folder + loadFolder() { + // Reset the index and files variables + this.index = 0; + this.files = []; + + dialog.showOpenDialog(Window.AppWindow, { + properties: ["openDirectory"] + }, (filePaths, bookmarks) => { + if(filePaths && filePaths.length > 0) { + fs.readdir(filePaths[0], (err, _files) => { + this.folder = filePaths[0]; + + // Filter out non-image files + for(let file of _files) { + let filePath = `${this.folder}/${file}`; + let fileStat = fs.statSync(filePath); + + // Check if the current "file" is a file + if(fileStat.isFile()) { + let imagesExtension = [ + ".png", ".jpg", ".gif" + ]; + let fileExtension = path.extname(filePath); + + // Check that the file is an image + if(imagesExtension.includes(fileExtension)) this.files.push(filePath); + } + } + + // Sort files via their timestamp + this.files.sort((a, b) => { + return fs.statSync(a).mtime.getTime() - fs.statSync(b).mtime.getTime(); + }); + + // Check if we have any files to load + this.files.length == 0 ? + dialog.showMessageBox(Window.AppWindow, { + type: "error", + title: "Error", + message: "No images were found in the selected folder." + }, () => { + this.loadFolder(); + }) + : this.loadPage(); + }); + } else { + remote.app.exit(0); + } + }); + + } +} \ No newline at end of file diff --git a/src/components/InfoBox.js b/src/components/InfoBox.js new file mode 100644 index 0000000..b3e8613 --- /dev/null +++ b/src/components/InfoBox.js @@ -0,0 +1,17 @@ +module.exports = class InfoBox { + constructor() { + this.infobox = document.querySelector(".info"); + + this.filename = this.infobox.querySelector(".filename"); + this.foldername = this.infobox.querySelector(".folder"); + } + + setInfo() { + this.filename.textContent = path.basename(ImageViewer.files[ImageViewer.index]); + this.foldername.textContent = path.normalize(ImageViewer.folder); + } + + toggle() { + this.infobox.dataset.show = this.infobox.dataset.show == "true" ? "false" : "true"; + } +} \ No newline at end of file diff --git a/src/components/Window.js b/src/components/Window.js new file mode 100644 index 0000000..98f7307 --- /dev/null +++ b/src/components/Window.js @@ -0,0 +1,58 @@ +/* + Window component, mostly take cares of document stuff + By Zoey Désautels +*/ + +module.exports = class Window { + constructor() { + this.AppWindow = remote.getCurrentWindow(); // Some electron thing + + document.addEventListener('DOMContentLoaded', () => { + ImageViewer.loadFolder(); + this.loadShortcuts(); + }); + } + + // Toggle fullscreen + toggleFullscreen() { + this.AppWindow.isFullScreen() ? this.AppWindow.setFullScreen(false) : this.AppWindow.setFullScreen(true); + } + + // Set/update the app title + setTitle() { + this.AppWindow.setTitle(`MangaReader - ${path.normalize(ImageViewer.files[ImageViewer.index])} - ${ImageViewer.index + 1}/${ImageViewer.files.length}`); + } + + loadShortcuts() { + const Shortcuts = { + "ArrowLeft": () => ImageViewer.loadPreviousPage(), + "ArrowRight": () => ImageViewer.loadNextPage(), + "Enter": () => shell.showItemInFolder(files[index]), + + "Home": () => { + ImageViewer.index = 0; + ImageViewer.loadPage(); + }, + "End": () => { + ImageViewer.index = ImageViewer.files.length - 1; + ImageViewer.loadPage(); + }, + " ": () => { + InfoBox.toggle(); + }, + + "p": () => ImageViewer.loadFolder(), + "f": () => this.toggleFullscreen(), + "c": () => clipboard.writeImage(files[index]) + }; + + document.addEventListener("keydown", (event) => { + let key = event.key; + if(Shortcuts[key]) Shortcuts[key](); + }); + + document.addEventListener("wheel", (event) => { + event.deltaY > 0 ? previousFile() : nextFile(); + }); + } +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index 0fd013b..c198841 100644 --- a/src/main.js +++ b/src/main.js @@ -11,8 +11,9 @@ let MainWindow; // Create Window function CreateMainWindow() { - MainWindow = new BrowserWindow({}); + MainWindow = new BrowserWindow({backgroundColor: "#212121", title: "MangaReader"}); MainWindow.setMenu(null); + MainWindow.webContents.openDevTools(); MainWindow.loadFile("src/app.html"); }