Add theme-and-state-adaptive icons, fixes #29
This commit is contained in:
parent
c36d9e9996
commit
5dafbbc59c
|
@ -0,0 +1,82 @@
|
|||
let colorScheme = "light";
|
||||
let state = "neutral";
|
||||
|
||||
/* Update the extension's icon by color scheme and state */
|
||||
function updateIcon(event) {
|
||||
browser.action.setIcon({
|
||||
path: {
|
||||
16: "icons/" + colorScheme + "-state-" + state + "-16x.png",
|
||||
32: "icons/" + colorScheme + "-state-" + state + "-32x.png",
|
||||
48: "icons/" + colorScheme + "-state-" + state + "-48x.png",
|
||||
64: "icons/" + colorScheme + "-state-" + state + "-64x.png",
|
||||
96: "icons/" + colorScheme + "-state-" + state + "-96x.png",
|
||||
128: "icons/" + colorScheme + "-state-" + state + "-128x.png"
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/* Listen for color scheme changes */
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateColorScheme);
|
||||
|
||||
/* Update the color scheme to light or dark */
|
||||
function updateColorScheme(event) {
|
||||
const isDark = event.matches;
|
||||
if (isDark) {
|
||||
colorScheme = "dark";
|
||||
} else {
|
||||
colorScheme = "light";
|
||||
}
|
||||
|
||||
updateIcon();
|
||||
}
|
||||
|
||||
/* Listen for tab changes */
|
||||
window.addEventListener("load", updateState());
|
||||
browser.tabs.onUpdated.addListener(updateStateOnReload, {urls: ["*://*/*"]});
|
||||
browser.tabs.onActivated.addListener(updateState);
|
||||
|
||||
/* Update whether the extension is enabled for a host */
|
||||
function updateState() {
|
||||
let tabs = browser.tabs.query({ active: true, currentWindow: true });
|
||||
tabs.then((tabs) => {
|
||||
const tab = tabs[0];
|
||||
const url = new URL(tab.url);
|
||||
const isAllowedProtocol = url.protocol == "https:" || url.protocol == "http:";
|
||||
|
||||
if (!isAllowedProtocol) {
|
||||
state = "neutral";
|
||||
updateIcon();
|
||||
return;
|
||||
}
|
||||
|
||||
let storage = browser.storage.local.get("domains");
|
||||
storage.then((storage) => {
|
||||
const hostname = url.host;
|
||||
const domains = storage.domains;
|
||||
if (domains === undefined) {
|
||||
state = "disabled";
|
||||
}
|
||||
else if (domains.includes(hostname)) {
|
||||
state = "enabled";
|
||||
} else {
|
||||
state = "disabled";
|
||||
}
|
||||
}, logError).then(() => {
|
||||
updateIcon();
|
||||
}, logError);
|
||||
}, logError);
|
||||
}
|
||||
|
||||
/* Only update the state if the page was reloaded */
|
||||
function updateStateOnReload(tabIs, changeInfo, tab) {
|
||||
if (changeInfo.url && tab.url.host === changeInfo.url.host) {
|
||||
return;
|
||||
} else {
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
|
||||
/* Required by then */
|
||||
function logError(error) {
|
||||
console.log(`Error: ${error}`);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "MetamorPOV",
|
||||
"author": "Jean Viscogliosi-Pate",
|
||||
"version": "1.3.0",
|
||||
|
||||
"description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.",
|
||||
|
||||
"action": {
|
||||
"default_title": "MetamorPOV",
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "icons/light-state-neutral-16x.png",
|
||||
"32": "icons/light-state-neutral-32x.png",
|
||||
"48": "icons/light-state-neutral-48x.png",
|
||||
"64": "icons/light-state-neutral-64x.png",
|
||||
"96": "icons/light-state-neutral-96x.png",
|
||||
"128": "icons/light-state-neutral-128x.png"
|
||||
}
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"storage",
|
||||
"tabs",
|
||||
"offscreen"
|
||||
],
|
||||
|
||||
"host_permissions": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
|
||||
"icons": {
|
||||
"16": "icons/light-state-neutral-16x.png",
|
||||
"32": "icons/light-state-neutral-32x.png",
|
||||
"48": "icons/light-state-neutral-48x.png",
|
||||
"64": "icons/light-state-neutral-64x.png",
|
||||
"96": "icons/light-state-neutral-96x.png",
|
||||
"128": "icons/light-state-neutral-128x.png"
|
||||
},
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"js": [
|
||||
"content-script.js"
|
||||
],
|
||||
"run_at": "document_idle",
|
||||
"matches": [
|
||||
"*://*/*"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"background": {
|
||||
"service_worker": "service-worker.js",
|
||||
"type": "module"
|
||||
},
|
||||
|
||||
"homepage_url": "https://git.viscogliosi-pate.com/jean/metamorpov"
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "MetamorPOV",
|
||||
"author": "Jean Viscogliosi-Pate",
|
||||
"version": "1.3.0",
|
||||
|
||||
"description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.",
|
||||
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "metamorpov@viscogliosi-pate.com",
|
||||
"strict_min_version": "113.0"
|
||||
},
|
||||
"gecko_android": {}
|
||||
},
|
||||
|
||||
"action": {
|
||||
"default_title": "MetamorPOV",
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "icons/light-state-neutral-16x.png",
|
||||
"32": "icons/light-state-neutral-32x.png",
|
||||
"48": "icons/light-state-neutral-48x.png",
|
||||
"64": "icons/light-state-neutral-64x.png",
|
||||
"96": "icons/light-state-neutral-96x.png",
|
||||
"128": "icons/light-state-neutral-128x.png"
|
||||
},
|
||||
"theme_icons": [{
|
||||
"light": "icons/light-state-neutral-16x.png",
|
||||
"dark": "icons/dark-state-neutral-16x.png",
|
||||
"size": 16
|
||||
}, {
|
||||
"light": "icons/light-state-neutral-32x.png",
|
||||
"dark": "icons/dark-state-neutral-32x.png",
|
||||
"size": 32
|
||||
}, {
|
||||
"light": "icons/light-state-neutral-48x.png",
|
||||
"dark": "icons/dark-state-neutral-48x.png",
|
||||
"size": 48
|
||||
}, {
|
||||
"light": "icons/light-state-neutral-64x.png",
|
||||
"dark": "icons/dark-state-neutral-64x.png",
|
||||
"size": 64
|
||||
}, {
|
||||
"light": "icons/light-state-neutral-96x.png",
|
||||
"dark": "icons/dark-state-neutral-96x.png",
|
||||
"size": 96
|
||||
}, {
|
||||
"light": "icons/light-state-neutral-128x.png",
|
||||
"dark": "icons/dark-state-neutral-128x.png",
|
||||
"size": 128
|
||||
}]
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"storage",
|
||||
"tabs"
|
||||
],
|
||||
|
||||
"host_permissions": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
|
||||
"icons": {
|
||||
"16": "icons/light-state-neutral-16x.png",
|
||||
"32": "icons/light-state-neutral-32x.png",
|
||||
"48": "icons/light-state-neutral-48x.png",
|
||||
"64": "icons/light-state-neutral-64x.png",
|
||||
"96": "icons/light-state-neutral-96x.png",
|
||||
"128": "icons/light-state-neutral-128x.png"
|
||||
},
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"js": [
|
||||
"content-script.js"
|
||||
],
|
||||
"run_at": "document_idle",
|
||||
"matches": [
|
||||
"*://*/*"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"background": {
|
||||
"scripts": [
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
|
||||
"homepage_url": "https://git.viscogliosi-pate.com/jean/metamorpov"
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "MetamorPOV",
|
||||
"author": "Jean Viscogliosi-Pate",
|
||||
"version": "1.2.0",
|
||||
|
||||
"description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.",
|
||||
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "metamorpov@viscogliosi-pate.com",
|
||||
"strict_min_version": "113.0"
|
||||
},
|
||||
"gecko_android": {}
|
||||
},
|
||||
|
||||
"action": {
|
||||
"default_title": "MetamorPOV",
|
||||
"default_icon": {
|
||||
"16": "icons/16x.png",
|
||||
"32": "icons/32x.png",
|
||||
"48": "icons/48x.png",
|
||||
"64": "icons/64x.png",
|
||||
"96": "icons/96x.png",
|
||||
"128": "icons/128x.png"
|
||||
},
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"storage",
|
||||
"tabs"
|
||||
],
|
||||
|
||||
"host_permissions": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
|
||||
"icons": {
|
||||
"16": "icons/16x.png",
|
||||
"32": "icons/32x.png",
|
||||
"48": "icons/48x.png",
|
||||
"64": "icons/64x.png",
|
||||
"96": "icons/96x.png",
|
||||
"128": "icons/128x.png"
|
||||
},
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"js": [
|
||||
"content-script.js"
|
||||
],
|
||||
"run_at": "document_idle",
|
||||
"matches": [
|
||||
"*://*/*"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"homepage_url": "https://git.viscogliosi-pate.com/jean/metamorpov"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<script src="service-worker-window.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
/* Broadcast color scheme on browser start, because no change event is fired */
|
||||
updateColorScheme(window.matchMedia('(prefers-color-scheme: dark)'));
|
||||
|
||||
function updateColorScheme(event) {
|
||||
console.log("doing!");
|
||||
chrome.runtime.sendMessage({
|
||||
content: "colorScheme",
|
||||
isDark: event.matches
|
||||
});
|
||||
}
|
||||
|
||||
/* Broadcast when page is loaded */
|
||||
window.addEventListener("load", updateState);
|
||||
|
||||
function updateState() {
|
||||
chrome.runtime.sendMessage({
|
||||
content: "updateState"
|
||||
});
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
let colorScheme = "light";
|
||||
let state = "neutral";
|
||||
|
||||
/* Update the extension's icon by color scheme and state */
|
||||
function updateIcon(event) {
|
||||
chrome.action.setIcon({
|
||||
path: {
|
||||
16: "icons/" + colorScheme + "-state-" + state + "-16x.png",
|
||||
32: "icons/" + colorScheme + "-state-" + state + "-32x.png",
|
||||
48: "icons/" + colorScheme + "-state-" + state + "-48x.png",
|
||||
64: "icons/" + colorScheme + "-state-" + state + "-64x.png",
|
||||
96: "icons/" + colorScheme + "-state-" + state + "-96x.png",
|
||||
128: "icons/" + colorScheme + "-state-" + state + "-128x.png"
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/* Track CSS media feature offscreen */
|
||||
chrome.offscreen.createDocument({
|
||||
url: "service-worker-window.html",
|
||||
reasons: ["MATCH_MEDIA"],
|
||||
justification: "Update icon by color scheme",
|
||||
})
|
||||
|
||||
/* Listen for color scheme changes */
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function(request, sender, sendResponse) {
|
||||
if (request.content === "colorScheme") {
|
||||
updateColorScheme(request.isDark);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/* Update the color scheme to light or dark */
|
||||
function updateColorScheme(isDark) {
|
||||
if (isDark) {
|
||||
colorScheme = "dark";
|
||||
} else {
|
||||
colorScheme = "light";
|
||||
}
|
||||
|
||||
updateIcon();
|
||||
}
|
||||
|
||||
/* Listen for tab changes */
|
||||
chrome.tabs.onUpdated.addListener(updateStateOnReload);
|
||||
chrome.tabs.onActivated.addListener(updateState);
|
||||
|
||||
/* Update whether the extension is enabled for a host */
|
||||
function updateState() {
|
||||
let tabs = chrome.tabs.query({ active: true, currentWindow: true });
|
||||
tabs.then((tabs) => {
|
||||
const tab = tabs[0];
|
||||
if (tab.url === "") {
|
||||
state = "neutral";
|
||||
updateIcon();
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(tab.url);
|
||||
const isAllowedProtocol = url.protocol == "https:" || url.protocol == "http:";
|
||||
|
||||
if (!isAllowedProtocol) {
|
||||
state = "neutral";
|
||||
updateIcon();
|
||||
return;
|
||||
}
|
||||
|
||||
let storage = chrome.storage.local.get("domains");
|
||||
storage.then((storage) => {
|
||||
const hostname = url.host;
|
||||
const domains = storage.domains;
|
||||
if (domains === undefined) {
|
||||
state = "disabled";
|
||||
}
|
||||
else if (domains.includes(hostname)) {
|
||||
state = "enabled";
|
||||
} else {
|
||||
state = "disabled";
|
||||
}
|
||||
}, logError).then(() => {
|
||||
updateIcon();
|
||||
}, logError);
|
||||
}, logError);
|
||||
}
|
||||
|
||||
/* Only update the state if the page was reloaded */
|
||||
function updateStateOnReload(tabIs, changeInfo, tab) {
|
||||
if (changeInfo.url && tab.url.host === changeInfo.url.host) {
|
||||
return;
|
||||
} else {
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
|
||||
/* Required by then */
|
||||
function logError(error) {
|
||||
console.log(`Error: ${error}`);
|
||||
}
|
Loading…
Reference in New Issue