Release v1.14.0 — monetization launch (E5-E8) #237
@@ -21,7 +21,10 @@
|
|||||||
let wallet = $state<Wallet | null>(null);
|
let wallet = $state<Wallet | null>(null);
|
||||||
let catalog = $state<Catalog | null>(null);
|
let catalog = $state<Catalog | null>(null);
|
||||||
let loading = $state(true);
|
let loading = $state(true);
|
||||||
let busy = $state(false);
|
// The product whose purchase is in flight, or null. It both guards against a concurrent purchase
|
||||||
|
// (busy) and scopes the pressed/dimmed visual to the tapped button — not every buy button.
|
||||||
|
let busyId = $state<string | null>(null);
|
||||||
|
const busy = $derived(busyId !== null);
|
||||||
// The value awaiting a web-spend warning confirmation (a spend that would draw vk/tg chips).
|
// The value awaiting a web-spend warning confirmation (a spend that would draw vk/tg chips).
|
||||||
let warnProduct = $state<CatalogProduct | null>(null);
|
let warnProduct = $state<CatalogProduct | null>(null);
|
||||||
|
|
||||||
@@ -99,13 +102,13 @@
|
|||||||
async function doBuy(p: CatalogProduct) {
|
async function doBuy(p: CatalogProduct) {
|
||||||
warnProduct = null;
|
warnProduct = null;
|
||||||
if (busy) return;
|
if (busy) return;
|
||||||
busy = true;
|
busyId = p.productId;
|
||||||
try {
|
try {
|
||||||
wallet = await gateway.walletBuy(p.productId);
|
wallet = await gateway.walletBuy(p.productId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError(e);
|
handleError(e);
|
||||||
} finally {
|
} finally {
|
||||||
busy = false;
|
busyId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +117,7 @@
|
|||||||
// paying accepts the public offer (linked below the packs).
|
// paying accepts the public offer (linked below the packs).
|
||||||
async function onOrder(p: CatalogProduct) {
|
async function onOrder(p: CatalogProduct) {
|
||||||
if (busy) return;
|
if (busy) return;
|
||||||
busy = true;
|
busyId = p.productId;
|
||||||
try {
|
try {
|
||||||
const order = await gateway.walletOrder(p.productId);
|
const order = await gateway.walletOrder(p.productId);
|
||||||
if (context === 'vk') {
|
if (context === 'vk') {
|
||||||
@@ -134,7 +137,7 @@
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError(e);
|
handleError(e);
|
||||||
} finally {
|
} finally {
|
||||||
busy = false;
|
busyId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -172,7 +175,9 @@
|
|||||||
<div class="row product" data-testid="product" data-kind="value" data-pid={p.productId}>
|
<div class="row product" data-testid="product" data-kind="value" data-pid={p.productId}>
|
||||||
<span class="name">{p.title}</span>
|
<span class="name">{p.title}</span>
|
||||||
<span class="price">🪙 {p.chips}</span>
|
<span class="price">🪙 {p.chips}</span>
|
||||||
<button class="buy" data-testid="buy" disabled={busy} onclick={() => onBuy(p)}>{t('wallet.buy')}</button>
|
<button class="buy" class:working={busyId === p.productId} data-testid="buy" disabled={busy} onclick={() => onBuy(p)}
|
||||||
|
>{t('wallet.buy')}</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
@@ -186,6 +191,7 @@
|
|||||||
<button
|
<button
|
||||||
class="buy"
|
class="buy"
|
||||||
class:blocked={purchaseBlocked}
|
class:blocked={purchaseBlocked}
|
||||||
|
class:working={busyId === p.productId}
|
||||||
data-testid="buy-pack"
|
data-testid="buy-pack"
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
@@ -271,10 +277,12 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.buy:disabled {
|
.buy:disabled {
|
||||||
opacity: 0.5;
|
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
.buy.blocked {
|
/* The dimmed look is scoped: the tapped button while its purchase is in flight (working), or a
|
||||||
|
blocked pack on VK iOS — never every buy button at once when one purchase is busy. */
|
||||||
|
.buy.blocked,
|
||||||
|
.buy.working {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.ios-note {
|
.ios-note {
|
||||||
|
|||||||
Reference in New Issue
Block a user