commit 8f6f8e71857b7ff7f0a79a74332dffd8a21d119d
parent 687e8759e3e0181ddeb40b2b0162e2c846142a46
Author: Florian Dold <dold@taler.net>
Date: Mon, 7 Sep 2026 15:40:13 +0200
wallet page: support DD 103 action continuation
Show installation guidance and action-specific continuation controls when
the fragment contains a DD 103 wallet action. Resume through the HTTPS
wallet link and offer a smaller direct taler:// link, preserving encoded
payloads in both links.
Support all three fragment forms, update the controls on fragment changes,
and provide responsive layout and text direction for translated prompts.
Diffstat:
2 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/static/styles.css b/static/styles.css
@@ -88,6 +88,7 @@ ul nav {
}
.wallet-section-heading h2,
+.wallet-action-notice h2,
.wallet-demo h2,
.wallet-resources h2 {
font-size: clamp(1.6rem, 3vw, 2rem);
@@ -181,7 +182,8 @@ ul nav {
color: var(--wallet-blue-dark);
}
-#body_content .wallet-page a.wallet-button:focus-visible {
+#body_content .wallet-page a.wallet-button:focus-visible,
+.wallet-action-direct:focus-visible {
outline: 3px solid #f5a623;
outline-offset: 3px;
}
@@ -218,6 +220,7 @@ ul nav {
padding: 0.85rem 1rem;
}
+.wallet-action-notice,
.wallet-demo {
align-items: center;
background: var(--wallet-blue-light);
@@ -230,14 +233,39 @@ ul nav {
padding: 1.75rem 2rem;
}
+.wallet-action-notice {
+ margin-top: 2rem;
+}
+
+.wallet-action-notice[hidden] {
+ display: none;
+}
+
+.wallet-action-notice p,
.wallet-demo p {
margin-bottom: 0;
}
+.wallet-action-notice .wallet-button,
.wallet-demo .wallet-button {
flex: 0 0 auto;
}
+.wallet-action-options {
+ display: flex;
+ flex: 0 0 auto;
+ flex-direction: column;
+ gap: 0.25rem;
+ max-width: 100%;
+ text-align: center;
+}
+
+.wallet-action-direct {
+ font-size: 0.9rem;
+ min-height: 44px;
+ padding: 0.5rem;
+}
+
.wallet-resources {
margin: 3.5rem 0 1rem;
}
@@ -283,6 +311,7 @@ ul nav {
flex-direction: column;
}
+ .wallet-action-notice,
.wallet-demo {
align-items: flex-start;
flex-direction: column;
@@ -291,6 +320,11 @@ ul nav {
padding: 1.5rem;
}
+ .wallet-action-notice {
+ margin-top: 2rem;
+ }
+
+ .wallet-action-options,
.wallet-demo .wallet-button {
width: 100%;
}
diff --git a/template/wallet.html.j2 b/template/wallet.html.j2
@@ -18,6 +18,22 @@
</header>
<div class="container wallet-content">
+ <section id="wallet-action-notice" class="wallet-action-notice"
+ aria-labelledby="wallet-action-heading" dir="auto" hidden>
+ <div>
+ <h2 id="wallet-action-heading">{% trans %}Continue in your Taler wallet{% endtrans %}</h2>
+ <p>{% trans %}You opened a Taler wallet action link, but your wallet may not have opened. If you don’t have a wallet yet, install one below, then return here to continue.{% endtrans %}</p>
+ </div>
+ <div class="wallet-action-options">
+ <a id="wallet-action-link" class="wallet-button wallet-button-primary">
+ {% trans %}Continue in your wallet{% endtrans %}
+ </a>
+ <a id="wallet-action-direct-link" class="wallet-action-direct">
+ {% trans %}Open <bdi>taler://</bdi> link directly{% endtrans %}
+ </a>
+ </div>
+ </section>
+
<section class="wallet-section" aria-labelledby="mobile-wallets-heading">
<div class="wallet-section-heading">
<h2 id="mobile-wallets-heading">{% trans %}Mobile wallets{% endtrans %}</h2>
@@ -155,4 +171,72 @@
</section>
</div>
</main>
+<script>
+ /*
+ @licstart The following is the entire license notice for the
+ JavaScript code in this page.
+
+ Copyright (C) 2026 Taler Systems SA
+
+ The JavaScript code in this page is free software: you can
+ redistribute it and/or modify it under the terms of the GNU
+ General Public License (GNU GPL) as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option)
+ any later version. The code is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
+
+ As additional permission under GNU GPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ @licend The above is the entire license notice
+ for the JavaScript code in this page.
+ */
+ (() => {
+ const notice = document.getElementById("wallet-action-notice");
+ const link = document.getElementById("wallet-action-link");
+ const directLink = document.getElementById("wallet-action-direct-link");
+ const defaultLabel = {{ _("Continue in your wallet") | tojson }};
+ const labels = new Map([
+ ["pay", {{ _("Continue payment") | tojson }}],
+ ["pay-pull", {{ _("Continue payment") | tojson }}],
+ ["pay-template", {{ _("Continue payment") | tojson }}],
+ ["withdraw", {{ _("Continue withdrawal") | tojson }}],
+ ["withdraw-exchange", {{ _("Continue withdrawal") | tojson }}],
+ ["refund", {{ _("Continue refund") | tojson }}],
+ ["pay-push", {{ _("Receive money") | tojson }}],
+ ["restore", {{ _("Restore your wallet") | tojson }}],
+ ]);
+
+ function updateAction() {
+ notice.hidden = true;
+ link.removeAttribute("href");
+ directLink.removeAttribute("href");
+ link.textContent = defaultLabel;
+
+ const fragment = window.location.hash.slice(1);
+ if (/[\s\u0000-\u001f\u007f-\u009f]/.test(fragment)) {
+ return;
+ }
+
+ // DD 103 permits #taler://action/rest, #/action/rest and #action/rest.
+ // Keep the payload encoded and let the wallet validate its contents.
+ const match = /^(?:taler:\/\/|\/)?([a-z-]+)\/(.+)$/i.exec(fragment);
+ if (!match) {
+ return;
+ }
+
+ link.href = "https://wallet.taler.net/#" + fragment;
+ directLink.href = "taler://" + match[1] + "/" + match[2];
+ link.textContent = labels.get(match[1].toLowerCase()) || defaultLabel;
+ notice.hidden = false;
+ }
+
+ updateAction();
+ window.addEventListener("hashchange", updateAction);
+ })();
+</script>
{% endblock body_content %}