Skip to content

Commit be5cd47

Browse files
committed
Add NMEA type and channel filters with a filter dialog, soften chart lines and fix dark mode contrast
1 parent 3462cfc commit be5cd47

7 files changed

Lines changed: 6542 additions & 6249 deletions

File tree

Source/Application/WebDB.cpp

Lines changed: 6267 additions & 6168 deletions
Large diffs are not rendered by default.

Source/DSP/Decoder/V2/V2Engine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ namespace V2
258258

259259
Engine::Engine() : filter17(Filters::Coherent.data()), filter37(Filters::Receiver.data())
260260
{
261-
memset(raw, 0, sizeof raw);
261+
for (int i = 0; i < 2 * BLOCK_SIZE; i++)
262+
raw[i] = CFLOAT32(0.0f, 0.0f);
262263
}
263264

264265
bool Engine::midWins(const CFLOAT32 *input) const

frontend/src/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,8 +776,10 @@ <h5 class="st-title">Custom Track Colors</h5>
776776
<div class="realtime-viewer">
777777
<div class="realtime-tabs">
778778
<div class="realtime-spacer"></div>
779-
<button class="realtime-control-btn" data-action="promptFilterMMSI" title="Filter by MMSI">
779+
<button id="realtime_filter_button" class="realtime-control-btn"
780+
data-action="openRealtimeFilters" title="Filters">
780781
<span class="filter_alt_icon"></span>
782+
<span id="realtime_filter_count" class="realtime-filter-count"></span>
781783
</button>
782784
<label class="realtime-background-toggle" title="Keep streaming when tab is hidden">
783785
<input type="checkbox" id="realtime_background_streaming"

