diff --git a/main.js b/main.js
deleted file mode 100644
index 573b0cc..0000000
--- a/main.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// Modules
-const electron = require('electron')
-const windowStateKeeper = require('electron-window-state')
-const {
- app,
- BrowserWindow,
- session,
- globalShortcut,
- Tray,
- ipcMain
-} = electron
-const readItem = require('./readItem')
-const updater = require('./updater')
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the JavaScript object is garbage collected.
-let mainWindow
-let monitorWindow
-
-// Listen for new item request
-ipcMain.on('new-item', (e, itemUrl) => {
- // console.log(itemUrl)
-
- // Get new item and send back to renderer
- readItem(itemUrl, item => {
- e.sender.send('new-item-success', item)
- })
-})
-
-// Create a new BrowserWindow when `app` is ready
-function createWindow() {
- let ses = session.defaultSession
-
- // Check for app updates 3 seconds after launch
- setTimeout( updater, 3000 )
-
- let windowState = windowStateKeeper({
- defaultWidth: 500, defaultHeight: 650
- })
-
- mainWindow = new BrowserWindow({
- width: windowState.width, height: windowState.height,
- x: windowState.x, y: windowState.y,
- minWidth: 350, maxWidth: 650, minHeight: 300,
- webPreferences: {nodeIntegration: true},
- titleBarStyle: 'hidden'
- })
-
- windowState.manage(mainWindow)
-
- // Load main.html into the new BrowserWindow
- mainWindow.loadFile('renderer/main.html')
-
- mainWindow.webContents.openDevTools()
-
- // Listen for window being closed
- mainWindow.on('closed', () => {
- mainWindow = null
- })
-
- let wc = mainWindow.webContents
- /*
- wc.on('before-input-event', (e, input) => {
- console.log('Before ' + input.key + ' ' + input.type)
- })
- */
- wc.on('did-finish-load', () => {
- console.log('main window fully loaded')
- })
- wc.on('dom-ready', () => {
- console.log('DOM ready')
- })
-
- //***//
- globalShortcut.register('f5', function() {
- console.log('f5 is pressed')
- mainWindow.reload()
- })
- globalShortcut.register('CommandOrControl+R', function() {
- console.log('CommandOrControl+R is pressed')
- mainWindow.reload()
- })
-}
-
-function createMonitorWindow() {
- let windowState = windowStateKeeper({
- defaultWidth: 500, defaultHeight: 400
- })
-
- // Create a new window
- monitorWindow = new BrowserWindow({
- width: windowState.width, height: windowState.height,
- x: windowState.x, y: windowState.y,
- minWidth: 300, maxWidth: 800, minHeight: 300, maxHeight: 800,
- // set the title bar style
- titleBarStyle: 'hiddenInset',
- // set the background color to black
- backgroundColor: "#111",
- // Don't show the window until it's ready, this prevents any white flickering
- show: false,
- webPreferences: {nodeIntegration: true}
- })
-
- windowState.manage(monitorWindow)
-
- monitorWindow.loadFile("renderer/monitor.html")
-
- monitorWindow.webContents.openDevTools()
-
- monitorWindow.once('ready-to-show', () => {
- monitorWindow.show()
- })
-
- let wc = monitorWindow.webContents
- wc.on('did-finish-load', () => {
- console.log('monitor window fully loaded')
- monitorWindow.webContents.send('init-monitor', true)
- })
-}
-
-/*
-app.on('browser-window-blur', () => {
- console.log('App unfocused')
- setTimeout(app.quit, 3000)
-})
-
-app.on('browser-window-focus', () => {
- console.log('App focused')
-})
-*/
-
-// Electron `app` is ready
-app.on('ready', () => {
- console.log('App is ready')
- console.log(app.getPath('desktop'))
- console.log(app.getPath('music'))
- console.log(app.getPath('temp'))
- console.log(app.getPath('userData'))
- createWindow()
- createMonitorWindow()
- // setTimeout(app.focus, 1000)
-})
-
-// Quit when all windows are closed - (Not macOS - Darwin)
-app.on('window-all-closed', () => {
- if (process.platform !== 'darwin') app.quit()
-})
-
-// When app icon is clicked and app is running, (macOS) recreate the BrowserWindow
-app.on('activate', () => {
- if (mainWindow === null) {
- createWindow()
- }
- if (monitorWindow === null) {
- createMonitorWindow()
- }
-})
-
-
-
-
-
diff --git a/package.json b/package.json
index d7b5e02..0a1e9b5 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "rb-electron-test",
"version": "1.1.0",
"description": "Resource Monitor",
- "main": "main.js",
+ "main": "src/main/main.js",
"scripts": {
"start": "electron .",
"watch": "nodemon --exec \"electron .\"",
diff --git a/renderer/app.js b/renderer/app.js
deleted file mode 100644
index 9635f43..0000000
--- a/renderer/app.js
+++ /dev/null
@@ -1,119 +0,0 @@
-
-// Modules
-const {ipcRenderer} = require('electron')
-const monitor = require('./monitor')
-const items = require('./items')
-
-// Dom Nodes
-let showModal = document.getElementById('show-modal'),
- closeModal = document.getElementById('close-modal'),
- modal = document.getElementById('modal'),
- addItem = document.getElementById('add-item'),
- itemUrl = document.getElementById('url'),
- search = document.getElementById('search')
-
-// Open new item modal
-window.newItem = () => {
- showModal.click()
-}
-
-// Open selected item
-window.openItem = () => {
- items.open()
-}
-
-// Delete selected item
-window.deleteItem = () => {
- let selectedItem = items.getSelectedItem();
- items.delete(selectedItem.index)
-}
-
-// Open selected item in native Browser
-window.openItemNative = () => {
- items.openNative()
-}
-
-// Search Items
-window.searchItems = () => {
- search.focus()
-}
-
-// Filter items with "search"
-search.addEventListener('keyup', e => {
-
- // Loop items
- Array.from( document.getElementsByClassName('read-item') ).forEach( item => {
-
- // Hide items that don't match search value
- let hasMatch = item.innerText.toLowerCase().includes(search.value)
- item.style.display = hasMatch ? 'flex' : 'none'
- })
-})
-
-// Navigate item selection with up/down arrows
-document.addEventListener('keydown', e => {
- if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
- items.changeSelection(e.key)
- }
-})
-
-// Disable & Enable modal buttons
-const toggleModalButtons = () => {
-
- // Check state of buttons
- if (addItem.disabled === true) {
- addItem.disabled = false
- addItem.style.opacity = 1
- addItem.innerText = 'Add Item'
- closeModal.style.display = 'inline'
- } else {
- addItem.disabled = true
- addItem.style.opacity = 0.5
- addItem.innerText = 'Adding...'
- closeModal.style.display = 'none'
- }
-}
-
-// Show modal
-showModal.addEventListener('click', e => {
- modal.style.display = 'flex'
- itemUrl.focus()
-})
-
-// Hide modal
-closeModal.addEventListener('click', e => {
- modal.style.display = 'none'
-})
-
-// Handle new item
-addItem.addEventListener('click', e => {
-
- // Check a url exists
- if (itemUrl.value) {
-
- // Send new item url to main process
- ipcRenderer.send('new-item', itemUrl.value)
-
- // Disable buttons
- toggleModalButtons()
- }
-})
-
-// Listen for new item from main process
-ipcRenderer.on('new-item-success', (e, newItem) => {
-
- // Add new item to "items" node
- items.addItem(newItem, true)
-
- // Enable buttons
- toggleModalButtons()
-
- // Hide modal and clear value
- modal.style.display = 'none'
- itemUrl.value = ''
-})
-
-// Listen for keyboard submit
-itemUrl.addEventListener('keyup', e => {
- if( e.key === 'Enter' ) addItem.click()
-})
diff --git a/renderer/items.js b/renderer/items.js
deleted file mode 100644
index 552d62e..0000000
--- a/renderer/items.js
+++ /dev/null
@@ -1,181 +0,0 @@
-
-// Modules
-const fs = require('fs')
-const {shell} = require('electron')
-
-// DOM nodes
-let items = document.getElementById('items')
-
-// Get readerJS contents
-let readerJS
-fs.readFile(`${__dirname}/reader.js`, (err, data) => {
- readerJS = data.toString()
-})
-
-// Track items in storage
-exports.storage = JSON.parse(localStorage.getItem('readit-items')) || []
-
-// Listen for "Done" message from reader window
-window.addEventListener('message', e => {
-
- // Check for correct message
- if (e.data.action === 'delete-reader-item') {
-
- // Delete item at given index
- this.delete(e.data.itemIndex)
-
- // Close the reader window
- e.source.close()
- }
-})
-
-// Delete item
-exports.delete = itemIndex => {
-
- // Remove item from DOM
- items.removeChild( items.childNodes[itemIndex] )
-
- // Remove from storage
- this.storage.splice(itemIndex, 1)
-
- // Persist
- this.save()
-
- // Select previous item or new first item if first was deleted
- if (this.storage.length) {
-
- // Get new selected item index
- let newSelectedItemIndex = (itemIndex === 0) ? 0 : itemIndex - 1
-
- // Set item at new index as selected
- document.getElementsByClassName('read-item')[newSelectedItemIndex].classList.add('selected')
- }
-}
-
-// Get selected item index
-exports.getSelectedItem = () => {
-
- // Get selected node
- let currentItem = document.getElementsByClassName('read-item selected')[0]
-
- // Get item index
- let itemIndex = 0
- let child = currentItem
- while( (child = child.previousSibling) != null ) itemIndex++
-
- // Return selected item and index
- return { node: currentItem, index: itemIndex }
-}
-
-// Persist storage
-exports.save = () => {
- localStorage.setItem('readit-items', JSON.stringify(this.storage))
-}
-
-// Set item as selected
-exports.select = e => {
-
- // Remove currently selected item class
- this.getSelectedItem().node.classList.remove('selected')
-
- // Add to clicked item
- e.currentTarget.classList.add('selected')
-}
-
-// Move to newly selected item
-exports.changeSelection = direction => {
-
- // Get selected item
- let currentItem = this.getSelectedItem()
-
- // Handle up/down
- if (direction === 'ArrowUp' && currentItem.node.previousSibling) {
- currentItem.node.classList.remove('selected')
- currentItem.node.previousSibling.classList.add('selected')
-
- } else if (direction === 'ArrowDown' && currentItem.node.nextSibling) {
- currentItem.node.classList.remove('selected')
- currentItem.node.nextSibling.classList.add('selected')
- }
-}
-
-// Open selected item
-exports.open = () => {
-
- // Only if we have items (in case of menu open)
- if( !this.storage.length ) return
-
- // Get selected item
- let selectedItem = this.getSelectedItem()
-
- // Get item's url
- let contentURL = selectedItem.node.dataset.url
-
- // Open item in proxy BrowserWindow
- let readerWin = window.open(contentURL, '', `
- maxWidth=2000,
- maxHeight=2000,
- width=1200,
- height=800,
- backgroundColor=#DEDEDE,
- nodeIntegration=0,
- contextIsolation=1
- `)
-
- // Inject JavaScript with specific item index (selectedItem.index)
- readerWin.eval( readerJS.replace('{{index}}', selectedItem.index) )
-}
-
-// Open selected item in native Browser
-exports.openNative = () => {
-
- // Only if we have items (in case of menu open)
- if( !this.storage.length ) return
-
- // Get selected item
- let selectedItem = this.getSelectedItem()
-
- // Open in system browser
- shell.openExternal(selectedItem.node.dataset.url)
-}
-
-// Add new item
-exports.addItem = (item, isNew = false) => {
-
- // Create a new DOM node
- let itemNode = document.createElement('div')
-
- // Assign "read-item" class
- itemNode.setAttribute('class', 'read-item')
-
- // Set item url as data attribute
- itemNode.setAttribute('data-url', item.url)
-
- // Add inner HTML
- itemNode.innerHTML = `![](${item.screenshot})
${item.title}
`
-
- // Append new node to "items"
- items.appendChild(itemNode)
-
- // Attach click handler to select
- itemNode.addEventListener('click', this.select)
-
- // Attach open doubleclick handler
- itemNode.addEventListener('dblclick', this.open)
-
- // If this is the first item, select it
- if (document.getElementsByClassName('read-item').length === 1) {
- itemNode.classList.add('selected')
- }
-
- // Add item to storage and persist
- if(isNew) {
- this.storage.push(item)
- this.save()
- }
-}
-
-// Add items from storage when app loads
-this.storage.forEach( item => {
- this.addItem(item)
-})
diff --git a/renderer/main.css b/renderer/main.css
deleted file mode 100644
index 555a05c..0000000
--- a/renderer/main.css
+++ /dev/null
@@ -1,122 +0,0 @@
-
-html, body {
- height: 100%;
-}
-
-body {
- font: caption;
- margin: 0;
- display: flex;
- flex-flow: column;
-}
-
-button {
- background: dodgerblue;
- color: white;
- border-radius: 5px;
- border: none;
- font-size: 20px;
- outline: none;
-}
-
-input {
- font-size: 20px;
- border-radius: 5px;
- border: 1px solid silver;
- padding: 0 10px;
-}
-
-input::placeholder {
- color: lightgray;
-}
-
-header {
- background: lightgray;
- display: flex;
- padding: 10px;
- font-weight: bold;
- border-bottom: 1px solid silver;
- box-shadow: 0px 10px 10px rgba(0,0,0,0.1);
-}
-
-#show-modal {
- padding: 0px 12px 5px;
- margin-right: 10px;
- font-size: 30px;
-}
-
-#search {
- flex-grow: 1;
-}
-
-main {
- flex-grow: 1;
- overflow-y: scroll;
-}
-
-#no-items {
- font-weight: bold;
- color: silver;
- text-align: center;
- width: 100%;
- position: absolute;
- top: 100px;
- z-index: -1;
-}
-
-#modal {
- position: absolute;
- width: 100%;
- height: 100%;
- background: rgba(0,0,0,0.85);
- display: flex;
- align-items: center;
- align-content: center;
- flex-wrap: wrap;
- display: none;
-}
-
-#url {
- flex-grow: 1;
- width: 100%;
- margin: 0 25px 15px;
- padding: 10px;
-}
-
-#modal button {
- padding: 10px;
-}
-
-#close-modal {
- background: white;
- color: black;
- margin-left: 15px;
-}
-
-#add-item {
- margin-left: 25px;
-}
-
-.read-item {
- display: flex;
- align-items: center;
- align-content: center;
- border-bottom: lightgray 2px solid;
- background: #FAFAFA;
- padding: 10px;
- border-left: 10px solid lightgray;
- -webkit-user-select: none;
-}
-
-.read-item:hover {
- background-color: #EEE;
-}
-
-.read-item.selected {
- border-left-color: dodgerblue;
-}
-
-.read-item img {
- width: 20%;
- margin-right: 25px;
-}
diff --git a/src/main/main.js b/src/main/main.js
new file mode 100644
index 0000000..3b72c35
--- /dev/null
+++ b/src/main/main.js
@@ -0,0 +1,49 @@
+// Modules
+const electron = require('electron')
+const windowStateKeeper = require('electron-window-state')
+const {app} = electron
+const mainWindow = require('./mainWindow')
+const monitorWindow = require('./monitorWindow')
+const updater = require('./updater')
+
+/*
+app.on('browser-window-blur', () => {
+ console.log('App unfocused')
+ setTimeout(app.quit, 3000)
+})
+
+app.on('browser-window-focus', () => {
+ console.log('App focused')
+})
+*/
+
+// Electron `app` is ready
+app.on('ready', () => {
+ console.log('App is ready')
+ console.log(app.getPath('desktop'))
+ console.log(app.getPath('music'))
+ console.log(app.getPath('temp'))
+ console.log(app.getPath('userData'))
+
+ mainWindow.activate()
+ // monitorWindow.activate()
+
+ // Check for app updates 3 seconds after launch
+ // setTimeout( updater, 3000 )
+})
+
+// Quit when all windows are closed - (Not macOS - Darwin)
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') app.quit()
+})
+
+// When app icon is clicked and app is running, (macOS) recreate the BrowserWindow
+app.on('activate', () => {
+ mainWindow.activate()
+ // montitorWindow.activate()
+})
+
+
+
+
+
diff --git a/src/main/mainWindow.js b/src/main/mainWindow.js
new file mode 100644
index 0000000..8af7bc6
--- /dev/null
+++ b/src/main/mainWindow.js
@@ -0,0 +1,88 @@
+// Modules
+const electron = require('electron')
+const windowStateKeeper = require('electron-window-state')
+const {
+ BrowserWindow,
+ globalShortcut,
+ ipcMain
+} = electron
+const readItem = require('./readItem')
+
+// Keep a global reference of the window object, if you don't, the window will
+// be closed automatically when the JavaScript object is garbage collected.
+let mainBrowserwindow = null
+
+// Listen for new item request
+ipcMain.on('new-item', (e, itemUrl) => {
+ console.log('Received new-item via ipcMain: ' + itemUrl)
+
+ // Get new item and send back to renderer
+ readItem(itemUrl, item => {
+ console.log('send new-item-success back to e.sender: ' + item)
+ e.sender.send('new-item-success', item)
+ })
+})
+
+exports.activate = () => {
+
+ console.log('activateMain')
+ console.log(mainBrowserwindow)
+ if (mainBrowserwindow === null) {
+ createMainWindow()
+ }
+}
+
+// Create a new BrowserWindow when `app` is ready
+function createMainWindow() {
+
+ let windowState = windowStateKeeper({
+ defaultWidth: 500, defaultHeight: 650
+ })
+
+ mainBrowserwindow = new BrowserWindow({
+ width: windowState.width, height: windowState.height,
+ x: windowState.x, y: windowState.y,
+ minWidth: 350, maxWidth: 650, minHeight: 300,
+ webPreferences: {nodeIntegration: true/*, webSecurity: false*/},
+ titleBarStyle: 'hidden'
+ })
+
+ windowState.manage(mainBrowserwindow)
+
+ // Load main.html into the new BrowserWindow
+ mainBrowserwindow.loadFile('src/renderer/html/main.html')
+
+ mainBrowserwindow.webContents.openDevTools()
+
+ // Listen for window being closed
+ mainBrowserwindow.on('closed', () => {
+ mainBrowserwindow = null
+ })
+
+ let wc = mainBrowserwindow.webContents
+ /*
+ wc.on('before-input-event', (e, input) => {
+ console.log('Before ' + input.key + ' ' + input.type)
+ })
+ */
+ wc.on('did-finish-load', () => {
+ console.log('main window fully loaded')
+ })
+ wc.on('dom-ready', () => {
+ console.log('DOM ready')
+ })
+
+ //***//
+ globalShortcut.register('f5', function () {
+ console.log('f5 is pressed')
+ mainBrowserwindow.reload()
+ })
+ globalShortcut.register('CommandOrControl+R', function () {
+ console.log('CommandOrControl+R is pressed')
+ mainBrowserwindow.reload()
+ })
+}
+
+
+
+
diff --git a/src/main/monitorWindow.js b/src/main/monitorWindow.js
new file mode 100644
index 0000000..ed3a783
--- /dev/null
+++ b/src/main/monitorWindow.js
@@ -0,0 +1,52 @@
+// Modules
+const electron = require('electron')
+const windowStateKeeper = require('electron-window-state')
+const {BrowserWindow} = electron
+
+// Keep a global reference of the window object, if you don't, the window will
+// be closed automatically when the JavaScript object is garbage collected.
+let monitorBrowserWindow = null
+
+exports.activate = () => {
+ if (monitorBrowserWindow === null) {
+ createMonitorWindow()
+ }
+}
+
+function createMonitorWindow() {
+
+ let windowState = windowStateKeeper({
+ defaultWidth: 500, defaultHeight: 400
+ })
+
+ // Create a new window
+ monitorBrowserWindow = new BrowserWindow({
+ width: windowState.width, height: windowState.height,
+ x: windowState.x, y: windowState.y,
+ minWidth: 300, maxWidth: 800, minHeight: 300, maxHeight: 800,
+ // set the title bar style
+ titleBarStyle: 'hiddenInset',
+ // set the background color to black
+ backgroundColor: "#111",
+ // Don't show the window until it's ready, this prevents any white flickering
+ show: false,
+ webPreferences: {nodeIntegration: true/*, webSecurity: false*/}
+ })
+
+ windowState.manage(monitorBrowserWindow)
+
+ monitorBrowserWindow.loadFile("src/renderer/html/monitor.html")
+
+ monitorBrowserWindow.webContents.openDevTools()
+
+ monitorBrowserWindow.once('ready-to-show', () => {
+ monitorBrowserWindow.show()
+ })
+
+ let wc = monitorBrowserWindow.webContents
+ wc.on('did-finish-load', () => {
+ console.log('monitor window fully loaded')
+ console.log('Send init-monitor via monitorBrowserWindow.webContents')
+ monitorBrowserWindow.webContents.send('init-monitor', true)
+ })
+}
diff --git a/readItem.js b/src/main/readItem.js
similarity index 100%
rename from readItem.js
rename to src/main/readItem.js
diff --git a/updater.js b/src/main/updater.js
similarity index 100%
rename from updater.js
rename to src/main/updater.js
diff --git a/src/renderer/app.js b/src/renderer/app.js
new file mode 100644
index 0000000..17a25b7
--- /dev/null
+++ b/src/renderer/app.js
@@ -0,0 +1,3 @@
+// Modules
+const main = require('./script/main')
+const monitor = require('./script/monitor')
diff --git a/renderer/main.html b/src/renderer/html/main.html
similarity index 76%
rename from renderer/main.html
rename to src/renderer/html/main.html
index cd420df..2e95003 100644
--- a/renderer/main.html
+++ b/src/renderer/html/main.html
@@ -1,21 +1,22 @@
+
Readit
-
+
-
+
- No Items
-
+ No Items
+
@@ -25,8 +26,9 @@
+
diff --git a/renderer/monitor.html b/src/renderer/html/monitor.html
similarity index 78%
rename from renderer/monitor.html
rename to src/renderer/html/monitor.html
index 93dbe38..6d3aaf1 100644
--- a/renderer/monitor.html
+++ b/src/renderer/html/monitor.html
@@ -3,15 +3,10 @@
-
Activity Monitor
-
-
-
-
-
-
+
+
diff --git a/src/renderer/script/main.js b/src/renderer/script/main.js
new file mode 100644
index 0000000..b101c9d
--- /dev/null
+++ b/src/renderer/script/main.js
@@ -0,0 +1,122 @@
+// Modules
+const {ipcRenderer} = require('electron')
+const items = require('./mainItems')
+
+// Dom Nodes
+let showModal = document.getElementById('show-modal'),
+ closeModal = document.getElementById('close-modal'),
+ modal = document.getElementById('modal'),
+ addItem = document.getElementById('add-item'),
+ itemUrl = document.getElementById('url'),
+ search = document.getElementById('search')
+
+// Open new item modal
+window.newItem = () => {
+ showModal.click()
+}
+
+// Open selected item
+window.openItem = () => {
+ items.open()
+}
+
+// Delete selected item
+window.deleteItem = () => {
+ let selectedItem = items.getSelectedItem();
+ items.delete(selectedItem.index)
+}
+
+// Open selected item in native Browser
+window.openItemNative = () => {
+ items.openNative()
+}
+
+// Search Items
+window.searchItems = () => {
+ search.focus()
+}
+
+// Filter items with "search"
+search.addEventListener('keyup', e => {
+
+ // Loop items
+ Array.from(document.getElementsByClassName('read-item')).forEach(item => {
+
+ // Hide items that don't match search value
+ let hasMatch = item.innerText.toLowerCase().includes(search.value)
+ item.style.display = hasMatch ? 'flex' : 'none'
+ })
+})
+
+// Navigate item selection with up/down arrows
+document.addEventListener('keydown', e => {
+ if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
+ items.changeSelection(e.key)
+ }
+})
+
+// Disable & Enable modal buttons
+const toggleModalButtons = () => {
+
+ // Check state of buttons
+ if (addItem.disabled === true) {
+ addItem.disabled = false
+ addItem.style.opacity = 1
+ addItem.innerText = 'Add Item'
+ closeModal.style.display = 'inline'
+ } else {
+ addItem.disabled = true
+ addItem.style.opacity = 0.5
+ addItem.innerText = 'Adding...'
+ closeModal.style.display = 'none'
+ }
+}
+
+// Show modal
+showModal.addEventListener('click', e => {
+ modal.style.display = 'flex'
+ itemUrl.focus()
+})
+
+// Hide modal
+closeModal.addEventListener('click', e => {
+ modal.style.display = 'none'
+})
+
+// Handle new item
+addItem.addEventListener('click', e => {
+
+ // Check a url exists
+ if (itemUrl.value) {
+
+ console.log('Send new-item via ipcRenderer: ' + itemUrl.value)
+
+ // Send new item url to main process
+ ipcRenderer.send('new-item', itemUrl.value)
+
+ // Disable buttons
+ toggleModalButtons()
+ }
+})
+
+// Listen for new item from main process
+ipcRenderer.on('new-item-success', (e, newItem) => {
+
+ console.log('Received new-item-success via ipcRenderer')
+ console.log(newItem)
+
+ // Add new item to "items" node
+ items.addItem(newItem, true)
+
+ // Enable buttons
+ toggleModalButtons()
+
+ // Hide modal and clear value
+ modal.style.display = 'none'
+ itemUrl.value = ''
+})
+
+// Listen for keyboard submit
+itemUrl.addEventListener('keyup', e => {
+ if (e.key === 'Enter') addItem.click()
+})
diff --git a/src/renderer/script/mainItems.js b/src/renderer/script/mainItems.js
new file mode 100644
index 0000000..95c78ab
--- /dev/null
+++ b/src/renderer/script/mainItems.js
@@ -0,0 +1,185 @@
+// Modules
+const fs = require('fs')
+const {shell} = require('electron')
+
+// Dom Nodes
+let main = document.getElementById('main'),
+ noMain = document.getElementById('no-main')
+
+// Get readerJS contents
+let readerJS
+fs.readFile(`${__dirname}/mainReader.js`, (err, data) => {
+ readerJS = data.toString()
+})
+
+// Track main in storage
+exports.storage = JSON.parse(localStorage.getItem('readit-main')) || []
+
+// Listen for "Done" message from reader window
+window.addEventListener('message', e => {
+
+ // Check for correct message
+ if (e.data.action === 'delete-reader-item') {
+
+ // Delete item at given index
+ this.delete(e.data.itemIndex)
+
+ // Close the reader window
+ e.source.close()
+ }
+})
+
+// Delete item
+exports.delete = itemIndex => {
+
+ // Remove item from DOM
+ main.removeChild(main.childNodes[itemIndex])
+ if (main.childNodes.length === 0) {
+ noMain.style.display = 'inline'
+ }
+
+ // Remove from storage
+ this.storage.splice(itemIndex, 1)
+
+ // Persist
+ this.save()
+
+ // Select previous item or new first item if first was deleted
+ if (this.storage.length) {
+
+ // Get new selected item index
+ let newSelectedItemIndex = (itemIndex === 0) ? 0 : itemIndex - 1
+
+ // Set item at new index as selected
+ document.getElementsByClassName('read-item')[newSelectedItemIndex].classList.add('selected')
+ }
+}
+
+// Get selected item index
+exports.getSelectedItem = () => {
+
+ // Get selected node
+ let currentItem = document.getElementsByClassName('read-item selected')[0]
+
+ // Get item index
+ let itemIndex = 0
+ let child = currentItem
+ while ((child = child.previousSibling) != null) itemIndex++
+
+ // Return selected item and index
+ return {node: currentItem, index: itemIndex}
+}
+
+// Persist storage
+exports.save = () => {
+ localStorage.setItem('readit-main', JSON.stringify(this.storage))
+}
+
+// Set item as selected
+exports.select = e => {
+
+ // Remove currently selected item class
+ this.getSelectedItem().node.classList.remove('selected')
+
+ // Add to clicked item
+ e.currentTarget.classList.add('selected')
+}
+
+// Move to newly selected item
+exports.changeSelection = direction => {
+
+ // Get selected item
+ let currentItem = this.getSelectedItem()
+
+ // Handle up/down
+ if (direction === 'ArrowUp' && currentItem.node.previousSibling) {
+ currentItem.node.classList.remove('selected')
+ currentItem.node.previousSibling.classList.add('selected')
+
+ } else if (direction === 'ArrowDown' && currentItem.node.nextSibling) {
+ currentItem.node.classList.remove('selected')
+ currentItem.node.nextSibling.classList.add('selected')
+ }
+}
+
+// Open selected item
+exports.open = () => {
+
+ // Only if we have main (in case of menu open)
+ if (!this.storage.length) return
+
+ // Get selected item
+ let selectedItem = this.getSelectedItem()
+
+ // Get item's url
+ let contentURL = selectedItem.node.dataset.url
+
+ // Open item in proxy BrowserWindow
+ let readerWin = window.open(contentURL, '', `
+ maxWidth=2000,
+ maxHeight=2000,
+ width=1200,
+ height=800,
+ backgroundColor=#DEDEDE,
+ nodeIntegration=0,
+ contextIsolation=1
+ `)
+
+ // Inject JavaScript with specific item index (selectedItem.index)
+ readerWin.eval(readerJS.replace('{{index}}', selectedItem.index))
+}
+
+// Open selected item in native Browser
+exports.openNative = () => {
+
+ // Only if we have main (in case of menu open)
+ if (!this.storage.length) return
+
+ // Get selected item
+ let selectedItem = this.getSelectedItem()
+
+ // Open in system browser
+ shell.openExternal(selectedItem.node.dataset.url)
+}
+
+// Add new item
+exports.addItem = (item, isNew = false) => {
+
+ // Create a new DOM node
+ let itemNode = document.createElement('div')
+
+ // Assign "read-item" class
+ itemNode.setAttribute('class', 'read-item')
+
+ // Set item url as data attribute
+ itemNode.setAttribute('data-url', item.url)
+
+ // Add inner HTML
+ itemNode.innerHTML = `![](${item.screenshot})
${item.title}
`
+
+ // Append new node to "main"
+ main.appendChild(itemNode)
+ noMain.style.display = 'none'
+
+ // Attach click handler to select
+ itemNode.addEventListener('click', this.select)
+
+ // Attach open doubleclick handler
+ itemNode.addEventListener('dblclick', this.open)
+
+ // If this is the first item, select it
+ if (document.getElementsByClassName('read-item').length === 1) {
+ itemNode.classList.add('selected')
+ }
+
+ // Add item to storage and persist
+ if (isNew) {
+ this.storage.push(item)
+ this.save()
+ }
+}
+
+// Add main from storage when app loads
+this.storage.forEach(item => {
+ this.addItem(item)
+})
diff --git a/renderer/menu.js b/src/renderer/script/mainMenu.js
similarity index 83%
rename from renderer/menu.js
rename to src/renderer/script/mainMenu.js
index 428be80..0395cf1 100644
--- a/renderer/menu.js
+++ b/src/renderer/script/mainMenu.js
@@ -44,13 +44,15 @@ const template = [
submenu: [
{
label: 'Learn more',
- click: () => {shell.openExternal('https://github.com/ptaucher/rb-electron-test')}
+ click: () => {
+ shell.openExternal('https://github.com/ptaucher/rb-electron-test')
+ }
}
]
}
]
-// Set Mac-specific first menu item
+// Set Mac-specific first mainMenu item
if (process.platform === 'darwin') {
template.unshift({
label: remote.app.getName(),
@@ -68,8 +70,8 @@ if (process.platform === 'darwin') {
})
}
-// Build menu
-const menu = remote.Menu.buildFromTemplate(template)
+// Build mainMenu
+const mainMenu = remote.Menu.buildFromTemplate(template)
-// Set as main menu
-remote.Menu.setApplicationMenu(menu)
+// Set as main mainMenu
+remote.Menu.setApplicationMenu(mainMenu)
diff --git a/renderer/reader.js b/src/renderer/script/mainReader.js
similarity index 81%
rename from renderer/reader.js
rename to src/renderer/script/mainReader.js
index d586086..442839c 100644
--- a/renderer/reader.js
+++ b/src/renderer/script/mainReader.js
@@ -1,4 +1,3 @@
-
// Create button in remote content to mark item as "Done"
let readitClose = document.createElement('div')
readitClose.innerText = 'Done'
@@ -19,11 +18,17 @@ readitClose.style.boxShadow = '2px 2px 2px rgba(0,0,0,0.2)'
// Attach click handler
readitClose.onclick = e => {
- // Message parent (opener) window
- window.opener.postMessage({
- action: 'delete-reader-item',
- itemIndex: {{index}}
- }, '*')
+ // Message parent (opener) window
+ window.opener.postMessage({
+ action: 'delete-reader-item',
+ itemIndex: {
+ {
+ index
+ }
+}
+},
+ '*'
+)
}
// Append button to body
diff --git a/renderer/monitor.js b/src/renderer/script/monitor.js
similarity index 97%
rename from renderer/monitor.js
rename to src/renderer/script/monitor.js
index 7243516..782f7eb 100644
--- a/renderer/monitor.js
+++ b/src/renderer/script/monitor.js
@@ -8,7 +8,7 @@ var lastMeasureTimes = [];
// Initialize/Start monitor only after the window is ready to show (-> call this via IPC)
ipcRenderer.on('init-monitor', (flag) => {
- console.log('init monitor')
+ console.log('Received init-monitor via ipcRenderer')
document.getElementById('info').innerText =
'Host: ' + os.hostname() +
diff --git a/src/renderer/style/main.css b/src/renderer/style/main.css
new file mode 100644
index 0000000..1810aa4
--- /dev/null
+++ b/src/renderer/style/main.css
@@ -0,0 +1,122 @@
+
+html, body {
+ height: 100%;
+}
+
+body {
+ font: caption;
+ margin: 0;
+ display: flex;
+ flex-flow: column;
+}
+
+button {
+ background: dodgerblue;
+ color: white;
+ border-radius: 5px;
+ border: none;
+ font-size: 20px;
+ outline: none;
+}
+
+input {
+ font-size: 20px;
+ border-radius: 5px;
+ border: 1px solid silver;
+ padding: 0 10px;
+}
+
+input::placeholder {
+ color: lightgray;
+}
+
+header {
+ background: lightgray;
+ display: flex;
+ padding: 10px;
+ font-weight: bold;
+ border-bottom: 1px solid silver;
+ box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.1);
+}
+
+#show-modal {
+ padding: 0px 12px 5px;
+ margin-right: 10px;
+ font-size: 30px;
+}
+
+#search {
+ flex-grow: 1;
+}
+
+main {
+ flex-grow: 1;
+ overflow-y: scroll;
+}
+
+#no-items {
+ font-weight: bold;
+ color: silver;
+ text-align: center;
+ width: 100%;
+ position: absolute;
+ top: 100px;
+ z-index: -1;
+}
+
+#modal {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.85);
+ display: flex;
+ align-items: center;
+ align-content: center;
+ flex-wrap: wrap;
+ display: none;
+}
+
+#url {
+ flex-grow: 1;
+ width: 100%;
+ margin: 0 25px 15px;
+ padding: 10px;
+}
+
+#modal button {
+ padding: 10px;
+}
+
+#close-modal {
+ background: white;
+ color: black;
+ margin-left: 15px;
+}
+
+#add-item {
+ margin-left: 25px;
+}
+
+.read-item {
+ display: flex;
+ align-items: center;
+ align-content: center;
+ border-bottom: lightgray 2px solid;
+ background: #FAFAFA;
+ padding: 10px;
+ border-left: 10px solid lightgray;
+ -webkit-user-select: none;
+}
+
+.read-item:hover {
+ background-color: #EEE;
+}
+
+.read-item.selected {
+ border-left-color: dodgerblue;
+}
+
+.read-item img {
+ width: 20%;
+ margin-right: 25px;
+}
diff --git a/renderer/monitor.css b/src/renderer/style/monitor.css
similarity index 100%
rename from renderer/monitor.css
rename to src/renderer/style/monitor.css