diff --git a/index.html b/index.html index cafafbb..ed1d1a1 100644 --- a/index.html +++ b/index.html @@ -208,7 +208,7 @@ 3. Finetune stick calibration
- + diff --git a/js/core.js b/js/core.js index 3693141..77d132b 100644 --- a/js/core.js +++ b/js/core.js @@ -14,8 +14,8 @@ import { isQuickTestVisible, quicktest_handle_controller_input } from './modals/quick-test-modal.js'; +import { show_calibration_history_modal } from './modals/calibration-history-modal.js'; import { FinetuneHistory } from './finetune-history.js'; -import { CalibrationHistoryModal } from './modals/calibration-history-modal.js'; // Application State - manages app-wide state and UI const app = { @@ -110,7 +110,6 @@ function gboot() { await loadAllTemplates(); - CalibrationHistoryModal.init(); initAnalyticsApi(app); // init just with gu for now lang_init(app, handleLanguageChange, show_welcome_modal); show_welcome_modal(); @@ -338,7 +337,7 @@ async function continue_connection({data, device}) { show_popup(`

${ l("It appears the latest joystick calibration has not been saved.") }

${ - l("You should save your changes, or reboot the controller if you don't want to keep them.") + l("You should save your changes, or reboot the controller to revert back to the previous state.") }

`, true); } @@ -1144,16 +1143,6 @@ window.ds5_finetune = () => ds5_finetune( (success) => success && switchToRangeMode() ); -window.apply_finetune_revert = async (finetuneData) => { - if (!controller || !controller.isConnected()) { - throw new Error('Controller not connected'); - } - if (!Array.isArray(finetuneData) || finetuneData.length !== 12) { - throw new Error('Invalid finetune data'); - } - await controller.writeFinetuneData(finetuneData); -}; - window.openCalibrationHistoryModal = async () => { let currentFinetuneData = null; let controllerSerialNumber = null; @@ -1161,7 +1150,6 @@ window.openCalibrationHistoryModal = async () => { if (controller && typeof controller.getInMemoryModuleData === 'function') { currentFinetuneData = await controller.getInMemoryModuleData('finetune'); } - // Get serial number from device info if (controller && typeof controller.getDeviceInfo === 'function') { const info = await controller.getDeviceInfo(); const serialNumberItem = info?.infoItems?.find(item => item.key === l("Serial Number")); @@ -1170,7 +1158,10 @@ window.openCalibrationHistoryModal = async () => { } catch (error) { console.warn('Could not retrieve current finetune data or serial number:', error); } - window.show_calibration_history_modal(currentFinetuneData, controllerSerialNumber); + await show_calibration_history_modal(controller, currentFinetuneData, controllerSerialNumber, (success, message) => { + if(!message) return; + success ? infoAlert(message) : errorAlert(message); + }); }; window.flash_all_changes = flash_all_changes; diff --git a/js/modals/calibration-history-modal.js b/js/modals/calibration-history-modal.js index 10d5ab2..745bed2 100644 --- a/js/modals/calibration-history-modal.js +++ b/js/modals/calibration-history-modal.js @@ -2,31 +2,46 @@ import { FinetuneHistory } from '../finetune-history.js'; import { formatLocalizedDate } from '../utils.js'; +import { l } from '../translations.js'; export class CalibrationHistoryModal { - static modalElement = null; - static bootstrapModal = null; - static currentFinetuneData = null; - static currentControllerSerialNumber = null; + constructor(controllerInstance = null, doneCallback = null) { + this.modalElement = null; + this.bootstrapModal = null; + this.currentFinetuneData = null; + this.currentControllerSerialNumber = null; + this.controller = controllerInstance; + this.doneCallback = doneCallback; - static init() { + this._boundModalHidden = () => { + destroyCurrentInstance(); + }; + + this._initEventListeners(); + } + + _initEventListeners() { this.modalElement = document.getElementById('calibrationHistoryModal'); if (this.modalElement) { this.bootstrapModal = new bootstrap.Modal(this.modalElement); + this.modalElement.addEventListener('hidden.bs.modal', this._boundModalHidden); } } - static async show(currentFinetuneData = null, controllerSerialNumber = null) { - if (!this.bootstrapModal) { - this.init(); + removeEventListeners() { + if (this.modalElement) { + this.modalElement.removeEventListener('hidden.bs.modal', this._boundModalHidden); } + } + + async open(currentFinetuneData = null, controllerSerialNumber = null) { this.currentFinetuneData = currentFinetuneData; this.currentControllerSerialNumber = controllerSerialNumber; await this._populateHistory(); this.bootstrapModal.show(); } - static hide() { + close() { if (this.bootstrapModal) { this.bootstrapModal.hide(); } @@ -36,12 +51,12 @@ export class CalibrationHistoryModal { * Populate the history list * @private */ - static async _populateHistory() { + async _populateHistory() { const history = FinetuneHistory.getAll(this.currentControllerSerialNumber); const container = document.getElementById('historyListContainer'); if (!history || history.length === 0) { - container.innerHTML = '

No saved calibration settings found.

'; + container.innerHTML = `

${l('No saved calibrations found')}.

