feat(chat): demo-chat seed for the screenshot sweep (debug)
Add App::seedChatDemoData() + a "Seed demo chat" button in the DEBUG OPTIONS card (shown only in chat-enabled builds, next to the screenshot sweep). It gives the Chat tab a demo identity and injects a few sample conversations into the in-memory store (NOT persisted — no DB attached, gone on restart) so the screenshot sweep captures the tab's real UI (conversation list, thread bubbles, composer, and the "waiting for reply" contact-request state) instead of the empty "unlock" hint. No-op when the chat feature is off. Verified: Linux + Windows build with chat ON, ctest 100%, hygiene clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,6 +174,10 @@ public:
|
||||
// message (to a conversation whose peer key we know) / a new-conversation contact request.
|
||||
void sendChatMessage(const std::string& conversationId, const std::string& text);
|
||||
void startChatConversation(const std::string& peerZaddr, const std::string& text);
|
||||
// Debug/sweep convenience: give the Chat tab a demo identity + a few sample conversations
|
||||
// (in-memory only, not persisted) so the screenshot sweep captures the populated UI. No-op when
|
||||
// the chat feature is off.
|
||||
void seedChatDemoData();
|
||||
// Reason the lite wallet failed to auto-open this session (empty if none / opened OK).
|
||||
const std::string& liteOpenError() const { return lite_open_error_; }
|
||||
// Show the lite send-time unlock modal (called when a spend is attempted on a locked wallet).
|
||||
|
||||
@@ -2660,6 +2660,46 @@ void App::ingestLiteChatMemos(const wallet::LiteWalletAppRefreshModel& model)
|
||||
if (!metadata.empty()) chat_service_.ingest(metadata, txTimestamps, std::time(nullptr));
|
||||
}
|
||||
|
||||
void App::seedChatDemoData()
|
||||
{
|
||||
if (!chat::hushChatFeatureEnabledAtBuild()) return;
|
||||
|
||||
// Demo identity so the tab renders the populated UI (hasIdentity()==true). Injected messages go
|
||||
// straight into the in-memory store (no DB attached here → not persisted, gone on restart).
|
||||
chat::ChatKeyPair keys;
|
||||
if (chat::deriveChatIdentityFromSecret("obsidian-dragon-demo-chat", keys).status
|
||||
== chat::ChatIdentityStatus::Ready) {
|
||||
chat_service_.setIdentity(keys);
|
||||
}
|
||||
chat::wipeChatKeyPair(keys);
|
||||
|
||||
auto& store = chat_service_.store();
|
||||
const std::string zAlice = "zs1demoalice6xh2n8fchrz23thcgqqd2353v8ev2pr7p7lq4p3elsyrfkuenq";
|
||||
const std::string zBob = "zs1demobob9k4p3elsyrfkuenq4kl79j2pg7l3h2juz4t6q9wqxkha2n8fchrz2";
|
||||
auto add = [&](const std::string& cid, const std::string& z, const std::string& pk,
|
||||
chat::ChatDirection dir, chat::ChatMessageKind kind, const std::string& body,
|
||||
std::int64_t ts, const std::string& id) {
|
||||
chat::ChatMessage m;
|
||||
m.direction = dir; m.kind = kind; m.conversation_id = cid; m.peer_zaddr = z;
|
||||
m.peer_public_key_hex = pk; m.body = body; m.timestamp = ts; m.txid = id;
|
||||
m.payload_position = 0;
|
||||
store.append(m);
|
||||
};
|
||||
// A full thread (peer key known → composer enabled).
|
||||
add("demo-1", zAlice, std::string(64, 'a'), chat::ChatDirection::Incoming, chat::ChatMessageKind::Message,
|
||||
"hey! got the DragonX wallet running, chat works great", 1751284800, "demo:a1");
|
||||
add("demo-1", zAlice, std::string(64, 'a'), chat::ChatDirection::Outgoing, chat::ChatMessageKind::Message,
|
||||
"nice - this is end-to-end encrypted over shielded memos", 1751285400, "demo:a2");
|
||||
add("demo-1", zAlice, std::string(64, 'a'), chat::ChatDirection::Incoming, chat::ChatMessageKind::Message,
|
||||
"and it survives the daemon's output shuffle now", 1751286000, "demo:a3");
|
||||
// An incoming contact request (peer key known → can reply).
|
||||
add("demo-2", zBob, std::string(64, 'b'), chat::ChatDirection::Incoming, chat::ChatMessageKind::ContactRequest,
|
||||
"hi, add me? - bob", 1751200000, "demo:b1");
|
||||
// An outgoing contact request awaiting a reply (no peer key → "waiting" composer state).
|
||||
add("demo-3", "zs1demopeerawaitingtheirfirstreplybeforewecanmessagethemyet00", "",
|
||||
chat::ChatDirection::Outgoing, chat::ChatMessageKind::ContactRequest, "hey, let's chat", 1751100000, "demo:c1");
|
||||
}
|
||||
|
||||
void App::exportAllKeys(std::function<void(const std::string&, int, int)> callback)
|
||||
{
|
||||
if (!state_.connected || !rpc_) {
|
||||
|
||||
@@ -2496,6 +2496,12 @@ void RenderSettingsPage(App* app) {
|
||||
ImGui::SameLine();
|
||||
if (TactileButton(TR("screenshot_open_dir"), ImVec2(0, 0), S.resolveFont("button")))
|
||||
util::Platform::openFolder(app->screenshotDir());
|
||||
if (chat::hushChatFeatureEnabledAtBuild()) {
|
||||
// Populate the Chat tab with demo conversations so the sweep captures its real UI.
|
||||
ImGui::SameLine();
|
||||
if (TactileButton("Seed demo chat", ImVec2(0, 0), S.resolveFont("button")))
|
||||
app->seedChatDemoData();
|
||||
}
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
ImGui::Separator();
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
|
||||
Reference in New Issue
Block a user