wip: connect to github
This commit is contained in:
@@ -1,39 +1,117 @@
|
||||
use gpui::{FontWeight, ParentElement, Styled, div};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use gpui::{AppContext, FontWeight, ParentElement, Styled, div, prelude::FluentBuilder};
|
||||
use rand::RngExt;
|
||||
|
||||
use crate::{
|
||||
api,
|
||||
api, app,
|
||||
component::text::text,
|
||||
query::{self, use_lazy_query},
|
||||
query::{self, QueryStatus, read_query, use_lazy_query},
|
||||
};
|
||||
|
||||
pub(crate) struct GithubStepView {
|
||||
last_tick: Instant,
|
||||
placeholder_code: String,
|
||||
create_device_code_query: query::Entity<api::auth::CreateDeviceCode>,
|
||||
}
|
||||
|
||||
pub(crate) fn new(cx: &mut gpui::Context<GithubStepView>) -> GithubStepView {
|
||||
GithubStepView {
|
||||
last_tick: Instant::now(),
|
||||
placeholder_code: "ABCDEFGH".to_owned(),
|
||||
create_device_code_query: use_lazy_query(api::auth::CreateDeviceCode, cx),
|
||||
}
|
||||
}
|
||||
|
||||
impl GithubStepView {
|
||||
const CHAR_POOL: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
fn generate_random_code(&mut self, cx: &mut gpui::Context<Self>) -> String {
|
||||
let rng = app::rng(cx);
|
||||
(0..8)
|
||||
.map(|_| {
|
||||
let idx = rng.random_range(0..Self::CHAR_POOL.len());
|
||||
Self::CHAR_POOL.chars().nth(idx).unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::Render for GithubStepView {
|
||||
fn render(
|
||||
&mut self,
|
||||
_window: &mut gpui::Window,
|
||||
window: &mut gpui::Window,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
div().flex().flex_col().size_full().child(header(cx))
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
let border_color = theme.colors.surface_elevated.clone();
|
||||
let bg_color = theme.colors.surface.clone();
|
||||
|
||||
let create_device_code_query = read_query(&self.create_device_code_query, cx);
|
||||
let is_loading_code = matches!(create_device_code_query, QueryStatus::Loading);
|
||||
|
||||
let now = Instant::now();
|
||||
let should_tick = now.duration_since(self.last_tick) >= Duration::from_millis(50);
|
||||
|
||||
if is_loading_code {
|
||||
cx.on_next_frame(window, move |this, _, cx| {
|
||||
if should_tick {
|
||||
this.placeholder_code = this.generate_random_code(cx);
|
||||
this.last_tick = Instant::now();
|
||||
}
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
|
||||
let letter_boxes = self
|
||||
.placeholder_code
|
||||
.split("")
|
||||
.filter(|c| !c.is_empty())
|
||||
.map(|c| {
|
||||
text(String::from(c))
|
||||
.bold()
|
||||
.text_2xl()
|
||||
.styled(move |it| {
|
||||
it.p_3()
|
||||
.font_family("CommitMono")
|
||||
.border_1()
|
||||
.border_color(border_color)
|
||||
.rounded_lg()
|
||||
.bg(bg_color)
|
||||
})
|
||||
.when(is_loading_code, |it| it.opacity(0.5))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.px_4()
|
||||
.py_12()
|
||||
.child(header())
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.flex_1()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.gap_1p5()
|
||||
.children(letter_boxes),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn header(cx: &gpui::Context<GithubStepView>) -> impl gpui::IntoElement {
|
||||
fn header() -> impl gpui::IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.items_center()
|
||||
.child(text("Connect to GitHub", cx).font_weight(FontWeight(700.)))
|
||||
.gap_1p5()
|
||||
.child(text("Connect to GitHub").text_xl().bold())
|
||||
.child(text(
|
||||
"You will be redirected to GitHub to authorize access. Copy the device code below into GitHub.",
|
||||
cx
|
||||
).opacity(0.8))
|
||||
"You will be redirected to GitHub to authorize access.\nCopy the device code below into GitHub.",
|
||||
).leading_tight().centered().opacity(0.8))
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
use gpui::{AppContext, FontWeight, IntoElement, ParentElement, Styled, div};
|
||||
use gpui::{
|
||||
AppContext, BorrowAppContext, InteractiveElement, IntoElement, ParentElement,
|
||||
StatefulInteractiveElement, Styled, div,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
api, app,
|
||||
app,
|
||||
component::text::text,
|
||||
query::{self, use_lazy_query},
|
||||
screen::setup_wizard::{github_step, welcome_step},
|
||||
screen::setup_wizard::{github_step, welcome_step::welcome_step},
|
||||
};
|
||||
|
||||
pub(crate) struct Screen {
|
||||
current_step: Step,
|
||||
github_step_view: gpui::Entity<github_step::GithubStepView>,
|
||||
}
|
||||
|
||||
enum Step {
|
||||
@@ -16,9 +19,27 @@ enum Step {
|
||||
ConnectToGithub,
|
||||
}
|
||||
|
||||
pub(crate) fn new(cx: &mut gpui::Context<Screen>) -> Screen {
|
||||
pub(crate) fn new(window: &mut gpui::Window, cx: &mut gpui::Context<Screen>) -> Screen {
|
||||
cx.observe_window_appearance(window, |_, window, cx| {
|
||||
cx.update_global::<app::Global, ()>(|global, cx| {
|
||||
global.current_theme = window.appearance().into();
|
||||
cx.notify();
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
|
||||
Screen {
|
||||
current_step: Step::Welcome,
|
||||
github_step_view: cx.new(|cx| github_step::new(cx)),
|
||||
}
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
fn advance_to_next_step(&mut self) {
|
||||
match self.current_step {
|
||||
Step::Welcome => self.current_step = Step::ConnectToGithub,
|
||||
Step::ConnectToGithub => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,13 +50,17 @@ impl gpui::Render for Screen {
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
let step_view = match self.current_step {
|
||||
Step::Welcome => welcome_step::new(cx).into_any_element(),
|
||||
Step::ConnectToGithub => cx.new(|cx| github_step::new(cx)).into_any_element(),
|
||||
Step::Welcome => welcome_step()
|
||||
.on_next(cx.listener(|this, _, _window, _cx| this.advance_to_next_step()))
|
||||
.into_any_element(),
|
||||
Step::ConnectToGithub => self.github_step_view.clone().into_any_element(),
|
||||
};
|
||||
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
div()
|
||||
.id("awd")
|
||||
.on_click(cx.listener(|a, b, c, d| {}))
|
||||
.flex()
|
||||
.flex_row()
|
||||
.items_center()
|
||||
@@ -51,11 +76,9 @@ impl gpui::Render for Screen {
|
||||
.bg(theme.colors.surface)
|
||||
.relative()
|
||||
.child(
|
||||
text("Novem", cx)
|
||||
.font_weight(FontWeight(700.))
|
||||
.absolute()
|
||||
.top_20()
|
||||
.left_8(),
|
||||
text("Novem")
|
||||
.bold()
|
||||
.styled(|it| it.absolute().top_20().left_8()),
|
||||
)
|
||||
.child(step_list(cx)),
|
||||
)
|
||||
@@ -83,9 +106,9 @@ fn step_list(cx: &gpui::Context<impl gpui::Render>) -> impl gpui::IntoElement {
|
||||
.gap_3()
|
||||
.text_sm()
|
||||
.children(vec![
|
||||
text("Welcome!", cx),
|
||||
text("Connect to GitHub", cx),
|
||||
text("Customize Novem", cx),
|
||||
text("Complete!", cx),
|
||||
text("Welcome!"),
|
||||
text("Connect to GitHub"),
|
||||
text("Customize Novem"),
|
||||
text("Complete!"),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -1,47 +1,62 @@
|
||||
use gpui::{FontWeight, ParentElement, Styled, div};
|
||||
use gpui::{ParentElement, Styled, div, prelude::FluentBuilder};
|
||||
|
||||
use crate::{
|
||||
app,
|
||||
component::{button::button, text::text},
|
||||
};
|
||||
use crate::component::{button::button, text::text};
|
||||
|
||||
struct WelcomeStep {
|
||||
on_next: Option<FnOnce>,
|
||||
#[derive(gpui::IntoElement)]
|
||||
pub(crate) struct WelcomeStep {
|
||||
on_next: Option<Box<dyn Fn(&(), &mut gpui::Window, &mut gpui::App) + 'static>>,
|
||||
}
|
||||
|
||||
pub(crate) fn new<E>(cx: &gpui::Context<E>) -> impl gpui::IntoElement {
|
||||
let theme = app::current_theme(cx);
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.items_start()
|
||||
.justify_center()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.flex_1()
|
||||
.justify_center()
|
||||
.w_full()
|
||||
.p_8()
|
||||
.child(
|
||||
text(
|
||||
"Welcome to Novem!\nThis wizard will guide you through setting up Novem.\n",
|
||||
cx,
|
||||
pub(crate) fn welcome_step() -> WelcomeStep {
|
||||
WelcomeStep { on_next: None }
|
||||
}
|
||||
|
||||
impl WelcomeStep {
|
||||
pub fn on_next(mut self, f: impl Fn(&(), &mut gpui::Window, &mut gpui::App) + 'static) -> Self {
|
||||
self.on_next = Some(Box::new(f));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::RenderOnce for WelcomeStep {
|
||||
fn render(self, _window: &mut gpui::Window, _cx: &mut gpui::App) -> impl gpui::IntoElement {
|
||||
let next_button = button("next")
|
||||
.label("Next")
|
||||
.when(self.on_next.is_some(), |b| {
|
||||
b.on_click(move |_, window, cx| self.on_next.as_ref().unwrap()(&(), window, cx))
|
||||
});
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.items_start()
|
||||
.justify_center()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.flex_1()
|
||||
.justify_center()
|
||||
.w_full()
|
||||
.p_8()
|
||||
.child(
|
||||
text(
|
||||
"Welcome to Novem!\nThis wizard will guide you through setting up Novem.\n",
|
||||
)
|
||||
.opacity(0.8),
|
||||
)
|
||||
.opacity(0.8),
|
||||
)
|
||||
.child(text("Press 'Next' to begin setup.", cx).font_weight(FontWeight(500.))),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.justify_end()
|
||||
.w_full()
|
||||
.p_4()
|
||||
.pt_0()
|
||||
.child(button("next", cx).label("Next")),
|
||||
)
|
||||
.child(text("Press 'Next' to begin setup.").medium()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.justify_end()
|
||||
.w_full()
|
||||
.p_4()
|
||||
.pt_0()
|
||||
.child(next_button),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user