Skip to content

Commit 7c10e91

Browse files
authoredApr 22, 2024··
Add setting to always compute hintables (#287)
* Add setting to always compute hintables * Make alwaysComputeHintables disabled by default
1 parent 915000b commit 7c10e91

File tree

8 files changed

+97
-6
lines changed

8 files changed

+97
-6
lines changed
 

‎src/common/settings.ts

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const defaultSettings = {
2121
hintsToggleHosts: new Map<string, boolean>(),
2222
hintsTogglePaths: new Map<string, boolean>(),
2323
hintsToggleTabs: new Map<number, boolean>(),
24+
alwaysComputeHintables: false,
2425
enableNotifications: true,
2526
toastPosition: "top-center",
2627
toastTransition: "bounce",

‎src/content/hints/HintClass.ts

+17
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
getCachedSettingAll,
1717
} from "../settings/cacheSettings";
1818
import { refresh } from "../wrappers/refresh";
19+
import { getToggles } from "../settings/toggles";
1920
import { matchesStagedSelector } from "./customSelectorsStaging";
2021
import { getElementToPositionHint } from "./getElementToPositionHint";
2122
import { getAptContainer, getContextForHint } from "./getContextForHint";
@@ -72,6 +73,11 @@ const processHintQueue = debounce(() => {
7273

7374
const toCache = [];
7475

76+
// The hints might be off but being computed because of alwaysComputeHintables
77+
// being enabled. In that case we do all the calculations up to this point but
78+
// we don't attach hints.
79+
if (!getToggles().computed) return;
80+
7581
for (const hint of queue) {
7682
// We need to render the hint but hide it so we can calculate its size for
7783
// positioning it and so we can have a transition.
@@ -680,6 +686,17 @@ export class HintClass implements Hint {
680686
)
681687
delete this.target.dataset["hint"];
682688
}
689+
690+
hide() {
691+
setStyleProperties(this.inner, {
692+
display: "none",
693+
opacity: "0%",
694+
});
695+
}
696+
697+
show() {
698+
addToHintQueue(this);
699+
}
683700
/* eslint-enable @typescript-eslint/no-dynamic-delete */
684701

685702
/**

‎src/content/observe.ts

+35-6
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,61 @@
1+
import { getCachedSetting } from "./settings/cacheSettings";
12
import { getToggles } from "./settings/toggles";
23
import {
34
addWrappersFrom,
45
mutationObserver,
56
disconnectObservers,
67
} from "./wrappers/ElementWrapperClass";
7-
import { clearWrappersAll } from "./wrappers/wrappers";
8+
import {
9+
showHintsAll,
10+
clearWrappersAll,
11+
hideHintsAll,
12+
} from "./wrappers/wrappers";
813

914
let enabled = false;
1015
const config = { attributes: true, childList: true, subtree: true };
1116

1217
export async function updateHintsEnabled() {
1318
const newEnabled = getToggles().computed;
19+
const alwaysComputeHintables = getCachedSetting("alwaysComputeHintables");
20+
21+
// Here we assume that just one change of state takes place. That is, in the
22+
// same call to this function, either the hints have been switched or the
23+
// setting alwaysComputeHintables has changed. Not both at the same time. This
24+
// function is also called when the content script first runs.
1425

26+
// 1. disabled -> enabled
1527
if (!enabled && newEnabled) {
28+
if (alwaysComputeHintables) {
29+
showHintsAll();
30+
} else {
31+
await observe();
32+
}
33+
34+
// 2. enabled -> disabled
35+
} else if (enabled && !newEnabled) {
36+
if (alwaysComputeHintables) {
37+
hideHintsAll();
38+
} else {
39+
disconnectObservers();
40+
clearWrappersAll();
41+
}
42+
43+
// 3. !alwaysComputeHintables -> alwaysComputeHintables
44+
} else if (!enabled && alwaysComputeHintables) {
1645
await observe();
17-
enabled = true;
18-
}
1946

20-
if (enabled && !newEnabled) {
47+
// 4. alwaysComputeHintables -> !alwaysComputeHintables
48+
} else if (!enabled && !alwaysComputeHintables) {
2149
disconnectObservers();
2250
clearWrappersAll();
23-
enabled = false;
2451
}
52+
53+
enabled = newEnabled;
2554
}
2655

2756
export default async function observe() {
2857
enabled = getToggles().computed;
29-
if (enabled) {
58+
if (enabled || getCachedSetting("alwaysComputeHintables")) {
3059
// We observe all the initial elements before any mutation
3160
if (document.body) addWrappersFrom(document.body);
3261

‎src/content/settings/watchSettingsChanges.ts

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ async function handleSettingsChanges(
3636
await notifyTogglesStatus();
3737
}
3838

39+
if ("alwaysComputeHintables" in changes) {
40+
await updateHintsEnabled();
41+
}
42+
3943
if ("keyboardClicking" in changes) {
4044
const keyboardClicking = getCachedSetting("keyboardClicking");
4145

‎src/content/wrappers/wrappers.ts

+18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ElementWrapper } from "../../typings/ElementWrapper";
2+
import { getToggles } from "../settings/toggles";
23
import { deepGetElements } from "../utils/deepGetElements";
34

45
const wrappersAll: Map<Element, ElementWrapper> = new Map();
@@ -34,6 +35,11 @@ export function getWrapper(
3435
}
3536

3637
if (Array.isArray(key)) {
38+
// The hints might be off and all hintedWrappers only exist because of
39+
// alwaysComputeHintables being on. In that case we make as if there weren't
40+
// any hinted wrappers for any given hint string.
41+
if (!getToggles().computed) return [];
42+
3743
result = [];
3844
for (const string of key) {
3945
if (wrappersHinted.has(string)) {
@@ -107,3 +113,15 @@ export function clearWrappersAll() {
107113
wrappersAll.clear();
108114
wrappersHinted.clear();
109115
}
116+
117+
export function hideHintsAll() {
118+
for (const wrapper of wrappersHinted.values()) {
119+
wrapper?.hint?.hide();
120+
}
121+
}
122+
123+
export function showHintsAll() {
124+
for (const wrapper of wrappersHinted.values()) {
125+
wrapper?.hint?.show();
126+
}
127+
}

‎src/settings/SettingsComponent.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ export function SettingsComponent() {
6969
return (
7070
<div className="Settings">
7171
<SettingsGroup label="General">
72+
<SettingRow>
73+
<Toggle
74+
label="Always compute hintable elements"
75+
isPressed={settings.alwaysComputeHintables}
76+
onClick={() => {
77+
handleChange(
78+
"alwaysComputeHintables",
79+
!settings.alwaysComputeHintables
80+
);
81+
}}
82+
>
83+
<p className="explanation">
84+
Always compute what elements should be hinted even if the hints
85+
are toggled off. This makes switching hints on quicker.
86+
</p>
87+
</Toggle>
88+
</SettingRow>
7289
<SettingRow>
7390
<Toggle
7491
label="Show What's New page after updating"

‎src/typings/Hint.ts

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export interface Hint {
4747
* @returns
4848
*/
4949
release(keepInCache?: boolean, removeElement?: boolean): void;
50+
hide(): void;
51+
show(): void;
5052
reattach(): void;
5153
applyDefaultStyle(): void;
5254
keyHighlight(): void;

‎src/typings/StorageSchema.ts

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ export const zStorageSchema = z.object({
5454
hintsTogglePaths: z.map(z.string(), z.boolean()),
5555
hintsToggleTabs: z.map(z.number(), z.boolean()),
5656

57+
// Always compute hintables
58+
alwaysComputeHintables: z.boolean(),
59+
5760
// Notifications
5861
enableNotifications: z.boolean(),
5962
toastPosition: z.enum([

0 commit comments

Comments
 (0)
Please sign in to comment.