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