Skip to content

Commit

Permalink
Refactoring: Use low-level audio API to play the sound
Browse files Browse the repository at this point in the history
Allows to play the sound regardless of browser permissions.
  • Loading branch information
dennisreimann committed Jun 23, 2023
1 parent 12fcd64 commit 48eb34b
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 19 deletions.
9 changes: 6 additions & 3 deletions BTCPayServer/Controllers/UIInvoiceController.UI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
using BTCPayServer.Models.InvoicingModels;
using BTCPayServer.Models.PaymentRequestViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Payments.Bitcoin;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Rating;
using BTCPayServer.Services;
using BTCPayServer.Services.Apps;
Expand Down Expand Up @@ -877,7 +875,6 @@ public async Task<IActionResult> CheckoutNoScript(string? invoiceId, string? id
CustomCSSLink = storeBlob.CustomCSS,
CustomLogoLink = storeBlob.CustomLogo,
LogoFileId = storeBlob.LogoFileId,
SoundFileId = storeBlob.SoundFileId,
CssFileId = storeBlob.CssFileId,
BrandColor = storeBlob.BrandColor,
CheckoutType = invoice.CheckoutType ?? storeBlob.CheckoutType,
Expand Down Expand Up @@ -961,6 +958,12 @@ public async Task<IActionResult> CheckoutNoScript(string? invoiceId, string? id
model.PaymentMethodId = paymentMethodId.ToString();
model.PaymentType = paymentMethodId.PaymentType.ToString();
model.OrderAmountFiat = OrderAmountFromInvoice(model.CryptoCode, invoice, DisplayFormatter.CurrencyFormat.Symbol);

if (!string.IsNullOrEmpty(storeBlob.SoundFileId))
{
model.PaymentSoundUrl = await _fileService.GetFileUrl(Request.GetAbsoluteRootUri(), storeBlob.SoundFileId);
}

var expiration = TimeSpan.FromSeconds(model.ExpirationSeconds);
model.TimeLeft = expiration.PrettyPrint();
return model;
Expand Down
4 changes: 4 additions & 0 deletions BTCPayServer/Controllers/UIInvoiceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
Expand Down Expand Up @@ -60,6 +61,7 @@ public partial class UIInvoiceController : Controller
private readonly LinkGenerator _linkGenerator;
private readonly IAuthorizationService _authorizationService;
private readonly AppService _appService;
private readonly IFileService _fileService;

public WebhookSender WebhookNotificationManager { get; }

Expand All @@ -84,6 +86,7 @@ public partial class UIInvoiceController : Controller
InvoiceActivator invoiceActivator,
LinkGenerator linkGenerator,
AppService appService,
IFileService fileService,
IAuthorizationService authorizationService)
{
_displayFormatter = displayFormatter;
Expand All @@ -105,6 +108,7 @@ public partial class UIInvoiceController : Controller
_invoiceActivator = invoiceActivator;
_linkGenerator = linkGenerator;
_authorizationService = authorizationService;
_fileService = fileService;
_appService = appService;
}

Expand Down
2 changes: 1 addition & 1 deletion BTCPayServer/Models/InvoicingModels/PaymentModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class AvailableCrypto
public string CustomLogoLink { get; set; }
public string CssFileId { get; set; }
public string LogoFileId { get; set; }
public string SoundFileId { get; set; }
public string PaymentSoundUrl { get; set; }
public string BrandColor { get; set; }
public string HtmlTitle { get; set; }
public string DefaultLang { get; set; }
Expand Down
14 changes: 5 additions & 9 deletions BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
@using BTCPayServer.Services
@using BTCPayServer.Abstractions.Contracts
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.EntityFrameworkCore.Diagnostics
@inject LanguageService LangService
@inject BTCPayServerEnvironment Env
@inject IEnumerable<IUIExtension> UiExtensions
@inject IFileService FileService
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
@model PaymentModel
Expand All @@ -28,6 +28,10 @@
<meta name="robots" content="noindex,nofollow">
<link href="~/checkout-v2/checkout.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
@if (!string.IsNullOrEmpty(Model.PaymentSoundUrl))
{
<link rel="preload" href="@Model.PaymentSoundUrl" as="audio" />
}
</head>
<body class="min-vh-100">
<div id="Checkout-v2" class="public-page-wrap" v-cloak>
Expand Down Expand Up @@ -104,10 +108,6 @@
<div class="top">
<span class="icn">
<div id="confetti" v-if="srvModel.celebratePayment" v-on:click="celebratePayment(5000)"></div>
@if (!string.IsNullOrEmpty(Model.SoundFileId))
{
<audio src="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.SoundFileId))" id="sound"></audio>
}
<vc:icon symbol="payment-sent" />
</span>
<h4 v-t="'payment_received'" class="mb-4"></h4>
Expand Down Expand Up @@ -147,10 +147,6 @@
<div class="top">
<span class="icn">
<div id="confetti" v-if="srvModel.celebratePayment" v-on:click="celebratePayment(5000)"></div>
@if (!string.IsNullOrEmpty(Model.SoundFileId))
{
<audio src="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.SoundFileId))" id="sound"></audio>
}
<vc:icon symbol="payment-complete" />
</span>
<h4 v-t="'invoice_paid'"></h4>
Expand Down
29 changes: 23 additions & 6 deletions BTCPayServer/wwwroot/checkout-v2/checkout.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ function initApp() {
paymentMethodId: null,
endData: null,
isModal: srvModel.isModal,
pollTimeoutID: null
pollTimeoutID: null,
paymentSound: null
}
},
computed: {
Expand Down Expand Up @@ -236,6 +237,9 @@ function initApp() {
if (this.isProcessing) {
this.listenForConfirmations();
}
if (this.srvModel.paymentSoundUrl) {
this.preparePaymentSound();
}
updateLanguageSelect();
window.parent.postMessage('loaded', '*');
},
Expand Down Expand Up @@ -335,12 +339,17 @@ function initApp() {
return value ? value.replace(/\n/ig, '<br>') : '';
},
async celebratePayment (duration) {
const $soundEl = document.getElementById('sound');
if ($soundEl && !$soundEl.dataset.running) {
$soundEl.dataset.running = true;
$soundEl.play();
delete $soundEl.dataset.running;
// sound
if (this.paymentSound && !this.paymentSound.playing) {
const { audioContext, audioBuffer } = this.paymentSound;
const source = audioContext.createBufferSource();
source.onended = () => { this.paymentSound.playing = false; };
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start();
this.paymentSound.playing = true;
}
// confetti
const $confettiEl = document.getElementById('confetti')
if (window.confetti && $confettiEl && !$confettiEl.dataset.running) {
$confettiEl.dataset.running = true;
Expand All @@ -353,6 +362,14 @@ function initApp() {
});
delete $confettiEl.dataset.running;
}
},
async preparePaymentSound () {
const audioContext = new AudioContext();
const response = await fetch(this.srvModel.paymentSoundUrl)
if (!response.ok) return console.error(`Could not load payment sound, HTTP error ${response.status}`);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
this.paymentSound = { audioContext, audioBuffer, playing: false };
}
}
});
Expand Down

0 comments on commit 48eb34b

Please sign in to comment.