diff --git a/src/ui/windows/shield_dialog.cpp b/src/ui/windows/shield_dialog.cpp index 1f88b6c..79172d3 100644 --- a/src/ui/windows/shield_dialog.cpp +++ b/src/ui/windows/shield_dialog.cpp @@ -720,7 +720,14 @@ void ShieldDialog::render(App* app) std::max(1, p.batchesEstimated), p.notesMerged); wrappedCaption(material::OnSurfaceMedium(), cap); if (!p.stopping) { - if (const char* key = services::runWaitKey(run.lastWait())) wrappedCaption(material::OnSurfaceMedium(), TR(key)); + // The pause notice (waiting for a batch gap / sync / a send) toggles on and off every batch. + // Reserve a fixed two-line slot for it so its coming and going doesn't change the content + // height and make the auto-height, vertically-centred modal jump around during the run. + const float waitTop = ImGui::GetCursorPosY(); + if (const char* key = services::runWaitKey(run.lastWait())) + wrappedCaption(material::OnSurfaceMedium(), TR(key)); + const float waitSlotH = ImGui::GetTextLineHeightWithSpacing() * 2.0f; + if (ImGui::GetCursorPosY() < waitTop + waitSlotH) ImGui::SetCursorPosY(waitTop + waitSlotH); } } ImGui::ProgressBar(static_cast(p.batchesDone) / static_cast(std::max(1, p.batchesEstimated)), @@ -765,9 +772,20 @@ void ShieldDialog::render(App* app) } } ImGui::EndChild(); - if (leftovers) { - ImGui::Spacing(); - wrappedCaption(material::OnSurfaceMedium(), TR("merge_keep_each_run_again")); + { + // The "run again" hint appears partway through a run (once an address has leftover notes). While + // the run is live, reserve its measured height up front so it appearing doesn't shift the modal. + const float loTop = ImGui::GetCursorPosY(); + if (leftovers) { + ImGui::Spacing(); + wrappedCaption(material::OnSurfaceMedium(), TR("merge_keep_each_run_again")); + } + if (live) { + const float loH = ImGui::GetStyle().ItemSpacing.y + + ImGui::CalcTextSize(TR("merge_keep_each_run_again"), nullptr, false, + ImGui::GetContentRegionAvail().x).y; + if (ImGui::GetCursorPosY() < loTop + loH) ImGui::SetCursorPosY(loTop + loH); + } } if (!live) { // below the rows: merge_keep_each_some_failed says "see the list above" std::string endLine;