Skip to content

Commit 0b06fbe

Browse files
committed
Merge branch 'master' into prettier-upgrade
2 parents f6b01df + a875aa6 commit 0b06fbe

32 files changed

+1244
-1138
lines changed

frontend/src/styles/media-queries-blue.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@
245245
}
246246

247247
.pageFriends {
248-
.content .friends table {
248+
.content .friends table,
249+
.content .pendingRequests table {
249250
font-size: 0.75rem;
250251
}
251252
}

frontend/src/styles/media-queries-brown.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@
107107
display: none;
108108
}
109109
}
110+
.content .pendingRequests table {
111+
td:nth-child(2) {
112+
display: none;
113+
}
114+
}
110115
}
111116

112117
.pageAccountSettings [data-tab="blockedUsers"] {

frontend/src/styles/media-queries-yellow.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@
9191
}
9292
}
9393
.pageFriends {
94-
.content .friends table {
94+
.content .friends table,
95+
.content .pendingRequests table {
9596
font-size: 0.9rem;
9697

9798
.badge .text {

frontend/src/ts/commandline/lists/result-screen.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ const practiceSubgroup: CommandsSubgroup = {
3333
});
3434
},
3535
},
36+
{
37+
id: "practiseWordsBoth",
38+
display: "both",
39+
exec: (): void => {
40+
PractiseWords.init("words", true);
41+
TestLogic.restart({
42+
practiseMissed: true,
43+
});
44+
},
45+
},
3646
{
3747
id: "practiseWordsCustom",
3848
display: "custom...",

frontend/src/ts/controllers/profile-search-controller.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.

frontend/src/ts/controllers/route-controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { isFunboxActive } from "../test/funbox/list";
66
import * as TestState from "../test/test-state";
77
import * as Notifications from "../elements/notifications";
88
import { LoadingOptions } from "../pages/page";
9+
import * as NavigationEvent from "../observables/navigation-event";
910

1011
//source: https://www.youtube.com/watch?v=OstALBk-jTc
1112
// https://www.youtube.com/watch?v=OstALBk-jTc
@@ -249,3 +250,7 @@ document.addEventListener("DOMContentLoaded", () => {
249250
}
250251
});
251252
});
253+
254+
NavigationEvent.subscribe((it) => {
255+
void navigate(it.url, { data: it.data });
256+
});

frontend/src/ts/elements/input-validation.ts

Lines changed: 61 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -142,80 +142,75 @@ export type ValidationOptions<T> = (T extends string
142142
callback?: (result: ValidationResult) => void;
143143
};
144144

