diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 3cc1782c8..3e64a52b7 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -44,6 +44,9 @@ const log = std.log.scoped(.gtk); pub const Options = struct {}; +/// A global variable indicating if user has dismissed the notice about existing crash reports +pub var crash_reports_notice_dismissed = false; + core_app: *CoreApp, config: Config, diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 71bd70d2c..a282ca2d3 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -253,78 +253,7 @@ pub fn init(self: *Window, app: *App) !void { c.gtk_box_append(@ptrCast(box), warning_box); } - // Display a banner informing about crash reports if any exist - { - var crash_dir = try crash.defaultDir(self.app.core_app.alloc); - defer self.app.core_app.alloc.free(crash_dir.path); - var it = try crash_dir.iterator(); - defer it.deinit(); - - if (try it.next()) |_| { - const warning_text = try std.fmt.allocPrintZ( - self.app.core_app.alloc, - \\ ⚠️ There are existing crash reports located at {s}. - \\ If possible, report them to the developers to help improve the application. - , - .{crash_dir.path, crash_dir.path} - ); - defer self.app.core_app.alloc.free(warning_text); - const warning_box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0); - - if ((comptime adwaita.versionAtLeast(1, 3, 0)) and - adwaita.enabled(&app.config) and - adwaita.versionAtLeast(1, 3, 0)) - { - const banner = c.adw_banner_new(warning_text.ptr); - c.adw_banner_set_revealed(@ptrCast(banner), 1); - c.adw_banner_set_use_markup(@ptrCast(banner), 1); - - c.adw_banner_set_button_label(@ptrCast(banner), "Dismiss"); - _ = c.g_signal_connect_data( - banner, - "button-clicked", - c.G_CALLBACK(&adwHideBanner), - banner, - null, - c.G_CONNECT_DEFAULT, - ); - - c.gtk_box_append(@ptrCast(warning_box), @ptrCast(banner)); - } else { - const center_box = c.gtk_center_box_new(); - - const message = c.gtk_label_new(null); - c.gtk_label_set_markup(@ptrCast(message), warning_text.ptr); - c.gtk_label_set_use_markup(@ptrCast(message), 1); - c.gtk_label_set_justify(@ptrCast(message), c.GTK_JUSTIFY_CENTER); - c.gtk_label_set_xalign(@ptrCast(message), 0.5); - c.gtk_widget_set_margin_top(@ptrCast(message), 10); - c.gtk_widget_set_margin_bottom(@ptrCast(message), 10); - - const close_button = c.gtk_button_new_from_icon_name("window-close-symbolic"); - c.gtk_widget_set_margin_top(@ptrCast(close_button), 10); - c.gtk_widget_set_margin_bottom(@ptrCast(close_button), 10); - c.gtk_widget_set_margin_end(@ptrCast(close_button), 10); - _ = c.g_signal_connect_data( - close_button, - "clicked", - c.G_CALLBACK(>kHideWidget), - warning_box, - null, - 0 - ); - - c.gtk_center_box_set_center_widget(@ptrCast(center_box), message); - c.gtk_center_box_set_end_widget(@ptrCast(center_box), close_button); - - c.gtk_box_append(@ptrCast(warning_box), @ptrCast(center_box)); - } - - c.gtk_widget_add_css_class(@ptrCast(warning_box), "background"); - c.gtk_widget_add_css_class(@ptrCast(warning_box), "banner-box"); - c.gtk_box_append(@ptrCast(box), warning_box); - } - } + try self.displayCrashReportsNoticeIfNeeded(app, box); // Setup our toast overlay if we have one self.toast_overlay = if (adwaita.enabled(&self.app.config)) toast: { @@ -650,6 +579,72 @@ pub fn sendToast(self: *Window, title: [:0]const u8) void { c.adw_toast_overlay_add_toast(@ptrCast(toast_overlay), toast); } +fn displayCrashReportsNoticeIfNeeded(self: *Window, app: *App, parent_widget: *c.GtkWidget) !void { + if (App.crash_reports_notice_dismissed) { + return; + } + + const crash_dir = try crash.defaultDir(self.app.core_app.alloc); + defer self.app.core_app.alloc.free(crash_dir.path); + var it = try crash_dir.iterator(); + defer it.deinit(); + + if (try it.next()) |_| { + const warning_text = try std.fmt.allocPrintZ(self.app.core_app.alloc, + \\ ⚠️ There are existing crash reports located at {s}. + \\ If possible, report them to the developers to help improve the application. + , .{ crash_dir.path, crash_dir.path }); + defer self.app.core_app.alloc.free(warning_text); + const warning_box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0); + + if ((comptime adwaita.versionAtLeast(1, 3, 0)) and + adwaita.enabled(&app.config) and + adwaita.versionAtLeast(1, 3, 0)) + { + const banner = c.adw_banner_new(warning_text.ptr); + c.adw_banner_set_revealed(@ptrCast(banner), 1); + c.adw_banner_set_use_markup(@ptrCast(banner), 1); + + c.adw_banner_set_button_label(@ptrCast(banner), "Dismiss"); + _ = c.g_signal_connect_data( + banner, + "button-clicked", + c.G_CALLBACK(&adwHideBanner), + banner, + null, + c.G_CONNECT_DEFAULT, + ); + + c.gtk_box_append(@ptrCast(warning_box), @ptrCast(banner)); + } else { + const center_box = c.gtk_center_box_new(); + + const message = c.gtk_label_new(null); + c.gtk_label_set_markup(@ptrCast(message), warning_text.ptr); + c.gtk_label_set_use_markup(@ptrCast(message), 1); + c.gtk_label_set_justify(@ptrCast(message), c.GTK_JUSTIFY_CENTER); + c.gtk_label_set_xalign(@ptrCast(message), 0.5); + c.gtk_widget_set_margin_top(@ptrCast(message), 10); + c.gtk_widget_set_margin_bottom(@ptrCast(message), 10); + + const close_button = c.gtk_button_new_from_icon_name("window-close-symbolic"); + c.gtk_widget_set_margin_top(@ptrCast(close_button), 10); + c.gtk_widget_set_margin_bottom(@ptrCast(close_button), 10); + c.gtk_widget_set_margin_end(@ptrCast(close_button), 10); + _ = c.g_signal_connect_data(close_button, "clicked", c.G_CALLBACK(>kHideWidget), warning_box, null, 0); + + c.gtk_center_box_set_center_widget(@ptrCast(center_box), message); + c.gtk_center_box_set_end_widget(@ptrCast(center_box), close_button); + + c.gtk_box_append(@ptrCast(warning_box), @ptrCast(center_box)); + } + + c.gtk_widget_add_css_class(@ptrCast(warning_box), "background"); + c.gtk_widget_add_css_class(@ptrCast(warning_box), "banner-box"); + c.gtk_box_append(@ptrCast(parent_widget), warning_box); + } +} + fn gtkRealize(v: *c.GtkWindow, ud: ?*anyopaque) callconv(.C) bool { const self = userdataSelf(ud.?); @@ -1039,11 +1034,13 @@ fn gtkActionReset( fn gtkHideWidget(_: ?*c.GtkWidget, data: ?*anyopaque) void { const widget: *c.GtkWidget = @ptrCast(@alignCast(data)); c.gtk_widget_set_visible(widget, c.FALSE); + App.crash_reports_notice_dismissed = true; } fn adwHideBanner(_: ?*c.GtkWidget, data: ?*anyopaque) void { const banner: *c.AdwBanner = @ptrCast(data); c.adw_banner_set_revealed(banner, c.FALSE); + App.crash_reports_notice_dismissed = true; } /// Returns the surface to use for an action. diff --git a/src/apprt/gtk/style.css b/src/apprt/gtk/style.css index 37eea515d..6274649ed 100644 --- a/src/apprt/gtk/style.css +++ b/src/apprt/gtk/style.css @@ -47,5 +47,5 @@ window.without-window-decoration-and-with-titlebar { } .banner-box:not(:first-child) { - border-top: 1px solid alpha(@borders, 0.2); + border-top: 1px solid alpha(@borders, 0.2); }