Skip to content

Commit 5ba39c6

Browse files
committed
refactor: rework theme picker button and tab approach
split some of the code into smaller functions refactor some functions fix styling
1 parent d4d621e commit 5ba39c6

File tree

3 files changed

+153
-150
lines changed

3 files changed

+153
-150
lines changed

frontend/src/ts/elements/settings/theme-picker.ts

Lines changed: 148 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { isAuthenticated } from "../../firebase";
1313
import * as ActivePage from "../../states/active-page";
1414
import { CustomThemeColors } from "@monkeytype/contracts/schemas/configs";
1515
import { tryCatch } from "@monkeytype/util/trycatch";
16+
import { captureException } from "../../sentry";
1617

1718
function updateActiveButton(): void {
1819
let activeThemeName = Config.theme;
@@ -113,139 +114,152 @@ function updateColors(
113114
colorPicker.find("input.color").attr("value", color);
114115
}
115116

116-
export async function refreshButtons(): Promise<void> {
117-
if (Config.customTheme) {
118-
// Update custom theme buttons
119-
const customThemesEl = $(
120-
".pageSettings .section.themes .allCustomThemes.buttons"
121-
).empty();
122-
const addButton = $(".pageSettings .section.themes .addCustomThemeButton");
117+
export async function refreshPresetButtons(): Promise<void> {
118+
// Update theme buttons
119+
const favThemesEl = document.querySelector<HTMLElement>(
120+
".pageSettings .section.themes .favThemes.buttons"
121+
);
122+
const themesEl = document.querySelector<HTMLElement>(
123+
".pageSettings .section.themes .allThemes.buttons"
124+
);
123125

124-
if (!isAuthenticated()) {
125-
$(
126-
".pageSettings .section.themes .customThemeEdit #saveCustomThemeButton"
127-
).text("save");
128-
return;
129-
} else {
130-
$(
131-
".pageSettings .section.themes .customThemeEdit #saveCustomThemeButton"
132-
).text("save as new");
133-
}
126+
if (favThemesEl === null || themesEl === null) {
127+
const msg =
128+
"Failed to fill preset theme buttons: favThemes or allThemes element not found";
129+
Notifications.add(msg, -1);
130+
captureException(new Error(msg));
131+
console.error(msg, { favThemesEl, themesEl });
132+
return;
133+
}
134134

135-
addButton.removeClass("hidden");
135+
favThemesEl.innerHTML = "";
136+
themesEl.innerHTML = "";
136137

137-
const customThemes = DB.getSnapshot()?.customThemes ?? [];
138+
let favThemesElHTML = "";
139+
let themesElHTML = "";
138140

139-
customThemes.forEach((customTheme) => {
140-
// const activeTheme =
141-
// Config.customThemeId === customTheme._id ? "active" : "";
142-
const bgColor = customTheme.colors[0];
143-
const mainColor = customTheme.colors[1];
141+
let activeThemeName = Config.theme;
142+
if (
143+
Config.randomTheme !== "off" &&
144+
Config.randomTheme !== "custom" &&
145+
ThemeController.randomTheme !== null
146+
) {
147+
activeThemeName = ThemeController.randomTheme;
148+
}
144149

145-
customThemesEl.append(
146-
`<div class="customTheme button" customThemeId='${customTheme._id}'
147-
style="color:${mainColor};background:${bgColor}">
148-
<div class="editButton"><i class="fas fa-pen"></i></div>
149-
<div class="text">${customTheme.name.replace(/_/g, " ")}</div>
150-
<div class="delButton"><i class="fas fa-trash fa-fw"></i></div>
151-
</div>`
152-
);
153-
});
154-
} else {
155-
// Update theme buttons
156-
const favThemesEl = document.querySelector(
157-
".pageSettings .section.themes .favThemes.buttons"
158-
) as HTMLElement;
159-
favThemesEl.innerHTML = "";
160-
let favThemesElHTML = "";
161-
const themesEl = document.querySelector(
162-
".pageSettings .section.themes .allThemes.buttons"
163-
) as HTMLElement;
164-
themesEl.innerHTML = "";
165-
let themesElHTML = "";
166-
167-
let activeThemeName = Config.theme;
168-
if (
169-
Config.randomTheme !== "off" &&
170-
Config.randomTheme !== "custom" &&
171-
ThemeController.randomTheme !== null
172-
) {
173-
activeThemeName = ThemeController.randomTheme;
174-
}
150+
const { data: themes, error } = await tryCatch(
151+
JSONData.getSortedThemesList()
152+
);
175153

176-
const { data: themes, error } = await tryCatch(
177-
JSONData.getSortedThemesList()
154+
if (error) {
155+
Notifications.add(
156+
Misc.createErrorMessage(error, "Failed to fill preset theme buttons"),
157+
-1
178158
);
159+
return;
160+
}
179161

180-
if (error) {
181-
Notifications.add(
182-
Misc.createErrorMessage(error, "Failed to refresh theme buttons"),
183-
-1
184-
);
185-
return;
186-
}
187-
188-
//first show favourites
189-
if (Config.favThemes.length > 0) {
190-
favThemesEl.style.marginBottom = "1rem";
191-
favThemesEl.style.marginTop = "1rem";
192-
for (const theme of themes) {
193-
if (Config.favThemes.includes(theme.name)) {
194-
const activeTheme = activeThemeName === theme.name ? "active" : "";
195-
favThemesElHTML += `<div class="theme button ${activeTheme}" theme='${
196-
theme.name
197-
}' style="background: ${theme.bgColor}; color: ${
198-
theme.mainColor
199-
};outline: 0 solid ${theme.mainColor};">
200-
<div class="favButton active"><i class="fas fa-star"></i></div>
201-
<div class="text">${theme.name.replace(/_/g, " ")}</div>
202-
<div class="themeBubbles" style="background: ${
203-
theme.bgColor
204-
};outline: 0.25rem solid ${theme.bgColor};">
205-
<div class="themeBubble" style="background: ${
206-
theme.mainColor
207-
}"></div>
208-
<div class="themeBubble" style="background: ${
209-
theme.subColor
210-
}"></div>
211-
<div class="themeBubble" style="background: ${
212-
theme.textColor
213-
}"></div>
214-
</div>
215-
</div>
216-
`;
217-
}
218-
}
219-
favThemesEl.innerHTML = favThemesElHTML;
220-
} else {
221-
favThemesEl.style.marginBottom = "0";
222-
favThemesEl.style.marginTop = "0";
223-
}
224-
//then the rest
162+
//first show favourites
163+
if (Config.favThemes.length > 0) {
164+
favThemesEl.style.marginBottom = "1rem";
225165
for (const theme of themes) {
226166
if (Config.favThemes.includes(theme.name)) {
227-
continue;
167+
const activeTheme = activeThemeName === theme.name ? "active" : "";
168+
favThemesElHTML += `<div class="theme button ${activeTheme}" theme='${
169+
theme.name
170+
}' style="background: ${theme.bgColor}; color: ${
171+
theme.mainColor
172+
};outline: 0 solid ${theme.mainColor};">
173+
<div class="favButton active"><i class="fas fa-star"></i></div>
174+
<div class="text">${theme.name.replace(/_/g, " ")}</div>
175+
<div class="themeBubbles" style="background: ${
176+
theme.bgColor
177+
};outline: 0.25rem solid ${theme.bgColor};">
178+
<div class="themeBubble" style="background: ${
179+
theme.mainColor
180+
}"></div>
181+
<div class="themeBubble" style="background: ${
182+
theme.subColor
183+
}"></div>
184+
<div class="themeBubble" style="background: ${
185+
theme.textColor
186+
}"></div>
187+
</div>
188+
</div>
189+
`;
228190
}
229-
230-
const activeTheme = activeThemeName === theme.name ? "active" : "";
231-
themesElHTML += `<div class="theme button ${activeTheme}" theme='${
232-
theme.name
233-
}' style="background: ${theme.bgColor}; color: ${
234-
theme.mainColor
235-
};outline: 0 solid ${theme.mainColor};">
236-
<div class="favButton"><i class="far fa-star"></i></div>
237-
<div class="text">${theme.name.replace(/_/g, " ")}</div>
238-
<div class="themeBubbles" style="background: ${
239-
theme.bgColor
240-
};outline: 0.25rem solid ${theme.bgColor};">
241-
<div class="themeBubble" style="background: ${theme.mainColor}"></div>
242-
<div class="themeBubble" style="background: ${theme.subColor}"></div>
243-
<div class="themeBubble" style="background: ${theme.textColor}"></div>
244-
</div>
245-
</div>
246-
`;
247191
}
248-
themesEl.innerHTML = themesElHTML;
192+
favThemesEl.innerHTML = favThemesElHTML;
193+
} else {
194+
favThemesEl.style.marginBottom = "0";
195+
}
196+
//then the rest
197+
for (const theme of themes) {
198+
if (Config.favThemes.includes(theme.name)) {
199+
continue;
200+
}
201+
202+
const activeTheme = activeThemeName === theme.name ? "active" : "";
203+
themesElHTML += `<div class="theme button ${activeTheme}" theme='${
204+
theme.name
205+
}' style="background: ${theme.bgColor}; color: ${
206+
theme.mainColor
207+
};outline: 0 solid ${theme.mainColor};">
208+
<div class="favButton"><i class="far fa-star"></i></div>
209+
<div class="text">${theme.name.replace(/_/g, " ")}</div>
210+
<div class="themeBubbles" style="background: ${
211+
theme.bgColor
212+
};outline: 0.25rem solid ${theme.bgColor};">
213+
<div class="themeBubble" style="background: ${theme.mainColor}"></div>
214+
<div class="themeBubble" style="background: ${theme.subColor}"></div>
215+
<div class="themeBubble" style="background: ${theme.textColor}"></div>
216+
</div>
217+
</div>
218+
`;
219+
}
220+
themesEl.innerHTML = themesElHTML;
221+
}
222+
223+
export async function refreshCustomButtons(): Promise<void> {
224+
// Update custom theme buttons
225+
const customThemesEl = $(
226+
".pageSettings .section.themes .allCustomThemes.buttons"
227+
).empty();
228+
const addButton = $(".pageSettings .section.themes .addCustomThemeButton");
229+
const saveButton = $(
230+
".pageSettings .section.themes .customThemeEdit #saveCustomThemeButton"
231+
);
232+
233+
if (!isAuthenticated()) {
234+
saveButton.text("save");
235+
addButton.addClass("hidden");
236+
customThemesEl.css("margin-bottom", "0");
237+
return;
238+
}
239+
240+
saveButton.text("save as new");
241+
addButton.removeClass("hidden");
242+
243+
const customThemes = DB.getSnapshot()?.customThemes ?? [];
244+
245+
if (customThemes.length === 0) {
246+
customThemesEl.css("margin-bottom", "0");
247+
} else {
248+
customThemesEl.css("margin-bottom", "1rem");
249+
}
250+
251+
for (const customTheme of customThemes) {
252+
const bgColor = customTheme.colors[0];
253+
const mainColor = customTheme.colors[1];
254+
255+
customThemesEl.append(
256+
`<div class="customTheme button" customThemeId='${customTheme._id}'
257+
style="color:${mainColor};background:${bgColor}">
258+
<div class="editButton"><i class="fas fa-pen"></i></div>
259+
<div class="text">${customTheme.name.replace(/_/g, " ")}</div>
260+
<div class="delButton"><i class="fas fa-trash fa-fw"></i></div>
261+
</div>`
262+
);
249263
}
250264
}
251265

@@ -288,33 +302,23 @@ function saveCustomThemeColors(): void {
288302
Notifications.add("Custom theme saved", 1);
289303
}
290304

291-
export function updateActiveTab(forced = false): void {
305+
export function updateActiveTab(): void {
292306
// Set force to true only when some change for the active tab has taken place
293307
// Prevent theme buttons from being added twice by doing an update only when the state has changed
294-
const $presetTabButton = $(
295-
".pageSettings .section.themes .tabs button[data-tab='preset']"
296-
);
297-
const $customTabButton = $(
298-
".pageSettings .section.themes .tabs button[data-tab='custom']"
299-
);
308+
$(".pageSettings .section.themes .tabs button").removeClass("active");
309+
$(
310+
`.pageSettings .section.themes .tabs button[data-tab="${
311+
Config.customTheme ? "custom" : "preset"
312+
}"]`
313+
).addClass("active");
300314

301315
if (Config.customTheme) {
302-
$presetTabButton.removeClass("active");
303-
if (!$customTabButton.hasClass("active") || forced) {
304-
$customTabButton.addClass("active");
305-
void refreshButtons();
306-
}
307316
void Misc.swapElements(
308317
$('.pageSettings [tabContent="preset"]'),
309318
$('.pageSettings [tabContent="custom"]'),
310319
250
311320
);
312321
} else {
313-
$customTabButton.removeClass("active");
314-
if (!$presetTabButton.hasClass("active") || forced) {
315-
$presetTabButton.addClass("active");
316-
void refreshButtons();
317-
}
318322
void Misc.swapElements(
319323
$('.pageSettings [tabContent="custom"]'),
320324
$('.pageSettings [tabContent="preset"]'),
@@ -364,8 +368,10 @@ $(".pageSettings").on("click", " .section.themes .customTheme.button", (e) => {
364368
// Handle click on favorite preset theme button
365369
$(".pageSettings").on("click", ".section.themes .theme .favButton", (e) => {
366370
const theme = $(e.currentTarget).parents(".theme.button").attr("theme");
367-
if (theme !== undefined) toggleFavourite(theme);
368-
else {
371+
if (theme !== undefined) {
372+
toggleFavourite(theme);
373+
void refreshPresetButtons();
374+
} else {
369375
console.error(
370376
"Could not find the theme attribute attached to the button clicked!"
371377
);
@@ -470,14 +476,10 @@ $(".pageSettings #saveCustomThemeButton").on("click", async () => {
470476
};
471477

472478
Loader.show();
473-
const response = await DB.addCustomTheme(newCustomTheme);
479+
await DB.addCustomTheme(newCustomTheme);
474480
Loader.hide();
475-
if (response) {
476-
updateActiveTab(true);
477-
}
478-
} else {
479-
updateActiveTab(true);
480481
}
482+
void refreshCustomButtons();
481483
});
482484

483485
ConfigEvent.subscribe((eventKey) => {

frontend/src/ts/modals/simple-modals.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ list.updateCustomTheme = new SimpleModal({
11511151
};
11521152
}
11531153
UpdateConfig.setCustomThemeColors(newColors as CustomThemeColors);
1154-
void ThemePicker.refreshButtons();
1154+
void ThemePicker.refreshCustomButtons();
11551155

11561156
return {
11571157
status: 1,
@@ -1178,7 +1178,7 @@ list.deleteCustomTheme = new SimpleModal({
11781178
onlineOnly: true,
11791179
execFn: async (_thisPopup): Promise<ExecReturn> => {
11801180
await DB.deleteCustomTheme(_thisPopup.parameters[0] as string);
1181-
void ThemePicker.refreshButtons();
1181+
void ThemePicker.refreshCustomButtons();
11821182

11831183
return {
11841184
status: 1,

frontend/src/ts/pages/settings.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,8 @@ async function fillSettingsPage(): Promise<void> {
708708
}
709709
}
710710
setEventDisabled(false);
711-
await ThemePicker.refreshButtons();
711+
await ThemePicker.refreshCustomButtons();
712+
await ThemePicker.refreshPresetButtons();
712713
await UpdateConfig.loadPromise;
713714
}
714715

@@ -823,7 +824,7 @@ export async function update(groupUpdate = true): Promise<void> {
823824
// LanguagePicker.setActiveGroup(); Shifted from grouped btns to combo-box
824825
setActiveFunboxButton();
825826
await Misc.sleep(0);
826-
ThemePicker.updateActiveTab(true);
827+
ThemePicker.updateActiveTab();
827828
ThemePicker.setCustomInputs(true);
828829
// ThemePicker.updateActiveButton();
829830

0 commit comments

Comments
 (0)