Bug report: clear submission steps, and no dialog growth at fractional scale (#242, #996) (#1085)

The screenshot controls, the submission steps and the Open GitHub draft button stay outside the scrolling review; the clipboard fallback is explained before a long draft opens; text fields leave a pixel of room so the window no longer widens while idle at 140% scale. Instructions in en/de/ja/ko/zh.
This commit is contained in:
Karl Von Richter authored and GitHub committed 2026-10-14 14:56:19 -04:00
1 parent a6fbc63746
commit 575c037f39
8 files changed
+129 -37

No files matched your search

+5
View File
@@ -1,4 +1,9 @@
{
"Send your report on GitHub": "Bericht auf GitHub senden",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Unten den GitHub-Entwurf öffnen und den kopierten Bericht aus der Zwischenablage einfügen.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Unten den GitHub-Entwurf öffnen. Titel und Bericht werden vorausgefüllt.",
"2. Attach your screenshot: copy and paste it, or save and upload the PNG.": "2. Screenshot anhängen: kopieren und einfügen oder als PNG speichern und hochladen.",
"3. Click Submit new issue on GitHub to send your report.": "3. Auf GitHub auf Submit new issue klicken, um den Bericht zu senden.",
"browser.body_name": "Körper {number}",
"browser.component_name": "Komponente {number}",
"browser.parameters": "Parameter ({count})",
+5
View File
@@ -1,4 +1,9 @@
{
"Send your report on GitHub": "Send your report on GitHub",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. Open GitHub draft below, then paste the report copied to your clipboard.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. Open GitHub draft below. Your title and report will be filled in.",
"2. Attach your screenshot: copy and paste it, or save and upload the PNG.": "2. Attach your screenshot: copy and paste it, or save and upload the PNG.",
"3. Click Submit new issue on GitHub to send your report.": "3. Click Submit new issue on GitHub to send your report.",
"browser.body_name": "Body{number}",
"browser.component_name": "Component{number}",
"browser.parameters": "Parameters ({count})",
+5
View File
@@ -1,4 +1,9 @@
{
"Send your report on GitHub": "GitHubでレポートを送信",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 下のボタンでGitHubの下書きを開き、クリップボードにコピーされたレポートを貼り付けます。",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 下のボタンでGitHubの下書きを開きます。タイトルとレポートは入力済みです。",
"2. Attach your screenshot: copy and paste it, or save and upload the PNG.": "2. スクリーンショットを添付します。コピーして貼り付けるか、PNGを保存してアップロードします。",
"3. Click Submit new issue on GitHub to send your report.": "3. GitHubでSubmit new issueをクリックしてレポートを送信します。",
"browser.body_name": "ボディ{number}",
"browser.component_name": "コンポーネント{number}",
"browser.parameters": "パラメータ ({count})",
+5
View File
@@ -1,4 +1,9 @@
{
"Send your report on GitHub": "GitHub에서 보고서 보내기",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 아래에서 GitHub 초안을 열고 클립보드에 복사된 보고서를 붙여넣으세요.",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 아래에서 GitHub 초안을 여세요. 제목과 보고서가 자동으로 입력됩니다.",
"2. Attach your screenshot: copy and paste it, or save and upload the PNG.": "2. 스크린샷을 첨부하세요. 복사하여 붙여넣거나 PNG로 저장한 뒤 업로드하세요.",
"3. Click Submit new issue on GitHub to send your report.": "3. GitHub에서 Submit new issue를 클릭하여 보고서를 보내세요.",
"browser.body_name": "바디{number}",
"browser.component_name": "컴포넌트{number}",
"browser.parameters": "매개변수 ({count})",
+5
View File
@@ -1,4 +1,9 @@
{
"Send your report on GitHub": "在 GitHub 上发送报告",
"1. Open GitHub draft below, then paste the report copied to your clipboard.": "1. 点击下方按钮打开 GitHub 草稿,然后粘贴已复制到剪贴板的报告。",
"1. Open GitHub draft below. Your title and report will be filled in.": "1. 点击下方按钮打开 GitHub 草稿。标题和报告将自动填入。",
"2. Attach your screenshot: copy and paste it, or save and upload the PNG.": "2. 附上截图:复制并粘贴,或保存为 PNG 后上传。",
"3. Click Submit new issue on GitHub to send your report.": "3. 在 GitHub 上点击 Submit new issue 发送报告。",
"browser.body_name": "实体{number}",
"browser.component_name": "组件{number}",
"browser.parameters": "参数 ({count})",
+95 -36
View File
@@ -507,45 +507,53 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
let mut retake = false;
let mut close = false;
let screen = ctx.content_rect();
let max_width = (screen.width() - 48.0).clamp(100.0, crate::frame::WINDOW_WIDE_MAX_W);
crate::frame::window(ctx, crate::i18n::tr_label("Create Issue — review draft"), crate::frame::Width::Wide)
.id(egui::Id::new("sc_issue_report"))
.open(&mut open)
.resizable(true)
.default_width((screen.width() - 32.0).clamp(100.0, 640.0))
.max_width((screen.width() - 24.0).max(100.0))
.max_width(max_width)
.max_height((screen.height() - 32.0).max(100.0))
.vscroll(true)
.show(ctx, |ui| {
ui.label(crate::i18n::tr_label("Review the report and screenshot before opening GitHub."));
ui.add(
egui::TextEdit::singleline(&mut draft.title)
.id(egui::Id::new("issue_report_title"))
.hint_text(crate::i18n::tr_label("Issue title"))
.char_limit(160)
.desired_width(f32::INFINITY),
);
egui::ScrollArea::vertical().id_salt("issue-report-body").max_height((screen.height() * 0.35).clamp(72.0, 240.0)).show(ui, |ui| {
// Only the editable report and evidence scroll. Keep the submission guide
// and actions visible even when a screenshot or long report needs more room.
egui::ScrollArea::vertical().id_salt("issue-report-review").max_height((screen.height() - 260.0).clamp(80.0, 520.0)).show(ui, |ui| {
ui.label(crate::i18n::tr_label("Review the report and screenshot before opening GitHub."));
// TextEdit rounds its allocation to physical pixels. Leaving one pixel of
// room prevents that rounding from increasing the window width every frame
// at fractional display/UI scales (for example 140%).
let editor_width = |ui: &egui::Ui| (ui.available_width() - ui.ctx().pixels_per_point().recip()).max(24.0);
ui.add(
egui::TextEdit::multiline(&mut draft.body)
.id(egui::Id::new("issue_report_body"))
.char_limit(MAX_BODY)
.desired_rows(5)
.desired_width(f32::INFINITY),
egui::TextEdit::singleline(&mut draft.title)
.id(egui::Id::new("issue_report_title"))
.hint_text(crate::i18n::tr_label("Issue title"))
.char_limit(160)
.desired_width(editor_width(ui)),
);
egui::ScrollArea::vertical().id_salt("issue-report-body").max_height((screen.height() * 0.35).clamp(72.0, 240.0)).show(ui, |ui| {
ui.add(
egui::TextEdit::multiline(&mut draft.body)
.id(egui::Id::new("issue_report_body"))
.char_limit(MAX_BODY)
.desired_rows(5)
.desired_width(editor_width(ui)),
);
});
truncate(&mut draft.title, 160);
truncate(&mut draft.body, MAX_BODY);
ui.label(RichText::new(crate::i18n::tr_label("Remove private design details or paths before sharing.")).small());
ui.add(egui::Label::new(&draft.note).wrap());
if let Some(image) = draft.image.as_ref() {
let texture =
draft.texture.get_or_insert_with(|| ctx.load_texture("issue-report-frame", image.clone(), egui::TextureOptions::LINEAR));
ui.add(
egui::Image::new(&*texture)
.max_size(vec2(ui.available_width(), (screen.height() * 0.25).clamp(60.0, 220.0)))
.maintain_aspect_ratio(true),
);
}
});
truncate(&mut draft.title, 160);
truncate(&mut draft.body, MAX_BODY);
ui.label(RichText::new(crate::i18n::tr_label("Remove private design details or paths before sharing.")).small());
ui.label(&draft.note);
if let Some(image) = draft.image.as_ref() {
let texture =
draft.texture.get_or_insert_with(|| ctx.load_texture("issue-report-frame", image.clone(), egui::TextureOptions::LINEAR));
ui.add(
egui::Image::new(&*texture)
.max_size(vec2(ui.available_width(), (screen.height() * 0.25).clamp(60.0, 220.0)))
.maintain_aspect_ratio(true),
);
}
ui.horizontal_wrapped(|ui| {
retake = ui.button(crate::i18n::tr_label("Retake screenshot")).clicked();
if ui.add_enabled(draft.image.is_some(), egui::Button::new(crate::i18n::tr_label("Copy screenshot"))).clicked()
@@ -575,24 +583,44 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
draft.note = "Screenshot removed from this draft.".into();
}
});
ui.separator();
ui.label(RichText::new(crate::i18n::tr_label("Send your report on GitHub")).strong());
let (url, copy_needed) = draft_url(&draft.title, &draft.body);
ui.add(
egui::Label::new(crate::i18n::tr_label(if copy_needed {
"1. Open GitHub draft below, then paste the report copied to your clipboard."
} else {
"1. Open GitHub draft below. Your title and report will be filled in."
}))
.wrap(),
);
ui.add(egui::Label::new(crate::i18n::tr_label("2. Attach your screenshot: copy and paste it, or save and upload the PNG.")).wrap());
ui.add(egui::Label::new(crate::i18n::tr_label("3. Click Submit new issue on GitHub to send your report.")).wrap());
ui.horizontal_wrapped(|ui| {
if ui.button(crate::i18n::tr_label("Copy report")).clicked() {
ctx.copy_text(draft.body.clone());
draft.note = "Report copied. Paste it into the GitHub draft if needed.".into();
}
let (url, copy_needed) = draft_url(&draft.title, &draft.body);
if ui.button(crate::i18n::tr_label("Open GitHub draft")).clicked() {
let t = crate::theme::Tokens::get();
if ui
.add(
egui::Button::new(RichText::new(crate::i18n::tr_label("Open GitHub draft")).strong().color(t.text))
.fill(t.accent_soft)
.stroke(egui::Stroke::new(1.0, t.accent)),
)
.clicked()
{
if copy_needed {
ctx.copy_text(draft.body.clone());
}
ctx.open_url(egui::OpenUrl::new_tab(url));
draft.note = if copy_needed {
"Report copied. Paste into the GitHub draft, then attach the screenshot."
"Report copied. Paste into the GitHub draft, attach the screenshot, then click Submit new issue on GitHub."
} else {
"Review the GitHub draft and attach the screenshot. GitHub's Submit new issue button publishes it."
}
.into();
}
if ui.button(crate::i18n::tr_label("Copy report")).clicked() {
ctx.copy_text(draft.body.clone());
draft.note = "Report copied. Paste it into the GitHub draft if needed.".into();
}
close = ui.button(crate::i18n::tr_label("Close draft")).clicked();
});
});
@@ -743,6 +771,8 @@ mod tests {
let reviewed = draft.body.clone();
h.app.issue_report.draft = Some(draft);
h.frames(4);
assert!(h.widget("1. Open GitHub draft below, then paste the report copied to your clipboard.").is_some());
assert!(h.widget("3. Click Submit new issue on GitHub to send your report.").is_some());
let [x, y] = h.widget("Open GitHub draft").unwrap();
assert_eq!(h.call("ui.move", json!({"x":x,"y":y}))["ok"], true);
let (request, _reply) = crate::control::ControlRequest::new("ui.click", json!({"x":x,"y":y}));
@@ -758,6 +788,35 @@ mod tests {
);
assert_eq!(h.app.issue_report.draft.as_ref().unwrap().body, reviewed);
assert!(h.app.issue_report.draft.as_ref().unwrap().note.starts_with("Report copied. Paste into the GitHub draft"));
assert!(h.app.issue_report.draft.as_ref().unwrap().note.contains("Submit new issue"));
}
#[test]
fn issue_report_idle_window_does_not_grow_with_a_screenshot() {
for size in [[1600, 1000], [900, 700], [640, 480]] {
for scale in [1.0, 1.25, 1.4, 2.0] {
let mut h = crate::scenario::Harness::new();
h.app.preferences.ui_scale = scale;
h.app.home.open = false;
h.call("ui.resize", json!({"width":size[0],"height":size[1]}));
let mut draft = draft_for(&h.app, None, None);
draft.note = "Screenshot captured locally. Review it before attaching it on GitHub.".into();
draft.image = Some(Arc::new(ColorImage::new([1600, 1000], vec![egui::Color32::GREEN; 1_600_000])));
h.app.issue_report.draft = Some(draft);
h.frames(20);
let rect = |h: &crate::scenario::Harness| egui::containers::AreaState::load(&h.ctx, egui::Id::new("sc_issue_report")).unwrap().rect();
let settled = rect(&h);
h.frames(120);
let idle = rect(&h);
assert!((idle.width() - settled.width()).abs() < 1.0, "size={size:?}: {settled:?} grew to {idle:?}");
assert!(idle.width() <= 790.0, "report must retain its width limit: {idle:?}");
assert!(h.ctx.content_rect().contains_rect(idle), "size={size:?} scale={scale}: window must fit: {idle:?}");
for label in ["Copy screenshot", "Save screenshot…", "Open GitHub draft", "Copy report", "Close draft"] {
let [x, y] = h.widget(label).unwrap();
assert!(idle.contains(egui::pos2(x as f32, y as f32)), "{label} must stay visible: {idle:?}, {x}, {y}");
}
}
}
}
#[test]
+1 -1
View File
@@ -126,7 +126,7 @@ unit regardless of the design, pass an expression with one: `"value": "50 mm"` o
| `ui.file` | `path`; `insert?`: bool | starts an interactive background Open or Insert; poll `ui.inspect.file_busy` for completion; the window stays responsive |
| `ui.home` | `open?`: bool; `sample?`: index | the start page: show or hide it, open a built-in sample (once built); returns `open` and the recent designs |
| `ui.shortcut` | `command`, `key?`, `replace?` | a command's key, or rebinds it (`""` clears; a key another command uses is refused unless `replace`) |
| `ui.help` | `item?`: `about`, `shortcuts` (read only), `report` (copies diagnostics), `crashes` (the Crash Reports window) | the version, commit, build date and diagnostic text |
| `ui.help` | `item?`: `about`, `shortcuts` (read only), `report` (opens a report draft for review), `crashes` (the Crash Reports window) | the version, commit, build date and diagnostic text |
| `ui.prefs` | any of `default_units`, `nav` (`fusion`, `solidworks`, `inventor`, `alias`, `tinkercad`, `openscad`), `zoom_reverse`, `zoom_to_cursor`, `smooth_wheel_zoom` (default true), `trackpad_pan` (default true: two-finger scroll pans, pinch zooms), `orbit_cursor`, `look_at_anim`, `look_at_speed`, `middle_double_click` (`home` (default), `fit`, `off`), `msaa`, `length_decimals`, `angle_decimals`, `theme` (`dark`, `light`, `system`), `language` (`en`, `ja`, `de`, `ko`, `ru`, `zh`; see [localization](localization.md)), `ui_scale`, `up_axis` (`z`, `y`), `offer_stand_up`, `check_updates` (default true; [updates](book/src/guide/updates.md)); `open` (a page: General, Navigation, Keyboard Shortcuts, Design, Graphics, Sketch, Selection) opens the Preferences dialog there; `button`: `ok`, `cancel`, `apply`, `defaults`; `stand_up: true` stands up a just-opened Y-up file | sets preferences (kept between runs), returns them all plus `dialog` (the open page or null), `dark` and `stand_up_offer` |
| `ui.capture` | `action?`: `capture`, `revert`, `cancel` | answers the Capture Position question (asked when a command starts or the design is saved while components were moved without capturing); without `action`, what waits |
| `ui.window` | `action`: minimize, maximize, restore, toggle, close | what the title bar's caption buttons do (on Windows and Linux the application bar is the title bar); close asks about unsaved designs first |
+8
View File
@@ -6,6 +6,14 @@ and the exact commands that trigger it. Reports are never sent anywhere. To shar
**Report…** in Help ▸ Crash Reports…, which opens a GitHub issue draft. Nothing is shared
until you review and submit it, and the design is not part of the draft.
To send a report:
1. Review the title, report text and screenshot in SolidCraft, then click **Open GitHub draft**.
For long reports, SolidCraft copies the text to your clipboard; paste it into the GitHub draft.
2. Attach the screenshot if you want to share it: use **Copy screenshot** and paste it into
GitHub, or use **Save screenshot…** and upload the PNG. Screenshots are not attached automatically.
3. Click **Submit new issue** on GitHub to publish the report. Opening the draft alone does not send it.
## Where they are
`<data dir>/solidcraft/crashes/`, next to the recovery folder: