From 951499dba4ea173ba4c1f08b956e5d558999da45 Mon Sep 17 00:00:00 2001 From: Florrie Date: Fri, 22 Mar 2019 21:03:44 -0300 Subject: Popup UI --- extension/background.js | 24 +++---- extension/manifest.json | 4 +- extension/popup/index.html | 23 ++++++- extension/popup/main.js | 162 +++++++++++++++++++++++++++++++++++++++++++++ extension/popup/style.css | 110 ++++++++++++++++++++++++++++++ 5 files changed, 307 insertions(+), 16 deletions(-) create mode 100644 extension/popup/main.js create mode 100644 extension/popup/style.css (limited to 'extension') diff --git a/extension/background.js b/extension/background.js index 020a2be..9b7db26 100644 --- a/extension/background.js +++ b/extension/background.js @@ -26,18 +26,14 @@ port.onDisconnect.addListener(() => { }); browser.runtime.onMessage.addListener(({hostname}) => { - const map = { - 'scratch.mit.edu': ['mantis'], - 'stackoverflow.com': ['bass', 'main'], - 'www.youtube.com': [] - }; - - const mode = map[hostname]; - - if (mode) { - console.log('BGM:', mode); - port.postMessage(mode.map(track => ({track, volume: 100}))); - } else { - console.log('No BGM found for ' + location.hostname); - } + browser.storage.sync.get('siteSettings').then(({siteSettings}) => { + const mode = siteSettings[hostname]; + + if (mode) { + console.log('BGM:', mode); + port.postMessage(mode.map(track => ({track, volume: 100}))); + } else { + console.log('No BGM found for ' + hostname); + } + }); }); diff --git a/extension/manifest.json b/extension/manifest.json index 27cafda..d949ee5 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -7,7 +7,9 @@ "permissions": [ "activeTab", - "nativeMessaging" + "nativeMessaging", + "storage", + "tabs" ], "applications": { diff --git a/extension/popup/index.html b/extension/popup/index.html index e6cf5e5..9ddbec4 100644 --- a/extension/popup/index.html +++ b/extension/popup/index.html @@ -1 +1,22 @@ -

Nice.

+ + + + + Interactive BGM + + + +
+

Loading...

+
+
+

+

Tracks

+ +
+
+

Sorry, this page doesn't appear to have a hostname. We can't configure music here.

+
+ + + diff --git a/extension/popup/main.js b/extension/popup/main.js new file mode 100644 index 0000000..ad1475a --- /dev/null +++ b/extension/popup/main.js @@ -0,0 +1,162 @@ +function changeScreen(id) { + for (const screen of document.getElementsByClassName('screen')) { + if (screen.id === id) { + screen.classList.add('visible'); + } else { + screen.classList.remove('visible'); + } + } +} + +function loadTrackList(opts) { + const {hostname, siteSettings} = opts; + const site = siteSettings[hostname] || []; + return browser.storage.sync.get('tracks').then(({tracks = []}) => { + const ul = document.getElementById('track-list'); + while (ul.firstChild) { + ul.removeChild(ul.firstChild); + } + + tracks.sort(); + + for (const track of tracks) { + const li = document.createElement('li'); + ul.appendChild(li); + + li.classList.add('track'); + + const label = document.createElement('label'); + li.appendChild(label); + + const checkbox = document.createElement('input'); + label.appendChild(checkbox); + + checkbox.type = 'checkbox'; + checkbox.checked = site.includes(track); + checkbox.title = `Toggles whether the track "${track}" will play when this site is opened.` + + checkbox.addEventListener('click', () => { + if (checkbox.checked) { + if (!site.includes(track)) { + site.push(track); + } + } else { + if (site.includes(track)) { + site.splice(site.indexOf(track), 1); + } + } + + if (!siteSettings[hostname]) { + siteSettings[hostname] = site; + } + + disableButton.style.display = 'inline-block'; + + browser.storage.sync.set({siteSettings}) + .then(() => browser.runtime.sendMessage({hostname})); + }); + + label.appendChild(document.createTextNode(' ' + track)); + + const deleteButton = document.createElement('button'); + li.appendChild(deleteButton); + + deleteButton.appendChild(document.createTextNode('Delete...')); + deleteButton.title = `Deletes the track from all sites. You will be confirmed first.`; + + deleteButton.addEventListener('click', () => { + if (confirm(`This will delete "${track}" from ALL sites - this cannot be undone. Are you sure?`)) { + changeScreen('loading-screen'); + browser.storage.sync.set({tracks: tracks.filter(t => t !== track)}) + .then(() => loadTrackList(opts)) + .then(() => changeScreen('main-screen')); + } + }); + } + + const actionLi = document.createElement('li'); + ul.appendChild(actionLi); + + actionLi.classList.add('action'); + + const addButton = document.createElement('button'); + actionLi.appendChild(addButton); + + addButton.appendChild(document.createTextNode('Create Track')); + addButton.title = `Creates a new track, which will be an option present in all sites.`; + + let newTrackInput = null; + addButton.addEventListener('click', () => { + if (newTrackInput) { + newTrackInput.focus(); + return; + } + + const li = document.createElement('li'); + li.classList.add('track'); + ul.insertBefore(li, actionLi); + + newTrackInput = document.createElement('input'); + li.appendChild(newTrackInput); + + const saveButton = document.createElement('button'); + li.appendChild(saveButton); + + saveButton.appendChild(document.createTextNode('Save')); + + saveButton.addEventListener('click', () => { + while (li.firstChild) { + li.removeChild(li.firstChild); + } + li.appendChild(document.createTextNode('Saving...')); + + const name = newTrackInput.value.trim(); + if (name.length) { + changeScreen('loading-screen'); + browser.storage.sync.set({tracks: tracks.concat([name])}) + .then(() => loadTrackList(opts)) + .then(() => changeScreen('main-screen')); + } + }); + + newTrackInput.focus(); + }); + + const disableButton = document.createElement('button'); + actionLi.appendChild(disableButton); + + disableButton.appendChild(document.createTextNode('Disable Site')); + disableButton.title = `Removes the entry for this site altogether. It won't change BGM when you open it again.`; + + disableButton.addEventListener('click', () => { + changeScreen('loading-screen'); + delete siteSettings[hostname]; + browser.storage.sync.set({siteSettings}) + .then(() => loadTrackList(opts)) + .then(() => changeScreen('main-screen')); + }); + + if (!(hostname in siteSettings)) { + disableButton.style.display = 'none'; + } + }); +} + +Promise.all([ + browser.tabs.query({active: true, currentWindow: true}) + .then(([tab]) => { + const url = new URL(tab.url); + document.getElementById('hostname').appendChild(document.createTextNode(url.hostname)); + return url.hostname; + }), + browser.storage.sync.get('siteSettings') + .then(({siteSettings = {}}) => siteSettings) +]) + .then(([hostname, siteSettings]) => { + if (hostname) { + return loadTrackList({hostname, siteSettings}) + .then(() => changeScreen('main-screen')); + } else { + changeScreen('invalid-host-screen'); + } + }); diff --git a/extension/popup/style.css b/extension/popup/style.css new file mode 100644 index 0000000..147a94e --- /dev/null +++ b/extension/popup/style.css @@ -0,0 +1,110 @@ +body, html { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + min-width: 300px; + max-width: 400px; +} + +body { + background-color: #EEEEEE; + color: black; + font-family: Helvetica, Arial, sans-serif; +} + +label { + font-weight: 800; +} + +input[type=checkbox] { + width: 13px; + height: 13px; + padding: 0; + margin: 0; + position: relative; + top: 1px; +} + +input, button { + margin-right: 4px; + margin-left: 4px; +} + +ul { + margin: 4px 0; +} + +li { + padding: 3px; +} + +li:nth-child(even) { + background-color: white; +} + +li:nth-child(odd) { + background-color: #DDDDDD; +} + +h1 { + margin: 2px 0; + font-size: 1.2em; + text-align: center; +} + +h2 { + font-size: 0.9em; + margin: 2px 0; + text-align: center; + overflow: hidden; +} + +h2:before, h2:after { + background-color: black; + content: ''; + display: inline-block; + height: 1px; + position: relative; + vertical-align: middle; + width: 50%; +} + +h2:before { + right: 0.5em; + margin-left: -50%; +} + +h2:after { + left: 0.5em; + margin-right: -50%; +} + +.screen { + width: 100%; + height: 100%; + padding: 5px; + box-sizing: border-box; +} + +.screen:not(.visible) { + display: none; +} + +#loading-screen p, #invalid-host-screen { + text-align: center; + font-style: oblique; +} + +#track-list { + list-style: none; + padding-left: 0; +} + +#track-list li.track button { + float: right; +} + +#track-list li.action { + text-align: center; +} -- cgit 1.3.0-6-gf8a5