54216aa133
Add persistent site history storage and plumbing between the renderer settings UI and the native app. The app now loads/saves site_history.txt in the user data directory (max 200 entries, http/https-only, stored one URL per line) and records visited sites on navigation. Settings pages receive the history via injected JavaScript when the settings page finishes loading, and a "clear-site-history" message from the settings UI clears the on-disk history and updates the renderer. Other changes: allow settings-related process messages from content frames in the CEF client, introduce OnContentLoadFinished to trigger history injection, expose electronAPI.send/sendToHost (and reuse the native postMessage handler) in the V8 context, and remove the BigPicture in-app history UI/refresh/clear handlers (history is now managed by the native app). Also cleaned up includes and added helper utilities for JSON escaping, lowercasing, and file path handling. The initial tab restore logic was simplified to always create an initial tab (home or initial_url) and persist the session.
498 lines
22 KiB
HTML
498 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Nebula - Big Picture Mode</title>
|
|
<link rel="icon" href="../assets/images/branding/Nebula-Icon.svg" type="image/svg+xml">
|
|
<link rel="stylesheet" href="../css/bigpicture.css">
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/remixicon@3/fonts/remixicon.css" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
<!-- Audio feedback for navigation -->
|
|
<audio id="navSound" preload="auto">
|
|
<source src="data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQ==" type="audio/wav">
|
|
</audio>
|
|
<audio id="selectSound" preload="auto">
|
|
<source src="data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQ==" type="audio/wav">
|
|
</audio>
|
|
|
|
<!-- Main container with ambient background -->
|
|
<div class="bp-container">
|
|
<!-- Animated background -->
|
|
<div class="bp-background">
|
|
<div class="bg-gradient"></div>
|
|
<div class="bg-particles"></div>
|
|
<div class="bg-glow"></div>
|
|
</div>
|
|
|
|
<!-- Top header bar -->
|
|
<header class="bp-header">
|
|
<div class="header-left">
|
|
<img src="../assets/images/branding/Nebula-Icon.svg" alt="Nebula" class="bp-logo">
|
|
<span class="bp-title">Nebula</span>
|
|
</div>
|
|
<div class="header-center">
|
|
<div class="clock-widget">
|
|
<span id="bp-time" class="time">--:--</span>
|
|
<span id="bp-date" class="date">---</span>
|
|
</div>
|
|
</div>
|
|
<div class="header-right">
|
|
<div class="status-icons">
|
|
<span id="bp-wifi" class="status-icon" title="Connected">
|
|
<span class="material-symbols-outlined">wifi</span>
|
|
</span>
|
|
<span id="bp-battery" class="status-icon" title="Battery">
|
|
<span class="material-symbols-outlined">battery_full</span>
|
|
</span>
|
|
</div>
|
|
<button id="exitBigPicture" class="bp-exit-btn" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">close</span>
|
|
<span class="btn-label">Exit</span>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main navigation area -->
|
|
<main class="bp-main">
|
|
<!-- Left sidebar navigation -->
|
|
<nav class="bp-sidebar">
|
|
<div class="nav-items">
|
|
<button class="nav-item active" data-section="home" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">home</span>
|
|
<span class="nav-label">Home</span>
|
|
</button>
|
|
<button class="nav-item" data-section="browse" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">language</span>
|
|
<span class="nav-label">Browse</span>
|
|
</button>
|
|
<button class="nav-item" data-section="bookmarks" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">bookmarks</span>
|
|
<span class="nav-label">Bookmarks</span>
|
|
</button>
|
|
<button class="nav-item" data-section="downloads" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">download</span>
|
|
<span class="nav-label">Downloads</span>
|
|
</button>
|
|
|
|
</div>
|
|
<div class="nav-footer">
|
|
<button class="nav-item" data-section="settings" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">settings</span>
|
|
<span class="nav-label">Settings</span>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Content area -->
|
|
<div class="bp-content">
|
|
<!-- Webview container for browsing -->
|
|
<div id="webview-container" class="webview-container hidden"></div>
|
|
|
|
<!-- Home section -->
|
|
<section id="section-home" class="bp-section active">
|
|
<div class="section-header">
|
|
<h1 class="section-title">
|
|
<span id="greeting-text">Welcome back</span>
|
|
</h1>
|
|
<p class="section-subtitle">What would you like to browse today?</p>
|
|
</div>
|
|
|
|
<!-- Search card -->
|
|
<div class="search-card" data-focusable tabindex="0">
|
|
<div class="search-icon">
|
|
<span class="material-symbols-outlined">search</span>
|
|
</div>
|
|
<input type="text" id="bp-search" class="search-input" placeholder="Search the web or enter URL..." autocomplete="off">
|
|
<div class="search-hint">
|
|
<span class="key-hint">A</span> Search
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick access grid -->
|
|
<div class="quick-access">
|
|
<h2 class="subsection-title">Quick Access</h2>
|
|
<div class="tile-grid" id="quickAccessGrid">
|
|
<!-- Tiles will be populated dynamically -->
|
|
</div>
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<!-- Browse section (for webview) -->
|
|
<section id="section-browse" class="bp-section">
|
|
<!-- Webview container is outside sections -->
|
|
</section>
|
|
|
|
<!-- Bookmarks section -->
|
|
<section id="section-bookmarks" class="bp-section">
|
|
<div class="section-header">
|
|
<h1 class="section-title">Bookmarks</h1>
|
|
<p class="section-subtitle">Your saved websites</p>
|
|
</div>
|
|
<div class="section-actions">
|
|
<button class="action-btn" id="addBookmarkBtn" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">bookmark_add</span>
|
|
<span>Add Bookmark</span>
|
|
</button>
|
|
<button class="action-btn" id="addCurrentBookmarkBtn" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">bookmark</span>
|
|
<span>Add Current Page</span>
|
|
</button>
|
|
</div>
|
|
<div class="tile-grid large" id="bookmarksGrid">
|
|
<!-- Bookmarks will be populated dynamically -->
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Downloads section -->
|
|
<section id="section-downloads" class="bp-section">
|
|
<div class="section-header">
|
|
<h1 class="section-title">Downloads</h1>
|
|
<p class="section-subtitle">Your downloaded files</p>
|
|
</div>
|
|
<div class="list-container" id="downloadsList">
|
|
<div class="empty-state">
|
|
<span class="material-symbols-outlined">folder_open</span>
|
|
<p>No recent downloads</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- NeBot AI section -->
|
|
<section id="section-nebot" class="bp-section">
|
|
<div class="section-header">
|
|
<h1 class="section-title">NeBot AI Assistant</h1>
|
|
<p class="section-subtitle">Your AI-powered browsing companion</p>
|
|
</div>
|
|
<div class="nebot-launch">
|
|
<div class="nebot-card" data-focusable tabindex="0" id="launchNebot">
|
|
<div class="nebot-icon">
|
|
<span class="material-symbols-outlined">smart_toy</span>
|
|
</div>
|
|
<div class="nebot-info">
|
|
<h3>Start Conversation</h3>
|
|
<p>Ask questions, get summaries, and more</p>
|
|
</div>
|
|
<div class="nebot-action">
|
|
<span class="key-hint">A</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Settings section -->
|
|
<section id="section-settings" class="bp-section">
|
|
<div class="section-header">
|
|
<h1 class="section-title">Settings</h1>
|
|
<p class="section-subtitle">Configure your browser</p>
|
|
</div>
|
|
|
|
<!-- Settings categories navigation -->
|
|
<div class="settings-tabs">
|
|
<button class="settings-tab active" data-settings-tab="themes" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">palette</span>
|
|
<span>Themes</span>
|
|
</button>
|
|
<button class="settings-tab" data-settings-tab="display" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">display_settings</span>
|
|
<span>Display</span>
|
|
</button>
|
|
<button class="settings-tab" data-settings-tab="privacy" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">shield</span>
|
|
<span>Privacy</span>
|
|
</button>
|
|
<button class="settings-tab" data-settings-tab="about" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">info</span>
|
|
<span>About</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Settings panels -->
|
|
<div class="settings-panels">
|
|
<!-- Themes Panel -->
|
|
<div class="settings-panel active" id="settings-panel-themes">
|
|
<h2 class="settings-panel-title">Theme Presets</h2>
|
|
<div class="theme-grid" id="bp-theme-grid">
|
|
<button class="theme-card" data-theme="default" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #121418, #1B1035);"></div>
|
|
<span class="theme-name">Default</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="ocean" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #1a365d, #2c5282);"></div>
|
|
<span class="theme-name">Ocean</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="forest" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #1a202c, #2d3748);"></div>
|
|
<span class="theme-name">Forest</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="sunset" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #744210, #c05621);"></div>
|
|
<span class="theme-name">Sunset</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="cyberpunk" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #0a0a0a, #2a0a3a);"></div>
|
|
<span class="theme-name">Cyberpunk</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="midnight-rose" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #1c1820, #3d3046);"></div>
|
|
<span class="theme-name">Midnight Rose</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="arctic-ice" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #f0f8ff, #d1e7ff);"></div>
|
|
<span class="theme-name">Arctic Ice</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="cherry-blossom" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #fff5f8, #ffd4db);"></div>
|
|
<span class="theme-name">Cherry Blossom</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="cosmic-purple" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #0f0524, #2d1b69);"></div>
|
|
<span class="theme-name">Cosmic Purple</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="emerald-dream" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #0d2818, #2d5a44);"></div>
|
|
<span class="theme-name">Emerald Dream</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="mocha-coffee" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #3c2414, #5d3a26);"></div>
|
|
<span class="theme-name">Mocha Coffee</span>
|
|
</button>
|
|
<button class="theme-card" data-theme="lavender-fields" data-focusable tabindex="0">
|
|
<div class="theme-preview" style="background: linear-gradient(145deg, #f8f4ff, #e6d8ff);"></div>
|
|
<span class="theme-name">Lavender Fields</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Display Panel -->
|
|
<div class="settings-panel" id="settings-panel-display">
|
|
<h2 class="settings-panel-title">Display Settings</h2>
|
|
<div class="settings-option">
|
|
<div class="option-info">
|
|
<span class="material-symbols-outlined">zoom_in</span>
|
|
<div class="option-text">
|
|
<span class="option-label">Display Scale</span>
|
|
<span class="option-description">Adjust the default zoom level</span>
|
|
</div>
|
|
</div>
|
|
<div class="option-control">
|
|
<button class="scale-btn" id="bp-scale-down" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">remove</span>
|
|
</button>
|
|
<span class="scale-value" id="bp-scale-value">100%</span>
|
|
<button class="scale-btn" id="bp-scale-up" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">add</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="settings-option">
|
|
<div class="option-info">
|
|
<span class="material-symbols-outlined">desktop_windows</span>
|
|
<div class="option-text">
|
|
<span class="option-label">Exit Big Picture Mode</span>
|
|
<span class="option-description">Return to standard desktop interface</span>
|
|
</div>
|
|
</div>
|
|
<div class="option-control">
|
|
<button class="action-button" id="bp-exit-desktop" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">logout</span>
|
|
<span>Exit</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Privacy Panel -->
|
|
<div class="settings-panel" id="settings-panel-privacy">
|
|
<h2 class="settings-panel-title">Privacy & Data</h2>
|
|
<div class="settings-option">
|
|
<div class="option-info">
|
|
<span class="material-symbols-outlined">delete_sweep</span>
|
|
<div class="option-text">
|
|
<span class="option-label">Clear Browsing Data</span>
|
|
<span class="option-description">Delete cookies, cache, and site data</span>
|
|
</div>
|
|
</div>
|
|
<div class="option-control">
|
|
<button class="action-button danger" id="bp-clear-data" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">delete</span>
|
|
<span>Clear All</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="settings-option">
|
|
<div class="option-info">
|
|
<span class="material-symbols-outlined">history</span>
|
|
<div class="option-text">
|
|
<span class="option-label">Clear History</span>
|
|
<span class="option-description">Delete browsing history</span>
|
|
</div>
|
|
</div>
|
|
<div class="option-control">
|
|
<button class="action-button" id="bp-clear-history" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">delete</span>
|
|
<span>Clear</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="settings-option">
|
|
<div class="option-info">
|
|
<span class="material-symbols-outlined">search_off</span>
|
|
<div class="option-text">
|
|
<span class="option-label">Clear Search History</span>
|
|
<span class="option-description">Delete search query history</span>
|
|
</div>
|
|
</div>
|
|
<div class="option-control">
|
|
<button class="action-button" id="bp-clear-search" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">delete</span>
|
|
<span>Clear</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- About Panel -->
|
|
<div class="settings-panel" id="settings-panel-about">
|
|
<h2 class="settings-panel-title">About Nebula Browser</h2>
|
|
<div class="about-info">
|
|
<div class="about-logo">
|
|
<img src="../assets/images/branding/Nebula-Icon.svg" alt="Nebula" class="about-logo-img">
|
|
<div class="about-title">
|
|
<h3>Nebula Browser</h3>
|
|
<span id="bp-version">Version loading...</span>
|
|
</div>
|
|
</div>
|
|
<div class="about-details">
|
|
<div class="about-row">
|
|
<span class="about-label">CEF</span>
|
|
<span class="about-value" id="bp-cef-version">--</span>
|
|
</div>
|
|
<div class="about-row">
|
|
<span class="about-label">Chromium</span>
|
|
<span class="about-value" id="bp-chromium-version">--</span>
|
|
</div>
|
|
<div class="about-row">
|
|
<span class="about-label">Node.js</span>
|
|
<span class="about-value" id="bp-node-version">--</span>
|
|
</div>
|
|
<div class="about-row">
|
|
<span class="about-label">Platform</span>
|
|
<span class="about-value" id="bp-platform">--</span>
|
|
</div>
|
|
</div>
|
|
<div class="about-actions">
|
|
<button class="action-button" id="bp-github-link" data-focusable tabindex="0">
|
|
<span class="ri-github-fill" style="font-size: 20px;"></span>
|
|
<span>GitHub</span>
|
|
</button>
|
|
<button class="action-button" id="bp-copy-diagnostics" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">content_copy</span>
|
|
<span>Copy Info</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Bottom controller hints -->
|
|
<footer class="bp-footer">
|
|
<div class="controller-hints">
|
|
<div class="hint">
|
|
<span class="controller-btn dpad">
|
|
<span class="material-symbols-outlined">gamepad</span>
|
|
</span>
|
|
<span>Navigate</span>
|
|
</div>
|
|
<div class="hint">
|
|
<span class="controller-btn a-btn">A</span>
|
|
<span>Select</span>
|
|
</div>
|
|
<div class="hint">
|
|
<span class="controller-btn b-btn">B</span>
|
|
<span>Back</span>
|
|
</div>
|
|
<div class="hint">
|
|
<span class="controller-btn y-btn">Y</span>
|
|
<span>Search</span>
|
|
</div>
|
|
<div class="hint">
|
|
<span class="controller-btn menu-btn">☰</span>
|
|
<span>Menu</span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- On-screen keyboard (for controller input) -->
|
|
<div id="osk-overlay" class="osk-overlay hidden">
|
|
<div class="osk-container">
|
|
<div class="osk-title">
|
|
<span class="material-symbols-outlined">keyboard</span>
|
|
<span id="osk-label">Enter text</span>
|
|
</div>
|
|
<div class="osk-header">
|
|
<div class="osk-input-wrapper">
|
|
<input type="text" id="osk-input" class="osk-text-input" placeholder="Your text appears here..." readonly>
|
|
<span id="osk-cursor" class="osk-cursor"></span>
|
|
<span id="osk-text-measure" class="osk-text-measure"></span>
|
|
</div>
|
|
<button class="osk-close" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">close</span>
|
|
</button>
|
|
</div>
|
|
<div class="osk-keyboard" id="osk-keyboard">
|
|
<!-- Keyboard rows will be generated by JS -->
|
|
</div>
|
|
<div class="osk-actions">
|
|
<button class="osk-action-btn" id="osk-space" data-focusable tabindex="0">
|
|
<span class="btn-hint">Y</span> Space
|
|
</button>
|
|
<button class="osk-action-btn" id="osk-backspace" data-focusable tabindex="0">
|
|
<span class="btn-hint">X</span>
|
|
<span class="material-symbols-outlined">backspace</span>
|
|
</button>
|
|
<button class="osk-action-btn" id="osk-clear" data-focusable tabindex="0">
|
|
<span class="btn-hint">LB</span> Clear
|
|
</button>
|
|
<button class="osk-action-btn primary" id="osk-submit" data-focusable tabindex="0">
|
|
<span class="btn-hint">RB</span> Go
|
|
</button>
|
|
</div>
|
|
<div class="osk-hints">
|
|
<span><b>A</b> Type</span>
|
|
<span><b>X</b> Backspace</span>
|
|
<span><b>Y</b> Space</span>
|
|
<span><b>B</b> Close</span>
|
|
<span><b>LB</b> Clear All</span>
|
|
<span><b>RB</b> Submit</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Context menu -->
|
|
<div id="context-menu" class="context-menu hidden">
|
|
<button class="context-item" data-action="open" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">open_in_new</span>
|
|
<span>Open</span>
|
|
</button>
|
|
<button class="context-item" data-action="edit" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">edit</span>
|
|
<span>Edit</span>
|
|
</button>
|
|
<button class="context-item" data-action="delete" data-focusable tabindex="0">
|
|
<span class="material-symbols-outlined">delete</span>
|
|
<span>Delete</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="../js/bigpicture.js"></script>
|
|
</body>
|
|
</html>
|