Use custom alert sound for invalid scans
- Serve bundled sound resources from the Resources folder - Play alert.wav when a scan has invalid QR format or missing data - Play alert.wav when the scanned unique number is not found in the database - Keep the alert silent for other failures, such as service errors or shipment mark update failures - Include alert.wav in build and publish outputmain
parent
20482ec357
commit
fd1655947e
|
|
@ -13,4 +13,8 @@
|
|||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Resources\Sound\alert.wav" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using AVSCartonShipmentVerifier.Repositories;
|
|||
using AVSCartonShipmentVerifier.ScanHistory;
|
||||
using AVSCartonShipmentVerifier.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
|
@ -50,6 +51,11 @@ if (!app.Environment.IsDevelopment())
|
|||
app.UseHttpsRedirection();
|
||||
app.UseRouting();
|
||||
app.UseAuthorization();
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "Resources")),
|
||||
RequestPath = "/resources"
|
||||
});
|
||||
app.MapStaticAssets();
|
||||
|
||||
app.MapControllerRoute(
|
||||
|
|
@ -58,4 +64,3 @@ app.MapControllerRoute(
|
|||
.WithStaticAssets();
|
||||
|
||||
app.Run();
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -17,6 +17,8 @@
|
|||
};
|
||||
|
||||
const antiForgeryToken = document.querySelector('input[name="__RequestVerificationToken"]')?.value;
|
||||
const failureAlarm = new Audio("/resources/Sound/alert.wav");
|
||||
failureAlarm.preload = "auto";
|
||||
let isSubmitting = false;
|
||||
|
||||
qrInput.addEventListener("keydown", async event => {
|
||||
|
|
@ -70,7 +72,6 @@
|
|||
if (!response.ok) {
|
||||
const fallbackMessage = "Verification service is unavailable.";
|
||||
setFailedState(payload.message ?? fallbackMessage);
|
||||
triggerFailureAlarm();
|
||||
resetDetails();
|
||||
return;
|
||||
}
|
||||
|
|
@ -97,7 +98,19 @@
|
|||
}
|
||||
|
||||
setFailedState(result.message);
|
||||
triggerFailureAlarm();
|
||||
if (shouldTriggerFailureAlarm(result)) {
|
||||
triggerFailureAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
function shouldTriggerFailureAlarm(result) {
|
||||
const message = (result.message ?? "").toLowerCase();
|
||||
return !result.existsInSystem
|
||||
&& (
|
||||
message.includes("invalid qr format")
|
||||
|| message.includes("qr value is required")
|
||||
|| message.includes("not found")
|
||||
);
|
||||
}
|
||||
|
||||
function setFailedState(message) {
|
||||
|
|
@ -183,22 +196,10 @@
|
|||
}
|
||||
|
||||
function triggerFailureAlarm() {
|
||||
const context = new AudioContext();
|
||||
const oscillator = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillator.type = "sawtooth";
|
||||
oscillator.frequency.setValueAtTime(740, context.currentTime);
|
||||
oscillator.frequency.exponentialRampToValueAtTime(320, context.currentTime + 0.4);
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.0001, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.5, context.currentTime + 0.05);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 0.45);
|
||||
|
||||
oscillator.start(context.currentTime);
|
||||
oscillator.stop(context.currentTime + 0.45);
|
||||
oscillator.onended = () => context.close();
|
||||
failureAlarm.pause();
|
||||
failureAlarm.currentTime = 0;
|
||||
failureAlarm.play().catch(() => {
|
||||
// Some browsers block audio until the scanner input is treated as a user gesture.
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in New Issue