feat: add keymap size (@butterflycup, @fehmer, @miodec) (#5659)

This commit is contained in:
butterflycup 2024-07-29 14:39:57 +02:00 committed by GitHub
parent 936aac677f
commit c906bfbe26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 208 additions and 4 deletions

View file

@ -1,4 +1,5 @@
import * as Config from "../../src/ts/config";
import { CustomThemeColors } from "@monkeytype/contracts/schemas/configs";
import { randomBytes } from "crypto";
@ -188,6 +189,22 @@ describe("Config", () => {
expect(Config.setKeymapShowTopRow("never")).toBe(true);
expect(Config.setKeymapShowTopRow("invalid" as any)).toBe(false);
});
it("setKeymapSize", () => {
expect(Config.setKeymapSize(0.5)).toBe(true);
expect(Config.setKeymapSize(2)).toBe(true);
expect(Config.setKeymapSize(3.5)).toBe(true);
expect(Config.setKeymapSize("invalid" as any)).toBe(false);
//invalid values being "auto-fixed"
expect(Config.setKeymapSize(0)).toBe(true);
expect(Config.default.keymapSize).toBe(0.5);
expect(Config.setKeymapSize(4)).toBe(true);
expect(Config.default.keymapSize).toBe(3.5);
expect(Config.setKeymapSize(1.25)).toBe(true);
expect(Config.default.keymapSize).toBe(1.3);
expect(Config.setKeymapSize(1.24)).toBe(true);
expect(Config.default.keymapSize).toBe(1.2);
});
it("setCustomBackgroundSize", () => {
expect(Config.setCustomBackgroundSize("contain")).toBe(true);
expect(Config.setCustomBackgroundSize("cover")).toBe(true);

View file

@ -1049,6 +1049,19 @@
<button data-config-value="never">never</button>
</div>
</div>
<div class="section" data-config-name="keymapSize">
<div class="groupTitle">
<i class="fas fa-keyboard"></i>
<span>keymap size</span>
</div>
<div class="text">Change the size of the keymap.</div>
<div class="inputs">
<div class="rangeGroup">
<div class="value">1.0</div>
<input type="range" min="0.5" max="3.5" step="0.1" />
</div>
</div>
</div>
<div class="sectionSpacer"></div>
</div>

View file

@ -70,6 +70,12 @@
}
}
.rangeGroup {
display: grid;
grid-template-columns: auto 1fr;
gap: 1rem;
}
&[data-config-name="autoSwitchThemeInputs"] {
grid-template-areas: unset;
grid-template-columns: 1fr 3fr 1fr 3fr;

View file

@ -56,6 +56,7 @@ import KeymapModeCommands from "./lists/keymap-mode";
import KeymapStyleCommands from "./lists/keymap-style";
import KeymapLegendStyleCommands from "./lists/keymap-legend-style";
import KeymapShowTopRowCommands from "./lists/keymap-show-top-row";
import KeymapSizeCommands from "./lists/keymap-size";
import EnableAdsCommands from "./lists/enable-ads";
import MonkeyPowerLevelCommands from "./lists/monkey-power-level";
import BailOutCommands from "./lists/bail-out";
@ -296,6 +297,7 @@ export const commands: MonkeyTypes.CommandsSubgroup = {
...KeymapModeCommands,
...KeymapStyleCommands,
...KeymapLegendStyleCommands,
...KeymapSizeCommands,
...KeymapLayoutsCommands,
...KeymapShowTopRowCommands,

View file

@ -0,0 +1,19 @@
import Config, * as UpdateConfig from "../../config";
const commands: MonkeyTypes.Command[] = [
{
id: "changeKeymapSize",
display: "Keymap size...",
icon: "fa-keyboard",
alias: "keyboard",
input: true,
defaultValue: (): string => {
return Config.keymapSize.toString();
},
exec: ({ input }): void => {
if (input === undefined || input === "") return;
UpdateConfig.setKeymapSize(parseFloat(input));
},
},
];
export default commands;

View file

@ -19,6 +19,7 @@ import {
import { isDevEnvironment, reloadAfter } from "./utils/misc";
import * as ConfigSchemas from "@monkeytype/contracts/schemas/configs";
import { Config } from "@monkeytype/contracts/schemas/configs";
import { roundTo1 } from "./utils/numbers";
export let localStorageConfig: Config;
@ -1701,6 +1702,38 @@ export function setKeymapShowTopRow(
return true;
}
export function setKeymapSize(
keymapSize: ConfigSchemas.KeymapSize,
nosave?: boolean
): boolean {
//auto-fix values to avoid validation errors
if (keymapSize < 0.5) keymapSize = 0.5;
if (keymapSize > 3.5) keymapSize = 3.5;
keymapSize = roundTo1(keymapSize);
if (
!isConfigValueValid(
"keymap size",
keymapSize,
ConfigSchemas.KeymapSizeSchema
)
) {
return false;
}
config.keymapSize = keymapSize;
$("#keymap").css("zoom", keymapSize);
saveToLocalStorage("keymapSize", nosave);
ConfigEvent.dispatch("keymapSize", config.keymapSize, nosave);
// trigger a resize event to update the layout - handled in ui.ts:108
$(window).trigger("resize");
return true;
}
export function setLayout(
layout: ConfigSchemas.Layout,
nosave?: boolean

View file

@ -59,6 +59,7 @@ export default {
keymapLegendStyle: "lowercase",
keymapLayout: "overrideSync",
keymapShowTopRow: "layout",
keymapSize: 1,
fontFamily: "Roboto_Mono",
smoothLineScroll: false,
alwaysShowDecimalPlaces: false,

View file

@ -3,18 +3,21 @@ import Config from "../../config";
import * as Notifications from "../notifications";
// @ts-expect-error TODO: update slim-select
import SlimSelect from "slim-select";
import { debounce } from "throttle-debounce";
type Mode = "select" | "button" | "range";
export default class SettingsGroup<T extends ConfigValue> {
public configName: string;
public configValue: T;
public configFunction: (param: T, nosave?: boolean) => boolean;
public mode: string;
public mode: Mode;
public setCallback?: () => void;
public updateCallback?: () => void;
constructor(
configName: string,
configFunction: (param: T, nosave?: boolean) => boolean,
mode: string,
mode: Mode,
setCallback?: () => void,
updateCallback?: () => void
) {
@ -67,6 +70,29 @@ export default class SettingsGroup<T extends ConfigValue> {
this.setValue(typed as T);
}
);
} else if (this.mode === "range") {
const rangeElement = document.querySelector(
`.pageSettings .section[data-config-name=${this.configName}] input[type=range]`
);
if (!rangeElement) {
Notifications.add(`Failed to find range element for ${configName}`, -1);
return;
}
const debounced = debounce(250, (val) => {
this.setValue(val);
});
rangeElement.addEventListener("input", (e) => {
const target = $(e.target as HTMLInputElement);
if (target.hasClass("disabled") || target.hasClass("no-auto-handle")) {
return;
}
const val = parseFloat(target.val() as string) as unknown as T;
this.updateUI(val);
debounced(val);
});
}
}
@ -76,8 +102,9 @@ export default class SettingsGroup<T extends ConfigValue> {
if (this.setCallback) this.setCallback();
}
updateUI(): void {
this.configValue = Config[this.configName as keyof typeof Config] as T;
updateUI(valueOverride?: T): void {
this.configValue =
valueOverride ?? (Config[this.configName as keyof typeof Config] as T);
$(
`.pageSettings .section[data-config-name='${this.configName}'] button`
).removeClass("active");
@ -103,6 +130,20 @@ export default class SettingsGroup<T extends ConfigValue> {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
`.pageSettings .section[data-config-name='${this.configName}'] button[data-config-value='${this.configValue}']`
).addClass("active");
} else if (this.mode === "range") {
const range = document.querySelector(
`.pageSettings .section[data-config-name='${this.configName}'] input[type=range]`
) as HTMLInputElement | null;
const rangeValue = document.querySelector(
`.pageSettings .section[data-config-name='${this.configName}'] .value`
) as HTMLSpanElement | null;
if (range === null || rangeValue === null) {
return;
}
range.value = this.configValue as unknown as string;
rangeValue.textContent = `${(this.configValue as number).toFixed(1)}`;
}
if (this.updateCallback) this.updateCallback();
}

View file

@ -72,6 +72,9 @@ async function initGroups(): Promise<void> {
$(
".pageSettings .section[data-config-name='keymapShowTopRow']"
).addClass("hidden");
$(".pageSettings .section[data-config-name='keymapSize']").addClass(
"hidden"
);
} else {
$(".pageSettings .section[data-config-name='keymapStyle']").removeClass(
"hidden"
@ -85,6 +88,9 @@ async function initGroups(): Promise<void> {
$(
".pageSettings .section[data-config-name='keymapShowTopRow']"
).removeClass("hidden");
$(".pageSettings .section[data-config-name='keymapSize']").removeClass(
"hidden"
);
}
}
) as SettingsGroup<ConfigValue>;
@ -108,6 +114,11 @@ async function initGroups(): Promise<void> {
UpdateConfig.setKeymapShowTopRow,
"button"
) as SettingsGroup<ConfigValue>;
groups["keymapSize"] = new SettingsGroup(
"keymapSize",
UpdateConfig.setKeymapSize,
"range"
) as SettingsGroup<ConfigValue>;
groups["showKeyTips"] = new SettingsGroup(
"showKeyTips",
UpdateConfig.setKeyTips,
@ -671,6 +682,10 @@ async function fillSettingsPage(): Promise<void> {
Config.maxLineWidth
);
$(".pageSettings .section[data-config-name='keymapSize'] input").val(
Config.keymapSize
);
$(".pageSettings .section[data-config-name='customLayoutfluid'] input").val(
Config.customLayoutfluid.replace(/#/g, " ")
);
@ -1311,6 +1326,59 @@ $(
}
});
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton button.save"
).on("click", () => {
const didConfigSave = UpdateConfig.setKeymapSize(
parseFloat(
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton input"
).val() as string
)
);
if (didConfigSave) {
Notifications.add("Saved", 1, {
duration: 1,
});
}
});
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton input"
).on("focusout", () => {
const didConfigSave = UpdateConfig.setKeymapSize(
parseFloat(
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton input"
).val() as string
)
);
if (didConfigSave) {
Notifications.add("Saved", 1, {
duration: 1,
});
}
});
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton input"
).on("keypress", (e) => {
if (e.key === "Enter") {
const didConfigSave = UpdateConfig.setKeymapSize(
parseFloat(
$(
".pageSettings .section[data-config-name='keymapSize'] .inputAndButton input"
).val() as string
)
);
if (didConfigSave) {
Notifications.add("Saved", 1, {
duration: 1,
});
}
}
});
$(
".pageSettings .section[data-config-name='customLayoutfluid'] .inputAndButton button.save"
).on("click", () => {

View file

@ -90,6 +90,9 @@ export type KeymapLegendStyle = z.infer<typeof KeymapLegendStyleSchema>;
export const KeymapShowTopRowSchema = z.enum(["always", "layout", "never"]);
export type KeymapShowTopRow = z.infer<typeof KeymapShowTopRowSchema>;
export const KeymapSizeSchema = z.number().min(0.5).max(3.5).step(0.1);
export type KeymapSize = z.infer<typeof KeymapSizeSchema>;
export const SingleListCommandLineSchema = z.enum(["manual", "on"]);
export type SingleListCommandLine = z.infer<typeof SingleListCommandLineSchema>;
@ -342,6 +345,7 @@ export const ConfigSchema = z
keymapLegendStyle: KeymapLegendStyleSchema,
keymapLayout: KeymapLayoutSchema,
keymapShowTopRow: KeymapShowTopRowSchema,
keymapSize: KeymapSizeSchema,
fontFamily: FontFamilySchema,
smoothLineScroll: z.boolean(),
alwaysShowDecimalPlaces: z.boolean(),