diff --git a/globe.png b/globe.png new file mode 100644 index 0000000..659e79c Binary files /dev/null and b/globe.png differ diff --git a/index.html b/index.html index b841af5..c27bd28 100644 --- a/index.html +++ b/index.html @@ -54,7 +54,7 @@ background-color: black; border-right: 0; font-weight: bold; - line-height: 30px; + line-height: 40px; vertical-align: middle; white-space: nowrap; overflow: hidden @@ -157,6 +157,87 @@ background-color: black; } +#zoomMenu{ + position: fixed; + left: 15px; + top: 70px; + width: 250px; + height: 40px; + z-index: 999; + background-color: black; + display: none; + border: 1px solid yellowgreen +} + +#currentZoom { + position: absolute; + top: 10px; + left: 5px; + outline: 0; + color: yellowgreen; + font-family: 'Fira Code', monospace; +} + +#findMenu{ + position: fixed; + right: 15px; + top: 70px; + width: 250px; + height: 40px; + z-index: 999; + background-color: black; + display: none; + border: 1px solid yellowgreen +} + +#findInput { + width: 150px; + height: 20px; + border: 0; + border-bottom: 2px solid yellowgreen; + position: absolute; + top: 10px; + left: 5px; + outline: 0; + background-color: black; + color: yellowgreen; + font-family: 'Fira Code', monospace; +} + +#findInput:focus{ + outline: 0 +} + +.findMenuButton{ + background-color: black; + color: yellowgreen; + border: 1px solid yellowgreen; +} + +.findMenuButtonDiv{ + position: absolute; + right: 5px; + top: 10px; +} + +.favicon{ + width: 15px; + height: 15px; + margin-left: -10px; + padding: 4px; + display: inline-block; +} + +#contextmenu, #contextmenuSelect { + position: absolute; + background-color: black; + color: yellowgreen; + z-index: 999; + top:0; + left: 0; + display: none; +} + @media screen and (max-width: 300px){ nav{ display: none; @@ -183,7 +264,7 @@ -
+
+
+
+
+ +
+ + + +
+
+
+ +
+
+
Back
+
Forward
+
Reload
+
Print
+
View page source
+
Inspect
+
+
+
Copy
+
Search Google
+
Inspect
diff --git a/main.js b/main.js index cdacdc7..f0df91a 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, ipcMain, Menu, MenuItem } = require("electron"); +const { app, BrowserWindow, ipcMain, Menu, MenuItem, webContents } = require("electron"); const path = require("path"); const createWindow = () => { @@ -23,6 +23,7 @@ const createWindow = () => { }] })) win.setMenu(menu); + // win.setMenu(null); win.loadFile("index.html"); }; diff --git a/renderer.js b/renderer.js index 4e0a682..25cfa05 100644 --- a/renderer.js +++ b/renderer.js @@ -44,7 +44,7 @@ function closeTabHandler(e) { } -function setTabActive(toSet) { +async function setTabActive(toSet) { // set currently active tab inactive let webviews = document.getElementById("webviews").children; let tabs = document.getElementById("tabs").children; @@ -71,6 +71,14 @@ function setTabActive(toSet) { [...webviews].find(view => view.dataset.index == toSet.dataset.index).style.height = "100%"; // activeView.style.flex = "0 1"; activeTabIndex = toSet.dataset.index; + + let url = document.getElementById("url"); + if (toSet.dataset.url == "file://" + await window.electronAPI.dirname() + "/newtab.html"){ + url.value = ""; + } else { + url.value = toSet.dataset.url; + } + } function closeTab(tab) { @@ -90,7 +98,7 @@ function closeTab(tab) { tabs.removeChild(tab); //delete webview // webviews.removeChild([...webviews].find(view => view.dataset.index == tab.dataset.index)); - [...webviews].find(view => view.dataset.index == tab.dataset.index).remove(); + [...webviews.children].find(view => view.dataset.index == tab.dataset.index).remove(); } function handleReload(e) { @@ -108,10 +116,11 @@ function createNewTab(url) { let tabs = document.getElementById("tabs"); let newTab = elementFromHTML( - `
` + `
` ); newTab.addEventListener("click", setTabActiveHandler); newTab.dataset.index = totalTabs; + newTab.dataset.url = url; tabs.appendChild(newTab); let closeButton = elementFromHTML('') @@ -128,7 +137,7 @@ function createNewTab(url) { function createNewWebview(url, tab) { let webviews = document.getElementById("webviews"); let newview = elementFromHTML( - `` + `` ); newview.style = `width: 100%; height: calc(100vh - 60px); @@ -137,26 +146,116 @@ function createNewWebview(url, tab) { top: 60px; left: 0`; -newview.addEventListener("did-finish-load", ()=>{ - tab.children[0].innerHTML = newview.getTitle() +newview.addEventListener("did-finish-load", async ()=>{ + tab.children[1].innerHTML = newview.getTitle(); + let domain = new URL(newview.getURL()); + domain = domain.hostname; + if (url == "file://" + await window.electronAPI.dirname() + "/newtab.html") { + tab.children[0].src = "globe.png" + } else { + tab.children[0].src = `http://www.google.com/s2/favicons?domain=${domain}`; + } +}) + +newview.addEventListener("context-menu", (e) => { + let contextmenu = document.getElementById("contextmenu"); + let contextmenuSelect = document.getElementById("contextmenuSelect"); + if (e.params.selectionText != ""){ + contextmenuSelect.style.display = "block"; + contextmenu.style.display = "none"; + contextmenuSelect.style.top = e.params.y + "px"; + contextmenuSelect.style.left = e.params.x + "px"; +} else { + contextmenu.style.display = "block"; + contextmenuSelect.style.display = "none"; + contextmenu.style.top = e.params.y + "px"; + contextmenu.style.left = e.params.x + "px"; + } +}); + +newview.addEventListener("ipc-message", (e)=>{ + let contextmenu = document.getElementById("contextmenu"); + let contextmenuSelect = document.getElementById("contextmenuSelect"); + if (e.args.length != 0) { // if is a keypress + let event = new KeyboardEvent('keydown', { + code: e.args[0], + key: e.args[1], + shiftKey: e.args[2], + altKey: e.args[3], + ctrlKey: e.args[4], + metaKey: e.args[5], + repeat: e.args[6] + }); + shortcutHandler(event); + } else { // if is a click + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } }) + + newview.dataset.index = totalTabs; + totalTabs++; webviews.appendChild(newview); } - -document.onkeydown = async function (e) { - if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "t") { +document.onkeydown = shortcutHandler; +async function shortcutHandler(e) { + let contextmenu = document.getElementById("contextmenu"); + let contextmenuSelect = document.getElementById("contextmenuSelect"); + let webviews = document.getElementById("webviews").children; + let currView = [...webviews].find(view => view.dataset.index == activeTabIndex); + if ((e.ctrlKey || e.metaKey) && e.key == "t") { createNewTab("file://" + await window.electronAPI.dirname() + "/newtab.html"); - } else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "w") { + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "w") { let tabs = document.getElementById("tabs").children; closeTab([...tabs].find(tab => tab.dataset.index == activeTabIndex)) - } else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "r") { + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "r") { handleReload(e); - } else if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() == "i") { - let webviews = document.getElementById("webviews").children; - [...webviews].find(view => view.dataset.index == activeTabIndex).openDevTools(); + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key == "I") { + currView.openDevTools(); + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "f") { + document.getElementById("findMenu").style.display = "block"; + document.getElementById("findInput").focus(); + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key == "V") { + currView.pasteAndMatchStyle(); + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if (e.key == "Escape") { + currView.stopFindInPage("keepSelection"); + document.getElementById("findMenu").style.display = "none"; + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "p") { + currView.printToPDF({}); + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "=") { + currView.setZoomFactor(currView.getZoomFactor()+0.1) + document.getElementById("currentZoom").innerText = Math.round(currView.getZoomFactor() * 100) + "%" + document.getElementById("zoomMenu").style.display = "block"; + setTimeout(() => {document.getElementById("zoomMenu").style.display = "none"}, 3000) + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; + } else if ((e.ctrlKey || e.metaKey) && e.key == "-") { + currView.setZoomFactor(currView.getZoomFactor()-0.1) + document.getElementById("currentZoom").innerText = Math.round(currView.getZoomFactor() * 100) + "%" + document.getElementById("zoomMenu").style.display = "block"; + setTimeout(() => {document.getElementById("zoomMenu").style.display = "none"}, 3000) + contextmenuSelect.style.display = "none"; + contextmenu.style.display = "none"; } + }; (async function() { @@ -167,9 +266,7 @@ document.onkeydown = async function (e) { document.getElementById("url").addEventListener("keydown", (e) => { - console.log(e.key) let tabs = document.getElementById("tabs").children; - console.log(e.target.value) if (e.key == "Enter") { // change src of webview // change tab name @@ -191,11 +288,60 @@ document.getElementById("url").addEventListener("keydown", (e) => { } }); +document.getElementById("findInput").addEventListener("input", () => { + let findInput = document.getElementById("findInput"); + let webviews = document.getElementById("webviews").children; + [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, { + forward: true, + findNext: true, + matchCase: false + }); +}) + +document.getElementById("findNext").addEventListener("click", () => { + let webviews = document.getElementById("webviews").children; + let findInput = document.getElementById("findInput"); + [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, { + forward: true, + findNext: false, + matchCase: false + }); +}) + +document.getElementById("findPrev").addEventListener("click", () => { + let webviews = document.getElementById("webviews").children; + let findInput = document.getElementById("findInput"); + [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, { + forward: false, + findNext: false, + matchCase: false + }); +}) + +document.getElementById("closeFindMenu").addEventListener("click", () => { + document.getElementById("findMenu").style.display = "none"; +}) + +document.body.addEventListener("click", (e) => { + contextmenu = document.getElementById("contextmenu"); + contextmenuSelect = document.getElementById("contextmenuSelect"); + if (e.target != contextmenu && e.target != contextmenuSelect) { + contextmenu.style.display = "none"; + contextmenuSelect.style.display = "none"; + } +}) + -// implement keboard shortcutrs: undo, redo, cut, copy, paste, select all, zoom in, zoom out -//change url when change tab -//fix webview component not deleting + + + +//draggable tabs // bookmarks -//setings with themes //autofill in url bar -// fix when closing tabs it deselects/ selects first \ No newline at end of file +// fix when closing tabs it selects first tab +//right click dropdown menu +// fix print to pdf + +//buttons in zoom menu +//settings menu with themes and history +//open \ No newline at end of file diff --git a/viewPreload.js b/viewPreload.js new file mode 100644 index 0000000..9528b18 --- /dev/null +++ b/viewPreload.js @@ -0,0 +1,21 @@ +window.onload = function () { + const { ipcRenderer } = require("electron"); + + document.body.addEventListener("click", (e) => { + ipcRenderer.sendToHost("ipc-message"); + }); + + document.onkeydown = function handle(e) { + console.log(e); + ipcRenderer.sendToHost( + "ipc-message", + e.code, + e.key, + e.shiftKey, + e.altKey, + e.ctrlKey, + e.metaKey, + e.repeat + ); + }; +};