diff --git a/src/js/export.js b/src/js/export.js
index ac0aef6..4ab4862 100644
--- a/src/js/export.js
+++ b/src/js/export.js
@@ -116,7 +116,16 @@ export async function saveOptions(event) {
} else if (event.target.type === 'checkbox') {
value = event.target.checked
} else if (event.target.type === 'number') {
- value = event.target.value.toString()
+ const number = parseFloat(event.target.value)
+ let min = 0.5
+ let max = 2.0
+ if (!isNaN(number) && number >= min && number <= max) {
+ event.target.value = number.toString()
+ value = number
+ } else {
+ event.target.value = options[event.target.id]
+ return
+ }
} else {
value = event.target.value?.trim()
}
@@ -147,13 +156,12 @@ export function updateOptions(options) {
}
// console.debug(`${key}: ${value}`)
const el = document.getElementById(key)
- // console.debug('el:', el)
if (!el) {
continue
}
if (!['INPUT', 'SELECT'].includes(el.tagName)) {
el.textContent = value.toString()
- } else if (el.type === 'checkbox') {
+ } else if (['checkbox', 'radio'].includes(el.type)) {
el.checked = value
} else {
el.value = value
diff --git a/src/js/options.js b/src/js/options.js
index 94aa847..41e0c07 100644
--- a/src/js/options.js
+++ b/src/js/options.js
@@ -3,7 +3,6 @@
import {
activateOrOpen,
checkPerms,
- onChanged,
requestPerms,
saveOptions,
showToast,
@@ -15,6 +14,8 @@ chrome.storage.onChanged.addListener(onChanged)
chrome.permissions.onAdded.addListener(onAdded)
chrome.permissions.onRemoved.addListener(onRemoved)
+window.addEventListener('keydown', handleKeyboard)
+
document.addEventListener('DOMContentLoaded', initOptions)
document.getElementById('reset-country').addEventListener('click', resetCountry)
document.getElementById('test-voice').addEventListener('click', testVoice)
@@ -44,14 +45,12 @@ document
*/
async function initOptions() {
console.debug('initOptions')
- await setShortcuts({
- mainKey: '_execute_action',
- openHome: 'openHome',
- })
+ await setShortcuts('#keyboard-shortcuts')
updateManifest()
const { options } = await chrome.storage.sync.get(['options'])
console.debug('options:', options)
updateOptions(options)
+ setBackground(options)
await checkPerms()
if (typeof speechSynthesis !== 'undefined') {
@@ -69,6 +68,32 @@ async function initOptions() {
}
}
+/**
+ * Login Background Change Callback
+ * @function loginBackgroundChange
+ * @param {InputEvent} event
+ */
+function loginBackgroundChange(event) {
+ console.debug('loginBackgroundChange:', event.target.id)
+ updateBackgroundInput(event.target.id)
+}
+
+/**
+ * Set Background
+ * @function setBackground
+ * @param {Object} options
+ */
+function setBackground(options) {
+ console.debug('setBackground:', options)
+ if (options.radioBackground === 'bgPicture') {
+ const url = options.pictureURL || 'https://picsum.photos/1920/1080'
+ document.body.style.background = `url('${url}') no-repeat center fixed`
+ document.body.style.backgroundSize = 'cover'
+ } else {
+ document.body.style.cssText = ''
+ }
+}
+
function addSpeechVoices(options, voices) {
console.debug('addSpeechVoices:', options, voices)
const voiceSelect = document.getElementById('speechVoice')
@@ -140,6 +165,39 @@ function getUtterance(text, options) {
return utterance
}
+/**
+ * Handle Keyboard Shortcuts Callback
+ * @function handleKeyboard
+ * @param {KeyboardEvent} e
+ */
+function handleKeyboard(e) {
+ // console.debug('handleKeyboard:', e)
+ console.debug('type:', e.target.type)
+ if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.repeat) {
+ return
+ }
+ if (
+ [
+ 'date',
+ 'email',
+ 'number',
+ 'password',
+ 'search',
+ 'tel',
+ 'text',
+ 'url',
+ ].includes(e.target.type)
+ ) {
+ return
+ }
+ if (!document.getElementById('enableKeyboard').checked) {
+ return
+ }
+ if (['KeyZ', 'KeyK'].includes(e.code)) {
+ bootstrap.Modal.getOrCreateInstance('#keybinds-modal').toggle()
+ }
+}
+
/**
* Copy Support/Debugging Information
* @function copySupport
@@ -215,18 +273,52 @@ async function openPermissions(event) {
/**
* Set Keyboard Shortcuts
* @function setShortcuts
- * @param {Object} mapping { elementID: name }
+ * @param {String} selector
*/
-async function setShortcuts(mapping) {
+async function setShortcuts(selector = '#keyboard-shortcuts') {
+ if (!chrome.commands) {
+ return console.debug('Skipping: chrome.commands')
+ }
+ document.getElementById('table-wrapper').classList.remove('d-none')
+ const table = document.querySelector(selector)
+ const tbody = table.querySelector('tbody')
+ const source = tbody.querySelector('tr.d-none').cloneNode(true)
+ source.classList.remove('d-none')
const commands = await chrome.commands.getAll()
- for (const [elementID, name] of Object.entries(mapping)) {
- // console.debug(`${elementID}: ${name}`)
- const command = commands.find((x) => x.name === name)
- if (command?.shortcut) {
- console.debug(`${elementID}: ${command.shortcut}`)
- const el = document.getElementById(elementID)
- if (el) {
- el.textContent = command.shortcut
+ for (const command of commands) {
+ // console.debug('command:', command)
+ const row = source.cloneNode(true)
+ // TODO: Chrome does not parse the description for _execute_action in manifest.json
+ let description = command.description
+ if (!description && command.name === '_execute_action') {
+ description = 'Show Popup'
+ }
+ row.querySelector('.description').textContent = description
+ row.querySelector('kbd').textContent = command.shortcut || 'Not Set'
+ tbody.appendChild(row)
+ }
+}
+
+/**
+ * On Changed Callback
+ * @function onChanged
+ * @param {Object} changes
+ * @param {String} namespace
+ */
+export function onChanged(changes, namespace) {
+ console.debug('onChanged:', changes, namespace)
+ for (const [key, { oldValue, newValue }] of Object.entries(changes)) {
+ if (namespace === 'sync' && key === 'options') {
+ console.debug('newValue:', newValue)
+ updateOptions(newValue)
+ if (oldValue.radioBackground !== newValue.radioBackground) {
+ setBackground(newValue)
+ }
+ if (
+ oldValue.pictureURL !== newValue.pictureURL ||
+ oldValue.videoURL !== newValue.videoURL
+ ) {
+ setBackground(newValue)
}
}
}
diff --git a/src/js/service-worker.js b/src/js/service-worker.js
index e472c7d..8350949 100644
--- a/src/js/service-worker.js
+++ b/src/js/service-worker.js
@@ -59,6 +59,8 @@ async function onInstalled(details) {
autoFill: false,
asnUsername: '',
asnEmail: '',
+ radioBackground: 'bgPicture',
+ pictureURL: 'https://picsum.photos/1920/1080',
contextMenu: true,
showUpdate: false,
})
From 3d29190d4b54714ea151d5a2f7543bdeb666080a Mon Sep 17 00:00:00 2001
From: Shane <6071159+smashedr@users.noreply.github.com>
Date: Sat, 13 Jul 2024 14:47:37 -0700
Subject: [PATCH 2/7] Update Options for Light Mode
---
src/css/options.css | 24 +++++++++++++++++------
src/html/options.html | 3 ++-
src/js/export.js | 3 +++
src/js/options.js | 42 +++++++++++++++++++++++++++++-----------
src/js/service-worker.js | 2 +-
5 files changed, 55 insertions(+), 19 deletions(-)
diff --git a/src/css/options.css b/src/css/options.css
index 5a432c1..a4b6e01 100644
--- a/src/css/options.css
+++ b/src/css/options.css
@@ -5,17 +5,29 @@ body {
}
#options-wrapper {
- background: rgba(0 0 0 / 60%);
- filter: drop-shadow(15px 15px 12px #000000);
- backdrop-filter: blur(6px);
- max-width: 800px;
width: 100%;
+ max-width: 800px;
+ backdrop-filter: blur(6px);
+ filter: drop-shadow(15px 15px 12px #000000);
}
-.form-control {
+[data-bs-theme='dark'] #options-wrapper {
+ background: rgba(0 0 0 / 60%);
+}
+[data-bs-theme='light'] #options-wrapper {
+ background: rgba(255 255 255 / 60%);
+}
+
+[data-bs-theme='dark'] .form-control {
background: rgba(0 0 0 / 50%);
}
+[data-bs-theme='light'] .form-control {
+ background: rgba(255 255 255 / 50%);
+}
-#table-wrapper {
+[data-bs-theme='dark'] #table-wrapper {
background: rgba(0 0 0 / 50%);
}
+[data-bs-theme='light'] #table-wrapper {
+ background: rgba(255 255 255 / 50%);
+}
diff --git a/src/html/options.html b/src/html/options.html
index 6688638..965fa32 100644
--- a/src/html/options.html
+++ b/src/html/options.html
@@ -1,5 +1,5 @@
-
+
@@ -255,6 +255,7 @@
ASN Plus