From 33fd7dd09bf5054a2310a507c3782684c870c3ed Mon Sep 17 00:00:00 2001 From: pepper <3782201+rohvani@users.noreply.github.com> Date: Mon, 31 Aug 2026 14:03:34 -0400 Subject: Replay IM transcripts without blank frames Detach chat-owned inline views before clearing and rebuild the transcript synchronously so an empty editor never reaches draw. Track notification panels as concurrent instances while deferred deletion overlaps old and replacement projections. Route offer updates to the live IM panel and ignore retiring friendship panels during deduplication. Validated with the RelWithDebInfo secondlife-bin build and the existing LLInstanceTracker test suite. --- indra/newview/llimprocessing.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview/llimprocessing.cpp') diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 9ba939d35b..eee44b7ae0 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1453,7 +1453,10 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, for (auto& panel : LLToastNotifyPanel::instance_snapshot()) { const std::string& notification_name = panel.getNotificationName(); - if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled()) + // Panels pending deferred deletion no longer suppress a live offer. + if (!panel.isDead() + && notification_name == "OfferFriendship" + && panel.isControlPanelEnabled()) { add_notification = false; break; -- cgit v1.3 From 38635da94eb5e7f2356305ffd38567199e65528f Mon Sep 17 00:00:00 2001 From: pepper <3782201+rohvani@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:18:17 -0400 Subject: Scope friendship offer deduplication by sender Treat an existing actionable friendship panel as a duplicate only when its notification belongs to the same resident. This preserves same-sender suppression and dead-panel replay behavior while allowing simultaneous offline requests from different residents to render in their own sessions. Validated with the RelWithDebInfo secondlife-bin build. --- indra/newview/llchathistory.cpp | 8 +++++--- indra/newview/llimprocessing.cpp | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'indra/newview/llimprocessing.cpp') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 3af23d2af3..8db072b445 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -1533,16 +1533,18 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL bool create_toast = true; if (notification->getName() == "OfferFriendship") { - // We don't want multiple friendship offers to appear, this code checks if there are previous offers - // by iterating though all panels. - // Note: it might be better to simply add a "pending offer" flag somewhere + // Keep one actionable offer per sender without hiding requests from other residents. + const LLUUID from_id = notification->getPayload()["from_id"].asUUID(); for (auto& panel : LLToastNotifyPanel::instance_snapshot()) { LLIMToastNotifyPanel * imtoastp = dynamic_cast(&panel); const std::string& notification_name = panel.getNotificationName(); + LLNotificationPtr panel_notification = LLNotificationsUtil::find(panel.getID()); // A synchronous transcript replay replaces panels already queued for deletion. if (!panel.isDead() && notification_name == "OfferFriendship" + && panel_notification + && panel_notification->getPayload()["from_id"].asUUID() == from_id && panel.isControlPanelEnabled() && imtoastp) { diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index eee44b7ae0..bd5a2cddee 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1453,9 +1453,12 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, for (auto& panel : LLToastNotifyPanel::instance_snapshot()) { const std::string& notification_name = panel.getNotificationName(); - // Panels pending deferred deletion no longer suppress a live offer. + LLNotificationPtr panel_notification = LLNotificationsUtil::find(panel.getID()); + // Only a live actionable offer from this sender makes the packet a duplicate. if (!panel.isDead() && notification_name == "OfferFriendship" + && panel_notification + && panel_notification->getPayload()["from_id"].asUUID() == from_id && panel.isControlPanelEnabled()) { add_notification = false; -- cgit v1.3