mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-21 15:56:24 +08:00
Add memoize async util (rewrite get json lists in misc) (#3596) Bruception Miodec
* Add memoize async util * Stricter types * type cast * added getjson function * removed unnecessary code removed comments * ignoring cache if value is undefined * checking if layouts list exists * messed up merge * checking if layouts exist * throwing if layouts list or layout is undefined * catching in case layouts or layout is undefined * catching in case layouts list or layout is undefined * breaking in case layouts list is undefined * showing a message if layout list is undefined * removed console log * themes list can return undefined * removed catch from fetch json * getlayoutslist no longer can return undefined * console logging then throwing again * rethrowing with a different message * try catch * catch * try catching * try catching * typo * url fix * moved definition up * moved functions up * moved functions up * removed unnecessary update * catching errors * updated return type not returning * try catching * updated return type throwing if list ends up undefined * removed return * moved functions up * try catching * checking if not undefined * removed unused file * try catching * try catching * rewrote language getting * rewrote funbox * try catching * notification instead of console error * notification instead of console error * rewrote fonts * rewrote challenges * try catch * typo * rewrote contributors and supporters Co-authored-by: Miodec <jack@monkeytype.com>
This commit is contained in:
parent
cbdfb732a1
commit
1eb71dc517
|
@ -676,34 +676,46 @@ $(".pageAccount .topFilters .button.toggleAdvancedFilters").on("click", () => {
|
|||
});
|
||||
|
||||
export async function appendButtons(): Promise<void> {
|
||||
await Misc.getLanguageList().then((languages) => {
|
||||
languages.forEach((language) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${language}">${language.replace(
|
||||
"_",
|
||||
" "
|
||||
)}</div>`
|
||||
await Misc.getLanguageList()
|
||||
.then((languages) => {
|
||||
languages.forEach((language) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${language}">${language.replace(
|
||||
"_",
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to append language buttons")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons"
|
||||
).append(`<div class="button" filter="none">none</div>`);
|
||||
await Misc.getFunboxList().then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${funbox.name}">${funbox.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</div>`
|
||||
await Misc.getFunboxList()
|
||||
.then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${funbox.name}">${funbox.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to append funbox buttons")
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function removeButtons(): void {
|
||||
|
|
|
@ -98,30 +98,66 @@ import * as Notifications from "../elements/notifications";
|
|||
import * as VideoAdPopup from "../popups/video-ad-popup";
|
||||
import * as ShareTestSettingsPopup from "../popups/share-test-settings-popup";
|
||||
|
||||
Misc.getLayoutsList().then((layouts) => {
|
||||
updateLayoutsCommands(layouts);
|
||||
updateKeymapLayoutsCommands(layouts);
|
||||
});
|
||||
Misc.getLayoutsList()
|
||||
.then((layouts) => {
|
||||
updateLayoutsCommands(layouts);
|
||||
updateKeymapLayoutsCommands(layouts);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update layouts commands")
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getLanguageList().then((languages) => {
|
||||
updateLanguagesCommands(languages);
|
||||
});
|
||||
Misc.getLanguageList()
|
||||
.then((languages) => {
|
||||
updateLanguagesCommands(languages);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update language commands")
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getFunboxList().then((funboxes) => {
|
||||
updateFunboxCommands(funboxes);
|
||||
});
|
||||
Misc.getFunboxList()
|
||||
.then((funboxes) => {
|
||||
updateFunboxCommands(funboxes);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update funbox commands")
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getFontsList().then((fonts) => {
|
||||
updateFontFamilyCommands(fonts);
|
||||
});
|
||||
Misc.getFontsList()
|
||||
.then((fonts) => {
|
||||
updateFontFamilyCommands(fonts);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update fonts commands")
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getThemesList().then((themes) => {
|
||||
updateThemesCommands(themes);
|
||||
});
|
||||
Misc.getThemesList()
|
||||
.then((themes) => {
|
||||
updateThemesCommands(themes);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update themes commands")
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getChallengeList().then((challenges) => {
|
||||
updateLoadChallengeCommands(challenges);
|
||||
});
|
||||
Misc.getChallengeList()
|
||||
.then((challenges) => {
|
||||
updateLoadChallengeCommands(challenges);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update challenges commands")
|
||||
);
|
||||
});
|
||||
|
||||
export const commands: MonkeyTypes.CommandsSubgroup = {
|
||||
title: "",
|
||||
|
|
|
@ -2,7 +2,6 @@ import * as ThemeController from "../controllers/theme-controller";
|
|||
import Config, * as UpdateConfig from "../config";
|
||||
import * as Focus from "../test/focus";
|
||||
import * as CommandlineLists from "./commands";
|
||||
import * as Misc from "./../utils/misc";
|
||||
import * as TestUI from "../test/test-ui";
|
||||
import * as DB from "../db";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
|
@ -14,7 +13,6 @@ import { Auth } from "../firebase";
|
|||
import { isAnyPopupVisible } from "../utils/misc";
|
||||
import { update as updateCustomThemesList } from "./lists/custom-themes-list";
|
||||
import { update as updateTagsCommands } from "./lists/tags";
|
||||
import { update as updateThemesCommands } from "./lists/themes";
|
||||
|
||||
let commandLineMouseMode = false;
|
||||
let themeChosen = false;
|
||||
|
@ -191,9 +189,6 @@ export let show = (): void => {
|
|||
);
|
||||
}
|
||||
$("#commandLine input").val("");
|
||||
Misc.getThemesList().then((themes) => {
|
||||
updateThemesCommands(themes);
|
||||
});
|
||||
updateSuggested();
|
||||
$("#commandLine input").trigger("focus");
|
||||
};
|
||||
|
|
|
@ -116,6 +116,16 @@ export async function isConfigValueValidAsync(
|
|||
|
||||
if (layoutNames.length < 2 || layoutNames.length > 5) break;
|
||||
|
||||
try {
|
||||
await Misc.getLayoutsList();
|
||||
} catch (e) {
|
||||
customMessage = Misc.createErrorMessage(
|
||||
e,
|
||||
"Failed to validate layoutfluid value"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// convert the layout names to layouts
|
||||
const layouts = await Promise.all(
|
||||
layoutNames.map(async (layoutName) => Misc.getLayout(layoutName))
|
||||
|
|
|
@ -117,17 +117,26 @@ export async function getDataAndInit(): Promise<boolean> {
|
|||
|
||||
ResultFilters.loadTags(snapshot.tags);
|
||||
|
||||
Promise.all([Misc.getLanguageList(), Misc.getFunboxList()]).then((values) => {
|
||||
const [languages, funboxes] = values;
|
||||
languages.forEach((language) => {
|
||||
ResultFilters.defaultResultFilters.language[language] = true;
|
||||
Promise.all([Misc.getLanguageList(), Misc.getFunboxList()])
|
||||
.then((values) => {
|
||||
const [languages, funboxes] = values;
|
||||
languages.forEach((language) => {
|
||||
ResultFilters.defaultResultFilters.language[language] = true;
|
||||
});
|
||||
funboxes.forEach((funbox) => {
|
||||
ResultFilters.defaultResultFilters.funbox[funbox.name] = true;
|
||||
});
|
||||
// filters = defaultResultFilters;
|
||||
ResultFilters.load();
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(
|
||||
Misc.createErrorMessage(
|
||||
e,
|
||||
"Something went wrong while loading the filters"
|
||||
)
|
||||
);
|
||||
});
|
||||
funboxes.forEach((funbox) => {
|
||||
ResultFilters.defaultResultFilters.funbox[funbox.name] = true;
|
||||
});
|
||||
// filters = defaultResultFilters;
|
||||
ResultFilters.load();
|
||||
});
|
||||
|
||||
if (snapshot.needsToChangeName) {
|
||||
Notifications.addBanner(
|
||||
|
|
|
@ -170,7 +170,20 @@ export async function setup(challengeName: string): Promise<boolean> {
|
|||
|
||||
UpdateConfig.setFunbox("none");
|
||||
|
||||
const list = await Misc.getChallengeList();
|
||||
let list;
|
||||
try {
|
||||
list = await Misc.getChallengeList();
|
||||
} catch (e) {
|
||||
const message = Misc.createErrorMessage(e, "Failed to setup challenge");
|
||||
Notifications.add(message, -1);
|
||||
ManualRestart.set();
|
||||
setTimeout(() => {
|
||||
$("#top .config").removeClass("hidden");
|
||||
$(".page.pageTest").removeClass("hidden");
|
||||
}, 250);
|
||||
return false;
|
||||
}
|
||||
|
||||
const challenge = list.filter((c) => c.name === challengeName)[0];
|
||||
let notitext;
|
||||
try {
|
||||
|
|
|
@ -206,7 +206,16 @@ export function clearPreview(applyTheme = true): void {
|
|||
let themesList: string[] = [];
|
||||
|
||||
async function changeThemeList(): Promise<void> {
|
||||
const themes = await Misc.getThemesList();
|
||||
let themes;
|
||||
try {
|
||||
themes = await Misc.getThemesList();
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to update random theme list")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config.randomTheme === "fav" && Config.favThemes.length > 0) {
|
||||
themesList = Config.favThemes;
|
||||
} else if (Config.randomTheme === "light") {
|
||||
|
|
|
@ -4,8 +4,10 @@ import * as SlowTimer from "../states/slow-timer";
|
|||
import * as ConfigEvent from "../observables/config-event";
|
||||
import * as Misc from "../utils/misc";
|
||||
import * as Hangul from "hangul-js";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
import * as ActivePage from "../states/active-page";
|
||||
|
||||
|
||||
export function highlightKey(currentKey: string): void {
|
||||
if (Config.mode === "zen") return;
|
||||
if (currentKey === "") currentKey = " ";
|
||||
|
@ -103,7 +105,17 @@ export async function refresh(
|
|||
if (ActivePage.get() !== "test") return;
|
||||
if (!layoutName) return;
|
||||
try {
|
||||
const layouts = await Misc.getLayoutsList();
|
||||
let layouts;
|
||||
try {
|
||||
layouts = await Misc.getLayoutsList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to refresh keymap"),
|
||||
-1
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let lts = layouts[layoutName]; //layout to show
|
||||
let layoutString = layoutName;
|
||||
if (Config.keymapLayout === "overrideSync") {
|
||||
|
|
|
@ -96,8 +96,27 @@ async function getStatsAndHistogramData(): Promise<void> {
|
|||
}
|
||||
|
||||
async function fill(): Promise<void> {
|
||||
const supporters = await Misc.getSupportersList();
|
||||
const contributors = await Misc.getContributorsList();
|
||||
let supporters: string[];
|
||||
try {
|
||||
supporters = await Misc.getSupportersList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to get supporters"),
|
||||
-1
|
||||
);
|
||||
supporters = [];
|
||||
}
|
||||
|
||||
let contributors: string[];
|
||||
try {
|
||||
contributors = await Misc.getContributorsList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to get contributors"),
|
||||
-1
|
||||
);
|
||||
contributors = [];
|
||||
}
|
||||
|
||||
await getStatsAndHistogramData();
|
||||
updateStatsAndHistogram();
|
||||
|
|
|
@ -408,17 +408,31 @@ export async function fillSettingsPage(): Promise<void> {
|
|||
|
||||
// Language Selection Combobox
|
||||
const languageEl = $(".pageSettings .section.language select").empty();
|
||||
const languageGroups = await Misc.getLanguageGroups();
|
||||
languageGroups.forEach((group) => {
|
||||
let langComboBox = `<optgroup label="${group.name}">`;
|
||||
group.languages.forEach((language: string) => {
|
||||
langComboBox += `<option value="${language}">
|
||||
|
||||
let languageGroups;
|
||||
try {
|
||||
languageGroups = await Misc.getLanguageGroups();
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(
|
||||
e,
|
||||
"Failed to initialize settings language picker"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (languageGroups) {
|
||||
languageGroups.forEach((group) => {
|
||||
let langComboBox = `<optgroup label="${group.name}">`;
|
||||
group.languages.forEach((language: string) => {
|
||||
langComboBox += `<option value="${language}">
|
||||
${language.replace(/_/g, " ")}
|
||||
</option>`;
|
||||
});
|
||||
langComboBox += `</optgroup>`;
|
||||
languageEl.append(langComboBox);
|
||||
});
|
||||
langComboBox += `</optgroup>`;
|
||||
languageEl.append(langComboBox);
|
||||
});
|
||||
}
|
||||
languageEl.select2({
|
||||
width: "100%",
|
||||
});
|
||||
|
@ -427,18 +441,28 @@ export async function fillSettingsPage(): Promise<void> {
|
|||
layoutEl.append(`<option value='default'>off</option>`);
|
||||
const keymapEl = $(".pageSettings .section.keymapLayout select").empty();
|
||||
keymapEl.append(`<option value='overrideSync'>emulator sync</option>`);
|
||||
Object.keys(await Misc.getLayoutsList()).forEach((layout) => {
|
||||
if (layout.toString() !== "korean") {
|
||||
layoutEl.append(
|
||||
`<option value='${layout}'>${layout.replace(/_/g, " ")}</option>`
|
||||
);
|
||||
}
|
||||
if (layout.toString() != "default") {
|
||||
keymapEl.append(
|
||||
`<option value='${layout}'>${layout.replace(/_/g, " ")}</option>`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let layoutsList;
|
||||
try {
|
||||
layoutsList = await Misc.getLayoutsList();
|
||||
} catch (e) {
|
||||
console.error(Misc.createErrorMessage(e, "Failed to refresh keymap"));
|
||||
}
|
||||
|
||||
if (layoutsList) {
|
||||
Object.keys(layoutsList).forEach((layout) => {
|
||||
if (layout.toString() !== "korean") {
|
||||
layoutEl.append(
|
||||
`<option value='${layout}'>${layout.replace(/_/g, " ")}</option>`
|
||||
);
|
||||
}
|
||||
if (layout.toString() != "default") {
|
||||
keymapEl.append(
|
||||
`<option value='${layout}'>${layout.replace(/_/g, " ")}</option>`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
layoutEl.select2({
|
||||
width: "100%",
|
||||
});
|
||||
|
@ -452,14 +476,32 @@ export async function fillSettingsPage(): Promise<void> {
|
|||
const themeEl2 = $(
|
||||
".pageSettings .section.autoSwitchThemeInputs select.dark"
|
||||
).empty();
|
||||
for (const theme of await Misc.getThemesList()) {
|
||||
themeEl1.append(
|
||||
`<option value='${theme.name}'>${theme.name.replace(/_/g, " ")}</option>`
|
||||
);
|
||||
themeEl2.append(
|
||||
`<option value='${theme.name}'>${theme.name.replace(/_/g, " ")}</option>`
|
||||
|
||||
let themes;
|
||||
try {
|
||||
themes = await Misc.getThemesList();
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to load themes into dropdown boxes")
|
||||
);
|
||||
}
|
||||
|
||||
if (themes) {
|
||||
for (const theme of themes) {
|
||||
themeEl1.append(
|
||||
`<option value='${theme.name}'>${theme.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</option>`
|
||||
);
|
||||
themeEl2.append(
|
||||
`<option value='${theme.name}'>${theme.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</option>`
|
||||
);
|
||||
}
|
||||
}
|
||||
themeEl1.select2({
|
||||
width: "100%",
|
||||
});
|
||||
|
@ -476,57 +518,71 @@ export async function fillSettingsPage(): Promise<void> {
|
|||
|
||||
const funboxEl = $(".pageSettings .section.funbox .buttons").empty();
|
||||
funboxEl.append(`<div class="funbox button" funbox='none'>none</div>`);
|
||||
Misc.getFunboxList().then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
if (funbox.name === "mirror") {
|
||||
funboxEl.append(
|
||||
`<div class="funbox button" funbox='${funbox.name}' aria-label="${
|
||||
funbox.info
|
||||
}" data-balloon-pos="up" data-balloon-length="fit" type="${
|
||||
funbox.type
|
||||
}" style="transform:scaleX(-1);">${funbox.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
} else {
|
||||
funboxEl.append(
|
||||
`<div class="funbox button" funbox='${funbox.name}' aria-label="${
|
||||
funbox.info
|
||||
}" data-balloon-pos="up" data-balloon-length="fit" type="${
|
||||
funbox.type
|
||||
}">${funbox.name.replace(/_/g, " ")}</div>`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let isCustomFont = true;
|
||||
const fontsEl = $(".pageSettings .section.fontFamily .buttons").empty();
|
||||
Misc.getFontsList().then((fonts) => {
|
||||
fonts.forEach((font) => {
|
||||
if (Config.fontFamily === font.name) isCustomFont = false;
|
||||
fontsEl.append(
|
||||
`<div class="button${
|
||||
Config.fontFamily === font.name ? " active" : ""
|
||||
}" style="font-family:${
|
||||
font.display !== undefined ? font.display : font.name
|
||||
}" fontFamily="${font.name.replace(/ /g, "_")}" tabindex="0"
|
||||
onclick="this.blur();">${
|
||||
font.display !== undefined ? font.display : font.name
|
||||
}</div>`
|
||||
Misc.getFunboxList()
|
||||
.then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
if (funbox.name === "mirror") {
|
||||
funboxEl.append(
|
||||
`<div class="funbox button" funbox='${funbox.name}' aria-label="${
|
||||
funbox.info
|
||||
}" data-balloon-pos="up" data-balloon-length="fit" type="${
|
||||
funbox.type
|
||||
}" style="transform:scaleX(-1);">${funbox.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
} else {
|
||||
funboxEl.append(
|
||||
`<div class="funbox button" funbox='${funbox.name}' aria-label="${
|
||||
funbox.info
|
||||
}" data-balloon-pos="up" data-balloon-length="fit" type="${
|
||||
funbox.type
|
||||
}">${funbox.name.replace(/_/g, " ")}</div>`
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to update funbox settings buttons"),
|
||||
-1
|
||||
);
|
||||
});
|
||||
|
||||
fontsEl.append(
|
||||
isCustomFont
|
||||
? `<div class="button no-auto-handle custom active" onclick="this.blur();">Custom (${Config.fontFamily.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)})</div>`
|
||||
: '<div class="button no-auto-handle custom" onclick="this.blur();">Custom</div>'
|
||||
);
|
||||
});
|
||||
let isCustomFont = true;
|
||||
const fontsEl = $(".pageSettings .section.fontFamily .buttons").empty();
|
||||
Misc.getFontsList()
|
||||
.then((fonts) => {
|
||||
fonts.forEach((font) => {
|
||||
if (Config.fontFamily === font.name) isCustomFont = false;
|
||||
fontsEl.append(
|
||||
`<div class="button${
|
||||
Config.fontFamily === font.name ? " active" : ""
|
||||
}" style="font-family:${
|
||||
font.display !== undefined ? font.display : font.name
|
||||
}" fontFamily="${font.name.replace(/ /g, "_")}" tabindex="0"
|
||||
onclick="this.blur();">${
|
||||
font.display !== undefined ? font.display : font.name
|
||||
}</div>`
|
||||
);
|
||||
});
|
||||
|
||||
fontsEl.append(
|
||||
isCustomFont
|
||||
? `<div class="button no-auto-handle custom active" onclick="this.blur();">Custom (${Config.fontFamily.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)})</div>`
|
||||
: '<div class="button no-auto-handle custom" onclick="this.blur();">Custom</div>'
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to update fonts settings buttons"),
|
||||
-1
|
||||
);
|
||||
});
|
||||
|
||||
$(".pageSettings .section.customBackgroundSize input").val(
|
||||
Config.customBackground
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
import * as Misc from "../utils/misc";
|
||||
import * as CustomText from "../test/custom-text";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
|
||||
let initialised = false;
|
||||
|
||||
async function init(): Promise<void> {
|
||||
if (!initialised) {
|
||||
$("#wordFilterPopup .languageInput").empty();
|
||||
const LanguageList = await Misc.getLanguageList();
|
||||
|
||||
let LanguageList;
|
||||
try {
|
||||
LanguageList = await Misc.getLanguageList();
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(
|
||||
e,
|
||||
"Failed to initialise word filter popup language list"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
LanguageList.forEach((language) => {
|
||||
let prettyLang = language;
|
||||
prettyLang = prettyLang.replace("_", " ");
|
||||
|
@ -42,7 +56,18 @@ async function filter(language: string): Promise<string[]> {
|
|||
filterout = filterout.replace(/\s+/gi, "|");
|
||||
const regexcl = new RegExp(filterout, "i");
|
||||
const filteredWords = [];
|
||||
const languageWordList = await Misc.getLanguage(language);
|
||||
|
||||
let languageWordList;
|
||||
try {
|
||||
languageWordList = await Misc.getLanguage(language);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to filter language words"),
|
||||
-1
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
const maxLengthInput = $("#wordFilterPopup .wordMaxInput").val() as string;
|
||||
const minLengthInput = $("#wordFilterPopup .wordMinInput").val() as string;
|
||||
let maxLength;
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
import * as Misc from "../utils/misc";
|
||||
import Config, * as UpdateConfig from "../config";
|
||||
|
||||
export async function setActiveGroup(
|
||||
groupName: string | undefined,
|
||||
clicked: boolean | undefined = false
|
||||
): Promise<void> {
|
||||
let currentGroup: MonkeyTypes.LanguageGroup | undefined;
|
||||
|
||||
if (groupName === undefined) {
|
||||
currentGroup = await Misc.findCurrentGroup(Config.language);
|
||||
} else {
|
||||
const groups: MonkeyTypes.LanguageGroup[] = await Misc.getLanguageGroups();
|
||||
groups.forEach((g: MonkeyTypes.LanguageGroup) => {
|
||||
if (g.name === groupName) {
|
||||
currentGroup = g;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(`.pageSettings .section.languageGroups .button`).removeClass("active");
|
||||
|
||||
if (currentGroup === undefined) return;
|
||||
|
||||
$(
|
||||
`.pageSettings .section.languageGroups .button[group='${currentGroup.name}']`
|
||||
).addClass("active");
|
||||
|
||||
const langElement: JQuery<HTMLElement> = $(
|
||||
".pageSettings .section.language .buttons"
|
||||
).empty();
|
||||
currentGroup.languages.forEach((langName: string) => {
|
||||
langElement.append(
|
||||
`<div class="language button" language='${langName}'>
|
||||
${langName.replace(/_/g, " ")}
|
||||
</div>`
|
||||
);
|
||||
});
|
||||
|
||||
if (clicked) {
|
||||
$($(`.pageSettings .section.language .buttons .button`)[0]).addClass(
|
||||
"active"
|
||||
);
|
||||
UpdateConfig.setLanguage(currentGroup.languages[0]);
|
||||
} else {
|
||||
$(
|
||||
`.pageSettings .section.language .buttons .button[language=${Config.language}]`
|
||||
).addClass("active");
|
||||
}
|
||||
}
|
|
@ -158,7 +158,17 @@ export async function refreshButtons(): Promise<void> {
|
|||
activeThemeName = ThemeController.randomTheme as string;
|
||||
}
|
||||
|
||||
const themes = await Misc.getSortedThemesList();
|
||||
let themes;
|
||||
try {
|
||||
themes = await Misc.getSortedThemesList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to refresh theme buttons"),
|
||||
-1
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//first show favourites
|
||||
if (Config.favThemes.length > 0) {
|
||||
favThemesEl.css({ paddingBottom: "1rem" });
|
||||
|
|
|
@ -120,13 +120,37 @@ export async function activate(funbox?: string): Promise<boolean | undefined> {
|
|||
if (funbox === undefined || funbox === null) {
|
||||
funbox = Config.funbox;
|
||||
}
|
||||
|
||||
const funboxInfo = await Misc.getFunbox(funbox);
|
||||
let funboxInfo;
|
||||
try {
|
||||
funboxInfo = await Misc.getFunbox(funbox);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to activate funbox"),
|
||||
-1
|
||||
);
|
||||
UpdateConfig.setFunbox("none", true);
|
||||
await clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
$("#funBoxTheme").attr("href", ``);
|
||||
$("#words").removeClass("nospace");
|
||||
$("#words").removeClass("arrows");
|
||||
if ((await Misc.getCurrentLanguage(Config.language)).ligatures) {
|
||||
|
||||
let language;
|
||||
try {
|
||||
language = await Misc.getCurrentLanguage(Config.language);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to activate funbox"),
|
||||
-1
|
||||
);
|
||||
UpdateConfig.setFunbox("none", true);
|
||||
await clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (language.ligatures) {
|
||||
if (funbox == "choo_choo" || funbox == "earthquake") {
|
||||
Notifications.add(
|
||||
"Current language does not support this funbox mode",
|
||||
|
@ -162,7 +186,17 @@ export async function activate(funbox?: string): Promise<boolean | undefined> {
|
|||
(funbox !== "none" && mode === undefined) ||
|
||||
(funbox !== "none" && mode === null)
|
||||
) {
|
||||
const list = await Misc.getFunboxList();
|
||||
let list;
|
||||
try {
|
||||
list = await Misc.getFunboxList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to activate funbox"),
|
||||
-1
|
||||
);
|
||||
await clear();
|
||||
return;
|
||||
}
|
||||
mode = list.filter((f) => f.name === funbox)[0].type;
|
||||
}
|
||||
|
||||
|
@ -228,7 +262,17 @@ export async function rememberSettings(): Promise<void> {
|
|||
(funbox !== "none" && mode === undefined) ||
|
||||
(funbox !== "none" && mode === null)
|
||||
) {
|
||||
const list = await Misc.getFunboxList();
|
||||
let list;
|
||||
try {
|
||||
list = await Misc.getFunboxList();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to remember setting"),
|
||||
-1
|
||||
);
|
||||
await clear();
|
||||
return;
|
||||
}
|
||||
mode = list.filter((f) => f.name === funbox)[0].type;
|
||||
}
|
||||
if (mode === "style") {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Config from "../config";
|
||||
import * as Misc from "../utils/misc";
|
||||
import { capsState } from "./caps-warning";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
|
||||
export async function getCharFromEvent(
|
||||
event: JQuery.KeyDownEvent
|
||||
|
@ -13,7 +14,17 @@ export async function getCharFromEvent(
|
|||
return event.shiftKey;
|
||||
}
|
||||
|
||||
const layout = await Misc.getLayout(Config.layout);
|
||||
let layout;
|
||||
|
||||
try {
|
||||
layout = await Misc.getLayout(Config.layout);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to emulate event"),
|
||||
-1
|
||||
);
|
||||
return event.key;
|
||||
}
|
||||
|
||||
let keyEventCodes: string[] = [];
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Config from "../config";
|
||||
import * as Misc from "../utils/misc";
|
||||
import { capsState } from "./caps-warning";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
|
||||
export let leftState = false;
|
||||
export let rightState = false;
|
||||
|
@ -50,9 +51,16 @@ function dynamicKeymapLegendStyle(uppercase: boolean): void {
|
|||
async function buildKeymapStrings(): Promise<void> {
|
||||
if (keymapStrings.keymap === Config.keymapLayout) return;
|
||||
|
||||
const layout = await Misc.getLayout(Config.keymapLayout);
|
||||
|
||||
if (layout === undefined) return;
|
||||
let layout;
|
||||
try {
|
||||
layout = await Misc.getLayout(Config.keymapLayout);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to track shift state"),
|
||||
-1
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const layoutKeys = layout.keys;
|
||||
const layoutKeysEntries = Object.entries(layoutKeys) as [string, string[]][];
|
||||
|
|
|
@ -892,19 +892,42 @@ export async function init(): Promise<void> {
|
|||
if (Config.quoteLength.includes(-3) && !Auth?.currentUser) {
|
||||
UpdateConfig.setQuoteLength(-1);
|
||||
}
|
||||
|
||||
let language = await Misc.getLanguage(Config.language);
|
||||
let language;
|
||||
try {
|
||||
language = await Misc.getLanguage(Config.language);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to load language"),
|
||||
-1
|
||||
);
|
||||
}
|
||||
if (language && language.name !== Config.language) {
|
||||
UpdateConfig.setLanguage("english");
|
||||
}
|
||||
|
||||
if (!language) {
|
||||
UpdateConfig.setLanguage("english");
|
||||
language = await Misc.getLanguage(Config.language);
|
||||
try {
|
||||
language = await Misc.getLanguage(Config.language);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
Misc.createErrorMessage(e, "Failed to load language"),
|
||||
-1
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.mode === "quote") {
|
||||
const group = await Misc.findCurrentGroup(Config.language);
|
||||
let group;
|
||||
try {
|
||||
group = await Misc.findCurrentGroup(Config.language);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to find current language group")
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (group && group.name !== "code" && group.name !== Config.language) {
|
||||
UpdateConfig.setLanguage(group.name);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,16 @@ export async function getSection(language: string): Promise<Section> {
|
|||
|
||||
// get TLD for wikipedia according to language group
|
||||
let urlTLD = "en";
|
||||
const currentLanguageGroup = await Misc.findCurrentGroup(language);
|
||||
|
||||
let currentLanguageGroup;
|
||||
try {
|
||||
currentLanguageGroup = await Misc.findCurrentGroup(language);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
Misc.createErrorMessage(e, "Failed to find current language group")
|
||||
);
|
||||
}
|
||||
|
||||
if (currentLanguageGroup !== undefined) {
|
||||
urlTLD = await getTLD(currentLanguageGroup);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,240 @@
|
|||
import * as Loader from "../elements/loader";
|
||||
|
||||
async function fetchJson<T>(url: string): Promise<T> {
|
||||
try {
|
||||
if (!url) throw new Error("No URL");
|
||||
const res = await fetch(url);
|
||||
if (res.ok) {
|
||||
return await res.json();
|
||||
} else {
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error fetching JSON: " + url, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export const cachedFetchJson = memoizeAsync(fetchJson);
|
||||
|
||||
export async function getLayoutsList(): Promise<MonkeyTypes.Layouts> {
|
||||
try {
|
||||
const layoutsList = await cachedFetchJson<MonkeyTypes.Layouts>(
|
||||
"/./layouts/_list.json"
|
||||
);
|
||||
return layoutsList;
|
||||
} catch (e) {
|
||||
throw new Error("Layouts JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws {Error} If layout list or layout doesnt exist.
|
||||
*/
|
||||
export async function getLayout(
|
||||
layoutName: string
|
||||
): Promise<MonkeyTypes.Layout> {
|
||||
const layouts = await getLayoutsList();
|
||||
const layout = layouts[layoutName];
|
||||
if (layout === undefined) {
|
||||
throw new Error(`Layout ${layoutName} is undefined`);
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
let themesList: MonkeyTypes.Theme[] | undefined;
|
||||
export async function getThemesList(): Promise<MonkeyTypes.Theme[]> {
|
||||
if (!themesList) {
|
||||
let themes = await cachedFetchJson<MonkeyTypes.Theme[]>(
|
||||
"/./themes/_list.json"
|
||||
);
|
||||
|
||||
themes = themes.sort(function (a: MonkeyTypes.Theme, b: MonkeyTypes.Theme) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
themesList = themes;
|
||||
return themesList;
|
||||
} else {
|
||||
return themesList;
|
||||
}
|
||||
}
|
||||
|
||||
let sortedThemesList: MonkeyTypes.Theme[] | undefined;
|
||||
export async function getSortedThemesList(): Promise<MonkeyTypes.Theme[]> {
|
||||
if (!sortedThemesList) {
|
||||
if (!themesList) {
|
||||
await getThemesList();
|
||||
}
|
||||
if (!themesList) {
|
||||
throw new Error("Themes list is undefined");
|
||||
}
|
||||
let sorted = [...themesList];
|
||||
sorted = sorted.sort((a, b) => {
|
||||
const b1 = hexToHSL(a.bgColor);
|
||||
const b2 = hexToHSL(b.bgColor);
|
||||
return b2.lgt - b1.lgt;
|
||||
});
|
||||
sortedThemesList = sorted;
|
||||
return sortedThemesList;
|
||||
} else {
|
||||
return sortedThemesList;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLanguageList(): Promise<string[]> {
|
||||
try {
|
||||
const languageList = await cachedFetchJson<string[]>(
|
||||
"/./languages/_list.json"
|
||||
);
|
||||
return languageList;
|
||||
} catch (e) {
|
||||
throw new Error("Language list JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLanguageGroups(): Promise<
|
||||
MonkeyTypes.LanguageGroup[]
|
||||
> {
|
||||
try {
|
||||
const languageGroupList = await cachedFetchJson<
|
||||
MonkeyTypes.LanguageGroup[]
|
||||
>("/./languages/_groups.json");
|
||||
return languageGroupList;
|
||||
} catch (e) {
|
||||
throw new Error("Language groups JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
let currentLanguage: MonkeyTypes.LanguageObject;
|
||||
export async function getLanguage(
|
||||
lang: string
|
||||
): Promise<MonkeyTypes.LanguageObject> {
|
||||
// try {
|
||||
if (currentLanguage == undefined || currentLanguage.name !== lang) {
|
||||
currentLanguage = await cachedFetchJson<MonkeyTypes.LanguageObject>(
|
||||
`/./languages/${lang}.json`
|
||||
);
|
||||
}
|
||||
return currentLanguage;
|
||||
// } catch (e) {
|
||||
// console.error(`error getting language`);
|
||||
// console.error(e);
|
||||
// currentLanguage = await cachedFetchJson<MonkeyTypes.LanguageObject>(
|
||||
// `/./language/english.json`
|
||||
// );
|
||||
// return currentLanguage;
|
||||
// }
|
||||
}
|
||||
|
||||
export async function getCurrentLanguage(
|
||||
languageName: string
|
||||
): Promise<MonkeyTypes.LanguageObject> {
|
||||
return await getLanguage(languageName);
|
||||
}
|
||||
|
||||
export async function findCurrentGroup(
|
||||
language: string
|
||||
): Promise<MonkeyTypes.LanguageGroup | undefined> {
|
||||
let retgroup: MonkeyTypes.LanguageGroup | undefined;
|
||||
const groups = await getLanguageGroups();
|
||||
groups.forEach((group) => {
|
||||
if (retgroup === undefined) {
|
||||
if (group.languages.includes(language)) {
|
||||
retgroup = group;
|
||||
}
|
||||
}
|
||||
});
|
||||
return retgroup;
|
||||
}
|
||||
|
||||
let funboxList: MonkeyTypes.FunboxObject[] | undefined;
|
||||
export async function getFunboxList(): Promise<MonkeyTypes.FunboxObject[]> {
|
||||
if (!funboxList) {
|
||||
let list = await cachedFetchJson<MonkeyTypes.FunboxObject[]>(
|
||||
"/./funbox/_list.json"
|
||||
);
|
||||
list = list.sort(function (
|
||||
a: MonkeyTypes.FunboxObject,
|
||||
b: MonkeyTypes.FunboxObject
|
||||
) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
funboxList = list;
|
||||
return funboxList;
|
||||
} else {
|
||||
return funboxList;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFunbox(
|
||||
funbox: string
|
||||
): Promise<MonkeyTypes.FunboxObject | undefined> {
|
||||
const list: MonkeyTypes.FunboxObject[] = await getFunboxList();
|
||||
return list.find(function (element) {
|
||||
return element.name == funbox;
|
||||
});
|
||||
}
|
||||
|
||||
let fontsList: MonkeyTypes.FontObject[] | undefined;
|
||||
export async function getFontsList(): Promise<MonkeyTypes.FontObject[]> {
|
||||
if (!fontsList) {
|
||||
let list = await cachedFetchJson<MonkeyTypes.FontObject[]>(
|
||||
"/./fonts/_list.json"
|
||||
);
|
||||
list = list.sort(function (
|
||||
a: MonkeyTypes.FontObject,
|
||||
b: MonkeyTypes.FontObject
|
||||
) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
fontsList = list;
|
||||
return fontsList;
|
||||
} else {
|
||||
return fontsList;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getChallengeList(): Promise<MonkeyTypes.Challenge[]> {
|
||||
try {
|
||||
const data = await cachedFetchJson<MonkeyTypes.Challenge[]>(
|
||||
"/./challenges/_list.json"
|
||||
);
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw new Error("Challenge list JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSupportersList(): Promise<string[]> {
|
||||
try {
|
||||
const data = await cachedFetchJson<string[]>("/./about/supporters.json");
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw new Error("Supporters list JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getContributorsList(): Promise<string[]> {
|
||||
try {
|
||||
const data = await cachedFetchJson<string[]>("/./about/contributors.json");
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw new Error("Contributors list JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
||||
function hexToHSL(hex: string): {
|
||||
hue: number;
|
||||
sat: number;
|
||||
|
@ -66,224 +301,6 @@ export function isColorDark(hex: string): boolean {
|
|||
return hsl.lgt < 50;
|
||||
}
|
||||
|
||||
let themesList: MonkeyTypes.Theme[] = [];
|
||||
export async function getThemesList(): Promise<MonkeyTypes.Theme[]> {
|
||||
if (themesList.length == 0) {
|
||||
return $.getJSON("/./themes/_list.json", function (data) {
|
||||
const list = data.sort(function (
|
||||
a: MonkeyTypes.Theme,
|
||||
b: MonkeyTypes.Theme
|
||||
) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
themesList = list;
|
||||
return themesList;
|
||||
});
|
||||
} else {
|
||||
return themesList;
|
||||
}
|
||||
}
|
||||
|
||||
let sortedThemesList: MonkeyTypes.Theme[] = [];
|
||||
export async function getSortedThemesList(): Promise<MonkeyTypes.Theme[]> {
|
||||
if (sortedThemesList.length === 0) {
|
||||
if (themesList.length === 0) {
|
||||
await getThemesList();
|
||||
}
|
||||
let sorted = [...themesList];
|
||||
sorted = sorted.sort((a, b) => {
|
||||
const b1 = hexToHSL(a.bgColor);
|
||||
const b2 = hexToHSL(b.bgColor);
|
||||
return b2.lgt - b1.lgt;
|
||||
});
|
||||
sortedThemesList = sorted;
|
||||
return sortedThemesList;
|
||||
} else {
|
||||
return sortedThemesList;
|
||||
}
|
||||
}
|
||||
|
||||
let funboxList: MonkeyTypes.FunboxObject[] = [];
|
||||
export async function getFunboxList(): Promise<MonkeyTypes.FunboxObject[]> {
|
||||
if (funboxList.length === 0) {
|
||||
return $.getJSON("/./funbox/_list.json", function (data) {
|
||||
funboxList = data.sort(function (
|
||||
a: MonkeyTypes.FunboxObject,
|
||||
b: MonkeyTypes.FunboxObject
|
||||
) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
return funboxList;
|
||||
});
|
||||
} else {
|
||||
return funboxList;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFunbox(
|
||||
funbox: string
|
||||
): Promise<MonkeyTypes.FunboxObject | undefined> {
|
||||
const list: MonkeyTypes.FunboxObject[] = await getFunboxList();
|
||||
return list.find(function (element) {
|
||||
return element.name == funbox;
|
||||
});
|
||||
}
|
||||
|
||||
let layoutsList: MonkeyTypes.Layouts = {};
|
||||
export async function getLayoutsList(): Promise<MonkeyTypes.Layouts> {
|
||||
if (Object.keys(layoutsList).length === 0) {
|
||||
return $.getJSON("/./layouts/_list.json", function (data) {
|
||||
layoutsList = data;
|
||||
return layoutsList;
|
||||
});
|
||||
} else {
|
||||
return layoutsList;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLayout(
|
||||
layoutName: string
|
||||
): Promise<MonkeyTypes.Layout> {
|
||||
if (Object.keys(layoutsList).length === 0) {
|
||||
await getLayoutsList();
|
||||
}
|
||||
return layoutsList[layoutName];
|
||||
}
|
||||
|
||||
let fontsList: MonkeyTypes.FontObject[] = [];
|
||||
export async function getFontsList(): Promise<MonkeyTypes.FontObject[]> {
|
||||
if (fontsList.length === 0) {
|
||||
return $.getJSON("/./fonts/_list.json", function (data) {
|
||||
fontsList = data.sort(function (
|
||||
a: MonkeyTypes.FontObject,
|
||||
b: MonkeyTypes.FontObject
|
||||
) {
|
||||
const nameA = a.name.toLowerCase();
|
||||
const nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) return -1;
|
||||
if (nameA > nameB) return 1;
|
||||
return 0;
|
||||
});
|
||||
return fontsList;
|
||||
});
|
||||
} else {
|
||||
return fontsList;
|
||||
}
|
||||
}
|
||||
|
||||
let supportersList: string[] = [];
|
||||
export async function getSupportersList(): Promise<string[]> {
|
||||
if (supportersList.length === 0) {
|
||||
return $.getJSON("/./about/supporters.json", function (data) {
|
||||
supportersList = data;
|
||||
return supportersList;
|
||||
});
|
||||
} else {
|
||||
return supportersList;
|
||||
}
|
||||
}
|
||||
|
||||
let contributorsList: string[] = [];
|
||||
export async function getContributorsList(): Promise<string[]> {
|
||||
if (contributorsList.length === 0) {
|
||||
return $.getJSON("/./about/contributors.json", function (data) {
|
||||
contributorsList = data;
|
||||
return contributorsList;
|
||||
});
|
||||
} else {
|
||||
return contributorsList;
|
||||
}
|
||||
}
|
||||
|
||||
let languageList: string[] = [];
|
||||
export async function getLanguageList(): Promise<string[]> {
|
||||
if (languageList.length === 0) {
|
||||
return $.getJSON("/./languages/_list.json", function (data) {
|
||||
languageList = data;
|
||||
return languageList;
|
||||
});
|
||||
} else {
|
||||
return languageList;
|
||||
}
|
||||
}
|
||||
|
||||
let languageGroupList: MonkeyTypes.LanguageGroup[] = [];
|
||||
export async function getLanguageGroups(): Promise<
|
||||
MonkeyTypes.LanguageGroup[]
|
||||
> {
|
||||
if (languageGroupList.length === 0) {
|
||||
return $.getJSON("/./languages/_groups.json", function (data) {
|
||||
languageGroupList = data;
|
||||
return languageGroupList;
|
||||
});
|
||||
} else {
|
||||
return languageGroupList;
|
||||
}
|
||||
}
|
||||
|
||||
let currentLanguage: MonkeyTypes.LanguageObject;
|
||||
export async function getLanguage(
|
||||
lang: string
|
||||
): Promise<MonkeyTypes.LanguageObject> {
|
||||
try {
|
||||
if (currentLanguage == undefined || currentLanguage.name !== lang) {
|
||||
console.log("getting language json");
|
||||
await $.getJSON(`/./languages/${lang}.json`, function (data) {
|
||||
currentLanguage = data;
|
||||
});
|
||||
}
|
||||
return currentLanguage;
|
||||
} catch (e) {
|
||||
console.error(`error getting language`);
|
||||
console.error(e);
|
||||
await $.getJSON(`/./languages/english.json`, function (data) {
|
||||
currentLanguage = data;
|
||||
});
|
||||
return currentLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCurrentLanguage(
|
||||
languageName: string
|
||||
): Promise<MonkeyTypes.LanguageObject> {
|
||||
return await getLanguage(languageName);
|
||||
}
|
||||
|
||||
export async function findCurrentGroup(
|
||||
language: string
|
||||
): Promise<MonkeyTypes.LanguageGroup | undefined> {
|
||||
let retgroup: MonkeyTypes.LanguageGroup | undefined;
|
||||
const groups = await getLanguageGroups();
|
||||
groups.forEach((group) => {
|
||||
if (retgroup === undefined) {
|
||||
if (group.languages.includes(language)) {
|
||||
retgroup = group;
|
||||
}
|
||||
}
|
||||
});
|
||||
return retgroup;
|
||||
}
|
||||
|
||||
let challengeList: MonkeyTypes.Challenge[] = [];
|
||||
export async function getChallengeList(): Promise<MonkeyTypes.Challenge[]> {
|
||||
if (challengeList.length === 0) {
|
||||
return $.getJSON("/./challenges/_list.json", function (data) {
|
||||
challengeList = data;
|
||||
return challengeList;
|
||||
});
|
||||
} else {
|
||||
return challengeList;
|
||||
}
|
||||
}
|
||||
|
||||
export function smooth(
|
||||
arr: number[],
|
||||
windowSize: number,
|
||||
|
@ -1244,6 +1261,30 @@ export async function sleep(ms: number): Promise<void> {
|
|||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export function memoizeAsync<T extends (...args: any) => Promise<any>>(
|
||||
fn: T,
|
||||
getKey?: (...args: Parameters<T>) => any
|
||||
): T {
|
||||
const cache = new Map<any, Promise<ReturnType<T>>>();
|
||||
|
||||
return (async (...args: Parameters<T>): Promise<ReturnType<T>> => {
|
||||
const key = getKey ? getKey.apply(args) : args[0];
|
||||
|
||||
if (cache.has(key)) {
|
||||
const ret = await cache.get(key);
|
||||
if (ret !== undefined) {
|
||||
return ret as ReturnType<T>;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-spread
|
||||
const result = fn.apply(null, args);
|
||||
cache.set(key, result);
|
||||
|
||||
return result;
|
||||
}) as T;
|
||||
}
|
||||
|
||||
export function isPasswordStrong(password: string): boolean {
|
||||
const hasCapital = !!password.match(/[A-Z]/);
|
||||
const hasNumber = !!password.match(/[\d]/);
|
||||
|
|
Loading…
Reference in a new issue