Skip to content

Commit

Permalink
Confirm exit if file transfer is in progress
Browse files Browse the repository at this point in the history
Closes #3.
  • Loading branch information
v1993 committed Oct 29, 2023
1 parent 6f50c69 commit 10e4c5c
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 35 deletions.
80 changes: 52 additions & 28 deletions po/nxdumpclient.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: nxdumpclient\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-28 13:37+0300\n"
"POT-Creation-Date: 2023-10-29 12:06+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down Expand Up @@ -39,7 +39,7 @@ msgstr ""
msgid "Client for dumping over USB with nxdumptool"
msgstr ""

#: data/org.v1993.NXDumpClient.appdata.xml.in:15 src/Application.vala:212
#: data/org.v1993.NXDumpClient.appdata.xml.in:15 src/Application.vala:247
msgid "Client for dumping over USB with nxdumptool."
msgstr ""

Expand Down Expand Up @@ -203,32 +203,32 @@ msgctxt "version string"
msgid "N/A"
msgstr ""

#: src/widgets/FileRow.blp:13
#: src/widgets/FileRow.blp:15
msgctxt "FileRow button"
msgid "Reset to default"
msgstr ""

#: src/Window.blp:26
#: src/Window.blp:27
msgid "No Devices Connected"
msgstr ""

#: src/Window.blp:27
#: src/Window.blp:28
msgid "Connect your Switch and start nxdumptool to proceed"
msgstr ""

#: src/Window.blp:52
#: src/Window.blp:53
msgid "_Preferences"
msgstr ""

#: src/Window.blp:53
#: src/Window.blp:54
msgid "_Keyboard Shortcuts"
msgstr ""

#: src/Window.blp:54
#: src/Window.blp:55
msgid "_About NX Dump Client"
msgstr ""

#: src/Window.blp:57
#: src/Window.blp:58
msgid "_Quit"
msgstr ""

Expand All @@ -255,85 +255,109 @@ msgstr ""
msgid "Error handling a new device"
msgstr ""

#: src/UsbDeviceClient.vala:156
#: src/UsbDeviceClient.vala:157
#, c-format
msgid "Not enough space for dump (%s required)"
msgstr ""

#: src/UsbDeviceClient.vala:552
#: src/UsbDeviceClient.vala:557
msgid "NCA checksum verification failed (non-standard dump options?)"
msgstr ""

#: src/UsbDeviceClient.vala:580
#: src/UsbDeviceClient.vala:585
msgid "NSP header"
msgstr ""

#: src/Application.vala:105
#: src/Application.vala:36
msgid "File transfer is in progres"
msgstr ""

#: src/Application.vala:103
msgid "Confirm exit"
msgstr ""

#: src/Application.vala:103
msgid ""
"A file transfer is currently in progress.\n"
"Are you sure you want to quit?"
msgstr ""

#: src/Application.vala:108
msgctxt "deny app exit"
msgid "Cancel"
msgstr ""

#: src/Application.vala:109
msgctxt "confirm app exit"
msgid "Confirm exit"
msgstr ""

#: src/Application.vala:140
msgid "nxdumptool device connected"
msgstr ""

#: src/Application.vala:113
#: src/Application.vala:148
msgid "nxdumptool device disconnected"
msgstr ""

#: src/Application.vala:130
#: src/Application.vala:165
msgid "File transfer started"
msgstr ""

#: src/Application.vala:155
#: src/Application.vala:190
msgid "File transfer complete"
msgstr ""

#: src/Application.vala:158 src/Application.vala:164
#: src/Application.vala:193 src/Application.vala:199
msgid "Show in folder"
msgstr ""

#: src/Application.vala:163
#: src/Application.vala:198
#, c-format
msgid "Transfer of file “%s” complete"
msgstr ""

#: src/Application.vala:185
#: src/Application.vala:220
msgid "File transfer canceled"
msgstr ""

#: src/Application.vala:185
#: src/Application.vala:220
msgid "File transfer failed"
msgstr ""

#: src/Application.vala:192
#: src/Application.vala:227
#, c-format
msgid "Transfer of file “%s” canceled"
msgstr ""

#: src/Application.vala:192
#: src/Application.vala:227
#, c-format
msgid "Transfer of file “%s” failed"
msgstr ""

#: src/Application.vala:205
#: src/Application.vala:240
msgid ""
"Launch without a visible window if allowed to in settings, exit otherwise"
msgstr ""

#: src/Application.vala:206
#: src/Application.vala:241
msgid "Print udev rules required for USB access and exit"
msgstr ""

#: src/Application.vala:207
#: src/Application.vala:242
msgid "Print application version and exit"
msgstr ""

#: src/Application.vala:331
#: src/Application.vala:366
#, c-format
msgid "Failed to initialize USB context: %s\n"
msgstr ""

#: src/Application.vala:391
#: src/Application.vala:426
msgid "translator-credits"
msgstr ""

#: src/Application.vala:398
#: src/Application.vala:433
msgctxt "credits section header"
msgid "nxdumptool team"
msgstr ""
Expand Down
53 changes: 52 additions & 1 deletion src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ namespace NXDumpClient {
new Application().show_error(desc, message);
}

internal class FileTransferInhibitor: Object {
public static uint current_count { get; private set; }

private uint cookie = 0;

construct {
cookie = new Application().inhibit(null, LOGOUT | SUSPEND, _("File transfer is in progres"));
++current_count;
debug("Inhibited, cookie: %u, active inhibitors: %u", cookie, current_count);
}

~FileTransferInhibitor() {
var app = new Application();
// May be false during app shutdown
if (app.is_registered) {
app.uninhibit(cookie);
}
--current_count;
debug("Uninhibited, cookie: %u, active inhibitors: %u", cookie, current_count);
}
}

