M3: a fractional zoom is remembered as it was, not rounded to a whole percent (#1767)

Review follow-up on #2195: the last view stored ViewDefaults::zoom_name(),
which rounds 62.5% to 63%. A fixed zoom is now written with its fraction
(with_zoom already reads it back); the fit tokens are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0175FWj4xFhMhSH3UpMU8DSC
This commit is contained in:
mtlcl410
2026-10-24 10:09:48 +08:00
co-authored by Claude Opus 5.5
parent fb53ddf02f
commit 6506c8cc45
2 changed files with 27 additions and 2 deletions
+7 -2
View File
@@ -18,7 +18,8 @@ pub struct LastView {
pub path: String,
/// 0-based.
pub page: usize,
/// As settings name it: `fit-width`, `fit-page` or a percentage (`ViewDefaults::zoom_name`).
/// As settings name it: `fit-width`, `fit-page` or a percentage, kept to its fraction
/// (`62.5%`; read back by `ViewDefaults::with_zoom`).
pub zoom: String,
/// The page display token (`canvas::display_token`).
pub display: String,
@@ -44,7 +45,11 @@ impl PdfCraftApp {
let view = self.views.get(index)?;
let path = self.session.get(view.id)?.path.as_deref()?;
let shown = view.normal_display();
let zoom = ViewDefaults { fit: shown.fit, zoom: shown.zoom, ..ViewDefaults::default() }.zoom_name();
// A fixed zoom keeps its fraction (62.5%, not 63%): `zoom_name` rounds to whole percents.
let zoom = match shown.fit {
canvas::Fit::None => format!("{}%", shown.zoom * 100.0),
fit => ViewDefaults { fit, zoom: shown.zoom, ..ViewDefaults::default() }.zoom_name(),
};
Some(LastView {
path: absolute(path),
page: view.current,
+20
View File
@@ -1652,6 +1652,26 @@ fn a_file_opened_again_shows_its_last_view() {
assert_eq!((app.last_views[0].page, app.last_views[0].zoom.as_str()), (1, "fit-page"));
}
/// #1767: a fixed zoom with a fraction comes back as it was, not rounded to a whole percent.
#[test]
fn a_fractional_zoom_is_remembered_exactly() {
use pdfcraft_ui_egui::canvas::Fit;
let path = std::env::temp_dir().join(format!("pdfcraft-last-view-frac-{}.pdf", std::process::id())).to_string_lossy().into_owned();
let p = path.clone();
let mut h = harness(move |app| app.open_bytes("doc.pdf", Some(p), pages_fixture(3)).expect("opens"));
h.state_mut().views[0].set_zoom(0.625);
h.run_steps(3);
h.state_mut().close_tab(0);
assert_eq!(h.state().last_views[0].zoom, "62.5%");
let saved = h.state().persist();
let h = harness(move |app| {
app.restore(&saved);
app.open_bytes("doc.pdf", Some(path), pages_fixture(3)).expect("opens");
});
let v = &h.state().views[0];
assert_eq!((v.fit, v.zoom), (Fit::None, 0.625));
}
/// #1767 with full screen: the view remembered while presenting is the one full screen will go
/// back to, and a file reopened in full screen presents one fitted page, then leaves full
/// screen for the remembered view.