App.svelte raw

   1  <script>
   2      import { onMount } from 'svelte';
   3      import Header from './components/Header.svelte';
   4      import LoginModal from './LoginModal.svelte';
   5      import Dashboard from './pages/Dashboard.svelte';
   6      import Config from './pages/Config.svelte';
   7      import Update from './pages/Update.svelte';
   8      import { isLoggedIn, userPubkey, userSigner, authMethod } from './stores.js';
   9  
  10      let currentPage = 'dashboard';
  11      let showLoginModal = false;
  12      let isDarkTheme = false;
  13  
  14      onMount(() => {
  15          // Check for stored auth
  16          const storedMethod = localStorage.getItem('launcher_auth_method');
  17          const storedPubkey = localStorage.getItem('launcher_pubkey');
  18  
  19          if (storedMethod === 'extension' && storedPubkey) {
  20              // Try to restore extension session
  21              if (window.nostr) {
  22                  window.nostr.getPublicKey().then(pk => {
  23                      if (pk === storedPubkey) {
  24                          $isLoggedIn = true;
  25                          $userPubkey = pk;
  26                          $userSigner = window.nostr;
  27                          $authMethod = 'extension';
  28                      }
  29                  }).catch(() => {
  30                      // Extension not available, clear stored auth
  31                      localStorage.removeItem('launcher_auth_method');
  32                      localStorage.removeItem('launcher_pubkey');
  33                  });
  34              }
  35          }
  36  
  37          // Check for dark theme preference
  38          isDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
  39      });
  40  
  41      function handleLogin(event) {
  42          const { method, pubkey, signer, privateKey } = event.detail;
  43  
  44          $isLoggedIn = true;
  45          $userPubkey = pubkey;
  46          $userSigner = signer;
  47          $authMethod = method;
  48  
  49          localStorage.setItem('launcher_auth_method', method);
  50          localStorage.setItem('launcher_pubkey', pubkey);
  51  
  52          if (method === 'nsec' && privateKey) {
  53              // Store encrypted key (handled by LoginModal)
  54          }
  55  
  56          showLoginModal = false;
  57      }
  58  
  59      function handleLogout() {
  60          $isLoggedIn = false;
  61          $userPubkey = '';
  62          $userSigner = null;
  63          $authMethod = '';
  64  
  65          localStorage.removeItem('launcher_auth_method');
  66          localStorage.removeItem('launcher_pubkey');
  67          localStorage.removeItem('launcher_privkey_encrypted');
  68      }
  69  
  70      function navigateTo(page) {
  71          currentPage = page;
  72      }
  73  </script>
  74  
  75  <main class:dark-theme={isDarkTheme}>
  76      <Header
  77          {currentPage}
  78          isLoggedIn={$isLoggedIn}
  79          userPubkey={$userPubkey}
  80          on:navigate={(e) => navigateTo(e.detail)}
  81          on:login={() => showLoginModal = true}
  82          on:logout={handleLogout}
  83      />
  84  
  85      <div class="content">
  86          {#if !$isLoggedIn}
  87              <div class="login-prompt">
  88                  <h2>ORLY Launcher Admin</h2>
  89                  <p>Please login to manage the relay services.</p>
  90                  <button class="login-btn" on:click={() => showLoginModal = true}>
  91                      Login with Nostr
  92                  </button>
  93              </div>
  94          {:else if currentPage === 'dashboard'}
  95              <Dashboard />
  96          {:else if currentPage === 'config'}
  97              <Config />
  98          {:else if currentPage === 'update'}
  99              <Update />
 100          {/if}
 101      </div>
 102  
 103      <LoginModal
 104          bind:showModal={showLoginModal}
 105          {isDarkTheme}
 106          on:login={handleLogin}
 107          on:close={() => showLoginModal = false}
 108      />
 109  </main>
 110  
 111  <style>
 112      :global(*) {
 113          box-sizing: border-box;
 114          margin: 0;
 115          padding: 0;
 116      }
 117  
 118      :global(body) {
 119          font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 120          background: var(--bg-color);
 121          color: var(--text-color);
 122          min-height: 100vh;
 123      }
 124  
 125      main {
 126          --bg-color: #f5f5f5;
 127          --card-bg: #ffffff;
 128          --text-color: #333333;
 129          --muted-color: #666666;
 130          --border-color: #e0e0e0;
 131          --primary: #00bcd4;
 132          --primary-hover: #00acc1;
 133          --success: #4caf50;
 134          --error: #f44336;
 135          --warning: #ff9800;
 136  
 137          min-height: 100vh;
 138          background: var(--bg-color);
 139      }
 140  
 141      main.dark-theme {
 142          --bg-color: #1a1a1a;
 143          --card-bg: #2d2d2d;
 144          --text-color: #e0e0e0;
 145          --muted-color: #999999;
 146          --border-color: #444444;
 147      }
 148  
 149      .content {
 150          max-width: 1200px;
 151          margin: 0 auto;
 152          padding: 20px;
 153      }
 154  
 155      .login-prompt {
 156          text-align: center;
 157          padding: 60px 20px;
 158      }
 159  
 160      .login-prompt h2 {
 161          font-size: 2rem;
 162          margin-bottom: 16px;
 163          color: var(--text-color);
 164      }
 165  
 166      .login-prompt p {
 167          color: var(--muted-color);
 168          margin-bottom: 24px;
 169      }
 170  
 171      .login-btn {
 172          padding: 12px 32px;
 173          font-size: 1rem;
 174          background: var(--primary);
 175          color: white;
 176          border: none;
 177          border-radius: 6px;
 178          cursor: pointer;
 179          transition: background 0.2s;
 180      }
 181  
 182      .login-btn:hover {
 183          background: var(--primary-hover);
 184      }
 185  </style>
 186