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" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Resources\Sound\alert.wav" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using AVSCartonShipmentVerifier.Repositories;
|
||||||
using AVSCartonShipmentVerifier.ScanHistory;
|
using AVSCartonShipmentVerifier.ScanHistory;
|
||||||
using AVSCartonShipmentVerifier.Services;
|
using AVSCartonShipmentVerifier.Services;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
|
@ -50,6 +51,11 @@ if (!app.Environment.IsDevelopment())
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "Resources")),
|
||||||
|
RequestPath = "/resources"
|
||||||
|
});
|
||||||
app.MapStaticAssets();
|
app.MapStaticAssets();
|
||||||
|
|
||||||
app.MapControllerRoute(
|
app.MapControllerRoute(
|
||||||
|
|
@ -58,4 +64,3 @@ app.MapControllerRoute(
|
||||||
.WithStaticAssets();
|
.WithStaticAssets();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -17,6 +17,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const antiForgeryToken = document.querySelector('input[name="__RequestVerificationToken"]')?.value;
|
const antiForgeryToken = document.querySelector('input[name="__RequestVerificationToken"]')?.value;
|
||||||
|
const failureAlarm = new Audio("/resources/Sound/alert.wav");
|
||||||
|
failureAlarm.preload = "auto";
|
||||||
let isSubmitting = false;
|
let isSubmitting = false;
|
||||||
|
|
||||||
qrInput.addEventListener("keydown", async event => {
|
qrInput.addEventListener("keydown", async event => {
|
||||||
|
|
@ -70,7 +72,6 @@
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const fallbackMessage = "Verification service is unavailable.";
|
const fallbackMessage = "Verification service is unavailable.";
|
||||||
setFailedState(payload.message ?? fallbackMessage);
|
setFailedState(payload.message ?? fallbackMessage);
|
||||||
triggerFailureAlarm();
|
|
||||||
resetDetails();
|
resetDetails();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +98,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
setFailedState(result.message);
|
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) {
|
function setFailedState(message) {
|
||||||
|
|
@ -183,22 +196,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerFailureAlarm() {
|
function triggerFailureAlarm() {
|
||||||
const context = new AudioContext();
|
failureAlarm.pause();
|
||||||
const oscillator = context.createOscillator();
|
failureAlarm.currentTime = 0;
|
||||||
const gainNode = context.createGain();
|
failureAlarm.play().catch(() => {
|
||||||
|
// Some browsers block audio until the scanner input is treated as a user gesture.
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue