Skip to content

Commit cd57d07

Browse files
committed
fix: collapse recently merged tray section into submenu
1 parent 4b0fc17 commit cd57d07

1 file changed

Lines changed: 78 additions & 31 deletions

File tree

src-tauri/src/menu.rs

Lines changed: 78 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use tauri::AppHandle;
2-
use tauri::menu::{CheckMenuItem, IconMenuItem, Menu, MenuItem, PredefinedMenuItem};
2+
use tauri::menu::{CheckMenuItem, IconMenuItem, Menu, MenuItem, PredefinedMenuItem, Submenu};
33
use tauri_plugin_autostart::ManagerExt;
44

55
use crate::avatars::AvatarCache;
@@ -8,6 +8,7 @@ use crate::models::{CheckStatus, PrState, PullRequest};
88
struct PrSection {
99
title: String,
1010
prs: Vec<PullRequest>,
11+
default_collapsed: bool,
1112
}
1213

1314
/// Port of src/lib/stores.ts groupPrs() with tray-specific section ordering.
@@ -42,6 +43,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
4243
.filter(|pr| pr.state == PrState::Open && pr.check_status == CheckStatus::Success)
4344
.cloned()
4445
.collect(),
46+
default_collapsed: false,
4547
},
4648
PrSection {
4749
title: "In Merge Queue".into(),
@@ -50,6 +52,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
5052
.filter(|pr| pr.merge_queue_info.is_some())
5153
.cloned()
5254
.collect(),
55+
default_collapsed: false,
5356
},
5457
PrSection {
5558
title: "Checks Failing".into(),
@@ -62,6 +65,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
6265
})
6366
.cloned()
6467
.collect(),
68+
default_collapsed: false,
6569
},
6670
PrSection {
6771
title: "Changes Requested".into(),
@@ -75,6 +79,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
7579
})
7680
.cloned()
7781
.collect(),
82+
default_collapsed: false,
7883
},
7984
PrSection {
8085
title: "Waiting for Review".into(),
@@ -89,6 +94,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
8994
})
9095
.cloned()
9196
.collect(),
97+
default_collapsed: false,
9298
},
9399
PrSection {
94100
title: "Approved".into(),
@@ -102,10 +108,12 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
102108
})
103109
.cloned()
104110
.collect(),
111+
default_collapsed: false,
105112
},
106113
PrSection {
107114
title: "Draft".into(),
108115
prs: drafts,
116+
default_collapsed: false,
109117
},
110118
PrSection {
111119
title: "Recently Merged".into(),
@@ -114,6 +122,7 @@ fn group_prs(all_prs: &[PullRequest]) -> Vec<PrSection> {
114122
.filter(|pr| pr.state == PrState::Merged)
115123
.cloned()
116124
.collect(),
125+
default_collapsed: true,
117126
},
118127
]
119128
}
@@ -139,42 +148,80 @@ pub fn build_pr_menu(
139148
}
140149
first = false;
141150

142-
// Section header (disabled)
143-
let header_text = format!("{} ({})", section.title, section.prs.len());
144-
let header = MenuItem::with_id(
145-
app,
146-
&format!("header_{}", section.title),
147-
&header_text,
148-
false,
149-
None::<&str>,
150-
)?;
151-
menu.append(&header)?;
151+
if section.default_collapsed {
152+
let sub_title = format!("{} ({})", section.title, section.prs.len());
153+
let submenu = Submenu::with_id(
154+
app,
155+
&format!("section_{}", section.title),
156+
&sub_title,
157+
true,
158+
)?;
159+
160+
let show_count = section.prs.len().min(5);
161+
for pr in &section.prs[..show_count] {
162+
let age = time_ago(&pr.created_at);
163+
let mut label = format!(
164+
" {} #{} — {}",
165+
pr.repository,
166+
pr.number,
167+
truncate(&pr.title, 32),
168+
);
169+
if pr.comment_count > 0 {
170+
label.push_str(&format!(" 💬{}", pr.comment_count));
171+
}
172+
label.push_str(&format!(" {}", age));
152173

153-
// PR items (max 5 per section)
154-
let show_count = section.prs.len().min(5);
155-
for pr in &section.prs[..show_count] {
156-
let age = time_ago(&pr.created_at);
157-
let mut label = format!(
158-
" {} #{} — {}",
159-
pr.repository,
160-
pr.number,
161-
truncate(&pr.title, 32),
162-
);
163-
if pr.comment_count > 0 {
164-
label.push_str(&format!(" 💬{}", pr.comment_count));
174+
let icon = avatar_cache.get_image(&pr.author_login);
175+
let item = IconMenuItem::with_id(
176+
app,
177+
&format!("pr_{}", pr.id),
178+
&label,
179+
true,
180+
icon,
181+
None::<&str>,
182+
)?;
183+
submenu.append(&item)?;
165184
}
166-
label.push_str(&format!(" {}", age));
167185

168-
let icon = avatar_cache.get_image(&pr.author_login);
169-
let item = IconMenuItem::with_id(
186+
menu.append(&submenu)?;
187+
} else {
188+
// Section header (disabled)
189+
let header_text = format!("{} ({})", section.title, section.prs.len());
190+
let header = MenuItem::with_id(
170191
app,
171-
&format!("pr_{}", pr.id),
172-
&label,
173-
true,
174-
icon,
192+
&format!("header_{}", section.title),
193+
&header_text,
194+
false,
175195
None::<&str>,
176196
)?;
177-
menu.append(&item)?;
197+
menu.append(&header)?;
198+
199+
// PR items (max 5 per section)
200+
let show_count = section.prs.len().min(5);
201+
for pr in &section.prs[..show_count] {
202+
let age = time_ago(&pr.created_at);
203+
let mut label = format!(
204+
" {} #{} — {}",
205+
pr.repository,
206+
pr.number,
207+
truncate(&pr.title, 32),
208+
);
209+
if pr.comment_count > 0 {
210+
label.push_str(&format!(" 💬{}", pr.comment_count));
211+
}
212+
label.push_str(&format!(" {}", age));
213+
214+
let icon = avatar_cache.get_image(&pr.author_login);
215+
let item = IconMenuItem::with_id(
216+
app,
217+
&format!("pr_{}", pr.id),
218+
&label,
219+
true,
220+
icon,
221+
None::<&str>,
222+
)?;
223+
menu.append(&item)?;
224+
}
178225
}
179226

180227
}

0 commit comments

Comments
 (0)