diff options
Diffstat (limited to 'packages')
4 files changed, 37 insertions, 16 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js b/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js index 2164eae..09c4acf 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/auth-page.js @@ -344,6 +344,23 @@ function WelcomePitch() { `; } +// The sign-in page's dark gradient backdrop and frosted card, without the +// pitch beside it — so Register (and its verify/recovery/done steps) sits on +// the same background and reads in the same dark theme as Login. A lone +// `.welcome-side` is centred by `.welcome`'s `justify-content`. +function AuthShell({ children }) { + return html` + <div class="page-center"> + <div class="welcome-backdrop" aria-hidden="true"></div> + <div class="welcome"> + <div class="welcome-side"> + ${children} + </div> + </div> + </div> + `; +} + export function RegisterPage() { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); @@ -358,7 +375,9 @@ export function RegisterPage() { const [recoveryMnemonic, setRecoveryMnemonic] = useState(''); const [recoverySaved, setRecoverySaved] = useState(false); const [recoveryCopied, setRecoveryCopied] = useState(false); - const [emailRecovery, setEmailRecovery] = useState(true); + // Off by default: mailing the recovery key is opt-in — the key is shown on + // screen to save, and sending a copy is the user's own choice to make. + const [emailRecovery, setEmailRecovery] = useState(false); const captcha = useCaptcha(); const onSubmit = async (e) => { @@ -457,7 +476,7 @@ export function RegisterPage() { if (phase === 'done') { return html` - <div class="page-center"> + <${AuthShell}> <div class="card login-card"> <h2>${t('register.verified_title')}</h2> <p style="text-align:center; margin-bottom:16px; color:var(--text-secondary)"> @@ -467,7 +486,7 @@ export function RegisterPage() { <p style="text-align:center; margin-bottom:16px">${t('invite.after_register')}</p>`} <a href="#/login" style="display:block; text-align:center">${t('register.go_login')}</a> </div> - </div> + </${AuthShell}> `; } @@ -480,7 +499,7 @@ export function RegisterPage() { } catch { /* clipboard blocked — the text is on screen to copy by hand */ } }; return html` - <div class="page-center"> + <${AuthShell}> <div class="card login-card"> <h2>${t('register.recovery_title')}</h2> <p style="margin-bottom:12px; color:var(--text-secondary)"> @@ -509,13 +528,13 @@ export function RegisterPage() { ${t('register.recovery_continue')} </button> </div> - </div> + </${AuthShell}> `; } if (phase === 'verify') { return html` - <div class="page-center"> + <${AuthShell}> <div class="card login-card"> <h2>${t('register.success_title')}</h2> <p style="text-align:center; margin-bottom:16px; color:var(--text-secondary)"> @@ -538,12 +557,12 @@ export function RegisterPage() { ${t('register.resend_sent')}</span>`} </div> </div> - </div> + </${AuthShell}> `; } return html` - <div class="page-center"> + <${AuthShell}> <div class="card login-card"> <h2>${t('register.title')}</h2> <form onSubmit=${onSubmit}> @@ -585,7 +604,7 @@ export function RegisterPage() { ${t('register.has_account')} <a href="#/login">${t('register.login_link')}</a> </div> </div> - </div> + </${AuthShell}> `; } diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js index a510e63..fba8a0e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js @@ -417,7 +417,8 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, // Whether the hub mails the invitation. Checked, the hub is handed the code // to write it into the mail — so it is the inviter's choice, remembered per // account (docs/MESHBAY_DESIGN.md §3.4). Unchecked, the hub never sees it. - const [inviteByEmail, setInviteByEmail] = useState(true); + // Off by default: mailing the code is opt-in, not something to do unasked. + const [inviteByEmail, setInviteByEmail] = useState(false); const [error, setError] = useState(''); // Node loopback state (Electron-only) @@ -811,7 +812,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, useEffect(() => { hubFetch('/v1/users/me/preferences', { token }) - .then(prefs => setInviteByEmail(prefs[INVITE_EMAIL_PREF] !== 'false')) + .then(prefs => setInviteByEmail(prefs[INVITE_EMAIL_PREF] === 'true')) .catch(() => {}); }, [token]); @@ -1059,7 +1060,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, ${inviting ? '...' : t('members.invite_btn')} </button> </div> - <label style="display:flex; gap:8px; align-items:flex-start; margin:6px 0 0; + <label style="display:flex; gap:8px; align-items:center; margin:6px 0 0; font-size:0.88em; color:var(--text-secondary)"> <input type="checkbox" checked=${inviteByEmail} onChange=${e => toggleInviteByEmail(e.target.checked)} /> @@ -1105,7 +1106,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, ${linking ? '...' : t('members.link_btn')} </button> </div> - <label style="display:flex; gap:8px; align-items:flex-start; margin:6px 0 0; + <label style="display:flex; gap:8px; align-items:center; margin:6px 0 0; font-size:0.88em; color:var(--text-secondary)"> <input type="checkbox" checked=${inviteByEmail} onChange=${e => toggleInviteByEmail(e.target.checked)} /> diff --git a/packages/meshbay-hub/src/meshbay_hub/static/style.css b/packages/meshbay-hub/src/meshbay_hub/static/style.css index 37775d8..8433b1a 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/style.css +++ b/packages/meshbay-hub/src/meshbay_hub/static/style.css @@ -682,7 +682,7 @@ a:hover { text-decoration: underline; } overflow: hidden; pointer-events: none; background: linear-gradient(155deg, - #86a3c4 0%, #6a819b 18%, #3d4d61 42%, #232b36 66%, #0f1113 100%); + #809cbc 0%, #6a819b 18%, #3d4d61 42%, #232b36 66%, #0f1113 100%); } /* The night-blue pool. */ .welcome-backdrop::before { diff --git a/packages/meshbay-hub/tests/test_invite_email_choice.py b/packages/meshbay-hub/tests/test_invite_email_choice.py index e04c31f..de9410d 100644 --- a/packages/meshbay-hub/tests/test_invite_email_choice.py +++ b/packages/meshbay-hub/tests/test_invite_email_choice.py @@ -3,8 +3,9 @@ Whether the hub mails an invitation is the inviter's choice, and it is remembere Mailing it hands the hub the code — `invite-notify` writes it into the message — which is exactly what §3.4 says the code is for not doing. So the Members tab -offers it as a box, checked by default, and an unchecked box must mean the hub -is never asked. The choice lives in an account preference; a key the hub does +offers it as a box, unchecked by default (mailing the code is opt-in), and an +unchecked box must mean the hub is never asked. The choice lives in an account +preference, remembered once set; a key the hub does not list is refused, and the box would snap back on every click with nothing on screen to say why. """ |