Skip to content

Commit a4cc50b

Browse files
authored
Don't wait until pipeline is loaded before showing artifacts (#17)
- closes #4 Makes the whole list item a button and shows the popup even if the pipeline hasn't finished yet.
1 parent 58bffd5 commit a4cc50b

File tree

1 file changed

+81
-83
lines changed

1 file changed

+81
-83
lines changed

src/github/pr.rs

Lines changed: 81 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
use crate::DiffSource;
2+
use crate::github::octokit::RepoClient;
3+
use crate::state::{AppStateRef, SystemCommand};
24
use eframe::egui;
3-
use eframe::egui::{Button, Context, ScrollArea, Spinner};
5+
use eframe::egui::{Context, Popup, ScrollArea, Spinner};
46
use egui_inbox::UiInbox;
57
use futures::TryStreamExt as _;
68
use futures::stream::FuturesUnordered;
79
use graphql_client::GraphQLQuery;
810
use octocrab::Octocrab;
11+
use octocrab::models::{RunId, workflows::WorkflowListArtifact};
912
use re_ui::egui_ext::boxed_widget::BoxedWidgetLocalExt as _;
13+
use re_ui::list_item::{LabelContent, ListItemContentButtonsExt as _, list_item_scope};
14+
use re_ui::{SectionCollapsingHeader, UiExt as _, icons};
1015
use std::collections::hash_map::Entry;
1116
use std::collections::{HashMap, HashSet};
1217
use std::task::Poll;
13-
// Import octocrab models
14-
use crate::github::octokit::RepoClient;
15-
use crate::state::{AppStateRef, SystemCommand};
16-
use octocrab::models::{RunId, workflows::WorkflowListArtifact};
17-
use re_ui::list_item::{LabelContent, ListItemContentButtonsExt as _, list_item_scope};
18-
use re_ui::{OnResponseExt as _, SectionCollapsingHeader, UiExt as _, icons};
19-
// use chrono::DateTime;
2018
pub type GitObjectID = String;
2119
pub type DateTime = String;
2220
#[expect(clippy::upper_case_acronyms)]
2321
pub type URI = String;
2422

25-
// The paths are relative to the directory where your `Cargo.toml` is located.
26-
// Both json and the GraphQL schema language are supported as sources for the schema
2723
#[derive(GraphQLQuery, Debug)]
2824
#[graphql(
2925
schema_path = "github.graphql",
@@ -33,6 +29,8 @@ pub type URI = String;
3329
pub struct PrDetailsQuery;
3430
use crate::github::model::{GithubArtifactLink, GithubPrLink, PrNumber};
3531
use anyhow::{Error, Result, anyhow};
32+
use eframe::emath::RectAlign;
33+
use re_ui::menu::menu_style;
3634

