Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Backend/App.vala
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@
*/

public class Backend.App : Object {
public static string normalize_app_id(string app_id) {
return app_id.replace(".desktop", "").down();
}

public DesktopAppInfo app_info { get; construct; }
public string app_id { get; private set; }
public string normalized_app_id {
owned get { return normalize_app_id(app_id); }
}
public Settings settings { get; private set; }

public App (DesktopAppInfo app_info) {
Expand Down
87 changes: 82 additions & 5 deletions src/Backend/NotifyManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,98 @@ public class Backend.NotifyManager : Object {
}

public Gee.HashMap<string, App> apps { get; construct; } /* string: app-id */
public Gee.HashSet<string> apps_that_have_notified { get; construct; }

public string selected_app_id { get; set; }

construct {
apps = new Gee.HashMap<string, App> ();
var apps_that_have_notified = new Gee.HashMap<string, string> ();

var installed_apps = AppInfo.get_all ();
var settings = new Settings.full (
GLib.SettingsSchemaSource.get_default ().lookup ("io.elementary.notifications", false),
null,
null
);
foreach (var app_id in settings.get_strv("applications")) {
apps_that_have_notified.set(App.normalize_app_id(app_id), app_id);
}

foreach (AppInfo app_info in AppInfo.get_all ()) {
var desktop_app_info = app_info as DesktopAppInfo;
if (desktop_app_info == null) { continue; }

foreach (AppInfo app_info in installed_apps) {
DesktopAppInfo? desktop_app_info = app_info as DesktopAppInfo;
var app = new App(desktop_app_info);

var alternate_names = new Gee.HashMap<string, string> ();
// Even though it is called `alternate_names`, it includes the
// app's formal name as well.
alternate_names.set(App.normalize_app_id(app.app_id), app.app_id);
foreach (var alt_name in desktop_app_info.get_string_list("X-Flatpak-RenamedFrom")) {
alternate_names.set(App.normalize_app_id(alt_name), alt_name);
}

if (desktop_app_info != null && desktop_app_info.get_boolean ("X-GNOME-UsesNotifications")) {
var app = new App (desktop_app_info);
if (desktop_app_info.get_boolean ("X-GNOME-UsesNotifications")) {
apps_that_have_notified.unset(app.normalized_app_id);
apps.@set (app.app_id, app);
} else if (apps_that_have_notified.has_key(app.normalized_app_id)) {
// Notifications in this category don't necessarily declare
// that they send notifications in their desktop file, but
// we've recorded them sending at least one notification.

// We use the desktop entry given in the application's
// notification hint (instead of the desktop file's id) because
// some apps use a different formal name than the name that
// they send notifications as. For example, 'firefox' sends
// notifications belonging to 'Firefox' (note the case
// difference).
var desktop_entry = apps_that_have_notified.get(app.normalized_app_id);
apps_that_have_notified.unset(app.normalized_app_id);
apps.@set (desktop_entry, app);
} else {
foreach (var entry in alternate_names.entries) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might have forgotten to break early out of this loop if we match an alternate name.

var normalized_alt_name = entry.key;
var alt_name = entry.value;

// e.g.: Installing 'Ungoogled Chromium' from Flatpak gives
// you a formal name of
// 'com.github.Eloston.UngoogledChromium', but
// notifications send as 'chromium-browser'. Similar to the
// non-notification-declaring applications above, we want
// to use the application's notification hint's desktop
// entry.
if (apps_that_have_notified.has_key(normalized_alt_name)) {
var desktop_entry = apps_that_have_notified.get(normalized_alt_name);
apps_that_have_notified.unset(normalized_alt_name);
apps.@set(desktop_entry, app);
}
}
}
}

// At this point, all that's left are applications that have sent
// notifications that either have no formal application (e.g.:
// `gnome-power-panel`), or send a different notification desktop entry
// hint that cannot be matched with their formal name (through
// normalization).
//
// Some apps that appear in this collection still might not send
// notifications if enabled from the panel: if the application disables
// notifications internally (e.g.: `nm-applet` can disable
// notifications *before* they're even handed off to elementary).
foreach (var name in apps_that_have_notified.values) {
// XXX Here is where I want to create a new `App` for this unknown
// application, but I don't know where how to start refactoring it,
// as they rely on Desktop entries, which every app in this
// category does *not* have.
// var app = new App.with_desktop_entry(name);
}
// XXX At this point, we're going to overwrite
// `io.elementary.notifications.applications` with whatever's left in
// `apps_that_have_notified`, which will just be a list of the above collection.
//
// Also, as new notifications are added to
// `io.elementary.notifications.applications`, we need to use a signal
// to update the app list in real-time.
}
}