mirror of
https://github.com/smittix/intercept.git
synced 2026-05-29 21:59:27 -07:00
Add welcome page with changelog and mode selection
- Replace simple splash screen with comprehensive welcome page - Show version number and latest changelog entries - Add 9-button mode selection grid for direct navigation - User can now choose which mode to start with - Responsive layout adapts to mobile screens - Flow: Welcome → Disclaimer (if needed) → Selected mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
4
app.py
4
app.py
@@ -25,7 +25,7 @@ from typing import Any
|
||||
|
||||
from flask import Flask, render_template, jsonify, send_file, Response, request
|
||||
|
||||
from config import VERSION
|
||||
from config import VERSION, CHANGELOG
|
||||
from utils.dependencies import check_tool, check_all_dependencies, TOOL_DEPENDENCIES
|
||||
from utils.process import cleanup_stale_processes
|
||||
from utils.sdr import SDRFactory
|
||||
@@ -164,7 +164,7 @@ def index() -> str:
|
||||
'rtl_433': check_tool('rtl_433')
|
||||
}
|
||||
devices = [d.to_dict() for d in SDRFactory.detect_devices()]
|
||||
return render_template('index.html', tools=tools, devices=devices, version=VERSION)
|
||||
return render_template('index.html', tools=tools, devices=devices, version=VERSION, changelog=CHANGELOG)
|
||||
|
||||
|
||||
@app.route('/favicon.svg')
|
||||
|
||||
34
config.py
34
config.py
@@ -9,6 +9,40 @@ import sys
|
||||
# Application version
|
||||
VERSION = "2.9.0"
|
||||
|
||||
# Changelog - latest release notes (shown on welcome screen)
|
||||
CHANGELOG = [
|
||||
{
|
||||
"version": "2.9.0",
|
||||
"date": "January 2026",
|
||||
"highlights": [
|
||||
"New dropdown navigation menus for cleaner UI",
|
||||
"TSCM baseline recording now captures device data",
|
||||
"Device identity engine integration for threat detection",
|
||||
"Welcome screen with mode selection",
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.8.0",
|
||||
"date": "December 2025",
|
||||
"highlights": [
|
||||
"Added TSCM counter-surveillance mode",
|
||||
"WiFi/Bluetooth device correlation engine",
|
||||
"Tracker detection (AirTag, Tile, SmartTag)",
|
||||
"Risk scoring and threat classification",
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.7.0",
|
||||
"date": "November 2025",
|
||||
"highlights": [
|
||||
"Multi-SDR hardware support via SoapySDR",
|
||||
"LimeSDR, HackRF, Airspy, SDRplay support",
|
||||
"Improved aircraft database with photo lookup",
|
||||
"GPS auto-detection and integration",
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _get_env(key: str, default: str) -> str:
|
||||
"""Get environment variable with default."""
|
||||
|
||||
@@ -83,10 +83,10 @@ body {
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
LANDING PAGE / SPLASH SCREEN
|
||||
WELCOME PAGE
|
||||
============================================ */
|
||||
|
||||
.landing-overlay {
|
||||
.welcome-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -100,7 +100,7 @@ body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.landing-overlay::before {
|
||||
.welcome-overlay::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -113,13 +113,14 @@ body {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.landing-content {
|
||||
text-align: center;
|
||||
.welcome-container {
|
||||
width: 90%;
|
||||
max-width: 900px;
|
||||
z-index: 1;
|
||||
animation: landingFadeIn 1s ease-out;
|
||||
animation: welcomeFadeIn 0.8s ease-out;
|
||||
}
|
||||
|
||||
@keyframes landingFadeIn {
|
||||
@keyframes welcomeFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
@@ -130,46 +131,44 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.landing-logo {
|
||||
/* Welcome Header */
|
||||
.welcome-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.welcome-logo {
|
||||
animation: logoPulse 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes logoPulse {
|
||||
0%, 100% {
|
||||
filter: drop-shadow(0 0 20px rgba(0, 212, 255, 0.3));
|
||||
filter: drop-shadow(0 0 15px rgba(0, 212, 255, 0.3));
|
||||
}
|
||||
50% {
|
||||
filter: drop-shadow(0 0 40px rgba(0, 212, 255, 0.6));
|
||||
filter: drop-shadow(0 0 30px rgba(0, 212, 255, 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
.landing-logo .signal-wave {
|
||||
.welcome-logo .signal-wave {
|
||||
animation: signalPulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-logo .signal-wave-1 {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.landing-logo .signal-wave-2 {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.landing-logo .signal-wave-3 {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.welcome-logo .signal-wave-1 { animation-delay: 0s; }
|
||||
.welcome-logo .signal-wave-2 { animation-delay: 0.2s; }
|
||||
.welcome-logo .signal-wave-3 { animation-delay: 0.4s; }
|
||||
|
||||
@keyframes signalPulse {
|
||||
0%, 100% {
|
||||
opacity: 0.3;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.landing-logo .logo-dot {
|
||||
.welcome-logo .logo-dot {
|
||||
animation: dotPulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@@ -184,119 +183,239 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.landing-title {
|
||||
.welcome-title-block {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 4rem;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
letter-spacing: 0.3em;
|
||||
margin: 0 0 10px 0;
|
||||
text-shadow: 0 0 30px rgba(0, 212, 255, 0.3);
|
||||
}
|
||||
|
||||
.landing-tagline {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 1.2rem;
|
||||
color: #00d4ff;
|
||||
letter-spacing: 0.2em;
|
||||
margin: 0 0 8px 0;
|
||||
opacity: 0.9;
|
||||
margin: 0;
|
||||
text-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
|
||||
}
|
||||
|
||||
.landing-subtitle {
|
||||
font-family: 'Inter', sans-serif;
|
||||
.welcome-tagline {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
color: var(--accent-cyan);
|
||||
letter-spacing: 0.15em;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
.welcome-version {
|
||||
display: inline-block;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.65rem;
|
||||
color: var(--bg-primary);
|
||||
background: var(--accent-cyan);
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
letter-spacing: 0.05em;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Welcome Content Grid */
|
||||
.welcome-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.5fr;
|
||||
gap: 30px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.welcome-content h2 {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
margin: 0 0 40px 0;
|
||||
letter-spacing: 0.15em;
|
||||
margin: 0 0 15px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.landing-enter-btn {
|
||||
background: transparent;
|
||||
border: 2px solid #00d4ff;
|
||||
color: #00d4ff;
|
||||
padding: 15px 50px;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 0.2em;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
/* Changelog Section */
|
||||
.welcome-changelog {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.changelog-release {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.changelog-release:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.changelog-version-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.landing-enter-btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(0, 212, 255, 0.2), transparent);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
.landing-enter-btn:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.landing-enter-btn:hover {
|
||||
background: rgba(0, 212, 255, 0.1);
|
||||
box-shadow: 0 0 30px rgba(0, 212, 255, 0.3), inset 0 0 20px rgba(0, 212, 255, 0.1);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.landing-enter-btn .btn-icon {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.landing-enter-btn:hover .btn-icon {
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.landing-version {
|
||||
.changelog-version {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent-cyan);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.changelog-date {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-dim);
|
||||
margin-top: 30px;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.landing-scanline {
|
||||
.changelog-list {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.changelog-list li {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.changelog-list li::before {
|
||||
content: '>';
|
||||
position: absolute;
|
||||
left: -15px;
|
||||
color: var(--accent-green);
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
|
||||
/* Mode Selection Grid */
|
||||
.welcome-modes {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.mode-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mode-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 15px 10px;
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mode-card:hover {
|
||||
background: var(--bg-elevated);
|
||||
border-color: var(--accent-cyan);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 20px rgba(0, 212, 255, 0.15);
|
||||
}
|
||||
|
||||
.mode-card:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.mode-card .mode-icon {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.mode-card .mode-name {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.mode-card .mode-desc {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.65rem;
|
||||
color: var(--text-dim);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Welcome Footer */
|
||||
.welcome-footer {
|
||||
text-align: center;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.welcome-footer p {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-dim);
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Welcome Scanline */
|
||||
.welcome-scanline {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, transparent, #00d4ff, transparent);
|
||||
animation: scanlineMove 4s linear infinite;
|
||||
opacity: 0.5;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
|
||||
animation: scanlineMove 5s linear infinite;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
@keyframes scanlineMove {
|
||||
0% {
|
||||
top: 0;
|
||||
}
|
||||
100% {
|
||||
top: 100%;
|
||||
}
|
||||
0% { top: 0; }
|
||||
100% { top: 100%; }
|
||||
}
|
||||
|
||||
.landing-overlay.fade-out {
|
||||
animation: landingFadeOut 0.5s ease-in forwards;
|
||||
/* Welcome Fade Out */
|
||||
.welcome-overlay.fade-out {
|
||||
animation: welcomeFadeOut 0.4s ease-in forwards;
|
||||
}
|
||||
|
||||
@keyframes landingFadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
@keyframes welcomeFadeOut {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; visibility: hidden; }
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.welcome-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
.welcome-header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.welcome-title-block {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mode-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,36 +17,111 @@
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Landing Page / Splash Screen -->
|
||||
<div class="landing-overlay" id="landingPage">
|
||||
<div class="landing-content">
|
||||
<div class="landing-logo">
|
||||
<svg width="200" height="200" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Signal brackets - left side -->
|
||||
<path d="M15 30 Q5 50, 15 70" stroke="#00d4ff" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5" class="signal-wave signal-wave-1"/>
|
||||
<path d="M22 35 Q14 50, 22 65" stroke="#00d4ff" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7" class="signal-wave signal-wave-2"/>
|
||||
<path d="M29 40 Q23 50, 29 60" stroke="#00d4ff" stroke-width="2" fill="none" stroke-linecap="round" class="signal-wave signal-wave-3"/>
|
||||
<!-- Signal brackets - right side -->
|
||||
<path d="M85 30 Q95 50, 85 70" stroke="#00d4ff" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5" class="signal-wave signal-wave-1"/>
|
||||
<path d="M78 35 Q86 50, 78 65" stroke="#00d4ff" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7" class="signal-wave signal-wave-2"/>
|
||||
<path d="M71 40 Q77 50, 71 60" stroke="#00d4ff" stroke-width="2" fill="none" stroke-linecap="round" class="signal-wave signal-wave-3"/>
|
||||
<!-- The 'i' letter -->
|
||||
<circle cx="50" cy="22" r="6" fill="#00ff88" class="logo-dot"/>
|
||||
<rect x="44" y="35" width="12" height="45" rx="2" fill="#00d4ff"/>
|
||||
<rect x="38" y="35" width="24" height="4" rx="1" fill="#00d4ff"/>
|
||||
<rect x="38" y="76" width="24" height="4" rx="1" fill="#00d4ff"/>
|
||||
</svg>
|
||||
<!-- Welcome Page -->
|
||||
<div class="welcome-overlay" id="welcomePage">
|
||||
<div class="welcome-container">
|
||||
<!-- Header Section -->
|
||||
<div class="welcome-header">
|
||||
<div class="welcome-logo">
|
||||
<svg width="80" height="80" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 30 Q5 50, 15 70" stroke="#00d4ff" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5" class="signal-wave signal-wave-1"/>
|
||||
<path d="M22 35 Q14 50, 22 65" stroke="#00d4ff" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7" class="signal-wave signal-wave-2"/>
|
||||
<path d="M29 40 Q23 50, 29 60" stroke="#00d4ff" stroke-width="2" fill="none" stroke-linecap="round" class="signal-wave signal-wave-3"/>
|
||||
<path d="M85 30 Q95 50, 85 70" stroke="#00d4ff" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5" class="signal-wave signal-wave-1"/>
|
||||
<path d="M78 35 Q86 50, 78 65" stroke="#00d4ff" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7" class="signal-wave signal-wave-2"/>
|
||||
<path d="M71 40 Q77 50, 71 60" stroke="#00d4ff" stroke-width="2" fill="none" stroke-linecap="round" class="signal-wave signal-wave-3"/>
|
||||
<circle cx="50" cy="22" r="6" fill="#00ff88" class="logo-dot"/>
|
||||
<rect x="44" y="35" width="12" height="45" rx="2" fill="#00d4ff"/>
|
||||
<rect x="38" y="35" width="24" height="4" rx="1" fill="#00d4ff"/>
|
||||
<rect x="38" y="76" width="24" height="4" rx="1" fill="#00d4ff"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="welcome-title-block">
|
||||
<h1 class="welcome-title">iNTERCEPT</h1>
|
||||
<p class="welcome-tagline">// See the Invisible</p>
|
||||
<span class="welcome-version">v{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Grid -->
|
||||
<div class="welcome-content">
|
||||
<!-- Left: Changelog -->
|
||||
<div class="welcome-changelog">
|
||||
<h2>What's New</h2>
|
||||
{% for release in changelog[:2] %}
|
||||
<div class="changelog-release">
|
||||
<div class="changelog-version-header">
|
||||
<span class="changelog-version">v{{ release.version }}</span>
|
||||
<span class="changelog-date">{{ release.date }}</span>
|
||||
</div>
|
||||
<ul class="changelog-list">
|
||||
{% for item in release.highlights %}
|
||||
<li>{{ item }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Right: Mode Selection -->
|
||||
<div class="welcome-modes">
|
||||
<h2>Select Mode</h2>
|
||||
<div class="mode-grid">
|
||||
<button class="mode-card" onclick="selectMode('pager')">
|
||||
<span class="mode-icon">📟</span>
|
||||
<span class="mode-name">Pager</span>
|
||||
<span class="mode-desc">POCSAG/FLEX decoding</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('sensor')">
|
||||
<span class="mode-icon">📡</span>
|
||||
<span class="mode-name">433MHz</span>
|
||||
<span class="mode-desc">IoT sensor monitoring</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('aircraft')">
|
||||
<span class="mode-icon">✈️</span>
|
||||
<span class="mode-name">Aircraft</span>
|
||||
<span class="mode-desc">ADS-B tracking</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('wifi')">
|
||||
<span class="mode-icon">📶</span>
|
||||
<span class="mode-name">WiFi</span>
|
||||
<span class="mode-desc">Network reconnaissance</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('bluetooth')">
|
||||
<span class="mode-icon">🔵</span>
|
||||
<span class="mode-name">Bluetooth</span>
|
||||
<span class="mode-desc">Device discovery</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('tscm')">
|
||||
<span class="mode-icon">🔍</span>
|
||||
<span class="mode-name">TSCM</span>
|
||||
<span class="mode-desc">Counter-surveillance</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('satellite')">
|
||||
<span class="mode-icon">🛰️</span>
|
||||
<span class="mode-name">Satellite</span>
|
||||
<span class="mode-desc">Pass prediction</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('listening')">
|
||||
<span class="mode-icon">📻</span>
|
||||
<span class="mode-name">Scanner</span>
|
||||
<span class="mode-desc">Frequency scanning</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('aprs')">
|
||||
<span class="mode-icon">📍</span>
|
||||
<span class="mode-name">APRS</span>
|
||||
<span class="mode-desc">Amateur radio</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="welcome-footer">
|
||||
<p>Signal Intelligence & Counter Surveillance Platform</p>
|
||||
</div>
|
||||
<h1 class="landing-title">iNTERCEPT</h1>
|
||||
<p class="landing-tagline">// See the Invisible</p>
|
||||
<p class="landing-subtitle">Signal Intelligence & Counter Surveillance Platform</p>
|
||||
<button class="landing-enter-btn" onclick="enterApp()">
|
||||
<span class="btn-text">ENTER</span>
|
||||
<span class="btn-icon">→</span>
|
||||
</button>
|
||||
<p class="landing-version">v{{ version }}</p>
|
||||
</div>
|
||||
<div class="landing-scanline"></div>
|
||||
<div class="welcome-scanline"></div>
|
||||
</div>
|
||||
|
||||
<!-- Disclaimer Modal -->
|
||||
@@ -2831,16 +2906,20 @@
|
||||
<script src="{{ url_for('static', filename='js/modes/listening-post.js') }}"></script>
|
||||
|
||||
<script>
|
||||
// Landing page enter function
|
||||
function enterApp() {
|
||||
const landing = document.getElementById('landingPage');
|
||||
landing.classList.add('fade-out');
|
||||
// Selected mode from welcome screen
|
||||
let selectedStartMode = 'pager';
|
||||
|
||||
// After fade out, hide landing and show disclaimer if needed
|
||||
// Mode selection from welcome page
|
||||
function selectMode(mode) {
|
||||
selectedStartMode = mode;
|
||||
const welcome = document.getElementById('welcomePage');
|
||||
welcome.classList.add('fade-out');
|
||||
|
||||
// After fade out, hide welcome and show disclaimer if needed
|
||||
setTimeout(() => {
|
||||
landing.style.display = 'none';
|
||||
welcome.style.display = 'none';
|
||||
checkDisclaimer();
|
||||
}, 500);
|
||||
}, 400);
|
||||
}
|
||||
|
||||
// Disclaimer handling
|
||||
@@ -2848,6 +2927,8 @@
|
||||
const accepted = localStorage.getItem('disclaimerAccepted');
|
||||
if (accepted === 'true') {
|
||||
document.getElementById('disclaimerModal').style.display = 'none';
|
||||
// Switch to the selected mode
|
||||
switchMode(selectedStartMode);
|
||||
} else {
|
||||
document.getElementById('disclaimerModal').style.display = 'flex';
|
||||
}
|
||||
@@ -2856,6 +2937,10 @@
|
||||
function acceptDisclaimer() {
|
||||
localStorage.setItem('disclaimerAccepted', 'true');
|
||||
document.getElementById('disclaimerModal').classList.add('disclaimer-hidden');
|
||||
// Switch to the selected mode after accepting
|
||||
setTimeout(() => {
|
||||
switchMode(selectedStartMode);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function declineDisclaimer() {
|
||||
@@ -2863,7 +2948,7 @@
|
||||
document.getElementById('rejectionPage').classList.remove('disclaimer-hidden');
|
||||
}
|
||||
|
||||
// Don't auto-check disclaimer - wait for landing page enter
|
||||
// Don't auto-check disclaimer - wait for welcome page mode selection
|
||||
|
||||
let eventSource = null;
|
||||
let isRunning = false;
|
||||
|
||||
Reference in New Issue
Block a user