1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use fedimint_gateway_common::MnemonicResponse;
use maud::{Markup, html};
use crate::DynGatewayApi;
pub async fn render<E>(api: &DynGatewayApi<E>) -> Markup
where
E: std::fmt::Display,
{
let result = api.handle_mnemonic_msg().await;
match result {
Ok(MnemonicResponse { mnemonic, .. }) => {
html! {
div class="card h-100" {
div class="card-header dashboard-header d-flex justify-content-between align-items-center" {
span { "Gateway Secret Phrase" }
// Toggle button
button
id="mnemonic-toggle-btn"
class="btn btn-sm btn-secondary"
type="button"
onclick="toggleMnemonicVisibility()"
{
"Show"
}
}
div class="card-body" {
// Ordered list with redacted words
ol id="mnemonic-list"
style="column-count: 2; column-gap: 2rem; font-size: 1.1rem; padding-left: 1.4rem;"
{
@for word in &mnemonic {
li class="mnemonic-word redacted" data-word=(word) {
"••••••••"
}
}
}
}
}
script {
(maud::PreEscaped(r#"
function toggleMnemonicVisibility() {
const btn = document.getElementById("mnemonic-toggle-btn");
const redacted = document.querySelectorAll(".mnemonic-word");
const showing = btn.dataset.showing === "true";
redacted.forEach(el => {
if (showing) {
// Hide → show redaction
el.textContent = "••••••••";
} else {
// Show → reveal actual word
el.textContent = el.dataset.word;
}
});
btn.textContent = showing ? "Show" : "Hide";
btn.dataset.showing = (!showing).toString();
}
"#))
}
}
}
Err(e) => {
html! {
div class="card h-100 border-danger" {
div class="card-header dashboard-header bg-danger text-white" {
"Gateway Secret Phrase"
}
div class="card-body" {
div class="alert alert-danger mb-0" {
strong { "Failed to fetch mnemonic: " }
(e.to_string())
}
}
}
}
}
}
}