fix: increase touch size for sensors, remove flicker on drag

This commit is contained in:
2026-05-15 16:07:42 +02:00
parent 077585bd73
commit be6ac42059
+48 -6
View File
@@ -351,7 +351,17 @@ function _onRoomDragEnd(room, group) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function renderSensors() { function renderSensors() {
sensorsLayer.destroyChildren(); const activeIds = new Set(
sensors
.filter(s => s.room_id != null && s.floor_x != null)
.map(s => `sensor-${s.id}`)
);
// Remove groups for sensors that are now unplaced or gone.
sensorsLayer.find('Group').forEach(g => {
if (!activeIds.has(g.id())) g.destroy();
});
sensors.forEach(sensor => { sensors.forEach(sensor => {
if (sensor.room_id == null || sensor.floor_x == null) return; if (sensor.room_id == null || sensor.floor_x == null) return;
const room = rooms.find(r => r.id === sensor.room_id); const room = rooms.find(r => r.id === sensor.room_id);
@@ -361,17 +371,39 @@ function renderSensors() {
const absY = (room.y + sensor.floor_y) * PPM; const absY = (room.y + sensor.floor_y) * PPM;
const label = sensor.name ?? sensor.sensor_id; const label = sensor.name ?? sensor.sensor_id;
const existing = sensorsLayer.findOne(`#sensor-${sensor.id}`);
if (existing) {
// Update in-place — avoids the destroy-rebuild flash on drag end.
if (!existing.isDragging()) existing.position({ x: absX, y: absY });
existing.draggable(mode === 'sensorMove');
existing.findOne('Text')?.text(label);
return;
}
_buildSensorGroup(sensor, absX, absY, label);
});
sensorsLayer.batchDraw();
}
function _buildSensorGroup(sensor, absX, absY, label) {
const group = new Konva.Group({ const group = new Konva.Group({
id: `sensor-${sensor.id}`, id: `sensor-${sensor.id}`,
x: absX, y: absY, x: absX, y: absY,
draggable: mode === 'sensorMove', draggable: mode === 'sensorMove',
}); });
// Visible dot — hitFunc expands the touch target without changing appearance.
group.add(new Konva.Circle({ group.add(new Konva.Circle({
radius: 8, radius: 8,
fill: '#1565C0', fill: '#1565C0',
stroke: '#ffffff', stroke: '#ffffff',
strokeWidth: 2, strokeWidth: 2,
hitFunc(ctx, shape) {
ctx.beginPath();
ctx.arc(0, 0, 20, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStrokeShape(shape);
},
})); }));
// Highlight ring — shown by highlightSensor(). // Highlight ring — shown by highlightSensor().
@@ -413,10 +445,13 @@ function renderSensors() {
clearTimeout(pressTimer); clearTimeout(pressTimer);
pressTimer = null; pressTimer = null;
}); });
group.on('dragend', () => _onSensorDragEnd(sensor, group, room)); // Look up the current sensor data at dragend so room_id is always fresh.
sensorsLayer.add(group); group.on('dragend', () => {
const s = sensors.find(ss => ss.id === sensor.id) ?? sensor;
const originalRoom = rooms.find(r => r.id === s.room_id) ?? rooms[0];
_onSensorDragEnd(s, group, originalRoom);
}); });
sensorsLayer.batchDraw(); sensorsLayer.add(group);
} }
function _onSensorDragEnd(sensor, group, originalRoom) { function _onSensorDragEnd(sensor, group, originalRoom) {
@@ -427,12 +462,19 @@ function _onSensorDragEnd(sensor, group, originalRoom) {
newAbsY >= r.y && newAbsY <= r.y + r.height, newAbsY >= r.y && newAbsY <= r.y + r.height,
) ?? originalRoom; ) ?? originalRoom;
// Optimistically update the local sensors array so any renderSensors()
// call that arrives before Flutter confirms the new position via loadSensors
// doesn't snap the group back to the old coordinates.
sensor.room_id = target.id;
sensor.floor_x = newAbsX - target.x;
sensor.floor_y = newAbsY - target.y;
notifyFlutter({ notifyFlutter({
type: 'sensorMoved', type: 'sensorMoved',
id: String(sensor.id), id: String(sensor.id),
roomId: target.id, roomId: target.id,
x: newAbsX - target.x, x: sensor.floor_x,
y: newAbsY - target.y, y: sensor.floor_y,
}); });
} }