Skip to content

Commit

Permalink
feat: Standalone options page; streamline help (#327)
Browse files Browse the repository at this point in the history
* Move to a stand-alone options page on all browsers (taking some inspiration from  #157).
* Streamline the content of the Help page.
* Streamline styles.

Closes #227. Fixes #288. Closes #226.
  • Loading branch information
matatk authored Feb 2, 2020
1 parent 8bc2e91 commit 4aa2b60
Show file tree
Hide file tree
Showing 20 changed files with 2,298 additions and 588 deletions.
6 changes: 6 additions & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": "tab"
}
}
1,824 changes: 1,799 additions & 25 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
"profile-guarding": "node scripts/profile-guarding.js",
"start:firefox": "web-ext run --browser-console --source-dir build/firefox/",
"pretest": "eslint .",
"test": "npm run test:landmarks && npm run test:contrast && npm run test:migration-manager",
"test": "npm run test:landmarks && npm run test:contrast && npm run test:migration-manager && npm run test:css",
"pretest:contrast": "rollup src/code/contrastChecker.js -f cjs > test/test-code-in-harness-contrast.js",
"test:contrast": "node test/test-contrast.js",
"test:css": "npx stylelint --config .stylelintrc.json src/**/*.css",
"pretest:landmarks": "rollup src/code/landmarksFinder.js -f cjs > test/test-code-in-harness-landmarks.js",
"test:landmarks": "node test/test-landmarks.js",
"pretest:migration-manager": "rollup src/code/migrationManager.js -f cjs > test/test-code-in-harness-migration-manager.js",
Expand Down Expand Up @@ -42,6 +43,8 @@
"rollup-plugin-esformatter": "~0.7",
"rollup-plugin-terser": "~4.0",
"stats-lite": "~2.2",
"stylelint": "^13.0.0",
"stylelint-config-standard": "^19.0.0",
"test": "~0.6",
"yargs": "~13.2"
}
Expand Down
2 changes: 1 addition & 1 deletion src/assemble/manifest.chrome.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},

"options_ui": {
"chrome_style": true
"chrome_style": false
},

"permissions": ["<all_urls>"]
Expand Down
3 changes: 2 additions & 1 deletion src/assemble/manifest.common.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
},

"options_ui": {
"page": "options.html"
"page": "options.html",
"open_in_tab": true
},

"browser_action": {
Expand Down
2 changes: 1 addition & 1 deletion src/assemble/manifest.firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},

"options_ui": {
"browser_style": true
"browser_style": false
},

"applications": {
Expand Down
2 changes: 1 addition & 1 deletion src/assemble/manifest.opera.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},

"options_ui": {
"chrome_style": true
"chrome_style": false
},

"minimum_opera_version": "57",
Expand Down
2 changes: 1 addition & 1 deletion src/assemble/messages.common.en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
},

"prefsBorderType": {
"message": "Border type:"
"message": "Border type"
},

