fix(ui): apply continuous scrolling and view defaults to active and remembered documents (#6780)

This commit is contained in:
Combiler01 committed 2026-11-10 21:01:34 +05:30
1 parent debb826f29
commit 4f16190e52
4 files changed
+111 -23

No files matched your search

+53 -15
View File
@@ -710,37 +710,75 @@ fn card_documents_and_view(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tokens,
ctx.label_secondary(ui, tl!("Used when opening PDFs. An explicit launch or control mode takes precedence for the session."), t);
ui.add_space(6.0);
let defaults = &mut app.view_defaults;
let mut layout_choice = app.view_defaults.layout;
let mut continuous = app.view_defaults.continuous;
let mut layout_changed = false;
let mut continuous_changed = false;
ui.horizontal(|ui| {
ctx.label_primary(ui, tl!("Default page display"), t);
let mut layout_choice = defaults.layout;
if ctx.pill_choice(ui, t, &mut layout_choice, &[(PageLayout::Single, tl!("Single page")), (PageLayout::TwoUp, tl!("Two-page view"))]) {
defaults.layout = layout_choice;
app.view_defaults.layout = layout_choice;
layout_changed = true;
}
let mut continuous = defaults.continuous;
if ctx.toggle_pill(ui, t, &mut continuous, tl!("Continuous scrolling")) {
defaults.continuous = continuous;
app.view_defaults.continuous = continuous;
continuous_changed = true;
}
});
ctx.checkbox(ui, &mut defaults.show_page_gaps, tl!("Show gaps between pages"), t);
let mut show_page_gaps = app.view_defaults.show_page_gaps;
let gaps_changed = ctx.checkbox(ui, &mut show_page_gaps, tl!("Show gaps between pages"), t).changed();
if gaps_changed {
app.view_defaults.show_page_gaps = show_page_gaps;
}
ctx.label_secondary(ui, tl!("Hide gaps to join page edges. Margins inside the PDF remain unchanged."), t);
ui.add_space(6.0);
let mut fit_changed = false;
let mut zoom_changed = false;
ui.horizontal(|ui| {
ctx.label_primary(ui, tl!("Default zoom"), t);
ctx.pill_choice(
ui,
t,
&mut defaults.fit,
&[(Fit::Width, tl!("Fit to width")), (Fit::Page, tl!("Zoom to page level")), (Fit::None, tl!("Custom"))],
);
let mut percent = defaults.zoom * 100.0;
let mut fit = app.view_defaults.fit;
if ctx.pill_choice(ui, t, &mut fit, &[(Fit::Width, tl!("Fit to width")), (Fit::Page, tl!("Zoom to page level")), (Fit::None, tl!("Custom"))])
{
app.view_defaults.fit = fit;
fit_changed = true;
}
let mut percent = app.view_defaults.zoom * 100.0;
if ui.add(egui::DragValue::new(&mut percent).range(8.0..=6400.0).max_decimals(0).suffix("%")).changed() {
(defaults.fit, defaults.zoom) = (Fit::None, percent / 100.0);
(app.view_defaults.fit, app.view_defaults.zoom) = (Fit::None, percent / 100.0);
zoom_changed = true;
}
});
ctx.label_secondary(ui, tl!("Used when a PDF doesn't ask for a layout or zoom. Continuous scrolling never snaps between pages."), t);
ctx.checkbox(ui, &mut app.always_default_view, tl!("Always use my default zoom and page layout"), t);
let always_changed = ctx.checkbox(ui, &mut app.always_default_view, tl!("Always use my default zoom and page layout"), t).changed();
if app.always_default_view && (always_changed || layout_changed || continuous_changed || gaps_changed || fit_changed || zoom_changed) {
let defaults = app.view_defaults;
for view in &mut app.views {
view.set_display(defaults.layout, defaults.continuous);
view.show_page_gaps = defaults.show_page_gaps;
match defaults.fit {
Fit::None => view.set_zoom(defaults.zoom),
fit => view.set_fit(fit),
}
}
} else if let Some(i) = app.active {
if layout_changed {
app.views[i].set_layout(layout_choice);
}
if continuous_changed {
app.views[i].set_continuous(continuous);
}
if gaps_changed {
app.views[i].show_page_gaps = show_page_gaps;
}
if fit_changed {
app.views[i].set_fit(app.view_defaults.fit);
}
if zoom_changed {
app.views[i].set_zoom(app.view_defaults.zoom);
}
}
ctx.checkbox(ui, &mut app.text_links, tl!("Open web and email addresses written in the page text"), t);
ctx.label_secondary(ui, tl!("Only web (http, https) and email addresses open, and PdfCraft asks first, as for other links."), t);
ui.add_space(6.0);
+10 -8
View File
@@ -112,14 +112,16 @@ impl PdfCraftApp {
let pages = doc.info.pages.len();
let Some(last) = self.last_views.iter().find(|l| l.path == path).cloned() else { return };
let Some(view) = self.views.get_mut(index) else { return };
if let Some((layout, continuous)) = canvas::parse_display_token(&last.display) {
view.set_display(layout, continuous);
}
view.set_cover(last.cover);
if let Some(defaults) = ViewDefaults::default().with_zoom(&last.zoom) {
match defaults.fit {
canvas::Fit::None => view.set_zoom(defaults.zoom),
fit => view.set_fit(fit),
if !self.always_default_view {
if let Some((layout, continuous)) = canvas::parse_display_token(&last.display) {
view.set_display(layout, continuous);
}
view.set_cover(last.cover);
if let Some(defaults) = ViewDefaults::default().with_zoom(&last.zoom) {
match defaults.fit {
canvas::Fit::None => view.set_zoom(defaults.zoom),
fit => view.set_fit(fit),
}
}
}
if last.page < pages {
+33
View File
@@ -1255,6 +1255,39 @@ fn preferences_turn_on_always_use_my_default_zoom_and_page_layout() {
assert!(h.state().always_default_view);
}
#[test]
fn preferences_turn_on_always_use_my_default_zoom_and_page_layout_updates_open_documents() {
use egui_kittest::kittest::Queryable;
let mut h = harness(&[("continuous", "off"), ("zoom", "50")]);
assert!(!h.state().views[0].continuous());
assert_ne!(h.state().views[0].fit, pdfcraft_ui_egui::canvas::Fit::Width);
assert!(h.state_mut().execute("app.preferences"));
h.run_steps(3);
h.get_by_label("Always use my default zoom and page layout").scroll_to_me();
h.run_steps(4);
h.get_by_label("Always use my default zoom and page layout").click();
h.run_steps(2);
assert!(h.state().always_default_view);
assert!(h.state().views[0].continuous(), "continuous scrolling is applied");
assert_eq!(h.state().views[0].fit, pdfcraft_ui_egui::canvas::Fit::Width, "default fit width is applied");
}
#[test]
fn preferences_toggle_continuous_scrolling_updates_active_document() {
use egui_kittest::kittest::Queryable;
let mut h = harness(&[("default-continuous", "off"), ("continuous", "off")]);
assert!(!h.state().view_defaults.continuous);
assert!(!h.state().views[0].continuous());
assert!(h.state_mut().execute("app.preferences"));
h.run_steps(3);
h.get_by_label("Continuous scrolling").scroll_to_me();
h.run_steps(4);
h.get_by_label("Continuous scrolling").click();
h.run_steps(2);
assert!(h.state().view_defaults.continuous, "defaults are updated");
assert!(h.state().views[0].continuous(), "active document view is updated");
}
#[test]
fn preferences_set_the_default_zoom() {
use egui_kittest::kittest::Queryable;
+15
View File
@@ -231,6 +231,21 @@ fn a_remembered_zoom_wins_over_the_layouts_fit_page() {
assert_eq!((v.fit, v.zoom, v.current), (Fit::None, 0.625, 1));
}
#[test]
fn always_default_view_wins_over_a_remembered_view() {
let path = std::env::temp_dir().join(format!("pdfcraft-viewer-prefs-always-default-{}.pdf", std::process::id())).to_string_lossy().into_owned();
let mut app = PdfCraftApp::new();
let json_path = serde_json::to_string(&path).unwrap();
app.restore(&format!(
r#"{{"last_views": [{{"path": {json_path}, "page": 1, "zoom": "62.5%", "display": "single"}}], "always_default_view": true}}"#
));
assert!(app.always_default_view);
assert!(app.restore_last_view);
app.open_bytes("x.pdf", Some(path), fixture("/PageLayout /SinglePage")).unwrap();
let v = &app.views[0];
assert_eq!((v.fit, v.layout, v.continuous(), v.current), (Fit::Width, pdfcraft_ui_egui::canvas::PageLayout::Single, true, 1));
}
/// The last `InnerSize` and `OuterPosition` asked for over `frames` frames.
fn window_commands(h: &mut Harness<'static, PdfCraftApp>, frames: usize) -> (Option<egui::Vec2>, Option<egui::Pos2>) {
let (mut size, mut at) = (None, None);