From 25de42b829a1a84c7932335d11b2845d84877508 Mon Sep 17 00:00:00 2001 From: Stijn Peeters Date: Thu, 10 Oct 2024 10:30:15 +0200 Subject: [PATCH] Popup with autoscroll feature --- js/zs-background.js | 14 +++- js/zs-scroller.js | 15 ++++ manifest.json | 14 +++- popup/interface.html | 74 +--------------- popup/interface.js | 68 +++------------ popup/lib.js | 65 ++++++++++++++ popup/popup.html | 196 +++++++++++++++++++++++++++++++++++++++++++ popup/popup.js | 85 +++++++++++++++++++ popup/style.css | 91 ++++++++++++++++++++ popup/tooltips.js | 12 +-- 10 files changed, 496 insertions(+), 138 deletions(-) create mode 100644 js/zs-scroller.js create mode 100644 popup/lib.js create mode 100644 popup/popup.html create mode 100644 popup/popup.js create mode 100644 popup/style.css diff --git a/js/zs-background.js b/js/zs-background.js index 54f6d9a..7423314 100644 --- a/js/zs-background.js +++ b/js/zs-background.js @@ -60,6 +60,17 @@ window.zeeschuimer = { let path = enabled.length > 0 ? 'images/zeeschuimer-icon-active.png' : 'images/zeeschuimer-icon-inactive.png'; browser.browserAction.setIcon({path: path}) }, 500); + + setInterval(async function () { + let scroll_speed = await browser.storage.local.get(['scroll-speed']) + scroll_speed = scroll_speed.hasOwnProperty('scroll-speed') ? parseInt(scroll_speed['scroll-speed']) : 0; + + if(!scroll_speed) { + return; + } + + window.scrollBy(0, scroll_speed * 10); + }, 100); }, /** @@ -231,7 +242,7 @@ browser.webRequest.onBeforeRequest.addListener( browser.webNavigation.onCommitted.addListener( zeeschuimer.nav_handler ); - +/* browser.browserAction.onClicked.addListener(async () => { let tab = await zeeschuimer.has_tab(); if (!tab) { @@ -240,3 +251,4 @@ browser.browserAction.onClicked.addListener(async () => { browser.tabs.update(tab.id, {active: true}); } }); +*/ \ No newline at end of file diff --git a/js/zs-scroller.js b/js/zs-scroller.js new file mode 100644 index 0000000..c0b204a --- /dev/null +++ b/js/zs-scroller.js @@ -0,0 +1,15 @@ +let interval = null; + +async function handleMessage(request, sender, sendResponse) { + clearInterval(interval); + if(request.speed) { + interval = setInterval(function () { + if(window.scrollY < window.scrollMaxY) { + window.scrollBy(0, request.speed * 5); + } + }, 5); + } +} + +// Assign handleMessages as listener for messages from the extension. +browser.runtime.onMessage.addListener(handleMessage); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 1944ed7..0a0d219 100644 --- a/manifest.json +++ b/manifest.json @@ -19,9 +19,21 @@ "browser_action": { "default_icon": "images/zeeschuimer-64.png", - "default_title": "Zeeschuimer Status" + "default_title": "Zeeschuimer Status", + "default_popup": "popup/popup.html" }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "js/zs-scroller.js" + ] + } + ], + "permissions": [ "webRequest", "webRequestBlocking", "webNavigation", "", "storage", "downloads", "activeTab", "tabs", "unlimitedStorage" diff --git a/popup/interface.html b/popup/interface.html index 2f4b794..c84b215 100644 --- a/popup/interface.html +++ b/popup/interface.html @@ -8,71 +8,8 @@ + + + +
+ +

Zeeschuimer