[SingleInstance]
public class Application: Adw.Application {
// Settings object and corresponding fields
Expand Down Expand Up @@ -77,6 +99,19 @@ namespace NXDumpClient {
return !cancellable.is_cancelled() && main_window != null;
}

public async bool query_app_exit() {
var dialog = new Adw.MessageDialog(main_window, _("Confirm exit"), _("A file transfer is currently in progress.\nAre you sure you want to quit?")) {
close_response = "cancel",
default_response = "confirm",

};
dialog.add_response("cancel", C_("deny app exit", "Cancel"));
dialog.add_response("confirm", C_("confirm app exit", "Confirm exit"));
dialog.set_response_appearance("confirm", DESTRUCTIVE);
var res = yield dialog.choose(cancellable);
return res == "confirm";
}

public void show_error(string desc, string message) {
if (should_show_toast()) {
var toast = new Adw.Toast.format("<span color=\"red\">%s</span>: %s", desc, message) {
Expand Down Expand Up @@ -215,7 +250,7 @@ namespace NXDumpClient {
// In-app only
{ "about", this.on_about_action },
{ "preferences", this.on_preferences_action },
{ "quit", this.quit },
{ "quit", this.on_quit_with_confirmation_action },

// May be invoked externally (e.g. from a notification)
{ "show-file", this.on_show_file_action, "s" }
Expand Down Expand Up @@ -420,6 +455,22 @@ namespace NXDumpClient {
show_file.begin(File.new_for_uri(param.get_string()));
}

private void on_quit_with_confirmation_action() {
// Do not test if background is enabled - app exit bypasses that
if (FileTransferInhibitor.current_count == 0) {
quit();
} else {
quit_with_confirmation.begin();
}
}

private async void quit_with_confirmation() {
var res = yield query_app_exit();
if (res) {
quit();
}
}

private async void show_file(File file) {
hold(); // Ensure that we won't exit if invoked without activation
try {
Expand Down
7 changes: 6 additions & 1 deletion src/UsbDeviceClient.vala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace NXDumpClient {
int64 header_size;
File file;
FileOutputStream ostream;
FileTransferInhibitor inhibitor;
}

private const string COMMAND_MAGIC = "NXDT";
Expand Down Expand Up @@ -376,14 +377,17 @@ namespace NXDumpClient {
var filename = (string)istream.read_bytes(0x301, cancellable).get_data();
File file;
FileOutputStream ostream;
FileTransferInhibitor inhibitor;

try {
if (nsp_dump_status == null) {
file = yield get_dump_target(filename, file_size, cancellable);
ostream = yield file.replace_async(null, false, REPLACE_DESTINATION, Priority.DEFAULT, cancellable);
inhibitor = new FileTransferInhibitor();
} else {
file = nsp_dump_status.file;
ostream = nsp_dump_status.ostream;
inhibitor = nsp_dump_status.inhibitor;
}
} catch(Error e) {
throw error_to_recoverable(e);
Expand Down Expand Up @@ -417,7 +421,8 @@ namespace NXDumpClient {
transferred_size = 0,
header_size = nsp_header_size,
file = file,
ostream = ostream
ostream = ostream,
inhibitor = inhibitor,
};

yield send_status_success();
Expand Down
1 change: 1 addition & 0 deletions src/Window.blp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ template $NXDumpClientWindow: Adw.ApplicationWindow {
default-width: 600;
default-height: 500;
title: _("NX Dump Client");
close-request => $on_close_request();

Box {
orientation: vertical;
Expand Down
41 changes: 36 additions & 5 deletions src/Window.vala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ namespace NXDumpClient {
[GtkChild]
private unowned Gtk.Stack content_selector;

protected Gtk.SelectionModel devices_model { get; set; }
public Gtk.SelectionModel devices_model { get; construct; }

private bool close_confirmed = false;

public Window(Gtk.Application app) {
Object(
Expand Down Expand Up @@ -56,24 +58,53 @@ namespace NXDumpClient {
}

[GtkCallback]
void setup_element(Gtk.SignalListItemFactory factory, Object o) {
private bool on_close_request() {
// Return true to NOT close, false to CLOSE
if (close_confirmed) {
return false; // Close, queried the user and was allowed to
}

if (FileTransferInhibitor.current_count == 0) {
return false; // Close, nothing is running in background
}

var app = new Application();
if (app.hold_background_reference) {
return false; // Close, application will keep running
}

query_for_close.begin();
return true; // Do not close; present a query
}

private async void query_for_close() {
var result = yield new Application().query_app_exit();
if (result) {
close_confirmed = true;
close();
close_confirmed = false;
}
}

[GtkCallback]
private void setup_element(Gtk.SignalListItemFactory factory, Object o) {
var litem = (Gtk.ListItem)o;
litem.child = new DeviceStatusRow();
}

[GtkCallback]
void teardown_element(Gtk.SignalListItemFactory factory, Object o) {
private void teardown_element(Gtk.SignalListItemFactory factory, Object o) {
}

[GtkCallback]
void bind_element(Gtk.SignalListItemFactory factory, Object o) {
private void bind_element(Gtk.SignalListItemFactory factory, Object o) {
var litem = (Gtk.ListItem)o;
var child = (DeviceStatusRow)litem.child;
child.bind((UsbDeviceClient)litem.item);
}

[GtkCallback]
void unbind_element(Gtk.SignalListItemFactory factory, Object o) {
private void unbind_element(Gtk.SignalListItemFactory factory, Object o) {
var litem = (Gtk.ListItem)o;
var child = (DeviceStatusRow)litem.child;
child.unbind();
Expand Down

0 comments on commit 10e4c5c

Please sign in to comment.