feat(ux): clearer chat delivery, explorer empty/range states, honest settings label
Three next-batch UX-audit fixes:
- Chat delivery: the sending/sent glyph has higher contrast and a tooltip
("Sent to the network — arrives after it confirms", so a check isn't mistaken
for "delivered"); a failed send now carries the real reason (ChatMessage::
fail_reason, set from onChatBroadcastResult via friendlyRpcError, in-memory
only) in the "not sent" hover tooltip.
- Explorer: a block height beyond the tip says so ("Block N is beyond the chain
tip (M)") instead of silently snapping to the top; the empty block list shows
Not connected / Syncing (N behind) / Loading instead of an endless "Loading".
- Settings: the misleading "Reset to Defaults" button (which only reloads the
last-saved values) is relabeled "Discard unsaved changes" with accurate copy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,9 @@ struct ChatMessage {
|
||||
std::string body; // decrypted plaintext (Message) or request text (ContactRequest)
|
||||
std::int64_t timestamp = 0; // tx time in seconds; set by the ingesting caller
|
||||
std::size_t payload_position = 0; // together with txid, the dedup key
|
||||
ChatDelivery delivery = ChatDelivery::Sent; // outgoing only
|
||||
ChatDelivery delivery = ChatDelivery::Sent; // outgoing only. Sent = broadcast to the network (not
|
||||
// necessarily confirmed/delivered yet).
|
||||
std::string fail_reason; // outgoing Failed only; in-memory, NOT persisted
|
||||
};
|
||||
|
||||
} // namespace dragonx::chat
|
||||
|
||||
@@ -189,8 +189,8 @@ bool ChatService::recordOutgoingPending(const ChatMessage& message) {
|
||||
return appended;
|
||||
}
|
||||
|
||||
void ChatService::resolveOutgoing(const std::string& txid, ChatDelivery delivery) {
|
||||
const ChatMessage* updated = store_.updateDelivery(txid, delivery);
|
||||
void ChatService::resolveOutgoing(const std::string& txid, ChatDelivery delivery, const std::string& reason) {
|
||||
const ChatMessage* updated = store_.updateDelivery(txid, delivery, reason);
|
||||
if (updated && db_) db_->upsert(*updated); // overwrite the Sending row with the final status
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
// quit), then resolveOutgoing() upserts the final status once the broadcast completes. A stray
|
||||
// persisted Sending (crash mid-broadcast) loads back as Sent.
|
||||
bool recordOutgoingPending(const ChatMessage& message);
|
||||
void resolveOutgoing(const std::string& txid, ChatDelivery delivery);
|
||||
void resolveOutgoing(const std::string& txid, ChatDelivery delivery, const std::string& reason = {});
|
||||
|
||||
const ChatStore& store() const { return store_; }
|
||||
ChatStore& store() { return store_; }
|
||||
|
||||
@@ -61,10 +61,12 @@ std::vector<ChatMessage> ChatStore::conversation(const std::string& conversation
|
||||
return out;
|
||||
}
|
||||
|
||||
const ChatMessage* ChatStore::updateDelivery(const std::string& txid, ChatDelivery delivery) {
|
||||
const ChatMessage* ChatStore::updateDelivery(const std::string& txid, ChatDelivery delivery,
|
||||
const std::string& reason) {
|
||||
for (auto& message : messages_) {
|
||||
if (message.txid == txid) {
|
||||
message.delivery = delivery;
|
||||
message.fail_reason = (delivery == ChatDelivery::Failed) ? reason : std::string();
|
||||
++revision_;
|
||||
return &message;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ public:
|
||||
|
||||
// Update an outgoing echo's delivery status by its local txid. Returns a pointer to the updated
|
||||
// message (for the caller to persist), or nullptr if no message has that txid.
|
||||
const ChatMessage* updateDelivery(const std::string& txid, ChatDelivery delivery);
|
||||
const ChatMessage* updateDelivery(const std::string& txid, ChatDelivery delivery,
|
||||
const std::string& reason = {});
|
||||
|
||||
// Distinct conversation ids, in first-seen order.
|
||||
std::vector<std::string> conversationIds() const;
|
||||
|
||||
Reference in New Issue
Block a user