Merge pull request #2771 from omnivore-app/feat/extension-improve-keyboard
Keyboard events + better keyboard handling
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 348 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 572 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 716 B After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 565 B |
|
Before Width: | Height: | Size: 729 B |
|
Before Width: | Height: | Size: 899 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 699 B |
|
Before Width: | Height: | Size: 871 B |
|
Before Width: | Height: | Size: 1023 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 615 B |
|
Before Width: | Height: | Size: 941 B |
|
Before Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 525 B |
|
Before Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 1018 B |
|
Before Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 374 B |
|
Before Width: | Height: | Size: 498 B |
|
Before Width: | Height: | Size: 732 B |
|
Before Width: | Height: | Size: 313 B |
|
Before Width: | Height: | Size: 503 B |
|
Before Width: | Height: | Size: 631 B |
|
Before Width: | Height: | Size: 940 B |
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||
<path fill="black" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 776 B |
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 776 B |
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 776 B |
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 776 B |
|
Before Width: | Height: | Size: 428 B |
|
Before Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 673 B |
|
Before Width: | Height: | Size: 832 B |
|
Before Width: | Height: | Size: 989 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 843 B |
|
Before Width: | Height: | Size: 1009 B |
|
Before Width: | Height: | Size: 1.2 KiB |
@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "process.env.EXTENSION_NAME",
|
||||
"short_name": "process.env.EXTENSION_NAME",
|
||||
"version": "2.2.1",
|
||||
"version": "2.4.2",
|
||||
"description": "Save PDFs and Articles to your Omnivore library",
|
||||
"author": "Omnivore Media, Inc",
|
||||
"default_locale": "en",
|
||||
@ -75,12 +75,12 @@
|
||||
],
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"16": "/images/toolbar/icon-16.png",
|
||||
"19": "/images/toolbar/icon-19.png",
|
||||
"24": "/images/toolbar/icon-24.png",
|
||||
"32": "/images/toolbar/icon-32.png",
|
||||
"38": "/images/toolbar/icon-38.png",
|
||||
"48": "/images/toolbar/icon-48.png"
|
||||
"16": "/images/extension/icon-16.png",
|
||||
"19": "/images/extension/icon-19.png",
|
||||
"24": "/images/extension/icon-24.png",
|
||||
"32": "/images/extension/icon-32.png",
|
||||
"38": "/images/extension/icon-38.png",
|
||||
"48": "/images/extension/icon-48.png"
|
||||
},
|
||||
"default_title": "Omnivore Save Article"
|
||||
},
|
||||
|
||||
@ -603,6 +603,7 @@ function handleActionClick() {
|
||||
|
||||
function executeAction(action) {
|
||||
getCurrentTab().then((currentTab) => {
|
||||
console.log('currentTab: ', currentTab)
|
||||
browserApi.tabs.sendMessage(
|
||||
currentTab.id,
|
||||
{
|
||||
@ -637,49 +638,6 @@ function executeAction(action) {
|
||||
})
|
||||
}
|
||||
|
||||
function getIconPath(active, dark) {
|
||||
let iconPath = '/images/toolbar/icon'
|
||||
if (ENV_IS_FIREFOX) {
|
||||
iconPath += '_firefox'
|
||||
} else if (ENV_IS_EDGE) {
|
||||
iconPath += '_edge'
|
||||
}
|
||||
if (!active) {
|
||||
iconPath += '_inactive'
|
||||
}
|
||||
/* we have to evaluate this every time as the onchange is not
|
||||
* fired inside background pages, due to https://crbug.com/968651 */
|
||||
const useDarkIcon =
|
||||
typeof dark === 'boolean'
|
||||
? dark
|
||||
: window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
|
||||
if (useDarkIcon) {
|
||||
iconPath += '_dark'
|
||||
}
|
||||
if (ENV_IS_FIREFOX) {
|
||||
return iconPath + '.svg'
|
||||
}
|
||||
|
||||
const iconSizes = ['16', '24', '32', '48']
|
||||
if (!ENV_IS_EDGE) {
|
||||
iconSizes.push('19', '38')
|
||||
}
|
||||
const iconPaths = {}
|
||||
for (let i = 0; i < iconSizes.length; i++) {
|
||||
const iconSize = iconSizes[i]
|
||||
iconPaths[iconSize] = iconPath + '-' + iconSize + '.png'
|
||||
}
|
||||
return iconPaths
|
||||
}
|
||||
|
||||
function updateActionIcon(tabId, active, dark) {
|
||||
browserActionApi.setIcon({
|
||||
path: getIconPath(active, dark),
|
||||
tabId: tabId,
|
||||
})
|
||||
}
|
||||
|
||||
function getActionableState(tab) {
|
||||
if (tab.status !== 'complete') return false
|
||||
|
||||
@ -698,17 +656,7 @@ function getActionableState(tab) {
|
||||
return true
|
||||
}
|
||||
|
||||
function reflectIconState(tab) {
|
||||
const tabId = tab && tab.id
|
||||
if (!tabId) return
|
||||
|
||||
const active = getActionableState(tab)
|
||||
|
||||
updateActionIcon(tabId, active)
|
||||
}
|
||||
|
||||
function init() {
|
||||
/* Extension icon switcher on page/tab load status */
|
||||
browserApi.tabs.onActivated.addListener(({ tabId }) => {
|
||||
// Due to a chrome bug, chrome.tabs.* may run into an error because onActivated is triggered too fast.
|
||||
function checkCurrentTab() {
|
||||
@ -716,21 +664,11 @@ function init() {
|
||||
if (browserApi.runtime.lastError) {
|
||||
setTimeout(checkCurrentTab, 150)
|
||||
}
|
||||
reflectIconState(tab)
|
||||
})
|
||||
}
|
||||
|
||||
checkCurrentTab()
|
||||
})
|
||||
|
||||
/* Extension icon switcher on page/tab load status */
|
||||
browserApi.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||
/* Not an update while this tab is active so we skip updating icon */
|
||||
if (!changeInfo.status || !tab || !tab.active) return
|
||||
|
||||
reflectIconState(tab)
|
||||
})
|
||||
|
||||
browserApi.tabs.onRemoved.addListener((tabId) => {
|
||||
/* cleanup any previous saveInProgress state for the tab */
|
||||
cleanupTabState(tabId)
|
||||
@ -746,10 +684,6 @@ function init() {
|
||||
return
|
||||
}
|
||||
|
||||
if (request.action === ACTIONS.RefreshDarkMode) {
|
||||
updateActionIcon(sender.tab.id, request.payload.value)
|
||||
}
|
||||
|
||||
if (request.action === ACTIONS.EditTitle) {
|
||||
pendingRequests.push({
|
||||
id: uuidv4(),
|
||||
@ -808,25 +742,9 @@ function init() {
|
||||
}
|
||||
})
|
||||
|
||||
// set initial extension icon
|
||||
browserActionApi.setIcon({
|
||||
path: getIconPath(true),
|
||||
})
|
||||
|
||||
browserApi.contextMenus.create({
|
||||
id: 'save-selection',
|
||||
title: 'Save link to Omnivore',
|
||||
contexts: ['link'],
|
||||
onclick: async function (obj) {
|
||||
executeAction(async function (currentTab) {
|
||||
await saveUrl(currentTab, obj.linkUrl)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
browserApi.contextMenus.create({
|
||||
id: 'save-selection',
|
||||
title: 'Save link to Omnivore',
|
||||
title: 'Save this link to Omnivore',
|
||||
contexts: ['link'],
|
||||
onclick: async function (obj) {
|
||||
executeAction(async function (currentTab) {
|
||||
|
||||
@ -64,6 +64,7 @@
|
||||
const html = await file.text()
|
||||
|
||||
const root = document.createElement('div')
|
||||
root.tabIndex = 0
|
||||
root.attachShadow({ mode: 'open' })
|
||||
if (root.shadowRoot) {
|
||||
root.shadowRoot.innerHTML = `<style>:host {all initial;}</style>`
|
||||
@ -72,11 +73,12 @@
|
||||
const toastEl = document.createElement('div')
|
||||
toastEl.id = '#omnivore-toast'
|
||||
toastEl.innerHTML = html
|
||||
toastEl.tabIndex = 0
|
||||
root.shadowRoot.appendChild(toastEl)
|
||||
|
||||
document.body.appendChild(root)
|
||||
connectButtons(root)
|
||||
// connectKeyboard(root)
|
||||
connectKeyboard(root)
|
||||
|
||||
return root
|
||||
}
|
||||
@ -217,6 +219,8 @@
|
||||
toastEl.remove()
|
||||
}
|
||||
})
|
||||
|
||||
currentToastEl.focus()
|
||||
}
|
||||
|
||||
function updatePageStatus(status) {
|
||||
@ -328,15 +332,7 @@
|
||||
}
|
||||
|
||||
function connectKeyboard(root) {
|
||||
console.log('connecting keyboard')
|
||||
root.addEventListener('keydown', (e) => {
|
||||
console.log(
|
||||
'root.addEventListener document code: ',
|
||||
e.key,
|
||||
'activeElement:',
|
||||
document.activeElement
|
||||
)
|
||||
|
||||
switch (e.key) {
|
||||
case 'r':
|
||||
readNow()
|
||||
@ -347,13 +343,19 @@
|
||||
case 'm':
|
||||
openMenu()
|
||||
break
|
||||
case 'i':
|
||||
case 't':
|
||||
editTitle()
|
||||
break
|
||||
case 't':
|
||||
case 'n':
|
||||
e.preventDefault()
|
||||
addNote()
|
||||
break
|
||||
}
|
||||
|
||||
e.cancelBubble = true
|
||||
if (e.stopPropogation) {
|
||||
e.stopPropogation()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -420,6 +422,11 @@
|
||||
}
|
||||
|
||||
function labelKeyDown(event) {
|
||||
event.cancelBubble = true
|
||||
if (event.stopPropogation) {
|
||||
event.stopPropogation()
|
||||
}
|
||||
|
||||
switch (event.key.toLowerCase()) {
|
||||
case 'arrowup': {
|
||||
if (
|
||||
@ -485,9 +492,37 @@
|
||||
function addNote() {
|
||||
cancelAutoDismiss()
|
||||
toggleRow('#omnivore-add-note-row')
|
||||
currentToastEl.shadowRoot
|
||||
.querySelector('#omnivore-add-note-textarea')
|
||||
?.focus()
|
||||
|
||||
const noteArea = currentToastEl.shadowRoot.querySelector(
|
||||
'#omnivore-add-note-textarea'
|
||||
)
|
||||
|
||||
if (noteArea) {
|
||||
noteArea.focus()
|
||||
|
||||
noteArea.onkeydown = (e) => {
|
||||
e.cancelBubble = true
|
||||
if (e.stopPropogation) {
|
||||
e.stopPropogation()
|
||||
}
|
||||
// Handle the enter key
|
||||
if (e.keyCode == 13 && (e.metaKey || e.ctrlKey)) {
|
||||
updateStatusBox(
|
||||
'#omnivore-add-note-status',
|
||||
'loading',
|
||||
'Adding note...'
|
||||
)
|
||||
|
||||
browserApi.runtime.sendMessage({
|
||||
action: ACTIONS.AddNote,
|
||||
payload: {
|
||||
ctx: ctx,
|
||||
note: noteArea.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentToastEl.shadowRoot.querySelector(
|
||||
'#omnivore-add-note-form'
|
||||
@ -504,17 +539,28 @@
|
||||
})
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropogation()
|
||||
}
|
||||
}
|
||||
|
||||
function editTitle() {
|
||||
console.log('editing title')
|
||||
|
||||
cancelAutoDismiss()
|
||||
toggleRow('#omnivore-edit-title-row')
|
||||
currentToastEl.shadowRoot
|
||||
.querySelector('#omnivore-edit-title-textarea')
|
||||
?.focus()
|
||||
|
||||
const titleArea = currentToastEl.shadowRoot.querySelector(
|
||||
'#omnivore-edit-title-textarea'
|
||||
)
|
||||
|
||||
if (titleArea) {
|
||||
titleArea.focus()
|
||||
|
||||
titleArea.onkeydown = (e) => {
|
||||
e.cancelBubble = true
|
||||
if (e.stopPropogation) {
|
||||
e.stopPropogation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentToastEl.shadowRoot.querySelector(
|
||||
'#omnivore-edit-title-form'
|
||||
|
||||