"prefsMomentary": {
Expand Down
4 changes: 2 additions & 2 deletions src/assemble/messages.interface.en_GB.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"prefsInterface": {
"message": "Show landmarks in:"
"message": "Show landmarks in"
},

"prefsPopup": {
Expand Down Expand Up @@ -38,7 +38,7 @@
},

"hintSidebarIsNotPrimaryOptions": {
"message": "Change options"
"message": "Change preferences"
},

"hintDismiss": {
Expand Down
220 changes: 22 additions & 198 deletions src/code/_help.js
Original file line number Diff line number Diff line change
@@ -1,235 +1,59 @@
let shortcutNotSet = false
import handlePopulateCommandsMessage from './keyboardShortcutTableMaker'

const shortcutTableRows = [
{
element: 'tr',
contains: [
{ element: 'th', content: 'Action' },
{ element: 'th', content: 'Keyboard shortcut' }
]
}
]

function makeLink(description, messageName) {
return {
element: 'a',
class: 'configAction',
tabindex: 0,
content: description,
listen: [{
event: 'click',
handler: () => browser.runtime.sendMessage({ name: messageName })
}, {
event: 'keydown',
handler: (event) => {
if (event.key === 'Enter') {
browser.runtime.sendMessage({ name: messageName })
}
}
}]
}
}

const keyboardShortcutsLink = makeLink(
'Add or change shortcuts',
'open-configure-shortcuts')

const settingsLink = makeLink(
'Change preferences (opens in new tab)',
'open-settings')

function makeHTML(structure, root) {
let newElement

for (const key in structure) {
switch (key) {
case 'element':
newElement = document.createElement(structure[key])
root.appendChild(newElement)
break
case 'class':
newElement.classList.add(structure[key])
break
case 'tabindex':
newElement.setAttribute('tabindex', String(structure[key]))
break
case 'text':
root.appendChild(document.createTextNode(structure[key]))
break
case 'content':
newElement.appendChild(document.createTextNode(structure[key]))
break
case 'listen':
for (const eventHandler of structure[key]) {
newElement.addEventListener(
eventHandler.event, eventHandler.handler)
}
break
case 'contains':
for (const contained of structure[key]) {
makeHTML(contained, newElement ? newElement : root)
}
break
default:
throw Error(`Unexpected structure key ${key} encountered.`)
}
}

return root
}

function addCommandRowAndReportIfMissing(command) {
// Work out the command's friendly name
const action = command.name === '_execute_browser_action'
? 'Show pop-up'
: command.description

// Work out the command's shortcut
let shortcutCellElement

if (command.shortcut) {
// Firefox gives "Alt+Shift+N" but Chrome gives ⌥⇧N
if (BROWSER === 'chrome' || BROWSER === 'opera') {
shortcutCellElement = { element: 'td', contains: [
{ element: 'kbd', content: command.shortcut }
]}
} else {
shortcutCellElement = { element: 'td', contains:
firefoxShortcutElements(command.shortcut)
}
}
} else {
shortcutCellElement = { element: 'td', class: 'errorItem', contains: [
{ text: 'Not set up' }
]}
shortcutNotSet = true
}

shortcutTableRows.push({
element: 'tr',
contains: [
{ element: 'td', content: action },
shortcutCellElement
]
})
}

function firefoxShortcutElements(shortcut) {
const shortcutElements = []
const shortcutParts = shortcut.split(/(\+)/)

for (const keyOrPlus of shortcutParts) {
if (keyOrPlus !== '+') {
shortcutElements.push({ element: 'kbd', content: keyOrPlus })
} else {
shortcutElements.push({ text: ' + ' })
}
}

return shortcutElements
}

function messageHandler(message) { // also sender, sendResponse
function messageHandler(message) {
if (message.name !== 'populate-commands') return

// Chrome allows only four keyboard shortcuts to be specified in the
// manifest; Firefox allows many.
//
// The extra ones for Firefox are patched in via its specific manifest file
// when the manifest is merged.
//
// The commands are in the manifest in the opposite order to that which
// seems most logical, and need to be reversed to pop out in the right
// order on the splash page. This is because the merging in of the extra
// keyboard shortcuts means that the commands with added keyboard shortucts
// in Firefox are bumped to the top of the commands object.
//
// What is a bit odd is that, on Chrome, it appears the reversal is not
// needed.
const commandsInOrder = (BROWSER === 'chrome' || BROWSER === 'opera') ?
message.commands : message.commands.reverse()

for (const command of commandsInOrder) {
addCommandRowAndReportIfMissing(command)
}

makeHTML({ element: 'table', contains: shortcutTableRows },
document.getElementById('keyboard-shortcuts-table'))

if (shortcutNotSet) {
document.querySelector('#section-keyboard-navigation summary')
.classList.add('errorItem')
const allShortcutsAreSet = handlePopulateCommandsMessage(
message, 'keyboard-shortcuts-table')

document.querySelector('[data-link="shortcuts"] a')
.classList.add('errorAction')
document.getElementById('warning-shortcuts').hidden = allShortcutsAreSet

for (const warning of document.querySelectorAll('[data-warning]')) {
warning.style.display = 'block'
}

document.getElementById('symbol').style.display = 'inline'
if (!allShortcutsAreSet) {
document.getElementById('section-keyboard-shortcuts-heading')
.classList.add('missing-shortcut')
}
}

function makeConfigLinks(type, template) {
for (const element of document.querySelectorAll(`[data-link="${type}"`)) {
makeHTML(template, element)
}
}

function makeSettingsAndShortcutsLinks() {
if (BROWSER === 'chrome' || BROWSER === 'opera') {
makeConfigLinks('shortcuts', keyboardShortcutsLink)
}

makeConfigLinks('settings', settingsLink)
}

function includeVersionNumber() {
const manifest = browser.runtime.getManifest()
const version = manifest.version
document.getElementById('version').innerText = version
}

function reflectInstallOrUpdate() {
// Move the appropriate section to the top
const fragment = window.location.hash.substr(2)
let sectionToMove = null

switch (fragment) {
case 'install':
document.getElementById('actions-update').remove()
sectionToMove = document.getElementById('section-features')
break
case 'update':
document.getElementById('actions-install').remove()
document.getElementById('section-new').open = true
sectionToMove = document.getElementById('section-new')
break
default:
// User opened the help page during normal use
document.getElementById('actions-install').remove()
document.getElementById('actions-update').remove()
}
}

function allowLinksToOpenSections() {
for (const link of document.querySelectorAll('a[href]')) {
if (link.getAttribute('href').startsWith('#')) {
link.onclick = function() {
document.querySelector(this.getAttribute('href')).open = true
}
}
if (sectionToMove) {
document.getElementById('placeholder').appendChild(sectionToMove)
}
}

function main() {
browser.runtime.onMessage.addListener(messageHandler)
browser.runtime.sendMessage({ name: 'get-commands' })

if (BROWSER !== 'firefox' && BROWSER !== 'opera') {
document.getElementById('section-sidebar').open = false
if (BROWSER === 'firefox') {
document.getElementById('open-browser-shortcuts-settings')
.parentElement.remove()
} else {
document.getElementById('open-browser-shortcuts-settings').addEventListener(
'click', () => browser.runtime.sendMessage({
name: 'open-configure-shortcuts' }))
}

makeSettingsAndShortcutsLinks()
includeVersionNumber()
reflectInstallOrUpdate()
allowLinksToOpenSections()
}

main()
Loading

0 comments on commit 4aa2b60

Please sign in to comment.