frontend/src/script.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ const ACTIONS = {
202202
toggleGraphVisibility: (e, d) => toggleGraphVisibility(d.graph),
203203

204204
// realtime / decoder controls
205-
promptFilterMMSI: () => realtimeModule?.promptFilter(),
205+
openRealtimeFilters: () => realtimeModule?.openFilters(),
206+
addRealtimeFilter: () => realtimeModule?.addFilterFromInput(),
207+
clearRealtimeFilters: () => realtimeModule?.clearFilters(),
208+
realtimeFilterKindChanged: () => realtimeModule?.filterKindChanged(),
206209
toggleBackgroundStreaming: () => realtimeModule?.toggleBackgroundStreaming(),
207210
toggleRealtimePause: () => realtimeModule?.togglePause(),
208211
clearRealtimeTable: () => realtimeModule?.clear(),
@@ -249,7 +252,7 @@ const ACTIONS = {
249252
techInfo: (e) => { e.stopPropagation(); toggleShipcardPopover("tech_popover", "shipcard_tech_info"); },
250253
shiptypeInfo: (e) => { e.stopPropagation(); toggleShipcardPopover("shiptype_popover", "shipcard_shiptype_info"); },
251254
showNMEAContextCopy: (e, d) => showContextMenu(e, d.copy || '', 'ship', ['settings', 'copy-text']),
252-
removeRealtimeFilterMMSI: (e, d) => realtimeModule?.removeFilter(d.mmsi),
255+
removeRealtimeFilter: (e, d) => realtimeModule?.removeFilter(d.kind, d.value),
253256
};
254257

255258
// Public plugin API. Mutable state uses getters so plugins always see the
@@ -503,7 +506,7 @@ function restoreDefaultSettings() {
503506
kiosk_pan_map: true,
504507
shiptable_columns: ["shipname", "mmsi", "imo", "callsign", "shipclass", "lat", "lon", "last_signal", "level", "distance", "bearing", "speed", "repeat", "ppm", "status"],
505508
realtime_background_streaming: false,
506-
realtime_filter_mmsis: [],
509+
realtime_filters: [],
507510
binary_messages: "highlight",
508511
binary_exclude: []
509512
});
@@ -3466,8 +3469,8 @@ function saveSettings() {
34663469
settings.shipcard_rows = selectedRows;
34673470
settings.activeReceiver = activeReceiver;
34683471

3469-
const filters = realtimeModule?.getFilterMMSIs();
3470-
if (filters !== null && filters !== undefined) settings.realtime_filter_mmsis = filters;
3472+
const filters = realtimeModule?.getFilters();
3473+
if (filters !== null && filters !== undefined) settings.realtime_filters = filters;
34713474
const bg = realtimeModule?.getBackgroundStreaming();
34723475
if (bg !== null && bg !== undefined) settings.realtime_background_streaming = bg;
34733476

frontend/src/style.css

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,11 @@ td {
18001800
overflow: hidden;
18011801
}
18021802

1803+
.dark #dialog-box {
1804+
border: 1px solid var(--hdr-border);
1805+
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.7);
1806+
}
1807+
18031808
.dialog-header {
18041809
display: flex;
18051810
align-items: center;
@@ -3969,6 +3974,90 @@ td {
39693974
flex: 1;
39703975
}
39713976

3977+
.realtime-filter-input {
3978+
padding: 0.35rem 0.5rem;
3979+
background: var(--panel-color);
3980+
border: 1px solid var(--menu-border-color);
3981+
border-radius: 3px;
3982+
color: var(--menu-font-color);
3983+
font-size: 0.9rem;
3984+
font-family: inherit;
3985+
}
3986+
3987+
.realtime-filter-row {
3988+
display: flex;
3989+
gap: 0.5rem;
3990+
align-items: center;
3991+
}
3992+
3993+
.realtime-filter-row .realtime-filter-input:nth-child(2) {
3994+
flex: 1;
3995+
}
3996+
3997+
.realtime-filter-add,
3998+
.realtime-filter-clear {
3999+
padding: 0.35rem 0.9rem;
4000+
background: var(--panel-color);
4001+
border: 1px solid var(--menu-border-color);
4002+
border-radius: 3px;
4003+
color: var(--menu-font-color);
4004+
font-size: 0.9rem;
4005+
font-family: inherit;
4006+
cursor: pointer;
4007+
}
4008+
4009+
.realtime-filter-add:hover,
4010+
.realtime-filter-clear:hover {
4011+
border-color: var(--menu-font-color);
4012+
}
4013+
4014+
.realtime-filter-active {
4015+
display: flex;
4016+
align-items: flex-start;
4017+
gap: 0.75rem;
4018+
margin-top: 1rem;
4019+
}
4020+
4021+
.realtime-filter-active .filter-chips {
4022+
display: flex;
4023+
flex-wrap: wrap;
4024+
gap: 0.4rem;
4025+
flex: 1;
4026+
}
4027+
4028+
.realtime-filter-none,
4029+
.realtime-filter-hint {
4030+
margin-top: 1rem;
4031+
opacity: 0.6;
4032+
font-size: 0.85rem;
4033+
}
4034+
4035+
.realtime-control-btn span.realtime-filter-count {
4036+
display: none;
4037+
position: absolute;
4038+
top: 3px;
4039+
right: 1px;
4040+
min-width: 15px;
4041+
height: 15px;
4042+
padding: 0 3px;
4043+
border-radius: 8px;
4044+
font-size: 10px;
4045+
font-weight: 600;
4046+
}
4047+
4048+
.realtime-control-btn.active span.realtime-filter-count {
4049+
display: flex;
4050+
background: var(--accent);
4051+
color: var(--panel-color);
4052+
}
4053+
4054+
.filter-chip-kind {
4055+
opacity: 0.6;
4056+
font-size: 0.75rem;
4057+
text-transform: uppercase;
4058+
letter-spacing: 0.02em;
4059+
}
4060+
39724061
.filter-chip {
39734062
display: inline-flex;
39744063
align-items: center;
@@ -4030,6 +4119,7 @@ td {
40304119
}
40314120

40324121
.realtime-control-btn {
4122+
position: relative;
40334123
padding: 0.6rem;
40344124
background: transparent;
40354125
border: none;
@@ -4207,6 +4297,24 @@ td {
42074297
background-color: #3a3a3a;
42084298
}
42094299

4300+
.dark .channel-box.active {
4301+
background-color: var(--accent);
4302+
color: var(--panel-color);
4303+
}
4304+
4305+
.nmea-mmsi {
4306+
display: inline-block;
4307+
padding: 2px 6px;
4308+
border: 1px solid #d0d0d0;
4309+
border-radius: 3px;
4310+
cursor: pointer;
4311+
font-size: 0.85em;
4312+
}
4313+
4314+
.dark .nmea-mmsi {
4315+
border-color: var(--menu-divider-color);
4316+
}
4317+
42104318
.aiscatcher-logo-control {
42114319
background: rgba(0, 0, 0, 0.1) !important;
42124320
backdrop-filter: blur(3px);

frontend/src/tabs/plots.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ function cloneChartConfig(config) {
6969
}
7070

7171
const FILL_ALPHA = 0.3;
72+
const BAR_ALPHA = 0.45;
7273

7374
function withAlpha(color, alpha) {
7475
const hex = color.replace("#", "");
@@ -79,10 +80,12 @@ function withAlpha(color, alpha) {
7980
}
8081

8182
function updateChartColors(c, colorVariables) {
83+
const bars = c.config.type === "bar";
8284
c.data.datasets.forEach((dataset, index) => {
8385
const color = cssvar(colorVariables[index]);
8486
dataset.borderColor = color;
85-
dataset.backgroundColor = dataset.fill ? withAlpha(color, FILL_ALPHA) : color;
87+
if (bars) dataset.backgroundColor = withAlpha(color, BAR_ALPHA);
88+
else dataset.backgroundColor = dataset.fill ? withAlpha(color, FILL_ALPHA) : color;
8689
});
8790
const ink = cssvar("--chart-color");
8891
const grid = cssvar("--chart-grid-color");
@@ -259,11 +262,11 @@ const plot_count = {
259262
type: "scatter",
260263
data: {
261264
datasets: [
262-
{ label: "Vessel Count", data: [], type: "line", showLine: true, fill: false, pointStyle: false, borderWidth: 2, yAxisID: 'y_right' },
263-
{ label: "Class A", data: [], showLine: true, fill: "origin", borderWidth: 2, pointStyle: false },
264-
{ label: "Class B", data: [], showLine: true, fill: "-1", borderWidth: 2, pointStyle: false },
265-
{ label: "Base Station", data: [], showLine: true, fill: "-1", borderWidth: 2, pointStyle: false },
266-
{ label: "Other", data: [], showLine: true, fill: "-1", borderWidth: 2, pointStyle: false },
265+
{ label: "Vessel Count", data: [], type: "line", showLine: true, fill: false, pointStyle: false, borderWidth: 1.5, yAxisID: 'y_right' },
266+
{ label: "Class A", data: [], showLine: true, fill: "origin", borderWidth: 1, pointStyle: false },
267+
{ label: "Class B", data: [], showLine: true, fill: "-1", borderWidth: 1, pointStyle: false },
268+
{ label: "Base Station", data: [], showLine: true, fill: "-1", borderWidth: 1, pointStyle: false },
269+
{ label: "Other", data: [], showLine: true, fill: "-1", borderWidth: 1, pointStyle: false },
267270
],
268271
},
269272
options: graph_options_count,
@@ -363,7 +366,7 @@ const plot_gain = {
363366
type: "bar",
364367
data: {
365368
datasets: [
366-
{ label: "Gain", data: [], borderWidth: 0 },
369+
{ label: "Gain", data: [], borderWidth: 1 },
367370
],
368371
},
369372
options: {

0 commit comments

Comments
 (0)