fix(chat): un-hide on lite receives + scope the contact picker per wallet
Review of fc414ee found two issues:
- HIGH: the lite variant harvests chat via ingestLiteChatMemos, which called
ingest() without the newIncomingCids out-param — so the un-hide never ran and a
hidden conversation stayed hidden PERMANENTLY on new messages (chat is default-ON
and fully supported in Lite), breaking the "a new message brings it back"
invariant. Wire the same un-hide + off-tab toast into the lite path.
- LOW: the new-conversation contact picker listed every z-address contact,
ignoring the per-wallet scope the Contacts tab enforces — leaking another
wallet's scoped contact into this wallet's picker. Apply the same scope test
(global + legacy fail open; "w:" scopes match the active wallet).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3147,7 +3147,22 @@ void App::ingestLiteChatMemos(const wallet::LiteWalletAppRefreshModel& model)
|
|||||||
auto extracted = chat::extractHushChatTransactionMetadata(entry.second, true);
|
auto extracted = chat::extractHushChatTransactionMetadata(entry.second, true);
|
||||||
for (auto& meta : extracted.metadata) metadata.push_back(std::move(meta));
|
for (auto& meta : extracted.metadata) metadata.push_back(std::move(meta));
|
||||||
}
|
}
|
||||||
if (!metadata.empty()) chat_service_.ingest(metadata, txTimestamps, std::time(nullptr));
|
if (!metadata.empty()) {
|
||||||
|
std::vector<std::string> newChatCids;
|
||||||
|
chat_service_.ingest(metadata, txTimestamps, std::time(nullptr), &newChatCids);
|
||||||
|
// Mirror the full-node paths: a new incoming message un-hides a hidden conversation (you can't
|
||||||
|
// un-receive), and a non-muted new message toasts when we're off the Chat tab.
|
||||||
|
if (settings_) {
|
||||||
|
bool unhid = false;
|
||||||
|
for (const auto& cid : newChatCids)
|
||||||
|
if (settings_->isChatHidden(cid)) { settings_->setChatHidden(cid, false); unhid = true; }
|
||||||
|
if (unhid) settings_->save();
|
||||||
|
}
|
||||||
|
if (current_page_ != ui::NavPage::Chat &&
|
||||||
|
std::any_of(newChatCids.begin(), newChatCids.end(),
|
||||||
|
[this](const std::string& cid){ return !(settings_ && settings_->isChatMuted(cid)); }))
|
||||||
|
ui::Notifications::instance().info(TR("chat_new_message_toast"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool App::lockLiteWallet()
|
bool App::lockLiteWallet()
|
||||||
|
|||||||
@@ -635,9 +635,15 @@ void RenderChatTab(App* app)
|
|||||||
// Selecting one fills the field above (manual paste still works).
|
// Selecting one fills the field above (manual paste still works).
|
||||||
ImGui::SetNextItemWidth(fieldW);
|
ImGui::SetNextItemWidth(fieldW);
|
||||||
if (ImGui::BeginCombo("##newzpick", TR("chat_pick_contact"), ImGuiComboFlags_HeightLarge)) {
|
if (ImGui::BeginCombo("##newzpick", TR("chat_pick_contact"), ImGuiComboFlags_HeightLarge)) {
|
||||||
|
const std::string activeHash = app->activeWalletScopeId(); // per-wallet contact scope
|
||||||
int shown = 0;
|
int shown = 0;
|
||||||
for (const auto& e : book.entries()) {
|
for (const auto& e : book.entries()) {
|
||||||
if (e.address.empty() || e.address[0] != 'z') continue; // chat requires a z-address
|
if (e.address.empty() || e.address[0] != 'z') continue; // chat requires a z-address
|
||||||
|
// Respect the same per-wallet scope the Contacts tab enforces — don't leak another
|
||||||
|
// wallet's scoped contact into this wallet's picker (global + legacy fail open).
|
||||||
|
const bool visible = e.isGlobal() ||
|
||||||
|
(e.scope.rfind("w:", 0) == 0 ? (!activeHash.empty() && e.scope == activeHash) : true);
|
||||||
|
if (!visible) continue;
|
||||||
++shown;
|
++shown;
|
||||||
const std::string item = e.label + " " + shorten(e.address, 16, 8);
|
const std::string item = e.label + " " + shorten(e.address, 16, 8);
|
||||||
if (ImGui::Selectable(item.c_str())) {
|
if (ImGui::Selectable(item.c_str())) {
|
||||||
|
|||||||
Reference in New Issue
Block a user