Boltcard Balance

This commit is contained in:
nicolas.dorier 2024-02-14 16:45:03 +09:00
parent 4c0c2d2e94
commit a4485b5377
No known key found for this signature in database
GPG key ID: 6618763EF09186FE
6 changed files with 174 additions and 2 deletions

View file

@ -22,6 +22,9 @@
<EmbeddedResource Remove="wwwroot\vendor\jquery-nice-select\**" />
<None Remove="Build\**" />
<None Remove="wwwroot\vendor\jquery-nice-select\**" />
<Content Update="Plugins\BoltcardBalance\Views\ScanCard.cshtml">
<Pack>$(IncludeRazorContentInPack)</Pack>
</Content>
<Content Update="Plugins\BoltcardFactory\Views\UpdateBoltcardFactory.cshtml">
<Pack>false</Pack>
</Content>

View file

@ -0,0 +1,35 @@
#nullable enable
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services;
using BTCPayServer.Client.Models;
using BTCPayServer.Configuration;
using BTCPayServer.Data;
using BTCPayServer.HostedServices;
using BTCPayServer.Plugins.BoltcardFactory.Controllers;
using BTCPayServer.Plugins.PointOfSale;
using BTCPayServer.Plugins.PointOfSale.Controllers;
using BTCPayServer.Services.Apps;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace BTCPayServer.Plugins.BoltcardBalance
{
public class BoltcardBalancePlugin : BaseBTCPayServerPlugin
{
public const string ViewsDirectory = "/Plugins/BoltcardBalance/Views";
public const string AppType = "BoltcardBalance";
public override string Identifier => "BTCPayServer.Plugins.BoltcardBalance";
public override string Name => "BoltcardBalance";
public override string Description => "Add ability to check the history and balance of a Boltcard";
public override void Execute(IServiceCollection services)
{
services.AddSingleton<IUIExtension>(new UIExtension($"{ViewsDirectory}/NavExtension.cshtml", "header-nav"));
base.Execute(services);
}
}
}

View file

@ -0,0 +1,15 @@
using BTCPayServer.Plugins.BoltcardFactory;
using Microsoft.AspNetCore.Mvc;
namespace BTCPayServer.Plugins.BoltcardBalance.Controllers
{
[AutoValidateAntiforgeryToken]
public class UIBoltcardBalanceController : Controller
{
[HttpGet("boltcards/balance")]
public IActionResult ScanCard()
{
return base.View($"{BoltcardBalancePlugin.ViewsDirectory}/ScanCard.cshtml");
}
}
}

View file

@ -0,0 +1,14 @@
@using BTCPayServer.Client
@using BTCPayServer.Plugins.BoltcardFactory
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Views.Apps
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.TagHelpers
<li class="nav-item">
<a asp-area="" asp-controller="UIBoltcardBalance" asp-action="ScanCard" class="nav-link">
<vc:icon symbol="pay-button" />
<span>Boltcard Balance</span>
</a>
</li>

View file

@ -0,0 +1,106 @@
@{
ViewData["Title"] = "C";
Layout = "/Views/Shared/_LayoutWizard.cshtml";
}
<header class="text-center">
<h1>Consult balance</h1>
<p class="lead text-secondary mt-3" id="explanation">Scan your card for consulting the balance</p>
</header>
<div id="body" class="my-4">
<div id="actions" class="d-flex align-items-center justify-content-center">
<div class="d-flex gap-3 mt-3 mt-sm-0">
<a id="ask-permission-btn" class="btn btn-primary" href="#">Ask permission...</a>
</div>
</div>
<div id="qr" class="d-flex flex-column align-items-center justify-content-center">
<div class="d-inline-flex flex-column" style="width:256px">
<div class="qr-container mb-2">
<vc:qr-code data="@Context.Request.GetCurrentUrl()" />
</div>
</div>
<p class="text-secondary">NFC not supported in this device</p>
</div>
<div id="scanning-btn" class="d-flex align-items-center justify-content-center">
<div class="d-flex gap-3 mt-3 mt-sm-0">
<a id="scanning-btn-link" class="btn btn-primary"></a>
</div>
</div>
</div>
<script>
(function () {
var permissionGranted = false;
var ndef = null;
var abortController = null;
async function askPermissionNFC() {
if (!('NDEFReader' in window)) {
return;
}
try {
permissionGranted = navigator.permissions && (await navigator.permissions.query({ name: 'nfc' })).state === 'granted';
} catch (e) { }
if (permissionGranted) {
setState("WaitingForCard");
ndef = new NDEFReader();
abortController = new AbortController();
abortController.signal.onabort = () => setState("WaitingForCard");
await ndef.scan({ signal: abortController.signal })
ndef.onreading = async ({ message }) => {
const record = message.records[0]
const textDecoder = new TextDecoder('utf-8')
const decoded = textDecoder.decode(record.data)
console.log("Read: " + decoded);
};
}
}
function setState(state)
{
if (state === "NFCNotSupported")
{
document.getElementById("actions").classList.add("d-none");
document.getElementById("qr").classList.remove("d-none");
document.getElementById("scanning-btn").classList.add("d-none");
}
else if (state === "WaitingForPermission")
{
document.getElementById("actions").classList.remove("d-none");
document.getElementById("qr").classList.add("d-none");
document.getElementById("scanning-btn").classList.add("d-none");
}
else if (state === "WaitingForCard")
{
document.getElementById("actions").classList.add("d-none");
document.getElementById("qr").classList.add("d-none");
document.getElementById("scanning-btn").classList.remove("d-none");
document.getElementById("scanning-btn-link").innerText = "Please, present your card..."
}
else if (state == "Scanning")
{
document.getElementById("actions").classList.add("d-none");
document.getElementById("qr").classList.add("d-none");
document.getElementById("scanning-btn").classList.remove("d-none");
document.getElementById("scanning-btn-link").innerText = "Reading..."
}
}
document.addEventListener("DOMContentLoaded", () => {
var nfcSupported = 'NDEFReader' in window;
if (!nfcSupported) {
setState("NFCNotSupported");
}
else {
setState("WaitingForPermission");
askPermissionNFC();
}
delegate('click', "#ask-permission-btn", askPermissionNFC);
});
})();
</script>

View file

@ -1,7 +1,7 @@
@model ViewBoltcardFactoryViewModel
@{
ViewData["Title"] = "C";
ViewData["Title"] = "Boltcard factory";
Layout = "/Views/Shared/_LayoutWizard.cshtml";
}
@ -23,7 +23,6 @@
<vc:qr-code data="@Context.Request.GetCurrentUrl()" />
</div>
</div>
</di>
</div>
</div>