Don't try to create previews of images that currently are displayed in preview window (#480)
* Don't try to create previews of images that currently are displayed in preview window * Don't need to use special buttons anymore
This commit is contained in:
parent
5e1ed0daeb
commit
b496809410
|
@ -36,6 +36,8 @@ pub async fn delete_things(gui_data: GuiData) {
|
||||||
|
|
||||||
let check_button_settings_use_trash = gui_data.settings.check_button_settings_use_trash.clone();
|
let check_button_settings_use_trash = gui_data.settings.check_button_settings_use_trash.clone();
|
||||||
|
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main).await {
|
if !check_if_can_delete_files(&check_button_settings_confirm_deletion, &window_main).await {
|
||||||
return;
|
return;
|
||||||
|
@ -66,11 +68,13 @@ pub async fn delete_things(gui_data: GuiData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
match &nb_object.notebook_type {
|
match &nb_object.notebook_type {
|
||||||
NotebookMainEnum::SimilarImages => {
|
NotebookMainEnum::SimilarImages | NotebookMainEnum::Duplicate => {
|
||||||
image_preview_similar_images.hide();
|
if nb_object.notebook_type == NotebookMainEnum::SimilarImages {
|
||||||
}
|
image_preview_similar_images.hide();
|
||||||
NotebookMainEnum::Duplicate => {
|
} else {
|
||||||
image_preview_duplicates.hide();
|
image_preview_duplicates.hide();
|
||||||
|
}
|
||||||
|
*preview_path.borrow_mut() = "".to_string();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
|
||||||
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
||||||
|
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
buttons_hardlink.connect_clicked(move |_| {
|
buttons_hardlink.connect_clicked(move |_| {
|
||||||
let nb_number = notebook_main.current_page().unwrap();
|
let nb_number = notebook_main.current_page().unwrap();
|
||||||
|
@ -30,11 +31,13 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
|
||||||
hardlink_symlink(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, true, &text_view_errors);
|
hardlink_symlink(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, true, &text_view_errors);
|
||||||
|
|
||||||
match &nb_object.notebook_type {
|
match &nb_object.notebook_type {
|
||||||
NotebookMainEnum::SimilarImages => {
|
NotebookMainEnum::SimilarImages | NotebookMainEnum::Duplicate => {
|
||||||
image_preview_similar_images.hide();
|
if nb_object.notebook_type == NotebookMainEnum::SimilarImages {
|
||||||
}
|
image_preview_similar_images.hide();
|
||||||
NotebookMainEnum::Duplicate => {
|
} else {
|
||||||
image_preview_duplicates.hide();
|
image_preview_duplicates.hide();
|
||||||
|
}
|
||||||
|
*preview_path.borrow_mut() = "".to_string();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +53,8 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
|
||||||
|
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
|
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
buttons_symlink.connect_clicked(move |_| {
|
buttons_symlink.connect_clicked(move |_| {
|
||||||
let nb_number = notebook_main.current_page().unwrap();
|
let nb_number = notebook_main.current_page().unwrap();
|
||||||
let tree_view = &main_tree_views[nb_number as usize];
|
let tree_view = &main_tree_views[nb_number as usize];
|
||||||
|
@ -59,11 +64,13 @@ pub fn connect_button_hardlink_symlink(gui_data: &GuiData) {
|
||||||
hardlink_symlink(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, false, &text_view_errors);
|
hardlink_symlink(tree_view, nb_object.column_name, nb_object.column_path, column_color, nb_object.column_selection, false, &text_view_errors);
|
||||||
|
|
||||||
match &nb_object.notebook_type {
|
match &nb_object.notebook_type {
|
||||||
NotebookMainEnum::SimilarImages => {
|
NotebookMainEnum::SimilarImages | NotebookMainEnum::Duplicate => {
|
||||||
image_preview_similar_images.hide();
|
if nb_object.notebook_type == NotebookMainEnum::SimilarImages {
|
||||||
}
|
image_preview_similar_images.hide();
|
||||||
NotebookMainEnum::Duplicate => {
|
} else {
|
||||||
image_preview_duplicates.hide();
|
image_preview_duplicates.hide();
|
||||||
|
}
|
||||||
|
*preview_path.borrow_mut() = "".to_string();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ pub fn connect_button_move(gui_data: &GuiData) {
|
||||||
|
|
||||||
let window_main = gui_data.window_main.clone();
|
let window_main = gui_data.window_main.clone();
|
||||||
|
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
buttons_move.connect_clicked(move |_| {
|
buttons_move.connect_clicked(move |_| {
|
||||||
let nb_number = notebook_main.current_page().unwrap();
|
let nb_number = notebook_main.current_page().unwrap();
|
||||||
let tree_view = &main_tree_views[nb_number as usize];
|
let tree_view = &main_tree_views[nb_number as usize];
|
||||||
|
@ -38,11 +40,13 @@ pub fn connect_button_move(gui_data: &GuiData) {
|
||||||
);
|
);
|
||||||
|
|
||||||
match &nb_object.notebook_type {
|
match &nb_object.notebook_type {
|
||||||
NotebookMainEnum::SimilarImages => {
|
NotebookMainEnum::SimilarImages | NotebookMainEnum::Duplicate => {
|
||||||
image_preview_similar_images.hide();
|
if nb_object.notebook_type == NotebookMainEnum::SimilarImages {
|
||||||
}
|
image_preview_similar_images.hide();
|
||||||
NotebookMainEnum::Duplicate => {
|
} else {
|
||||||
image_preview_duplicates.hide();
|
image_preview_duplicates.hide();
|
||||||
|
}
|
||||||
|
*preview_path.borrow_mut() = "".to_string();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ pub struct GuiData {
|
||||||
pub shared_same_invalid_symlinks: Rc<RefCell<InvalidSymlinks>>,
|
pub shared_same_invalid_symlinks: Rc<RefCell<InvalidSymlinks>>,
|
||||||
pub shared_broken_files_state: Rc<RefCell<BrokenFiles>>,
|
pub shared_broken_files_state: Rc<RefCell<BrokenFiles>>,
|
||||||
|
|
||||||
|
pub preview_path: Rc<RefCell<String>>,
|
||||||
|
|
||||||
//// Entry
|
//// Entry
|
||||||
pub entry_info: gtk::Entry,
|
pub entry_info: gtk::Entry,
|
||||||
|
|
||||||
|
@ -147,6 +149,8 @@ impl GuiData {
|
||||||
let shared_same_invalid_symlinks: Rc<RefCell<_>> = Rc::new(RefCell::new(InvalidSymlinks::new()));
|
let shared_same_invalid_symlinks: Rc<RefCell<_>> = Rc::new(RefCell::new(InvalidSymlinks::new()));
|
||||||
let shared_broken_files_state: Rc<RefCell<_>> = Rc::new(RefCell::new(BrokenFiles::new()));
|
let shared_broken_files_state: Rc<RefCell<_>> = Rc::new(RefCell::new(BrokenFiles::new()));
|
||||||
|
|
||||||
|
let preview_path: Rc<RefCell<_>> = Rc::new(RefCell::new("".to_string()));
|
||||||
|
|
||||||
//// Entry
|
//// Entry
|
||||||
let entry_info: gtk::Entry = builder.object("entry_info").unwrap();
|
let entry_info: gtk::Entry = builder.object("entry_info").unwrap();
|
||||||
|
|
||||||
|
@ -183,6 +187,7 @@ impl GuiData {
|
||||||
shared_same_music_state,
|
shared_same_music_state,
|
||||||
shared_same_invalid_symlinks,
|
shared_same_invalid_symlinks,
|
||||||
shared_broken_files_state,
|
shared_broken_files_state,
|
||||||
|
preview_path,
|
||||||
entry_info,
|
entry_info,
|
||||||
text_view_errors,
|
text_view_errors,
|
||||||
scrolled_window_errors,
|
scrolled_window_errors,
|
||||||
|
|
|
@ -23,12 +23,12 @@ pub const KEY_DELETE: u32 = 119;
|
||||||
pub const KEY_ENTER: u32 = 36;
|
pub const KEY_ENTER: u32 = 36;
|
||||||
pub const KEY_SPACE: u32 = 65;
|
pub const KEY_SPACE: u32 = 65;
|
||||||
|
|
||||||
pub const KEY_DOWN: u32 = 116;
|
// pub const KEY_DOWN: u32 = 116;
|
||||||
pub const KEY_UP: u32 = 111;
|
// pub const KEY_UP: u32 = 111;
|
||||||
pub const KEY_PG_DOWN: u32 = 117;
|
// pub const KEY_PG_DOWN: u32 = 117;
|
||||||
pub const KEY_PG_UP: u32 = 112;
|
// pub const KEY_PG_UP: u32 = 112;
|
||||||
pub const KEY_HOME: u32 = 115;
|
// pub const KEY_HOME: u32 = 115;
|
||||||
pub const KEY_END: u32 = 110;
|
// pub const KEY_END: u32 = 110;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
pub enum PopoverTypes {
|
pub enum PopoverTypes {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use directories_next::ProjectDirs;
|
use directories_next::ProjectDirs;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
@ -108,11 +111,21 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
||||||
|
|
||||||
let check_button_settings_show_preview_duplicates = gui_data.settings.check_button_settings_show_preview_duplicates.clone();
|
let check_button_settings_show_preview_duplicates = gui_data.settings.check_button_settings_show_preview_duplicates.clone();
|
||||||
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
tree_view.connect_button_press_event(opening_double_click_function);
|
tree_view.connect_button_press_event(opening_double_click_function);
|
||||||
tree_view.connect_button_release_event(move |tree_view, _event| {
|
tree_view.connect_button_release_event(move |tree_view, _event| {
|
||||||
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::Duplicate as usize];
|
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::Duplicate as usize];
|
||||||
show_preview(tree_view, &text_view_errors, &check_button_settings_show_preview_duplicates, &image_preview_duplicates, nb_object.column_path, nb_object.column_name);
|
let preview_path = preview_path.clone();
|
||||||
|
show_preview(
|
||||||
|
tree_view,
|
||||||
|
&text_view_errors,
|
||||||
|
&check_button_settings_show_preview_duplicates,
|
||||||
|
&image_preview_duplicates,
|
||||||
|
preview_path,
|
||||||
|
nb_object.column_path,
|
||||||
|
nb_object.column_name,
|
||||||
|
);
|
||||||
|
|
||||||
gtk::Inhibit(false)
|
gtk::Inhibit(false)
|
||||||
});
|
});
|
||||||
|
@ -248,16 +261,19 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
||||||
{
|
{
|
||||||
// Other connects
|
// Other connects
|
||||||
let check_button_settings_show_preview_similar_images = gui_data.settings.check_button_settings_show_preview_similar_images.clone();
|
let check_button_settings_show_preview_similar_images = gui_data.settings.check_button_settings_show_preview_similar_images.clone();
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
tree_view.connect_button_press_event(opening_double_click_function);
|
tree_view.connect_button_press_event(opening_double_click_function);
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
tree_view.connect_button_release_event(move |tree_view, _event| {
|
tree_view.connect_button_release_event(move |tree_view, _event| {
|
||||||
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::SimilarImages as usize];
|
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::SimilarImages as usize];
|
||||||
|
let preview_path = preview_path.clone();
|
||||||
show_preview(
|
show_preview(
|
||||||
tree_view,
|
tree_view,
|
||||||
&text_view_errors,
|
&text_view_errors,
|
||||||
&check_button_settings_show_preview_similar_images,
|
&check_button_settings_show_preview_similar_images,
|
||||||
&image_preview_similar_images,
|
&image_preview_similar_images,
|
||||||
|
preview_path,
|
||||||
nb_object.column_path,
|
nb_object.column_path,
|
||||||
nb_object.column_name,
|
nb_object.column_name,
|
||||||
);
|
);
|
||||||
|
@ -387,6 +403,8 @@ pub fn initialize_gui(gui_data: &mut GuiData) {
|
||||||
evk.connect_key_pressed(opening_enter_function_ported);
|
evk.connect_key_pressed(opening_enter_function_ported);
|
||||||
gui_data.main_notebook.evk_tree_view_broken_files = evk;
|
gui_data.main_notebook.evk_tree_view_broken_files = evk;
|
||||||
|
|
||||||
|
tree_view.connect_button_press_event(opening_double_click_function);
|
||||||
|
|
||||||
tree_view.set_widget_name("tree_view_broken_files");
|
tree_view.set_widget_name("tree_view_broken_files");
|
||||||
gui_data.main_notebook.tree_view_broken_files = tree_view.clone();
|
gui_data.main_notebook.tree_view_broken_files = tree_view.clone();
|
||||||
scrolled_window_broken_files.add(&tree_view);
|
scrolled_window_broken_files.add(&tree_view);
|
||||||
|
@ -484,24 +502,23 @@ fn connect_event_buttons(gui_data: &GuiData) {
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
let check_button_settings_show_preview_duplicates = gui_data.settings.check_button_settings_show_preview_duplicates.clone();
|
let check_button_settings_show_preview_duplicates = gui_data.settings.check_button_settings_show_preview_duplicates.clone();
|
||||||
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
let image_preview_duplicates = gui_data.main_notebook.image_preview_duplicates.clone();
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
gui_data.main_notebook.evk_tree_view_duplicate_finder.connect_key_released(move |event_controller_key, _key_value, key_code, _modifier_type| {
|
gui_data.main_notebook.evk_tree_view_duplicate_finder.connect_key_released(move |event_controller_key, _key_value, key_code, _modifier_type| {
|
||||||
if key_code == KEY_DELETE {
|
if key_code == KEY_DELETE {
|
||||||
glib::MainContext::default().spawn_local(delete_things(gui_data_clone.clone()));
|
glib::MainContext::default().spawn_local(delete_things(gui_data_clone.clone()));
|
||||||
}
|
}
|
||||||
|
let preview_path = preview_path.clone();
|
||||||
// Allowed keys for generating preview,
|
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::Duplicate as usize];
|
||||||
// LEFT, UP, RIGHT, DOWN, Pageup, pagedown, home, end
|
show_preview(
|
||||||
if [KEY_DOWN, KEY_UP, KEY_PG_DOWN, KEY_PG_UP, KEY_HOME, KEY_END].iter().any(|any_key| *any_key == key_code) {
|
&event_controller_key.widget().unwrap().downcast::<gtk::TreeView>().unwrap(),
|
||||||
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::Duplicate as usize];
|
&text_view_errors,
|
||||||
show_preview(
|
&check_button_settings_show_preview_duplicates,
|
||||||
&event_controller_key.widget().unwrap().downcast::<gtk::TreeView>().unwrap(),
|
&image_preview_duplicates,
|
||||||
&text_view_errors,
|
preview_path,
|
||||||
&check_button_settings_show_preview_duplicates,
|
nb_object.column_path,
|
||||||
&image_preview_duplicates,
|
nb_object.column_name,
|
||||||
nb_object.column_path,
|
);
|
||||||
nb_object.column_name,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Empty Folder
|
// Empty Folder
|
||||||
|
@ -546,25 +563,23 @@ fn connect_event_buttons(gui_data: &GuiData) {
|
||||||
let text_view_errors = gui_data.text_view_errors.clone();
|
let text_view_errors = gui_data.text_view_errors.clone();
|
||||||
let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone();
|
let image_preview_similar_images = gui_data.main_notebook.image_preview_similar_images.clone();
|
||||||
let gui_data_clone = gui_data.clone();
|
let gui_data_clone = gui_data.clone();
|
||||||
|
let preview_path = gui_data.preview_path.clone();
|
||||||
|
|
||||||
gui_data.main_notebook.evk_tree_view_similar_images_finder.connect_key_released(move |event_controller_key, _key_value, key_code, _modifier_type| {
|
gui_data.main_notebook.evk_tree_view_similar_images_finder.connect_key_released(move |event_controller_key, _key_value, key_code, _modifier_type| {
|
||||||
if key_code == KEY_DELETE {
|
if key_code == KEY_DELETE {
|
||||||
glib::MainContext::default().spawn_local(delete_things(gui_data_clone.clone()));
|
glib::MainContext::default().spawn_local(delete_things(gui_data_clone.clone()));
|
||||||
}
|
}
|
||||||
|
let preview_path = preview_path.clone();
|
||||||
// Allowed keys for generating preview,
|
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::SimilarImages as usize];
|
||||||
// LEFT, UP, RIGHT, DOWN, Pageup, pagedown, home, end
|
show_preview(
|
||||||
if [KEY_DOWN, KEY_UP, KEY_PG_DOWN, KEY_PG_UP, KEY_HOME, KEY_END].iter().any(|any_key| *any_key == key_code) {
|
&event_controller_key.widget().unwrap().downcast::<gtk::TreeView>().unwrap(),
|
||||||
let nb_object = &NOTEBOOKS_INFOS[NotebookMainEnum::SimilarImages as usize];
|
&text_view_errors,
|
||||||
show_preview(
|
&check_button_settings_show_preview_similar_images,
|
||||||
&event_controller_key.widget().unwrap().downcast::<gtk::TreeView>().unwrap(),
|
&image_preview_similar_images,
|
||||||
&text_view_errors,
|
preview_path,
|
||||||
&check_button_settings_show_preview_similar_images,
|
nb_object.column_path,
|
||||||
&image_preview_similar_images,
|
nb_object.column_name,
|
||||||
nb_object.column_path,
|
);
|
||||||
nb_object.column_name,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Empty Folder
|
// Empty Folder
|
||||||
|
@ -606,7 +621,7 @@ fn connect_event_buttons(gui_data: &GuiData) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_settings_show_preview: &CheckButton, image_preview_similar_images: &Image, column_path: i32, column_name: i32) {
|
fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_settings_show_preview: &CheckButton, image_preview_similar_images: &Image, preview_path: Rc<RefCell<String>>, column_path: i32, column_name: i32) {
|
||||||
let (selected_rows, tree_model) = tree_view.selection().selected_rows();
|
let (selected_rows, tree_model) = tree_view.selection().selected_rows();
|
||||||
|
|
||||||
let mut created_image = false;
|
let mut created_image = false;
|
||||||
|
@ -639,6 +654,14 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
|
||||||
break 'dir;
|
break 'dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let preview_path = preview_path.borrow();
|
||||||
|
let preview_path = preview_path.deref();
|
||||||
|
if file_name == preview_path {
|
||||||
|
return; // Preview is already created, no need to recreate it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let img = match image::open(&file_name) {
|
let img = match image::open(&file_name) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -676,6 +699,12 @@ fn show_preview(tree_view: &TreeView, text_view_errors: &TextView, check_button_
|
||||||
}
|
}
|
||||||
let string_dir = file_dir.to_string_lossy().to_string();
|
let string_dir = file_dir.to_string_lossy().to_string();
|
||||||
image_preview_similar_images.set_from_file(string_dir);
|
image_preview_similar_images.set_from_file(string_dir);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut preview_path = preview_path.borrow_mut();
|
||||||
|
*preview_path = file_name.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = fs::remove_file(&file_dir) {
|
if let Err(e) = fs::remove_file(&file_dir) {
|
||||||
add_text_to_text_view(text_view_errors, format!("Failed to delete temporary image file to {}, reason {}", file_dir.display(), e).as_str());
|
add_text_to_text_view(text_view_errors, format!("Failed to delete temporary image file to {}, reason {}", file_dir.display(), e).as_str());
|
||||||
break 'dir;
|
break 'dir;
|
||||||
|
|
Loading…
Reference in a new issue