`; document.getElementById('clearAllBtn').style.display = 'none'; return; } @@ -59,13 +74,13 @@ export class CalibrationHistoryModal {
${date}
-

Values: ${entry.data.join(', ')}

+

${l('Values')}: ${entry.data.join(', ')}

${isCurrent ? - `` : - ` - ` + `` : + ` + ` }
@@ -81,7 +96,7 @@ export class CalibrationHistoryModal { * Compare two data arrays for equality * @private */ - static _dataEquals(data1, data2) { + _dataEquals(data1, data2) { if (!Array.isArray(data1) || !Array.isArray(data2)) { return false; } @@ -92,66 +107,45 @@ export class CalibrationHistoryModal { } /** - * Escape HTML special characters + * Apply finetune calibration to the controller + * @param {Array} finetuneData - The finetune data to apply * @private */ - static _escapeHtml(text) { - const div = document.createElement('div'); - div.textContent = text; - return div.innerHTML; + async _applyCalibration(finetuneData) { + if (!this.controller || !this.controller.isConnected()) { + throw new Error('Controller not connected'); + } + if (!Array.isArray(finetuneData) || finetuneData.length !== 12) { + throw new Error('Invalid finetune data'); + } + await this.controller.writeFinetuneData(finetuneData); + this.controller.setHasChangesToWrite(true); } /** - * Revert to a saved calibration + * Restore a saved calibration * @param {string} entryId - The ID of the entry to revert to */ - static revertTo(entryId) { + async restoreCalibration(entryId) { const entry = FinetuneHistory.getById(entryId, this.currentControllerSerialNumber); - if (!entry) { - alert('Calibration settings not found.'); - return; - } + if (!entry) throw new Error('Calibration settings not found.'); - // Export revert function to window for onclick handlers - window.calibration_history_pending_revert_id = entryId; - window.calibration_history_pending_revert_data = entry.data; - - // Show confirmation dialog - const confirmMsg = `Revert to this version?\n\nThis will restore the stored finetune settings.`; - if (confirm(confirmMsg)) { - this._executeRevert(entryId, entry.data); - } - } - - /** - * Execute the revert operation - * @private - */ - static _executeRevert(entryId, finetuneData) { - // Call the revert function exposed in core.js - if (typeof window.apply_finetune_revert === 'function') { - window.apply_finetune_revert(finetuneData).then(() => { - this.hide(); - alert('Calibration reverted successfully. Remember to save changes permanently.'); - }).catch(err => { - alert('Failed to revert calibration: ' + err.message); - }); - } else { - alert('Controller not ready. Please try again.'); - } + await this._applyCalibration(entry.data); + this.close(); + this.doneCallback(true, l('The calibration was restored successfully! Remember to save the changes in order not to loose them when the controller is rebooted.')); } /** * Delete a saved entry * @param {string} entryId - The ID of the entry to delete */ - static async delete(entryId) { + async delete(entryId) { const entry = FinetuneHistory.getById(entryId, this.currentControllerSerialNumber); if (!entry) { return; } - if (confirm(`Delete this calibration entry?`)) { + if (confirm(l(`Delete this calibration entry?`))) { FinetuneHistory.delete(entryId, this.currentControllerSerialNumber); await this._populateHistory(); } @@ -160,16 +154,46 @@ export class CalibrationHistoryModal { /** * Clear all saved entries */ - static async clearAll() { - if (confirm('Delete all calibration history for this controller? This cannot be undone.')) { + async clearAll() { + if (confirm(l('Delete all calibration history for this controller? This cannot be undone.'))) { FinetuneHistory.clearAll(this.currentControllerSerialNumber); await this._populateHistory(); } } } -// Export functions to window for onclick handlers -window.calibration_history_revert = (entryId) => CalibrationHistoryModal.revertTo(entryId); -window.calibration_history_delete = (entryId) => CalibrationHistoryModal.delete(entryId); -window.calibration_history_clear_all = () => CalibrationHistoryModal.clearAll(); -window.show_calibration_history_modal = (currentFinetuneData = null, controllerSerialNumber = null) => CalibrationHistoryModal.show(currentFinetuneData, controllerSerialNumber); \ No newline at end of file +let currentCalibrationHistoryInstance = null; + +function destroyCurrentInstance() { + if (currentCalibrationHistoryInstance) { + currentCalibrationHistoryInstance.removeEventListeners(); + currentCalibrationHistoryInstance = null; + } +} + +export async function show_calibration_history_modal(controllerInstance = null, currentFinetuneData = null, controllerSerialNumber = null, doneCallback = null) { + destroyCurrentInstance(); + + currentCalibrationHistoryInstance = new CalibrationHistoryModal(controllerInstance, doneCallback); + await currentCalibrationHistoryInstance.open(currentFinetuneData, controllerSerialNumber); +} + +window.calibration_history_restore = (entryId) => { + if (currentCalibrationHistoryInstance) { + currentCalibrationHistoryInstance.restoreCalibration(entryId); + } +}; + +window.calibration_history_delete = (entryId) => { + if (currentCalibrationHistoryInstance) { + currentCalibrationHistoryInstance.delete(entryId); + } +}; + +window.calibration_history_clear_all = () => { + if (currentCalibrationHistoryInstance) { + currentCalibrationHistoryInstance.clearAll(); + } +}; + +window.show_calibration_history_modal = show_calibration_history_modal; \ No newline at end of file