Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/src/styles/media-queries-blue.scss
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@
}

.pageFriends {
.content .friends table {
.content .friends table,
.content .pendingRequests table {
font-size: 0.75rem;
}
}
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/styles/media-queries-brown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
display: none;
}
}
.content .pendingRequests table {
td:nth-child(2) {
display: none;
}
}
}

.pageAccountSettings [data-tab="blockedUsers"] {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/styles/media-queries-yellow.scss
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
}
}
.pageFriends {
.content .friends table {
.content .friends table,
.content .pendingRequests table {
font-size: 0.9rem;

.badge .text {
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/ts/commandline/lists/result-screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ const practiceSubgroup: CommandsSubgroup = {
});
},
},
{
id: "practiseWordsBoth",
display: "both",
exec: (): void => {
PractiseWords.init("words", true);
TestLogic.restart({
practiseMissed: true,
});
},
},
{
id: "practiseWordsCustom",
display: "custom...",
Expand Down
79 changes: 0 additions & 79 deletions frontend/src/ts/controllers/profile-search-controller.ts

This file was deleted.

5 changes: 5 additions & 0 deletions frontend/src/ts/controllers/route-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { isFunboxActive } from "../test/funbox/list";
import * as TestState from "../test/test-state";
import * as Notifications from "../elements/notifications";
import { LoadingOptions } from "../pages/page";
import * as NavigationEvent from "../observables/navigation-event";

//source: https://www.youtube.com/watch?v=OstALBk-jTc
// https://www.youtube.com/watch?v=OstALBk-jTc
Expand Down Expand Up @@ -249,3 +250,7 @@ document.addEventListener("DOMContentLoaded", () => {
}
});
});

NavigationEvent.subscribe((it) => {
void navigate(it.url, { data: it.data });
});
127 changes: 61 additions & 66 deletions frontend/src/ts/elements/input-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,80 +142,75 @@ export type ValidationOptions<T> = (T extends string
callback?: (result: ValidationResult) => void;
};

export type ValidatedHtmlInputElement = HTMLInputElement & {
getValidationResult: () => ValidationResult;
setValue: (val: string | null) => void;
triggerValidation: () => void;
};
/**
* adds an 'InputIndicator` to the given `inputElement` and updates its status depending on the given validation
* @param inputElement
* @param options
*/
export function validateWithIndicator<T>(
inputElement: HTMLInputElement,
options: ValidationOptions<T>
): ValidatedHtmlInputElement {
//use indicator
const indicator = new InputIndicator(inputElement, {
success: {
icon: "fa-check",
level: 1,
},
failed: {
icon: "fa-times",
level: -1,
},
warning: {
icon: "fa-exclamation-triangle",
level: 1,
},
checking: {
icon: "fa-circle-notch",
spinIcon: true,
level: 0,
},
});

let currentStatus: ValidationResult = {
export class ValidatedHtmlInputElement<T = string> {
public native: HTMLInputElement;
private indicator: InputIndicator;
private currentStatus: ValidationResult = {
status: "checking",
};
const callback = (result: ValidationResult): void => {
currentStatus = result;
if (result.status === "failed" || result.status === "warning") {
indicator.show(result.status, result.errorMessage);
} else {
indicator.show(result.status);
}
options.callback?.(result);
};

const handler = createInputEventHandler(
callback,
options,
"inputValueConvert" in options ? options.inputValueConvert : undefined
);
constructor(inputElement: HTMLInputElement, options: ValidationOptions<T>) {
this.native = inputElement;

inputElement.addEventListener("input", handler);
this.indicator = new InputIndicator(inputElement, {
success: {
icon: "fa-check",
level: 1,
},
failed: {
icon: "fa-times",
level: -1,
},
warning: {
icon: "fa-exclamation-triangle",
level: 1,
},
checking: {
icon: "fa-circle-notch",
spinIcon: true,
level: 0,
},
});

const result = inputElement as ValidatedHtmlInputElement;
result.getValidationResult = () => {
return currentStatus;
};
result.setValue = (val: string | null) => {
inputElement.value = val ?? "";
const callback = (result: ValidationResult): void => {
this.currentStatus = result;
if (result.status === "failed" || result.status === "warning") {
this.indicator.show(result.status, result.errorMessage);
} else {
this.indicator.show(result.status);
}
options.callback?.(result);
};

const handler = createInputEventHandler(
callback,
options,
"inputValueConvert" in options ? options.inputValueConvert : undefined
);

inputElement.addEventListener("input", handler);
}

getValidationResult(): ValidationResult {
return this.currentStatus;
}
setValue(val: string | null): this {
this.native.value = val ?? "";
if (val === null) {
indicator.hide();
currentStatus = { status: "checking" };
this.indicator.hide();
this.currentStatus = { status: "checking" };
} else {
inputElement.dispatchEvent(new Event("input"));
this.native.dispatchEvent(new Event("input"));
}
};
result.triggerValidation = () => {
inputElement.dispatchEvent(new Event("input"));
};

return result;
return this;
}
getValue(): string {
return this.native.value;
}
triggerValidation(): void {
this.native.dispatchEvent(new Event("input"));
}
}

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

validateWithIndicator(input, {
new ValidatedHtmlInputElement(input, {
schema: validation.schema ? schema : undefined,
//@ts-expect-error this is fine
isValid: validation.isValid,
Expand Down
42 changes: 21 additions & 21 deletions frontend/src/ts/elements/keymap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { areSortedArraysEqual } from "../utils/arrays";
import { LayoutObject } from "@monkeytype/schemas/layouts";
import { animate } from "animejs";

export const keyDataDelimiter = "~~";
export const keyDataDelimiter = "\uE000";

const stenoKeys: LayoutObject = {
keymapShowTopRow: true,
Expand Down Expand Up @@ -58,27 +58,30 @@ const stenoKeys: LayoutObject = {
},
};

function findKeyElements(char: string): JQuery {
if (char === " ") {
return $("#keymap .keySpace");
}

if (char === '"') {
return $(`#keymap .keymapKey[data-key*='${char}']`);
}

return $(`#keymap .keymapKey[data-key*="${char}"]`);
}

function highlightKey(currentKey: string): void {
if (Config.mode === "zen") return;
if (currentKey === "") currentKey = " ";
try {
$(".activeKey").removeClass("activeKey");

let highlightKey;
if (Config.language.startsWith("korean")) {
currentKey = Hangul.disassemble(currentKey)[0] ?? currentKey;
}
if (currentKey === " ") {
highlightKey = "#keymap .keySpace";
} else if (currentKey === '"') {
highlightKey = `#keymap .keymapKey[data-key*='${currentKey}']`;
} else {
highlightKey = `#keymap .keymapKey[data-key*="${currentKey}"]`;
}

// console.log("highlighting", highlightKey);

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

async function flashKey(key: string, correct?: boolean): Promise<void> {
if (key === undefined) return;
//console.log("key", key);
if (key === " ") {
key = "#keymap .keySpace";
} else if (key === '"') {
key = `#keymap .keymapKey[data-key*='${key}']`;
} else {
key = `#keymap .keymapKey[data-key*="${key}"]`;
}

const $target = findKeyElements(key);

const elements = $target.toArray();
if (elements.length === 0) return;

const themecolors = await ThemeColors.getAll();

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

animate(key, {
animate(elements, {
color: [startingStyle.color, themecolors.sub],
backgroundColor: [startingStyle.backgroundColor, themecolors.subAlt],
borderColor: [startingStyle.borderColor, themecolors.sub],
Expand Down
Loading
Loading