Spaces:
Running
Running
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | |
| <title>Notion Remote - Secure Container</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary: #6366f1; | |
| --primary-dark: #4f46e5; | |
| --secondary: #10b981; | |
| --danger: #ef4444; | |
| --warning: #f59e0b; | |
| --bg: #ffffff; | |
| --bg-secondary: #f9fafb; | |
| --bg-tertiary: #f3f4f6; | |
| --text: #111827; | |
| --text-secondary: #6b7280; | |
| --border: #e5e7eb; | |
| --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | |
| --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| --radius: 12px; | |
| --radius-sm: 8px; | |
| --transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| --bg: #111827; | |
| --bg-secondary: #1f2937; | |
| --bg-tertiary: #374151; | |
| --text: #f9fafb; | |
| --text-secondary: #9ca3af; | |
| --border: #4b5563; | |
| --shadow: 0 1px 3px rgba(0, 0, 0, 0.3); | |
| --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5); | |
| } | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; | |
| background: var(--bg); | |
| color: var(--text); | |
| overflow-x: hidden; | |
| overscroll-behavior: none; | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| } | |
| .app-container { | |
| min-height: 100vh; | |
| display: grid; | |
| grid-template-rows: auto 1fr auto; | |
| grid-template-areas: "header" "main" "nav"; | |
| max-width: 100%; | |
| margin: 0 auto; | |
| position: relative; | |
| } | |
| .header { | |
| grid-area: header; | |
| padding: 1rem; | |
| background: var(--bg-secondary); | |
| border-bottom: 1px solid var(--border); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| backdrop-filter: blur(10px); | |
| -webkit-backdrop-filter: blur(10px); | |
| } | |
| .header-title { | |
| font-size: clamp(1.2rem, 4vw, 1.5rem); | |
| font-weight: 700; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .header-title a { | |
| color: var(--text); | |
| text-decoration: none; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .security-indicator { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| padding: 0.5rem 1rem; | |
| background: var(--bg-tertiary); | |
| border-radius: var(--radius-sm); | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| } | |
| .security-indicator.active { | |
| background: rgba(16, 185, 129, 0.1); | |
| color: var(--secondary); | |
| } | |
| .main-content { | |
| grid-area: main; | |
| padding: 1rem; | |
| overflow-y: auto; | |
| padding-bottom: 5rem; | |
| } | |
| .bottom-nav { | |
| grid-area: nav; | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| background: var(--bg-secondary); | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| justify-content: space-around; | |
| padding: 0.5rem 0; | |
| z-index: 200; | |
| backdrop-filter: blur(10px); | |
| -webkit-backdrop-filter: blur(10px); | |
| } | |
| .nav-item { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.5rem 1rem; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| border-radius: var(--radius-sm); | |
| min-width: 4rem; | |
| } | |
| .nav-item:hover { | |
| background: var(--bg-tertiary); | |
| } | |
| .nav-item.active { | |
| color: var(--primary); | |
| } | |
| .nav-item .material-icons { | |
| font-size: 1.5rem; | |
| } | |
| .nav-item span { | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| } | |
| .tab-content { | |
| display: none; | |
| animation: fadeIn 0.3s ease-in-out; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .card { | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 1.5rem; | |
| margin-bottom: 1rem; | |
| transition: var(--transition); | |
| box-shadow: var(--shadow); | |
| } | |
| .card:hover { | |
| box-shadow: var(--shadow-lg); | |
| transform: translateY(-2px); | |
| } | |
| .card-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| } | |
| .card-title { | |
| font-size: 1.125rem; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .connection-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
| gap: 1rem; | |
| margin-top: 1rem; | |
| } | |
| .connection-card { | |
| background: var(--bg-tertiary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 1rem; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .connection-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 4px; | |
| background: var(--primary); | |
| transform: scaleX(0); | |
| transition: transform 0.3s ease; | |
| } | |
| .connection-card.connected::before { | |
| transform: scaleX(1); | |
| } | |
| .connection-card:hover { | |
| background: var(--bg); | |
| border-color: var(--primary); | |
| } | |
| .connection-status { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| margin-top: 0.5rem; | |
| } | |
| .status-connected { | |
| background: rgba(16, 185, 129, 0.1); | |
| color: var(--secondary); | |
| } | |
| .status-disconnected { | |
| background: rgba(239, 68, 68, 0.1); | |
| color: var(--danger); | |
| } | |
| .btn { | |
| padding: 0.75rem 1.5rem; | |
| border: none; | |
| border-radius: var(--radius-sm); | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| text-decoration: none; | |
| color: var(--text); | |
| } | |
| .btn-primary { | |
| background: var(--primary); | |
| color: white; | |
| } | |
| .btn-primary:hover { | |
| background: var(--primary-dark); | |
| transform: translateY(-1px); | |
| } | |
| .btn-secondary { | |
| background: var(--bg-tertiary); | |
| border: 1px solid var(--border); | |
| } | |
| .btn-secondary:hover { | |
| background: var(--border); | |
| } | |
| .btn-danger { | |
| background: var(--danger); | |
| color: white; | |
| } | |
| .security-container { | |
| background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); | |
| color: white; | |
| padding: 2rem; | |
| border-radius: var(--radius); | |
| margin-bottom: 1rem; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .security-container::before { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| right: -50%; | |
| width: 200%; | |
| height: 200%; | |
| background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); | |
| animation: pulse 4s ease-in-out infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); opacity: 0.5; } | |
| 50% { transform: scale(1.1); opacity: 0.3; } | |
| } | |
| .security-lock { | |
| font-size: 3rem; | |
| margin-bottom: 1rem; | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .security-status { | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .password-input { | |
| width: 100%; | |
| padding: 0.75rem 1rem; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| background: var(--bg); | |
| color: var(--text); | |
| font-size: 1rem; | |
| margin-bottom: 1rem; | |
| transition: var(--transition); | |
| } | |
| .password-input:focus { | |
| outline: none; | |
| border-color: var(--primary); | |
| box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); | |
| } | |
| .modal { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(0, 0, 0, 0.8); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| z-index: 1000; | |
| opacity: 0; | |
| visibility: hidden; | |
| transition: var(--transition); | |
| backdrop-filter: blur(5px); | |
| -webkit-backdrop-filter: blur(5px); | |
| } | |
| .modal.active { | |
| opacity: 1; | |
| visibility: visible; | |
| } | |
| .modal-content { | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 2rem; | |
| max-width: 400px; | |
| width: 90%; | |
| transform: scale(0.9); | |
| transition: transform 0.3s ease; | |
| } | |
| .modal.active .modal-content { | |
| transform: scale(1); | |
| } | |
| .connection-log { | |
| background: var(--bg-tertiary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 1rem; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| font-family: 'Courier New', monospace; | |
| font-size: 0.875rem; | |
| color: var(--text-secondary); | |
| } | |
| .log-entry { | |
| padding: 0.5rem 0; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .log-entry:last-child { | |
| border-bottom: none; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); | |
| gap: 1rem; | |
| margin-top: 1rem; | |
| } | |
| .stat-item { | |
| text-align: center; | |
| padding: 1rem; | |
| background: var(--bg-tertiary); | |
| border-radius: var(--radius-sm); | |
| } | |
| .stat-value { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| color: var(--primary); | |
| } | |
| .stat-label { | |
| font-size: 0.875rem; | |
| color: var(--text-secondary); | |
| margin-top: 0.25rem; | |
| } | |
| .toggle-switch { | |
| position: relative; | |
| width: 50px; | |
| height: 26px; | |
| background: var(--bg-tertiary); | |
| border-radius: 9999px; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .toggle-switch.active { | |
| background: var(--primary); | |
| } | |
| .toggle-switch::after { | |
| content: ''; | |
| position: absolute; | |
| top: 3px; | |
| left: 3px; | |
| width: 20px; | |
| height: 20px; | |
| background: white; | |
| border-radius: 50%; | |
| transition: var(--transition); | |
| } | |
| .toggle-switch.active::after { | |
| transform: translateX(24px); | |
| } | |
| .android-app-bar { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 24px; | |
| background: var(--bg); | |
| z-index: 999; | |
| } | |
| @media (max-width: 768px) { | |
| .android-app-bar { | |
| display: block; | |
| } | |
| .header { | |
| padding-top: 1.5rem; | |
| } | |
| .connection-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .modal-content { | |
| padding: 1.5rem; | |
| } | |
| } | |
| .ripple { | |
| position: absolute; | |
| border-radius: 50%; | |
| background: rgba(255, 255, 255, 0.3); | |
| transform: scale(0); | |
| animation: ripple-animation 0.6s ease-out; | |
| } | |
| @keyframes ripple-animation { | |
| to { | |
| transform: scale(4); | |
| opacity: 0; | |
| } | |
| } | |
| .section-title { | |
| font-size: 1.25rem; | |
| font-weight: 700; | |
| margin-bottom: 1rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .feature-list { | |
| list-style: none; | |
| padding: 0; | |
| } | |
| .feature-list li { | |
| padding: 0.75rem 0; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .feature-list li:last-child { | |
| border-bottom: none; | |
| } | |
| .feature-list .material-icons { | |
| color: var(--primary); | |
| } | |
| .quick-actions { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); | |
| gap: 0.75rem; | |
| margin-top: 1rem; | |
| } | |
| .quick-action-btn { | |
| aspect-ratio: 1; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| background: var(--bg-tertiary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| cursor: pointer; | |
| transition: var(--transition); | |
| padding: 1rem; | |
| text-align: center; | |
| } | |
| .quick-action-btn:hover { | |
| background: var(--primary); | |
| color: white; | |
| border-color: var(--primary); | |
| transform: scale(1.05); | |
| } | |
| .quick-action-btn .material-icons { | |
| font-size: 2rem; | |
| } | |
| .quick-action-btn span { | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="android-app-bar"></div> | |
| <div class="app-container"> | |
| <header class="header"> | |
| <div class="header-title"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank"> | |
| <span class="material-icons">verified</span> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| <div class="security-indicator" id="securityIndicator"> | |
| <span class="material-icons">shield</span> | |
| <span id="securityStatus">Gesichert</span> | |
| </div> | |
| </header> | |
| <main class="main-content"> | |
| <!-- Dashboard Tab --> | |
| <div class="tab-content active" id="dashboard"> | |
| <div class="security-container"> | |
| <div class="security-lock"> | |
| <span class="material-icons" style="font-size: 3rem;">lock</span> | |
| </div> | |
| <h2>Sicherer Container</h2> | |
| <p>Ihre Verbindungen sind Ende-zu-Ende verschlüsselt und in einem sicheren Container isoliert.</p> | |
| <div class="stats-grid"> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="activeConnections">0</div> | |
| <div class="stat-label">Aktive VPNs</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="secureApps">0</div> | |
| <div class="stat-label">Gesicherte Apps</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value">256-bit</div> | |
| <div class="stat-label">Verschlüsselung</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">speed</span> | |
| Schnellzugriff | |
| </h3> | |
| <div class="quick-actions"> | |
| <button class="quick-action-btn" onclick="quickAction('vpn')"> | |
| <span class="material-icons">vpn_lock</span> | |
| <span>VPN</span> | |
| </button> | |
| <button class="quick-action-btn" onclick="quickAction('ssh')"> | |
| <span class="material-icons">terminal</span> | |
| <span>SSH</span> | |
| </button> | |
| <button class="quick-action-btn" onclick="quickAction('firewall')"> | |
| <span class="material-icons">security</span> | |
| <span>Firewall</span> | |
| </button> | |
| <button class="quick-action-btn" onclick="quickAction('scan')"> | |
| <span class="material-icons">network_check</span> | |
| <span>Scan</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <h3 class="card-title"> | |
| <span class="material-icons">list_alt</span> | |
| Verbindungsprotokoll | |
| </h3> | |
| <button class="btn btn-secondary" onclick="clearLog()"> | |
| <span class="material-icons">clear_all</span> | |
| Löschen | |
| </button> | |
| </div> | |
| <div class="connection-log" id="connectionLog"> | |
| <div class="log-entry">System initialisiert...</div> | |
| <div class="log-entry">Sicherer Container aktiviert</div> | |
| <div class="log-entry">Verschlüsselung: AES-256 aktiv</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Connections Tab --> | |
| <div class="tab-content" id="connections"> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <h3 class="card-title"> | |
| <span class="material-icons">device_hub</span> | |
| Verbindungsmanager | |
| </h3> | |
| <button class="btn btn-primary" onclick="addConnection()"> | |
| <span class="material-icons">add</span> | |
| Neue Verbindung | |
| </button> | |
| </div> | |
| <div class="connection-grid" id="connectionGrid"> | |
| <!-- VPN Cards --> | |
| <div class="connection-card" data-type="vpn" data-id="vpn1"> | |
| <div style="display: flex; justify-content: space-between; align-items: center;"> | |
| <h4>VPN Frankfurt</h4> | |
| <div class="toggle-switch" onclick="toggleConnection(this, 'vpn1')"></div> | |
| </div> | |
| <p style="color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.5rem;"> | |
| 185.42.12.88 • 0ms Latenz | |
| </p> | |
| <div class="connection-status status-disconnected" id="vpn1-status"> | |
| <span class="material-icons" style="font-size: 1rem;">link_off</span> | |
| Getrennt | |
| </div> | |
| </div> | |
| <div class="connection-card" data-type="vpn" data-id="vpn2"> | |
| <div style="display: flex; justify-content: space-between; align-items: center;"> | |
| <h4>VPN Amsterdam</h4> | |
| <div class="toggle-switch" onclick="toggleConnection(this, 'vpn2')"></div> | |
| </div> | |
| <p style="color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.5rem;"> | |
| 203.15.77.34 • 12ms Latenz | |
| </p> | |
| <div class="connection-status status-disconnected" id="vpn2-status"> | |
| <span class="material-icons" style="font-size: 1rem;">link_off</span> | |
| Getrennt | |
| </div> | |
| </div> | |
| <!-- SSH Cards --> | |
| <div class="connection-card" data-type="ssh" data-id="ssh1"> | |
| <div style="display: flex; justify-content: space-between; align-items: center;"> | |
| <h4>SSH Server Prod</h4> | |
| <div class="toggle-switch" onclick="toggleConnection(this, 'ssh1')"></div> | |
| </div> | |
| <p style="color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.5rem;"> | |
| prod.example.com • Port 22 | |
| </p> | |
| <div class="connection-status status-disconnected" id="ssh1-status"> | |
| <span class="material-icons" style="font-size: 1rem;">link_off</span> | |
| Getrennt | |
| </div> | |
| </div> | |
| <div class="connection-card" data-type="ssh" data-id="ssh2"> | |
| <div style="display: flex; justify-content: space-between; align-items: center;"> | |
| <h4>SSH Dev Container</h4> | |
| <div class="toggle-switch" onclick="toggleConnection(this, 'ssh2')"></div> | |
| </div> | |
| <p style="color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.5rem;"> | |
| dev.local • Port 2222 | |
| </p> | |
| <div class="connection-status status-disconnected" id="ssh2-status"> | |
| <span class="material-icons" style="font-size: 1rem;">link_off</span> | |
| Getrennt | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">insights</span> | |
| Netzwerk-Scanner | |
| </h3> | |
| <button class="btn btn-primary" onclick="scanNetwork()"> | |
| <span class="material-icons">search</span> | |
| Netzwerk scannen | |
| </button> | |
| <div id="scanResults" style="margin-top: 1rem;"></div> | |
| </div> | |
| </div> | |
| <!-- Security Tab --> | |
| <div class="tab-content" id="security"> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">security</span> | |
| Container-Sicherheit | |
| </h3> | |
| <ul class="feature-list"> | |
| <li> | |
| <span class="material-icons">check_circle</span> | |
| <span>Ende-zu-Ende Verschlüsselung aktiv</span> | |
| </li> | |
| <li> | |
| <span class="material-icons">check_circle</span> | |
| <span>Zero-Knowledge-Architektur</span> | |
| </li> | |
| <li> | |
| <span class="material-icons">check_circle</span> | |
| <span>Biometrische Authentifizierung</span> | |
| </li> | |
| <li> | |
| <span class="material-icons">check_circle</span> | |
| <span>Automatische Sperre nach Inaktivität</span> | |
| </li> | |
| </ul> | |
| </div> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <h3 class="card-title"> | |
| <span class="material-icons">lock</span> | |
| Master-Passwort | |
| </h3> | |
| </div> | |
| <p style="margin-bottom: 1rem; color: var(--text-secondary);"> | |
| Ändern Sie Ihr Master-Passwort für den sicheren Container | |
| </p> | |
| <input type="password" class="password-input" placeholder="Neues Passwort" id="newPassword"> | |
| <input type="password" class="password-input" placeholder="Passwort bestätigen" id="confirmPassword"> | |
| <button class="btn btn-primary" onclick="changePassword()"> | |
| <span class="material-icons">save</span> | |
| Passwort aktualisieren | |
| </button> | |
| </div> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">fingerprint</span> | |
| Biometrische Daten | |
| </h3> | |
| <button class="btn btn-primary" onclick="setupBiometrics()"> | |
| <span class="material-icons">fingerprint</span> | |
| Fingerabdruck einrichten | |
| </button> | |
| <p style="margin-top: 1rem; color: var(--text-secondary); font-size: 0.875rem;"> | |
| Verwenden Sie Face ID oder Touch ID für schnellen Zugriff | |
| </p> | |
| </div> | |
| </div> | |
| <!-- Settings Tab --> | |
| <div class="tab-content" id="settings"> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">tune</span> | |
| Allgemeine Einstellungen | |
| </h3> | |
| <div style="display: flex; flex-direction: column; gap: 1rem;"> | |
| <label style="display: flex; justify-content: space-between; align-items: center;"> | |
| <span>Automatischer Start</span> | |
| <div class="toggle-switch active" onclick="toggleSetting(this)"></div> | |
| </label> | |
| <label style="display: flex; justify-content: space-between; align-items: center;"> | |
| <span>Dunkles Design</span> | |
| <div class="toggle-switch" onclick="toggleDarkMode(this)"></div> | |
| </label> | |
| <label style="display: flex; justify-content: space-between; align-items: center;"> | |
| <span>Benachrichtigungen</span> | |
| <div class="toggle-switch active" onclick="toggleSetting(this)"></div> | |
| </label> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">storage</span> | |
| Daten & Speicher | |
| </h3> | |
| <button class="btn btn-secondary" onclick="exportData()"> | |
| <span class="material-icons">download</span> | |
| Daten exportieren | |
| </button> | |
| <button class="btn btn-danger" onclick="clearData()" style="margin-left: 0.5rem;"> | |
| <span class="material-icons">delete</span> | |
| Alle Daten löschen | |
| </button> | |
| </div> | |
| <div class="card"> | |
| <h3 class="section-title"> | |
| <span class="material-icons">info</span> | |
| Über die App | |
| </h3> | |
| <p style="color: var(--text-secondary); margin-bottom: 1rem;"> | |
| Notion Remote Secure Container v2.1.0 | |
| </p> | |
| <p style="color: var(--text-secondary); font-size: 0.875rem;"> | |
| Eine sichere Plattform für Verbindungsmanagement mit militärischer Verschlüsselung. | |
| </p> | |
| </div> | |
| </div> | |
| </main> | |
| <nav class="bottom-nav"> | |
| <div class="nav-item active" onclick="switchTab('dashboard', this)"> | |
| <span class="material-icons">dashboard</span> | |
| <span>Dashboard</span> | |
| </div> | |
| <div class="nav-item" onclick="switchTab('connections', this)"> | |
| <span class="material-icons">device_hub</span> | |
| <span>Verbindungen</span> | |
| </div> | |
| <div class="nav-item" onclick="switchTab('security', this)"> | |
| <span class="material-icons">security</span> | |
| <span>Sicherheit</span> | |
| </div> | |
| <div class="nav-item" onclick="switchTab('settings', this)"> | |
| <span class="material-icons">settings</span> | |
| <span>Einstellungen</span> | |
| </div> | |
| </nav> | |
| </div> | |
| <!-- Auth Modal --> | |
| <div class="modal" id="authModal"> | |
| <div class="modal-content"> | |
| <h3 style="margin-bottom: 1rem;">Authentifizierung erforderlich</h3> | |
| <input type="password" class="password-input" placeholder="Master-Passwort" id="authPassword"> | |
| <button class="btn btn-primary" onclick="authenticate()" style="width: 100%;"> | |
| <span class="material-icons">login</span> | |
| Anmelden | |
| </button> | |
| <p style="margin-top: 1rem; text-align: center; color: var(--text-secondary); font-size: 0.875rem;"> | |
| Oder verwenden Sie <a href="#" onclick="biometricAuth()" style="color: var(--primary);">Biometrie</a> | |
| </p> | |
| </div> | |
| </div> | |
| <script> | |
| // App State | |
| const appState = { | |
| connections: new Set(), | |
| secureApps: new Set(['notion', 'slack', 'github']), | |
| isSecured: true, | |
| masterPassword: localStorage.getItem('masterPassword') || 'default123', | |
| logs: [] | |
| }; | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', () => { | |
| loadState(); | |
| updateStats(); | |
| addRippleEffect(); | |
| checkSecurityStatus(); | |
| }); | |
| // Tab Switching | |
| function switchTab(tabName, navItem) { | |
| // Hide all tabs | |
| document.querySelectorAll('.tab-content').forEach(tab => { | |
| tab.classList.remove('active'); | |
| }); | |
| // Show selected tab | |
| document.getElementById(tabName).classList.add('active'); | |
| // Update nav | |
| document.querySelectorAll('.nav-item').forEach(item => { | |
| item.classList.remove('active'); | |
| }); | |
| navItem.classList.add('active'); | |
| // Add authentication for security tab | |
| if (tabName === 'security') { | |
| showAuthModal(); | |
| } | |
| } | |
| // Quick Actions | |
| function quickAction(action) { | |
| addLog(`Schnellzugriff: ${action.toUpperCase()} aktiviert`); | |
| switch(action) { | |
| case 'vpn': | |
| const vpnCard = document.querySelector('[data-id="vpn1"] .toggle-switch'); | |
| if (!vpnCard.classList.contains('active')) { | |
| toggleConnection(vpnCard, 'vpn1'); | |
| } | |
| break; | |
| case 'ssh': | |
| const sshCard = document.querySelector('[data-id="ssh1"] .toggle-switch'); | |
| if (!sshCard.classList.contains('active')) { | |
| toggleConnection(sshCard, 'ssh1'); | |
| } | |
| break; | |
| case 'firewall': | |
| addLog('Firewall-Regeln aktualisiert'); | |
| break; | |
| case 'scan': | |
| scanNetwork(); | |
| break; | |
| } | |
| // Haptic feedback simulation | |
| if (navigator.vibrate) { | |
| navigator.vibrate(50); | |
| } | |
| } | |
| // Connection Management | |
| function toggleConnection(toggle, connectionId) { | |
| const isActive = toggle.classList.contains('active'); | |
| const statusEl = document.getElementById(`${connectionId}-status`); | |
| const card = document.querySelector(`[data-id="${connectionId}"]`); | |
| if (isActive) { | |
| toggle.classList.remove('active'); | |
| card.classList.remove('connected'); | |
| statusEl.innerHTML = '<span class="material-icons" style="font-size: 1rem;">link_off</span> Getrennt'; | |
| statusEl.className = 'connection-status status-disconnected'; | |
| appState.connections.delete(connectionId); | |
| addLog(`${connectionId} getrennt`); | |
| } else { | |
| toggle.classList.add('active'); | |
| card.classList.add('connected'); | |
| statusEl.innerHTML = '<span class="material-icons" style="font-size: 1rem;">link</span> Verbunden'; | |
| statusEl.className = 'connection-status status-connected'; | |
| appState.connections.add(connectionId); | |
| addLog(`${connectionId} verbunden`); | |
| // Simulate data transfer | |
| simulateDataTransfer(connectionId); | |
| } | |
| updateStats(); | |
| } | |
| // Simulate data transfer | |
| function simulateDataTransfer(connectionId) { | |
| let transferred = 0; | |
| const interval = setInterval(() => { | |
| transferred += Math.floor(Math.random() * 100); | |
| addLog(`${connectionId}: ${transferred}MB übertragen`, 'info'); | |
| if (transferred > 500) { | |
| clearInterval(interval); | |
| } | |
| }, 2000); | |
| } | |
| // Network Scanner | |
| function scanNetwork() { | |
| const resultsEl = document.getElementById('scanResults'); | |
| resultsEl.innerHTML = '<div style="display: flex; align-items: center; gap: 0.5rem; color: var(--text-secondary);"><span class="material-icons">hourglass_empty</span> Scanning...</div>'; | |
| setTimeout(() => { | |
| const devices = [ | |
| { ip: '192.168.1.1', name: 'Router', status: 'open' }, | |
| { ip: '192.168.1.42', name: 'Laptop', status: 'filtered' }, | |
| { ip: '192.168.1.88', name: 'Smartphone', status: 'open' } | |
| ]; | |
| resultsEl.innerHTML = devices.map(device => ` | |
| <div style="padding: 0.75rem; background: var(--bg-tertiary); border-radius: var(--radius-sm); margin-bottom: 0.5rem; display: flex; justify-content: space-between; align-items: center;"> | |
| <div> | |
| <strong>${device.name}</strong><br> | |
| <small style="color: var(--text-secondary);">${device.ip}</small> | |
| </div> | |
| <span style="color: ${device.status === 'open' ? 'var(--secondary)' : 'var(--warning)'};"> | |
| ${device.status === 'open' ? 'Sicher' : 'Gefiltert'} | |
| </span> | |
| </div> | |
| `).join(''); | |
| addLog('Netzwerk-Scan abgeschlossen'); | |
| }, 2000); | |
| } | |
| // Security Functions | |
| function showAuthModal() { | |
| document.getElementById('authModal').classList.add('active'); | |
| } | |
| function authenticate() { | |
| const password = document.getElementById('authPassword').value; | |
| if (password === appState.masterPassword) { | |
| document.getElementById('authModal').classList.remove('active'); | |
| document.getElementById('authPassword').value = ''; | |
| addLog('Authentifizierung erfolgreich'); | |
| } else { | |
| alert('Falsches Passwort!'); | |
| addLog('Authentifizierung fehlgeschlagen', 'error'); | |
| } | |
| } | |
| function biometricAuth() { | |
| addLog('Biometrische Authentifizierung gestartet'); | |
| // Simulate biometric auth | |
| setTimeout(() => { | |
| const success = Math.random() > 0.3; | |
| if (success) { | |
| document.getElementById('authModal').classList.remove('active'); | |
| addLog('Biometrische Authentifizierung erfolgreich'); | |
| } else { | |
| alert('Biometrische Authentifizierung fehlgeschlagen'); | |
| addLog('Biometrische Authentifizierung fehlgeschlagen', 'error'); | |
| } | |
| }, 1500); | |
| } | |
| function changePassword() { | |
| const newPass = document.getElementById('newPassword').value; | |
| const confirmPass = document.getElementById('confirmPassword').value; | |
| if (newPass && newPass === confirmPass) { | |
| appState.masterPassword = newPass; | |
| localStorage.setItem('masterPassword', newPass); | |
| document.getElementById('newPassword').value = ''; | |
| document.getElementById('confirmPassword').value = ''; | |
| addLog('Passwort erfolgreich geändert'); | |
| alert('Passwort wurde aktualisiert!'); | |
| } else { | |
| alert('Passwörter stimmen nicht überein!'); | |
| } | |
| } | |
| function setupBiometrics() { | |
| addLog('Einrichtung der biometrischen Authentifizierung gestartet'); | |
| if (window.PublicKeyCredential) { | |
| alert('Biometrische Authentifizierung wird eingerichtet...'); | |
| addLog('Biometrische Authentifizierung eingerichtet'); | |
| } else { | |
| alert('Biometrische Authentifizierung wird nicht unterstützt'); | |
| addLog('Biometrische Authentifizierung nicht verfügbar', 'warning'); | |
| } | |
| } | |
| // Settings | |
| function toggleSetting(toggle) { | |
| toggle.classList.toggle('active'); | |
| addLog('Einstellung geändert'); | |
| } | |
| function toggleDarkMode(toggle) { | |
| toggle.classList.toggle('active'); | |
| addLog('Dark Mode umgeschaltet'); | |
| // In a real app, this would toggle dark mode | |
| } | |
| function exportData() { | |
| const data = JSON.stringify(appState, null, 2); | |
| const blob = new Blob([data], { type: 'application/json' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'notion-remote-backup.json'; | |
| a.click(); | |
| addLog('Daten exportiert'); | |
| } | |
| function clearData() { | |
| if (confirm('Möchten Sie wirklich alle Daten löschen?')) { | |
| localStorage.clear(); | |
| appState.connections.clear(); | |
| appState.logs = []; | |
| updateStats(); | |
| addLog('Alle Daten gelöscht', 'warning'); | |
| location.reload(); | |
| } | |
| } | |
| // Logging | |
| function addLog(message, type = 'info') { | |
| const timestamp = new Date().toLocaleTimeString(); | |
| const logEntry = `[${timestamp}] ${message}`; | |
| appState.logs.push({ message, type, timestamp }); | |
| const logEl = document.getElementById('connectionLog'); | |
| const newEntry = document.createElement('div'); | |
| newEntry.className = 'log-entry'; | |
| newEntry.textContent = logEntry; | |
| logEl.appendChild(newEntry); | |
| logEl.scrollTop = logEl.scrollHeight; | |
| // Keep only last 50 logs | |
| if (appState.logs.length > 50) { | |
| appState.logs.shift(); | |
| logEl.removeChild(logEl.firstChild); | |
| } | |
| } | |
| function clearLog() { | |
| document.getElementById('connectionLog').inner |