feat: syntax highlighting for diff view
This commit is contained in:
@@ -10,7 +10,7 @@ use crate::{
|
||||
font_icon::{FontIcon, FontIconSvg, font_icon},
|
||||
text::text,
|
||||
},
|
||||
query::{self, QueryStatus, read_query, use_query},
|
||||
query::{self, QueryStatus, read_query, use_query, watch_query},
|
||||
util::str::ToSharedString,
|
||||
};
|
||||
|
||||
@@ -56,28 +56,44 @@ pub(crate) fn new(cx: &mut gpui::Context<IssueList>) -> IssueList {
|
||||
|
||||
impl IssueList {
|
||||
fn on_create(&mut self, cx: &mut gpui::Context<Self>) {
|
||||
cx.observe(&self.pr_query, |this, _, cx| {
|
||||
let data = read_query(&this.pr_query, cx);
|
||||
if let QueryStatus::Loaded(res) = data {
|
||||
let old_len = this.list_state.item_count();
|
||||
let new_len = res.items.len();
|
||||
let pr_query = self.pr_query.clone();
|
||||
|
||||
let new_items = res.items.iter().enumerate().map(|(i, it)| IssueListItem {
|
||||
watch_query(&pr_query, Self::sync_pr_query, cx).detach();
|
||||
}
|
||||
|
||||
fn sync_pr_query(
|
||||
&mut self,
|
||||
query: &query::Entity<api::issues::ListPullRequests>,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
let data = read_query(query, cx);
|
||||
if let QueryStatus::Loaded(res) = data {
|
||||
let selected_id = self
|
||||
.list_items
|
||||
.iter()
|
||||
.find(|item| item.is_selected)
|
||||
.map(|item| item.id.clone());
|
||||
let old_len = self.list_state.item_count();
|
||||
let new_len = res.items.len();
|
||||
|
||||
self.list_items = res
|
||||
.items
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, it)| IssueListItem {
|
||||
is_selected: selected_id.as_ref().is_some_and(|id| *id == it.id),
|
||||
id: it.id.clone(),
|
||||
repo_name: Some(it.repo_slug.to_shared_string()),
|
||||
title: it.title.to_shared_string(),
|
||||
description: None,
|
||||
status: it.state,
|
||||
is_selected: false,
|
||||
is_last: i == new_len - 1,
|
||||
is_draft: it.is_draft,
|
||||
});
|
||||
})
|
||||
.collect();
|
||||
|
||||
this.list_items.splice(old_len..old_len, new_items);
|
||||
this.list_state.splice(old_len..old_len, new_len);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
self.list_state.splice(0..old_len, new_len);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_item_click(&mut self, i: usize, cx: &mut gpui::Context<Self>) {
|
||||
|
||||
@@ -6,9 +6,10 @@ use crate::{
|
||||
diff_view::{DiffViewContent, DiffViewState, diff_view},
|
||||
text::text,
|
||||
},
|
||||
query::{self, QueryStatus, observe_query, read_query, use_query},
|
||||
query::{self, QueryStatus, read_query, use_query, watch_query},
|
||||
util,
|
||||
};
|
||||
use gpui::{ParentElement, Styled, div};
|
||||
use gpui::{AppContext, ParentElement, Styled, div};
|
||||
|
||||
pub(crate) struct PullRequestDiffView {
|
||||
selected_file_path: Option<Arc<str>>,
|
||||
@@ -104,23 +105,68 @@ impl PullRequestDiffView {
|
||||
},
|
||||
cx,
|
||||
);
|
||||
|
||||
_ = observe_query(
|
||||
&content_diff_query,
|
||||
|this, query, cx| {
|
||||
if let QueryStatus::Loaded(diff) = read_query(query, cx) {
|
||||
println!("diff len {}", diff.len());
|
||||
this.diff_view_state.reset(diff.len());
|
||||
this.diff_view_content = Some(Arc::clone(diff).into());
|
||||
}
|
||||
cx.notify();
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.detach();
|
||||
_ = watch_query(&content_diff_query, Self::sync_content_diff_query, cx).detach();
|
||||
|
||||
self.content_diff_query = Some(content_diff_query);
|
||||
}
|
||||
|
||||
fn sync_content_diff_query(
|
||||
&mut self,
|
||||
query: &query::Entity<api::repo::FetchFileDiff>,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
if let Some(diff) = {
|
||||
match read_query(query, cx) {
|
||||
| QueryStatus::Loaded(diff) => Some(Arc::clone(diff)),
|
||||
| _ => None,
|
||||
}
|
||||
} {
|
||||
self.load_diff_view(diff, cx);
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
fn load_diff_view(
|
||||
&mut self,
|
||||
content_diff: Arc<util::diff::ContentDiff>,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
let theme = app::current_theme(cx);
|
||||
let old_content = content_diff.old_content.clone();
|
||||
let new_content = content_diff.new_content.clone();
|
||||
|
||||
self.diff_view_state.reset(content_diff.len());
|
||||
self.diff_view_content = Some(content_diff.into());
|
||||
|
||||
let theme_syntax = theme.syntax;
|
||||
|
||||
if let Some(path) = &self.selected_file_path {
|
||||
let path = Arc::clone(&path);
|
||||
let file_type = util::file::file_type_from_path(&path);
|
||||
|
||||
let t1 = cx.background_spawn(async move {
|
||||
util::syntax_highlight::highlight_content(old_content, file_type, &theme_syntax)
|
||||
});
|
||||
let t2 = cx.background_spawn(async move {
|
||||
util::syntax_highlight::highlight_content(new_content, file_type, &theme_syntax)
|
||||
});
|
||||
|
||||
_ = cx
|
||||
.spawn(async move |weak, cx| match tokio::join!(t1, t2) {
|
||||
| (Some(old_side_highlights), Some(new_side_highlights)) => {
|
||||
_ = weak.update(cx, |this, cx| {
|
||||
this.diff_view_state
|
||||
.set_old_side_highlights(old_side_highlights);
|
||||
this.diff_view_state
|
||||
.set_new_side_highlights(new_side_highlights);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
| _ => {}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::Render for PullRequestDiffView {
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
markdown::{self, MarkdownText},
|
||||
text::text,
|
||||
},
|
||||
query::{self, QueryStatus, read_query, use_query},
|
||||
query::{self, QueryStatus, read_query, use_query, watch_query},
|
||||
screen::dashboard::pull_request_diff_view::{self, PullRequestDiffView},
|
||||
};
|
||||
|
||||
@@ -46,21 +46,20 @@ impl PullRequestView {
|
||||
|
||||
self.pull_request_query = Some(query.clone());
|
||||
|
||||
_ = cx
|
||||
.observe(&query.clone(), move |this, _, cx| {
|
||||
this.load_markdown_content(cx);
|
||||
this.load_pr_diff(cx);
|
||||
})
|
||||
.detach();
|
||||
|
||||
// cached query will not trigger observe callback
|
||||
// this is required so that content is loaded immediately for cached query
|
||||
self.load_markdown_content(cx);
|
||||
self.load_pr_diff(cx);
|
||||
_ = watch_query(&query, Self::sync_pull_request_query, cx).detach();
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn sync_pull_request_query(
|
||||
&mut self,
|
||||
_query: &query::Entity<api::issues::FetchPullRequest>,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
self.load_markdown_content(cx);
|
||||
self.load_pr_diff(cx);
|
||||
}
|
||||
|
||||
fn load_markdown_content(&mut self, cx: &mut gpui::Context<Self>) {
|
||||
let Some(query) = &self.pull_request_query else {
|
||||
return;
|
||||
@@ -115,41 +114,41 @@ impl PullRequestView {
|
||||
.rounded_full();
|
||||
|
||||
match pr.state {
|
||||
| api::issues::PullRequestState::Open => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.success_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestArrow)
|
||||
.size_3()
|
||||
.text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Open")
|
||||
.text_color(theme.colors.success_on_solid)
|
||||
| api::issues::PullRequestState::Open => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.success_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestArrow)
|
||||
.size_3()
|
||||
.text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Open")
|
||||
.text_color(theme.colors.success_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Closed => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.danger_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestClosed)
|
||||
.size_3()
|
||||
.text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Closed")
|
||||
.text_color(theme.colors.danger_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Merged => {
|
||||
status_pill = status_pill.bg(theme.colors.accent_solid).child(
|
||||
text("Merged")
|
||||
.text_color(theme.colors.accent_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Closed => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.danger_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestClosed)
|
||||
.size_3()
|
||||
.text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Closed")
|
||||
.text_color(theme.colors.danger_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Merged => {
|
||||
status_pill = status_pill.bg(theme.colors.accent_solid).child(
|
||||
text("Merged")
|
||||
.text_color(theme.colors.accent_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let merge_text = pr.author.as_ref().map(|author| {
|
||||
@@ -284,23 +283,23 @@ impl gpui::Render for PullRequestView {
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
div().size_full().child(match &self.pull_request_query {
|
||||
| Some(q) => match read_query(q, cx) {
|
||||
| QueryStatus::Loaded(pr) => match &self.diff_view {
|
||||
| Some(v) => v.clone().into_any_element(),
|
||||
| None => self.pr_content(pr, cx),
|
||||
},
|
||||
| Some(q) => match read_query(q, cx) {
|
||||
| QueryStatus::Loaded(pr) => match &self.diff_view {
|
||||
| Some(v) => v.clone().into_any_element(),
|
||||
| None => self.pr_content(pr, cx),
|
||||
},
|
||||
|
||||
| QueryStatus::Err(e) => div()
|
||||
.size_full()
|
||||
.child(format!("{:?}", e))
|
||||
.into_any_element(),
|
||||
| QueryStatus::Loading => div()
|
||||
.size_full()
|
||||
.child("loading pr content")
|
||||
.into_any_element(),
|
||||
},
|
||||
| QueryStatus::Err(e) => div()
|
||||
.size_full()
|
||||
.child(format!("{:?}", e))
|
||||
.into_any_element(),
|
||||
| QueryStatus::Loading => div()
|
||||
.size_full()
|
||||
.child("loading pr content")
|
||||
.into_any_element(),
|
||||
},
|
||||
|
||||
| None => div().size_full().child("no pr selected").into_any_element(),
|
||||
| None => div().size_full().child("no pr selected").into_any_element(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ impl Screen {
|
||||
fn on_create(&mut self, cx: &mut gpui::Context<Self>) {
|
||||
_ = cx
|
||||
.subscribe(&self.issue_list, |this, _, event, cx| match event {
|
||||
| issue_list::Event::ItemSelected(pr_id) => {
|
||||
this.handle_issue_list_item_selected(pr_id, cx);
|
||||
}
|
||||
| issue_list::Event::ItemSelected(pr_id) => {
|
||||
this.handle_issue_list_item_selected(pr_id, cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ use std::{ops::Range, sync::Arc};
|
||||
use bytes::Bytes;
|
||||
use gpui::{
|
||||
AnyElement, AppContext, InteractiveElement, IntoElement, ParentElement,
|
||||
StatefulInteractiveElement,
|
||||
Styled, div, point, px, size,
|
||||
StatefulInteractiveElement, Styled, div, point, px, size,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -54,6 +53,8 @@ pub(crate) struct Screen {
|
||||
struct DiffCase {
|
||||
title: &'static str,
|
||||
description: &'static str,
|
||||
old_line_count: usize,
|
||||
new_line_count: usize,
|
||||
old_lines: Vec<SourceLine>,
|
||||
new_lines: Vec<SourceLine>,
|
||||
op_groups: Vec<OpGroup>,
|
||||
@@ -233,8 +234,8 @@ impl gpui::Render for Screen {
|
||||
text(format!(
|
||||
"{} ops, {} old lines, {} new lines",
|
||||
case.op_groups.len(),
|
||||
line_count(&case.old_lines),
|
||||
line_count(&case.new_lines),
|
||||
case.old_line_count,
|
||||
case.new_line_count,
|
||||
))
|
||||
.text_xs()
|
||||
.font_family("Menlo")
|
||||
@@ -252,11 +253,11 @@ impl gpui::Render for Screen {
|
||||
.border_b_1()
|
||||
.border_color(theme.colors.border_muted)
|
||||
.child(
|
||||
panel_header("Old", line_count(&case.old_lines), theme)
|
||||
panel_header("Old", case.old_line_count, theme)
|
||||
.flex_1(),
|
||||
)
|
||||
.child(
|
||||
panel_header("New", line_count(&case.new_lines), theme)
|
||||
panel_header("New", case.new_line_count, theme)
|
||||
.flex_1(),
|
||||
),
|
||||
)
|
||||
@@ -276,6 +277,8 @@ impl gpui::Render for Screen {
|
||||
.child(render_source_content(
|
||||
&case.old_lines,
|
||||
&case.new_lines,
|
||||
case.old_line_count,
|
||||
case.new_line_count,
|
||||
theme,
|
||||
))
|
||||
.child(text("Diff Rows Render").text_sm())
|
||||
@@ -377,6 +380,8 @@ impl DiffCase {
|
||||
Self {
|
||||
title,
|
||||
description,
|
||||
old_line_count: diff.old_line_count,
|
||||
new_line_count: diff.new_line_count,
|
||||
old_lines: collect_source_lines(&diff, SourceSide::Old),
|
||||
new_lines: collect_source_lines(&diff, SourceSide::New),
|
||||
op_groups: collect_op_groups(&diff),
|
||||
@@ -408,23 +413,24 @@ fn panel_header(label: &'static str, line_count: usize, theme: &crate::theme::Th
|
||||
fn render_source_content(
|
||||
old_lines: &[SourceLine],
|
||||
new_lines: &[SourceLine],
|
||||
old_line_count: usize,
|
||||
new_line_count: usize,
|
||||
theme: &crate::theme::Theme,
|
||||
) -> gpui::Div {
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.gap_2()
|
||||
.child(render_source_panel("Old Content", old_lines, theme).flex_1())
|
||||
.child(render_source_panel("New Content", new_lines, theme).flex_1())
|
||||
.child(render_source_panel("Old Content", old_lines, old_line_count, theme).flex_1())
|
||||
.child(render_source_panel("New Content", new_lines, new_line_count, theme).flex_1())
|
||||
}
|
||||
|
||||
fn render_source_panel(
|
||||
title: &'static str,
|
||||
lines: &[SourceLine],
|
||||
line_count: usize,
|
||||
theme: &crate::theme::Theme,
|
||||
) -> gpui::Div {
|
||||
let line_count = line_count(lines);
|
||||
|
||||
let rows: Vec<AnyElement> = lines
|
||||
.iter()
|
||||
.map(|line| {
|
||||
@@ -573,7 +579,7 @@ fn render_row(op_index: usize, row: &DiffLine, theme: &crate::theme::Theme) -> g
|
||||
.child(render_line_cell(
|
||||
op_index,
|
||||
row.op,
|
||||
row.old_content.as_ref().map(|_| row.old_line),
|
||||
row.old_line,
|
||||
row.old_content.as_deref().map(display_text),
|
||||
true,
|
||||
theme,
|
||||
@@ -581,7 +587,7 @@ fn render_row(op_index: usize, row: &DiffLine, theme: &crate::theme::Theme) -> g
|
||||
.child(render_line_cell(
|
||||
op_index,
|
||||
row.op,
|
||||
row.new_content.as_ref().map(|_| row.new_line),
|
||||
row.new_line,
|
||||
row.new_content.as_deref().map(display_text),
|
||||
false,
|
||||
theme,
|
||||
@@ -661,10 +667,6 @@ fn display_text(text: &str) -> String {
|
||||
rendered
|
||||
}
|
||||
|
||||
fn line_count(lines: &[SourceLine]) -> usize {
|
||||
lines.last().map(|line| line.line_number + 1).unwrap_or(0)
|
||||
}
|
||||
|
||||
fn collect_source_lines(diff: &ContentDiff, side: SourceSide) -> Vec<SourceLine> {
|
||||
let mut lines = Vec::new();
|
||||
|
||||
@@ -673,17 +675,17 @@ fn collect_source_lines(diff: &ContentDiff, side: SourceSide) -> Vec<SourceLine>
|
||||
|
||||
match side {
|
||||
| SourceSide::Old => {
|
||||
if let Some(content) = &row.old_content {
|
||||
if let (Some(line_number), Some(content)) = (row.old_line, &row.old_content) {
|
||||
lines.push(SourceLine {
|
||||
line_number: row.old_line,
|
||||
line_number,
|
||||
content: Arc::clone(content),
|
||||
});
|
||||
}
|
||||
}
|
||||
| SourceSide::New => {
|
||||
if let Some(content) = &row.new_content {
|
||||
if let (Some(line_number), Some(content)) = (row.new_line, &row.new_content) {
|
||||
lines.push(SourceLine {
|
||||
line_number: row.new_line,
|
||||
line_number,
|
||||
content: Arc::clone(content),
|
||||
});
|
||||
}
|
||||
@@ -710,8 +712,8 @@ fn collect_op_groups(diff: &ContentDiff) -> Vec<OpGroup> {
|
||||
|
||||
groups.push(OpGroup {
|
||||
op,
|
||||
old_range: group_range(&rows, SourceSide::Old),
|
||||
new_range: group_range(&rows, SourceSide::New),
|
||||
old_range: group_range(diff, start, end, SourceSide::Old),
|
||||
new_range: group_range(diff, start, end, SourceSide::New),
|
||||
rows,
|
||||
});
|
||||
|
||||
@@ -721,18 +723,13 @@ fn collect_op_groups(diff: &ContentDiff) -> Vec<OpGroup> {
|
||||
groups
|
||||
}
|
||||
|
||||
fn group_range(rows: &[DiffLine], side: SourceSide) -> Range<usize> {
|
||||
let anchor = match side {
|
||||
| SourceSide::Old => rows.first().map(|row| row.old_line).unwrap_or(0),
|
||||
| SourceSide::New => rows.first().map(|row| row.new_line).unwrap_or(0),
|
||||
};
|
||||
|
||||
fn group_range(diff: &ContentDiff, start: usize, end: usize, side: SourceSide) -> Range<usize> {
|
||||
let mut first = None;
|
||||
let mut last = None;
|
||||
|
||||
for line_number in rows.iter().filter_map(|row| match side {
|
||||
| SourceSide::Old => row.old_content.as_ref().map(|_| row.old_line),
|
||||
| SourceSide::New => row.new_content.as_ref().map(|_| row.new_line),
|
||||
for line_number in (start..end).filter_map(|index| match side {
|
||||
| SourceSide::Old => diff.get(index).old_line,
|
||||
| SourceSide::New => diff.get(index).new_line,
|
||||
}) {
|
||||
if first.is_none() {
|
||||
first = Some(line_number);
|
||||
@@ -742,10 +739,31 @@ fn group_range(rows: &[DiffLine], side: SourceSide) -> Range<usize> {
|
||||
|
||||
match (first, last) {
|
||||
| (Some(start), Some(end)) => start..end + 1,
|
||||
| _ => anchor..anchor,
|
||||
| _ => {
|
||||
let anchor = group_anchor(diff, start, end, side);
|
||||
anchor..anchor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn group_anchor(diff: &ContentDiff, start: usize, end: usize, side: SourceSide) -> usize {
|
||||
if let Some(line_number) = (end..diff.len()).find_map(|index| match side {
|
||||
| SourceSide::Old => diff.get(index).old_line,
|
||||
| SourceSide::New => diff.get(index).new_line,
|
||||
}) {
|
||||
return line_number;
|
||||
}
|
||||
|
||||
if let Some(line_number) = (0..start).rev().find_map(|index| match side {
|
||||
| SourceSide::Old => diff.get(index).old_line,
|
||||
| SourceSide::New => diff.get(index).new_line,
|
||||
}) {
|
||||
return line_number + 1;
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
struct Colors {
|
||||
background: gpui::Rgba,
|
||||
border: gpui::Rgba,
|
||||
|
||||
@@ -183,60 +183,60 @@ impl GithubStepView {
|
||||
let poll_interval = u64::from(*interval);
|
||||
|
||||
match read_query(query, cx) {
|
||||
| QueryStatus::Loaded(data) => {
|
||||
let auth_tokens = api::AuthTokens {
|
||||
access_token: data.access_token.clone(),
|
||||
};
|
||||
|
||||
cx.update_global::<query::Store<api::QueryContext>, _>(|store, _| {
|
||||
store.update_query_context(|c| {
|
||||
c.auth = Some(auth_tokens.clone());
|
||||
});
|
||||
});
|
||||
|
||||
self.user_query = Some(use_query(api::user::Fetch, cx));
|
||||
|
||||
cx.spawn(async move |weak, cx| {
|
||||
let ent = fetch_query(api::user::Fetch, cx).await;
|
||||
|
||||
let fut = weak
|
||||
.update(cx, move |_this, cx| {
|
||||
let Ok(query) = ent else {
|
||||
return None;
|
||||
};
|
||||
let QueryStatus::Loaded(user) = read_query(&query, cx) else {
|
||||
return None;
|
||||
};
|
||||
Some(storage::store_auth_tokens(&auth_tokens, user, cx))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
_ = if let Some(task) = fut {
|
||||
task.await
|
||||
} else {
|
||||
Err(anyhow::Error::msg(""))
|
||||
| QueryStatus::Loaded(data) => {
|
||||
let auth_tokens = api::AuthTokens {
|
||||
access_token: data.access_token.clone(),
|
||||
};
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
| QueryStatus::Err(api::Error::Github(api::GithubError { error, .. })) => {
|
||||
if error == "authorization_pending" {
|
||||
cx.update_global::<query::Store<api::QueryContext>, _>(|store, _| {
|
||||
store.update_query_context(|c| {
|
||||
c.auth = Some(auth_tokens.clone());
|
||||
});
|
||||
});
|
||||
|
||||
self.user_query = Some(use_query(api::user::Fetch, cx));
|
||||
|
||||
cx.spawn(async move |weak, cx| {
|
||||
Timer::after(Duration::from_secs(poll_interval)).await;
|
||||
if let Ok(Some(query)) =
|
||||
weak.read_with(cx, |this, _cx| this.request_access_token_query.clone())
|
||||
{
|
||||
let _ = weak.update(cx, |_this, cx| {
|
||||
query.refetch(cx);
|
||||
});
|
||||
}
|
||||
let ent = fetch_query(api::user::Fetch, cx).await;
|
||||
|
||||
let fut = weak
|
||||
.update(cx, move |_this, cx| {
|
||||
let Ok(query) = ent else {
|
||||
return None;
|
||||
};
|
||||
let QueryStatus::Loaded(user) = read_query(&query, cx) else {
|
||||
return None;
|
||||
};
|
||||
Some(storage::store_auth_tokens(&auth_tokens, user, cx))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
_ = if let Some(task) = fut {
|
||||
task.await
|
||||
} else {
|
||||
Err(anyhow::Error::msg(""))
|
||||
};
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
| _ => {}
|
||||
| QueryStatus::Err(api::Error::Github(api::GithubError { error, .. })) => {
|
||||
if error == "authorization_pending" {
|
||||
cx.spawn(async move |weak, cx| {
|
||||
Timer::after(Duration::from_secs(poll_interval)).await;
|
||||
if let Ok(Some(query)) =
|
||||
weak.read_with(cx, |this, _cx| this.request_access_token_query.clone())
|
||||
{
|
||||
let _ = weak.update(cx, |_this, cx| {
|
||||
query.refetch(cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
| _ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +257,8 @@ impl GithubStepView {
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
let (displayed_code, copyable_code) = match create_device_code_query {
|
||||
| QueryStatus::Loaded(data) => (data.user_code.as_ref(), Some(data.user_code.clone())),
|
||||
| _ => (self.placeholder_code.as_str(), None),
|
||||
| QueryStatus::Loaded(data) => (data.user_code.as_ref(), Some(data.user_code.clone())),
|
||||
| _ => (self.placeholder_code.as_str(), None),
|
||||
};
|
||||
|
||||
let border_color = theme.colors.border.clone();
|
||||
@@ -352,14 +352,16 @@ impl gpui::Render for GithubStepView {
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
let (can_go_next, header, body) = match self.user_query {
|
||||
| None => (false, self.header(), self.device_code_area(cx)),
|
||||
| Some(ref q) => {
|
||||
let user_query = read_query(q, cx);
|
||||
match user_query {
|
||||
| QueryStatus::Loaded(user) => (true, connected_header(), connected_body(user, cx)),
|
||||
| _ => (false, self.header(), self.device_code_area(cx)),
|
||||
| None => (false, self.header(), self.device_code_area(cx)),
|
||||
| Some(ref q) => {
|
||||
let user_query = read_query(q, cx);
|
||||
match user_query {
|
||||
| QueryStatus::Loaded(user) => {
|
||||
(true, connected_header(), connected_body(user, cx))
|
||||
}
|
||||
| _ => (false, self.header(), self.device_code_area(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
div()
|
||||
|
||||
Reference in New Issue
Block a user