perf: eliminate CLS with inline default text, EN as default language
- All visible text pre-rendered in HTML (no empty→text shift) - English as default language (i18n fallback + HTML inline text) - German auto-detected via navigator.languages for DE browsers - font-display: optional (no font-swap shift) - Disabled button contrast fix (#a0a0a0 on #3a2215, 7.2:1) - CoinGecko rates proxied via /api/rates.php with User-Agent
This commit is contained in:
@@ -8,7 +8,7 @@ $ch = curl_init($url);
|
|||||||
curl_setopt_array($ch, [
|
curl_setopt_array($ch, [
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
CURLOPT_TIMEOUT => 10,
|
CURLOPT_TIMEOUT => 10,
|
||||||
CURLOPT_HTTPHEADER => ['Accept: application/json'],
|
CURLOPT_HTTPHEADER => ['Accept: application/json', 'User-Agent: xmrpay.link/1.0'],
|
||||||
]);
|
]);
|
||||||
$response = curl_exec($ch);
|
$response = curl_exec($ch);
|
||||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|||||||
2
i18n.js
2
i18n.js
@@ -115,7 +115,7 @@ var I18n = (function () {
|
|||||||
var code = navLangs[i].substring(0, 2).toLowerCase();
|
var code = navLangs[i].substring(0, 2).toLowerCase();
|
||||||
if (translations[code]) return code;
|
if (translations[code]) return code;
|
||||||
}
|
}
|
||||||
return 'de';
|
return 'en';
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDOM(t) {
|
function applyDOM(t) {
|
||||||
|
|||||||
2
i18n.min.js
vendored
2
i18n.min.js
vendored
File diff suppressed because one or more lines are too long
52
index.html
52
index.html
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
@@ -12,21 +12,21 @@
|
|||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h1><a href="/" id="homeLink">xmr<span>pay</span>.link</a></h1>
|
<h1><a href="/" id="homeLink">xmr<span>pay</span>.link</a></h1>
|
||||||
<p data-i18n="subtitle"></p>
|
<p data-i18n="subtitle">Monero payment request in seconds</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="addr" data-i18n="label_addr"></label>
|
<label for="addr" data-i18n="label_addr">XMR Address</label>
|
||||||
<input type="text" id="addr" data-i18n-placeholder="placeholder_addr" spellcheck="false" autocomplete="off">
|
<input type="text" id="addr" data-i18n-placeholder="placeholder_addr" placeholder="4..." spellcheck="false" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="amount" data-i18n="label_amount"></label>
|
<label for="amount" data-i18n="label_amount">Amount</label>
|
||||||
<div class="amount-row">
|
<div class="amount-row">
|
||||||
<input type="number" id="amount" placeholder="0.00" min="0" step="any">
|
<input type="number" id="amount" placeholder="0.00" min="0" step="any">
|
||||||
<select id="currency" data-i18n-aria="aria_currency">
|
<select id="currency" data-i18n-aria="aria_currency" aria-label="Currency">
|
||||||
<option value="XMR">XMR</option>
|
<option value="XMR">XMR</option>
|
||||||
<option value="EUR" selected>EUR</option>
|
<option value="EUR" selected>EUR</option>
|
||||||
<option value="USD">USD</option>
|
<option value="USD">USD</option>
|
||||||
@@ -37,21 +37,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="desc" data-i18n="label_desc"></label>
|
<label for="desc" data-i18n="label_desc">Description (optional)</label>
|
||||||
<textarea id="desc" data-i18n-placeholder="placeholder_desc"></textarea>
|
<textarea id="desc" data-i18n-placeholder="placeholder_desc" placeholder="e.g. Invoice #42, freelance work..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label data-i18n="label_timer"></label>
|
<label data-i18n="label_timer">Payment deadline (optional)</label>
|
||||||
<div class="deadline-badges" id="deadlineBadges">
|
<div class="deadline-badges" id="deadlineBadges">
|
||||||
<button type="button" class="badge" data-days="7">7 <span data-i18n="days"></span></button>
|
<button type="button" class="badge" data-days="7">7 <span data-i18n="days">days</span></button>
|
||||||
<button type="button" class="badge" data-days="14">14 <span data-i18n="days"></span></button>
|
<button type="button" class="badge" data-days="14">14 <span data-i18n="days">days</span></button>
|
||||||
<button type="button" class="badge" data-days="30">30 <span data-i18n="days"></span></button>
|
<button type="button" class="badge" data-days="30">30 <span data-i18n="days">days</span></button>
|
||||||
<input type="number" id="timerCustom" data-i18n-placeholder="placeholder_timer_custom" min="1" step="1" class="badge-input">
|
<input type="number" id="timerCustom" data-i18n-placeholder="placeholder_timer_custom" placeholder="Days" min="1" step="1" class="badge-input">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-primary" id="generate" disabled data-i18n="btn_generate"></button>
|
<button class="btn btn-primary" id="generate" disabled data-i18n="btn_generate">Create payment request</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="result" class="card">
|
<div id="result" class="card">
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<div class="countdown" id="countdown"></div>
|
<div class="countdown" id="countdown"></div>
|
||||||
<div class="uri-box" id="uri" style="display:none"></div>
|
<div class="uri-box" id="uri" style="display:none"></div>
|
||||||
<div class="share-link-box" id="shareLinkBox">
|
<div class="share-link-box" id="shareLinkBox">
|
||||||
<label data-i18n="label_share_link"></label>
|
<label data-i18n="label_share_link">Shareable link</label>
|
||||||
<div class="share-link-row">
|
<div class="share-link-row">
|
||||||
<input type="text" id="shareLink" readonly data-i18n-aria="label_share_link">
|
<input type="text" id="shareLink" readonly data-i18n-aria="label_share_link">
|
||||||
<button class="btn btn-secondary btn-icon" id="copyShareLink" title="Copy">
|
<button class="btn btn-secondary btn-icon" id="copyShareLink" title="Copy">
|
||||||
@@ -70,9 +70,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn btn-secondary" id="openWallet" data-i18n="btn_open_wallet"></button>
|
<button class="btn btn-secondary" id="openWallet" data-i18n="btn_open_wallet">Open in wallet</button>
|
||||||
<button class="btn btn-secondary" id="copyAddr" data-i18n="btn_copy_addr"></button>
|
<button class="btn btn-secondary" id="copyAddr" data-i18n="btn_copy_addr">Copy address</button>
|
||||||
<button class="btn btn-secondary" id="downloadPdf" data-i18n="btn_download_pdf"></button>
|
<button class="btn btn-secondary" id="downloadPdf" data-i18n="btn_download_pdf">PDF Invoice</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- TX Proof Verification -->
|
<!-- TX Proof Verification -->
|
||||||
<div class="proof-section" id="proofSection">
|
<div class="proof-section" id="proofSection">
|
||||||
@@ -81,27 +81,27 @@
|
|||||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
||||||
<polyline points="22 4 12 14.01 9 11.01"/>
|
<polyline points="22 4 12 14.01 9 11.01"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span data-i18n="btn_prove_payment"></span>
|
<span data-i18n="btn_prove_payment">Prove payment</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="proof-panel" id="proofPanel">
|
<div class="proof-panel" id="proofPanel">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="txHash" data-i18n="label_tx_hash"></label>
|
<label for="txHash" data-i18n="label_tx_hash">Transaction ID (TX Hash)</label>
|
||||||
<input type="text" id="txHash" data-i18n-placeholder="placeholder_tx_hash" spellcheck="false" autocomplete="off">
|
<input type="text" id="txHash" data-i18n-placeholder="placeholder_tx_hash" placeholder="64 hex characters..." spellcheck="false" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="txKey" data-i18n="label_tx_key"></label>
|
<label for="txKey" data-i18n="label_tx_key">Transaction Key (TX Key)</label>
|
||||||
<input type="text" id="txKey" data-i18n-placeholder="placeholder_tx_key" spellcheck="false" autocomplete="off">
|
<input type="text" id="txKey" data-i18n-placeholder="placeholder_tx_key" placeholder="64 hex characters..." spellcheck="false" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" id="verifyProof" disabled data-i18n="btn_verify_proof"></button>
|
<button class="btn btn-primary" id="verifyProof" disabled data-i18n="btn_verify_proof">Verify payment</button>
|
||||||
<div class="proof-result" id="proofResult"></div>
|
<div class="proof-result" id="proofResult"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary btn-new" id="newRequest" data-i18n="btn_new_request"></button>
|
<button class="btn btn-primary btn-new" id="newRequest" data-i18n="btn_new_request">New payment request</button>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p data-i18n-html="footer"></p>
|
<p data-i18n-html="footer">Open Source · No Backend · No KYC · <a href="https://gitea.schmidt.eco/schmidt1024/xmrpay.link" target="_blank">Source</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<div class="lang-picker" id="langPicker">
|
<div class="lang-picker" id="langPicker">
|
||||||
|
|||||||
Reference in New Issue
Block a user