Release v0.2.12
This commit is contained in:
parent
7d6202e0a2
commit
77d6e3b68b
7 changed files with 294 additions and 86 deletions
119
src/viewer.rs
119
src/viewer.rs
|
|
@ -26,6 +26,7 @@ const IMAGE_ZOOM_MAX: f64 = 4.0;
|
|||
const VIEWER_CONTROLLER_KEY: &str = "comicviewer-viewer-controller";
|
||||
const MEDIA_VIEWER_CONTROLLER_KEY: &str = "comicviewer-media-viewer-controller";
|
||||
const VIEWER_FILE_SEARCH_KEY: &str = "comicviewer-file-search";
|
||||
const VIEWER_FILE_SCROLL_KEY: &str = "comicviewer-file-scroll";
|
||||
const PRESERVE_SEEK_CLASS: &str = "viewer-preserve-seek";
|
||||
|
||||
fn clear_viewer_controller(window: >k::ApplicationWindow) {
|
||||
|
|
@ -289,6 +290,10 @@ impl ViewerWindow {
|
|||
.as_ref()
|
||||
.map(viewer_file_search_query)
|
||||
.unwrap_or_default();
|
||||
let file_list_scroll = reuse_window
|
||||
.as_ref()
|
||||
.map(viewer_file_scroll_position)
|
||||
.unwrap_or_default();
|
||||
if let Some(window) = reuse_window.as_ref() {
|
||||
clear_viewer_controller(window);
|
||||
}
|
||||
|
|
@ -305,7 +310,7 @@ impl ViewerWindow {
|
|||
set_viewer_loading(&window, false);
|
||||
window.set_title(Some(&title));
|
||||
let header = gtk::HeaderBar::new();
|
||||
header.set_title_widget(Some(>k::Label::new(Some(&title))));
|
||||
header.set_title_widget(Some(&viewer_title_label(&title)));
|
||||
let favorite_button = gtk::Button::with_label(favorite_label(favorite_control.active));
|
||||
let download_button = gtk::Button::with_label("파일 다운로드");
|
||||
let file_list_button = gtk::ToggleButton::with_label("파일 목록");
|
||||
|
|
@ -454,8 +459,10 @@ impl ViewerWindow {
|
|||
file_list_button,
|
||||
file_list_panel: file_list.panel,
|
||||
file_list_search: file_list.search,
|
||||
file_list_scrolled: file_list.scrolled,
|
||||
file_list: file_list.list,
|
||||
file_list_files: RefCell::new(Vec::new()),
|
||||
file_list_scroll_restore: Cell::new(Some(file_list_scroll)),
|
||||
favorite_button,
|
||||
favorite_toggle: favorite_control.toggle,
|
||||
download_button,
|
||||
|
|
@ -625,8 +632,10 @@ struct ViewerController {
|
|||
file_list_button: gtk::ToggleButton,
|
||||
file_list_panel: gtk::Box,
|
||||
file_list_search: gtk::SearchEntry,
|
||||
file_list_scrolled: gtk::ScrolledWindow,
|
||||
file_list: gtk::ListBox,
|
||||
file_list_files: RefCell<Vec<SiblingFile>>,
|
||||
file_list_scroll_restore: Cell<Option<f64>>,
|
||||
favorite_button: gtk::Button,
|
||||
favorite_toggle: Rc<dyn Fn() -> bool>,
|
||||
download_button: gtk::Button,
|
||||
|
|
@ -752,6 +761,16 @@ impl ViewerController {
|
|||
controller.refresh_file_list();
|
||||
}
|
||||
});
|
||||
let controller = Rc::downgrade(self);
|
||||
self.file_list_scrolled
|
||||
.vadjustment()
|
||||
.connect_value_changed(move |adjustment| {
|
||||
if let Some(controller) = controller.upgrade()
|
||||
&& controller.file_list_scroll_restore.get().is_none()
|
||||
{
|
||||
store_viewer_file_scroll_position(&controller.window, adjustment.value());
|
||||
}
|
||||
});
|
||||
let file_list_typeahead = Rc::new(RefCell::new(TypeaheadBuffer::default()));
|
||||
let file_list_keys = gtk::EventControllerKey::new();
|
||||
let controller = Rc::downgrade(self);
|
||||
|
|
@ -1073,6 +1092,11 @@ impl ViewerController {
|
|||
if let Some(row) = current.and_then(|index| self.file_list.row_at_index(index as i32)) {
|
||||
self.file_list.select_row(Some(&row));
|
||||
}
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
}
|
||||
|
||||
fn open_file_list_row(&self, index: i32) {
|
||||
|
|
@ -1264,6 +1288,11 @@ impl ViewerController {
|
|||
self.status_label.set_visible(true);
|
||||
self.file_list_panel
|
||||
.set_visible(self.file_list_button.is_active());
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1304,6 +1333,11 @@ impl ViewerController {
|
|||
self.status_label.set_visible(visible);
|
||||
self.file_list_panel
|
||||
.set_visible(visible && self.file_list_button.is_active());
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
self.window.queue_allocate();
|
||||
let controller = Rc::downgrade(self);
|
||||
glib::idle_add_local_once(move || {
|
||||
|
|
@ -2209,6 +2243,10 @@ impl MediaViewerWindow {
|
|||
.as_ref()
|
||||
.map(viewer_file_search_query)
|
||||
.unwrap_or_default();
|
||||
let file_list_scroll = reuse_window
|
||||
.as_ref()
|
||||
.map(viewer_file_scroll_position)
|
||||
.unwrap_or_default();
|
||||
if let Some(window) = reuse_window.as_ref() {
|
||||
clear_viewer_controller(window);
|
||||
}
|
||||
|
|
@ -2225,7 +2263,7 @@ impl MediaViewerWindow {
|
|||
set_viewer_loading(&window, false);
|
||||
window.set_title(Some(&title));
|
||||
let header = gtk::HeaderBar::new();
|
||||
header.set_title_widget(Some(>k::Label::new(Some(&title))));
|
||||
header.set_title_widget(Some(&viewer_title_label(&title)));
|
||||
let favorite_button = gtk::Button::with_label(favorite_label(favorite_control.active));
|
||||
let download_button = gtk::Button::with_label("파일 다운로드");
|
||||
let file_list_button = gtk::ToggleButton::with_label("파일 목록");
|
||||
|
|
@ -2335,8 +2373,10 @@ impl MediaViewerWindow {
|
|||
file_list_button,
|
||||
file_list_panel: file_list.panel,
|
||||
file_list_search: file_list.search,
|
||||
file_list_scrolled: file_list.scrolled,
|
||||
file_list: file_list.list,
|
||||
file_list_files: RefCell::new(Vec::new()),
|
||||
file_list_scroll_restore: Cell::new(Some(file_list_scroll)),
|
||||
favorite_button,
|
||||
favorite_toggle: favorite_control.toggle,
|
||||
download_button,
|
||||
|
|
@ -2422,8 +2462,10 @@ struct MediaViewerController {
|
|||
file_list_button: gtk::ToggleButton,
|
||||
file_list_panel: gtk::Box,
|
||||
file_list_search: gtk::SearchEntry,
|
||||
file_list_scrolled: gtk::ScrolledWindow,
|
||||
file_list: gtk::ListBox,
|
||||
file_list_files: RefCell<Vec<SiblingFile>>,
|
||||
file_list_scroll_restore: Cell<Option<f64>>,
|
||||
favorite_button: gtk::Button,
|
||||
favorite_toggle: Rc<dyn Fn() -> bool>,
|
||||
download_button: gtk::Button,
|
||||
|
|
@ -2653,6 +2695,16 @@ impl MediaViewerController {
|
|||
controller.refresh_file_list();
|
||||
}
|
||||
});
|
||||
let controller = Rc::downgrade(self);
|
||||
self.file_list_scrolled
|
||||
.vadjustment()
|
||||
.connect_value_changed(move |adjustment| {
|
||||
if let Some(controller) = controller.upgrade()
|
||||
&& controller.file_list_scroll_restore.get().is_none()
|
||||
{
|
||||
store_viewer_file_scroll_position(&controller.window, adjustment.value());
|
||||
}
|
||||
});
|
||||
let file_list_typeahead = Rc::new(RefCell::new(TypeaheadBuffer::default()));
|
||||
let file_list_keys = gtk::EventControllerKey::new();
|
||||
let controller = Rc::downgrade(self);
|
||||
|
|
@ -2779,6 +2831,11 @@ impl MediaViewerController {
|
|||
if let Some(row) = current.and_then(|index| self.file_list.row_at_index(index as i32)) {
|
||||
self.file_list.select_row(Some(&row));
|
||||
}
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
}
|
||||
|
||||
fn open_file_list_row(&self, index: i32) {
|
||||
|
|
@ -3191,6 +3248,11 @@ impl MediaViewerController {
|
|||
self.status_label.set_visible(true);
|
||||
self.file_list_panel
|
||||
.set_visible(self.file_list_button.is_active());
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3230,6 +3292,11 @@ impl MediaViewerController {
|
|||
self.status_label.set_visible(visible);
|
||||
self.file_list_panel
|
||||
.set_visible(visible && self.file_list_button.is_active());
|
||||
restore_pending_viewer_file_scroll(
|
||||
&self.file_list_panel,
|
||||
&self.file_list_scrolled,
|
||||
&self.file_list_scroll_restore,
|
||||
);
|
||||
self.window.queue_allocate();
|
||||
let controller = Rc::downgrade(self);
|
||||
glib::idle_add_local_once(move || {
|
||||
|
|
@ -3295,9 +3362,19 @@ fn favorite_label(active: bool) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
fn viewer_title_label(title: &str) -> gtk::Label {
|
||||
gtk::Label::builder()
|
||||
.label(title)
|
||||
.hexpand(true)
|
||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
||||
.tooltip_text(title)
|
||||
.build()
|
||||
}
|
||||
|
||||
struct ViewerFileList {
|
||||
panel: gtk::Box,
|
||||
search: gtk::SearchEntry,
|
||||
scrolled: gtk::ScrolledWindow,
|
||||
list: gtk::ListBox,
|
||||
}
|
||||
|
||||
|
|
@ -3430,6 +3507,7 @@ fn viewer_file_list(query: &str) -> ViewerFileList {
|
|||
ViewerFileList {
|
||||
panel,
|
||||
search,
|
||||
scrolled,
|
||||
list,
|
||||
}
|
||||
}
|
||||
|
|
@ -3449,6 +3527,43 @@ fn store_viewer_file_search_query(window: >k::ApplicationWindow, query: &str)
|
|||
}
|
||||
}
|
||||
|
||||
fn viewer_file_scroll_position(window: >k::ApplicationWindow) -> f64 {
|
||||
unsafe {
|
||||
window
|
||||
.data::<f64>(VIEWER_FILE_SCROLL_KEY)
|
||||
.map(|position| *position.as_ref())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
fn store_viewer_file_scroll_position(window: >k::ApplicationWindow, position: f64) {
|
||||
unsafe {
|
||||
window.set_data(VIEWER_FILE_SCROLL_KEY, position.max(0.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_viewer_file_scroll(scrolled: >k::ScrolledWindow, position: f64) {
|
||||
let scrolled = scrolled.clone();
|
||||
glib::idle_add_local_once(move || {
|
||||
let adjustment = scrolled.vadjustment();
|
||||
let maximum = (adjustment.upper() - adjustment.page_size()).max(adjustment.lower());
|
||||
adjustment.set_value(position.clamp(adjustment.lower(), maximum));
|
||||
});
|
||||
}
|
||||
|
||||
fn restore_pending_viewer_file_scroll(
|
||||
panel: >k::Box,
|
||||
scrolled: >k::ScrolledWindow,
|
||||
pending: &Cell<Option<f64>>,
|
||||
) {
|
||||
if !panel.is_visible() {
|
||||
return;
|
||||
}
|
||||
if let Some(position) = pending.take() {
|
||||
restore_viewer_file_scroll(scrolled, position);
|
||||
}
|
||||
}
|
||||
|
||||
fn widget_contains_focus(widget: &impl IsA<gtk::Widget>, window: >k::ApplicationWindow) -> bool {
|
||||
gtk::prelude::GtkWindowExt::focus(window).is_some_and(|focus| {
|
||||
let widget = widget.as_ref();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue