From 2673c7c6456155c256452df1a4102441c46d8b95 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Sun, 14 Mar 2021 18:22:59 -0600 Subject: [PATCH 1/8] updated hotkey storage scheme to allow multiple --- js/background.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/js/background.js b/js/background.js index 9cd6c80..e2a120a 100644 --- a/js/background.js +++ b/js/background.js @@ -2,17 +2,17 @@ chrome.runtime.onInstalled.addListener(function () { let settings = { hotkeys: { codes: { - navUp: ["w"], - navLeft: ["a"], - navDown: ["s"], - navRight: ["d"], - expand: ["e"], - contract: ["shift", "e"], - quit: ["q"], - click: ["enter"], - shiftClick: ["shift", "enter"], - controlClick: ["control", "enter"], - disableKeys: ["control", "shift", "x"], + navUp: [["w"]], + navLeft: [["a"]], + navDown: [["s"]], + navRight: [["d"]], + expand: [["e"]], + contract: [["shift", "e"]], + quit: [["q"]], + click: [["f"], ["enter"]], + shiftClick: [["shift", "enter"]], + controlClick: [["control", "enter"]], + disableKeys: [["control", "shift", "x"]], }, }, }; From d43f2eca7cb08a5c0f3c6fd7aab2ef9faa85c009 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Sun, 14 Mar 2021 19:19:02 -0600 Subject: [PATCH 2/8] now checks for matches against multiple key combos --- js/spatial-navigation.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/spatial-navigation.js b/js/spatial-navigation.js index 31e6342..eec338b 100644 --- a/js/spatial-navigation.js +++ b/js/spatial-navigation.js @@ -1819,7 +1819,9 @@ function getSettings(callback) { exports.getSettings = getSettings; function isHotkeyPressed(hotkeyID) { - return setArrayMatch(KEYS_DOWN, HOTKEY_CODES[hotkeyID]); + return HOTKEY_CODES[hotkeyID].some((combo) => { + return setArrayMatch(KEYS_DOWN, combo); + }) } exports.isHotkeyPressed = isHotkeyPressed; From b7cc62eb3eafca0a9c9ea3eae60beda68fa8a396 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 00:17:00 -0600 Subject: [PATCH 3/8] frontend for multiple hotkeys for each command The options UI can now handle setting and deleting multiple hotkeys for each command --- css/options.css | 17 ++++++++++ js/options.js | 87 ++++++++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/css/options.css b/css/options.css index a20b109..e9e6c63 100644 --- a/css/options.css +++ b/css/options.css @@ -120,6 +120,10 @@ hr { margin: 6px 10px; } +.hotkeys { + margin: 0 4px; +} + .hotkeys .btn-text { margin-right: 0; } @@ -130,6 +134,7 @@ hr { .btn-enter { background-color: #00b1e2; + margin-left: auto; } .reset-area { @@ -202,3 +207,15 @@ hr { border-radius: 8px; box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1); } + +.addHotkey { + opacity: 0; + margin-left: auto; + margin-right: 4px; + transition: opacity 0.4s ease-out; +} + +.setting:hover .addHotkey { + opacity: 1; + transition: opacity 0.2s linear; +} diff --git a/js/options.js b/js/options.js index fd80170..95a4340 100644 --- a/js/options.js +++ b/js/options.js @@ -61,13 +61,21 @@ function enterNewHotkey(event) { } } -function updateHotkey(element, newVal) { +function updateHotkey(element, newVal, index) { let parentSection = element.parentNode; parentSection.removeChild(element); let newSettings = SETTINGS_FULL; - newSettings.hotkeys.codes[parentSection.id] = newVal; + + if (newVal === null) { + // remove the hotkey at the index provided + newSettings.hotkeys.codes[parentSection.id].splice(index, 1); + } else { + // add the new hotkey to the end of the stored hotkeys + newSettings.hotkeys.codes[parentSection.id].push(newVal); + } + chrome.storage.local.set({ "extension-settings": newSettings }, function () { - setHotkeyBtn(parentSection); + getSettings(setHotkeyBtn(parentSection)); // TODO: Send message to content scripts that settings updated }); } @@ -97,23 +105,38 @@ function formateHotkeys(set1) { return keyString; } -function setHotkeyBtn(element) { - let el = document.createElement("div"); +function setHotkeyBtn(btnParent) { + let hotkeys = HOTKEY_CODES[btnParent.id]; + + // remove old buttons + while (btnParent.childNodes.length > 2) { + btnParent.removeChild(btnParent.lastChild); + } + // TODO: Check if hotkey combo in storage + let createNewBtn = document.createElement("div"); + createNewBtn.setAttribute("id", btnParent.id + "-btn"); + createNewBtn.setAttribute("class", "btn btn-hov addHotkey"); + createNewBtn.innerHTML = ` + + Click to type a new shortcut + + `; + // Add listner for new hotkey input + createNewBtn.addEventListener("click", enterNewHotkey); + btnParent.appendChild(createNewBtn); + // if in storage print stored combo - if (HOTKEY_CODES[element.id].length !== 0) { - console.log(element.id); - // delete previous btn - let old = document.getElementById(element.id + "-hotkey"); - if (old !== null && element.parentNode) { - old.parentNode.removeChild(old); - } - el.setAttribute("id", element.id + "-hotkey"); - el.setAttribute("class", "btn hotkeys"); - el.innerHTML = ` + if (hotkeys.length !== 0) { + hotkeys.forEach((hotkey, index) => { + let el = document.createElement("div"); + console.log(hotkey + " " + index); + el.setAttribute("id", btnParent.id + "-hotkey-" + index); + el.setAttribute("class", "btn hotkeys"); + el.innerHTML = ` - ${formateHotkeys(new Set(HOTKEY_CODES[element.id]))} + ${formateHotkeys(new Set(hotkey))} `; - el.getElementsByClassName("close")[0].addEventListener( - "click", - (deleteHotkey = function () { - updateHotkey(el, []); - }) - ); - element.appendChild(el); - } else { - // delete any previous btn - let old = document.getElementById(element.id + "-btn"); - if (old !== null && element.parentNode) { - old.parentNode.removeChild(old); - } - - el.setAttribute("id", element.id + "-btn"); - el.setAttribute("class", "btn btn-hov"); - el.innerHTML = ` - - Click to type a new shortcut - - `; - // Add listner for new hotkey input - el.addEventListener("click", enterNewHotkey); - element.appendChild(el); + el.getElementsByClassName("close")[0].addEventListener( + "click", + (deleteHotkey = function () { + updateHotkey(el, null, index); + }) + ); + btnParent.appendChild(el); + }); } } From 1e4b8f387008b4068a85fd493d608b20c5937da7 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 01:50:14 -0600 Subject: [PATCH 4/8] Give larger hover area for showing "add hotkey" button --- css/options.css | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/css/options.css b/css/options.css index e9e6c63..26e0c5a 100644 --- a/css/options.css +++ b/css/options.css @@ -59,12 +59,11 @@ h2 { .setting { display: flex; - justify-content: space-between; - padding: 1px; font-size: 12px; font-weight: 400; position: relative; flex-wrap: wrap; + height: 2.7rem; } .setting-description { @@ -83,8 +82,8 @@ h2 { } hr { - margin-top: 1rem; - margin-bottom: 1rem; + margin-top: 2px; + margin-bottom: 2px; border: 0; border-top: 1px solid #3e4852; box-sizing: content-box; @@ -121,7 +120,7 @@ hr { } .hotkeys { - margin: 0 4px; + margin: auto 4px; } .hotkeys .btn-text { From 22b9b328a519805cdc2d084d50359c7427740e93 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 01:51:10 -0600 Subject: [PATCH 5/8] Cleaner visual for adding and removing of new hotkeys --- css/options.css | 9 ++++++--- js/options.js | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/css/options.css b/css/options.css index 26e0c5a..c879860 100644 --- a/css/options.css +++ b/css/options.css @@ -133,7 +133,7 @@ hr { .btn-enter { background-color: #00b1e2; - margin-left: auto; + margin: auto 4px; } .reset-area { @@ -209,8 +209,7 @@ hr { .addHotkey { opacity: 0; - margin-left: auto; - margin-right: 4px; + margin: auto 4px; transition: opacity 0.4s ease-out; } @@ -218,3 +217,7 @@ hr { opacity: 1; transition: opacity 0.2s linear; } + +.setting > div:first-of-type { + margin: auto 4px auto auto; +} diff --git a/js/options.js b/js/options.js index 95a4340..8b8c9a4 100644 --- a/js/options.js +++ b/js/options.js @@ -70,8 +70,8 @@ function updateHotkey(element, newVal, index) { // remove the hotkey at the index provided newSettings.hotkeys.codes[parentSection.id].splice(index, 1); } else { - // add the new hotkey to the end of the stored hotkeys - newSettings.hotkeys.codes[parentSection.id].push(newVal); + // add the new hotkey to the beginning of the stored hotkeys + newSettings.hotkeys.codes[parentSection.id].unshift(newVal); } chrome.storage.local.set({ "extension-settings": newSettings }, function () { From 03623e91efaf7e998eeb23ffe43cf981f5d7d686 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 02:18:37 -0600 Subject: [PATCH 6/8] Allow hotkeys to wrap if necessary --- css/options.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/css/options.css b/css/options.css index c879860..c4918fa 100644 --- a/css/options.css +++ b/css/options.css @@ -63,7 +63,7 @@ h2 { font-weight: 400; position: relative; flex-wrap: wrap; - height: 2.7rem; + justify-content: flex-end; } .setting-description { @@ -120,7 +120,7 @@ hr { } .hotkeys { - margin: auto 4px; + margin: 7px 4px; } .hotkeys .btn-text { @@ -133,7 +133,7 @@ hr { .btn-enter { background-color: #00b1e2; - margin: auto 4px; + margin: 7px 4px; } .reset-area { @@ -209,7 +209,7 @@ hr { .addHotkey { opacity: 0; - margin: auto 4px; + margin: 7px 4px; transition: opacity 0.4s ease-out; } From 02526b68e394689b314bd1deebcd399cd5871af9 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 23:51:58 -0600 Subject: [PATCH 7/8] added check for duplicate hotkeys with notifications --- css/options.css | 34 ++++++++++++++++++++++ js/options.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- options.html | 5 ++++ 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/css/options.css b/css/options.css index c4918fa..37fd954 100644 --- a/css/options.css +++ b/css/options.css @@ -64,6 +64,7 @@ h2 { position: relative; flex-wrap: wrap; justify-content: flex-end; + min-height: 44px; } .setting-description { @@ -221,3 +222,36 @@ hr { .setting > div:first-of-type { margin: auto 4px auto auto; } + +/* For Notification Messages */ + +#notify { + --notificationBGColor: rgba(0, 137, 255, 0.6); + --notificationBorder: rgb(0, 137, 255); + --notificationTextColor: white; + position: sticky; + top: 0px; + width: 400px; + height: 0; + color: var(--notificationTextColor); + font-size: 15px; + font-weight: 500; + text-align: center; + background: var(--notificationBGColor); + overflow: hidden; + box-sizing: border-box; + transition: height .2s, border .2s, margin .2s; + left: 50%; + transform: translateX(-50%); +} + +#notifyText { + line-height: 50px; + vertical-align: middle; +} + +.active { + height:50px !important; + border-bottom: 2px var(--notificationBorder) solid !important; + margin-top: -50px; +} diff --git a/js/options.js b/js/options.js index 8b8c9a4..5e0dcbc 100644 --- a/js/options.js +++ b/js/options.js @@ -56,20 +56,64 @@ function enterNewHotkey(event) { window.removeEventListener("keydown", keyPress); window.removeEventListener("keyup", keyRelease); // setHotkeyBtn(element.parentNode); - updateHotkey(element, [...keysFinal]); + let newHotkey = [...keysFinal]; + if (isNotDuplicateHotkey(newHotkey, HOTKEY_CODES)) { + updateHotkey(element, newHotkey); + alertMessage("success", "Hotkey successfully added!", 2000); + } else { + updateHotkey(element, null); + alertMessage("failure", "That hotkey is already in use...", 2000); + } } } } +function alertMessage(type, text, timeOut) { + let notification = document.getElementById("notify"); + let notificationText = document.getElementById("notifyText"); + + // color the notification + let bgColor, textColor, borderColor; + switch (type) { + case "success": + bgColor = "rgb(67 255 125 / 70%)"; + textColor = "white"; + borderColor = "lime"; + break; + case "failure": + bgColor = "rgb(255 70 104 / 70%)"; + textColor = "white"; + borderColor = "red"; + break; + default: + bgColor = "rgb(0 137 255 / 60%)"; + textColor = "white"; + borderColor = "rgb(0 137 255)"; + break; + } + notification.style.setProperty("--notificationBGColor", bgColor); + notification.style.setProperty("--notificationBorder", borderColor); + notification.style.setProperty("--notificationTextColor", textColor); + + // Set the text + notificationText.innerHTML = text; + + // Show the notification for the specified time + notification.classList.add("active"); + setTimeout(function () { + notification.classList.remove("active"); + }, timeOut); +} + function updateHotkey(element, newVal, index) { let parentSection = element.parentNode; parentSection.removeChild(element); let newSettings = SETTINGS_FULL; - if (newVal === null) { + if (newVal === null && typeof index !== "undefined") { // remove the hotkey at the index provided newSettings.hotkeys.codes[parentSection.id].splice(index, 1); - } else { + } else if (newVal !== null) { // add the new hotkey to the beginning of the stored hotkeys newSettings.hotkeys.codes[parentSection.id].unshift(newVal); } @@ -148,6 +192,7 @@ function setHotkeyBtn(btnParent) { "click", (deleteHotkey = function () { updateHotkey(el, null, index); + alertMessage("success", "Hotkey removed!", 2000); }) ); btnParent.appendChild(el); @@ -155,6 +200,30 @@ function setHotkeyBtn(btnParent) { } } +function isNotDuplicateHotkey(newHotkey, allHotkeys) { + let arrayHotkeys = Object.values(allHotkeys); + for (command of arrayHotkeys) { + for (hotkey of command) { + if (areArraysEqual(newHotkey, hotkey)) { + return false; + } + } + } + // no duplicates found + return true; +} + +function areArraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length !== b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + return true; +} + getSettings(function () { // once the DOM is ready file in all settings info let stateCheck = setInterval(() => { diff --git a/options.html b/options.html index bccbfd5..3dcfb4e 100644 --- a/options.html +++ b/options.html @@ -9,6 +9,11 @@ + +
+ +
+

Spatial Navigation Options


From 36541996cced46535f5ee52b4004d8265c6c25c1 Mon Sep 17 00:00:00 2001 From: ortiza5 <43008712+ortiza5@users.noreply.github.com> Date: Mon, 15 Mar 2021 23:52:23 -0600 Subject: [PATCH 8/8] removed debugging printouts --- js/options.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/options.js b/js/options.js index 5e0dcbc..d13baea 100644 --- a/js/options.js +++ b/js/options.js @@ -5,7 +5,6 @@ function getSettings(callback) { chrome.storage.local.get(["extension-settings"], function (result) { SETTINGS_FULL = result["extension-settings"]; HOTKEY_CODES = SETTINGS_FULL.hotkeys.codes; - console.log(HOTKEY_CODES); if (callback instanceof Function) { callback(); } @@ -44,7 +43,6 @@ function enterNewHotkey(event) { setHotkeyBtn(element.parentNode); } keysDown.add(e.key.toLowerCase(), keysDown.size); - console.log(keysDown); textArea.innerHTML = formateHotkeys(keysDown); keysFinal = new Set(keysDown); } @@ -175,7 +173,6 @@ function setHotkeyBtn(btnParent) { if (hotkeys.length !== 0) { hotkeys.forEach((hotkey, index) => { let el = document.createElement("div"); - console.log(hotkey + " " + index); el.setAttribute("id", btnParent.id + "-hotkey-" + index); el.setAttribute("class", "btn hotkeys"); el.innerHTML = `