feat(profile): let guests manage their localStorage username
/profile previously required auth and returned a raw JSON 401 for guests. Now it renders a guest variant: edit guestUsername in localStorage, clear it to re-prompt on next visit, or sign in to claim a permanent username. Unifies the two username flows (authed DB display_name vs guest localStorage) under one page.
This commit is contained in:
parent
b2fb60d1b7
commit
f7862bc54a
2 changed files with 80 additions and 6 deletions
3
app.py
3
app.py
|
|
@ -884,9 +884,8 @@ def logout():
|
|||
|
||||
|
||||
@app.route("/profile")
|
||||
@auth.require_auth
|
||||
def profile_page():
|
||||
"""Profile settings page"""
|
||||
"""Profile settings page — works for both authenticated users and guests."""
|
||||
user = auth.get_current_user()
|
||||
return render_template("profile.html", user=user)
|
||||
|
||||
|
|
|
|||
|
|
@ -269,14 +269,19 @@
|
|||
<div class="header-actions">
|
||||
<a href="/" class="btn">🏠 Home</a>
|
||||
<a href="/browse" class="btn btn-secondary">📋 Browse Rooms</a>
|
||||
{% if user %}
|
||||
<button class="btn btn-secondary" onclick="logout()">🚪 Log Out</button>
|
||||
{% else %}
|
||||
<a href="/auth" class="btn btn-secondary">🔐 Sign In</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-container">
|
||||
<p class="subtitle">Manage your account preferences</p>
|
||||
|
||||
<!-- Username Section -->
|
||||
{% if user %}
|
||||
<!-- Authenticated: Change DB-backed Username -->
|
||||
<div class="section">
|
||||
<h2>Change Username</h2>
|
||||
<div class="current-value">
|
||||
|
|
@ -299,6 +304,36 @@
|
|||
<button type="submit" id="update-username-btn" disabled>Update Username</button>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- Guest: Change localStorage guest name -->
|
||||
<div class="section">
|
||||
<h2>Guest Name</h2>
|
||||
<p style="color: var(--text-secondary); font-size: 14px; margin-top: 0;">
|
||||
You're browsing as a guest. Your name is stored in your browser only.
|
||||
<a href="/auth" style="color: var(--button-primary);">Sign in</a> to claim a permanent username.
|
||||
</p>
|
||||
<div class="current-value">
|
||||
Current guest name: <strong id="current-guest-name">(none)</strong>
|
||||
</div>
|
||||
<div id="guest-message" class="message"></div>
|
||||
<form id="guest-username-form">
|
||||
<div class="form-group">
|
||||
<label for="new-guest-username">New Guest Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="new-guest-username"
|
||||
placeholder="Enter new guest name"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<button type="submit" id="save-guest-btn">Save Guest Name</button>
|
||||
</form>
|
||||
<button type="button" id="clear-guest-btn"
|
||||
style="background: #6c757d; margin-top: 10px;">
|
||||
🗑️ Clear Guest Name (re-prompt on next visit)
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Theme Section -->
|
||||
<div class="section">
|
||||
|
|
@ -317,9 +352,6 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
let checkTimeout;
|
||||
const currentUsername = "{{ user.display_name }}";
|
||||
|
||||
// Theme Management
|
||||
function setTheme(theme) {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
|
@ -336,6 +368,10 @@
|
|||
const savedTheme = localStorage.getItem('theme') || 'light';
|
||||
setTheme(savedTheme);
|
||||
|
||||
{% if user %}
|
||||
let checkTimeout;
|
||||
const currentUsername = "{{ user.display_name }}";
|
||||
|
||||
// Username availability check
|
||||
document.getElementById('new-username').addEventListener('input', function(e) {
|
||||
const username = e.target.value.trim();
|
||||
|
|
@ -462,6 +498,45 @@
|
|||
alert('Network error. Please try again.');
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
// Guest username management — mirrors chat.html's GUEST_USERNAME_KEY
|
||||
const GUEST_USERNAME_KEY = 'guestUsername';
|
||||
|
||||
function refreshGuestName() {
|
||||
const name = localStorage.getItem(GUEST_USERNAME_KEY);
|
||||
document.getElementById('current-guest-name').textContent = name || '(none — will prompt on next visit)';
|
||||
document.getElementById('new-guest-username').value = name || '';
|
||||
}
|
||||
refreshGuestName();
|
||||
|
||||
document.getElementById('guest-username-form').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const newName = document.getElementById('new-guest-username').value.trim();
|
||||
const messageDiv = document.getElementById('guest-message');
|
||||
|
||||
if (!newName) {
|
||||
messageDiv.textContent = 'Guest name cannot be empty.';
|
||||
messageDiv.className = 'message error show';
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem(GUEST_USERNAME_KEY, newName);
|
||||
refreshGuestName();
|
||||
messageDiv.textContent = 'Guest name saved! Refresh chat to use it.';
|
||||
messageDiv.className = 'message success show';
|
||||
});
|
||||
|
||||
document.getElementById('clear-guest-btn').addEventListener('click', function() {
|
||||
if (!confirm('Clear your guest name? You will be prompted for a new one next time you visit chat.')) {
|
||||
return;
|
||||
}
|
||||
localStorage.removeItem(GUEST_USERNAME_KEY);
|
||||
refreshGuestName();
|
||||
const messageDiv = document.getElementById('guest-message');
|
||||
messageDiv.textContent = 'Guest name cleared.';
|
||||
messageDiv.className = 'message success show';
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue