mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-06-12 01:14:51 +02:00
Don't display blocked contacts on the map. Closes #269.
This commit is contained in:
@@ -680,6 +680,8 @@ export function App() {
|
||||
onToggleTrackedTelemetry: handleToggleTrackedTelemetry,
|
||||
repeaterAutoLoginKey,
|
||||
onClearRepeaterAutoLogin: () => setRepeaterAutoLoginKey(null),
|
||||
blockedKeys: appSettings?.blocked_keys,
|
||||
blockedNames: appSettings?.blocked_names,
|
||||
};
|
||||
const searchProps = {
|
||||
contacts,
|
||||
|
||||
@@ -92,6 +92,8 @@ interface ConversationPaneProps {
|
||||
onToggleTrackedTelemetry: (publicKey: string) => Promise<void>;
|
||||
repeaterAutoLoginKey: string | null;
|
||||
onClearRepeaterAutoLogin: () => void;
|
||||
blockedKeys?: string[];
|
||||
blockedNames?: string[];
|
||||
}
|
||||
|
||||
function LoadingPane({ label }: { label: string }) {
|
||||
@@ -171,6 +173,8 @@ export function ConversationPane({
|
||||
onToggleTrackedTelemetry,
|
||||
repeaterAutoLoginKey,
|
||||
onClearRepeaterAutoLogin,
|
||||
blockedKeys,
|
||||
blockedNames,
|
||||
}: ConversationPaneProps) {
|
||||
const [roomAuthenticated, setRoomAuthenticated] = useState(false);
|
||||
const activeContactIsRepeater = useMemo(() => {
|
||||
@@ -215,6 +219,8 @@ export function ConversationPane({
|
||||
focusedKey={activeConversation.mapFocusKey}
|
||||
rawPackets={rawPackets}
|
||||
config={config}
|
||||
blockedKeys={blockedKeys}
|
||||
blockedNames={blockedNames}
|
||||
onSelectContact={(contact) =>
|
||||
onSelectConversation({
|
||||
type: 'contact',
|
||||
|
||||
@@ -30,6 +30,8 @@ interface MapViewProps {
|
||||
focusedKey?: string | null;
|
||||
rawPackets?: RawPacket[];
|
||||
config?: RadioConfig | null;
|
||||
blockedKeys?: string[];
|
||||
blockedNames?: string[];
|
||||
/** When provided, the contact name in each popup becomes a clickable link
|
||||
* that opens the conversation for that contact (DM, repeater, or room). */
|
||||
onSelectContact?: (contact: Contact) => void;
|
||||
@@ -496,6 +498,8 @@ export function MapView({
|
||||
focusedKey,
|
||||
rawPackets,
|
||||
config,
|
||||
blockedKeys,
|
||||
blockedNames,
|
||||
onSelectContact,
|
||||
}: MapViewProps) {
|
||||
const [sevenDaysAgo] = useState(() => Date.now() / 1000 - 7 * 24 * 60 * 60);
|
||||
@@ -563,10 +567,14 @@ export function MapView({
|
||||
|
||||
// Filter contacts for map display
|
||||
const mappableContacts = useMemo(() => {
|
||||
const isBlocked = (c: Contact) =>
|
||||
(blockedKeys?.length && blockedKeys.includes(c.public_key.toLowerCase())) ||
|
||||
(blockedNames?.length && c.name != null && blockedNames.includes(c.name));
|
||||
|
||||
if (showPackets && discoveryMode) {
|
||||
// Discovery mode: only show nodes that have appeared in resolved packets
|
||||
return contacts.filter(
|
||||
(c) => isValidLocation(c.lat, c.lon) && discoveredKeys.has(c.public_key)
|
||||
(c) => isValidLocation(c.lat, c.lon) && discoveredKeys.has(c.public_key) && !isBlocked(c)
|
||||
);
|
||||
}
|
||||
if (showPackets) {
|
||||
@@ -574,12 +582,14 @@ export function MapView({
|
||||
return contacts.filter(
|
||||
(c) =>
|
||||
isValidLocation(c.lat, c.lon) &&
|
||||
!isBlocked(c) &&
|
||||
(c.public_key === focusedKey || (c.last_seen != null && c.last_seen > threeDaysAgoSec))
|
||||
);
|
||||
}
|
||||
return contacts.filter(
|
||||
(c) =>
|
||||
isValidLocation(c.lat, c.lon) &&
|
||||
!isBlocked(c) &&
|
||||
(c.public_key === focusedKey || (c.last_seen != null && c.last_seen > sevenDaysAgo))
|
||||
);
|
||||
}, [
|
||||
@@ -590,6 +600,8 @@ export function MapView({
|
||||
showPackets,
|
||||
discoveryMode,
|
||||
discoveredKeys,
|
||||
blockedKeys,
|
||||
blockedNames,
|
||||
]);
|
||||
|
||||
// Resolve a path of hop tokens to geographic waypoints (only unambiguous + has GPS)
|
||||
|
||||
@@ -172,4 +172,104 @@ describe('MapView', () => {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('excludes contacts whose public key is in blockedKeys', () => {
|
||||
const visible: Contact = {
|
||||
public_key: 'aa'.repeat(32),
|
||||
name: 'Visible',
|
||||
type: 1,
|
||||
flags: 0,
|
||||
direct_path: null,
|
||||
direct_path_len: -1,
|
||||
direct_path_hash_mode: -1,
|
||||
route_override_path: null,
|
||||
route_override_len: null,
|
||||
route_override_hash_mode: null,
|
||||
last_advert: null,
|
||||
lat: 40,
|
||||
lon: -74,
|
||||
last_seen: Math.floor(Date.now() / 1000),
|
||||
on_radio: false,
|
||||
favorite: false,
|
||||
last_contacted: null,
|
||||
last_read_at: null,
|
||||
first_seen: null,
|
||||
};
|
||||
const blocked: Contact = {
|
||||
public_key: 'bb'.repeat(32),
|
||||
name: 'Blocked',
|
||||
type: 2,
|
||||
flags: 0,
|
||||
direct_path: null,
|
||||
direct_path_len: -1,
|
||||
direct_path_hash_mode: -1,
|
||||
route_override_path: null,
|
||||
route_override_len: null,
|
||||
route_override_hash_mode: null,
|
||||
last_advert: null,
|
||||
lat: 41,
|
||||
lon: -73,
|
||||
last_seen: Math.floor(Date.now() / 1000),
|
||||
on_radio: false,
|
||||
favorite: false,
|
||||
last_contacted: null,
|
||||
last_read_at: null,
|
||||
first_seen: null,
|
||||
};
|
||||
|
||||
render(<MapView contacts={[visible, blocked]} blockedKeys={['bb'.repeat(32)]} />);
|
||||
|
||||
expect(screen.getByText('Visible')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Blocked')).toBeNull();
|
||||
});
|
||||
|
||||
it('excludes contacts whose name is in blockedNames', () => {
|
||||
const visible: Contact = {
|
||||
public_key: 'aa'.repeat(32),
|
||||
name: 'Visible',
|
||||
type: 1,
|
||||
flags: 0,
|
||||
direct_path: null,
|
||||
direct_path_len: -1,
|
||||
direct_path_hash_mode: -1,
|
||||
route_override_path: null,
|
||||
route_override_len: null,
|
||||
route_override_hash_mode: null,
|
||||
last_advert: null,
|
||||
lat: 40,
|
||||
lon: -74,
|
||||
last_seen: Math.floor(Date.now() / 1000),
|
||||
on_radio: false,
|
||||
favorite: false,
|
||||
last_contacted: null,
|
||||
last_read_at: null,
|
||||
first_seen: null,
|
||||
};
|
||||
const blocked: Contact = {
|
||||
public_key: 'cc'.repeat(32),
|
||||
name: 'BadActor',
|
||||
type: 2,
|
||||
flags: 0,
|
||||
direct_path: null,
|
||||
direct_path_len: -1,
|
||||
direct_path_hash_mode: -1,
|
||||
route_override_path: null,
|
||||
route_override_len: null,
|
||||
route_override_hash_mode: null,
|
||||
last_advert: null,
|
||||
lat: 41,
|
||||
lon: -73,
|
||||
last_seen: Math.floor(Date.now() / 1000),
|
||||
on_radio: false,
|
||||
favorite: false,
|
||||
last_contacted: null,
|
||||
last_read_at: null,
|
||||
first_seen: null,
|
||||
};
|
||||
|
||||
render(<MapView contacts={[visible, blocked]} blockedNames={['BadActor']} />);
|
||||
|
||||
expect(screen.getByText('Visible')).toBeInTheDocument();
|
||||
expect(screen.queryByText('BadActor')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user