Fix Virtual Controller Remapper's bug

This commit is contained in:
redphx 2024-10-23 20:00:27 +07:00
parent b06dc6e219
commit 6440c91cdf
2 changed files with 117 additions and 110 deletions

View File

@ -1,4 +1,4 @@
import { CE, createButton, ButtonStyle } from "@utils/html";
import { CE, createButton, ButtonStyle, removeChildElements } from "@utils/html";
import { t } from "@utils/translation";
import { Dialog } from "@modules/dialog";
import { KeyHelper } from "./key-helper";
@ -61,12 +61,10 @@ export class MkbRemapper {
public static getInstance = () => MkbRemapper.instance ?? (MkbRemapper.instance = new MkbRemapper());
private readonly LOG_TAG = 'MkbRemapper';
private STATE: MkbRemapperStates = {
private states: MkbRemapperStates = {
currentPresetId: 0,
presets: {},
editingPresetData: null,
isEditing: false,
};
@ -83,7 +81,7 @@ export class MkbRemapper {
private constructor() {
BxLogger.info(this.LOG_TAG, 'constructor()');
this.STATE.currentPresetId = getPref(PrefKey.MKB_DEFAULT_PRESET_ID);
this.states.currentPresetId = getPref(PrefKey.MKB_DEFAULT_PRESET_ID);
this.bindingDialog = new Dialog({
className: 'bx-binding-dialog',
@ -117,7 +115,7 @@ export class MkbRemapper {
}
}
this.STATE.editingPresetData!.mapping[buttonIndex][keySlot] = key.code;
this.states.editingPresetData!.mapping[buttonIndex][keySlot] = key.code;
$elm.textContent = key.name;
$elm.dataset.keyCode = key.code;
}
@ -127,7 +125,7 @@ export class MkbRemapper {
const keySlot = parseInt($elm.dataset.keySlot!);
// Remove key from preset
this.STATE.editingPresetData!.mapping[buttonIndex][keySlot] = null;
this.states.editingPresetData!.mapping[buttonIndex][keySlot] = null;
$elm.textContent = '';
delete $elm.dataset.keyCode;
}
@ -161,7 +159,7 @@ export class MkbRemapper {
};
private onBindingKey = (e: MouseEvent) => {
if (!this.STATE.isEditing || e.button !== 0) {
if (!this.states.isEditing || e.button !== 0) {
return;
}
@ -178,7 +176,7 @@ export class MkbRemapper {
private onContextMenu = (e: Event) => {
e.preventDefault();
if (!this.STATE.isEditing) {
if (!this.states.isEditing) {
return;
}
@ -186,15 +184,24 @@ export class MkbRemapper {
};
private getPreset = (presetId: number) => {
return this.STATE.presets[presetId];
return this.states.presets[presetId];
}
private getCurrentPreset = () => {
return this.getPreset(this.STATE.currentPresetId);
let preset = this.getPreset(this.states.currentPresetId);
if (!preset) {
// Get the first preset in the list
const firstPresetId = parseInt(Object.keys(this.states.presets)[0]);
preset = this.states.presets[firstPresetId];
this.states.currentPresetId = firstPresetId;
setPref(PrefKey.MKB_DEFAULT_PRESET_ID, firstPresetId);
}
return preset;
}
private switchPreset = (presetId: number) => {
this.STATE.currentPresetId = presetId;
this.states.currentPresetId = presetId;
const presetData = this.getCurrentPreset().data;
for (const $elm of this.allKeyElements) {
@ -223,26 +230,25 @@ export class MkbRemapper {
}
// Update state of Activate button
const activated = getPref(PrefKey.MKB_DEFAULT_PRESET_ID) === this.STATE.currentPresetId;
const activated = getPref(PrefKey.MKB_DEFAULT_PRESET_ID) === this.states.currentPresetId;
this.$activateButton.disabled = activated;
this.$activateButton.querySelector('span')!.textContent = activated ? t('activated') : t('activate');
}
private refresh() {
private async refresh() {
// Clear presets select
while (this.$presetsSelect.firstChild) {
this.$presetsSelect.removeChild(this.$presetsSelect.firstChild);
}
removeChildElements(this.$presetsSelect);
MkbPresetsDb.getInstance().getPresets().then(presets => {
this.STATE.presets = presets;
const $fragment = document.createDocumentFragment();
const presets = await MkbPresetsDb.getInstance().getPresets();
this.states.presets = presets;
const fragment = document.createDocumentFragment();
let defaultPresetId;
if (this.STATE.currentPresetId === 0) {
this.STATE.currentPresetId = parseInt(Object.keys(presets)[0]);
if (this.states.currentPresetId === 0) {
this.states.currentPresetId = parseInt(Object.keys(presets)[0]);
defaultPresetId = this.STATE.currentPresetId;
defaultPresetId = this.states.currentPresetId;
setPref(PrefKey.MKB_DEFAULT_PRESET_ID, defaultPresetId);
EmulatedMkbHandler.getInstance().refreshPresetData();
} else {
@ -257,30 +263,29 @@ export class MkbRemapper {
}
const $options = CE<HTMLOptionElement>('option', {value: id}, name);
$options.selected = parseInt(id) === this.STATE.currentPresetId;
$options.selected = parseInt(id) === this.states.currentPresetId;
$fragment.appendChild($options);
fragment.appendChild($options);
};
this.$presetsSelect.appendChild($fragment);
this.$presetsSelect.appendChild(fragment);
// Update state of Activate button
const activated = defaultPresetId === this.STATE.currentPresetId;
const activated = defaultPresetId === this.states.currentPresetId;
this.$activateButton.disabled = activated;
this.$activateButton.querySelector('span')!.textContent = activated ? t('activated') : t('activate');
!this.STATE.isEditing && this.switchPreset(this.STATE.currentPresetId);
});
!this.states.isEditing && this.switchPreset(this.states.currentPresetId);
}
private toggleEditing = (force?: boolean) => {
this.STATE.isEditing = typeof force !== 'undefined' ? force : !this.STATE.isEditing;
this.$wrapper.classList.toggle('bx-editing', this.STATE.isEditing);
this.states.isEditing = typeof force !== 'undefined' ? force : !this.states.isEditing;
this.$wrapper.classList.toggle('bx-editing', this.states.isEditing);
if (this.STATE.isEditing) {
this.STATE.editingPresetData = deepClone(this.getCurrentPreset().data);
if (this.states.isEditing) {
this.states.editingPresetData = deepClone(this.getCurrentPreset().data);
} else {
this.STATE.editingPresetData = null;
this.states.editingPresetData = null;
}
@ -290,7 +295,7 @@ export class MkbRemapper {
continue;
}
let disable = !this.STATE.isEditing;
let disable = !this.states.isEditing;
if ($elm.parentElement!.classList.contains('bx-mkb-preset-tools')) {
disable = !disable;
@ -328,7 +333,7 @@ export class MkbRemapper {
title: t('rename'),
icon: BxIcon.CURSOR_TEXT,
tabIndex: -1,
onClick: e => {
onClick: async () => {
const preset = this.getCurrentPreset();
let newName = promptNewName(preset.name);
@ -338,7 +343,9 @@ export class MkbRemapper {
// Update preset with new name
preset.name = newName;
MkbPresetsDb.getInstance().updatePreset(preset).then(id => this.refresh());
await MkbPresetsDb.getInstance().updatePreset(preset);
await this.refresh();
},
}),
@ -355,7 +362,7 @@ export class MkbRemapper {
// Create new preset selected name
MkbPresetsDb.getInstance().newPreset(newName, MkbPreset.DEFAULT_PRESET).then(id => {
this.STATE.currentPresetId = id;
this.states.currentPresetId = id;
this.refresh();
});
},
@ -376,7 +383,7 @@ export class MkbRemapper {
// Create new preset selected name
MkbPresetsDb.getInstance().newPreset(newName, preset.data).then(id => {
this.STATE.currentPresetId = id;
this.states.currentPresetId = id;
this.refresh();
});
},
@ -393,8 +400,8 @@ export class MkbRemapper {
return;
}
MkbPresetsDb.getInstance().deletePreset(this.STATE.currentPresetId).then(id => {
this.STATE.currentPresetId = 0;
MkbPresetsDb.getInstance().deletePreset(this.states.currentPresetId).then(id => {
this.states.currentPresetId = 0;
this.refresh();
});
},
@ -448,7 +455,7 @@ export class MkbRemapper {
let $elm;
const onChange = (e: Event, value: any) => {
(this.STATE.editingPresetData!.mouse as any)[key] = value;
(this.states.editingPresetData!.mouse as any)[key] = value;
};
const $row = CE('label', {
class: 'bx-settings-row',
@ -481,7 +488,7 @@ export class MkbRemapper {
style: ButtonStyle.PRIMARY,
tabIndex: -1,
onClick: e => {
setPref(PrefKey.MKB_DEFAULT_PRESET_ID, this.STATE.currentPresetId);
setPref(PrefKey.MKB_DEFAULT_PRESET_ID, this.states.currentPresetId);
EmulatedMkbHandler.getInstance().refreshPresetData();
this.refresh();
@ -497,7 +504,7 @@ export class MkbRemapper {
tabIndex: -1,
onClick: e => {
// Restore preset
this.switchPreset(this.STATE.currentPresetId);
this.switchPreset(this.states.currentPresetId);
this.toggleEditing(false);
},
}),
@ -509,7 +516,7 @@ export class MkbRemapper {
tabIndex: -1,
onClick: e => {
const updatedPreset = deepClone(this.getCurrentPreset());
updatedPreset.data = this.STATE.editingPresetData as MkbPresetData;
updatedPreset.data = this.states.editingPresetData as MkbPresetData;
MkbPresetsDb.getInstance().updatePreset(updatedPreset).then(id => {
// If this is the default preset => refresh preset data

View File

@ -32,65 +32,65 @@ export class MkbPresetsDb extends LocalDb {
}
}
private presetsTable() {
return this.open()
.then(() => this.table(this.TABLE_PRESETS, 'readwrite'))
private async presetsTable() {
await this.open();
return await this.table(this.TABLE_PRESETS, 'readwrite');
}
newPreset(name: string, data: any) {
return this.presetsTable()
.then(table => this.add(table, {name, data}))
.then(([table, id]) => new Promise<number>(resolve => resolve(id)));
async newPreset(name: string, data: any) {
const table = await this.presetsTable();
const [, id] = await this.add(table, { name, data });
return id;
}
updatePreset(preset: MkbStoredPreset) {
return this.presetsTable()
.then(table => this.put(table, preset))
.then(([table, id]) => new Promise(resolve => resolve(id)));
async updatePreset(preset: MkbStoredPreset) {
const table = await this.presetsTable();
const [, id] = await this.put(table, preset);
return id;
}
deletePreset(id: number) {
return this.presetsTable()
.then(table => this.delete(table, id))
.then(([table, id]) => new Promise(resolve => resolve(id)));
async deletePreset(id: number) {
const table = await this.presetsTable();
await this.delete(table, id);
return id;
}
getPreset(id: number): Promise<MkbStoredPreset> {
return this.presetsTable()
.then(table => this.get(table, id))
.then(([table, preset]) => new Promise(resolve => resolve(preset)));
async getPreset(id: number): Promise<MkbStoredPreset> {
const table = await this.presetsTable();
const [, preset] = await this.get(table, id);
return preset;
}
getPresets(): Promise<MkbStoredPresets> {
return this.presetsTable()
.then(table => this.count(table))
.then(([table, count]) => {
async getPresets(): Promise<MkbStoredPresets> {
const table = await this.presetsTable();
const [, count] = await this.count(table);
// Return stored presets
if (count > 0) {
return new Promise(resolve => {
this.getAll(table)
.then(([table, items]) => {
const [, items] = await this.getAll(table);
const presets: MkbStoredPresets = {};
items.forEach((item: MkbStoredPreset) => (presets[item.id!] = item));
resolve(presets);
});
});
return presets;
}
// Create "Default" preset when the table is empty
const preset: MkbStoredPreset = {
name: t('default'),
data: MkbPreset.DEFAULT_PRESET,
}
};
const [, id] = await this.add(table, preset);
return new Promise<MkbStoredPresets>(resolve => {
this.add(table, preset)
.then(([table, id]) => {
preset.id = id;
setPref(PrefKey.MKB_DEFAULT_PRESET_ID, id);
resolve({[id]: preset});
});
});
});
return {
[id]: preset,
};
}
}