diff --git a/css/options.css b/css/options.css new file mode 100644 index 0000000..a20b109 --- /dev/null +++ b/css/options.css @@ -0,0 +1,204 @@ +html * { + box-sizing: border-box; +} + +body { + background: black; + color: #fafafa; + margin: 0px !important; +} + +@media only screen and (max-width: 730px) { + body { + padding: 10px; + } +} + +h1, +h2 { + color: #fafafa; + font-family: system-ui; + font-weight: 500; +} + +h1 { + font-size: 30px; +} + +h2 { + font-size: 18px; +} + +.title { + padding: 15px 0 2px 0; + text-align: center; + margin-bottom: -20px; +} + +.title-area { + display: flex; + justify-content: space-between; + position: relative; + max-width: 700px; + margin: 20px auto 2px auto; +} + +.setting-area { + padding-left: 10px; +} + +.card { + padding: 12px 18px; + background-color: #171b1f; + border: 1px solid #3e4852; + border-radius: 5px; + font-family: system-ui; + max-width: 700px; + margin: 0 auto 20px auto; +} + +.setting { + display: flex; + justify-content: space-between; + padding: 1px; + font-size: 12px; + font-weight: 400; + position: relative; + flex-wrap: wrap; +} + +.setting-description { + margin: auto 0; +} + +.btn { + background-color: rgb(42, 52, 61); + border: 1px solid #3e4852; + border-radius: 3px; + box-sizing: border-box; + display: inline-block; + position: relative; + height: 30px; + cursor: pointer; +} + +hr { + margin-top: 1rem; + margin-bottom: 1rem; + border: 0; + border-top: 1px solid #3e4852; + box-sizing: content-box; + height: 0; + overflow: visible; +} + +.close { + margin: 6px 3px; + font-family: "Segoe UI", system-ui, sans-serif; + display: inline-block; + vertical-align: middle; + animation: pop 16ms linear; + width: 18px; + height: 18px; + border-radius: 1px; + background-color: rgba(0, 0, 0, 0); + opacity: 1; + border: 0; + padding: 0; + fill: #fafafa; +} + +.close:hover { + fill: red; + background-color: rgba(0, 0, 0, 0.3); +} + +.btn-text { + display: inline-block; + align-items: center; + vertical-align: middle; + margin: 6px 10px; +} + +.hotkeys .btn-text { + margin-right: 0; +} + +.btn-hov:hover { + background-color: #3e4852; +} + +.btn-enter { + background-color: #00b1e2; +} + +.reset-area { + display: flex; + justify-content: center; + position: relative; + margin: 50px 0; +} + +.reset { + font-size: 12px; + font-weight: 400; + background-color: rgb(202, 74, 74); +} + +.reset:hover { + background-color: rgb(148, 54, 54); +} + +.info { + color: #00b1e2; + position: relative; + display: inline-block; + margin-left: 4px; +} + +.info .info-content { + visibility: hidden; + width: max-content; + max-width: 450px; + background-color: rgb(44, 44, 44); + border: 1px solid rgb(1, 140, 179); + color: #fff; + padding: 5px 8px; + border-radius: 6px; + display: inline-block; + font-style: normal; + + /* Positioning the tooltip */ + position: absolute; + z-index: 1; + top: -5px; + left: 105%; +} + +.info-content img { + margin-top: 6px; + max-width: 432px; +} + +/* Show the tooltip when the mouse hovers the tooltip container */ +.info:hover .info-content { + visibility: visible; +} + +.options-container { + margin: 30px 0 15px 0; + width: 100%; + text-align: center; +} + +.options-container input[type="radio"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.options-container img { + height: 200px; + border-radius: 8px; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1); +} diff --git a/js/options.js b/js/options.js new file mode 100644 index 0000000..fd80170 --- /dev/null +++ b/js/options.js @@ -0,0 +1,159 @@ +var SETTINGS_FULL; +var HOTKEY_CODES; + +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(); + } + }); +} + +function populateFields() { + let hotkeyDivs = document.querySelectorAll(".setting[data-type='shortcut']"); + hotkeyDivs.forEach((hotkeyDiv) => { + setHotkeyBtn(hotkeyDiv); + }); +} + +function enterNewHotkey(event) { + let element = event.currentTarget; + element.removeEventListener("click", enterNewHotkey); + element.setAttribute("class", "btn btn-enter"); + let textArea = element.children[0]; + textArea.innerHTML = ` + Enter the shortcut + `; + + let keysDown = new Set(); + let keysFinal; + window.addEventListener("keydown", keyPress); + window.addEventListener("keyup", keyRelease); + + function keyPress(e) { + e.preventDefault(); + e.stopPropagation(); + + // hitting escape cancels input + if (e.key.toLowerCase() === "escape") { + window.removeEventListener("keydown", keyPress); + window.removeEventListener("keyup", keyRelease); + setHotkeyBtn(element.parentNode); + } + keysDown.add(e.key.toLowerCase(), keysDown.size); + console.log(keysDown); + textArea.innerHTML = formateHotkeys(keysDown); + keysFinal = new Set(keysDown); + } + function keyRelease(e) { + keysDown.delete(e.key.toLowerCase()); + + // once no more keys are pressed, the final combo is recorded + if (keysDown.size === 0) { + window.removeEventListener("keydown", keyPress); + window.removeEventListener("keyup", keyRelease); + // setHotkeyBtn(element.parentNode); + updateHotkey(element, [...keysFinal]); + } + } +} + +function updateHotkey(element, newVal) { + let parentSection = element.parentNode; + parentSection.removeChild(element); + let newSettings = SETTINGS_FULL; + newSettings.hotkeys.codes[parentSection.id] = newVal; + chrome.storage.local.set({ "extension-settings": newSettings }, function () { + setHotkeyBtn(parentSection); + // TODO: Send message to content scripts that settings updated + }); +} + +function formateHotkeys(set1) { + let replaceTable = { + Control: "Ctrl", + Arrowup: "↑", + Arrowright: "→", + Arrowdown: "↓", + Arrowleft: "←", + " ": " Space", + Pageup: "PgUp", + Pagedown: "PgDn", + Delete: "Del", + }; + + let keyString = [...set1].map((c) => c.slice(0, 1).toUpperCase() + c.slice(1).toLowerCase()).join(" + "); + keyString = keyString.replace( + /Control|Arrowup|Arrowright|Arrowdown|Arrowleft|\s\s|Pageup|Pagedown|Delete/g, + function (match) { + return replaceTable[match]; + } + ); + keyString = keyString === " " ? "Space" : keyString; + + return keyString; +} + +function setHotkeyBtn(element) { + let el = document.createElement("div"); + // TODO: Check if hotkey combo in storage + + // 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 = ` + + ${formateHotkeys(new Set(HOTKEY_CODES[element.id]))} + + + `; + 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); + } +} + +getSettings(function () { + // once the DOM is ready file in all settings info + let stateCheck = setInterval(() => { + if (document.readyState === "complete") { + clearInterval(stateCheck); + populateFields(); + } + }, 100); +}); diff --git a/manifest.json b/manifest.json index 393361b..db3019c 100755 --- a/manifest.json +++ b/manifest.json @@ -15,4 +15,5 @@ "short_name": "spatial-navigation", "update_url": "https://clients2.google.com/service/update2/crx", "version": "0.4.7" + "options_page": "options.html" } diff --git a/options.html b/options.html new file mode 100644 index 0000000..9c4ad30 --- /dev/null +++ b/options.html @@ -0,0 +1,71 @@ + + + +
+ + +