connection fixes
This commit is contained in:
@@ -21,7 +21,7 @@ class ConfigManager {
|
||||
// Конфигурация по умолчанию
|
||||
return {
|
||||
server: {
|
||||
url: 'http://localhost:3001',
|
||||
url: 'http://localhost:3002',
|
||||
autoConnect: false,
|
||||
reconnectAttempts: 3,
|
||||
reconnectInterval: 5000
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,11 +11,101 @@
|
||||
<!-- Header -->
|
||||
<header class="app-header">
|
||||
<div class="logo">
|
||||
<h1>🔍 GodEye Operator</h1>
|
||||
<!-- SVG Logo Icon -->
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" class="logo-icon">
|
||||
<defs>
|
||||
<linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#4CAF50"/>
|
||||
<stop offset="100%" style="stop-color:#8BC34A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="16" cy="16" r="15" fill="url(#logoGradient)" stroke="#2E7D32" stroke-width="2"/>
|
||||
<circle cx="16" cy="16" r="8" fill="none" stroke="#fff" stroke-width="2"/>
|
||||
<circle cx="16" cy="16" r="3" fill="#fff"/>
|
||||
<path d="M8 8 L12 12 M24 8 L20 12 M8 24 L12 20 M24 24 L20 20" stroke="#fff" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<h1>GodEye Operator</h1>
|
||||
</div>
|
||||
<div class="connection-status">
|
||||
<span id="connection-indicator" class="status disconnected">● Отключен</span>
|
||||
<span id="session-info"></span>
|
||||
|
||||
<div class="header-controls">
|
||||
<!-- Connection Status & Info -->
|
||||
<div class="connection-info">
|
||||
<span id="connection-status-text">Не подключен</span>
|
||||
<span id="ping-indicator">Ping: --</span>
|
||||
</div>
|
||||
|
||||
<!-- Connection Button -->
|
||||
<button id="connection-toggle" class="connection-toggle disconnected" title="Нажмите для подключения/отключения">
|
||||
<svg id="connection-status-icon" width="16" height="16" viewBox="0 0 16 16" class="status-icon disconnected">
|
||||
<circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||
<circle cx="8" cy="8" r="2" fill="currentColor"/>
|
||||
</svg>
|
||||
<span id="connection-button-text">Отключен</span>
|
||||
</button>
|
||||
|
||||
<!-- Settings Dropdown -->
|
||||
<div class="settings-dropdown">
|
||||
<button id="settings-toggle" class="settings-button" title="Настройки">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20">
|
||||
<path fill="currentColor" d="M10 6a4 4 0 100 8 4 4 0 000-8zM8 10a2 2 0 114 0 2 2 0 01-4 0z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" d="M10 2a1 1 0 011 1v1.323l1.532.884a1 1 0 01.5.866v.654l1.532.884a1 1 0 010 1.732L13.032 10l1.532.884a1 1 0 010 1.732l-1.532.884v.654a1 1 0 01-.5.866L11 16.677V18a1 1 0 11-2 0v-1.323L7.468 15.793a1 1 0 01-.5-.866v-.654l-1.532-.884a1 1 0 010-1.732L6.968 10 5.436 9.116a1 1 0 010-1.732l1.532-.884v-.654a1 1 0 01.5-.866L9 4.323V3a1 1 0 011-1z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div id="settings-menu" class="settings-menu">
|
||||
<!-- Server URL -->
|
||||
<div class="setting-item">
|
||||
<label for="server-url">URL сервера:</label>
|
||||
<input type="text" id="server-url" value="http://localhost:3001" placeholder="http://localhost:3001">
|
||||
</div>
|
||||
|
||||
<!-- Auto-connect -->
|
||||
<div class="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" id="auto-connect"> Автоподключение
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Advanced Settings Divider -->
|
||||
<div class="setting-divider"></div>
|
||||
<div class="setting-label">Расширенные настройки</div>
|
||||
|
||||
<!-- Connection Timeout -->
|
||||
<div class="setting-item">
|
||||
<label for="connection-timeout">Таймаут (мс):</label>
|
||||
<input type="number" id="connection-timeout" value="10000" min="1000" max="60000">
|
||||
</div>
|
||||
|
||||
<!-- Reconnect Attempts -->
|
||||
<div class="setting-item">
|
||||
<label for="reconnect-attempts">Попытки переподключения:</label>
|
||||
<input type="number" id="reconnect-attempts" value="5" min="0" max="20">
|
||||
</div>
|
||||
|
||||
<!-- Ping Interval -->
|
||||
<div class="setting-item">
|
||||
<label for="ping-interval">Интервал пинга (мс):</label>
|
||||
<input type="number" id="ping-interval" value="25000" min="5000" max="120000">
|
||||
</div>
|
||||
|
||||
<!-- Compression -->
|
||||
<div class="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" id="compression" checked> Сжатие данных
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Debug Mode -->
|
||||
<div class="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" id="debug-mode"> Режим отладки
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session Info -->
|
||||
<span id="session-info" class="session-info"></span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -99,69 +189,104 @@
|
||||
|
||||
<!-- Right Panel - Devices & Sessions -->
|
||||
<div class="control-panel">
|
||||
<!-- Connection Settings -->
|
||||
<div class="connection-panel panel-section collapsible">
|
||||
<div class="panel-header clickable" id="connection-toggle">
|
||||
<h3>🔌 Подключение к серверу</h3>
|
||||
<span class="collapse-icon collapsed">▼</span>
|
||||
</div>
|
||||
<div class="panel-content collapsed" id="connection-content">
|
||||
<div class="input-group">
|
||||
<label for="server-url">URL сервера:</label>
|
||||
<input type="text" id="server-url" value="http://localhost:3001" placeholder="http://localhost:3001">
|
||||
</div>
|
||||
<div class="checkbox-group">
|
||||
<label>
|
||||
<input type="checkbox" id="auto-connect"> Автоматически подключаться при запуске
|
||||
</label>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button id="connect-btn" class="btn-primary">Подключиться</button>
|
||||
<button id="disconnect-btn" class="btn-secondary" disabled>Отключиться</button>
|
||||
</div>
|
||||
<div id="connection-info" class="connection-info">
|
||||
<span id="connection-status-text">Не подключен</span>
|
||||
<span id="ping-indicator">Ping: --</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-header">
|
||||
<h2>Панель управления</h2>
|
||||
<button id="sidebar-toggle" class="btn-collapse sidebar-collapse" title="Свернуть/развернуть сайдбар">
|
||||
<span class="collapse-icon">◄</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="sidebar-content" class="sidebar-content">
|
||||
|
||||
<!-- Available Devices -->
|
||||
<div class="devices-panel panel-section">
|
||||
<div class="devices-panel">
|
||||
<div class="panel-header">
|
||||
<h3>📱 Доступные устройства</h3>
|
||||
<button id="refresh-devices" class="btn-icon" title="Обновить список">🔄</button>
|
||||
<h3>Доступные устройства</h3>
|
||||
<button id="devices-toggle" class="btn-collapse" title="Свернуть/развернуть">
|
||||
<span class="collapse-icon">▲</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="devices-list" class="devices-list compact-list">
|
||||
<div class="no-devices">Нет подключенных устройств</div>
|
||||
<div id="devices-content" class="panel-content">
|
||||
<div class="devices-header" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span></span>
|
||||
<button id="refresh-devices" class="btn-secondary btn-small" title="Обновить список устройств">🔄 Обновить</button>
|
||||
</div>
|
||||
<div id="devices-list" class="devices-list">
|
||||
<div class="no-devices">Нет подключенных устройств</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Sessions -->
|
||||
<div class="sessions-panel panel-section">
|
||||
<h3>🔗 Активные сессии</h3>
|
||||
<div id="sessions-list" class="sessions-list compact-list">
|
||||
<div class="no-sessions">Нет активных сессий</div>
|
||||
<div class="sessions-panel">
|
||||
<div class="panel-header">
|
||||
<h3>Активные сессии</h3>
|
||||
<button id="sessions-toggle" class="btn-collapse" title="Свернуть/развернуть">
|
||||
<span class="collapse-icon">▲</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="sessions-content" class="panel-content">
|
||||
<div id="sessions-list" class="sessions-list">
|
||||
<div class="no-sessions">Нет активных сессий</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session History -->
|
||||
<div class="history-panel">
|
||||
<div class="panel-header">
|
||||
<h3>История сессий</h3>
|
||||
<button id="history-toggle" class="btn-collapse" title="Свернуть/развернуть">
|
||||
<span class="collapse-icon">▲</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="history-content" class="history-content panel-content">
|
||||
<div class="history-stats">
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Всего сессий:</span>
|
||||
<span id="total-sessions">0</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Успешных:</span>
|
||||
<span id="successful-sessions">0</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-label">Общее время:</span>
|
||||
<span id="total-duration">0:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="history-controls">
|
||||
<button id="export-history" class="btn-secondary btn-small">📊 Экспорт</button>
|
||||
<button id="clear-history" class="btn-secondary btn-small">🗑️ Очистить</button>
|
||||
</div>
|
||||
<div id="history-list" class="history-list">
|
||||
<div class="no-history">История пуста</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logs -->
|
||||
<div class="logs-panel panel-section collapsible">
|
||||
<div class="panel-header clickable" id="logs-toggle">
|
||||
<h3>📋 Журнал событий</h3>
|
||||
<span class="collapse-icon">▲</span>
|
||||
<div class="logs-panel">
|
||||
<div class="panel-header">
|
||||
<h3>Журнал событий</h3>
|
||||
<button id="logs-toggle" class="btn-collapse" title="Свернуть/развернуть">
|
||||
<span class="collapse-icon">▲</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="panel-content" id="logs-content">
|
||||
<div id="logs-container" class="logs-container"></div>
|
||||
<div id="logs-content" class="panel-content">
|
||||
<div id="logs-container" class="logs-container" style="max-height: 180px; overflow-y: auto;"></div>
|
||||
<button id="clear-logs" class="btn-secondary btn-small">Очистить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notifications Container -->
|
||||
<div id="toast-container" class="toast-container"></div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
4908
desktop-operator/src/renderer/socket.io.js
Normal file
4908
desktop-operator/src/renderer/socket.io.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: #1a1a1a;
|
||||
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
|
||||
color: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -20,34 +20,184 @@ body {
|
||||
|
||||
/* Header */
|
||||
.app-header {
|
||||
background: #2d2d2d;
|
||||
padding: 10px 20px;
|
||||
background: linear-gradient(135deg, #2d2d2d 0%, #3d3d3d 100%);
|
||||
padding: 15px 25px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 2px solid #333;
|
||||
border-bottom: 2px solid #4CAF50;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
animation: logoRotate 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes logoRotate {
|
||||
0%, 100% { transform: rotate(0deg); }
|
||||
50% { transform: rotate(5deg); }
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 20px;
|
||||
color: #4CAF50;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #4CAF50, #8BC34A);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.connection-status {
|
||||
.header-controls {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.status {
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
.connection-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.status.connected {
|
||||
background: #4CAF50;
|
||||
.connection-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.connection-toggle.connected {
|
||||
background: linear-gradient(135deg, #4CAF50, #66BB6A);
|
||||
color: white;
|
||||
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.4);
|
||||
}
|
||||
|
||||
.connection-toggle.disconnected {
|
||||
background: linear-gradient(135deg, #f44336, #ef5350);
|
||||
color: white;
|
||||
box-shadow: 0 2px 12px rgba(244, 67, 54, 0.4);
|
||||
}
|
||||
|
||||
.connection-toggle:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.settings-dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.settings-button {
|
||||
background: none;
|
||||
border: 1px solid #555;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.settings-button:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
color: #fff;
|
||||
border-color: #4CAF50;
|
||||
}
|
||||
|
||||
.settings-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: linear-gradient(135deg, #2d2d2d 0%, #3d3d3d 100%);
|
||||
border: 1px solid #555;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
min-width: 300px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||
z-index: 2000;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.settings-menu.show {
|
||||
display: block;
|
||||
animation: settingsSlideIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
@keyframes settingsSlideIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.setting-item label {
|
||||
display: block;
|
||||
color: #ccc;
|
||||
font-size: 13px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.setting-item input[type="text"],
|
||||
.setting-item input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border: 1px solid #555;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.setting-item input[type="checkbox"] {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.setting-divider {
|
||||
height: 1px;
|
||||
background: #555;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
font-weight: 600;
|
||||
color: #4CAF50;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.session-info {
|
||||
font-size: 12px;
|
||||
color: #4CAF50;
|
||||
font-weight: 500;
|
||||
}
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -306,91 +456,19 @@ body {
|
||||
background: #252525;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 380px;
|
||||
min-width: 300px;
|
||||
transition: max-width 0.3s ease;
|
||||
}
|
||||
|
||||
.control-panel.logs-collapsed {
|
||||
max-width: 320px;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.control-panel > div {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
/* Panel Sections */
|
||||
.panel-section {
|
||||
padding: 12px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.panel-header.clickable {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.panel-header.clickable:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
margin: -5px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.collapse-icon {
|
||||
font-size: 12px;
|
||||
transition: transform 0.3s ease;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.collapse-icon.collapsed {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel-content.collapsed {
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Connection Panel */
|
||||
.connection-panel {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.connection-panel.collapsed {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.connection-panel h3 {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 15px;
|
||||
color: #4CAF50;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.connection-panel h3 span {
|
||||
font-size: 10px;
|
||||
margin-left: auto;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
@@ -457,53 +535,32 @@ button:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Devices and Sessions Panels */
|
||||
.devices-panel,
|
||||
.sessions-panel {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* Devices Panel */
|
||||
.devices-panel h3,
|
||||
.sessions-panel h3 {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 15px;
|
||||
color: #2196F3;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.compact-list {
|
||||
max-height: 180px;
|
||||
.devices-list,
|
||||
.sessions-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.control-panel.logs-collapsed .compact-list {
|
||||
max-height: 250px;
|
||||
}
|
||||
|
||||
.device-item,
|
||||
.session-item {
|
||||
background: #3a3a3a;
|
||||
margin-bottom: 6px;
|
||||
padding: 8px;
|
||||
margin-bottom: 8px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
border-left: 3px solid #4CAF50;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.device-item:hover,
|
||||
.session-item:hover {
|
||||
background: #404040;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.device-info {
|
||||
font-size: 11px;
|
||||
margin-bottom: 4px;
|
||||
line-height: 1.3;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.device-info strong {
|
||||
@@ -511,56 +568,28 @@ button:disabled {
|
||||
}
|
||||
|
||||
.device-capabilities {
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
margin-bottom: 6px;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.device-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.btn-device {
|
||||
background: #2196F3;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 3px 6px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 9px;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.btn-device:hover {
|
||||
background: #1976D2;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.btn-device.btn-success {
|
||||
background: #4CAF50;
|
||||
}
|
||||
|
||||
.btn-device.btn-success:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
padding: 2px;
|
||||
border-radius: 3px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-icon:hover {
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.no-devices,
|
||||
@@ -571,119 +600,29 @@ button:disabled {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Session styles */
|
||||
.session-item {
|
||||
border-left: 3px solid #2196F3;
|
||||
}
|
||||
|
||||
.session-item.session-pending {
|
||||
border-left-color: #FF9800;
|
||||
}
|
||||
|
||||
.session-item.session-active {
|
||||
border-left-color: #4CAF50;
|
||||
}
|
||||
|
||||
.session-item.session-rejected {
|
||||
border-left-color: #f44336;
|
||||
}
|
||||
|
||||
.session-item.session-ended {
|
||||
border-left-color: #666;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.session-item.active {
|
||||
background: #4a4a4a;
|
||||
border: 2px solid #4CAF50;
|
||||
border-left: 3px solid #4CAF50;
|
||||
}
|
||||
|
||||
.session-header {
|
||||
font-size: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.session-header strong {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.status-pending { color: #FF9800; }
|
||||
.status-active { color: #4CAF50; }
|
||||
.status-rejected { color: #f44336; }
|
||||
.status-ended { color: #666; }
|
||||
|
||||
.session-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 2px 6px;
|
||||
font-size: 10px;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-small.btn-primary {
|
||||
background: #2196F3;
|
||||
}
|
||||
|
||||
.btn-small.btn-success {
|
||||
background: #4CAF50;
|
||||
}
|
||||
|
||||
.btn-small.btn-secondary {
|
||||
background: #757575;
|
||||
}
|
||||
|
||||
.btn-small.btn-danger {
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
.btn-small:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Logs Panel */
|
||||
.logs-panel {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.logs-panel.collapsed {
|
||||
flex: none;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.logs-panel h3 {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 15px;
|
||||
color: #FF9800;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.logs-container {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
padding: 8px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 8px;
|
||||
max-height: 120px;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.control-panel.logs-collapsed .logs-container {
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
@@ -906,4 +845,399 @@ button:disabled {
|
||||
border-right: 1px solid #333;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toast Notifications */
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
background: linear-gradient(135deg, #2d2d2d 0%, #3d3d3d 100%);
|
||||
color: white;
|
||||
padding: 16px 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
|
||||
border-left: 4px solid #4CAF50;
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
animation: toastSlideIn 0.3s ease-out forwards;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.toast.removing {
|
||||
animation: toastSlideOut 0.3s ease-in forwards;
|
||||
}
|
||||
|
||||
.toast.success {
|
||||
border-left-color: #4CAF50;
|
||||
}
|
||||
|
||||
.toast.error {
|
||||
border-left-color: #f44336;
|
||||
}
|
||||
|
||||
.toast.warning {
|
||||
border-left-color: #ff9800;
|
||||
}
|
||||
|
||||
.toast.info {
|
||||
border-left-color: #2196F3;
|
||||
}
|
||||
|
||||
.toast-content {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.toast-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.toast-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
font-size: 13px;
|
||||
opacity: 0.9;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.toast-close:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes toastSlideIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes toastSlideOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Advanced Settings */
|
||||
.advanced-toggle {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #4CAF50;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
text-decoration: underline;
|
||||
padding: 4px 0;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-link:hover {
|
||||
color: #66BB6A;
|
||||
}
|
||||
|
||||
.advanced-settings {
|
||||
background: rgba(255,255,255,0.05);
|
||||
border: 1px solid #333;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
animation: slideDown 0.3s ease-out;
|
||||
}
|
||||
|
||||
.advanced-settings.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.settings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.settings-grid .input-group,
|
||||
.settings-grid .checkbox-group {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.settings-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Session History */
|
||||
.history-panel {
|
||||
background: #2d2d2d;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Collapsible Panels */
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
background: linear-gradient(135deg, #3d3d3d, #4d4d4d);
|
||||
border-bottom: 1px solid #555;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.panel-header:hover {
|
||||
background: linear-gradient(135deg, #4d4d4d, #5d5d5d);
|
||||
}
|
||||
|
||||
.panel-header h3 {
|
||||
color: #4CAF50;
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
max-height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel-content.collapsed {
|
||||
max-height: 0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.btn-collapse {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn-collapse:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.collapse-icon {
|
||||
transition: transform 0.2s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.collapse-icon.collapsed {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Sidebar Collapsible */
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
background: linear-gradient(135deg, #3d3d3d, #4d4d4d);
|
||||
border-bottom: 2px solid #4CAF50;
|
||||
}
|
||||
|
||||
.sidebar-header h2 {
|
||||
color: #4CAF50;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sidebar-collapse {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .sidebar-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.control-panel.collapsed {
|
||||
width: 60px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .sidebar-header {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .sidebar-header h2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .collapse-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.history-panel {
|
||||
background: #2d2d2d;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.history-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-item span:last-child {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.history-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.history-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
background: rgba(255,255,255,0.05);
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
border-left: 3px solid #4CAF50;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.history-item:hover {
|
||||
background: rgba(255,255,255,0.08);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.history-item.failed {
|
||||
border-left-color: #f44336;
|
||||
}
|
||||
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.history-device {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.history-duration {
|
||||
font-size: 12px;
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.history-details {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.no-history {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
padding: 20px;
|
||||
}
|
||||
Reference in New Issue
Block a user