mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Fix zap dialog positioning and gating
This commit is contained in:
1 parent
5d04571b6b
commit
0fd54abde8
6 files changed
+447
-145
No files matched your search
+118
-95
@@ -35,18 +35,124 @@
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
id="modalZapBtn"
|
||||
type="button"
|
||||
class="icon-button"
|
||||
aria-label="Send a zap"
|
||||
>
|
||||
<img
|
||||
src="assets/svg/lightning-bolt.svg"
|
||||
alt="Zap"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<div class="relative" data-modal-zap-wrapper>
|
||||
<button
|
||||
id="modalZapBtn"
|
||||
type="button"
|
||||
class="icon-button"
|
||||
aria-label="Send a zap"
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded="false"
|
||||
aria-controls="modalZapDialog"
|
||||
>
|
||||
<img
|
||||
src="assets/svg/lightning-bolt.svg"
|
||||
alt="Zap"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
id="modalZapDialog"
|
||||
class="zap-popover hidden"
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="zap-popover__content w-72 max-w-[calc(100vw-2rem)] rounded-lg bg-gray-900/95 p-4 shadow-lg backdrop-blur"
|
||||
>
|
||||
<div class="mb-3 flex items-center justify-between gap-4">
|
||||
<h3
|
||||
class="text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Send a zap
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
id="modalZapCloseBtn"
|
||||
class="text-gray-400 transition-colors hover:text-gray-200"
|
||||
aria-label="Close zap dialog"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
id="modalZapWalletPrompt"
|
||||
class="mb-3 hidden text-sm text-gray-200"
|
||||
aria-hidden="true"
|
||||
>
|
||||
Connect a wallet in
|
||||
<button
|
||||
type="button"
|
||||
id="modalZapWalletLink"
|
||||
class="font-semibold text-blue-300 underline decoration-dotted transition-colors hover:text-blue-200"
|
||||
>
|
||||
Wallet Connect settings
|
||||
</button>
|
||||
to send zaps.
|
||||
</p>
|
||||
<form id="modalZapForm" class="space-y-3">
|
||||
<div>
|
||||
<label
|
||||
for="modalZapAmountInput"
|
||||
class="mb-2 block text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Zap amount (sats)
|
||||
</label>
|
||||
<input
|
||||
id="modalZapAmountInput"
|
||||
type="number"
|
||||
min="1"
|
||||
step="1"
|
||||
inputmode="numeric"
|
||||
class="w-full rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Enter sats"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="modalZapCommentInput"
|
||||
class="mb-2 block text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Comment (optional)
|
||||
</label>
|
||||
<textarea
|
||||
id="modalZapCommentInput"
|
||||
rows="2"
|
||||
maxlength="280"
|
||||
class="w-full resize-y rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Include a note with your zap"
|
||||
></textarea>
|
||||
</div>
|
||||
<p
|
||||
id="modalZapSplitSummary"
|
||||
class="text-sm text-gray-300"
|
||||
aria-live="polite"
|
||||
>
|
||||
Enter an amount to view the split.
|
||||
</p>
|
||||
<p
|
||||
id="modalZapStatus"
|
||||
class="text-xs text-gray-400"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
></p>
|
||||
<ul
|
||||
id="modalZapReceipts"
|
||||
class="space-y-2 text-xs text-gray-300"
|
||||
></ul>
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<button
|
||||
type="submit"
|
||||
id="modalZapSendBtn"
|
||||
class="rounded bg-blue-500 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-offset-2 focus:ring-offset-gray-900"
|
||||
>
|
||||
Send zap
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button id="shareBtn" class="icon-button">
|
||||
<img
|
||||
src="assets/svg/share-video.svg"
|
||||
@@ -167,89 +273,6 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Zap dialog -->
|
||||
<div id="modalZapDialog" class="hidden mt-4" aria-hidden="true">
|
||||
<div
|
||||
class="w-full rounded-lg bg-gray-900 bg-opacity-70 p-4 shadow-lg backdrop-blur"
|
||||
>
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3
|
||||
class="text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Send a zap
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
id="modalZapCloseBtn"
|
||||
class="text-gray-400 hover:text-gray-200 transition-colors"
|
||||
aria-label="Close zap dialog"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<form id="modalZapForm" class="space-y-3">
|
||||
<div>
|
||||
<label
|
||||
for="modalZapAmountInput"
|
||||
class="block text-xs font-semibold uppercase tracking-wide text-gray-300 mb-2"
|
||||
>
|
||||
Zap amount (sats)
|
||||
</label>
|
||||
<input
|
||||
id="modalZapAmountInput"
|
||||
type="number"
|
||||
min="1"
|
||||
step="1"
|
||||
inputmode="numeric"
|
||||
class="w-full rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Enter sats"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
for="modalZapCommentInput"
|
||||
class="block text-xs font-semibold uppercase tracking-wide text-gray-300 mb-2"
|
||||
>
|
||||
Comment (optional)
|
||||
</label>
|
||||
<textarea
|
||||
id="modalZapCommentInput"
|
||||
rows="2"
|
||||
maxlength="280"
|
||||
class="w-full resize-y rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Include a note with your zap"
|
||||
></textarea>
|
||||
</div>
|
||||
<p
|
||||
id="modalZapSplitSummary"
|
||||
class="text-sm text-gray-300"
|
||||
aria-live="polite"
|
||||
>
|
||||
Enter an amount to view the split.
|
||||
</p>
|
||||
<p
|
||||
id="modalZapStatus"
|
||||
class="text-xs text-gray-400"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
></p>
|
||||
<ul
|
||||
id="modalZapReceipts"
|
||||
class="space-y-2 text-xs text-gray-300"
|
||||
></ul>
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<button
|
||||
type="submit"
|
||||
id="modalZapSendBtn"
|
||||
class="rounded bg-blue-500 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-offset-2 focus:ring-offset-gray-900"
|
||||
>
|
||||
Send zap
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Torrent stats -->
|
||||
<div class="bg-gray-800/50 rounded-lg p-4">
|
||||
<div class="w-full bg-gray-700 rounded-full h-2 mb-2">
|
||||
|
||||
@@ -1016,6 +1016,19 @@ body.modal-open #app {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.zap-popover {
|
||||
position: absolute;
|
||||
top: calc(100% + 0.5rem);
|
||||
right: 0;
|
||||
z-index: 80;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.zap-popover__content {
|
||||
width: 18rem;
|
||||
max-width: calc(100vw - 2rem);
|
||||
}
|
||||
|
||||
.modal-actions__overflow {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
|
||||
@@ -198,6 +198,7 @@ class Application {
|
||||
this.boundVideoModalShareHandler = null;
|
||||
this.boundVideoModalCreatorHandler = null;
|
||||
this.boundVideoModalZapHandler = null;
|
||||
this.boundVideoModalZapWalletHandler = null;
|
||||
this.videoListViewPlaybackHandler = null;
|
||||
this.videoListViewEditHandler = null;
|
||||
this.videoListViewRevertHandler = null;
|
||||
@@ -529,6 +530,15 @@ class Application {
|
||||
"zap:comment-change",
|
||||
this.boundVideoModalZapCommentHandler
|
||||
);
|
||||
this.boundVideoModalZapWalletHandler = () => {
|
||||
if (typeof this.openWalletPane === "function") {
|
||||
this.openWalletPane();
|
||||
}
|
||||
};
|
||||
this.videoModal.addEventListener(
|
||||
"zap:wallet-link",
|
||||
this.boundVideoModalZapWalletHandler
|
||||
);
|
||||
|
||||
// Hide/Show Subscriptions Link
|
||||
this.subscriptionsLink = null;
|
||||
@@ -4512,6 +4522,17 @@ class Application {
|
||||
return cached ? { ...cached } : createDefaultNwcSettings();
|
||||
}
|
||||
|
||||
hasActiveWalletConnection() {
|
||||
const settings = this.getActiveNwcSettings();
|
||||
const candidate =
|
||||
typeof settings?.nwcUri === "string" ? settings.nwcUri.trim() : "";
|
||||
return candidate.length > 0;
|
||||
}
|
||||
|
||||
isUserLoggedIn() {
|
||||
return Boolean(this.normalizeHexPubkey(this.pubkey));
|
||||
}
|
||||
|
||||
async updateActiveNwcSettings(partial = {}) {
|
||||
const normalized = this.normalizeHexPubkey(this.pubkey);
|
||||
if (!normalized) {
|
||||
@@ -5726,8 +5747,12 @@ class Application {
|
||||
}
|
||||
|
||||
setModalZapVisibility(visible) {
|
||||
const lightningVisible = !!visible;
|
||||
const shouldShow = lightningVisible && this.isUserLoggedIn();
|
||||
const hasWallet = this.hasActiveWalletConnection();
|
||||
if (this.videoModal) {
|
||||
this.videoModal.setZapVisibility(visible);
|
||||
this.videoModal.setZapVisibility(shouldShow);
|
||||
this.videoModal.setWalletPromptVisible(shouldShow && !hasWallet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9479,6 +9504,13 @@ class Application {
|
||||
);
|
||||
this.boundVideoModalZapCommentHandler = null;
|
||||
}
|
||||
if (this.boundVideoModalZapWalletHandler) {
|
||||
this.videoModal.removeEventListener(
|
||||
"zap:wallet-link",
|
||||
this.boundVideoModalZapWalletHandler
|
||||
);
|
||||
this.boundVideoModalZapWalletHandler = null;
|
||||
}
|
||||
if (typeof this.videoModal.destroy === "function") {
|
||||
try {
|
||||
this.videoModal.destroy();
|
||||
|
||||
+161
-7
@@ -109,9 +109,13 @@ let cachedZapAmountInput = null;
|
||||
let cachedZapSplitSummary = null;
|
||||
let cachedZapStatus = null;
|
||||
let cachedZapReceipts = null;
|
||||
let cachedZapWalletPrompt = null;
|
||||
let cachedZapWalletLink = null;
|
||||
let cachedZapCloseBtn = null;
|
||||
|
||||
let pendingZapRetry = null;
|
||||
let zapInFlight = false;
|
||||
let zapControlsOpen = false;
|
||||
|
||||
function getChannelZapButton() {
|
||||
if (cachedZapButton && !document.body.contains(cachedZapButton)) {
|
||||
@@ -126,28 +130,53 @@ function getChannelZapButton() {
|
||||
function setChannelZapVisibility(visible) {
|
||||
const zapButton = getChannelZapButton();
|
||||
const controls = getZapControlsContainer();
|
||||
const amountInput = getZapAmountInput();
|
||||
if (!zapButton) {
|
||||
return;
|
||||
}
|
||||
const shouldShow = !!visible;
|
||||
const app = getApp();
|
||||
const isLoggedIn =
|
||||
typeof app?.isUserLoggedIn === "function"
|
||||
? app.isUserLoggedIn()
|
||||
: Boolean(app?.normalizeHexPubkey?.(app?.pubkey));
|
||||
const shouldShow = !!visible && isLoggedIn;
|
||||
zapButton.classList.toggle("hidden", !shouldShow);
|
||||
zapButton.disabled = !shouldShow;
|
||||
zapButton.setAttribute("aria-disabled", (!shouldShow).toString());
|
||||
zapButton.setAttribute("aria-hidden", (!shouldShow).toString());
|
||||
zapButton.setAttribute("aria-expanded", "false");
|
||||
if (shouldShow) {
|
||||
zapButton.removeAttribute("tabindex");
|
||||
} else {
|
||||
zapButton.setAttribute("tabindex", "-1");
|
||||
if (controls) {
|
||||
controls.classList.add("hidden");
|
||||
}
|
||||
resetZapRetryState();
|
||||
zapInFlight = false;
|
||||
clearZapReceipts();
|
||||
setZapStatus("", "neutral");
|
||||
}
|
||||
closeZapControls();
|
||||
if (controls) {
|
||||
controls.classList.toggle("hidden", !shouldShow);
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
if (amountInput) {
|
||||
amountInput.disabled = !shouldShow;
|
||||
}
|
||||
|
||||
const hasWallet =
|
||||
typeof app?.hasActiveWalletConnection === "function"
|
||||
? app.hasActiveWalletConnection()
|
||||
: (() => {
|
||||
const settings =
|
||||
typeof app?.getActiveNwcSettings === "function"
|
||||
? app.getActiveNwcSettings()
|
||||
: {};
|
||||
const uri =
|
||||
typeof settings?.nwcUri === "string" ? settings.nwcUri.trim() : "";
|
||||
return uri.length > 0;
|
||||
})();
|
||||
setZapWalletPromptVisible(shouldShow && !hasWallet);
|
||||
if (shouldShow) {
|
||||
setupZapWalletLink();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +250,114 @@ function getZapReceiptsList() {
|
||||
return cachedZapReceipts;
|
||||
}
|
||||
|
||||
function getZapWalletPrompt() {
|
||||
if (cachedZapWalletPrompt && !document.body.contains(cachedZapWalletPrompt)) {
|
||||
cachedZapWalletPrompt = null;
|
||||
}
|
||||
if (!cachedZapWalletPrompt) {
|
||||
cachedZapWalletPrompt = document.getElementById("zapWalletPrompt");
|
||||
}
|
||||
return cachedZapWalletPrompt;
|
||||
}
|
||||
|
||||
function getZapWalletLink() {
|
||||
if (cachedZapWalletLink && !document.body.contains(cachedZapWalletLink)) {
|
||||
cachedZapWalletLink = null;
|
||||
}
|
||||
if (!cachedZapWalletLink) {
|
||||
cachedZapWalletLink = document.getElementById("zapWalletLink");
|
||||
}
|
||||
return cachedZapWalletLink;
|
||||
}
|
||||
|
||||
function getZapCloseButton() {
|
||||
if (cachedZapCloseBtn && !document.body.contains(cachedZapCloseBtn)) {
|
||||
cachedZapCloseBtn = null;
|
||||
}
|
||||
if (!cachedZapCloseBtn) {
|
||||
cachedZapCloseBtn = document.getElementById("zapCloseBtn");
|
||||
}
|
||||
return cachedZapCloseBtn;
|
||||
}
|
||||
|
||||
function setZapWalletPromptVisible(visible) {
|
||||
const prompt = getZapWalletPrompt();
|
||||
if (!prompt) {
|
||||
return;
|
||||
}
|
||||
const shouldShow = !!visible;
|
||||
prompt.classList.toggle("hidden", !shouldShow);
|
||||
prompt.setAttribute("aria-hidden", (!shouldShow).toString());
|
||||
}
|
||||
|
||||
function setupZapWalletLink() {
|
||||
const link = getZapWalletLink();
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
if (link.dataset.initialized === "true") {
|
||||
return;
|
||||
}
|
||||
link.addEventListener("click", (event) => {
|
||||
event?.preventDefault?.();
|
||||
const app = getApp();
|
||||
if (typeof app?.openWalletPane === "function") {
|
||||
app.openWalletPane();
|
||||
}
|
||||
});
|
||||
link.dataset.initialized = "true";
|
||||
}
|
||||
|
||||
function focusZapAmountField() {
|
||||
const amountInput = getZapAmountInput();
|
||||
if (amountInput && typeof amountInput.focus === "function") {
|
||||
try {
|
||||
amountInput.focus({ preventScroll: true });
|
||||
} catch (error) {
|
||||
amountInput.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isZapControlsOpen() {
|
||||
return zapControlsOpen;
|
||||
}
|
||||
|
||||
function openZapControls({ focus = false } = {}) {
|
||||
const controls = getZapControlsContainer();
|
||||
const zapButton = getChannelZapButton();
|
||||
if (!controls || !zapButton) {
|
||||
return false;
|
||||
}
|
||||
if (!zapControlsOpen) {
|
||||
controls.classList.remove("hidden");
|
||||
controls.setAttribute("aria-hidden", "false");
|
||||
zapButton.setAttribute("aria-expanded", "true");
|
||||
zapControlsOpen = true;
|
||||
}
|
||||
if (focus) {
|
||||
focusZapAmountField();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function closeZapControls({ focusButton = false } = {}) {
|
||||
const controls = getZapControlsContainer();
|
||||
const zapButton = getChannelZapButton();
|
||||
if (controls) {
|
||||
controls.classList.add("hidden");
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
if (zapButton) {
|
||||
zapButton.setAttribute("aria-expanded", "false");
|
||||
if (focusButton && typeof zapButton.focus === "function") {
|
||||
zapButton.focus();
|
||||
}
|
||||
}
|
||||
zapControlsOpen = false;
|
||||
return Boolean(controls && zapButton);
|
||||
}
|
||||
|
||||
function updateZapSplitSummary({ overrideFee = null } = {}) {
|
||||
const summaryEl = getZapSplitSummaryElement();
|
||||
if (!summaryEl) {
|
||||
@@ -388,8 +525,8 @@ function resetZapRetryState() {
|
||||
const zapButton = getChannelZapButton();
|
||||
if (zapButton) {
|
||||
delete zapButton.dataset.retryPending;
|
||||
zapButton.setAttribute("aria-label", "Send a zap");
|
||||
zapButton.title = "Send a zap";
|
||||
zapButton.setAttribute("aria-label", "Open zap dialog");
|
||||
zapButton.title = "Open zap dialog";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,6 +960,11 @@ async function handleZapButtonClick(event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isZapControlsOpen()) {
|
||||
openZapControls({ focus: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentChannelLightningAddress) {
|
||||
setZapStatus("This creator has not configured a Lightning address yet.", "error");
|
||||
app?.showError?.("This creator has not configured a Lightning address yet.");
|
||||
@@ -1160,6 +1302,18 @@ function setupZapButton() {
|
||||
}
|
||||
|
||||
setChannelZapVisibility(false);
|
||||
controls.classList.add("hidden");
|
||||
controls.setAttribute("aria-hidden", "true");
|
||||
zapButton.setAttribute("aria-expanded", "false");
|
||||
setupZapWalletLink();
|
||||
const closeBtn = getZapCloseButton();
|
||||
if (closeBtn && closeBtn.dataset.initialized !== "true") {
|
||||
closeBtn.addEventListener("click", (event) => {
|
||||
event?.preventDefault?.();
|
||||
closeZapControls({ focusButton: true });
|
||||
});
|
||||
closeBtn.dataset.initialized = "true";
|
||||
}
|
||||
|
||||
if (zapButton.dataset.initialized === "true") {
|
||||
updateZapSplitSummary();
|
||||
|
||||
@@ -54,6 +54,8 @@ export class VideoModal {
|
||||
this.modalZapReceipts = null;
|
||||
this.modalZapSendBtn = null;
|
||||
this.modalZapCloseBtn = null;
|
||||
this.modalZapWalletPrompt = null;
|
||||
this.modalZapWalletLink = null;
|
||||
this.modalZapDialogOpen = false;
|
||||
this.modalZapPending = false;
|
||||
|
||||
@@ -208,6 +210,10 @@ export class VideoModal {
|
||||
playerModal.querySelector("#modalZapSendBtn") || null;
|
||||
this.modalZapCloseBtn =
|
||||
playerModal.querySelector("#modalZapCloseBtn") || null;
|
||||
this.modalZapWalletPrompt =
|
||||
playerModal.querySelector("#modalZapWalletPrompt") || null;
|
||||
this.modalZapWalletLink =
|
||||
playerModal.querySelector("#modalZapWalletLink") || null;
|
||||
|
||||
const closeButton = playerModal.querySelector("#closeModal");
|
||||
if (closeButton) {
|
||||
@@ -307,6 +313,13 @@ export class VideoModal {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.modalZapWalletLink) {
|
||||
this.modalZapWalletLink.addEventListener("click", (event) => {
|
||||
event?.preventDefault?.();
|
||||
this.dispatch("zap:wallet-link", { video: this.activeVideo });
|
||||
});
|
||||
}
|
||||
|
||||
if (this.modalZapForm) {
|
||||
this.modalZapForm.addEventListener("submit", (event) => {
|
||||
event?.preventDefault?.();
|
||||
@@ -539,6 +552,7 @@ export class VideoModal {
|
||||
this.modalZapBtn.disabled = disableButton;
|
||||
this.modalZapBtn.setAttribute("aria-disabled", (!shouldShow).toString());
|
||||
this.modalZapBtn.setAttribute("aria-hidden", (!shouldShow).toString());
|
||||
this.modalZapBtn.setAttribute("aria-expanded", "false");
|
||||
if (shouldShow) {
|
||||
this.modalZapBtn.removeAttribute("tabindex");
|
||||
} else {
|
||||
@@ -558,6 +572,18 @@ export class VideoModal {
|
||||
}
|
||||
}
|
||||
|
||||
setWalletPromptVisible(visible) {
|
||||
if (!this.modalZapWalletPrompt) {
|
||||
return;
|
||||
}
|
||||
const shouldShow = !!visible;
|
||||
this.modalZapWalletPrompt.classList.toggle("hidden", !shouldShow);
|
||||
this.modalZapWalletPrompt.setAttribute(
|
||||
"aria-hidden",
|
||||
(!shouldShow).toString()
|
||||
);
|
||||
}
|
||||
|
||||
openZapDialog() {
|
||||
if (!this.modalZapDialog) {
|
||||
return;
|
||||
@@ -565,6 +591,9 @@ export class VideoModal {
|
||||
this.modalZapDialog.classList.remove("hidden");
|
||||
this.modalZapDialogOpen = true;
|
||||
this.modalZapDialog.setAttribute("aria-hidden", "false");
|
||||
if (this.modalZapBtn) {
|
||||
this.modalZapBtn.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
this.focusZapAmount();
|
||||
}
|
||||
|
||||
@@ -576,6 +605,9 @@ export class VideoModal {
|
||||
this.modalZapDialog.classList.add("hidden");
|
||||
this.modalZapDialog.setAttribute("aria-hidden", "true");
|
||||
this.modalZapDialogOpen = false;
|
||||
if (this.modalZapBtn) {
|
||||
this.modalZapBtn.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
if (!silent) {
|
||||
this.dispatch("zap:close", { video: this.activeVideo });
|
||||
}
|
||||
|
||||
+90
-42
@@ -29,18 +29,96 @@
|
||||
</div>
|
||||
<div class="flex flex-col items-end gap-3 self-start sm:self-end">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
id="zapButton"
|
||||
type="button"
|
||||
class="icon-button"
|
||||
aria-label="Send a zap"
|
||||
>
|
||||
<img
|
||||
src="assets/svg/lightning-bolt.svg"
|
||||
alt="Zap"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<div class="relative" data-channel-zap-wrapper>
|
||||
<button
|
||||
id="zapButton"
|
||||
type="button"
|
||||
class="icon-button"
|
||||
aria-label="Open zap dialog"
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded="false"
|
||||
aria-controls="zapControls"
|
||||
>
|
||||
<img
|
||||
src="assets/svg/lightning-bolt.svg"
|
||||
alt="Zap"
|
||||
class="icon-image"
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
id="zapControls"
|
||||
class="zap-popover hidden"
|
||||
role="dialog"
|
||||
aria-hidden="true"
|
||||
aria-label="Channel zap dialog"
|
||||
>
|
||||
<div
|
||||
class="zap-popover__content w-72 max-w-[calc(100vw-2rem)] rounded-lg bg-gray-900/95 p-4 shadow-lg backdrop-blur"
|
||||
>
|
||||
<div class="mb-3 flex items-center justify-between gap-4">
|
||||
<h3
|
||||
class="text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Send a zap
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
id="zapCloseBtn"
|
||||
class="text-gray-400 transition-colors hover:text-gray-200"
|
||||
aria-label="Close zap dialog"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
id="zapWalletPrompt"
|
||||
class="mb-3 hidden text-sm text-gray-200"
|
||||
aria-hidden="true"
|
||||
>
|
||||
Connect a wallet in
|
||||
<button
|
||||
type="button"
|
||||
id="zapWalletLink"
|
||||
class="font-semibold text-blue-300 underline decoration-dotted transition-colors hover:text-blue-200"
|
||||
>
|
||||
Wallet Connect settings
|
||||
</button>
|
||||
to send zaps.
|
||||
</p>
|
||||
<label
|
||||
for="zapAmountInput"
|
||||
id="zapAmountLabel"
|
||||
class="mb-2 block text-xs font-semibold uppercase tracking-wide text-gray-300"
|
||||
>
|
||||
Zap amount (sats)
|
||||
</label>
|
||||
<input
|
||||
id="zapAmountInput"
|
||||
type="number"
|
||||
min="1"
|
||||
step="1"
|
||||
inputmode="numeric"
|
||||
class="w-full rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Enter sats"
|
||||
aria-labelledby="zapAmountLabel"
|
||||
/>
|
||||
<p
|
||||
id="zapSplitSummary"
|
||||
class="mt-3 text-sm text-gray-300"
|
||||
aria-live="polite"
|
||||
>
|
||||
Enter an amount to view the split.
|
||||
</p>
|
||||
<p
|
||||
id="zapStatus"
|
||||
class="mt-2 text-xs text-gray-400"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
></p>
|
||||
<ul id="zapReceipts" class="mt-3 space-y-2 text-xs text-gray-300"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
id="channelShareBtn"
|
||||
type="button"
|
||||
@@ -108,36 +186,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="zapControls" class="hidden w-full max-w-xs sm:max-w-sm">
|
||||
<div class="w-full rounded-lg bg-gray-900 bg-opacity-70 p-4 shadow-lg backdrop-blur">
|
||||
<label for="zapAmountInput" class="mb-2 block text-xs font-semibold uppercase tracking-wide text-gray-300">
|
||||
Zap amount (sats)
|
||||
</label>
|
||||
<input
|
||||
id="zapAmountInput"
|
||||
type="number"
|
||||
min="1"
|
||||
step="1"
|
||||
inputmode="numeric"
|
||||
class="w-full rounded border border-gray-600 bg-gray-800 px-3 py-2 text-sm text-gray-100 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
||||
placeholder="Enter sats"
|
||||
/>
|
||||
<p
|
||||
id="zapSplitSummary"
|
||||
class="mt-3 text-sm text-gray-300"
|
||||
aria-live="polite"
|
||||
>
|
||||
Enter an amount to view the split.
|
||||
</p>
|
||||
<p
|
||||
id="zapStatus"
|
||||
class="mt-2 text-xs text-gray-400"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
></p>
|
||||
<ul id="zapReceipts" class="mt-3 space-y-2 text-xs text-gray-300"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user