mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-05-02 11:32:35 +02:00
fix(chat): prevent poll-triggered reload after send by using server timestamp
The 60s checkForUpdates poll was detecting has_updates due to clock skew between client and server timestamps. Now the send API returns the server timestamp, and the frontend uses it for markChannelAsRead — ensuring the poll sees no updates for own sent messages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1252,7 +1252,7 @@ class DeviceManager:
|
||||
'id': msg_id,
|
||||
}, namespace='/chat')
|
||||
|
||||
return {'success': True, 'message': 'Message sent', 'id': msg_id}
|
||||
return {'success': True, 'message': 'Message sent', 'id': msg_id, 'timestamp': ts}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send channel message: {e}")
|
||||
|
||||
@@ -60,20 +60,17 @@ def recv_messages() -> Tuple[bool, str]:
|
||||
return True, "Messages are received automatically via events"
|
||||
|
||||
|
||||
def send_message(text: str, reply_to: Optional[str] = None, channel_index: int = 0) -> Tuple[bool, str, Optional[int]]:
|
||||
"""Send a message to a channel. Returns (success, message, msg_id)."""
|
||||
def send_message(text: str, reply_to: Optional[str] = None, channel_index: int = 0) -> Dict:
|
||||
"""Send a message to a channel. Returns result dict with id and timestamp."""
|
||||
if reply_to:
|
||||
text = f"@[{reply_to}] {text}"
|
||||
|
||||
try:
|
||||
dm = _get_dm()
|
||||
result = dm.send_channel_message(channel_index, text)
|
||||
if result['success']:
|
||||
return True, result.get('message', 'Message sent'), result.get('id')
|
||||
return False, result.get('error', 'Failed to send message'), None
|
||||
return dm.send_channel_message(channel_index, text)
|
||||
except Exception as e:
|
||||
logger.error(f"send_message error: {e}")
|
||||
return False, str(e), None
|
||||
return {'success': False, 'error': str(e)}
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -601,21 +601,22 @@ def send_message():
|
||||
channel_idx = data.get('channel_idx', 0)
|
||||
|
||||
# Send message via meshcli
|
||||
success, message, msg_id = cli.send_message(text, reply_to=reply_to, channel_index=channel_idx)
|
||||
result = cli.send_message(text, reply_to=reply_to, channel_index=channel_idx)
|
||||
|
||||
if success:
|
||||
if result['success']:
|
||||
# v2: Echo tracking is handled automatically by DeviceManager events
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Message sent successfully',
|
||||
'channel_idx': channel_idx,
|
||||
'id': msg_id,
|
||||
'id': result.get('id'),
|
||||
'timestamp': result.get('timestamp'),
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': message
|
||||
'error': result.get('error', 'Failed to send message')
|
||||
}), 500
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@@ -1325,6 +1325,10 @@ async function sendMessage() {
|
||||
const wrapper = document.querySelector(`.message-wrapper[data-msg-id="${optimisticId}"]`);
|
||||
if (wrapper) wrapper.dataset.msgId = data.id;
|
||||
}
|
||||
// Use server timestamp to prevent poll-triggered reload due to clock skew
|
||||
if (data.timestamp) {
|
||||
markChannelAsRead(currentChannelIdx, data.timestamp);
|
||||
}
|
||||
} else {
|
||||
showNotification('Failed to send: ' + data.error, 'danger');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user