Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c6afb3c
feat: add quick favorite toggle to theme picker (via footer current t…
byseif21 Apr 17, 2025
466343c
remove the notifications
byseif21 Apr 18, 2025
d9518eb
Merge branch 'master' into add-quick-favorite-toggle-theme-button
byseif21 Apr 18, 2025
99561f9
add keyboard accesibility for the star favorite toggle in the command…
byseif21 Apr 19, 2025
44ca091
unclickable star indcator
byseif21 Apr 27, 2025
1608471
modify the footer star to not sound clickable
byseif21 Apr 27, 2025
f2d391f
Merge branch 'master' into add-quick-favorite-toggle-theme-button
byseif21 May 8, 2025
243e6d7
remove keys acces
byseif21 May 8, 2025
d8a8f64
no need for hover if not favorite to not sound clickable
byseif21 May 8, 2025
8b0cd0c
resolve the conflictsand try aligning with the new changes
byseif21 May 8, 2025
3915e30
fix
byseif21 May 8, 2025
fcf942d
fix to algin with the cahnges and add initialization function, not ne…
byseif21 May 8, 2025
ddd1ff3
remove duplicated
byseif21 May 8, 2025
647a32a
cleanup
byseif21 May 8, 2025
d936bf4
replace the heart with star in the commandline for consistency?
byseif21 May 8, 2025
b852e1a
cleanup
byseif21 May 8, 2025
da4226a
refactor themes.ts a bit to impr maintainability
byseif21 May 8, 2025
87ce025
Merge branch 'master' into add-quick-favorite-toggle-theme-button
byseif21 May 12, 2025
52874ec
Merge branch 'master' into add-quick-favorite-toggle-theme-button
byseif21 May 15, 2025
ec296a1
update the star footer while themes being previewed
byseif21 May 15, 2025
ba7083c
refactor to reduce duplication
byseif21 May 16, 2025
1c2baed
refactor & move star footer to html
byseif21 May 16, 2025
0aa204d
Merge branch 'master' into add-quick-favorite-toggle-theme-button
byseif21 May 16, 2025
95088a6
Refactor theme favorite indicator updates to use config subscriptions
byseif21 May 18, 2025
ec29644
make getThemesList synchronous to remove unnecessary Promise overhead
byseif21 May 18, 2025
909716a
fix remove the useless fetch and use ThemesList directly
byseif21 May 19, 2025
762860f
revert
byseif21 May 19, 2025
75dd68f
no need for favorite icon for custom themes
byseif21 May 19, 2025
ff6fa94
support regular icon
Miodec May 29, 2025
3eda8cd
chore: ls with schema debug logs
Miodec May 17, 2025
88ade18
chore: disable rule
Miodec May 17, 2025
51e33c9
chore: remove anniversary elements
Miodec May 22, 2025
f325f34
feat(language): add viossa (@nginearing) (#6571)
Nginearing May 26, 2025
dda932e
fix(language): incorrect and non-standard words in kazakh_1K wordlist…
byseif21 May 26, 2025
036f7bb
fix(language): update Ukrainian Latin to national standard (@paiv) (#…
paiv May 26, 2025
89bf5ab
perf(test): optimize test-timer checkIfTimeIsUp (@fehmer) (#6588)
fehmer May 26, 2025
dd2cf0b
fix(theme): dark note and reduced-motion not replacing letters with c…
fehmer May 26, 2025
56b15e5
feat(layout): add Tarmak layouts (@siily-g) (#6574)
siily-g May 26, 2025
21fcc46
feat(profile): add Open Graph meta tags for social sharing (@TryOmar)…
TryOmar May 26, 2025
37a9840
docs: update PR template (@fehmer) (#6600)
fehmer May 26, 2025
e593e7a
fix: sanitize result filters before storing in LS (@fehmer) (#6583)
fehmer May 26, 2025
6621ddf
refactor: cleanup schema and types for CustomText (@fehmer) (#6605)
fehmer May 27, 2025
e3826de
chore: remove log (@fehmer) (#6601)
fehmer May 27, 2025
6d52acb
fix: compatability check header shown if client is using cached respo…
fehmer May 27, 2025
39b1ce9
chore: correct text in difficulty settings descriptions (@byseif21) (…
byseif21 May 27, 2025
80d675b
perf: use cache in local-storage-with-schema (@fehmer) (#6596)
fehmer May 27, 2025
61e6852
chore: release v25.22.0
Miodec May 27, 2025
c1c7e36
fix(commandline): improve caching to fix stale checkmark and UI state…
byseif21 May 27, 2025
4276c45
update indicator styling, html structure
Miodec May 29, 2025
06a08f7
Merge branch 'master' into add-quick-favorite-toggle-theme-button
Miodec May 29, 2025
81bb8ba
fix bubble alignment
Miodec May 29, 2025
11fada6
use custom data instead of adding another param to the command object…
Miodec May 29, 2025
eaef011
unnecessary code
Miodec May 29, 2025
fc300b4
move config event from footer to theme controller, connect text and f…
Miodec May 29, 2025
648befc
unnecessary function calls
Miodec May 29, 2025
d52796e
unnecessary extra comment
Miodec May 29, 2025
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
5 changes: 4 additions & 1 deletion frontend/src/html/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@
aria-label="Shift-click to toggle custom theme"
data-balloon-pos="left"
>
<i class="fas fa-fw fa-palette"></i>
<div class="icon">
<i class="fas fa-star favIndicator"></i>
<i class="fas fa-fw fa-palette"></i>
</div>
<div class="text">serika dark</div>
</button>
<button class="currentVersion textButton">
Expand Down
12 changes: 9 additions & 3 deletions frontend/src/styles/commandline.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
color: var(--sub-color);
}

.fas {
.fas,
.far {
margin-right: 0.5rem;
color: var(--sub-color);
}
Expand All @@ -86,11 +87,13 @@
}
}

&.withThemeBubbles {
grid-template-columns: auto 1fr auto;
&.changeThemeCommand {
grid-template-columns: auto 1fr auto auto;
position: relative;
.themeBubbles {
display: grid;
grid-auto-flow: column;
place-content: center;
gap: 0.5em;
border-radius: 1em;
.themeBubble {
Expand All @@ -99,6 +102,9 @@
border-radius: 100%;
}
}
.themeFavIcon {
margin-right: 0.25rem;
}
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/styles/footer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ footer {
}
}

.current-theme {
.icon {
position: relative;
.favIndicator {
font-size: 0.5em;
top: -0.5em;
right: -0.5em;
padding: 0.25em;
position: absolute;
background: var(--bg-color);
border-radius: 100%;
}
}
}

&.focus {
.keyTips {
opacity: 0 !important;
Expand Down
29 changes: 23 additions & 6 deletions frontend/src/ts/commandline/commandline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,12 @@ async function showCommands(): Promise<void> {
if (command.found !== true) continue;
let icon = command.icon ?? "fa-chevron-right";
const faIcon = icon.startsWith("fa-");
const iconType = command.iconType ?? "solid";
const iconTypeClass = iconType === "solid" ? "fas" : "far";
if (!faIcon) {
icon = `<div class="textIcon">${icon}</div>`;
} else {
icon = `<i class="fas fa-fw ${icon}"></i>`;
icon = `<i class="${iconTypeClass} fa-fw ${icon}"></i>`;
}
let configIcon = "";
if (command.isActive) {
Expand Down Expand Up @@ -451,12 +453,27 @@ async function showCommands(): Promise<void> {

if (command.customData !== undefined) {
if (command.id.startsWith("changeTheme")) {
html += `<div class="command withThemeBubbles" data-command-id="${command.id}" data-index="${index}" style="${customStyle}">
html += `<div class="command changeThemeCommand" data-command-id="${
command.id
}" data-index="${index}" style="${customStyle}">
${iconHTML}<div>${display}</div>
<div class="themeBubbles" style="background: ${command.customData["bgColor"]};outline: 0.25rem solid ${command.customData["bgColor"]};">
<div class="themeBubble" style="background: ${command.customData["mainColor"]}"></div>
<div class="themeBubble" style="background: ${command.customData["subColor"]}"></div>
<div class="themeBubble" style="background: ${command.customData["textColor"]}"></div>
<div class="themeFavIcon ${
command.customData["isFavorite"] === true ? "" : "hidden"
}">
<i class="fas fa-star"></i>
</div>
<div class="themeBubbles" style="background: ${
command.customData["bgColor"]
};outline: 0.25rem solid ${command.customData["bgColor"]};">
<div class="themeBubble" style="background: ${
command.customData["mainColor"]
}"></div>
<div class="themeBubble" style="background: ${
command.customData["subColor"]
}"></div>
<div class="themeBubble" style="background: ${
command.customData["textColor"]
}"></div>
</div>
</div>`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const commands: Command[] = [
{
id: "addThemeToFavorite",
display: "Add current theme to favorite",
icon: "fa-heart",
icon: "fa-star",
available: (): boolean => {
return (
!Config.customTheme &&
Expand All @@ -25,7 +25,8 @@ const commands: Command[] = [
{
id: "removeThemeFromFavorite",
display: "Remove current theme from favorite",
icon: "fa-heart-broken",
icon: "fa-star",
iconType: "regular",
available: (): boolean => {
return (
!Config.customTheme &&
Expand Down
61 changes: 53 additions & 8 deletions frontend/src/ts/commandline/lists/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import * as ThemeController from "../../controllers/theme-controller";
import { Command, CommandsSubgroup } from "../types";
import { Theme, ThemesList } from "../../constants/themes";
import { not } from "@monkeytype/util/predicates";
import * as ConfigEvent from "../../observables/config-event";
import * as Misc from "../../utils/misc";

const isFavorite = (theme: Theme): boolean =>
Config.favThemes.includes(theme.name);

const subgroup: CommandsSubgroup = {
title: "Theme...",
configKey: "theme",
list: [
...ThemesList.filter(isFavorite),
...ThemesList.filter(not(isFavorite)),
].map((theme: Theme) => ({
/**
* creates a theme command object for the given theme
* @param theme the theme to create a command for
* @returns a command object for the theme
*/
const createThemeCommand = (theme: Theme): Command => {
return {
id: "changeTheme" + capitalizeFirstLetterOfEachWord(theme.name),
display: theme.name.replace(/_/g, " "),
configValue: theme.name,
Expand All @@ -24,6 +26,7 @@ const subgroup: CommandsSubgroup = {
bgColor: theme.bgColor,
subColor: theme.subColor,
textColor: theme.textColor,
isFavorite: isFavorite(theme),
},
hover: (): void => {
// previewTheme(theme.name);
Expand All @@ -32,7 +35,25 @@ const subgroup: CommandsSubgroup = {
exec: (): void => {
UpdateConfig.setTheme(theme.name);
},
})),
};
};

/**
* sorts themes with favorites first, then non-favorites
* @param themes the themes to sort
* @returns sorted array of themes
*/
const sortThemesByFavorite = (themes: Theme[]): Theme[] => [
...themes.filter(isFavorite),
...themes.filter(not(isFavorite)),
];

const subgroup: CommandsSubgroup = {
title: "Theme...",
configKey: "theme",
list: sortThemesByFavorite(ThemesList).map((theme) =>
createThemeCommand(theme)
),
};

const commands: Command[] = [
Expand All @@ -44,4 +65,28 @@ const commands: Command[] = [
},
];

export function update(themes: Theme[]): void {
// clear the current list
subgroup.list = [];

// rebuild with favorites first, then non-favorites
subgroup.list = sortThemesByFavorite(themes).map((theme) =>
createThemeCommand(theme)
);
}

// subscribe to theme-related config events to update the theme command list
ConfigEvent.subscribe((eventKey, _eventValue) => {
if (eventKey === "favThemes") {
// update themes list when favorites change
try {
update(ThemesList);
} catch (e: unknown) {
console.error(
Misc.createErrorMessage(e, "Failed to update themes commands")
);
}
}
});

export default commands;
1 change: 1 addition & 0 deletions frontend/src/ts/commandline/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type Command = {
subgroup?: CommandsSubgroup;
found?: boolean;
icon?: string;
iconType?: "regular" | "solid";
sticky?: boolean;
alias?: string;
input?: boolean;
Expand Down
51 changes: 48 additions & 3 deletions frontend/src/ts/controllers/theme-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ async function apply(
void updateFavicon();
$("#metaThemeColor").attr("content", colors.bg);
// }
updateFooterThemeName(isPreview ? themeName : undefined);
updateFooterIndicator(isPreview ? themeName : undefined);

if (isColorDark(await ThemeColors.get("bg"))) {
$("body").addClass("darkMode");
Expand All @@ -188,13 +188,47 @@ async function apply(
}
}

function updateFooterThemeName(nameOverride?: string): void {
function updateFooterIndicator(nameOverride?: string): void {
const indicator = document.querySelector<HTMLElement>(
"footer .right .current-theme"
);
const text = indicator?.querySelector<HTMLElement>(".text");
const favIcon = indicator?.querySelector<HTMLElement>(".favIndicator");

if (
!(indicator instanceof HTMLElement) ||
!(text instanceof HTMLElement) ||
!(favIcon instanceof HTMLElement)
) {
return;
}

//text
let str: string = Config.theme;
if (randomTheme !== null) str = randomTheme;
if (Config.customTheme) str = "custom";
if (nameOverride !== undefined && nameOverride !== "") str = nameOverride;
str = str.replace(/_/g, " ");
$(".current-theme .text").text(str);
text.innerText = str;

//fav icon
const isCustom = Config.customTheme;
// hide the favorite icon completely for custom themes
if (isCustom) {
favIcon.style.display = "none";
return;
}
favIcon.style.display = "";
const currentTheme = nameOverride ?? randomTheme ?? Config.theme;
const isFavorite =
currentTheme !== null &&
Config.favThemes.includes(currentTheme as ThemeName);

if (isFavorite) {
favIcon.style.display = "block";
} else {
favIcon.style.display = "none";
}
}

export function preview(
Expand Down Expand Up @@ -433,6 +467,17 @@ ConfigEvent.subscribe(async (eventKey, eventValue, nosave) => {
) {
await set(Config.themeDark, true);
}
if (
[
"theme",
"customTheme",
"customThemeColors",
"randomTheme",
"favThemes",
].includes(eventKey)
) {
updateFooterIndicator();
}
});

window.addEventListener("customBackgroundFailed", () => {
Expand Down