v8.9
This commit is contained in:
parent
138e7e9489
commit
ca4f82ba78
|
@ -18,8 +18,21 @@
|
|||
<dl>
|
||||
|
||||
<dt>8.9</dt>
|
||||
<dd>Added "Log" to the toolbar popup buttons (#44)</dd>
|
||||
<dd>Added limited log display on Chrome (experimental)</dd>
|
||||
<dd>Added Theme feature (#71, #100)</dd>
|
||||
<dd>Added toggle more options on toolbar popup (#54)</dd>
|
||||
<dd>Fixed proxy DNS in "Import Proxy List" (#102) (from 8.7)</dd>
|
||||
<dd>Fixed settings upgrade when username/password is missing (#103)</dd>
|
||||
<dd>Fixed settings upgrade (import older) when hostname is missing (#108)</dd>
|
||||
<dd>Fixed settings upgrade (import older) when username/password is missing (#103)</dd>
|
||||
<dd>Increased log content</dd>
|
||||
<dd>Removed "Show Pattern Proxy" option and made it default (#57) (from 8.7) (Firefox only)</dd>
|
||||
<dd>Removed Tab Proxy page-action and set it to the toolbar icon (#114) (Firefox only)</dd>
|
||||
<dd>Updated add pattern user interface (#105)</dd>
|
||||
<dd>Updated code to process duplicate hostname:port (#33, #76)</dd>
|
||||
<dd>Updated options to disable "Store Locally" on Firefox (Chrome only)</dd>
|
||||
<dd>Updated popup include/exclude host feature</dd>
|
||||
<dd>Updated popup user interface</dd>
|
||||
|
||||
<dt>8.8</dt>
|
||||
<dd>Added Show hidden feature</dd>
|
||||
|
@ -31,7 +44,7 @@
|
|||
<dd>Added Auto Backup feature</dd>
|
||||
<dd>Added FoxyProxy Basic detection (disabled for now)</dd>
|
||||
<dd>Added Help translation form</dd>
|
||||
<dd>Added option to show proxies on the toolbar badge when in Proxy by Patterns mode (Firefox only) (#57)</dd>
|
||||
<dd>Added "Show Pattern Proxy" option to show proxies when in "Proxy by Patterns" mode (#57) (Firefox only)</dd>
|
||||
<dd>Added pattern matching to the Log display (#91)</dd>
|
||||
<dd>Added proxy title to the toolbar icon mouse-over title display (#74)</dd>
|
||||
<dd>Changed the global Proxy DNS to per-proxy setting (#75)</dd>
|
||||
|
@ -60,7 +73,7 @@
|
|||
|
||||
<dt>8.3</dt>
|
||||
<dd>Added enterprise policy & managed storage feature (#42) (experimental)</dd>
|
||||
<dd>Added locally stored PAC feature (#46) (experimental)</dd>
|
||||
<dd>Added PAC "Store Locally" feature (#46) (experimental) (Chrome only)</dd>
|
||||
<dd>Added PAC view feature</dd>
|
||||
<dd>Fixed an issue with empty Global Exclude</dd>
|
||||
<dd>Fixed an issue with upgrade sync data on Firefox (#53)</dd>
|
||||
|
|
|
@ -13,8 +13,8 @@ export const pref = {
|
|||
mode: 'disable',
|
||||
sync: false,
|
||||
autoBackup: false,
|
||||
showPatternProxy: false,
|
||||
passthrough: '',
|
||||
theme: '',
|
||||
container: {},
|
||||
commands: {},
|
||||
data: []
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
--bg: #fff;
|
||||
--alt-bg: #f5f5f5;
|
||||
--hover: #eaeaea;
|
||||
--highlight: #f90;
|
||||
|
||||
--body-bg: #630;
|
||||
--header: #c60;
|
||||
|
@ -17,7 +18,7 @@
|
|||
|
||||
--link: #e70;
|
||||
--border: #ddd;
|
||||
/* --shadow: #0004; */
|
||||
--shadow: #0004;
|
||||
--dim: #777;
|
||||
--tr: #f5f5f5;
|
||||
}
|
||||
|
@ -30,7 +31,7 @@
|
|||
--alt-bg: #666;
|
||||
--hover: #888;
|
||||
|
||||
--body-bg: #630;
|
||||
/* --body-bg: #630; */
|
||||
--header: #e70;
|
||||
|
||||
--btn-bg: #f90;
|
||||
|
@ -38,7 +39,7 @@
|
|||
|
||||
--link: #f90;
|
||||
--border: #777;
|
||||
/* --shadow: #fff8; */
|
||||
--shadow: #fff8;
|
||||
--dim: #ccc;
|
||||
--tr: #531;
|
||||
}
|
||||
|
@ -66,6 +67,11 @@ section {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
select,
|
||||
textarea,
|
||||
input[type="number"],
|
||||
|
@ -79,9 +85,11 @@ input[type="url"] {
|
|||
border-radius: 0.3em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
text-decoration: none;
|
||||
label[for],
|
||||
input[type="checkbox"],
|
||||
summary,
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
|
@ -90,16 +98,35 @@ a {
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
button {
|
||||
background: var(--btn-bg);
|
||||
.invalid,
|
||||
input:invalid {
|
||||
box-shadow: 1px 1px 4px #f20, -1px -1px 4px #f20;
|
||||
}
|
||||
|
||||
/* ----- Buttons ----- */
|
||||
button,
|
||||
label.flat {
|
||||
background-color: var(--btn-bg);
|
||||
border: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: 0.5s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: var(--btn-hover);
|
||||
button.flat,
|
||||
label.flat {
|
||||
display: inline-block;
|
||||
font-size: 0.9em;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 0.4em 1em;
|
||||
min-width: 8em;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
label.flat:hover {
|
||||
background-color: var(--btn-hover);
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
|
@ -108,7 +135,19 @@ select:disabled {
|
|||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.invalid,
|
||||
input:invalid {
|
||||
box-shadow: 1px 1px 4px #f20, -1px -1px 4px #f20;
|
||||
button.plain {
|
||||
background-color: unset;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 1em;
|
||||
}
|
||||
|
||||
button[type="submit"] {
|
||||
display: table;
|
||||
color: #fff;
|
||||
font-size:0.9em;
|
||||
border-radius: 5px;
|
||||
padding: 0.5em 5em;
|
||||
margin: 1em auto 0;
|
||||
}
|
||||
/* ----- /Buttons ----- */
|
||||
|
|
|
@ -407,12 +407,16 @@
|
|||
<dt>Individual Proxy</dt>
|
||||
<dd>Connections are passed through the selected proxy (or PAC)</dd>
|
||||
|
||||
<dt>▶ More</dt>
|
||||
<dd>Show or hide additional options</dd>
|
||||
<dd>User choice is temporarily stored in localStorage (not available in Private/Incognito)</dd>
|
||||
|
||||
<dt>Search Filter</dt>
|
||||
<dd>Proxy <i>Title</i>, <i>Hostname</i>, & <i>Port</i> are searched and display filtered based on the input value (case-insensitive)</dd>
|
||||
<dd>Use <i>:port</i> to filter by port</dd>
|
||||
|
||||
<dt>Quick Add</dt>
|
||||
<dd>Select a proxy to add a pattern based on the current page URL</dd>
|
||||
<dd>Add current page's host pattern to the selected proxy's include</dd>
|
||||
<dd>Only top 10 active proxies are listed</dd>
|
||||
|
||||
<dt>Exclude Host</dt>
|
||||
|
@ -494,6 +498,7 @@
|
|||
<p>There is a discussion to increase the storage sync quota to 1MB.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="https://github.com/w3c/webextensions/issues/520" target="_blank">Increase maximum total size (QUOTA_BYTES) for storage.sync</a></li>
|
||||
<li><a href="https://github.com/w3c/webextensions/issues/351" target="_blank">Discuss limits applied to storage.local and storage.sync API</a></li>
|
||||
<li><a href="https://github.com/w3c/webextensions/issues/510">Proposal: Increase maximum item size in Storage sync quotas</a></li>
|
||||
</ul>
|
||||
|
@ -508,8 +513,8 @@
|
|||
<p>Toggle changes the browser preferences and does not require SAVE.</p>
|
||||
|
||||
|
||||
<h3 id="show-pattern-proxy">Show Pattern Proxy <span>(Firefox only)</span></h3>
|
||||
<p>Show per-tab proxies on the toolbar badge when in Proxy by Patterns mode</p>
|
||||
<!-- <h3 id="show-pattern-proxy">Show Pattern Proxy <span>(Firefox only)</span></h3>
|
||||
<p>Show per-tab proxies on the toolbar badge when in Proxy by Patterns mode</p> -->
|
||||
|
||||
<h3 id="container" class="experimental">Incognito/Container</h3>
|
||||
<p>Set a proxy for Incognito (Private Mode) and/or Containers</p>
|
||||
|
@ -778,7 +783,7 @@
|
|||
<dd>Option to pass DNS to the SOCKS proxy when using SOCKS</dd>
|
||||
<dd class="note">See also:
|
||||
<ul>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1741375" target="_blank">Proxy DNS by default when using SOCKS v5</a> has landed in Firefox 123</li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1741375" target="_blank">Proxy DNS by default when using SOCKS v5</a> (Firefox 123)</li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1799411" target="_blank">DNS leaks with proxy extension</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1791243" target="_blank">Firefox queries DNS of Proxy destination</a></li>
|
||||
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1867562" target="_blank">Despite the fact that DNS over HTTPS is switched off on Privacy and Security bar in Settings it still leaks my DNS</a></li>
|
||||
|
@ -788,10 +793,11 @@
|
|||
<dt>PAC URL <span>(not available on Android)</span></dt>
|
||||
<dd>Required for PAC type</dd>
|
||||
<dd>Proxy Auto-Configuration file (PAC) can be used to handle all proxying configurations</dd>
|
||||
<dd>PAC is a configuration file, not a proxy server</dd>
|
||||
<dd>Patterns are not applicable in PAC type</dd>
|
||||
<dd>See also: <a href="https://developer.mozilla.org/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file" target="_blank">Proxy Auto-Configuration (PAC) file</a></dd>
|
||||
|
||||
<dt id="store-locally" class="experimental">Store Locally</dt>
|
||||
<dt id="store-locally" class="experimental">Store Locally <span>(Chrome only)</span></dt>
|
||||
<dd>Option to store PAC locally</dd>
|
||||
<dd>Option should only be used for altering remote PAC rules</dd>
|
||||
<dd>Storing large or many PACs locally is not recommended and can prevent browser sync</dd>
|
||||
|
@ -1064,16 +1070,25 @@ http://pac-url.com/etc?type=pac&title=Work PAC&color=663300</pre>
|
|||
<li>Result will be match ✅ or fail ❌</li>
|
||||
</ol>
|
||||
|
||||
<h3 id="log">Log <span>(Firefox only)</span></h3>
|
||||
<h3 id="log">Log <span>(Firefox mainly)</span> <span class="experimental">(limited on Chrome v8.9)</span></h3>
|
||||
<ul>
|
||||
<li>Live Log displays the web requests in reversed order (new one on top)</li>
|
||||
<li>It will continue to display while the Options page is open and will stop logging as soon as the page is closed</li>
|
||||
<li>Log data is not stored</li>
|
||||
<li>Not available on chrome since in Chrome <a href="https://developer.chrome.com/docs/extensions/reference/webRequest/#event-onBeforeRequest" target="_blank">webRequest.onBeforeRequest</a> API does not provide <a href="https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest" target="_blank">proxyInfo</a></li>
|
||||
<!-- <li>Not available on chrome since in Chrome <a href="https://developer.chrome.com/docs/extensions/reference/webRequest/#event-onBeforeRequest" target="_blank">webRequest.onBeforeRequest</a> API does not provide <a href="https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest" target="_blank">proxyInfo</a></li> -->
|
||||
<li>Patterns will show if FoxyProxy was in Proxy by Patterns mode when the log page is loaded (refresh if necessary)</li>
|
||||
|
||||
<li>Limited logging on chrome since Chrome <a href="https://developer.chrome.com/docs/extensions/reference/webRequest/#event-onBeforeRequest" target="_blank">webRequest.onBeforeRequest</a> API does not provide <a href="https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest" target="_blank">proxyInfo</a> (and some others)
|
||||
<ul>
|
||||
<li>No Incognito or Container data on Chrome</li>
|
||||
<li>No proxy data on Chrome</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2 id="enterprise-policy" class="experimental">Enterprise Policy <span>(v8.2)</span></h2>
|
||||
<p>FoxyProxy supports enterprise policy and managed storage, and they can be configured to set FoxyProxy options.</p>
|
||||
<p><a href="https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/storage/managed" target="_blank">storage.managed</a> is not supported on Firefox for Android.</p>
|
||||
|
@ -1091,14 +1106,14 @@ http://pac-url.com/etc?type=pac&title=Work PAC&color=663300</pre>
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<h5>Default Options <span>(v8.7)</span></h5>
|
||||
<h5>Default Options <span>(v8.9)</span></h5>
|
||||
<pre>
|
||||
{
|
||||
"mode": "disable", // mandatory: current option, necessary to enable
|
||||
"sync": false, // optional: not necessary as it will be disabled on managed storage
|
||||
"autoBackup": false, // optional: not necessary as save is disabled on managed storage
|
||||
"showPatternProxy": false, // optional: Show proxies on the toolbar badge when in Proxy by Patterns mode (Firefox only)
|
||||
"passthrough": "", // optional: Global Exclude
|
||||
"theme": "", // optional: set the theme
|
||||
"container": {}, // optional: Incognito/Container settings
|
||||
"commands": {}, // optional: keyboard shortcut settings
|
||||
"data": [] // mandatory: array of proxies and their patterns
|
||||
|
|
|
@ -5,7 +5,7 @@ class I18n {
|
|||
static {
|
||||
document.querySelectorAll('template').forEach(i => this.set(i.content));
|
||||
this.set();
|
||||
document.body.style.opacity = 1; // show after i18n
|
||||
// document.body.style.opacity = 1; // show after i18n
|
||||
}
|
||||
|
||||
static set(target = document) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import 'default.css';
|
||||
@import 'theme.css';
|
||||
|
||||
/* ----- General ----- */
|
||||
:root {
|
||||
|
@ -27,7 +28,7 @@ article {
|
|||
/* ----- h1-h5 ----- */
|
||||
h2 {
|
||||
color: var(--header);
|
||||
font-size: 2.2em;
|
||||
font-size: 2.5em;
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -37,7 +38,6 @@ h2:first-of-type {
|
|||
}
|
||||
|
||||
h3 {
|
||||
color: var(--nav-hover);
|
||||
font-size: 1.5em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ mark {
|
|||
/* ----- About ----- */
|
||||
.about dt {
|
||||
background-color: unset;
|
||||
color: var(--nav-hover);
|
||||
color: var(--h3);
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.2em;
|
||||
font-size: 1.1em;
|
||||
|
@ -201,11 +201,11 @@ nav {
|
|||
nav a {
|
||||
color: var(--color);
|
||||
padding: 0.5em 1em;
|
||||
transition: 0.5s;
|
||||
/* transition: 0.5s; */
|
||||
}
|
||||
|
||||
nav a:hover {
|
||||
color: var(--btn-bg);
|
||||
background-color: var(--hover);
|
||||
}
|
||||
|
||||
/* ----- /Navigation ----- */
|
||||
|
|
|
@ -7,28 +7,22 @@ export class Log {
|
|||
static {
|
||||
this.trTemplate = document.querySelector('.log template').content.firstElementChild;
|
||||
this.tbody = document.querySelector('.log tbody');
|
||||
|
||||
// no proxy info on chrome
|
||||
if (App.firefox) {
|
||||
this.tbody.textContent = ''; // remove "not available" notice
|
||||
browser.webRequest.onBeforeRequest.addListener(e => this.process(e), {urls: ['*://*/*']});
|
||||
}
|
||||
|
||||
this.proxyCache = {}; // used to find proxy
|
||||
this.mode = 'disable';
|
||||
browser.webRequest.onBeforeRequest.addListener(e => this.process(e), {urls: ['*://*/*']});
|
||||
}
|
||||
|
||||
static process(e) {
|
||||
const tr = this.tbody.children[199] || this.trTemplate.cloneNode(true);
|
||||
const [, time, container, method, doc, url, title, type, host, port, pattern] = tr.children;
|
||||
const [, time, container, method, reqType, doc, url, title, type, host, port, pattern] = tr.children;
|
||||
|
||||
time.textContent = this.formatInt(e.timeStamp);
|
||||
method.textContent = e.method;
|
||||
doc.textContent = e.documentUrl || ''; // For a top-level document, documentUrl is undefined
|
||||
doc.title = e.documentUrl || '';
|
||||
url.textContent = decodeURIComponent(e.url);
|
||||
url.title = e.url;
|
||||
container.classList.toggle('incognito', e.incognito);
|
||||
reqType.textContent = e.type;
|
||||
// For a top-level document, documentUrl is undefined, chrome uses e.initiator
|
||||
this.prepareOverflow(doc, e.documentUrl || e.initiator || '');
|
||||
this.prepareOverflow(url, decodeURIComponent(e.url));
|
||||
container.classList.toggle('incognito', !!e.incognito);
|
||||
container.textContent = e.cookieStoreId?.startsWith('firefox-container-') ? 'C' + e.cookieStoreId.substring(18) : '';
|
||||
|
||||
const info = e.proxyInfo || {host: '', port: '', type: ''};
|
||||
|
@ -43,8 +37,7 @@ export class Log {
|
|||
// show matching pattern in pattern mode
|
||||
const pat = this.mode === 'pattern' && item?.include.find(i => new RegExp(Pattern.get(i.pattern, i.type), 'i').test(e.url));
|
||||
const text = pat?.title || pat?.pattern || '';
|
||||
pattern.textContent = text;
|
||||
pattern.title = text;
|
||||
this.prepareOverflow(pattern, text);
|
||||
|
||||
this.tbody.prepend(tr); // in reverse order, new on top
|
||||
}
|
||||
|
@ -53,4 +46,10 @@ export class Log {
|
|||
return new Intl.DateTimeFormat(navigator.language,
|
||||
{hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false}).format(new Date(d));
|
||||
}
|
||||
|
||||
// set title, in case text overflows
|
||||
static prepareOverflow(elem, value) {
|
||||
elem.textContent = value;
|
||||
elem.title = value;
|
||||
}
|
||||
}
|
|
@ -40,30 +40,19 @@ import {CryptoJS} from '../lib/aes.3.1.2.js';
|
|||
export class Migrate {
|
||||
|
||||
static async init(pref) {
|
||||
// --- 8.8
|
||||
// tidy up left-over obj from 8.0 Sync typo mistake
|
||||
if (Object.hasOwn(pref, 'obj')) {
|
||||
delete pref.obj;
|
||||
await browser.storage.local.remove('obj');
|
||||
await browser.storage.sync.remove('obj');
|
||||
}
|
||||
|
||||
// --- 8.7
|
||||
// change global proxyDNS to per-proxy
|
||||
// --- 8.9
|
||||
// 8.9 remove showPatternProxy (from 8.7)
|
||||
// 8.8 tidy up left-over obj Sync typo mistake (from 8.0)
|
||||
// 8.7 change global proxyDNS to per-proxy (from 8.0)
|
||||
if (Object.hasOwn(pref, 'proxyDNS') && pref.data) {
|
||||
pref.data.forEach(i => i.proxyDNS = !!pref.proxyDNS);
|
||||
delete pref.proxyDNS;
|
||||
await browser.storage.local.remove('proxyDNS');
|
||||
await browser.storage.local.set(pref);
|
||||
}
|
||||
|
||||
// --- 8.1
|
||||
if (Object.hasOwn(pref, 'globalExcludeWildcard')) {
|
||||
delete pref.globalExcludeWildcard; // from 8.0, removed in 8.1
|
||||
delete pref.globalExcludeRegex; // from 8.0, removed in 8.1
|
||||
delete pref.obj; // 8.0 Sync typo mistake
|
||||
await browser.storage.local.remove(['globalExcludeWildcard', 'globalExcludeRegex', 'obj']);
|
||||
}
|
||||
// 8.1 remove globalExcludeWildcard, globalExcludeRegex (from 8.0)
|
||||
const keys = ['showPatternProxy', 'obj', 'proxyDNS', 'globalExcludeWildcard', 'globalExcludeRegex'];
|
||||
keys.forEach(i => delete pref[i]);
|
||||
await browser.storage.local.remove(keys);
|
||||
await browser.storage.sync.remove(keys);
|
||||
|
||||
// --- 8.0
|
||||
if (pref.data) { return; }
|
||||
|
@ -185,7 +174,9 @@ export class Migrate {
|
|||
const db = App.getDefaultPref();
|
||||
db.sync = !!pref.sync;
|
||||
|
||||
const data = Object.values(pref).filter(i => i && Object.hasOwn(i, 'address')); // null value causes an error
|
||||
// null value causes an error in hasOwn, direct proxies don't have 'address'
|
||||
const data = Object.values(pref).filter(i => i && ['address', 'type'].some(p => Object.hasOwn(i, p)));
|
||||
|
||||
data.sort((a, b) => a.index - b.index); // sort by index
|
||||
|
||||
data.forEach(item => {
|
||||
|
@ -193,8 +184,8 @@ export class Migrate {
|
|||
active: item.active === 'true' || item.active === true, // convert to boolean, some old databases have mixed types
|
||||
title: item.title || '',
|
||||
type: typeSet[item.type], // convert to actual type: http | https | socks4 | socks5 | direct | + add PAC
|
||||
hostname: item.address, // rename to hostname
|
||||
port: item.port,
|
||||
hostname: item.address || '', // rename to hostname
|
||||
port: item.port || '',
|
||||
username: item.username || '',
|
||||
password: item.password || '',
|
||||
cc: item.cc || '', // remove country, use CC in country-code.js
|
||||
|
@ -208,9 +199,7 @@ export class Migrate {
|
|||
};
|
||||
|
||||
pxy.cc === 'UK' && (pxy.cc = 'GB'); // convert UK to ISO 3166-1 GB
|
||||
|
||||
// --- type 'direct'
|
||||
pxy.type === 'direct' && (pxy.hostname = 'DIRECT');
|
||||
pxy.type === 'direct' && (pxy.hostname = 'DIRECT'); // type 'direct'
|
||||
|
||||
/*
|
||||
{
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
// Fixed in Firefox 119
|
||||
|
||||
import {Pattern} from './pattern.js';
|
||||
import {PageAction} from './page-action.js';
|
||||
import {Location} from './location.js';
|
||||
|
||||
// ---------- Firefox Proxy Process ------------------------
|
||||
|
@ -16,11 +15,10 @@ export class OnRequest {
|
|||
static {
|
||||
// --- default values
|
||||
this.mode = 'disable';
|
||||
this.proxy = null; // used for Single Proxy
|
||||
this.proxy = {}; // used for Single Proxy
|
||||
this.data = []; // used for Proxy by Pattern
|
||||
this.passthrough = []; // RegExp string
|
||||
this.net = []; // [start, end] strings
|
||||
this.showPatternProxy = false;
|
||||
this.tabProxy = {}; // tab proxy, may be lost in MV3 if bg is unloaded
|
||||
this.container = {}; // incognito/container proxy
|
||||
|
||||
|
@ -40,12 +38,12 @@ export class OnRequest {
|
|||
const [passthrough, , net] = Pattern.getPassthrough(pref.passthrough);
|
||||
this.passthrough = passthrough;
|
||||
this.net = net;
|
||||
this.showPatternProxy = pref.showPatternProxy;
|
||||
|
||||
const data = pref.data.filter(i => i.active && i.type !== 'pac' && i.hostname); // filter data
|
||||
// filter data
|
||||
const data = pref.data.filter(i => i.active && i.type !== 'pac' && i.hostname);
|
||||
|
||||
// --- single proxy
|
||||
/:\d+$/.test(pref.mode) && (this.proxy = data.find(i => pref.mode === `${i.hostname}:${i.port}`));
|
||||
// --- single proxy (false|undefined|proxy object)
|
||||
this.proxy = /:\d+[^/]*$/.test(pref.mode) && data.find(i => pref.mode === `${i.hostname}:${i.port}`);
|
||||
|
||||
// --- proxy by pattern
|
||||
this.data = data.filter(i => i.include[0] || i.exclude[0]).map(item => {
|
||||
|
@ -75,34 +73,37 @@ export class OnRequest {
|
|||
}
|
||||
|
||||
static process(e) {
|
||||
const tabId = e.tabId;
|
||||
switch (true) {
|
||||
// --- check local & global passthrough
|
||||
case this.bypass(e.url):
|
||||
this.setAction(null, tabId);
|
||||
return {type: 'direct'};
|
||||
|
||||
// --- tab proxy
|
||||
case e.tabId !== -1 && !!this.tabProxy[e.tabId]:
|
||||
return this.processProxy(this.tabProxy[e.tabId]);
|
||||
case tabId !== -1 && !!this.tabProxy[tabId]:
|
||||
return this.processProxy(this.tabProxy[tabId], tabId);
|
||||
|
||||
// --- incognito proxy
|
||||
case e.tabId !== -1 && e.incognito && !!this.container.incognito:
|
||||
return this.processProxy(this.container.incognito);
|
||||
case tabId !== -1 && e.incognito && !!this.container.incognito:
|
||||
return this.processProxy(this.container.incognito, tabId);
|
||||
|
||||
// --- container proxy
|
||||
case e.tabId !== -1 && e.cookieStoreId && !!this.container[e.cookieStoreId]:
|
||||
return this.processProxy(this.container[e.cookieStoreId]);
|
||||
case tabId !== -1 && e.cookieStoreId && !!this.container[e.cookieStoreId]:
|
||||
return this.processProxy(this.container[e.cookieStoreId], tabId);
|
||||
|
||||
// --- standard operation
|
||||
case this.mode === 'disable': // pass direct
|
||||
case this.mode === 'direct': // pass direct
|
||||
case this.mode.includes('://') && !/:\d+$/.test(this.mode): // PAC URL is set
|
||||
this.setAction(null, tabId);
|
||||
return {type: 'direct'};
|
||||
|
||||
case this.mode === 'pattern': // check if url matches patterns
|
||||
return this.processPattern(e.url, e.tabId);
|
||||
return this.processPattern(e.url, tabId);
|
||||
|
||||
default: // get the proxy for all
|
||||
return this.processProxy(this.proxy);
|
||||
return this.processProxy(this.proxy, tabId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,31 +112,19 @@ export class OnRequest {
|
|||
|
||||
for (const proxy of this.data) {
|
||||
if (!match(proxy.exclude) && match(proxy.include)) {
|
||||
this.processShowPatternProxy(proxy, tabId);
|
||||
return this.processProxy(proxy);
|
||||
// this.processShowPatternProxy(proxy, tabId);
|
||||
return this.processProxy(proxy, tabId);
|
||||
}
|
||||
}
|
||||
|
||||
this.setAction(null, tabId);
|
||||
return {type: 'direct'}; // no match
|
||||
}
|
||||
|
||||
static processShowPatternProxy(item, tabId) {
|
||||
// Set to -1 if the request isn't related to a tab
|
||||
if (tabId === -1 || !this.showPatternProxy) { return; }
|
||||
|
||||
const host = [item.hostname, item.port].filter(Boolean).join(':');
|
||||
const title = [item.title, host, item.city, ...Location.get(item.cc)].filter(Boolean).join('\n');
|
||||
const text = item.title || item.hostname;
|
||||
const color = item.color;
|
||||
|
||||
browser.action.setBadgeBackgroundColor({color, tabId});
|
||||
browser.action.setTitle({title, tabId});
|
||||
browser.action.setBadgeText({text, tabId});
|
||||
}
|
||||
|
||||
static processProxy(proxy) {
|
||||
const {type, hostname: host, port, username, password, proxyDNS} = proxy;
|
||||
if (type === 'direct') { return {type: 'direct'}; }
|
||||
static processProxy(proxy, tabId) {
|
||||
this.setAction(proxy, tabId);
|
||||
const {type, hostname: host, port, username, password, proxyDNS} = proxy || {};
|
||||
if (!type || type === 'direct') { return {type: 'direct'}; }
|
||||
|
||||
// https://searchfox.org/mozilla-central/source/toolkit/components/extensions/ProxyChannelFilter.sys.mjs#102
|
||||
// Although API converts to number -> let port = Number.parseInt(proxyData.port, 10);
|
||||
|
@ -163,6 +152,28 @@ export class OnRequest {
|
|||
return response;
|
||||
}
|
||||
|
||||
static setAction(item, tabId) {
|
||||
// Set to -1 if the request isn't related to a tab
|
||||
if (tabId === -1) { return; }
|
||||
|
||||
// --- reset values
|
||||
let title = null;
|
||||
let text = null;
|
||||
let color = null;
|
||||
|
||||
// --- set proxy details
|
||||
if (item) {
|
||||
const host = [item.hostname, item.port].filter(Boolean).join(':');
|
||||
title = [item.title, host, item.city, ...Location.get(item.cc)].filter(Boolean).join('\n');
|
||||
text = item.title || item.hostname;
|
||||
color = item.color;
|
||||
}
|
||||
|
||||
browser.action.setBadgeBackgroundColor({color, tabId});
|
||||
browser.action.setTitle({title, tabId});
|
||||
browser.action.setBadgeText({text, tabId});
|
||||
}
|
||||
|
||||
// ---------- passthrough --------------------------------
|
||||
static bypass(url) {
|
||||
switch (true) {
|
||||
|
@ -223,13 +234,21 @@ export class OnRequest {
|
|||
}
|
||||
|
||||
this.tabProxy[tab.id] = pxy;
|
||||
PageAction.set(tab.id, pxy);
|
||||
// PageAction.set(tab.id, pxy);
|
||||
}
|
||||
|
||||
static async unsetTabProxy() {
|
||||
const [tab] = await browser.tabs.query({currentWindow: true, active: true});
|
||||
delete this.tabProxy[tab.id];
|
||||
PageAction.unset(tab.id);
|
||||
// PageAction.unset(tab.id);
|
||||
}
|
||||
|
||||
// ---------- Update Page Action -------------------------
|
||||
static onUpdated(tabId, changeInfo, tab) {
|
||||
if (changeInfo.status !== 'complete') { return; }
|
||||
|
||||
const pxy = this.tabProxy[tabId];
|
||||
pxy ? this.setAction(pxy, tabId) : this.checkPageAction(tab);
|
||||
}
|
||||
|
||||
// ---------- Incognito/Container ------------------------
|
||||
|
@ -237,14 +256,6 @@ export class OnRequest {
|
|||
if (tab.id === -1 || this.tabProxy[tab.id]) { return; } // not if tab proxy is set
|
||||
|
||||
const pxy = tab.incognito ? this.container.incognito : this.container[tab.cookieStoreId];
|
||||
pxy && PageAction.set(tab.id, pxy);
|
||||
}
|
||||
|
||||
// ---------- Update Page Action -------------------------
|
||||
static onUpdated(tabId, changeInfo, tab) {
|
||||
if (changeInfo.status !== 'complete') { return; }
|
||||
|
||||
const pxy = this.tabProxy[tab.id];
|
||||
pxy ? PageAction.set(tab.id, pxy) : this.checkPageAction(tab);
|
||||
pxy && this.setAction(pxy, tab.id);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
@import 'default.css';
|
||||
@import 'progress-bar.css';
|
||||
@import 'spinner.css';
|
||||
@import 'theme.css';
|
||||
|
||||
/* ----- General ----- */
|
||||
:root {
|
||||
|
@ -58,13 +59,6 @@ iframe {
|
|||
vertical-align: text-bottom;
|
||||
} */
|
||||
|
||||
label[for],
|
||||
input[type="checkbox"],
|
||||
summary,
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label > input[type="checkbox"] {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
@ -80,29 +74,17 @@ textarea {
|
|||
resize: vertical;
|
||||
}
|
||||
|
||||
.flat {
|
||||
background: var(--btn-bg);
|
||||
/* .flat {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: 0.5s;
|
||||
border-radius: 5px;
|
||||
padding: 0.4em 1em;
|
||||
border: 0;
|
||||
font-weight: bold;
|
||||
font-size: 0.9em;
|
||||
min-width: 8em;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flat:hover {
|
||||
background: var(--btn-hover);
|
||||
/* box-shadow: 0px 1px 5px var(--shadow); */
|
||||
}
|
||||
} */
|
||||
|
||||
fieldset {
|
||||
background: var(--bg);
|
||||
background-color: var(--bg);
|
||||
border-radius: 0.5em;
|
||||
border: 0;
|
||||
padding: 1.5em;
|
||||
|
@ -154,7 +136,7 @@ input[type="checkbox"].control {
|
|||
}
|
||||
|
||||
div.nav {
|
||||
background: var(--nav-bg);
|
||||
background-color: var(--nav-bg);
|
||||
}
|
||||
|
||||
nav {
|
||||
|
@ -175,12 +157,12 @@ nav img {
|
|||
|
||||
nav > label {
|
||||
padding: 0.5em 1em;
|
||||
transition: 0.5s;
|
||||
/* transition: 0.5s; */
|
||||
border-radius: 0.5em 0.5em 0 0;
|
||||
}
|
||||
|
||||
nav > label:hover {
|
||||
background: var(--nav-hover);
|
||||
background-color: var(--nav-hover);
|
||||
}
|
||||
|
||||
/* nav > label img {
|
||||
|
@ -231,29 +213,19 @@ input[type="file"] {
|
|||
/* ----- /Import/Export ----- */
|
||||
|
||||
/* ----- Submit Button ----- */
|
||||
button[type="submit"] {
|
||||
/* button[type="submit"] {
|
||||
display: table;
|
||||
color: #fff;
|
||||
background: var(--btn-bg);
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
background-color: var(--btn-bg);
|
||||
font-size:0.9em;
|
||||
margin: 1em auto 0;
|
||||
padding: 0.5em 3em;
|
||||
text-shadow: 0 -1px 1px #333;
|
||||
border: 0;
|
||||
padding: 0.5em 5em;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 5px var(--body-bg);
|
||||
}
|
||||
|
||||
button[type="submit"]:hover {
|
||||
background-color: var(--btn-hover);
|
||||
}
|
||||
|
||||
button[type="submit"]:active {
|
||||
/* background-color: #3e8e41; */
|
||||
box-shadow: 0 1px var(--body-bg);
|
||||
transform: translateY(4px);
|
||||
}
|
||||
} */
|
||||
/* ----- /Submit Button ----- */
|
||||
|
||||
/* ----- Toggle Switch ----- */
|
||||
|
@ -274,7 +246,7 @@ button[type="submit"]:active {
|
|||
z-index: 2;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: #fff;
|
||||
background-color: #fff;
|
||||
left: 1px;
|
||||
top: 1px;
|
||||
border-radius: 50%;
|
||||
|
@ -292,14 +264,6 @@ button[type="submit"]:active {
|
|||
/* ----- /Toggle Switch ----- */
|
||||
|
||||
/* ----- Button ----- */
|
||||
button.plain {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 1em;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button.bin,
|
||||
button.test,
|
||||
button.close {
|
||||
|
@ -344,10 +308,15 @@ textarea {
|
|||
font-size: 1em;
|
||||
} */
|
||||
|
||||
section.options fieldset * {
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
input[type="color"] {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.options div.theme,
|
||||
.options div.container,
|
||||
.options div.commands {
|
||||
display: grid;
|
||||
|
@ -357,6 +326,10 @@ input[type="color"] {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.options div.theme {
|
||||
margin-left: unset;
|
||||
}
|
||||
|
||||
.options div.buttons {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
|
@ -369,7 +342,7 @@ input[type="color"] {
|
|||
/* .options div.buttons {
|
||||
padding: 0 1.5em;
|
||||
margin: 0 -1.5em 1em;
|
||||
background: var(--btn-bg);
|
||||
background-color: var(--btn-bg);
|
||||
}
|
||||
|
||||
.options div.buttons > * {
|
||||
|
@ -520,7 +493,7 @@ details.proxy > summary span:nth-of-type(2):empty::before {
|
|||
.pattern-box button.bin {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
/* border: none; */
|
||||
font-size: 1em;
|
||||
transition: 0.5s;
|
||||
color: #ccc;
|
||||
|
@ -529,74 +502,6 @@ details.proxy > summary span:nth-of-type(2):empty::before {
|
|||
}
|
||||
/* ----- /Pattern ----- */
|
||||
|
||||
/* ----- show/hide elements ----- */
|
||||
details.proxy[data-type="direct"] :is(
|
||||
[data-i18n="port"], [data-id="port"],
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password,
|
||||
[data-i18n="country"], [data-id="cc"],
|
||||
[data-i18n="city"], [data-id="city"],
|
||||
[data-type="pac"], .pac) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="pac"] :is(
|
||||
[data-i18n="port"], [data-id="port"],
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="pac"] :is(.pattern-head, .pattern-box) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
details.proxy:not([data-type="pac"]) :is([data-type="pac"], .pac) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="socks4"] :is(
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy:not([data-type="socks5"]) :is([data-i18n="proxyDNS"], [data-id="proxyDNS"]) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* --- Chrome --- */
|
||||
.chrome .firefox {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.chrome details.proxy[data-type="socks5"] :is(
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* --- Basic --- */
|
||||
.basic :is(.pattern-head, .pattern-box) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ----- /show/hide elements ----- */
|
||||
|
||||
/* ----- Popup ----- */
|
||||
div.popup {
|
||||
display: none;
|
||||
|
@ -718,7 +623,7 @@ section.log {
|
|||
|
||||
.log thead th {
|
||||
color: #fff;
|
||||
background: #999;
|
||||
background-color: #999;
|
||||
padding: 0.5em 0.2em;
|
||||
font-size: 0.9em;
|
||||
font-weight: normal;
|
||||
|
@ -730,13 +635,13 @@ section.log {
|
|||
vertical-align: unset;
|
||||
}
|
||||
|
||||
.log tbody tr {
|
||||
/* border-bottom: 1px solid var(--border); */
|
||||
/* .log tbody tr {
|
||||
/* border-bottom: 1px solid var(--border); * /
|
||||
animation: sect 0.5s ease-in-out;
|
||||
}
|
||||
} */
|
||||
|
||||
.log tr:hover {
|
||||
background: var(--hover) !important;
|
||||
background-color: var(--hover) !important;
|
||||
}
|
||||
|
||||
.log tbody tr:nth-of-type(even) {
|
||||
|
@ -748,28 +653,27 @@ section.log {
|
|||
padding: 0.2em;
|
||||
}
|
||||
|
||||
.log td:nth-of-type(5),
|
||||
.log td:nth-of-type(6),
|
||||
.log td:nth-of-type(11) {
|
||||
.log td:nth-of-type(7),
|
||||
.log td:nth-of-type(12) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
.log td:nth-of-type(6) {
|
||||
.log td:nth-of-type(7) {
|
||||
max-width: 40em;
|
||||
}
|
||||
|
||||
.log td:nth-of-type(7) {
|
||||
.log td:nth-of-type(8) {
|
||||
border-left: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.log td:nth-of-type(11) {
|
||||
.log td:nth-of-type(12) {
|
||||
max-width: 5em;
|
||||
}
|
||||
|
||||
|
||||
.log td.incognito::before {
|
||||
content: '';
|
||||
width: 1em;
|
||||
|
@ -795,17 +699,87 @@ section.log {
|
|||
content: counter(n);
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
/* Not Available On Chrome (Firefox Only)" */
|
||||
.log td.unavailable {
|
||||
height: 50vh;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
color: var(--btn-bg);
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.log td.unavailable::before {
|
||||
content: none !important;
|
||||
}
|
||||
/* ----- /Log ----- */
|
||||
|
||||
/* ----- show/hide elements ----- */
|
||||
details.proxy[data-type="direct"] :is(
|
||||
[data-i18n="port"], [data-id="port"],
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password,
|
||||
[data-i18n="country"], [data-id="cc"],
|
||||
[data-i18n="city"], [data-id="city"],
|
||||
[data-type="pac"], .pac) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="pac"] :is(
|
||||
[data-i18n="port"], [data-id="port"],
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="pac"] :is(.pattern-head, .pattern-box) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
details.proxy:not([data-type="pac"]) :is([data-type="pac"], .pac) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy[data-type="socks4"] :is(
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details.proxy:not([data-type="socks5"]) :is([data-i18n="proxyDNS"], [data-id="proxyDNS"]) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* --- Chrome --- */
|
||||
body.chrome .firefox {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body.chrome details.proxy[data-type="socks5"] :is(
|
||||
[data-i18n="username"], [data-id="username"],
|
||||
[data-i18n="password"], .password) {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body:not(.chrome) [data-i18n="storeLocally"] {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
caption.firefox {
|
||||
color: var(--nav-color);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
body.chrome caption.firefox {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* --- Basic --- */
|
||||
.basic :is(.pattern-head, .pattern-box) {
|
||||
display: none;
|
||||
}
|
||||
/* ----- /show/hide elements ----- */
|
|
@ -70,8 +70,17 @@
|
|||
<label data-i18n="limitWebRTC"><input type="checkbox" id="limitWebRTC"></label>
|
||||
<p class="description" data-i18n="limitWebRTCDescription"></p>
|
||||
|
||||
<label class="firefox" data-i18n="showPatternProxy"><input type="checkbox" id="showPatternProxy"></label>
|
||||
<p class="description firefox" data-i18n="showPatternProxyDescription"></p>
|
||||
<!-- <label class="firefox" data-i18n="showPatternProxy"><input type="checkbox" id="showPatternProxy"></label>
|
||||
<p class="description firefox" data-i18n="showPatternProxyDescription"></p> -->
|
||||
|
||||
<div class="theme">
|
||||
<label data-i18n="theme"></label>
|
||||
<select id="theme">
|
||||
<option value="" data-i18n="default"></option>
|
||||
<option>moonlight</option>
|
||||
<option>moonlight alt</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label data-i18n="container"></label>
|
||||
<p class="description" data-i18n="containerDescription"></p>
|
||||
|
@ -602,12 +611,14 @@
|
|||
<!-- log -->
|
||||
<section class="log">
|
||||
<table>
|
||||
<caption class="firefox" data-i18n="notAvailable"></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 1.5em;"></th>
|
||||
<th style="width: 5em;" data-i18n="time"></th>
|
||||
<th style="width: 1em;"><img src="../image/container.svg" alt=""></th>
|
||||
<th style="width: 3em;" data-i18n="method"></th>
|
||||
<th style="width: 3em;" data-i18n="type"></th>
|
||||
<th data-i18n="documentURL"></th>
|
||||
<th data-i18n="url"></th>
|
||||
<th><span data-i18n="proxy"></span> <span data-i18n="title"></span></th>
|
||||
|
@ -618,9 +629,6 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="unavailable" colspan="11" data-i18n="notAvailable"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -638,6 +646,7 @@
|
|||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</template>
|
||||
</section>
|
||||
|
|
|
@ -61,6 +61,22 @@ class Toggle {
|
|||
}
|
||||
// ---------- /Toggle --------------------------------------
|
||||
|
||||
// ---------- Theme ----------------------------------------
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
class Theme {
|
||||
static {
|
||||
this.elem = [document, ...[...document.querySelectorAll('iframe')].map(i => i.contentDocument)];
|
||||
pref.theme && this.set(pref.theme);
|
||||
document.body.style.opacity = 1; // show after
|
||||
document.getElementById('theme').addEventListener('change', e => this.set(e.target.value));
|
||||
}
|
||||
|
||||
static set(value) {
|
||||
this.elem.forEach(i => i.documentElement.className = value);
|
||||
}
|
||||
}
|
||||
// ---------- /Theme ---------------------------------------
|
||||
|
||||
// ---------- Options --------------------------------------
|
||||
class Options {
|
||||
|
||||
|
@ -77,7 +93,7 @@ class Options {
|
|||
// --- buttons
|
||||
document.querySelector('.options button[data-i18n="restoreDefaults"]').addEventListener('click', () => this.restoreDefaults());
|
||||
|
||||
this.init(['sync', 'autoBackup', 'showPatternProxy', 'passthrough']);
|
||||
this.init(['sync', 'autoBackup', 'theme', 'showPatternProxy', 'passthrough']);
|
||||
}
|
||||
|
||||
static init(keys = Object.keys(pref)) {
|
||||
|
@ -581,7 +597,11 @@ class Proxies {
|
|||
});
|
||||
|
||||
// patterns
|
||||
pxy.querySelector('button[data-i18n="add|title"]').addEventListener('click', () => this.addPattern(patternBox));
|
||||
pxy.querySelector('button[data-i18n="add|title"]').addEventListener('click', () => {
|
||||
this.addPattern(patternBox);
|
||||
patternBox.lastElementChild.scrollIntoView(false);
|
||||
patternBox.lastElementChild.children[4].focus();
|
||||
});
|
||||
pxy.querySelector('input[type="file"]').addEventListener('change', e => this.importPattern(e, patternBox));
|
||||
pxy.querySelector('button[data-i18n^="export"]').addEventListener('click', () =>
|
||||
this.exportPattern(patternBox, title.value.trim() || hostname.value.trim()));
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
@import 'default.css';
|
||||
@import 'theme.css';
|
||||
|
||||
/* ----- Light Theme ----- */
|
||||
:root {
|
||||
--filter: opacity(0.4) grayscale(1);
|
||||
}
|
||||
|
||||
/* for the default theme */
|
||||
:root:not([class]) {
|
||||
--nav-bg: #630;
|
||||
}
|
||||
|
||||
/* ----- Dark Theme ----- */
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
|
@ -23,7 +29,7 @@ body {
|
|||
|
||||
h1 {
|
||||
color: var(--nav-color);
|
||||
background: var(--body-bg);
|
||||
background-color: var(--nav-bg);
|
||||
margin: 0;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
@ -34,7 +40,7 @@ h1 img {
|
|||
}
|
||||
|
||||
/* ----- Buttons ----- */
|
||||
div.buttons {
|
||||
div.popup-buttons {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
column-gap: 0.1em;
|
||||
|
@ -42,13 +48,13 @@ div.buttons {
|
|||
|
||||
button {
|
||||
color: #fff;
|
||||
border: 0;
|
||||
border: none;
|
||||
padding: 0.8em;
|
||||
font-weight: bold;
|
||||
/* font-weight: bold; */
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: var(--btn-hover);
|
||||
background-color: var(--btn-hover);
|
||||
}
|
||||
/* ----- /Buttons ----- */
|
||||
|
||||
|
@ -125,13 +131,19 @@ input#filter {
|
|||
background: url('../image/filter.svg') no-repeat left 0.5em center / 1em;
|
||||
padding-left: 2em;
|
||||
margin-bottom: 0.2em;
|
||||
grid-column: span 2;
|
||||
/* grid-column: span 2; */
|
||||
}
|
||||
|
||||
div.list label.off {
|
||||
display: none;
|
||||
}
|
||||
|
||||
summary {
|
||||
background-color: var(--alt-bg);
|
||||
padding: 0.2em 0.5em;
|
||||
margin-bottom: 0.1em;
|
||||
}
|
||||
|
||||
div.host {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
@ -141,24 +153,23 @@ div.host {
|
|||
}
|
||||
|
||||
div.host button {
|
||||
padding: 0.2em;
|
||||
background: unset;
|
||||
background-color: unset;
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--color);
|
||||
font-weight: normal;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 5px;
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
div.host button:hover {
|
||||
background: var(--hover);
|
||||
background-color: var(--hover);
|
||||
}
|
||||
|
||||
div.host select {
|
||||
/* div.host select {
|
||||
grid-column: span 2;
|
||||
}
|
||||
} */
|
||||
|
||||
/* ----- show/hide elements ----- */
|
||||
|
||||
/* --- Chrome --- */
|
||||
.chrome .firefox {
|
||||
opacity: 0.3;
|
||||
|
@ -177,5 +188,4 @@ div.host select {
|
|||
.basic .pattern {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ----- /show/hide elements ----- */
|
|
@ -26,26 +26,30 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<div class="host">
|
||||
<input type="text" id="filter" spellcheck="false" placeholder="filter">
|
||||
<details>
|
||||
<summary data-i18n="more"></summary>
|
||||
<div class="host">
|
||||
<select class="local">
|
||||
<option value="" disabled selected> </option>
|
||||
</select>
|
||||
|
||||
<select class="local">
|
||||
<option value="" disabled selected> </option>
|
||||
</select>
|
||||
<input type="text" id="filter" spellcheck="false" placeholder="filter">
|
||||
|
||||
<button type="button" class="local" data-i18n="quickAdd"></button>
|
||||
<button type="button" class="firefox local" data-i18n="setTabProxy"></button>
|
||||
<button type="button" class="local" data-i18n="quickAdd"></button>
|
||||
<button type="button" class="local" data-i18n="excludeHost"></button>
|
||||
<button type="button" class="firefox local" data-i18n="setTabProxy"></button>
|
||||
<button type="button" class="firefox local" data-i18n="unsetTabProxy"></button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<button type="button" class="local" data-i18n="excludeHost"></button>
|
||||
<button type="button" class="firefox local" data-i18n="unsetTabProxy"></button>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<div class="popup-buttons">
|
||||
<button type="button" data-i18n="options"></button>
|
||||
<button type="button" data-i18n="location"></button>
|
||||
<button type="button" data-i18n="ip"></button>
|
||||
<button type="button" data-i18n="log"></button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- template -->
|
||||
<template>
|
||||
<label>
|
||||
|
|
|
@ -11,15 +11,16 @@ await App.getPref();
|
|||
class Popup {
|
||||
|
||||
static {
|
||||
// --- theme
|
||||
pref.theme && (document.documentElement.className = pref.theme);
|
||||
document.body.style.opacity = 1; // show after
|
||||
|
||||
document.querySelectorAll('button').forEach(i => i.addEventListener('click', e => this.processButtons(e)));
|
||||
|
||||
this.list = document.querySelector('div.list');
|
||||
this.select = document.querySelector('select');
|
||||
this.proxyCache = {}; // used to find proxy
|
||||
|
||||
// this.showJS = document.querySelector('.show-js');
|
||||
// disable buttons on Chrome
|
||||
// !App.firefox && this.showJS.classList.add('chrome');
|
||||
// disable buttons on storage.managed
|
||||
pref.managed && document.body.classList.add('managed');
|
||||
|
||||
|
@ -28,6 +29,11 @@ class Popup {
|
|||
filter.value = ''; // reset after reload
|
||||
filter.addEventListener('input', e => this.filterProxy(e));
|
||||
|
||||
// --- store details open toggle
|
||||
const details = document.querySelector('details');
|
||||
details.open = localStorage.getItem('more') !== 'false'; // defaults to true
|
||||
details.addEventListener('toggle', e => localStorage.setItem('more', details.open));
|
||||
|
||||
this.process();
|
||||
}
|
||||
|
||||
|
@ -113,6 +119,11 @@ class Popup {
|
|||
this.getIP();
|
||||
break;
|
||||
|
||||
case 'log':
|
||||
browser.tabs.create({url: '/content/options.html?log'});
|
||||
window.close();
|
||||
break;
|
||||
|
||||
case 'quickAdd':
|
||||
if (!this.select.value) { break; }
|
||||
if (pref.managed) { break; } // not for storage.managed
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"sync": {"type": "boolean"},
|
||||
"showPatternProxy": {"type": "boolean"},
|
||||
"passthrough": {"type": "string"},
|
||||
"theme": {"type": "string"},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* ---------- Alternative Themes ---------- */
|
||||
|
||||
/* ----- moonlight ----- */
|
||||
:root.moonlight {
|
||||
--bg: #fff;
|
||||
--body-bg: #f9f9fb;
|
||||
|
||||
--nav-bg: #d9d9db;
|
||||
--nav-hover: var(--hover);
|
||||
--nav-color: var(--color);
|
||||
}
|
||||
|
||||
:root.moonlight .flat {
|
||||
color: inherit;
|
||||
background-color: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
:root.moonlight .flat:hover {
|
||||
background-color: var(--hover);
|
||||
}
|
||||
|
||||
:root.moonlight .pattern-head button span.plus {
|
||||
filter: unset;
|
||||
}
|
||||
|
||||
:root.moonlight .popup-buttons button {
|
||||
color: inherit;
|
||||
background-color: var(--alt-bg);
|
||||
}
|
||||
|
||||
:root.moonlight .popup-buttons button:hover {
|
||||
background-color: var(--hover);
|
||||
}
|
||||
|
||||
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
:root.moonlight {
|
||||
--bg: #333;
|
||||
--body-bg: #444;
|
||||
--nav-bg: #000;
|
||||
}
|
||||
|
||||
:root.moonlight .pattern-head button span.plus {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
}
|
||||
/* ----- /moonlight ----- */
|
||||
|
||||
|
||||
|
||||
/* ----- alt ----- */
|
||||
:root.alt {
|
||||
--body-bg: var(--bg);
|
||||
}
|
||||
/* ----- /alt ----- */
|
Loading…
Reference in New Issue