145-
export type ValidatedHtmlInputElement = HTMLInputElement & {
146-
getValidationResult: () => ValidationResult;
147-
setValue: (val: string | null) => void;
148-
triggerValidation: () => void;
149-
};
150-
/**
151-
* adds an 'InputIndicator` to the given `inputElement` and updates its status depending on the given validation
152-
* @param inputElement
153-
* @param options
154-
*/
155-
export function validateWithIndicator<T>(
156-
inputElement: HTMLInputElement,
157-
options: ValidationOptions<T>
158-
): ValidatedHtmlInputElement {
159-
//use indicator
160-
const indicator = new InputIndicator(inputElement, {
161-
success: {
162-
icon: "fa-check",
163-
level: 1,
164-
},
165-
failed: {
166-
icon: "fa-times",
167-
level: -1,
168-
},
169-
warning: {
170-
icon: "fa-exclamation-triangle",
171-
level: 1,
172-
},
173-
checking: {
174-
icon: "fa-circle-notch",
175-
spinIcon: true,
176-
level: 0,
177-
},
178-
});
179-
180-
let currentStatus: ValidationResult = {
145+
export class ValidatedHtmlInputElement<T = string> {
146+
public native: HTMLInputElement;
147+
private indicator: InputIndicator;
148+
private currentStatus: ValidationResult = {
181149
status: "checking",
182150
};
183-
const callback = (result: ValidationResult): void => {
184-
currentStatus = result;
185-
if (result.status === "failed" || result.status === "warning") {
186-
indicator.show(result.status, result.errorMessage);
187-
} else {
188-
indicator.show(result.status);
189-
}
190-
options.callback?.(result);
191-
};
192151

193-
const handler = createInputEventHandler(
194-
callback,
195-
options,
196-
"inputValueConvert" in options ? options.inputValueConvert : undefined
197-
);
152+
constructor(inputElement: HTMLInputElement, options: ValidationOptions<T>) {
153+
this.native = inputElement;
198154

199-
inputElement.addEventListener("input", handler);
155+
this.indicator = new InputIndicator(inputElement, {
156+
success: {
157+
icon: "fa-check",
158+
level: 1,
159+
},
160+
failed: {
161+
icon: "fa-times",
162+
level: -1,
163+
},
164+
warning: {
165+
icon: "fa-exclamation-triangle",
166+
level: 1,
167+
},
168+
checking: {
169+
icon: "fa-circle-notch",
170+
spinIcon: true,
171+
level: 0,
172+
},
173+
});
200174

201-
const result = inputElement as ValidatedHtmlInputElement;
202-
result.getValidationResult = () => {
203-
return currentStatus;
204-
};
205-
result.setValue = (val: string | null) => {
206-
inputElement.value = val ?? "";
175+
const callback = (result: ValidationResult): void => {
176+
this.currentStatus = result;
177+
if (result.status === "failed" || result.status === "warning") {
178+
this.indicator.show(result.status, result.errorMessage);
179+
} else {
180+
this.indicator.show(result.status);
181+
}
182+
options.callback?.(result);
183+
};
184+
185+
const handler = createInputEventHandler(
186+
callback,
187+
options,
188+
"inputValueConvert" in options ? options.inputValueConvert : undefined
189+
);
190+
191+
inputElement.addEventListener("input", handler);
192+
}
193+
194+
getValidationResult(): ValidationResult {
195+
return this.currentStatus;
196+
}
197+
setValue(val: string | null): this {
198+
this.native.value = val ?? "";
207199
if (val === null) {
208-
indicator.hide();
209-
currentStatus = { status: "checking" };
200+
this.indicator.hide();
201+
this.currentStatus = { status: "checking" };
210202
} else {
211-
inputElement.dispatchEvent(new Event("input"));
203+
this.native.dispatchEvent(new Event("input"));
212204
}
213-
};
214-
result.triggerValidation = () => {
215-
inputElement.dispatchEvent(new Event("input"));
216-
};
217205

218-
return result;
206+
return this;
207+
}
208+
getValue(): string {
209+
return this.native.value;
210+
}
211+
triggerValidation(): void {
212+
this.native.dispatchEvent(new Event("input"));
213+
}
219214
}
220215

221216
export type ConfigInputOptions<K extends ConfigKey, T = ConfigType[K]> = {
@@ -260,7 +255,7 @@ export function handleConfigInput<T extends ConfigKey>({
260255
if (validation !== undefined) {
261256
const schema = ConfigSchema.shape[configName] as ZodType;
262257

263-
validateWithIndicator(input, {
258+
new ValidatedHtmlInputElement(input, {
264259
schema: validation.schema ? schema : undefined,
265260
//@ts-expect-error this is fine
266261
isValid: validation.isValid,

frontend/src/ts/elements/keymap.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { areSortedArraysEqual } from "../utils/arrays";
1717
import { LayoutObject } from "@monkeytype/schemas/layouts";
1818
import { animate } from "animejs";
1919

20-
export const keyDataDelimiter = "~~";
20+
export const keyDataDelimiter = "\uE000";
2121

2222
const stenoKeys: LayoutObject = {
2323
keymapShowTopRow: true,
@@ -58,27 +58,30 @@ const stenoKeys: LayoutObject = {
5858
},
5959
};
6060

61+
function findKeyElements(char: string): JQuery {
62+
if (char === " ") {
63+
return $("#keymap .keySpace");
64+
}
65+
66+
if (char === '"') {
67+
return $(`#keymap .keymapKey[data-key*='${char}']`);
68+
}
69+
70+
return $(`#keymap .keymapKey[data-key*="${char}"]`);
71+
}
72+
6173
function highlightKey(currentKey: string): void {
6274
if (Config.mode === "zen") return;
6375
if (currentKey === "") currentKey = " ";
6476
try {
6577
$(".activeKey").removeClass("activeKey");
6678

67-
let highlightKey;
6879
if (Config.language.startsWith("korean")) {
6980
currentKey = Hangul.disassemble(currentKey)[0] ?? currentKey;
7081
}
71-
if (currentKey === " ") {
72-
highlightKey = "#keymap .keySpace";
73-
} else if (currentKey === '"') {
74-
highlightKey = `#keymap .keymapKey[data-key*='${currentKey}']`;
75-
} else {
76-
highlightKey = `#keymap .keymapKey[data-key*="${currentKey}"]`;
77-
}
78-
79-
// console.log("highlighting", highlightKey);
8082

81-
$(highlightKey).addClass("activeKey");
83+
const $target = findKeyElements(currentKey);
84+
$target.addClass("activeKey");
8285
} catch (e) {
8386
if (e instanceof Error) {
8487
console.log("could not update highlighted keymap key: " + e.message);
@@ -88,14 +91,11 @@ function highlightKey(currentKey: string): void {
8891

8992
async function flashKey(key: string, correct?: boolean): Promise<void> {
9093
if (key === undefined) return;
91-
//console.log("key", key);
92-
if (key === " ") {
93-
key = "#keymap .keySpace";
94-
} else if (key === '"') {
95-
key = `#keymap .keymapKey[data-key*='${key}']`;
96-
} else {
97-
key = `#keymap .keymapKey[data-key*="${key}"]`;
98-
}
94+
95+
const $target = findKeyElements(key);
96+
97+
const elements = $target.toArray();
98+
if (elements.length === 0) return;
9999

100100
const themecolors = await ThemeColors.getAll();
101101

@@ -120,7 +120,7 @@ async function flashKey(key: string, correct?: boolean): Promise<void> {
120120
};
121121
}
122122

123-
animate(key, {
123+
animate(elements, {
124124
color: [startingStyle.color, themecolors.sub],
125125
backgroundColor: [startingStyle.backgroundColor, themecolors.subAlt],
126126
borderColor: [startingStyle.borderColor, themecolors.sub],

0 commit comments

Comments
 (0)