HotFixPerformance

This commit is contained in:
pe1hvh
2026-03-12 13:15:58 +01:00
parent 794f08c780
commit c30eb5a467
5 changed files with 193 additions and 112 deletions
+2 -2
View File
@@ -25,7 +25,7 @@ from typing import Any, Dict, List
# ==============================================================================
VERSION: str = "1.13.2"
VERSION: str = "1.13.3"
# ==============================================================================
@@ -293,7 +293,7 @@ CHANNEL_CACHE_ENABLED: bool = False
# Fixed device name applied when the BOT checkbox is enabled.
# The original device name is saved and restored when BOT is disabled.
BOT_DEVICE_NAME: str = "NL-OV-ZWL-STDSHGN-WKC Bot"
BOT_DEVICE_NAME: str = "ZwolsBotje"
# Default device name used as fallback when restoring from BOT mode
# and no original name was saved (e.g. after a restart).
+146 -62
View File
@@ -677,34 +677,17 @@ class DashboardPage:
container.set_visibility(pid == panel_id)
self._active_panel = panel_id
# Apply channel filter to messages panel
if panel_id == 'messages' and self._messages:
self._messages.set_active_channel(channel)
# Force immediate rebuild so the panel is populated the
# moment it becomes visible, instead of waiting for the
# next 500 ms timer tick (which caused the "empty on first
# click, populated on second click" symptom).
data = self._shared.get_snapshot()
self._messages.update(
data,
self._messages.channel_filters,
self._messages.last_channels,
room_pubkeys=(
self._room_server.get_room_pubkeys()
if self._room_server else None
),
)
# Apply channel filter to archive panel
if panel_id == 'archive' and self._archive_page:
self._archive_page.set_channel_filter(channel)
# Force map recenter when opening map panel (Leaflet may be hidden on load)
if panel_id == 'map' and self._map:
data = self._shared.get_snapshot()
data['force_center'] = True
self._map.update(data)
<<<<<<< HEAD
=======
self._refresh_active_panel_now(force_map_center=(panel_id == 'map'))
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
# Update active menu highlight (standalone buttons only)
for pid, btn in self._menu_buttons.items():
if pid == panel_id:
@@ -712,10 +695,89 @@ class DashboardPage:
else:
btn.classes(remove='domca-menu-active')
# Refresh only the selected panel immediately so the user does not
# need to wait for the next 500 ms dashboard tick.
self._refresh_active_panel_now()
# Close drawer after selection
if self._drawer:
self._drawer.hide()
<<<<<<< HEAD
def _refresh_active_panel_now(self) -> None:
"""Refresh exactly the active panel once, outside the timer tick."""
data = self._shared.get_snapshot()
if self._active_panel == 'device' and self._device:
self._device.update(data)
elif self._active_panel == 'map' and self._map:
data = dict(data)
data['force_center'] = True
self._map.update(data)
elif self._active_panel == 'actions' and self._actions:
self._actions.update(data)
elif self._active_panel == 'contacts' and self._contacts:
self._contacts.update(data)
elif self._active_panel == 'messages' and self._messages:
if data.get('channels'):
self._messages.update_filters(data)
self._messages.update_channel_options(data['channels'])
self._update_submenus(data)
=======
def _refresh_active_panel_now(self, force_map_center: bool = False) -> None:
"""Refresh only the currently visible panel.
This is used directly after a panel switch so the user does not
need to wait for the next 500 ms dashboard tick.
"""
data = self._shared.get_snapshot()
if data.get('channels'):
self._messages.update_filters(data)
self._messages.update_channel_options(data['channels'])
self._update_submenus(data)
if self._active_panel == 'device':
self._device.update(data)
elif self._active_panel == 'map':
if force_map_center:
data['force_center'] = True
self._map.update(data)
elif self._active_panel == 'actions':
self._actions.update(data)
elif self._active_panel == 'contacts':
self._contacts.update(data)
elif self._active_panel == 'messages':
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
self._messages.update(
data,
self._messages.channel_filters,
self._messages.last_channels,
<<<<<<< HEAD
room_pubkeys=self._room_server.get_room_pubkeys() if self._room_server else None,
)
elif self._active_panel == 'rooms' and self._room_server:
if data.get('channels'):
self._messages.update_filters(data)
self._messages.update_channel_options(data['channels'])
self._update_submenus(data)
self._room_server.update(data)
elif self._active_panel == 'rxlog' and self._rxlog:
self._rxlog.update(data)
elif self._active_panel == 'archive' and self._archive_page:
self._archive_page.refresh()
=======
room_pubkeys=(
self._room_server.get_room_pubkeys()
if self._room_server else None
),
)
elif self._active_panel == 'rooms':
self._room_server.update(data)
elif self._active_panel == 'rxlog':
self._rxlog.update(data)
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
# ------------------------------------------------------------------
# Room Server callback (from ContactsPanel)
# ------------------------------------------------------------------
@@ -753,56 +815,78 @@ class DashboardPage:
# Always update status
self._status_label.text = data['status']
# Device info
if data['device_updated'] or is_first:
self._device.update(data)
# Map: always send a snapshot while the panel is active.
# The JS runtime coalesces pending payloads — only the newest
# is ever applied — so calling update() on every tick is cheap.
# This ensures the Leaflet runtime always gets at least one
# valid snapshot after it finishes loading, regardless of
# whether device_updated or is_first happened to be True
# on the tick that fired before MeshCoreLeafletBoot was defined.
if self._active_panel == 'map':
self._map.update(data)
# Channel-dependent UI: always ensure consistency when
# channels exist. Because a single DashboardPage instance
# is shared across browser sessions (render() is called on
# each new connection), the old session's timer can steal
# the is_first flag before the new timer fires. Running
# these unconditionally is safe because each method has an
# internal fingerprint/equality check that prevents
# unnecessary DOM updates.
<<<<<<< HEAD
# Channel-dependent navigation/filter state remains global, but
# expensive panel refreshes must only run for the active panel.
=======
# Channel-dependent drawer/submenu state may stay global.
# The helpers below already contain equality checks, so this
# remains cheap while keeping navigation consistent.
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
if data['channels']:
self._messages.update_filters(data)
self._messages.update_channel_options(data['channels'])
self._update_submenus(data)
# BOT checkbox state (only on actual change or first render
# to avoid overwriting user interaction mid-toggle)
if data['channels_updated'] or is_first:
self._actions.update(data)
if self._active_panel == 'device':
if data['device_updated'] or is_first:
self._device.update(data)
<<<<<<< HEAD
elif self._active_panel == 'map':
self._map.update(data)
elif self._active_panel == 'actions':
if data['channels_updated'] or is_first:
self._actions.update(data)
elif self._active_panel == 'contacts':
if data['contacts_updated'] or is_first:
self._contacts.update(data)
=======
# Contacts
if data['contacts_updated'] or is_first:
self._contacts.update(data)
elif self._active_panel == 'map':
# Keep sending snapshots while the map panel is active.
# The browser runtime coalesces pending payloads, so only
# the newest snapshot is applied.
self._map.update(data)
# Messages (always — for live filter changes)
self._messages.update(
data,
self._messages.channel_filters,
self._messages.last_channels,
room_pubkeys=self._room_server.get_room_pubkeys() if self._room_server else None,
)
elif self._active_panel == 'actions':
if data['channels_updated'] or is_first:
self._actions.update(data)
# Room Server panels (always — for live messages + contact changes)
self._room_server.update(data)
elif self._active_panel == 'contacts':
if data['contacts_updated'] or is_first:
self._contacts.update(data)
# RX Log
if data['rxlog_updated']:
self._rxlog.update(data)
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
elif self._active_panel == 'messages':
self._messages.update(
data,
self._messages.channel_filters,
self._messages.last_channels,
<<<<<<< HEAD
room_pubkeys=self._room_server.get_room_pubkeys() if self._room_server else None,
)
elif self._active_panel == 'rooms':
self._room_server.update(data)
elif self._active_panel == 'rxlog':
if data['rxlog_updated'] or is_first:
self._rxlog.update(data)
elif self._active_panel == 'archive' and self._archive_page:
if data.get('messages_updated') or data.get('channels_updated') or is_first:
self._archive_page.refresh()
=======
room_pubkeys=(
self._room_server.get_room_pubkeys()
if self._room_server else None
),
)
elif self._active_panel == 'rooms':
self._room_server.update(data)
elif self._active_panel == 'rxlog':
if data['rxlog_updated'] or is_first:
self._rxlog.update(data)
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
# Signal worker that GUI is ready for data
if is_first and data['channels'] and data['contacts']:
-1
View File
@@ -48,7 +48,6 @@ class MapPanel:
ui.element('div').props(f'id={self._container_id}').classes(
'meshcore-leaflet-host w-full h-72'
)
self._dispatch_to_browser(snapshot={'__command__': 'ensure_map'})
self._apply_theme_only()
def set_ui_dark_mode(self, value: bool | None) -> None:
+12
View File
@@ -634,6 +634,18 @@
}
}
<<<<<<< HEAD
const hasSnapshotWork = Boolean(current.snapshot);
const hasLiveMap = maps.has(containerId);
if (!hasSnapshotWork && !hasLiveMap) {
=======
if (!current.snapshot && current.theme && !maps.has(containerId)) {
pending.set(containerId, current);
>>>>>>> b76eacf1119026c49c25d2811a6d713da8f8e01b
return;
}
pending.set(containerId, current);
scheduleProcess(containerId, 0);
};