clone box button
This commit is contained in:
parent
198ca52059
commit
3caed56733
3 changed files with 221 additions and 68 deletions
153
po/boxbuddy.pot
153
po/boxbuddy.pot
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-02-20 16:36+0000\n"
|
||||
"POT-Creation-Date: 2024-03-30 17:24+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -18,329 +18,348 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. TRANSLATORS: Button tooltip
|
||||
#: src/main.rs:128
|
||||
#: src/main.rs:139
|
||||
msgid "Create A Distrobox"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button tooltip
|
||||
#: src/main.rs:147
|
||||
#: src/main.rs:158
|
||||
msgid "Assemble A Distrobox"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: File type
|
||||
#: src/main.rs:153
|
||||
#: src/main.rs:164
|
||||
msgid "INI-Files"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button tooltip
|
||||
#: src/main.rs:174
|
||||
#: src/main.rs:185
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Menu Item
|
||||
#: src/main.rs:230
|
||||
#: src/main.rs:241
|
||||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Menu Item
|
||||
#: src/main.rs:236
|
||||
#: src/main.rs:247
|
||||
msgid "Set Preferred Terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Menu Item
|
||||
#: src/main.rs:243
|
||||
#: src/main.rs:254
|
||||
msgid "About BoxBuddy"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Menu Item
|
||||
#: src/main.rs:248
|
||||
#: src/main.rs:259
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error message
|
||||
#: src/main.rs:256
|
||||
#: src/main.rs:267
|
||||
msgid "Distrobox not found!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error message
|
||||
#: src/main.rs:261
|
||||
#: src/main.rs:272
|
||||
msgid "Distrobox could not be found, please ensure it is installed!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button tooltip
|
||||
#: src/main.rs:333
|
||||
#: src/main.rs:344
|
||||
msgid "Stop Box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:366
|
||||
#: src/main.rs:377
|
||||
msgid "Open Terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:379
|
||||
#: src/main.rs:390
|
||||
msgid "Upgrade Box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:395
|
||||
#: src/main.rs:406
|
||||
msgid "View Applications"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:425
|
||||
#: src/main.rs:436
|
||||
msgid "Delete Box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:441
|
||||
#: src/main.rs:450
|
||||
msgid "Clone Box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:466
|
||||
msgid "Install .deb File"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.rs:447
|
||||
#: src/main.rs:472
|
||||
msgid "Install .rpm File"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:470 src/main.rs:526
|
||||
#: src/main.rs:520 src/main.rs:576
|
||||
msgid "Create New Distrobox"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Context label of the application doing something
|
||||
#: src/main.rs:476
|
||||
#: src/main.rs:526
|
||||
msgid "Assembling Distroboxes, please wait..."
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:530
|
||||
#: src/main.rs:580
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:535
|
||||
#: src/main.rs:585
|
||||
msgid "Additional Information"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:540 src/main.rs:1003 src/main.rs:1165 src/main.rs:1382
|
||||
#: src/main.rs:590 src/main.rs:1053 src/main.rs:1100 src/main.rs:1328 src/main.rs:1545
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Entry Label - Name input for new distrobox
|
||||
#: src/main.rs:572
|
||||
#: src/main.rs:622 src/main.rs:1136
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Entry Label - Select home directory for new distrobox
|
||||
#: src/main.rs:592
|
||||
#: src/main.rs:642
|
||||
msgid "Home Directory (Leave blank for default)"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS - Label for Dropdown where the user selects the container image to create
|
||||
#: src/main.rs:625
|
||||
#: src/main.rs:675
|
||||
msgid "Image"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS - Label for Toggle when creating box to add systemd support
|
||||
#: src/main.rs:632
|
||||
#: src/main.rs:682
|
||||
msgid "Use init system"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Help text for volume input
|
||||
#: src/main.rs:765
|
||||
#: src/main.rs:815
|
||||
msgid "Enter the location to mount this folder inside your new box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Subheading
|
||||
#: src/main.rs:789
|
||||
#: src/main.rs:839
|
||||
msgid "Additional Volumes:"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Context for the Additional Volumes subheading
|
||||
#: src/main.rs:792
|
||||
#: src/main.rs:842
|
||||
msgid "Additional directories the new box should be able to access"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Window Title - shows list of installed applications in distrobox
|
||||
#: src/main.rs:845
|
||||
#: src/main.rs:895
|
||||
msgid "Installed Applications"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Loading Message
|
||||
#: src/main.rs:856
|
||||
#: src/main.rs:906
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error Message
|
||||
#: src/main.rs:898
|
||||
#: src/main.rs:948
|
||||
msgid "No Applications Installed"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Window Title
|
||||
#: src/main.rs:903
|
||||
#: src/main.rs:953
|
||||
msgid "Available Applications"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:915
|
||||
#: src/main.rs:965
|
||||
msgid "Run"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:931
|
||||
#: src/main.rs:981
|
||||
msgid "Remove From Menu"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:948
|
||||
#: src/main.rs:998
|
||||
msgid "Add To Menu"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Success Message
|
||||
#: src/main.rs:979
|
||||
#: src/main.rs:1029
|
||||
msgid "App Exported!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Success Message
|
||||
#: src/main.rs:985
|
||||
#: src/main.rs:1035
|
||||
msgid "App Removed!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Confirmation Dialogue - has name of Distrobox appended to the end, please leave a space
|
||||
#: src/main.rs:994
|
||||
#: src/main.rs:1044
|
||||
msgid "Are you sure you want to delete "
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Confirmation Dialogue
|
||||
#: src/main.rs:998
|
||||
#: src/main.rs:1048
|
||||
msgid "Really Delete?"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:1005
|
||||
#: src/main.rs:1055
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Success Text
|
||||
#: src/main.rs:1018
|
||||
#: src/main.rs:1068
|
||||
msgid "Box Deleted!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:1091 src/main.rs:1096
|
||||
msgid "Clone"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Title / Instruction label
|
||||
#: src/main.rs:1121
|
||||
msgid "Enter the name of your new box"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.rs:1125
|
||||
msgid "Note: Cloning can take a long time, please be patient"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error Message
|
||||
#: src/main.rs:1042
|
||||
#: src/main.rs:1205
|
||||
msgid "Please install one of the supported terminals:"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error Message
|
||||
#: src/main.rs:1047
|
||||
#: src/main.rs:1210
|
||||
msgid "No supported terminal found"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:1052 src/main.rs:1090 src/main.rs:1108 src/main.rs:1144 src/main.rs:1322 src/main.rs:1347
|
||||
#: src/main.rs:1215 src/main.rs:1253 src/main.rs:1271 src/main.rs:1307 src/main.rs:1485 src/main.rs:1510
|
||||
msgid "Ok"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error Message
|
||||
#: src/main.rs:1065
|
||||
#: src/main.rs:1228
|
||||
msgid "No Boxes"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Instructions
|
||||
#: src/main.rs:1068
|
||||
#: src/main.rs:1231
|
||||
msgid "Click the + at the top-left to create your first box!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error / Info Message
|
||||
#: src/main.rs:1080
|
||||
#: src/main.rs:1243
|
||||
msgid "You appear to be using a Flatpak of BoxBuddy without filesystem access. If you wish to set a Custom Home Directory you will need to grant filesystem access. Please see the <a href='https://dvlv.github.io/BoxBuddyRS/tips'>documentation for details.</a>"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Heading
|
||||
#: src/main.rs:1084
|
||||
#: src/main.rs:1247
|
||||
msgid "Sandboxed Flatpak Detected"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error / Info Message
|
||||
#: src/main.rs:1099
|
||||
#: src/main.rs:1262
|
||||
msgid "Distrobox can already access folders in your home directory - even if you have specified a custom home folder"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Heading
|
||||
#: src/main.rs:1103
|
||||
#: src/main.rs:1266
|
||||
msgid "Volume is already accessible"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Heading
|
||||
#: src/main.rs:1139
|
||||
#: src/main.rs:1302
|
||||
msgid "No Suitable Boxes Found"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:1161
|
||||
#: src/main.rs:1324
|
||||
msgid "Install"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.rs:1188
|
||||
#: src/main.rs:1351
|
||||
msgid "Select a box to install this file into:"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS - Label for Dropdown of existing Boxes to install .deb or .rpm into
|
||||
#: src/main.rs:1206
|
||||
#: src/main.rs:1369
|
||||
msgid "Box"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: File type
|
||||
#: src/main.rs:1244
|
||||
#: src/main.rs:1407
|
||||
msgid "DEB Files"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: File type
|
||||
#: src/main.rs:1279
|
||||
#: src/main.rs:1442
|
||||
msgid "RPM Files"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error / Info Message
|
||||
#: src/main.rs:1312
|
||||
#: src/main.rs:1475
|
||||
msgid "This file is not accessible to Flatpak - please copy it to your Downloads folder, or allow filesystem access. Please see the <a href='https://dvlv.github.io/BoxBuddyRS/tips'>documentation for details.</a>"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Heading
|
||||
#: src/main.rs:1316
|
||||
#: src/main.rs:1479
|
||||
msgid "File Not Accessible"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Heading
|
||||
#: src/main.rs:1342
|
||||
#: src/main.rs:1505
|
||||
msgid "Incorrect File Type"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Popup Header
|
||||
#: src/main.rs:1374
|
||||
#: src/main.rs:1537
|
||||
msgid "Preferred Terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Button Label
|
||||
#: src/main.rs:1378
|
||||
#: src/main.rs:1541
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Instructions label
|
||||
#: src/main.rs:1398
|
||||
#: src/main.rs:1561
|
||||
msgid "Select your preferred terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Label for Dropdown of terminals available
|
||||
#: src/main.rs:1418
|
||||
#: src/main.rs:1581
|
||||
msgid "Terminal"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Success Message
|
||||
#: src/main.rs:1438
|
||||
#: src/main.rs:1601
|
||||
msgid "Terminal Preference Saved!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Error Message
|
||||
#: src/main.rs:1450
|
||||
#: src/main.rs:1613
|
||||
msgid "Sorry, Preference Could Not Be Saved"
|
||||
msgstr ""
|
||||
|
|
|
@ -511,3 +511,12 @@ pub fn install_rpm_in_box(box_name: String, file_path: String) {
|
|||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_box(box_to_clone: String, new_name: String) -> String {
|
||||
stop_box(box_to_clone.clone());
|
||||
|
||||
get_command_output(
|
||||
String::from("distrobox"),
|
||||
Some(&["create", "--clone", &box_to_clone, "--name", &new_name]),
|
||||
)
|
||||
}
|
||||
|
|
127
src/main.rs
127
src/main.rs
|
@ -60,7 +60,7 @@ fn make_window(app: &Application) -> ApplicationWindow {
|
|||
.title("BoxBuddy")
|
||||
.build();
|
||||
|
||||
window.set_default_size(800, 475);
|
||||
window.set_default_size(800, 525);
|
||||
|
||||
make_titlebar(&window);
|
||||
|
||||
|
@ -437,6 +437,20 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B
|
|||
delete_row.add_suffix(&delete_button);
|
||||
delete_row.set_activatable_widget(Some(&delete_button));
|
||||
|
||||
// Clone Box button
|
||||
let clone_button = gtk::Button::from_icon_name("edit-copy-symbolic");
|
||||
clone_button.add_css_class("flat");
|
||||
|
||||
let clone_bn = box_name.clone();
|
||||
let win_clone = window.clone();
|
||||
clone_button.connect_clicked(move |_btn| on_clone_clicked(&win_clone, clone_bn.clone()));
|
||||
|
||||
let clone_row = ActionRow::new();
|
||||
//TRANSLATORS: Button Label
|
||||
clone_row.set_title(&gettext("Clone Box"));
|
||||
clone_row.add_suffix(&clone_button);
|
||||
clone_row.set_activatable_widget(Some(&clone_button));
|
||||
|
||||
// put all into list
|
||||
boxed_list.append(&open_terminal_row);
|
||||
boxed_list.append(&upgrade_row);
|
||||
|
@ -462,6 +476,7 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B
|
|||
boxed_list.append(&binary_row);
|
||||
}
|
||||
|
||||
boxed_list.append(&clone_row);
|
||||
boxed_list.append(&delete_row);
|
||||
|
||||
tab_box.append(&title_box);
|
||||
|
@ -1063,6 +1078,116 @@ fn on_delete_clicked(window: &ApplicationWindow, box_name: String) {
|
|||
d.present()
|
||||
}
|
||||
|
||||
fn on_clone_clicked(window: &ApplicationWindow, box_name: String) {
|
||||
let name_input_popup = gtk::Window::new();
|
||||
name_input_popup.set_transient_for(Some(window));
|
||||
name_input_popup.set_modal(true);
|
||||
name_input_popup.set_default_size(700, 250);
|
||||
|
||||
// TRANSLATORS: Heading Label - has box name appended
|
||||
let clone_prefix = &gettext("Clone");
|
||||
let title_lbl = gtk::Label::new(Some(&format!("{} {}", clone_prefix, box_name.clone())));
|
||||
title_lbl.add_css_class("header");
|
||||
|
||||
// TRANSLATORS: Button Label
|
||||
let create_btn = gtk::Button::with_label(&gettext("Clone"));
|
||||
create_btn.add_css_class("suggested-action");
|
||||
|
||||
// TRANSLATORS: Button Label
|
||||
let cancel_btn = gtk::Button::with_label(&gettext("Cancel"));
|
||||
|
||||
cancel_btn.connect_clicked(move |btn| {
|
||||
let win = btn.root().and_downcast::<gtk::Window>().unwrap();
|
||||
win.destroy();
|
||||
});
|
||||
|
||||
let new_box_titlebar = adw::HeaderBar::builder().title_widget(&title_lbl).build();
|
||||
|
||||
new_box_titlebar.pack_end(&create_btn);
|
||||
new_box_titlebar.pack_start(&cancel_btn);
|
||||
|
||||
name_input_popup.set_titlebar(Some(&new_box_titlebar));
|
||||
|
||||
let main_box = gtk::Box::new(Orientation::Vertical, 20);
|
||||
main_box.set_margin_start(10);
|
||||
main_box.set_margin_end(10);
|
||||
main_box.set_margin_top(10);
|
||||
main_box.set_margin_bottom(10);
|
||||
|
||||
//TRANSLATORS: Title / Instruction label
|
||||
let title_label = gtk::Label::new(Some(&gettext("Enter the name of your new box")));
|
||||
title_label.add_css_class("title-2");
|
||||
|
||||
let notice_label = gtk::Label::new(Some(&gettext(
|
||||
"Note: Cloning can take a long time, please be patient",
|
||||
)));
|
||||
|
||||
let boxed_list = gtk::ListBox::new();
|
||||
boxed_list.add_css_class("boxed-list");
|
||||
|
||||
// name input
|
||||
let name_entry_row = adw::EntryRow::new();
|
||||
name_entry_row.set_hexpand(true);
|
||||
|
||||
// TRANSLATORS: Entry Label - Name input for new distrobox
|
||||
name_entry_row.set_title(&gettext("Name"));
|
||||
|
||||
let loading_spinner = gtk::Spinner::new();
|
||||
|
||||
let loading_spinner_clone = loading_spinner.clone();
|
||||
let win_clone = window.clone();
|
||||
let ne_row = name_entry_row.clone();
|
||||
create_btn.connect_clicked(move |btn| {
|
||||
loading_spinner_clone.start();
|
||||
let mut name = ne_row.text().to_string();
|
||||
|
||||
if name.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
name = name.replace(' ', "-");
|
||||
let name_clone = name.clone();
|
||||
|
||||
let (sender, receiver) =
|
||||
glib::MainContext::channel::<BoxCreatedMessage>(glib::Priority::DEFAULT);
|
||||
|
||||
let bn = box_name.clone();
|
||||
thread::spawn(move || {
|
||||
clone_box(bn, name);
|
||||
sender.send(BoxCreatedMessage::Success).unwrap();
|
||||
});
|
||||
|
||||
let b_clone = btn.clone();
|
||||
let ls_clone = loading_spinner_clone.clone();
|
||||
let w_clone = win_clone.clone();
|
||||
receiver.attach(None, move |msg| match msg {
|
||||
BoxCreatedMessage::Success => {
|
||||
ls_clone.stop();
|
||||
|
||||
let win = b_clone.root().and_downcast::<gtk::Window>().unwrap();
|
||||
win.destroy();
|
||||
|
||||
let num_boxes = get_number_of_boxes();
|
||||
delayed_rerender(&w_clone, Some(num_boxes - 1));
|
||||
|
||||
open_terminal_in_box(name_clone.clone());
|
||||
|
||||
glib::ControlFlow::Continue
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
boxed_list.append(&name_entry_row);
|
||||
main_box.append(&title_label);
|
||||
main_box.append(&boxed_list);
|
||||
main_box.append(¬ice_label);
|
||||
main_box.append(&loading_spinner);
|
||||
|
||||
name_input_popup.set_child(Some(&main_box));
|
||||
|
||||
name_input_popup.present();
|
||||
}
|
||||
|
||||
fn delayed_rerender(window: &ApplicationWindow, active_page: Option<u32>) {
|
||||
let main_box = window.child().unwrap().first_child().unwrap();
|
||||
let main_box_as_box = main_box.downcast::<gtk::Box>().unwrap();
|
||||
|
|
Loading…
Reference in a new issue