Skip to content

Commit 63c0b52

Browse files
authored
fix: Broken preferences (#267)
This PR fixes the broken preferences. This issue occurs by #193, since v0.5.0. Close #233 and #258.
1 parent 6084379 commit 63c0b52

13 files changed

+92
-31
lines changed

.eslintrc

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"eslint:recommended",
1111
"plugin:@typescript-eslint/recommended",
1212
"plugin:react/recommended",
13-
"plugin:prettier/recommended",
13+
"plugin:prettier/recommended"
1414
],
1515
"plugins": [
1616
"@typescript-eslint",
@@ -34,7 +34,8 @@
3434
"@typescript-eslint/no-empty-function": "off",
3535
"@typescript-eslint/no-explicit-any": "off",
3636
"@typescript-eslint/no-non-null-assertion": "off",
37-
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
37+
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
38+
"no-console": "error"
3839
},
3940
"overrides": [
4041
{

src/background/clients/ConsoleMessageSender.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const newSender = (tabId: number, frameId?: number) => {
77
const sender = new Sender<Schema>((type: Key, args: Request) => {
88
if (process.env.NODE_ENV === "development") {
99
const style = "background-color: green; color: white; padding: 4px;";
10+
// eslint-disable-next-line no-console
1011
console.debug("%cSEND%c %s %o", style, "", type, args);
1112
}
1213

src/background/clients/ContentMessageSender.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const newSender = (tabId: number, frameId?: number) => {
88
if (process.env.NODE_ENV === "development") {
99
const style = "background-color: green; color: white; padding: 4px;";
1010
const reset = "background-color: unset; color: unset; padding: unset;";
11+
// eslint-disable-next-line no-console
1112
console.debug("%cSEND%c %s %o", style, reset, type, args);
1213
}
1314

src/background/messaging/BackgroundMessageListener.ts

+4
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export default class BackgroundMessageListener {
8686
) => {
8787
const ctx: RequestContext = { sender };
8888
if (typeof message !== "object" && message !== null) {
89+
// eslint-disable-next-line no-console
8990
console.warn("unexpected message format:", message);
9091
return;
9192
}
@@ -94,19 +95,22 @@ export default class BackgroundMessageListener {
9495
typeof type !== "string" ||
9596
(typeof args !== "undefined" && typeof args !== "object")
9697
) {
98+
// eslint-disable-next-line no-console
9799
console.warn("unexpected message format:", message);
98100
return;
99101
}
100102

101103
if (process.env.NODE_ENV === "development") {
102104
const style = "background-color: purple; color: white; padding: 4px;";
105+
// eslint-disable-next-line no-console
103106
console.debug("%cRECEIVE%c %s %o", style, "", type, args);
104107
}
105108

106109
Promise.resolve()
107110
.then(() => this.receiver.receive(ctx, type, args))
108111
.then(sendResponse)
109112
.catch((err) => {
113+
// eslint-disable-next-line no-console
110114
console.error(err);
111115
if (!sender.tab || !sender.tab.id) {
112116
return;

src/background/settings/PropertySettings.ts

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export class PropertySettingsImpl {
4747
try {
4848
def.validate(value);
4949
} catch (e) {
50+
// eslint-disable-next-line no-console
5051
console.warn(`Property ${name} has invalid value: ${e.message}`);
5152
return def.defaultValue();
5253
}

src/background/settings/SettingsRepository.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ export class PermanentSettingsRepository implements SettingsRepository {
2424
try {
2525
return deserialize(settings);
2626
} catch (e) {
27+
// eslint-disable-next-line no-console
2728
console.warn("settings may be storage is broken:", e);
28-
console.warn("loaded settings is:");
29-
console.warn(settings);
29+
// eslint-disable-next-line no-console
30+
console.warn("loaded settings is:", settings);
3031
return defaultSettings;
3132
}
3233
}
@@ -48,9 +49,10 @@ export class PermanentSettingsRepository implements SettingsRepository {
4849
try {
4950
settings = deserialize(changes.settings.newValue);
5051
} catch (e) {
52+
// eslint-disable-next-line no-console
5153
console.warn("settings may be storage is broken:", e);
52-
console.warn("loaded settings is:");
53-
console.warn(changes.settings.newValue);
54+
// eslint-disable-next-line no-console
55+
console.warn("loaded settings is:", changes.settings.newValue);
5456
return;
5557
}
5658

src/content/client/BackgroundMessageSender.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const newSender = () => {
77
const sender = new Sender<Schema>((type: Key, args: Request) => {
88
if (process.env.NODE_ENV === "development") {
99
const style = "background-color: green; color: white; padding: 4px;";
10+
// eslint-disable-next-line no-console
1011
console.debug("%cSEND%c %s %o", style, "", type, args);
1112
}
1213

src/content/controllers/KeymapController.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export default class KeymapController {
2424
// identify to continue of abandon the event propagation.
2525
this.operationUseCase
2626
.exec(op.name, op.props, op.repeat)
27+
// eslint-disable-next-line no-console
2728
.catch(console.error);
2829
return true;
2930
}

src/content/controllers/SettingsController.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default class SettingsController {
2626
}
2727
} catch (e) {
2828
// Sometime sendMessage fails when background script is not ready.
29+
// eslint-disable-next-line no-console
2930
console.warn(e);
3031
setTimeout(() => this.initSettings(), 1000);
3132
}

src/content/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const initDom = () => {
99
const app = container.resolve(Application);
1010
await app.init();
1111
} catch (e) {
12+
// eslint-disable-next-line no-console
1213
console.error(e);
1314
}
1415
})();

src/content/messaging/ContentMessageListener.ts

+4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export default class ContentMessageListener {
143143
chrome.runtime.onMessage.addListener(
144144
(message: unknown, _sender, sendResponse) => {
145145
if (typeof message !== "object" && message !== null) {
146+
// eslint-disable-next-line no-console
146147
console.warn("unexpected message format:", message);
147148
return;
148149
}
@@ -151,19 +152,22 @@ export default class ContentMessageListener {
151152
typeof type !== "string" ||
152153
(typeof args !== "undefined" && typeof args !== "object")
153154
) {
155+
// eslint-disable-next-line no-console
154156
console.warn("unexpected message format:", message);
155157
return;
156158
}
157159

158160
if (process.env.NODE_ENV === "development") {
159161
const style = "background-color: purple; color: white; padding: 4px;";
162+
// eslint-disable-next-line no-console
160163
console.debug("%cRECEIVE%c %s %o", style, "", type, args);
161164
}
162165

163166
const ret = this.receiver.receive(type, args);
164167
Promise.resolve(ret)
165168
.then(sendResponse)
166169
.catch((err) => {
170+
// eslint-disable-next-line no-console
167171
console.error(err);
168172
});
169173
return true;

src/content/messaging/WindowMessageListener.ts

+4
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ export default class WindowMessageListener {
4242
try {
4343
message = JSON.parse(event.data);
4444
} catch (e) {
45+
// eslint-disable-next-line no-console
4546
console.warn("unexpected message format:", e);
4647
return;
4748
}
4849

4950
if (typeof message !== "object" && message !== null) {
51+
// eslint-disable-next-line no-console
5052
console.warn("unexpected message format:", message);
5153
return;
5254
}
@@ -56,6 +58,7 @@ export default class WindowMessageListener {
5658
typeof type !== "string" ||
5759
(typeof args !== "undefined" && typeof args !== "object")
5860
) {
61+
// eslint-disable-next-line no-console
5962
console.warn("unexpected message format:", message);
6063
return;
6164
}
@@ -64,6 +67,7 @@ export default class WindowMessageListener {
6467
try {
6568
this.receiver.receive(ctx, type, args);
6669
} catch (e) {
70+
// eslint-disable-next-line no-console
6771
console.error(e);
6872
}
6973
});

src/options/components/TextArea.tsx

+64-25
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "prismjs/themes/prism-coy.css";
77
const Container = styled.div`
88
width: 100%;
99
height: 100%;
10-
resize: both;
10+
resize: none;
1111
overflow: auto;
1212
border: ButtonBorder 1px solid;
1313
border-radius: 4px;
@@ -18,13 +18,14 @@ const Container = styled.div`
1818

1919
const Content = styled.div`
2020
margin: 8px;
21+
font: 14px monospace;
2122
position: relative;
2223
overflow: hidden;
2324
`;
2425

2526
const StyledPre = styled.pre`
2627
position: absolute;
27-
font-size: 14px;
28+
font: inherit;
2829
width: 100%;
2930
height: 100%;
3031
resize: none;
@@ -34,7 +35,8 @@ const StyledPre = styled.pre`
3435

3536
const StyledTextarea = styled.textarea`
3637
position: absolute;
37-
font-size: 14px;
38+
overflow: hidden;
39+
font: inherit;
3840
width: 100%;
3941
height: 100%;
4042
padding: 0;
@@ -47,53 +49,87 @@ const StyledTextarea = styled.textarea`
4749
caret-color: CanvasText;
4850
`;
4951

52+
const TextMeasure = styled.div`
53+
font: inherit;
54+
position: absolute;
55+
visibility: hidden;
56+
`;
57+
5058
type Props = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
5159

5260
const TextArea: React.FC<Props> = (props) => {
5361
const highlightContainer = React.useRef<HTMLDivElement>(null);
5462
const container = React.useRef<HTMLDivElement>(null);
5563
const content = React.useRef<HTMLDivElement>(null);
5664
const textarea = React.useRef<HTMLTextAreaElement>(null);
65+
const measure = React.useRef<HTMLDivElement>(null);
5766
const [json, setJson] = React.useState(props.value as string);
5867

59-
React.useEffect(() => {
60-
highlight(json);
61-
}, []);
62-
6368
const onChange = React.useCallback(
6469
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
6570
setJson(e.target.value);
66-
highlight(e.target.value);
67-
autoResize();
6871
props.onChange?.(e);
6972
},
7073
[],
7174
);
7275

73-
const highlight = React.useCallback((source: string) => {
74-
if (!highlightContainer.current) {
75-
return;
76+
const [charWidth, charHeight] = React.useMemo(() => {
77+
if (!measure.current) {
78+
return [0, 0];
7679
}
80+
const { width, height } = measure.current.getBoundingClientRect();
81+
return [width, height];
82+
}, [measure.current]);
7783

78-
const highlighted = Prism.highlight(source, Prism.languages.json, "json");
79-
highlightContainer.current.innerHTML = highlighted;
80-
autoResize();
81-
}, []);
84+
const [cols, rows] = React.useMemo(() => {
85+
const lines = json.split("\n");
86+
const cols = Math.max(...lines.map((line) => line.length));
87+
const rows = lines.length;
88+
return [cols, rows];
89+
}, [json]);
8290

8391
const autoResize = React.useCallback(() => {
84-
if (!textarea.current || !content.current) {
92+
if (!textarea.current || !content.current || !container.current) {
8593
return;
8694
}
8795

88-
// shrink scroll area to get the correct scroll area
89-
content.current.style.width = "0";
90-
content.current.style.height = "0";
96+
// resize textarea
97+
const parentWidth = container.current.getBoundingClientRect().width - 16;
98+
content.current.style.width = `${Math.max(
99+
parentWidth,
100+
charWidth * cols,
101+
)}px`;
102+
content.current.style.height = `${charHeight * rows}px`;
103+
}, [
104+
textarea.current,
105+
content.current,
106+
container.current,
107+
charWidth,
108+
charHeight,
109+
cols,
110+
rows,
111+
]);
91112

92-
const { scrollHeight, scrollWidth } = textarea.current;
93-
console.log(scrollHeight, scrollWidth);
94-
content.current.style.width = `${scrollWidth}px`;
95-
content.current.style.height = `${scrollHeight}px`;
96-
}, []);
113+
React.useEffect(() => {
114+
if (!highlightContainer.current) {
115+
return;
116+
}
117+
const highlighted = Prism.highlight(json, Prism.languages.json, "json");
118+
highlightContainer.current.innerHTML = highlighted;
119+
autoResize();
120+
}, [json]);
121+
122+
React.useEffect(() => {
123+
setJson(props.value as string);
124+
}, [props.value]);
125+
126+
React.useEffect(() => {
127+
autoResize();
128+
window.addEventListener("resize", autoResize);
129+
return () => {
130+
window.removeEventListener("resize", autoResize);
131+
};
132+
}, [autoResize]);
97133

98134
return (
99135
<Container ref={container}>
@@ -104,11 +140,14 @@ const TextArea: React.FC<Props> = (props) => {
104140
<StyledTextarea
105141
{...props}
106142
wrap="off"
143+
cols={cols}
144+
rows={rows}
107145
ref={textarea}
108146
onChange={onChange}
109147
spellCheck={false}
110148
value={json}
111149
/>
150+
<TextMeasure ref={measure}>@</TextMeasure>
112151
</Content>
113152
</Container>
114153
);

0 commit comments

Comments
 (0)