summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Federico Brigante <me@fregante.com> 2023-05-04 17:52:33 +0800
committerGravatar GitHub <noreply@github.com> 2023-05-04 09:52:33 +0000
commit0f0d7435a649466084fab40bb7fe0481b0c73dba (patch)
tree8f78f48062c8d2599a6850c3c74b18957108f44b
parentb3e7358daa453481574a796bd8b3c2238701a2bc (diff)
downloadrefined-github-0f0d7435a649466084fab40bb7fe0481b0c73dba.tar.gz
refined-github-0f0d7435a649466084fab40bb7fe0481b0c73dba.tar.zst
refined-github-0f0d7435a649466084fab40bb7fe0481b0c73dba.zip
Meta: Include information about storage in options (#6595)
-rw-r--r--package-lock.json61
-rw-r--r--package.json3
-rw-r--r--source/background.ts11
-rw-r--r--source/helpers/types.d.ts5
-rw-r--r--source/helpers/used-storage.ts10
-rw-r--r--source/options.css4
-rw-r--r--source/options.html7
-rw-r--r--source/options.tsx49
8 files changed, 103 insertions, 47 deletions
diff --git a/package-lock.json b/package-lock.json
index 789e7eec..962fdf42 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -32,6 +32,7 @@
"one-mutation": "^2.0.0",
"onetime": "^6.0.0",
"p-retry": "^5.1.2",
+ "pretty-bytes": "^6.1.0",
"push-form": "^1.0.1",
"regex-join": "^2.0.0",
"select-dom": "^7.1.1",
@@ -53,9 +54,9 @@
"devDependencies": {
"@sindresorhus/tsconfig": "^3.0.1",
"@types/codemirror": "^5.60.7",
- "@types/firefox-webext-browser": "^109.0.0",
"@types/jsdom": "^21.1.0",
"@types/react": "^17.0.52",
+ "@types/webextension-polyfill": "^0.10.0",
"copy-webpack-plugin": "^11.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.3",
@@ -893,12 +894,6 @@
"integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
"dev": true
},
- "node_modules/@types/firefox-webext-browser": {
- "version": "109.0.0",
- "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-109.0.0.tgz",
- "integrity": "sha512-tkEjBP/zZxaS5bv8MH/0kUs3WeUm8KU3Ew1B9BtQQdq5PwtG23SXvAbjxjMSQpoIzbxyWG4Yu4mi1uB2S8W7ng==",
- "dev": true
- },
"node_modules/@types/jsdom": {
"version": "21.1.0",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.0.tgz",
@@ -986,6 +981,12 @@
"integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
"dev": true
},
+ "node_modules/@types/webextension-polyfill": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz",
+ "integrity": "sha512-If4EcaHzYTqcbNMp/FdReVdRmLL/Te42ivnJII551bYjhX19bWem5m14FERCqdJA732OloGuxCRvLBvcMGsn4A==",
+ "dev": true
+ },
"node_modules/@vitest/expect": {
"version": "0.28.4",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.28.4.tgz",
@@ -7497,12 +7498,11 @@
}
},
"node_modules/pretty-bytes": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
- "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
- "dev": true,
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.0.tgz",
+ "integrity": "sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==",
"engines": {
- "node": ">=6"
+ "node": "^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -8362,6 +8362,18 @@
"node": ">=4"
}
},
+ "node_modules/size-plugin/node_modules/pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/size-plugin/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -11708,12 +11720,6 @@
"integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
"dev": true
},
- "@types/firefox-webext-browser": {
- "version": "109.0.0",
- "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-109.0.0.tgz",
- "integrity": "sha512-tkEjBP/zZxaS5bv8MH/0kUs3WeUm8KU3Ew1B9BtQQdq5PwtG23SXvAbjxjMSQpoIzbxyWG4Yu4mi1uB2S8W7ng==",
- "dev": true
- },
"@types/jsdom": {
"version": "21.1.0",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.0.tgz",
@@ -11801,6 +11807,12 @@
"integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
"dev": true
},
+ "@types/webextension-polyfill": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz",
+ "integrity": "sha512-If4EcaHzYTqcbNMp/FdReVdRmLL/Te42ivnJII551bYjhX19bWem5m14FERCqdJA732OloGuxCRvLBvcMGsn4A==",
+ "dev": true
+ },
"@vitest/expect": {
"version": "0.28.4",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.28.4.tgz",
@@ -16469,10 +16481,9 @@
}
},
"pretty-bytes": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
- "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
- "dev": true
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.0.tgz",
+ "integrity": "sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ=="
},
"pretty-format": {
"version": "27.5.1",
@@ -17097,6 +17108,12 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
+ "pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true
+ },
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
diff --git a/package.json b/package.json
index bc2deaf4..a25e8f11 100644
--- a/package.json
+++ b/package.json
@@ -68,6 +68,7 @@
"one-mutation": "^2.0.0",
"onetime": "^6.0.0",
"p-retry": "^5.1.2",
+ "pretty-bytes": "^6.1.0",
"push-form": "^1.0.1",
"regex-join": "^2.0.0",
"select-dom": "^7.1.1",
@@ -89,9 +90,9 @@
"devDependencies": {
"@sindresorhus/tsconfig": "^3.0.1",
"@types/codemirror": "^5.60.7",
- "@types/firefox-webext-browser": "^109.0.0",
"@types/jsdom": "^21.1.0",
"@types/react": "^17.0.52",
+ "@types/webextension-polyfill": "^0.10.0",
"copy-webpack-plugin": "^11.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.3",
diff --git a/source/background.ts b/source/background.ts
index 6d559273..e2ac0e04 100644
--- a/source/background.ts
+++ b/source/background.ts
@@ -1,3 +1,4 @@
+import {type Runtime} from 'webextension-polyfill';
import 'webext-dynamic-content-scripts';
import cache from 'webext-storage-cache'; // Also needed to regularly clear the cache
import {isSafari} from 'webext-detect-page';
@@ -7,6 +8,7 @@ import addDomainPermissionToggle from 'webext-domain-permission-toggle';
import optionsStorage, {isBrowserActionAPopup} from './options-storage';
import {getRghIssueUrl} from './helpers/rgh-issue-link';
import isDevelopmentVersion from './helpers/is-development-version';
+import getStorageBytesInUse from './helpers/used-storage';
// GHE support
addDomainPermissionToggle();
@@ -17,7 +19,7 @@ if (isBrowserActionAPopup) {
}
const messageHandlers = {
- openUrls(urls: string[], {tab}: browser.runtime.MessageSender) {
+ openUrls(urls: string[], {tab}: Runtime.MessageSender) {
for (const [i, url] of urls.entries()) {
void browser.tabs.create({
url,
@@ -26,7 +28,7 @@ const messageHandlers = {
});
}
},
- closeTab(_: any, {tab}: browser.runtime.MessageSender) {
+ closeTab(_: any, {tab}: Runtime.MessageSender) {
void browser.tabs.remove(tab!.id!);
},
async fetch(url: string) {
@@ -60,9 +62,8 @@ browser.browserAction.onClicked.addListener(async tab => {
async function hasUsedStorage(): Promise<boolean> {
return (
- await browser.storage.sync.getBytesInUse() > 0
- // Note: Not available in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1385832
- || Number(await browser.storage.local.getBytesInUse?.()) > 0
+ await getStorageBytesInUse('sync') > 0
+ || Number(await getStorageBytesInUse('local')) > 0
);
}
diff --git a/source/helpers/types.d.ts b/source/helpers/types.d.ts
index 06f4cb80..e3224b49 100644
--- a/source/helpers/types.d.ts
+++ b/source/helpers/types.d.ts
@@ -15,4 +15,9 @@ declare global {
closest<S extends string>(selector: S | readonly S[]): StrictlyParseSelector<S, HTMLElement> | null;
matches(selectors: string | readonly string[]): boolean;
}
+
+ // This cannot be a regular import because it turns `globals.d.ts` in a "module definition", which it isn't
+ type Browser = import('webextension-polyfill').Browser;
+ const browser: Browser;
+
}
diff --git a/source/helpers/used-storage.ts b/source/helpers/used-storage.ts
new file mode 100644
index 00000000..8a95bf18
--- /dev/null
+++ b/source/helpers/used-storage.ts
@@ -0,0 +1,10 @@
+/** `getBytesInUse` polyfill */
+export default async function getStorageBytesInUse(area: 'local' | 'sync'): Promise<any> {
+ const storage = browser.storage[area];
+ // From https://bugzilla.mozilla.org/show_bug.cgi?id=1385832#c20
+ return 'getBytesInUse' in storage ? storage.getBytesInUse() : new TextEncoder().encode(
+ Object.entries(await storage.get())
+ .map(([key, value]) => key + JSON.stringify(value))
+ .join(''),
+ ).length;
+}
diff --git a/source/options.css b/source/options.css
index c6b7972d..f8001c89 100644
--- a/source/options.css
+++ b/source/options.css
@@ -47,6 +47,10 @@ details {
margin-bottom: 1em;
}
+output {
+ font-style: italic;
+}
+
details[open] {
--border-left: 4px;
border-left: solid var(--border-left) #aaa4;
diff --git a/source/options.html b/source/options.html
index c5925a53..62fb6727 100644
--- a/source/options.html
+++ b/source/options.html
@@ -1,6 +1,7 @@
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<base target="_blank">
<title>Refined GitHub options</title>
<link rel="stylesheet" href="options.css">
<form id="options-form" class="detail-view-container">
@@ -41,6 +42,8 @@
<summary><strong>💅 Custom CSS</strong></summary>
<p>Like a userstyle, useful to undo unwanted style changes</p>
<p><textarea name="customCSS" rows="2" spellcheck="false"></textarea></p>
+ <p>CSS is limited to 100KB, after which the options <a href="https://github.com/fregante/webext-options-sync/issues/27">will stop being saved</a>.</p>
+ <p>Options storage: <output class="storage-sync">unknown</output></p>
</details>
<details id="action">
@@ -77,6 +80,10 @@
</label>
</p>
<p>
+ Options storage: <output class="storage-sync">unknown</output><br>
+ Cache storage: <output class="storage-local">unknown</output>
+ </p>
+ <p>
<button id="clear-cache">Clear cache</button>
</p>
diff --git a/source/options.tsx b/source/options.tsx
index 9a763615..2d8b56e5 100644
--- a/source/options.tsx
+++ b/source/options.tsx
@@ -5,16 +5,18 @@ import cache from 'webext-storage-cache';
import domify from 'doma';
import select from 'select-dom';
import fitTextarea from 'fit-textarea';
+import prettyBytes from 'pretty-bytes';
import {assertError} from 'ts-extras';
import * as indentTextarea from 'indent-textarea';
import delegate, {DelegateEvent} from 'delegate-it';
-import {isChrome, isFirefox, isSafari} from 'webext-detect-page';
+import {isChrome, isFirefox} from 'webext-detect-page';
import featureLink from './helpers/feature-link';
import clearCacheHandler from './helpers/clear-cache-handler';
import {getLocalHotfixes} from './helpers/hotfix';
import {createRghIssueLink} from './helpers/rgh-issue-link';
import {importedFeatures, featuresMeta} from '../readme.md';
+import getStorageBytesInUse from './helpers/used-storage';
import {isBrowserActionAPopup, perDomainOptions} from './options-storage';
type Status = {
@@ -74,6 +76,19 @@ function expandTokenSection(): void {
select('details#token')!.open = true;
}
+async function updateStorageUsage(area: 'sync' | 'local'): Promise<void> {
+ const storage = browser.storage[area];
+ const used = await getStorageBytesInUse(area);
+ const available = storage.QUOTA_BYTES - used;
+ for (const output of select.all(`.storage-${area}`)) {
+ output.textContent = available < 1000
+ ? 'FULL!'
+ : (available < 100_000
+ ? `Only ${prettyBytes(available)} available`
+ : `${prettyBytes(used)} used`);
+ }
+}
+
async function validateToken(): Promise<void> {
reportStatus({});
const tokenField = select('input[name="personalToken"]')!;
@@ -241,6 +256,15 @@ async function generateDom(): Promise<void> {
// Update rate link if necessary
updateRateLink();
+
+ // Update storage usage info
+ void updateStorageUsage('local');
+ void updateStorageUsage('sync');
+
+ // Hide non-applicable "Button link" section
+ if (isBrowserActionAPopup) {
+ select('#action')!.hidden = true;
+ }
}
function addEventListeners(): void {
@@ -260,6 +284,11 @@ function addEventListeners(): void {
location.reload();
});
+ // Update storage usage info
+ browser.storage.onChanged.addListener((_, areaName) => {
+ void updateStorageUsage(areaName as 'sync' | 'local');
+ });
+
// Improve textareas editing
fitTextarea.watch('textarea');
indentTextarea.watch('textarea');
@@ -281,19 +310,6 @@ function addEventListeners(): void {
// Add token validation
select('[name="personalToken"]')!.addEventListener('input', validateToken);
-
- // Ensure all links open in a new tab #3181
- delegate('a[href^="http"]', 'click', event => {
- if (!event.defaultPrevented) {
- event.preventDefault();
- window.open(event.delegateTarget.href);
- }
- });
-
- // Hide non-applicable "Button link" section
- if (isBrowserActionAPopup) {
- select('#action')!.hidden = true;
- }
}
async function init(): Promise<void> {
@@ -302,11 +318,6 @@ async function init(): Promise<void> {
// TODO: Storage cleanup #6421, Drop in June 2023
void browser.storage.local.remove('featuresAlreadySeen');
-
- // Safari’s storage is inexplicably limited #4823
- if (isSafari()) {
- void cache.clear();
- }
}
void init();