diff --git a/api/button.html b/api/button.html new file mode 100644 index 0000000..d68664b --- /dev/null +++ b/api/button.html @@ -0,0 +1,134 @@ + + + + + + + Embedded NOSTR_LOGIN_LITE + + + + +
+
Login
+
+ + + + + + + + \ No newline at end of file diff --git a/api/index.html b/api/index.html index 353144c..9d93f24 100644 --- a/api/index.html +++ b/api/index.html @@ -243,6 +243,53 @@ background-color: var(--secondary-color); } + .user-info-container { + display: flex; + align-items: flex-start; + gap: 20px; + } + + .user-details { + flex: 1; + } + + .login-logout-btn { + width: auto; + min-width: 120px; + padding: 12px 16px; + background: var(--secondary-color); + color: var(--primary-color); + border: var(--border-width) solid var(--primary-color); + border-radius: var(--border-radius); + font-family: var(--font-family); + font-size: 14px; + font-weight: bold; + cursor: pointer; + transition: all 0.2s ease; + margin: 0; + flex-shrink: 0; + } + + .login-logout-btn:hover { + border-color: var(--accent-color); + } + + .login-logout-btn:active { + background: var(--accent-color); + color: var(--secondary-color); + } + + .login-logout-btn.logout-state { + background: var(--accent-color); + color: var(--secondary-color); + border-color: var(--accent-color); + } + + .login-logout-btn.logout-state:hover { + background: var(--primary-color); + border-color: var(--primary-color); + } + .user-pubkey { font-family: var(--font-family); font-size: 12px; @@ -378,7 +425,19 @@ transition: all 0.2s ease; } - @media (max-width: 768px) { + /* Two-Column Layout */ + .two-column-layout { + display: flex; + gap: var(--border-width); + margin-bottom: 20px; + } + + .column { + flex: 1; + min-width: 300px; /* Ensure columns are at least 300px wide */ + } + + @media (max-width: 700px) { body { padding: 10px; } @@ -394,6 +453,12 @@ h2 { font-size: 14px; } + + /* Stack columns vertically on screens smaller than 700px */ + .two-column-layout { + flex-direction: column; + gap: 20px; + } } @@ -401,70 +466,77 @@

C-RELAY ADMIN API

- -
-
-

NOSTR AUTHENTICATION

-

Please login with your Nostr identity to access the admin interface.

- + +
+ +
+ + +
+ +
+
+

NOSTR AUTHENTICATION

+

Please login with your Nostr identity to access the admin interface.

+ +
+
+ + +
+
+

RELAY CONNECTION

+ +
+ + +
+ +
+ + + If the relay hasn't been configured yet, enter the relay pubkey shown during startup +
+ +
+ + + +
+ +
NOT CONNECTED
+ + + +
@@ -675,10 +747,10 @@ // DOM elements const loginSection = document.getElementById('login-section'); const mainInterface = document.getElementById('main-interface'); - const userName = document.getElementById('user-name'); - const userPubkeyDisplay = document.getElementById('user-pubkey'); - const userAbout = document.getElementById('user-about'); - const logoutBtn = document.getElementById('logout-btn'); + const persistentUserName = document.getElementById('persistent-user-name'); + const persistentUserPubkey = document.getElementById('persistent-user-pubkey'); + const persistentUserAbout = document.getElementById('persistent-user-about'); + const persistentUserDetails = document.getElementById('persistent-user-details'); const relayUrl = document.getElementById('relay-url'); const relayStatus = document.getElementById('relay-status'); const fetchConfigBtn = document.getElementById('fetch-config-btn'); @@ -1106,6 +1178,7 @@ // Show main interface showMainInterface(); loadUserProfile(); + updateLoginLogoutButton(); // Note: Configuration fetching now requires explicit relay connection // User must connect to relay manually after login @@ -1131,25 +1204,25 @@ readonly: true, connect: true, remote: true, - otp: true + otp: false }, floatingTab: { - enabled: true, - hPosition: 1, // 0.0-1.0 or '95%' from left - vPosition: 0, // 0.0-1.0 or '50%' from top - appearance: { - style: 'square', // 'pill', 'square', 'circle', 'minimal' - // icon: '[LOGIN]', // Now uses text-based icons like [LOGIN], [KEY], [NET] - text: 'Login' - }, - behavior: { - hideWhenAuthenticated: false, - showUserInfo: true, - autoSlide: true - }, - animation: { - slideDirection: 'auto' // 'auto', 'left', 'right', 'up', 'down' - } + enabled: false, + // hPosition: 1, // 0.0-1.0 or '95%' from left + // vPosition: 0, // 0.0-1.0 or '50%' from top + // appearance: { + // style: 'square', // 'pill', 'square', 'circle', 'minimal' + // // icon: '[LOGIN]', // Now uses text-based icons like [LOGIN], [KEY], [NET] + // text: 'Login' + // }, + // behavior: { + // hideWhenAuthenticated: false, + // showUserInfo: true, + // autoSlide: true + // }, + // animation: { + // slideDirection: 'auto' // 'auto', 'left', 'right', 'up', 'down' + // } } }); @@ -1167,6 +1240,7 @@ // Listen for authentication events window.addEventListener('nlMethodSelected', handleAuthEvent); + window.addEventListener('nlLogout', handleLogoutEvent); } catch (error) { console.log('Failed to initialize Nostr login: ' + error.message); @@ -1185,6 +1259,7 @@ showMainInterface(); loadUserProfile(); + updateLoginLogoutButton(); // Note: Configuration fetching now requires explicit relay connection // User must connect to relay manually after login @@ -1195,11 +1270,47 @@ } } + // Handle logout events + function handleLogoutEvent() { + console.log('Logout event received'); + + userPubkey = null; + isLoggedIn = false; + currentConfig = null; + + // Clean up relay connection + disconnectFromRelay(); + + // Reset UI + mainInterface.classList.add('hidden'); + loginSection.classList.remove('hidden'); + updateConfigStatus(false); + relayStatus.textContent = 'READY TO FETCH'; + relayStatus.className = 'status disconnected'; + updateLoginLogoutButton(); + hideAuthRulesSection(); + + console.log('Logout event handled successfully'); + } + + // Disconnect from relay and clean up connections + function disconnectFromRelay() { + if (relayPool) { + console.log('Cleaning up relay pool connection...'); + const url = relayUrl.value.trim(); + if (url) { + relayPool.close([url]); + } + relayPool = null; + subscriptionId = null; + } + } + // Show main interface after login function showMainInterface() { loginSection.classList.add('hidden'); mainInterface.classList.remove('hidden'); - userPubkeyDisplay.textContent = userPubkey; + updateLoginLogoutButton(); } // Load user profile using nostr-tools pool @@ -1207,8 +1318,8 @@ if (!userPubkey) return; console.log('Loading user profile...'); - userName.textContent = 'Loading...'; - userAbout.textContent = 'Loading...'; + persistentUserName.textContent = 'Loading...'; + persistentUserAbout.textContent = 'Loading...'; try { // Create a SimplePool instance for profile loading @@ -1223,11 +1334,16 @@ }); if (events.length > 0) { + console.log('Profile event found:', events[0]); const profile = JSON.parse(events[0].content); + console.log('Parsed profile:', profile); displayProfile(profile); } else { - userName.textContent = 'Anonymous User'; - userAbout.textContent = 'No profile found'; + console.log('No profile events found for pubkey:', userPubkey); + persistentUserName.textContent = 'Anonymous User'; + persistentUserAbout.textContent = 'No profile found'; + // Still show the pubkey since we have it + persistentUserPubkey.textContent = userPubkey; } // Close the profile pool @@ -1235,8 +1351,10 @@ } catch (error) { console.log('Profile loading failed: ' + error.message); - userName.textContent = 'Error loading profile'; - userAbout.textContent = error.message; + persistentUserName.textContent = 'Error loading profile'; + persistentUserAbout.textContent = error.message; + // Still show the pubkey since we have it + persistentUserPubkey.textContent = userPubkey; } } @@ -1245,10 +1363,12 @@ const name = profile.name || profile.display_name || profile.displayName || 'Anonymous User'; const about = profile.about || 'No description provided'; - userName.textContent = name; - userAbout.textContent = about; + // Update persistent user details + persistentUserName.textContent = name; + persistentUserPubkey.textContent = userPubkey; + persistentUserAbout.textContent = about; - console.log(`Profile loaded for: ${name}`); + console.log(`Profile loaded for: ${name} with pubkey: ${userPubkey}`); } // Logout function @@ -1257,7 +1377,7 @@ try { // Clean up relay connection disconnectFromRelay(); - + // Clean up configuration pool if (relayPool) { console.log('Closing configuration pool...'); @@ -1275,12 +1395,13 @@ isLoggedIn = false; currentConfig = null; - // Reset UI + // Reset UI - keep persistent auth container visible mainInterface.classList.add('hidden'); loginSection.classList.remove('hidden'); updateConfigStatus(false); relayStatus.textContent = 'READY TO FETCH'; relayStatus.className = 'status disconnected'; + updateLoginLogoutButton(); console.log('Logged out successfully'); @@ -2224,8 +2345,39 @@ + // Login/Logout button functionality + function updateLoginLogoutButton() { + const loginLogoutBtn = document.getElementById('login-logout-btn'); + if (!loginLogoutBtn) return; + + if (isLoggedIn) { + loginLogoutBtn.textContent = 'LOGOUT'; + loginLogoutBtn.className = 'login-logout-btn logout-state'; + loginLogoutBtn.onclick = logout; + // Show user details when logged in + if (persistentUserDetails) { + persistentUserDetails.style.display = 'block'; + } + } else { + loginLogoutBtn.textContent = 'ADMIN NOSTR LOGIN'; + loginLogoutBtn.className = 'login-logout-btn'; + loginLogoutBtn.onclick = () => { + if (window.NOSTR_LOGIN_LITE && window.NOSTR_LOGIN_LITE.launch) { + window.NOSTR_LOGIN_LITE.launch('login'); + } else { + console.log('NOSTR_LOGIN_LITE not available'); + } + }; + // Hide user details when logged out + if (persistentUserDetails) { + persistentUserDetails.style.display = 'none'; + } + } + } + // Event handlers - logoutBtn.addEventListener('click', logout); + // Initialize login/logout button + updateLoginLogoutButton(); fetchConfigBtn.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation(); @@ -2336,9 +2488,18 @@ function hideAuthRulesSection() { if (authRulesSection) { authRulesSection.style.display = 'none'; - authRulesTableContainer.style.display = 'none'; - authRuleFormContainer.style.display = 'none'; - authRulesStatusDisplay.style.display = 'none'; + + // Add null checks for all elements + if (authRulesTableContainer) { + authRulesTableContainer.style.display = 'none'; + } + if (authRuleFormContainer) { + authRuleFormContainer.style.display = 'none'; + } + if (authRulesStatusDisplay) { + authRulesStatusDisplay.style.display = 'none'; + } + currentAuthRules = []; editingAuthRule = null; log('Auth rules section hidden', 'INFO'); @@ -3715,6 +3876,10 @@ // Initialize the app document.addEventListener('DOMContentLoaded', () => { console.log('C-Relay Admin API interface loaded'); + + // Initialize login/logout button state + updateLoginLogoutButton(); + setTimeout(() => { initializeApp(); // Enhance SimplePool for testing after initialization