+ Manage data +
+
+
+
    +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/popup/popup.js b/popup/popup.js new file mode 100644 index 0000000..56ac11e --- /dev/null +++ b/popup/popup.js @@ -0,0 +1,85 @@ +let platform_map = []; + +/** + * Get Zeeschuimer stats + * + * Loads the amount of items collected, etc. This function is called + * periodically to keep the numbers in the interface updated as items are + * coming in. + * + * @returns {Promise} + */ +async function get_modules() { + let response = {}; + Object.keys(background.zeeschuimer.modules).forEach(function(platform) { platform_map[platform] = background.zeeschuimer.modules[platform].name; }); + for (let module in background.zeeschuimer.modules) { + response[module] = await background.db.items.where("source_platform").equals(module).count(); + } + for (const platform in response) { + const css_platform = platform.replace(/\./g, ''); + const toggle_field = `zs-enabled-${platform}`; + const icon_id = `#platform-${css_platform}`; + const num_items = new Intl.NumberFormat().format(response[platform]); + let enabled = await background.browser.storage.local.get([toggle_field]) + enabled = enabled.hasOwnProperty(toggle_field) && !!parseInt(enabled[toggle_field]); + + if (document.querySelector(icon_id)) { + const icon = document.querySelector(icon_id); + icon.querySelector('.num-badge').innerText = num_items; + icon.querySelector('.num-badge').setAttribute('data-num', response[platform]) + icon.setAttribute('data-enabled', enabled ? '1': '0'); + } else { + const icon = createElement('li', {'id': `platform-${css_platform}`, 'class': 'platform-icon'}, createElement('img', { + 'class': 'tooltippable', + 'title': platform_map[platform], + 'src': '/images/platform-icons/' + platform.split('.')[0].split('-')[0] + '.png', + 'alt': platform_map[platform], + 'name': toggle_field, + })); + icon.appendChild(createElement('span', {'class': 'num-badge', 'data-num': response[platform]}, num_items)); + icon.addEventListener('click', toggle_listening); + icon.setAttribute('data-enabled', enabled ? '1' : '0'); + document.querySelector('#platform-list ol').appendChild(icon); + } + } + + init_tooltips(); +} + +async function trigger_scroll() { + let scroll_speed = await background.browser.storage.local.get(['scroll-speed']) + scroll_speed = scroll_speed.hasOwnProperty('scroll-speed') ? parseInt(scroll_speed['scroll-speed']) : 0; + + browser.tabs.query({ + currentWindow: true, + active: true + }).then(tabs => tabs.forEach(tab => tab && browser.tabs.sendMessage(tab.id + , {speed: scroll_speed}))); +} + +async function update_autoscroll(e = null) { + let scroll_speed = e ? e.target.value : 0; + await background.browser.storage.local.set({['scroll-speed']: String(scroll_speed)}); + return scroll_speed; +} + + +document.addEventListener('DOMContentLoaded', async function () { + get_modules(); + setInterval(get_modules, 1000); + + document.getElementById('interface-opener').onclick = async () => { + let tab = await background.zeeschuimer.has_tab(); + if (!tab) { + browser.tabs.create({url: 'interface.html'}); + } else if (!tab.active) { + browser.tabs.update(tab.id, {active: true}); + } + }; + + const scroll_speed = await update_autoscroll(); + document.querySelector('#autoscroll input').value = scroll_speed; + document.querySelector('#autoscroll input').addEventListener('change', update_autoscroll); + + setInterval(trigger_scroll, 100); +}); \ No newline at end of file diff --git a/popup/style.css b/popup/style.css new file mode 100644 index 0000000..27b310b --- /dev/null +++ b/popup/style.css @@ -0,0 +1,91 @@ +:root { + --neutral: #d9c398; + --neutral-contrast: #3C3C3B; + --neutral-contrast-alt: #5d6c4c; + --accent-alt: #b45d3d; + --accent: #e0ba5f; +} + +*[aria-hidden=true] { + display: none; +} + +*[aria-hidden=false] { + display: auto; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +@font-face { + font-family: 'Open Sans'; + src: url("../fonts/OpenSans-Regular.ttf") +} + +@font-face { + font-family: 'Open Sans'; + font-weight: bold; + src: url("../fonts/OpenSans-Bold.ttf") +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + src: url("../fonts/OpenSans-Italic.ttf") +} + +@font-face { + font-family: 'Open Sans'; + font-weight: bold; + font-style: italic; + src: url("../fonts/OpenSans-BoldItalic.ttf") +} + +@font-face { + font-family: 'Lobster Two'; + src: url("../fonts/LobsterTwo-Regular.ttf") +} + +@font-face { + font-family: 'Lobster Two'; + font-weight: bold; + src: url("../fonts/LobsterTwo-Bold.ttf") +} + +@font-face { + font-family: 'Lobster Two'; + font-style: italic; + src: url("../fonts/LobsterTwo-Italic.ttf") +} + +@font-face { + font-family: 'Lobster Two'; + font-weight: bold; + font-style: italic; + src: url("../fonts/LobsterTwo-BoldItalic.ttf") +} + +body { + font-family: 'Open Sans', sans-serif; + color: var(--neutral-contrast); + margin: 0 auto; + background: var(--neutral); +} + +.platform-icon img { + filter: grayscale(1) contrast(0.5); + transition: .2s; + border-radius: 0.2em; +} + +*[data-enabled='1'] .platform-icon img, .platform-icon[data-enabled='1'] img { + filter: grayscale(0) contrast(1); +} \ No newline at end of file diff --git a/popup/tooltips.js b/popup/tooltips.js index 15551c4..9917e3e 100644 --- a/popup/tooltips.js +++ b/popup/tooltips.js @@ -46,11 +46,11 @@ const init_tooltips = function() { var title = this.getAttribute('title'); if (title && title != '' && title != null && title != 'null') { - var pos = this.getBoundingClientRect(); - var bpos = document.body.getBoundingClientRect(); + const pos = this.getBoundingClientRect(); + const bpos = document.body.getBoundingClientRect(); - var tooltip = $_('#tooltip') - var up = this.classList.contains('points-up'); + const tooltip = $_('#tooltip') + const up = this.classList.contains('points-up'); this.setAttribute('data-title-content', title); this.removeAttribute('title'); @@ -61,8 +61,8 @@ const init_tooltips = function() { tooltip.style.visibility = 'hidden'; tooltip.style.display = 'block'; - var pos_x = pos.left - (tooltip.offsetWidth / 2) + (this.offsetWidth / 2) - 1; - var pos_y; + let pos_x = pos.left - (tooltip.offsetWidth / 2) + (this.offsetWidth / 2) - 1; + let pos_y; if (up) { tooltip.classList.add('up'); tooltip.classList.remove('down');