3735
pub fn parse_github_pr_url(url: &str) -> Result<(String, String, u32), String> {
3836
// Parse URLs like: https://github.com/rerun-io/rerun/pull/11253
@@ -162,27 +160,22 @@ impl GithubPr {
162160
Entry::Occupied(_) => {}
163161
Entry::Vacant(entry) => {
164162
entry.insert(Poll::Pending);
165-
166-
let workflow_run_ids = pr_data
167-
.commits
168-
.iter()
169-
.find(|c| c.sha == sha)
170-
.map(|c| c.workflow_run_ids.clone())
171-
.unwrap_or_default();
172-
173-
let client =
174-
RepoClient::new(self.client.clone(), self.link.repo.clone());
175-
self.inbox.spawn(move |tx| async move {
176-
let artifacts =
177-
fetch_commit_artifacts(&client, workflow_run_ids).await;
178-
tx.send(GithubPrCommand::FetchedCommitArtifacts {
179-
sha,
180-
artifacts,
181-
})
182-
.ok();
183-
});
184163
}
185164
}
165+
166+
let workflow_run_ids = pr_data
167+
.commits
168+
.iter()
169+
.find(|c| c.sha == sha)
170+
.map(|c| c.workflow_run_ids.clone())
171+
.unwrap_or_default();
172+
173+
let client = RepoClient::new(self.client.clone(), self.link.repo.clone());
174+
self.inbox.spawn(move |tx| async move {
175+
let artifacts = fetch_commit_artifacts(&client, workflow_run_ids).await;
176+
tx.send(GithubPrCommand::FetchedCommitArtifacts { sha, artifacts })
177+
.ok();
178+
});
186179
}
187180
}
188181
}
@@ -335,67 +328,72 @@ pub fn pr_ui(ui: &mut egui::Ui, state: &AppStateRef<'_>, pr: &GithubPr) {
335328
let item = ui.list_item();
336329

337330
let button = match &commit.status {
338-
CommitState::Failure => Button::image(
339-
icons::ERROR.as_image().tint(ui.tokens().alert_error.icon),
340-
)
341-
.boxed_local(),
331+
CommitState::Failure => icons::ERROR
332+
.as_image()
333+
.tint(ui.tokens().alert_error.icon)
334+
.boxed_local(),
342335
CommitState::Pending => Spinner::new().boxed_local(),
343-
CommitState::Success => Button::image(
344-
icons::SUCCESS
345-
.as_image()
346-
.tint(ui.tokens().alert_success.icon),
347-
)
348-
.boxed_local(),
336+
CommitState::Success => icons::SUCCESS
337+
.as_image()
338+
.tint(ui.tokens().alert_success.icon)
339+
.boxed_local(),
349340
};
350341

351-
let button = button.on_menu(|ui| {
352-
ui.set_min_width(250.0);
353-
match data.artifacts.get(&commit.sha) {
354-
None => {
355-
pr.inbox
356-
.sender()
357-
.send(GithubPrCommand::FetchCommitArtifacts {
358-
sha: commit.sha.clone(),
359-
})
360-
.ok();
361-
}
362-
Some(Poll::Pending) => {
363-
ui.spinner();
364-
}
365-
Some(Poll::Ready(Err(error))) => {
366-
ui.colored_label(
367-
ui.visuals().error_fg_color,
368-
format!("Error: {error}"),
369-
);
370-
}
371-
#[expect(clippy::excessive_nesting)]
372-
Some(Poll::Ready(Ok(artifacts))) => {
373-
if artifacts.is_empty() {
374-
ui.label("No artifacts found");
375-
} else {
376-
for artifact in artifacts {
377-
if ui.button(&artifact.data.name).clicked() {
378-
selected_source = Some(DiffSource::GHArtifact(
379-
GithubArtifactLink {
380-
repo: pr.link.repo.clone(),
381-
artifact_id: artifact.data.id,
382-
name: Some(artifact.data.name.clone()),
383-
branch_name: Some(data.head_branch.clone()),
384-
run_id: Some(artifact.run_id),
385-
},
386-
));
387-
}
388-
}
389-
}
390-
}
391-
}
392-
});
393-
394342
let content = LabelContent::new(&commit.message)
395343
.with_button(button)
396344
.with_always_show_buttons(true);
397345

398-
item.show_hierarchical(ui, content);
346+
let response = item.show_hierarchical(ui, content);
347+
if response.clicked() {
348+
pr.inbox
349+
.sender()
350+
.send(GithubPrCommand::FetchCommitArtifacts {
351+
sha: commit.sha.clone(),
352+
})
353+
.ok();
354+
}
355+
Popup::menu(&response)
356+
.align(RectAlign::BOTTOM_END)
357+
.style(menu_style())
358+
.show(|ui| {
359+
ui.set_min_width(250.0);
360+
match data.artifacts.get(&commit.sha) {
361+
None => {
362+
// Loading should be triggered by the click handler above
363+
}
364+
Some(Poll::Pending) => {
365+
ui.spinner();
366+
}
367+
Some(Poll::Ready(Err(error))) => {
368+
ui.colored_label(
369+
ui.visuals().error_fg_color,
370+
format!("Error: {error}"),
371+
);
372+
}
373+
#[expect(clippy::excessive_nesting)]
374+
Some(Poll::Ready(Ok(artifacts))) => {
375+
if artifacts.is_empty() {
376+
ui.label("No artifacts found");
377+
} else {
378+
for artifact in artifacts {
379+
if ui.button(&artifact.data.name).clicked() {
380+
selected_source = Some(DiffSource::GHArtifact(
381+
GithubArtifactLink {
382+
repo: pr.link.repo.clone(),
383+
artifact_id: artifact.data.id,
384+
name: Some(artifact.data.name.clone()),
385+
branch_name: Some(
386+
data.head_branch.clone(),
387+
),
388+
run_id: Some(artifact.run_id),
389+
},
390+
));
391+
}
392+
}
393+
}
394+
}
395+
}
396+
});
399397
}
400398
});
401399
});

0 commit comments

Comments
 (0)