wip: connect to github
This commit is contained in:
@@ -9,6 +9,7 @@ use crate::{api, app};
|
||||
pub struct Global {
|
||||
pub safe_area: gpui::Bounds<gpui::Pixels>,
|
||||
pub current_theme: theme::Theme,
|
||||
pub rng: rand::prelude::ThreadRng,
|
||||
}
|
||||
|
||||
pub struct Chrome {}
|
||||
@@ -50,10 +51,14 @@ impl gpui::Render for Chrome {
|
||||
|
||||
impl gpui::Global for Global {}
|
||||
|
||||
pub fn current_theme<'a, E>(cx: &'a gpui::Context<E>) -> &'a theme::Theme {
|
||||
pub fn current_theme(cx: &gpui::App) -> &theme::Theme {
|
||||
&cx.global::<Global>().current_theme
|
||||
}
|
||||
|
||||
pub fn rng(cx: &mut gpui::App) -> &mut rand::prelude::ThreadRng {
|
||||
&mut cx.global_mut::<Global>().rng
|
||||
}
|
||||
|
||||
pub fn query_store<'a, E>(cx: &'a gpui::Context<E>) -> &'a query::Store<api::QueryContext> {
|
||||
cx.global::<query::Store<api::QueryContext>>()
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod button;
|
||||
pub mod font_icon;
|
||||
pub mod text;
|
||||
@@ -3,23 +3,20 @@ use gpui::{
|
||||
StatefulInteractiveElement, Styled, div, prelude::FluentBuilder,
|
||||
};
|
||||
|
||||
use crate::{app, component::text::Text};
|
||||
use crate::{app, component::text::TextContent, theme};
|
||||
|
||||
#[derive(gpui::IntoElement)]
|
||||
pub struct Button {
|
||||
id: gpui::ElementId,
|
||||
text_color: gpui::Rgba,
|
||||
label: Option<gpui::AnyElement>,
|
||||
leading: Option<gpui::Svg>,
|
||||
trailing: Option<gpui::Svg>,
|
||||
on_click: Option<Box<dyn Fn(&gpui::ClickEvent, &mut gpui::Window, &mut gpui::App)>>,
|
||||
}
|
||||
|
||||
pub fn button<E>(id: impl Into<gpui::ElementId>, cx: &gpui::Context<E>) -> Button {
|
||||
let theme = app::current_theme(cx);
|
||||
pub fn button(id: impl Into<gpui::ElementId>) -> Button {
|
||||
Button {
|
||||
id: id.into(),
|
||||
text_color: theme.colors.accent_text,
|
||||
label: None,
|
||||
leading: None,
|
||||
trailing: None,
|
||||
@@ -28,40 +25,53 @@ pub fn button<E>(id: impl Into<gpui::ElementId>, cx: &gpui::Context<E>) -> Butto
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn label(mut self, s: impl Text) -> Self {
|
||||
pub fn label(mut self, s: impl TextContent) -> Self {
|
||||
self.label = Some(s.into_any_element());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn leading(mut self, s: gpui::Svg) -> Self {
|
||||
self.leading = Some(s.size_3().text_color(self.text_color));
|
||||
self.leading = Some(s.size_3());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn trailing(mut self, s: gpui::Svg) -> Self {
|
||||
self.trailing = Some(s.text_color(self.text_color));
|
||||
self.trailing = Some(s.size_3());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_click(mut self, fn: impl Fn(&gpui::ClickEvent, &mut gpui::Window, &mut gpui::App)) -> Self {
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
f: impl Fn(&gpui::ClickEvent, &mut gpui::Window, &mut gpui::App) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Box::new(f));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::RenderOnce for Button {
|
||||
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
let mut children: Vec<AnyElement> = Vec::with_capacity(3);
|
||||
if let Some(leading) = self.leading {
|
||||
children.push(leading.into_any_element());
|
||||
children.push(
|
||||
leading
|
||||
.text_color(theme.colors.accent_text)
|
||||
.into_any_element(),
|
||||
);
|
||||
}
|
||||
if let Some(label) = self.label {
|
||||
children.push(label);
|
||||
}
|
||||
if let Some(trailing) = self.trailing {
|
||||
children.push(trailing.into_any_element());
|
||||
children.push(
|
||||
trailing
|
||||
.text_color(theme.colors.accent_text)
|
||||
.into_any_element(),
|
||||
);
|
||||
}
|
||||
|
||||
let theme = cx.global::<app::Global>().current_theme;
|
||||
|
||||
div()
|
||||
.id(self.id)
|
||||
.flex()
|
||||
|
||||
3
src/component/mod.rs
Normal file
3
src/component/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub(crate) mod button;
|
||||
pub(crate) mod font_icon;
|
||||
pub(crate) mod text;
|
||||
@@ -1,13 +1,177 @@
|
||||
use crate::app;
|
||||
use gpui::{ParentElement, Styled, div};
|
||||
|
||||
pub trait Text: gpui::IntoElement {}
|
||||
|
||||
impl Text for &'static str {}
|
||||
impl Text for String {}
|
||||
impl Text for gpui::SharedString {}
|
||||
|
||||
pub fn text<'a, Content: Text, T>(s: Content, cx: &gpui::Context<T>) -> gpui::Div {
|
||||
let theme = cx.global::<app::Global>().current_theme;
|
||||
div().text_color(theme.colors.text).child(s)
|
||||
#[derive(gpui::IntoElement)]
|
||||
pub(crate) struct Text {
|
||||
content: gpui::AnyElement,
|
||||
font_weight: gpui::FontWeight,
|
||||
opacity: f32,
|
||||
text_align: gpui::TextAlign,
|
||||
text_size: Option<gpui::AbsoluteLength>,
|
||||
line_height: gpui::DefiniteLength,
|
||||
styled: Option<Box<dyn Fn(gpui::Div) -> gpui::Div>>,
|
||||
}
|
||||
|
||||
pub(crate) trait TextContent: gpui::IntoElement {}
|
||||
|
||||
impl TextContent for &'static str {}
|
||||
impl TextContent for String {}
|
||||
impl TextContent for gpui::SharedString {}
|
||||
|
||||
pub(crate) fn text(content: impl TextContent) -> Text {
|
||||
Text {
|
||||
content: content.into_any_element(),
|
||||
font_weight: gpui::FontWeight::NORMAL,
|
||||
opacity: 1.,
|
||||
text_align: gpui::TextAlign::Left,
|
||||
text_size: None,
|
||||
line_height: gpui::relative(1.5),
|
||||
styled: None,
|
||||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub(crate) fn light(mut self) -> Self {
|
||||
self.font_weight = gpui::FontWeight::LIGHT;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn medium(mut self) -> Self {
|
||||
self.font_weight = gpui::FontWeight::MEDIUM;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn bold(mut self) -> Self {
|
||||
self.font_weight = gpui::FontWeight::BOLD;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn opacity(mut self, opacity: f32) -> Self {
|
||||
self.opacity = opacity;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn text_size(mut self, size: impl Into<gpui::AbsoluteLength>) -> Self {
|
||||
self.text_size = Some(size.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn text_xs(self) -> Self {
|
||||
self.text_size(gpui::rems(0.75))
|
||||
}
|
||||
|
||||
pub(crate) fn text_sm(self) -> Self {
|
||||
self.text_size(gpui::rems(0.875))
|
||||
}
|
||||
|
||||
pub(crate) fn text_base(self) -> Self {
|
||||
self.text_size(gpui::rems(1.0))
|
||||
}
|
||||
|
||||
pub(crate) fn text_lg(self) -> Self {
|
||||
self.text_size(gpui::rems(1.125))
|
||||
}
|
||||
|
||||
pub(crate) fn text_xl(self) -> Self {
|
||||
self.text_size(gpui::rems(1.25))
|
||||
}
|
||||
|
||||
pub(crate) fn text_2xl(self) -> Self {
|
||||
self.text_size(gpui::rems(1.5))
|
||||
}
|
||||
|
||||
pub(crate) fn text_3xl(self) -> Self {
|
||||
self.text_size(gpui::rems(1.875))
|
||||
}
|
||||
|
||||
pub(crate) fn line_height(mut self, line_height: impl Into<gpui::DefiniteLength>) -> Self {
|
||||
self.line_height = line_height.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn leading_none(self) -> Self {
|
||||
self.line_height(gpui::relative(1.0))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_tight(self) -> Self {
|
||||
self.line_height(gpui::relative(1.25))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_snug(self) -> Self {
|
||||
self.line_height(gpui::relative(1.375))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_normal(self) -> Self {
|
||||
self.line_height(gpui::relative(1.5))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_relaxed(self) -> Self {
|
||||
self.line_height(gpui::relative(1.625))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_loose(self) -> Self {
|
||||
self.line_height(gpui::relative(2.0))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_3(self) -> Self {
|
||||
self.line_height(gpui::rems(0.75))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_4(self) -> Self {
|
||||
self.line_height(gpui::rems(1.0))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_5(self) -> Self {
|
||||
self.line_height(gpui::rems(1.25))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_6(self) -> Self {
|
||||
self.line_height(gpui::rems(1.5))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_7(self) -> Self {
|
||||
self.line_height(gpui::rems(1.75))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_8(self) -> Self {
|
||||
self.line_height(gpui::rems(2.0))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_9(self) -> Self {
|
||||
self.line_height(gpui::rems(2.25))
|
||||
}
|
||||
|
||||
pub(crate) fn leading_10(self) -> Self {
|
||||
self.line_height(gpui::rems(2.5))
|
||||
}
|
||||
|
||||
pub(crate) fn styled(mut self, styled: impl Fn(gpui::Div) -> gpui::Div + 'static) -> Self {
|
||||
self.styled = Some(Box::new(styled));
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn centered(mut self) -> Self {
|
||||
self.text_align = gpui::TextAlign::Center;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::RenderOnce for Text {
|
||||
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
|
||||
let theme = app::current_theme(cx);
|
||||
let mut div = div()
|
||||
.text_color(theme.colors.text)
|
||||
.font_weight(self.font_weight)
|
||||
.opacity(self.opacity)
|
||||
.text_align(self.text_align)
|
||||
.line_height(self.line_height)
|
||||
.child(self.content);
|
||||
if let Some(text_size) = self.text_size {
|
||||
div = div.text_size(text_size);
|
||||
}
|
||||
if let Some(styled) = self.styled {
|
||||
div = styled(div);
|
||||
}
|
||||
div
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ fn setup_application(cx: &mut gpui::App) {
|
||||
let global = app::Global {
|
||||
safe_area: bounds(point(px(0.), px(0.)), size(px(72.), px(12.))),
|
||||
current_theme: cx.window_appearance().into(),
|
||||
rng: rand::rng(),
|
||||
};
|
||||
|
||||
let top_left = global.safe_area.origin;
|
||||
@@ -61,7 +62,7 @@ fn setup_application(cx: &mut gpui::App) {
|
||||
is_resizable: false,
|
||||
..Default::default()
|
||||
},
|
||||
|_window, cx| cx.new(|cx| setup_wizard::new(cx)),
|
||||
|window, cx| cx.new(|cx| setup_wizard::new(window, cx)),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ pub enum Variant {
|
||||
VioletDark,
|
||||
}
|
||||
|
||||
pub(crate) fn current(cx: &gpui::App) -> &Theme {
|
||||
cx.global::<Theme>()
|
||||
}
|
||||
|
||||
impl Variant {
|
||||
#[allow(dead_code)]
|
||||
pub const ALL: [Self; 2] = [Self::VioletLight, Self::VioletDark];
|
||||
@@ -115,3 +119,5 @@ impl From<gpui::WindowAppearance> for Theme {
|
||||
variant.theme()
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::Global for Theme {}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{ParentElement, Styled, div};
|
||||
|
||||
use crate::component::button::button;
|
||||
@@ -36,7 +35,7 @@ impl gpui::Render for TitleBar {
|
||||
|
||||
let user_avatar = match user {
|
||||
QueryStatus::Err(api::Error::Unauthenticated) => div().absolute().right_2p5().child(
|
||||
button("login-btn", cx)
|
||||
button("login-btn")
|
||||
.leading(font_icon(FontIcon::Github, cx))
|
||||
.label("Login"),
|
||||
),
|
||||
@@ -78,6 +77,6 @@ fn repo_selector<T: 'static>(cx: &gpui::Context<T>) -> gpui::Div {
|
||||
.gap_1()
|
||||
.text_xs()
|
||||
.child(font_icon(FontIcon::FolderGit, cx).size_3())
|
||||
.child(text("test/repo", cx))
|
||||
.child(text("test/repo"))
|
||||
.child(font_icon(FontIcon::ChevronDown, cx).size_3())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user