Show a thin scroll cue on Android instead of no scrollbar at all
On Android the desktop scrollbar is off, so every scroller that has one on a desktop (the develop column, the grid, the collections sidebar, Settings, the help sheet and the film list) gave no sign of how long it was or where the view was in it. That is how the black-and-white film stocks came to look deleted when the list could not scroll. ScrollBar now has a second mode, chosen in the one Scrolling global: where bars are off and `cue` is on, it draws the thumb alone, 3 px wide against the edge, while the viewport moves, and fades it 500 ms after the last move. It has no TouchArea, so a flick that starts on it scrolls the content. Rust sets cue on touch-first builds; a desktop build shows it when DR_SCROLL_CUE is set, to look at it without a device. Desktop is otherwise unchanged. Test: on the testing backend's help sheet, a press on the cue moves nothing, a drag starting on it carries the list with the finger, the cue is drawn while the list moves (drag, fling, wheel) and not once it is idle; with bars on there is no cue and the thumb still takes a drag.
This commit is contained in:
@@ -189,6 +189,16 @@ fn report_position(window: &AppWindow, ctl: &Rc<LibraryController>, row: usize)
|
||||
window.set_total(window.global::<Library>().get_library_total());
|
||||
}
|
||||
|
||||
/// Whether scrollers show the touch cue rather than the desktop bar.
|
||||
///
|
||||
/// A touch-first build always does. A desktop build does when
|
||||
/// `DR_SCROLL_CUE` is set to anything but empty or `0` — not a setting, but
|
||||
/// the way to look at the tablet's cue with a mouse: a developer checking it,
|
||||
/// or a screenshot of it, without an APK and a device.
|
||||
fn scroll_cue(touch_first: bool, env: Option<std::ffi::OsString>) -> bool {
|
||||
touch_first || env.is_some_and(|v| !v.is_empty() && v != "0")
|
||||
}
|
||||
|
||||
/// Connect the grid's callbacks.
|
||||
pub fn wire<F>(
|
||||
window: &AppWindow,
|
||||
@@ -229,14 +239,15 @@ pub fn wire<F>(
|
||||
.global::<Library>()
|
||||
.set_library_touched(cfg!(target_os = "android"));
|
||||
|
||||
// TRACES: FR-UI-1
|
||||
// Scrollbars for a pointer, none for a finger: the same question, asked
|
||||
// of the same function, that puts the develop groups in the rail. Set
|
||||
// here, once, because every scroller that draws a bar reads it and none
|
||||
// of them can change it.
|
||||
window
|
||||
.global::<crate::Scrolling>()
|
||||
.set_bars(!dr_plat::is_touch_first());
|
||||
// TRACES: FR-UI-1 | FR-UI-2
|
||||
// Scrollbars for a pointer, the thin cue for a finger: the same question,
|
||||
// asked of the same function, that puts the develop groups in the rail.
|
||||
// Set here, once, because every scroller that draws a bar reads it and
|
||||
// none of them can change it.
|
||||
let cue = scroll_cue(dr_plat::is_touch_first(), std::env::var_os("DR_SCROLL_CUE"));
|
||||
let scrolling = window.global::<crate::Scrolling>();
|
||||
scrolling.set_bars(!cue);
|
||||
scrolling.set_cue(cue);
|
||||
|
||||
// TRACES: FR-UI-4
|
||||
// The gesture reference. Pushed once, here, rather than on demand: the
|
||||
@@ -815,6 +826,15 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::library_ui::window::{locate_open, window_for, window_start};
|
||||
|
||||
#[test]
|
||||
fn the_cue_is_the_tablets_and_a_desktop_opts_in() {
|
||||
assert!(scroll_cue(true, None), "a touch-first build always cues");
|
||||
assert!(!scroll_cue(false, None), "a desktop keeps its bars");
|
||||
assert!(scroll_cue(false, Some("1".into())));
|
||||
assert!(!scroll_cue(false, Some("0".into())), "0 is off");
|
||||
assert!(!scroll_cue(false, Some("".into())), "empty is off");
|
||||
}
|
||||
|
||||
/// A library larger than one loaded window, and the window over it as
|
||||
/// `load_window` leaves it: offset clamped so the window stays full, and
|
||||
/// holding the photographs from there on. A photograph's id is its
|
||||
|
||||
Reference in New Issue
Block a user