pokerogue/src/ui/test-dialogue-ui-handler.ts
Opaque02 a2419c4fc3
[Misc] Add admin for (un)linking 3rd party accounts (#4198)
* Updated admin panel to allow the concept of unlinking accounts

* Don't look too hard at this commit, nothing to see here

* Admin stuff

* Fixed linking and unlinking and updated menu options

* Undid some changes and cleaned up some code

* Updated some logic and added some comments

* Updates to admin panel logic

* Stupid promises everyone hates them and they deserver to die

* Promise stuff still

* Promises working thanks to Ydarissep on discord - pushing with debug code before it decides to stop working again

* Removed debugging code

* All discord functionality seems to be working here?? Not sure what happened but yay

* Fixed up some bugs and code

* Added registered date to the panel

* Fixed and updated some minor error message related stuff

* Minor changes

* Fixed some minor bugs, made the save related errors have error codes, and added updated icons

* Updated search field error

* Missed a couple of things to push

* Fixed linting and doc errors

* Revert dev related code and clean up dev comments

* Reverting utils

* Updating front end to match back end from Pancakes' comments

* make getFields and getInputFieldConfigs a single function of FormUiHandler

* remove outdated doc

* Apply suggestions from code review

Moka review changes

Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com>

* Added docs

* eslint fixes

* Fixed error not showing up in certain conditions

---------

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
Co-authored-by: MokaStitcher <millennium.stitcher@gmail.com>
Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com>
Co-authored-by: innerthunder <brandonerickson98@gmail.com>
2024-10-23 22:00:07 +02:00

151 lines
5.6 KiB
TypeScript

import { FormModalUiHandler, InputFieldConfig } from "./form-modal-ui-handler";
import { ModalConfig } from "./modal-ui-handler";
import i18next from "i18next";
import { PlayerPokemon } from "#app/field/pokemon";
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
import { isNullOrUndefined } from "#app/utils";
import { Mode } from "./ui";
export default class TestDialogueUiHandler extends FormModalUiHandler {
keys: string[];
constructor(scene, mode) {
super(scene, mode);
}
setup() {
super.setup();
const flattenKeys = (object?: any, topKey?: string, midleKey?: string[]): Array<any> => {
return Object.keys(object ?? {}).map((t, i) => {
const value = Object.values(object)[i];
if (typeof value === "object" && !isNullOrUndefined(value)) { // we check for not null or undefined here because if the language json file has a null key, the typeof will still be an object, but that object will be null, causing issues
// If the value is an object, execute the same process
// si el valor es un objeto ejecuta el mismo proceso
return flattenKeys(value, topKey ?? t, topKey ? midleKey ? [ ...midleKey, t ] : [ t ] : undefined).filter((t) => t.length > 0);
} else if (typeof value === "string" || isNullOrUndefined(value)) { // we check for null or undefined here as per above - the typeof is still an object but the value is null so we need to exit out of this and pass the null key
// Return in the format expected by i18next
return midleKey ? `${topKey}:${midleKey.map((m) => m).join(".")}.${t}` : `${topKey}:${t}`;
}
}).filter((t) => t);
};
const keysInArrays = flattenKeys(i18next.getDataByLanguage(String(i18next.resolvedLanguage))).filter((t) => t.length > 0); // Array of arrays
const keys = keysInArrays.flat(Infinity).map(String); // One array of string
this.keys = keys;
}
getModalTitle(config?: ModalConfig): string {
return "Test Dialogue";
}
getWidth(config?: ModalConfig): number {
return 300;
}
getMargin(config?: ModalConfig): [number, number, number, number] {
return [ 0, 0, 48, 0 ];
}
getButtonLabels(config?: ModalConfig): string[] {
return [ "Check", "Cancel" ];
}
getReadableErrorMessage(error: string): string {
const colonIndex = error?.indexOf(":");
if (colonIndex > 0) {
error = error.slice(0, colonIndex);
}
return super.getReadableErrorMessage(error);
}
override getInputFieldConfigs(): InputFieldConfig[] {
return [{ label: "Dialogue" }];
}
show(args: any[]): boolean {
const ui = this.getUi();
const hasTitle = !!this.getModalTitle();
this.updateFields(this.getInputFieldConfigs(), hasTitle);
this.updateContainer(args[0] as ModalConfig);
const input = this.inputs[0];
input.setMaxLength(255);
input.on("keydown", (inputObject, evt: KeyboardEvent) => {
if ([ "escape", "space" ].some((v) => v === evt.key.toLowerCase() || v === evt.code.toLowerCase()) && ui.getMode() === Mode.AUTO_COMPLETE) {
// Delete autocomplete list and recovery focus.
inputObject.on("blur", () => inputObject.node.focus(), { once: true });
ui.revertMode();
}
});
input.on("textchange", (inputObject, evt: InputEvent) => {
// Delete autocomplete.
if (ui.getMode() === Mode.AUTO_COMPLETE) {
ui.revertMode();
}
let options: OptionSelectItem[] = [];
const splitArr = inputObject.text.split(" ");
const filteredKeys = this.keys.filter((command) => command.toLowerCase().includes(splitArr[splitArr.length - 1].toLowerCase()));
if (inputObject.text !== "" && filteredKeys.length > 0) {
// if performance is required, you could reduce the number of total results by changing the slice below to not have all ~8000 inputs going
options = filteredKeys.slice(0).map((value) => {
return {
label: value,
handler: () => {
// this is here to make sure that if you try to backspace then enter, the last known evt.data (backspace) is picked up
// this is because evt.data is null for backspace, so without this, the autocomplete windows just closes
if (!isNullOrUndefined(evt.data) || evt.inputType?.toLowerCase() === "deletecontentbackward") {
const separatedArray = inputObject.text.split(" ");
separatedArray[separatedArray.length - 1] = value;
inputObject.setText(separatedArray.join(" "));
}
ui.revertMode();
return true;
}
};
});
}
if (options.length > 0) {
const modalOpts = {
options: options,
maxOptions: 5,
modalContainer: this.modalContainer
};
ui.setOverlayMode(Mode.AUTO_COMPLETE, modalOpts);
}
});
if (super.show(args)) {
const config = args[0] as ModalConfig;
this.inputs[0].resize(1150, 116);
this.inputContainers[0].list[0].width = 200;
if (args[1] && typeof (args[1] as PlayerPokemon).getNameToRender === "function") {
this.inputs[0].text = (args[1] as PlayerPokemon).getNameToRender();
} else {
this.inputs[0].text = args[1];
}
this.submitAction = (_) => {
if (ui.getMode() === Mode.TEST_DIALOGUE) {
this.sanitizeInputs();
const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text)));
config.buttonActions[0](sanitizedName);
return true;
}
return false;
};
return true;
}
return false;
}
}