Move capture button left of search; always visible; disabled when server-disabled
- capture-btn moved to first child of trace-topbar (before search input) - Button always visible: shows Start/Stop/Connect-to-server as before - When server capture is disabled: grayed-out Start Capture with tooltip via existing i18n key 'Capture is disabled ...' - No more hiding button when viewing saved session or when disabled - Bump 1.22.4, SW cache v35->v36
This commit is contained in:
1 parent
0fac73833d
commit
0ec7db8d34
5 files changed
+27
-23
No files matched your search
+23
-19
@@ -114,6 +114,7 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(-
|
|||||||
.trace-topbar button.stop:hover { background: var(--danger-hover); }
|
.trace-topbar button.stop:hover { background: var(--danger-hover); }
|
||||||
.trace-topbar button.connect { background: var(--warn); color: #0f172a; }
|
.trace-topbar button.connect { background: var(--warn); color: #0f172a; }
|
||||||
.trace-topbar button.connect:hover { background: var(--warn-hover); }
|
.trace-topbar button.connect:hover { background: var(--warn-hover); }
|
||||||
|
.trace-topbar button.disabled { background: var(--bg-input); color: var(--text-muted); cursor: not-allowed; opacity: 0.6; }
|
||||||
.trace-main { display: flex; flex: 1; overflow: hidden; }
|
.trace-main { display: flex; flex: 1; overflow: hidden; }
|
||||||
.trace-left { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
|
.trace-left { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
|
||||||
|
|
||||||
@@ -280,15 +281,15 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(-
|
|||||||
</div>
|
</div>
|
||||||
</div><!-- Trace Panel -->
|
</div><!-- Trace Panel -->
|
||||||
<div class="panel active" id="panel-trace">
|
<div class="panel active" id="panel-trace">
|
||||||
<div class="trace-topbar">
|
<div class="trace-topbar">
|
||||||
<input type="text" id="search-input" data-l10n="Search hex bytes..." placeholder="Search hex bytes..." autocomplete="off">
|
<button id="capture-btn" data-l10n="Start Capture">Start Capture</button>
|
||||||
<label for="filter-select" class="filter-label" data-l10n="Filter">Filter</label>
|
<input type="text" id="search-input" data-l10n="Search hex bytes..." placeholder="Search hex bytes..." autocomplete="off">
|
||||||
<select id="filter-select">
|
<label for="filter-select" class="filter-label" data-l10n="Filter">Filter</label>
|
||||||
<option value="" data-l10n="All commands">All commands</option>
|
<select id="filter-select">
|
||||||
</select>
|
<option value="" data-l10n="All commands">All commands</option>
|
||||||
<button id="capture-btn" data-l10n="Start Capture">Start Capture</button>
|
</select>
|
||||||
<span id="session-name-display" style="display:none; color:var(--text-muted); font-size:15px; font-weight:700;"></span>
|
<span id="session-name-display" style="display:none; color:var(--text-muted); font-size:15px; font-weight:700;"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="trace-main">
|
<div class="trace-main">
|
||||||
<div class="trace-left">
|
<div class="trace-left">
|
||||||
<div class="apdu-list" id="apdu-list"></div>
|
<div class="apdu-list" id="apdu-list"></div>
|
||||||
@@ -2130,26 +2131,29 @@ async function stopCapture() {
|
|||||||
function updateCaptureButton() {
|
function updateCaptureButton() {
|
||||||
const btn = el('capture-btn');
|
const btn = el('capture-btn');
|
||||||
const newCapture = el('new-capture-btn');
|
const newCapture = el('new-capture-btn');
|
||||||
btn.classList.remove('stop', 'connect');
|
btn.classList.remove('stop', 'connect', 'disabled');
|
||||||
const captureOff = STATE.captureMode === 'disabled' && STATE.serverAvailable;
|
const captureOff = STATE.captureMode === 'disabled' && STATE.serverAvailable;
|
||||||
newCapture.style.display = captureOff ? 'none' : '';
|
newCapture.style.display = captureOff ? 'none' : '';
|
||||||
if (captureOff) {
|
|
||||||
btn.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (STATE.sessionViewId && !STATE.captureActive) {
|
|
||||||
btn.style.display = 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
btn.style.display = '';
|
btn.style.display = '';
|
||||||
if (!STATE.serverAvailable) {
|
if (!STATE.serverAvailable) {
|
||||||
btn.textContent = t('Connect to server');
|
btn.textContent = t('Connect to server');
|
||||||
btn.classList.add('connect');
|
btn.classList.add('connect');
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.title = '';
|
||||||
|
} else if (captureOff) {
|
||||||
|
btn.textContent = t('Start Capture');
|
||||||
|
btn.classList.add('disabled');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.title = t('Capture is disabled — only pre-captured traces (saved sessions / PCAP import) are available.');
|
||||||
} else if (STATE.captureActive) {
|
} else if (STATE.captureActive) {
|
||||||
btn.textContent = t('Stop Capture');
|
btn.textContent = t('Stop Capture');
|
||||||
btn.classList.add('stop');
|
btn.classList.add('stop');
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.title = '';
|
||||||
} else {
|
} else {
|
||||||
btn.textContent = t('Start Capture');
|
btn.textContent = t('Start Capture');
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.title = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2518,7 +2522,7 @@ function onFilterChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ──────────────────── Versioning ────────────────────
|
// ──────────────────── Versioning ────────────────────
|
||||||
const PWA_VERSION = '1.22.3';
|
const PWA_VERSION = '1.22.4';
|
||||||
const MIN_SERVER_VERSION = '1.0.0';
|
const MIN_SERVER_VERSION = '1.0.0';
|
||||||
|
|
||||||
function parseVersion(v) {
|
function parseVersion(v) {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'simtrace-analyser-v35';
|
const CACHE = 'simtrace-analyser-v36';
|
||||||
|
|
||||||
const PRECACHE = [
|
const PRECACHE = [
|
||||||
'index.html',
|
'index.html',
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "simtrace2-pysniff"
|
name = "simtrace2-pysniff"
|
||||||
version = "1.22.3"
|
version = "1.22.4"
|
||||||
description = "Python-based sniffing tool for SIMtrace2 hardware (SIM card communication sniffer)"
|
description = "Python-based sniffing tool for SIMtrace2 hardware (SIM card communication sniffer)"
|
||||||
readme = {file = "README.md", content-type = "text/markdown"}
|
readme = {file = "README.md", content-type = "text/markdown"}
|
||||||
license = {text = "GPL-2.0-or-later"}
|
license = {text = "GPL-2.0-or-later"}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from .gsmtap import GsmtapSender, GsmtapReceiver
|
|||||||
from .pcap import PcapWriter
|
from .pcap import PcapWriter
|
||||||
from .dump import FileDumper, format_message
|
from .dump import FileDumper, format_message
|
||||||
|
|
||||||
__version__ = '1.22.3'
|
__version__ = '1.22.4'
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'SniffSession',
|
'SniffSession',
|
||||||
'DeviceDisconnected',
|
'DeviceDisconnected',
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ class TestImportEndpoint(unittest.TestCase):
|
|||||||
class TestVersion(unittest.TestCase):
|
class TestVersion(unittest.TestCase):
|
||||||
def test_package_version(self):
|
def test_package_version(self):
|
||||||
from simtrace2_pysniff import __version__
|
from simtrace2_pysniff import __version__
|
||||||
self.assertEqual(__version__, '1.22.3')
|
self.assertEqual(__version__, '1.22.4')
|
||||||
|
|
||||||
def test_status_includes_version(self):
|
def test_status_includes_version(self):
|
||||||
import os
|
import os
|
||||||
|
|||||||
Reference in new issue
Block a user