Skip to content

Commit

Permalink
fix(tray): vastly improve rendering performance
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeStanger committed Feb 1, 2024
1 parent 0616633 commit 133632d
Show file tree
Hide file tree
Showing 5 changed files with 650 additions and 291 deletions.
291 changes: 0 additions & 291 deletions src/modules/tray.rs

This file was deleted.

104 changes: 104 additions & 0 deletions src/modules/tray/diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use system_tray::message::menu::{MenuItem as MenuItemInfo, ToggleState};

/// Diff change type and associated info.
#[derive(Debug, Clone)]
pub enum Diff {
Add(MenuItemInfo),
Update(i32, MenuItemDiff),
Remove(i32),
}

/// Diff info to be applied to an existing menu item as an update.
#[derive(Debug, Clone)]
pub struct MenuItemDiff {
/// Text of the item,
pub label: Option<String>,
/// Whether the item can be activated or not.
pub enabled: Option<bool>,
/// True if the item is visible in the menu.
pub visible: Option<bool>,
/// Icon name of the item, following the freedesktop.org icon spec.
// pub icon_name: Option<Option<String>>,
/// Describe the current state of a "togglable" item. Can be one of:
/// - Some(true): on
/// - Some(false): off
/// - None: indeterminate
pub toggle_state: Option<ToggleState>,
/// A submenu for this item, typically this would ve revealed to the user by hovering the current item
pub submenu: Vec<Diff>,
}

impl MenuItemDiff {
fn new(old: &MenuItemInfo, new: &MenuItemInfo) -> Self {
macro_rules! diff {
($field:ident) => {
if old.$field == new.$field {
None
} else {
Some(new.$field)
}
};

(&$field:ident) => {
if &old.$field == &new.$field {
None
} else {
Some(new.$field.clone())
}
};
}

Self {
label: diff!(&label),
enabled: diff!(enabled),
visible: diff!(visible),
// icon_name: diff!(&icon_name),
toggle_state: diff!(toggle_state),
submenu: get_diffs(&old.submenu, &new.submenu),
}
}

/// Whether this diff contains any changes
fn has_diff(&self) -> bool {
self.label.is_some()
|| self.enabled.is_some()
|| self.visible.is_some()
// || self.icon_name.is_some()
|| self.toggle_state.is_some()
|| !self.submenu.is_empty()
}
}

/// Gets a diff set between old and new state.
pub fn get_diffs(old: &[MenuItemInfo], new: &[MenuItemInfo]) -> Vec<Diff> {
let mut diffs = vec![];

for new_item in new {
let old_item = old.iter().find(|&item| item.id == new_item.id);

let diff = match old_item {
Some(old_item) => {
let item_diff = MenuItemDiff::new(old_item, new_item);
if item_diff.has_diff() {
Some(Diff::Update(old_item.id, item_diff))
} else {
None
}
}
None => Some(Diff::Add(new_item.clone())),
};

if let Some(diff) = diff {
diffs.push(diff);
}
}

for old_item in old {
let new_item = new.iter().find(|&item| item.id == old_item.id);
if new_item.is_none() {
diffs.push(Diff::Remove(old_item.id));
}
}

diffs
}
Loading

0 comments on commit 133632d

Please sign in to comment.