Skip to content

Commit b355910

Browse files
committed
Options cleanups:
- Make the color scheme selector fit on mobile without scrolling. - Replace the 'disabler' with a dirty counter.
1 parent da0b371 commit b355910

File tree

6 files changed

+82
-65
lines changed

6 files changed

+82
-65
lines changed

src/common.js

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -169,50 +169,55 @@ const NAT64_DEFAULT = parseIP("64:ff9b::").slice(0, 96/4);
169169

170170
let _watchOptionsFunc = null;
171171
const options = {ready: false, [NAT64_KEY]: new Set([NAT64_DEFAULT])};
172+
const optionsDirty = {}; // {option: number of writes in flight}
172173
const optionsReady = (async function() {
173-
const items = await chrome.storage.sync.get();
174-
for (const option of Object.keys(DEFAULT_OPTIONS)) {
175-
options[option] = items.hasOwnProperty(option) ?
176-
items[option] : DEFAULT_OPTIONS[option];
174+
for (const [option, value] of Object.entries(DEFAULT_OPTIONS)) {
175+
options[option] = value;
176+
optionsDirty[option] = 0;
177177
}
178-
for (const option of Object.keys(items)) {
179-
if (NAT64_VALIDATE.test(option)) {
178+
const items = await chrome.storage.sync.get();
179+
for (const [option, value] of Object.entries(items)) {
180+
if (DEFAULT_OPTIONS.hasOwnProperty(option)) {
181+
options[option] = value;
182+
} else if (NAT64_VALIDATE.test(option)) {
180183
options[NAT64_KEY].add(option.slice(NAT64_KEY.length));
181184
}
182185
}
183186
options.ready = true;
184-
if (_watchOptionsFunc) {
185-
_watchOptionsFunc(Object.keys(options));
186-
}
187+
_watchOptionsFunc?.(Object.keys(options));
187188
})();
188189

189190
chrome.storage.sync.onChanged.addListener(function(changes) {
190191
// changes = {option: {oldValue: x, newValue: y}}
191192
if (!options.ready) return;
192193
const optionsChanged = [];
193-
for (const option of Object.keys(DEFAULT_OPTIONS)) {
194-
const change = changes[option];
195-
if (!change) continue;
196-
options[option] = change.hasOwnProperty("newValue") ?
197-
change.newValue : DEFAULT_OPTIONS[option];
198-
optionsChanged.push(option);
199-
}
200-
let nat64Changed = false;
201194
for (const [option, {oldValue, newValue}] of Object.entries(changes)) {
202-
if (NAT64_VALIDATE.test(option)) {
195+
if (DEFAULT_OPTIONS.hasOwnProperty(option)) {
196+
const value = newValue || DEFAULT_OPTIONS[option];
197+
if (options[option] != value) {
198+
if (optionsDirty[option] > 1) {
199+
// Forget local changes that occurred mid-write.
200+
optionsDirty[option] = 1;
201+
}
202+
options[option] = value;
203+
optionsChanged.push(option);
204+
}
205+
} else if (NAT64_VALIDATE.test(option)) {
203206
const packed96 = option.slice(NAT64_KEY.length);
204207
if (newValue && !options[NAT64_KEY].has(packed96)) {
205208
options[NAT64_KEY].add(packed96);
206-
nat64Changed = true;
207209
} else if (!newValue && options[NAT64_KEY].has(packed96)) {
208210
options[NAT64_KEY].delete(packed96);
209-
nat64Changed = true;
211+
} else {
212+
continue; // no change
213+
}
214+
if (!optionsChanged.includes(NAT64_KEY)) {
215+
optionsChanged.push(NAT64_KEY);
210216
}
211217
}
212218
}
213-
if (nat64Changed) optionsChanged.push(NAT64_KEY);
214-
if (_watchOptionsFunc && optionsChanged.length) {
215-
_watchOptionsFunc(optionsChanged);
219+
if (optionsChanged.length) {
220+
_watchOptionsFunc?.(optionsChanged);
216221
}
217222
});
218223

@@ -225,18 +230,44 @@ function watchOptions(f) {
225230
}
226231

227232
function setOptions(newOptions) {
228-
console.log("setOptions", newOptions);
229233
const toSet = {};
234+
const optionsChanged = [];
230235
for (const option of Object.keys(DEFAULT_OPTIONS)) {
231-
if (newOptions[option] != options[option]) {
232-
toSet[option] = newOptions[option];
236+
const value = newOptions[option];
237+
if (options[option] != value) {
238+
options[option] = value;
239+
optionsChanged.push(option);
240+
if (++optionsDirty[option] == 1) {
241+
toSet[option] = value;
242+
} else {
243+
// dirty > 1; the value is buffered and written later.
244+
console.log("setOptions buffered", option);
245+
}
233246
}
234247
}
235-
if (Object.keys(toSet).length == 0) {
236-
return false; // no change
248+
const doSet = () => {
249+
if (Object.keys(toSet).length == 0) {
250+
return; // no change
251+
}
252+
chrome.storage.sync.set(toSet, () => {
253+
for (const [option, value] of Object.entries(toSet)) {
254+
const dirty = optionsDirty[option];
255+
if (dirty > 1 && value != options[option]) {
256+
// user changed the value mid-write; push the latest value.
257+
toSet[option] = options[option];
258+
optionsDirty[option] = 1;
259+
} else {
260+
delete toSet[option];
261+
optionsDirty[option] = 0;
262+
}
263+
}
264+
doSet();
265+
});
266+
};
267+
doSet();
268+
if (optionsChanged.length) {
269+
_watchOptionsFunc?.(optionsChanged);
237270
}
238-
chrome.storage.sync.set(toSet);
239-
return true; // caller should wait for watchOptions()
240271
}
241272

242273
// Users can manually call this function to add a NAT64 prefix from the console.
@@ -287,4 +318,4 @@ if (chrome.runtime.getManifest().background.service_worker &&
287318
query.addEventListener("change", (event) => {
288319
chrome.runtime.sendMessage({darkModeInteractive: event.matches});
289320
});
290-
}
321+
}

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "IPvFoo",
33
"manifest_version": 3,
4-
"version": "2.20",
4+
"version": "2.21",
55
"description": "Display the server IP address, with a realtime summary of IPv4, IPv6, and HTTPS information across all page elements.",
66
"homepage_url": "https://github.com/pmarks-net/ipvfoo",
77
"icons": {

src/manifest/chrome-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "IPvFoo",
33
"manifest_version": 3,
4-
"version": "2.20",
4+
"version": "2.21",
55
"description": "Display the server IP address, with a realtime summary of IPv4, IPv6, and HTTPS information across all page elements.",
66
"homepage_url": "https://github.com/pmarks-net/ipvfoo",
77
"icons": {

src/manifest/firefox-manifest.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "IPvFoo",
33
"manifest_version": 3,
4-
"version": "2.20",
4+
"version": "2.21",
55
"description": "Display the server IP address, with a realtime summary of IPv4, IPv6, and HTTPS information across all page elements.",
66
"homepage_url": "https://github.com/pmarks-net/ipvfoo",
77
"icons": {
@@ -17,7 +17,6 @@
1717
"strict_min_version": "115.0"
1818
},
1919
"gecko_android": {
20-
2120
"strict_min_version": "120.0"
2221
}
2322
},

src/options.html

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
-->
1818
<head>
1919
<meta charset="UTF-8">
20-
<meta name="viewport" content="width=360, initial-scale=1" />
20+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
2121
<style type="text/css">
2222
body {
2323
font-family: sans-serif;
@@ -35,14 +35,17 @@
3535
border-collapse: collapse;
3636
border-color: #888;
3737
border-style: solid;
38-
padding: 0;
38+
padding: 3pt;
3939
white-space: nowrap;
4040
vertical-align: middle;
4141
}
42+
td {
43+
border-left: none;
44+
border-right: none;
45+
}
4246
#nat64 table, #nat64 td, #nat64 tr {
4347
font-family: monospace;
4448
color: #800000;
45-
padding: 3pt;
4649
}
4750
ul {
4851
list-style-position: inside;
@@ -51,27 +54,24 @@
5154
}
5255
label {
5356
display: flex;
54-
padding: 1em;
57+
padding: 0pt;
5558
align-items: center;
5659
}
5760
input[type="radio"] {
58-
margin-right: 1em;
61+
margin-right: 3pt;
5962
}
6063
a, a:visited {
6164
color: blue;
6265
}
6366
.darkfg_frame {
6467
background-color: #f2f2f2;
65-
font-size: 0;
6668
padding: 8px;
6769
}
6870
.lightfg_frame {
6971
background-color: #505050;
70-
font-size: 0;
7172
padding: 8px;
7273
}
7374
.colorscheme_title {
74-
padding: 1em;
7575
font-weight: bold;
7676
}
7777

@@ -102,23 +102,23 @@ <h1>Icon color scheme</h1>
102102
<td class="colorscheme_title">Regular tabs:</td>
103103
<td>
104104
<label>
105-
<input type="radio" name="regularColorScheme" value="darkfg" class="disabler">
105+
<input type="radio" name="regularColorScheme" value="darkfg">
106106
<div class="darkfg_frame">
107107
<canvas id="regularColorScheme:darkfg" width="16px" height="16px"></canvas>
108108
</div>
109109
</label>
110110
</td>
111111
<td>
112112
<label>
113-
<input type="radio" name="regularColorScheme" value="lightfg" class="disabler">
113+
<input type="radio" name="regularColorScheme" value="lightfg">
114114
<div class="lightfg_frame">
115115
<canvas id="regularColorScheme:lightfg" width="16px" height="16px"></canvas>
116116
</div>
117117
</label>
118118
</td>
119119
<td>
120120
<label>
121-
<input type="radio" name="regularColorScheme" value="auto" class="disabler">
121+
<input type="radio" name="regularColorScheme" value="auto">
122122
Auto
123123
</label>
124124
</td>
@@ -127,15 +127,15 @@ <h1>Icon color scheme</h1>
127127
<td class="colorscheme_title">Incognito tabs:</td>
128128
<td>
129129
<label>
130-
<input type="radio" name="incognitoColorScheme" value="darkfg" class="disabler">
130+
<input type="radio" name="incognitoColorScheme" value="darkfg">
131131
<div class="darkfg_frame">
132132
<canvas id="incognitoColorScheme:darkfg" width="16px" height="16px"></canvas>
133133
</div>
134134
</label>
135135
</td>
136136
<td>
137137
<label>
138-
<input type="radio" name="incognitoColorScheme" value="lightfg" class="disabler">
138+
<input type="radio" name="incognitoColorScheme" value="lightfg">
139139
<div class="lightfg_frame">
140140
<canvas id="incognitoColorScheme:lightfg" width="16px" height="16px"></canvas>
141141
</div>
@@ -158,7 +158,7 @@ <h1>NAT64 prefixes</h1>
158158
</table>
159159

160160
<div style="display:inline-block; padding-top:1.5em; width:100%">
161-
<button id="revert_btn" style="float:left" class="disabler">Revert to Defaults</button>
161+
<button id="revert_btn" style="float:left">Revert to Defaults</button>
162162
<button id="dismiss_btn" style="float:right">Dismiss</button>
163163
</div>
164164
</body>

src/options.js

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ limitations under the License.
1919
// Requires <script src="common.js">
2020

2121
window.onload = async () => {
22-
disableAll(true);
2322
await spriteImgReady;
2423

2524
for (const option of Object.keys(DEFAULT_OPTIONS)) {
@@ -45,7 +44,7 @@ window.onload = async () => {
4544

4645
watchOptions(function(optionsChanged) {
4746
for (const option of optionsChanged) {
48-
if (option.endsWith("ColorScheme")) {
47+
if (DEFAULT_OPTIONS.hasOwnProperty(option)) {
4948
const radio = document.optionsForm[option];
5049
radio.value = options[option];
5150
} else if (option == NAT64_KEY) {
@@ -60,25 +59,19 @@ window.onload = async () => {
6059
}
6160
}
6261
}
63-
disableAll(false);
6462
});
6563

6664
document.optionsForm.onchange = function(evt) {
6765
const newOptions = {};
6866
for (const option of Object.keys(DEFAULT_OPTIONS)) {
69-
if (!option.endsWith("ColorScheme")) continue;
7067
newOptions[option] = document.optionsForm[option].value;
7168
}
72-
if (setOptions(newOptions)) {
73-
disableAll(true);
74-
}
69+
setOptions(newOptions);
7570
};
7671

7772
document.getElementById("revert_btn").onclick = function() {
7873
revertNAT64();
79-
if (setOptions(DEFAULT_OPTIONS)) {
80-
disableAll(true);
81-
}
74+
setOptions(DEFAULT_OPTIONS);
8275
};
8376

8477
document.getElementById("dismiss_btn").onclick = function() {
@@ -89,9 +82,3 @@ window.onload = async () => {
8982
}
9083
};
9184
}
92-
93-
function disableAll(disabled) {
94-
for (const e of document.getElementsByClassName("disabler")) {
95-
e.disabled = disabled;
96-
}
97-
}

0 commit comments

Comments
 (0)