v0.2.1: Change SHA256 input to file upload field

- Replace SHA256 text input with file upload field for checksum files
- Add readChecksumFile() JavaScript function using FileReader API
- Support .sha256 and .txt checksum file formats
- Add Promise-based async handling for file reading
- Add localized error messages for checksum file validation
- Update translations (de_CH) with new strings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 17:13:27 +01:00
parent f5a1e55710
commit fc2fe70576
7 changed files with 1220 additions and 1167 deletions

View File

@@ -101,9 +101,38 @@
$('#selected_file_name').text('');
$('#remove-version-file-btn').hide();
// Hide and clear SHA256 hash field
// Hide and clear checksum file field
$('#sha256-hash-row').hide();
$('#new_file_hash').val('');
$('#new_checksum_file').val('');
},
/**
* Read checksum from uploaded file
* Supports formats: "hash filename" or just "hash"
*/
readChecksumFile: function(file) {
return new Promise(function(resolve, reject) {
if (!file) {
resolve('');
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var content = e.target.result.trim();
// Extract hash from content (format: "hash filename" or just "hash")
var match = content.match(/^([a-fA-F0-9]{64})/);
if (match) {
resolve(match[1].toLowerCase());
} else {
reject(new Error(wcLicensedProductVersions.strings.invalidChecksumFile || 'Invalid checksum file format'));
}
};
reader.onerror = function() {
reject(new Error(wcLicensedProductVersions.strings.checksumReadError || 'Failed to read checksum file'));
};
reader.readAsText(file);
});
},
/**
@@ -134,13 +163,14 @@
addVersion: function(e) {
e.preventDefault();
var self = WCLicensedProductVersions;
var $btn = $(this);
var $spinner = $btn.siblings('.spinner');
var productId = $btn.data('product-id');
var version = $('#new_version').val().trim();
var releaseNotes = $('#new_release_notes').val().trim();
var attachmentId = $('#new_attachment_id').val();
var fileHash = $('#new_file_hash').val().trim();
var checksumFile = $('#new_checksum_file')[0].files[0];
// Validate version
if (!version) {
@@ -156,45 +186,52 @@
$btn.prop('disabled', true);
$spinner.addClass('is-active');
$.ajax({
url: wcLicensedProductVersions.ajaxUrl,
type: 'POST',
data: {
action: 'wc_licensed_product_add_version',
nonce: wcLicensedProductVersions.nonce,
product_id: productId,
version: version,
release_notes: releaseNotes,
attachment_id: attachmentId,
file_hash: fileHash
},
success: function(response) {
if (response.success) {
// Remove "no versions" row if present
$('#versions-table tbody .no-versions').remove();
// Read checksum file if provided, then submit
self.readChecksumFile(checksumFile).then(function(fileHash) {
$.ajax({
url: wcLicensedProductVersions.ajaxUrl,
type: 'POST',
data: {
action: 'wc_licensed_product_add_version',
nonce: wcLicensedProductVersions.nonce,
product_id: productId,
version: version,
release_notes: releaseNotes,
attachment_id: attachmentId,
file_hash: fileHash
},
success: function(response) {
if (response.success) {
// Remove "no versions" row if present
$('#versions-table tbody .no-versions').remove();
// Add new row to table
$('#versions-table tbody').prepend(response.data.html);
// Add new row to table
$('#versions-table tbody').prepend(response.data.html);
// Clear form
$('#new_version').val('');
$('#new_release_notes').val('');
$('#new_attachment_id').val('');
$('#selected_file_name').text('');
$('#remove-version-file-btn').hide();
$('#sha256-hash-row').hide();
$('#new_file_hash').val('');
} else {
alert(response.data.message || wcLicensedProductVersions.strings.error);
// Clear form
$('#new_version').val('');
$('#new_release_notes').val('');
$('#new_attachment_id').val('');
$('#selected_file_name').text('');
$('#remove-version-file-btn').hide();
$('#sha256-hash-row').hide();
$('#new_checksum_file').val('');
} else {
alert(response.data.message || wcLicensedProductVersions.strings.error);
}
},
error: function() {
alert(wcLicensedProductVersions.strings.error);
},
complete: function() {
$btn.prop('disabled', false);
$spinner.removeClass('is-active');
}
},
error: function() {
alert(wcLicensedProductVersions.strings.error);
},
complete: function() {
$btn.prop('disabled', false);
$spinner.removeClass('is-active');
}
});
}).catch(function(error) {
alert(error.message);
$btn.prop('disabled', false);
$spinner.removeClass('is-active');
});
},