mirror of
https://github.com/dualshock-tools/dualshock-tools.github.io.git
synced 2026-03-01 11:19:54 +03:00
On connecting to a controller, show a message if the last calibration change was not saved
This commit is contained in:
@@ -45,12 +45,97 @@ class ControllerManager {
|
||||
this._lastBatteryText = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique storage key for the device
|
||||
* @param {string} serialNumber The device serial number
|
||||
* @returns {string} Storage key based on serial number
|
||||
*/
|
||||
_getDeviceStorageKey(serialNumber) {
|
||||
if (!serialNumber) return null;
|
||||
return `changes_${serialNumber}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save has_changes_to_write state to localStorage
|
||||
*/
|
||||
async _saveHasChangesState() {
|
||||
if (!this.currentController) return;
|
||||
try {
|
||||
const serialNumber = await this.currentController.getSerialNumber();
|
||||
const key = this._getDeviceStorageKey(serialNumber);
|
||||
if (key) {
|
||||
localStorage.setItem(key, JSON.stringify(this.has_changes_to_write));
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to save changes state:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore has_changes_to_write state from localStorage
|
||||
*/
|
||||
async _restoreHasChangesState() {
|
||||
if (!this.currentController) return;
|
||||
try {
|
||||
const serialNumber = await this.currentController.getSerialNumber();
|
||||
const key = this._getDeviceStorageKey(serialNumber);
|
||||
if (key) {
|
||||
const saved = localStorage.getItem(key);
|
||||
if (saved !== null) {
|
||||
try {
|
||||
const restoredState = JSON.parse(saved);
|
||||
this.has_changes_to_write = restoredState;
|
||||
this._updateUI();
|
||||
} catch (e) {
|
||||
console.warn('Failed to parse changes state:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to restore changes state:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI based on current has_changes_to_write state
|
||||
*/
|
||||
_updateUI() {
|
||||
const saveBtn = $("#savechanges");
|
||||
saveBtn
|
||||
.prop('disabled', !this.has_changes_to_write)
|
||||
.toggleClass('btn-success', this.has_changes_to_write)
|
||||
.toggleClass('btn-outline-secondary', !this.has_changes_to_write);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear controller state: remove localStorage entry and reset UI
|
||||
* @private
|
||||
*/
|
||||
async _clearControllerState() {
|
||||
if (this.currentController) {
|
||||
try {
|
||||
const serialNumber = await this.currentController.getSerialNumber();
|
||||
const key = this._getDeviceStorageKey(serialNumber);
|
||||
if (key) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to clear localStorage:', e);
|
||||
}
|
||||
}
|
||||
this.has_changes_to_write = false;
|
||||
this._updateUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current controller instance
|
||||
* @param {BaseController} controller Controller instance
|
||||
*/
|
||||
setControllerInstance(instance) {
|
||||
this.currentController = instance;
|
||||
if (instance) {
|
||||
this._restoreHasChangesState().catch(e => console.warn('Failed to restore changes state:', e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,13 +245,9 @@ class ControllerManager {
|
||||
if (hasChanges === this.has_changes_to_write)
|
||||
return;
|
||||
|
||||
const saveBtn = $("#savechanges");
|
||||
saveBtn
|
||||
.prop('disabled', !hasChanges)
|
||||
.toggleClass('btn-success', hasChanges)
|
||||
.toggleClass('btn-outline-secondary', !hasChanges);
|
||||
|
||||
this.has_changes_to_write = hasChanges;
|
||||
this._updateUI();
|
||||
this._saveHasChangesState().catch(e => console.warn('Failed to save changes state:', e));
|
||||
}
|
||||
|
||||
// Unified controller operations that delegate to the current controller
|
||||
@@ -175,7 +256,7 @@ class ControllerManager {
|
||||
* Flash/save changes to the controller
|
||||
*/
|
||||
async flash(progressCallback = null) {
|
||||
this.setHasChangesToWrite(false);
|
||||
await this._clearControllerState();
|
||||
return this.currentController.flash(progressCallback);
|
||||
}
|
||||
|
||||
@@ -183,7 +264,8 @@ class ControllerManager {
|
||||
* Reset the controller
|
||||
*/
|
||||
async reset() {
|
||||
await this.currentController.reset();
|
||||
await this._clearControllerState();
|
||||
return this.currentController.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,6 +100,14 @@ class BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serial number of the device
|
||||
* @returns {Promise<string>} The device serial number
|
||||
*/
|
||||
async getSerialNumber() {
|
||||
throw new Error('getSerialNumber() must be implemented by subclass');
|
||||
}
|
||||
|
||||
// Abstract methods that must be implemented by subclasses
|
||||
async getInfo() {
|
||||
throw new Error('getInfo() must be implemented by subclass');
|
||||
|
||||
@@ -131,6 +131,10 @@ class DS4Controller extends BaseController {
|
||||
return DS4_INPUT_CONFIG;
|
||||
}
|
||||
|
||||
async getSerialNumber() {
|
||||
return await this.getBdAddr();
|
||||
}
|
||||
|
||||
async getInfo() {
|
||||
// Device-only: collect info and return a common structure; do not touch the DOM
|
||||
try {
|
||||
|
||||
@@ -266,6 +266,10 @@ class DS5Controller extends BaseController {
|
||||
return DS5_INPUT_CONFIG;
|
||||
}
|
||||
|
||||
async getSerialNumber() {
|
||||
return await this.getSystemInfo(1, 19, 17);
|
||||
}
|
||||
|
||||
async getInfo() {
|
||||
return this._getInfo(false);
|
||||
}
|
||||
|
||||
17
js/core.js
17
js/core.js
@@ -333,13 +333,20 @@ async function continue_connection({data, device}) {
|
||||
show_popup(l("<p>Support for PS VR2 controllers is <b>minimal and highly experimental</b>.</p><p>I currently don't own these controllers, so I cannot verify the calibration process myself.</p><p>If you'd like to help improve full support, you can contribute with a donation or even send the controllers for testing.</p><p>Feel free to contact me on Discord (the_al) or by email at ds4@the.al .</p><br><p>Thank you for your support!</p>"), true)
|
||||
}
|
||||
|
||||
// Check for unsaved calibration changes
|
||||
if (controller.has_changes_to_write) {
|
||||
show_popup(`<p>${
|
||||
l("It appears the latest joystick calibration has not been saved.")
|
||||
}</p><p>${
|
||||
l("You should save your changes, or reboot the controller if you don't want to keep them.")
|
||||
}</p>`, true);
|
||||
}
|
||||
|
||||
// Save finetune parameters for DS5 and Edge controllers
|
||||
if (model === "DS5" || model === "DS5_Edge") {
|
||||
const finetuneData = await controllerInstance.getInMemoryModuleData();
|
||||
// Extract serial number from info items
|
||||
const serialNumberItem = info.infoItems?.find(item => item.key === l("Serial Number"));
|
||||
const serialNumber = serialNumberItem?.value;
|
||||
if (serialNumber) {
|
||||
if (!controller.has_changes_to_write) {
|
||||
const finetuneData = await controllerInstance.getInMemoryModuleData();
|
||||
const serialNumber = await controllerInstance.getSerialNumber();
|
||||
FinetuneHistory.save(finetuneData, serialNumber);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user