refactor: redesign theme tokens and split catppuccin themes
This commit is contained in:
10
build.rs
10
build.rs
@@ -229,8 +229,8 @@ fn render_github_fixtures(fixture_root: &Path) -> String {
|
|||||||
output.push_str(&string_literal(&id));
|
output.push_str(&string_literal(&id));
|
||||||
output.push_str(", ");
|
output.push_str(", ");
|
||||||
match previous_end_cursor.as_deref() {
|
match previous_end_cursor.as_deref() {
|
||||||
Some(after) => output.push_str(&format!("Some({})", string_literal(after))),
|
| Some(after) => output.push_str(&format!("Some({})", string_literal(after))),
|
||||||
None => output.push_str("None"),
|
| None => output.push_str("None"),
|
||||||
}
|
}
|
||||||
output.push_str(") => Some(");
|
output.push_str(") => Some(");
|
||||||
output.push_str(&string_literal(&fixture.json));
|
output.push_str(&string_literal(&fixture.json));
|
||||||
@@ -343,9 +343,9 @@ fn issue_fixture_state(issue: &serde_json::Value) -> &'static str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match required_string(issue, &["state"]) {
|
match required_string(issue, &["state"]) {
|
||||||
"open" => "OPEN",
|
| "open" => "OPEN",
|
||||||
"closed" => "CLOSED",
|
| "closed" => "CLOSED",
|
||||||
state => panic!("unsupported pull request state in fixture: {state}"),
|
| state => panic!("unsupported pull request state in fixture: {state}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ where
|
|||||||
{
|
{
|
||||||
let mut body: graphql_client::Response<T> = res.json().await?;
|
let mut body: graphql_client::Response<T> = res.json().await?;
|
||||||
match body.data.take() {
|
match body.data.take() {
|
||||||
None => Err(Error::GraphQLError(body.errors.unwrap_or_default())),
|
| None => Err(Error::GraphQLError(body.errors.unwrap_or_default())),
|
||||||
Some(data) => Ok((body, data)),
|
| Some(data) => Ok((body, data)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,10 @@ mod tests {
|
|||||||
.map(|author| author.login.as_str()),
|
.map(|author| author.login.as_str()),
|
||||||
Some("kennethnym")
|
Some("kennethnym")
|
||||||
);
|
);
|
||||||
assert_eq!(documented_failover.base_branch_name.as_deref(), Some("main"));
|
assert_eq!(
|
||||||
|
documented_failover.base_branch_name.as_deref(),
|
||||||
|
Some("main")
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
documented_failover.head_branch_name.as_deref(),
|
documented_failover.head_branch_name.as_deref(),
|
||||||
Some("docs/manual-failover-steps")
|
Some("docs/manual-failover-steps")
|
||||||
@@ -203,7 +206,10 @@ mod tests {
|
|||||||
Some(chrono::DateTime::parse_from_rfc3339("2026-05-03T07:40:00Z").unwrap())
|
Some(chrono::DateTime::parse_from_rfc3339("2026-05-03T07:40:00Z").unwrap())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
worker_split.author.as_ref().map(|author| author.login.as_str()),
|
worker_split
|
||||||
|
.author
|
||||||
|
.as_ref()
|
||||||
|
.map(|author| author.login.as_str()),
|
||||||
Some("leaferiksen")
|
Some("leaferiksen")
|
||||||
);
|
);
|
||||||
assert_eq!(worker_split.base_branch_name.as_deref(), Some("main"));
|
assert_eq!(worker_split.base_branch_name.as_deref(), Some("main"));
|
||||||
@@ -295,36 +301,36 @@ mod tests {
|
|||||||
.expect("third timeline fixture json should parse");
|
.expect("third timeline fixture json should parse");
|
||||||
|
|
||||||
let first_page_nodes = match first_page.node.as_ref() {
|
let first_page_nodes = match first_page.node.as_ref() {
|
||||||
Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
| Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
||||||
pull_request
|
pull_request
|
||||||
.timeline_items
|
.timeline_items
|
||||||
.nodes
|
.nodes
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("first timeline fixture page should contain timeline nodes")
|
.expect("first timeline fixture page should contain timeline nodes")
|
||||||
}
|
}
|
||||||
_ => panic!("first timeline fixture page should resolve to a pull request node"),
|
| _ => panic!("first timeline fixture page should resolve to a pull request node"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let second_page_nodes = match second_page.node.as_ref() {
|
let second_page_nodes = match second_page.node.as_ref() {
|
||||||
Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
| Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
||||||
pull_request
|
pull_request
|
||||||
.timeline_items
|
.timeline_items
|
||||||
.nodes
|
.nodes
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("second timeline fixture page should contain timeline nodes")
|
.expect("second timeline fixture page should contain timeline nodes")
|
||||||
}
|
}
|
||||||
_ => panic!("second timeline fixture page should resolve to a pull request node"),
|
| _ => panic!("second timeline fixture page should resolve to a pull request node"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let third_page_nodes = match third_page.node.as_ref() {
|
let third_page_nodes = match third_page.node.as_ref() {
|
||||||
Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
| Some(issues::PullRequestTimelineResponseNode::PullRequest(pull_request)) => {
|
||||||
pull_request
|
pull_request
|
||||||
.timeline_items
|
.timeline_items
|
||||||
.nodes
|
.nodes
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("third timeline fixture page should contain timeline nodes")
|
.expect("third timeline fixture page should contain timeline nodes")
|
||||||
}
|
}
|
||||||
_ => panic!("third timeline fixture page should resolve to a pull request node"),
|
| _ => panic!("third timeline fixture page should resolve to a pull request node"),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
107
src/colors.rs
107
src/colors.rs
@@ -11,74 +11,85 @@ pub const fn hex(hex: u32) -> Rgba {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn hex_alpha(hex: u32, alpha: f32) -> Rgba {
|
||||||
|
let [_, r, g, b] = hex.to_be_bytes();
|
||||||
|
|
||||||
|
Rgba {
|
||||||
|
r: r as f32 / 255.0,
|
||||||
|
g: g as f32 / 255.0,
|
||||||
|
b: b as f32 / 255.0,
|
||||||
|
a: alpha,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const fn neutral(shade: u16) -> Rgba {
|
pub const fn neutral(shade: u16) -> Rgba {
|
||||||
match shade {
|
match shade {
|
||||||
50 => hex(0xfafafa),
|
| 50 => hex(0xfafafa),
|
||||||
100 => hex(0xf5f5f5),
|
| 100 => hex(0xf5f5f5),
|
||||||
200 => hex(0xe5e5e5),
|
| 200 => hex(0xe5e5e5),
|
||||||
300 => hex(0xd4d4d4),
|
| 300 => hex(0xd4d4d4),
|
||||||
400 => hex(0xa3a3a3),
|
| 400 => hex(0xa3a3a3),
|
||||||
500 => hex(0x737373),
|
| 500 => hex(0x737373),
|
||||||
600 => hex(0x525252),
|
| 600 => hex(0x525252),
|
||||||
700 => hex(0x404040),
|
| 700 => hex(0x404040),
|
||||||
800 => hex(0x262626),
|
| 800 => hex(0x262626),
|
||||||
900 => hex(0x171717),
|
| 900 => hex(0x171717),
|
||||||
950 => hex(0x0a0a0a),
|
| 950 => hex(0x0a0a0a),
|
||||||
_ => panic!("unsupported Tailwind neutral shade"),
|
| _ => panic!("unsupported Tailwind neutral shade"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const fn violet(shade: u16) -> Rgba {
|
pub const fn violet(shade: u16) -> Rgba {
|
||||||
match shade {
|
match shade {
|
||||||
50 => hex(0xf5f3ff),
|
| 50 => hex(0xf5f3ff),
|
||||||
100 => hex(0xede9fe),
|
| 100 => hex(0xede9fe),
|
||||||
200 => hex(0xddd6fe),
|
| 200 => hex(0xddd6fe),
|
||||||
300 => hex(0xc4b5fd),
|
| 300 => hex(0xc4b5fd),
|
||||||
400 => hex(0xa78bfa),
|
| 400 => hex(0xa78bfa),
|
||||||
500 => hex(0x8b5cf6),
|
| 500 => hex(0x8b5cf6),
|
||||||
600 => hex(0x7c3aed),
|
| 600 => hex(0x7c3aed),
|
||||||
700 => hex(0x6d28d9),
|
| 700 => hex(0x6d28d9),
|
||||||
800 => hex(0x5b21b6),
|
| 800 => hex(0x5b21b6),
|
||||||
900 => hex(0x4c1d95),
|
| 900 => hex(0x4c1d95),
|
||||||
950 => hex(0x2e1065),
|
| 950 => hex(0x2e1065),
|
||||||
_ => panic!("unsupported Tailwind violet shade"),
|
| _ => panic!("unsupported Tailwind violet shade"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const fn amber(shade: u16) -> Rgba {
|
pub const fn amber(shade: u16) -> Rgba {
|
||||||
match shade {
|
match shade {
|
||||||
50 => hex(0xfffbeb),
|
| 50 => hex(0xfffbeb),
|
||||||
100 => hex(0xfef3c7),
|
| 100 => hex(0xfef3c7),
|
||||||
200 => hex(0xfde68a),
|
| 200 => hex(0xfde68a),
|
||||||
300 => hex(0xfcd34d),
|
| 300 => hex(0xfcd34d),
|
||||||
400 => hex(0xfbbf24),
|
| 400 => hex(0xfbbf24),
|
||||||
500 => hex(0xf59e0b),
|
| 500 => hex(0xf59e0b),
|
||||||
600 => hex(0xd97706),
|
| 600 => hex(0xd97706),
|
||||||
700 => hex(0xb45309),
|
| 700 => hex(0xb45309),
|
||||||
800 => hex(0x92400e),
|
| 800 => hex(0x92400e),
|
||||||
900 => hex(0x78350f),
|
| 900 => hex(0x78350f),
|
||||||
950 => hex(0x451a03),
|
| 950 => hex(0x451a03),
|
||||||
_ => panic!("unsupported Tailwind amber shade"),
|
| _ => panic!("unsupported Tailwind amber shade"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const fn red(shade: u16) -> Rgba {
|
pub const fn red(shade: u16) -> Rgba {
|
||||||
match shade {
|
match shade {
|
||||||
50 => hex(0xfef2f2),
|
| 50 => hex(0xfef2f2),
|
||||||
100 => hex(0xfee2e2),
|
| 100 => hex(0xfee2e2),
|
||||||
200 => hex(0xfecaca),
|
| 200 => hex(0xfecaca),
|
||||||
300 => hex(0xfca5a5),
|
| 300 => hex(0xfca5a5),
|
||||||
400 => hex(0xf87171),
|
| 400 => hex(0xf87171),
|
||||||
500 => hex(0xef4444),
|
| 500 => hex(0xef4444),
|
||||||
600 => hex(0xdc2626),
|
| 600 => hex(0xdc2626),
|
||||||
700 => hex(0xb91c1c),
|
| 700 => hex(0xb91c1c),
|
||||||
800 => hex(0x991b1b),
|
| 800 => hex(0x991b1b),
|
||||||
900 => hex(0x7f1d1d),
|
| 900 => hex(0x7f1d1d),
|
||||||
950 => hex(0x450a0a),
|
| 950 => hex(0x450a0a),
|
||||||
_ => panic!("unsupported Tailwind red shade"),
|
| _ => panic!("unsupported Tailwind red shade"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ impl gpui::RenderOnce for Button {
|
|||||||
let theme = app::current_theme(cx);
|
let theme = app::current_theme(cx);
|
||||||
|
|
||||||
let icon_color = match self.variant {
|
let icon_color = match self.variant {
|
||||||
| Variant::Primary => theme.colors.accent_text,
|
| Variant::Primary => theme.colors.accent_on_solid,
|
||||||
| Variant::Secondary => theme.colors.text,
|
| Variant::Secondary => theme.colors.text,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,10 +115,10 @@ impl gpui::RenderOnce for Button {
|
|||||||
.py_0p5()
|
.py_0p5()
|
||||||
.children(children)
|
.children(children)
|
||||||
.when(matches!(self.variant, Variant::Primary), |div| {
|
.when(matches!(self.variant, Variant::Primary), |div| {
|
||||||
div.bg(theme.colors.accent)
|
div.bg(theme.colors.accent_solid)
|
||||||
.text_color(theme.colors.accent_text)
|
.text_color(theme.colors.accent_on_solid)
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(theme.colors.border.blend(theme.colors.accent))
|
.border_color(theme.colors.border.blend(theme.colors.accent_solid))
|
||||||
})
|
})
|
||||||
.when(matches!(self.variant, Variant::Secondary), |div| {
|
.when(matches!(self.variant, Variant::Secondary), |div| {
|
||||||
div.bg(theme.colors.surface_elevated)
|
div.bg(theme.colors.surface_elevated)
|
||||||
|
|||||||
@@ -201,9 +201,9 @@ impl MarkdownText {
|
|||||||
highlights.push((
|
highlights.push((
|
||||||
node_range!(),
|
node_range!(),
|
||||||
gpui::HighlightStyle {
|
gpui::HighlightStyle {
|
||||||
color: Some(theme.colors.accent.into()),
|
color: Some(theme.colors.link.into()),
|
||||||
underline: Some(gpui::UnderlineStyle {
|
underline: Some(gpui::UnderlineStyle {
|
||||||
color: Some(theme.colors.accent.into()),
|
color: Some(theme.colors.link.into()),
|
||||||
thickness: px(1.),
|
thickness: px(1.),
|
||||||
wavy: false,
|
wavy: false,
|
||||||
}),
|
}),
|
||||||
@@ -214,8 +214,10 @@ impl MarkdownText {
|
|||||||
if cursor.goto_next_sibling()
|
if cursor.goto_next_sibling()
|
||||||
&& let Ok(src) = cursor.node().utf8_text(content.as_bytes())
|
&& let Ok(src) = cursor.node().utf8_text(content.as_bytes())
|
||||||
{
|
{
|
||||||
links
|
links.push((
|
||||||
.push((node_range!(), gpui::SharedString::from(String::from(src))));
|
node_range!(),
|
||||||
|
gpui::SharedString::from(String::from(src)),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
// the link src is invalid, use an empty string as a fallback
|
// the link src is invalid, use an empty string as a fallback
|
||||||
// link on click handler will ignore empty string
|
// link on click handler will ignore empty string
|
||||||
@@ -496,10 +498,10 @@ impl MarkdownText {
|
|||||||
.px_3()
|
.px_3()
|
||||||
.py_2()
|
.py_2()
|
||||||
.rounded_sm()
|
.rounded_sm()
|
||||||
.bg(theme.colors.surface)
|
.bg(theme.colors.code_bg)
|
||||||
.border_1()
|
.border_1()
|
||||||
.my_4()
|
.my_4()
|
||||||
.border_color(theme.colors.border);
|
.border_color(theme.colors.code_border);
|
||||||
|
|
||||||
self.blocks.push(block);
|
self.blocks.push(block);
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/main.rs
12
src/main.rs
@@ -73,17 +73,17 @@ fn setup_application(cx: &mut gpui::App) {
|
|||||||
let start = resume_application_state(cx);
|
let start = resume_application_state(cx);
|
||||||
|
|
||||||
match start {
|
match start {
|
||||||
Start::FromScratch => {
|
| Start::FromScratch => {
|
||||||
let screen = setup_wizard::new();
|
let screen = setup_wizard::new();
|
||||||
_ = setup_wizard::open_window(screen, cx);
|
_ = setup_wizard::open_window(screen, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Start::FromSetup(state) => {
|
| Start::FromSetup(state) => {
|
||||||
let screen = setup_wizard::from_saved(state);
|
let screen = setup_wizard::from_saved(state);
|
||||||
_ = setup_wizard::open_window(screen, cx);
|
_ = setup_wizard::open_window(screen, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Start::FromSaved(_) => {
|
| Start::FromSaved(_) => {
|
||||||
_ = dashboard::open_window(cx);
|
_ = dashboard::open_window(cx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -123,8 +123,8 @@ fn resume_application_state(cx: &mut gpui::App) -> Start {
|
|||||||
println!("[main] setup status: {:?}", setup_status);
|
println!("[main] setup status: {:?}", setup_status);
|
||||||
|
|
||||||
match setup_status {
|
match setup_status {
|
||||||
setup_wizard::SetupStatus::NotStarted => Start::FromScratch,
|
| setup_wizard::SetupStatus::NotStarted => Start::FromScratch,
|
||||||
setup_wizard::SetupStatus::InProgress(state) => Start::FromSetup(state),
|
| setup_wizard::SetupStatus::InProgress(state) => Start::FromSetup(state),
|
||||||
setup_wizard::SetupStatus::Completed => Start::FromSaved(state),
|
| setup_wizard::SetupStatus::Completed => Start::FromSaved(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/query.rs
18
src/query.rs
@@ -137,10 +137,10 @@ where
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
match wait_state {
|
match wait_state {
|
||||||
WaitState::Cached => {
|
| WaitState::Cached => {
|
||||||
return Ok(ent);
|
return Ok(ent);
|
||||||
}
|
}
|
||||||
WaitState::Waiting { rx, sub } => {
|
| WaitState::Waiting { rx, sub } => {
|
||||||
_ = sub;
|
_ = sub;
|
||||||
_ = rx.await;
|
_ = rx.await;
|
||||||
}
|
}
|
||||||
@@ -181,9 +181,9 @@ where
|
|||||||
let state = query.raw.read(cx);
|
let state = query.raw.read(cx);
|
||||||
|
|
||||||
match &state.data {
|
match &state.data {
|
||||||
QueryData::Loading | QueryData::Pending | QueryData::Stale => QueryStatus::Loading,
|
| QueryData::Loading | QueryData::Pending | QueryData::Stale => QueryStatus::Loading,
|
||||||
QueryData::Some(data) => QueryStatus::Loaded(data.downcast_ref::<F::Data>().unwrap()),
|
| QueryData::Some(data) => QueryStatus::Loaded(data.downcast_ref::<F::Data>().unwrap()),
|
||||||
QueryData::Err(error) => QueryStatus::Err(error.downcast_ref::<F::Error>().unwrap()),
|
| QueryData::Err(error) => QueryStatus::Err(error.downcast_ref::<F::Error>().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,11 +284,11 @@ where
|
|||||||
|
|
||||||
entity.raw.update(cx, |state, cx| {
|
entity.raw.update(cx, |state, cx| {
|
||||||
state.data = match result {
|
state.data = match result {
|
||||||
Ok(data) => {
|
| Ok(data) => {
|
||||||
println!("[query] OK {}", q.key());
|
println!("[query] OK {}", q.key());
|
||||||
QueryData::Some(Box::new(data))
|
QueryData::Some(Box::new(data))
|
||||||
}
|
}
|
||||||
Err(err) => {
|
| Err(err) => {
|
||||||
println!("[query] ERR {:?}: {:?}", q.key(), err);
|
println!("[query] ERR {:?}: {:?}", q.key(), err);
|
||||||
QueryData::Err(Box::new(err))
|
QueryData::Err(Box::new(err))
|
||||||
}
|
}
|
||||||
@@ -317,8 +317,8 @@ where
|
|||||||
.raw
|
.raw
|
||||||
.update(cx, |query, cx| {
|
.update(cx, |query, cx| {
|
||||||
query.data = match result {
|
query.data = match result {
|
||||||
Ok(data) => QueryData::Some(Box::new(data)),
|
| Ok(data) => QueryData::Some(Box::new(data)),
|
||||||
Err(err) => QueryData::Err(Box::new(err)),
|
| Err(err) => QueryData::Err(Box::new(err)),
|
||||||
};
|
};
|
||||||
cx.notify();
|
cx.notify();
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
api::{self},
|
api::{self},
|
||||||
app,
|
app,
|
||||||
component::{
|
component::{
|
||||||
font_icon::{FontIcon, font_icon},
|
font_icon::{FontIcon, FontIconSvg, font_icon},
|
||||||
text::text,
|
text::text,
|
||||||
},
|
},
|
||||||
query::{self, QueryStatus, read_query, use_query},
|
query::{self, QueryStatus, read_query, use_query},
|
||||||
@@ -134,6 +134,19 @@ impl gpui::RenderOnce for IssueListItem {
|
|||||||
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
||||||
let theme = app::current_theme(cx);
|
let theme = app::current_theme(cx);
|
||||||
|
|
||||||
|
fn pill(label: impl gpui::IntoElement + gpui::Styled, icon: FontIconSvg) -> gpui::Div {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.flex_row()
|
||||||
|
.items_center()
|
||||||
|
.justify_start()
|
||||||
|
.rounded_full()
|
||||||
|
.px_2()
|
||||||
|
.gap_1()
|
||||||
|
.child(icon.size_3())
|
||||||
|
.child(label.text_xs())
|
||||||
|
}
|
||||||
|
|
||||||
let repo_name_text = match self.repo_name {
|
let repo_name_text = match self.repo_name {
|
||||||
| Some(name) => text(name),
|
| Some(name) => text(name),
|
||||||
| None => text("Unknown repo"),
|
| None => text("Unknown repo"),
|
||||||
@@ -141,39 +154,43 @@ impl gpui::RenderOnce for IssueListItem {
|
|||||||
.text_xs()
|
.text_xs()
|
||||||
.opacity(0.5);
|
.opacity(0.5);
|
||||||
|
|
||||||
let icon = if self.is_draft {
|
let status_pill = if self.is_draft {
|
||||||
font_icon(FontIcon::PullRequestDraft)
|
pill(
|
||||||
.text_color(theme.colors.text)
|
text("Draft").text_color(theme.colors.text),
|
||||||
.opacity(0.5)
|
font_icon(FontIcon::PullRequestDraft).text_color(theme.colors.text),
|
||||||
|
)
|
||||||
|
.bg(theme.colors.surface)
|
||||||
} else {
|
} else {
|
||||||
match self.status {
|
match self.status {
|
||||||
| api::issues::PullRequestState::Closed => {
|
| api::issues::PullRequestState::Closed => pill(
|
||||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.danger)
|
text("Closed").text_color(theme.colors.danger_on_solid),
|
||||||
|
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.danger_on_solid),
|
||||||
|
)
|
||||||
|
.bg(theme.colors.danger_solid),
|
||||||
|
| api::issues::PullRequestState::Merged => pill(
|
||||||
|
text("Merged").text_color(theme.colors.accent_on_solid),
|
||||||
|
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.accent_on_solid),
|
||||||
|
)
|
||||||
|
.bg(theme.colors.accent_solid),
|
||||||
|
| _ => pill(
|
||||||
|
text("Open").text_color(theme.colors.success_on_solid),
|
||||||
|
font_icon(FontIcon::PullRequestArrow).text_color(theme.colors.success_on_solid),
|
||||||
|
)
|
||||||
|
.bg(theme.colors.success_solid),
|
||||||
}
|
}
|
||||||
| api::issues::PullRequestState::Merged => {
|
|
||||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.success)
|
|
||||||
}
|
|
||||||
| _ => font_icon(FontIcon::PullRequestArrow).text_color(theme.colors.success),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.flex_shrink_0()
|
|
||||||
.size_4();
|
|
||||||
|
|
||||||
let description_text = match self.description {
|
|
||||||
| Some(description) => text(description).text_xs(),
|
|
||||||
| None => text("No description provided").opacity(0.5).text_xs(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let pills_row = div().flex().flex_row().gap_1().my_1().child(status_pill);
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.relative()
|
.relative()
|
||||||
.w_full()
|
.w_full()
|
||||||
.px_1p5()
|
.px_3()
|
||||||
.py_1()
|
.py_1()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_row()
|
.flex_row()
|
||||||
.items_center()
|
.items_center()
|
||||||
.child(icon)
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
@@ -191,16 +208,13 @@ impl gpui::RenderOnce for IssueListItem {
|
|||||||
.min_w_0()
|
.min_w_0()
|
||||||
.line_clamp(2),
|
.line_clamp(2),
|
||||||
)
|
)
|
||||||
.child(description_text),
|
.child(pills_row),
|
||||||
)
|
)
|
||||||
.when(!self.is_last, |it| {
|
.when(!self.is_last, |it| {
|
||||||
it.border_b_1().border_color(theme.colors.border)
|
it.border_b_1().border_color(theme.colors.border)
|
||||||
})
|
})
|
||||||
.when(self.is_selected, |it| {
|
.when(self.is_selected, |it| {
|
||||||
it.bg(gpui::Rgba {
|
it.bg(theme.colors.selection_bg)
|
||||||
a: 0.05,
|
|
||||||
..theme.colors.accent
|
|
||||||
})
|
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.border_r_1()
|
.border_r_1()
|
||||||
.child(
|
.child(
|
||||||
@@ -210,11 +224,11 @@ impl gpui::RenderOnce for IssueListItem {
|
|||||||
.top_0()
|
.top_0()
|
||||||
.bottom_0()
|
.bottom_0()
|
||||||
.w_px()
|
.w_px()
|
||||||
.bg(theme.colors.accent)
|
.bg(theme.colors.selection_border)
|
||||||
.shadow(vec![gpui::BoxShadow {
|
.shadow(vec![gpui::BoxShadow {
|
||||||
blur_radius: px(16.),
|
blur_radius: px(16.),
|
||||||
spread_radius: px(2.),
|
spread_radius: px(2.),
|
||||||
color: gpui::Hsla::from(theme.colors.accent).alpha(0.8),
|
color: gpui::Hsla::from(theme.colors.selection_border).alpha(0.8),
|
||||||
offset: point(px(-2.), px(0.)),
|
offset: point(px(-2.), px(0.)),
|
||||||
}]),
|
}]),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
AppContext, InteractiveElement, IntoElement, ParentElement, StatefulInteractiveElement, Styled,
|
AppContext, InteractiveElement, IntoElement, ParentElement, StatefulInteractiveElement, Styled,
|
||||||
div, img, point, prelude::FluentBuilder, px,
|
div, img, prelude::FluentBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -24,7 +24,7 @@ pub(crate) struct PullRequestView {
|
|||||||
#[derive(gpui::IntoElement)]
|
#[derive(gpui::IntoElement)]
|
||||||
struct Toolbar {}
|
struct Toolbar {}
|
||||||
|
|
||||||
pub fn new(cx: &mut gpui::Context<PullRequestView>) -> PullRequestView {
|
pub fn new(_cx: &mut gpui::Context<PullRequestView>) -> PullRequestView {
|
||||||
PullRequestView {
|
PullRequestView {
|
||||||
markdown_viewer: None,
|
markdown_viewer: None,
|
||||||
pull_request_query: None,
|
pull_request_query: None,
|
||||||
@@ -91,32 +91,36 @@ impl PullRequestView {
|
|||||||
match pr.state {
|
match pr.state {
|
||||||
| api::issues::PullRequestState::Open => {
|
| api::issues::PullRequestState::Open => {
|
||||||
status_pill = status_pill
|
status_pill = status_pill
|
||||||
.bg(theme.colors.success)
|
.bg(theme.colors.success_solid)
|
||||||
.child(
|
.child(
|
||||||
font_icon(FontIcon::PullRequestArrow)
|
font_icon(FontIcon::PullRequestArrow)
|
||||||
.size_3()
|
.size_3()
|
||||||
.text_color(theme.colors.accent_text),
|
.text_color(theme.colors.success_on_solid),
|
||||||
)
|
)
|
||||||
.child(text("Open").text_color(theme.colors.accent_text).text_xs());
|
.child(
|
||||||
|
text("Open")
|
||||||
|
.text_color(theme.colors.success_on_solid)
|
||||||
|
.text_xs(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
| api::issues::PullRequestState::Closed => {
|
| api::issues::PullRequestState::Closed => {
|
||||||
status_pill = status_pill
|
status_pill = status_pill
|
||||||
.bg(theme.colors.danger)
|
.bg(theme.colors.danger_solid)
|
||||||
.child(
|
.child(
|
||||||
font_icon(FontIcon::PullRequestClosed)
|
font_icon(FontIcon::PullRequestClosed)
|
||||||
.size_3()
|
.size_3()
|
||||||
.text_color(theme.colors.accent_text),
|
.text_color(theme.colors.danger_on_solid),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
text("Closed")
|
text("Closed")
|
||||||
.text_color(theme.colors.accent_text)
|
.text_color(theme.colors.danger_on_solid)
|
||||||
.text_xs(),
|
.text_xs(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
| api::issues::PullRequestState::Merged => {
|
| api::issues::PullRequestState::Merged => {
|
||||||
status_pill = status_pill.bg(theme.colors.accent).child(
|
status_pill = status_pill.bg(theme.colors.accent_solid).child(
|
||||||
text("Merged")
|
text("Merged")
|
||||||
.text_color(theme.colors.accent_text)
|
.text_color(theme.colors.accent_on_solid)
|
||||||
.text_xs(),
|
.text_xs(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -148,7 +152,7 @@ impl PullRequestView {
|
|||||||
head_branch_text_offset..head_branch_text_offset + head_branch.len(),
|
head_branch_text_offset..head_branch_text_offset + head_branch.len(),
|
||||||
gpui::HighlightStyle {
|
gpui::HighlightStyle {
|
||||||
font_weight: Some(gpui::FontWeight::BOLD),
|
font_weight: Some(gpui::FontWeight::BOLD),
|
||||||
color: Some(theme.colors.accent.into()),
|
color: Some(theme.colors.accent_fg.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -156,7 +160,7 @@ impl PullRequestView {
|
|||||||
base_branch_text_offset..base_branch_text_offset + base_branch.len(),
|
base_branch_text_offset..base_branch_text_offset + base_branch.len(),
|
||||||
gpui::HighlightStyle {
|
gpui::HighlightStyle {
|
||||||
font_weight: Some(gpui::FontWeight::BOLD),
|
font_weight: Some(gpui::FontWeight::BOLD),
|
||||||
color: Some(theme.colors.accent.into()),
|
color: Some(theme.colors.accent_fg.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -274,7 +278,7 @@ impl gpui::Render for PullRequestView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl gpui::RenderOnce for Toolbar {
|
impl gpui::RenderOnce for Toolbar {
|
||||||
fn render(self, window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
||||||
fn toolbar_button(id: impl Into<gpui::ElementId>) -> Button {
|
fn toolbar_button(id: impl Into<gpui::ElementId>) -> Button {
|
||||||
button(id)
|
button(id)
|
||||||
.px_2p5()
|
.px_2p5()
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::{
|
|||||||
screen::dashboard::{
|
screen::dashboard::{
|
||||||
issue_list::{self, IssueList},
|
issue_list::{self, IssueList},
|
||||||
pull_request_view::{self, PullRequestView},
|
pull_request_view::{self, PullRequestView},
|
||||||
sidebar::{self, Sidebar, SidebarItemValue},
|
|
||||||
titlebar::{self, TitleBar},
|
titlebar::{self, TitleBar},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -13,7 +12,6 @@ use crate::{
|
|||||||
pub(crate) struct Screen {
|
pub(crate) struct Screen {
|
||||||
titlebar: gpui::Entity<TitleBar>,
|
titlebar: gpui::Entity<TitleBar>,
|
||||||
issue_list: gpui::Entity<IssueList>,
|
issue_list: gpui::Entity<IssueList>,
|
||||||
sidebar: gpui::Entity<Sidebar>,
|
|
||||||
pull_request_view: gpui::Entity<PullRequestView>,
|
pull_request_view: gpui::Entity<PullRequestView>,
|
||||||
|
|
||||||
issue_filter: Option<&'static str>,
|
issue_filter: Option<&'static str>,
|
||||||
@@ -23,7 +21,6 @@ pub(crate) fn new(cx: &mut gpui::Context<Screen>) -> Screen {
|
|||||||
let mut screen = Screen {
|
let mut screen = Screen {
|
||||||
titlebar: cx.new(titlebar::new),
|
titlebar: cx.new(titlebar::new),
|
||||||
issue_list: cx.new(issue_list::new),
|
issue_list: cx.new(issue_list::new),
|
||||||
sidebar: cx.new(|_| sidebar::new()),
|
|
||||||
pull_request_view: cx.new(pull_request_view::new),
|
pull_request_view: cx.new(pull_request_view::new),
|
||||||
|
|
||||||
issue_filter: None,
|
issue_filter: None,
|
||||||
@@ -34,13 +31,6 @@ pub(crate) fn new(cx: &mut gpui::Context<Screen>) -> Screen {
|
|||||||
|
|
||||||
impl Screen {
|
impl Screen {
|
||||||
fn on_create(&mut self, cx: &mut gpui::Context<Self>) {
|
fn on_create(&mut self, cx: &mut gpui::Context<Self>) {
|
||||||
let on_item_change = cx.listener(|this, value, _, cx| {
|
|
||||||
this.handle_sidebar_item_change(value, cx);
|
|
||||||
});
|
|
||||||
self.sidebar.update(cx, |sidebar, _| {
|
|
||||||
sidebar.on_item_change(on_item_change);
|
|
||||||
});
|
|
||||||
|
|
||||||
_ = cx
|
_ = cx
|
||||||
.subscribe(&self.issue_list, |this, _, event, cx| match event {
|
.subscribe(&self.issue_list, |this, _, event, cx| match event {
|
||||||
| issue_list::Event::ItemSelected(pr_id) => {
|
| issue_list::Event::ItemSelected(pr_id) => {
|
||||||
@@ -50,19 +40,6 @@ impl Screen {
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_sidebar_item_change(
|
|
||||||
&mut self,
|
|
||||||
value: &SidebarItemValue,
|
|
||||||
cx: &mut gpui::Context<Self>,
|
|
||||||
) {
|
|
||||||
match value {
|
|
||||||
| SidebarItemValue::PullRequest { filter } => {
|
|
||||||
self.issue_filter = Some(*filter);
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_issue_list_item_selected(
|
fn handle_issue_list_item_selected(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: &api::issues::Id,
|
id: &api::issues::Id,
|
||||||
@@ -97,21 +74,12 @@ impl gpui::Render for Screen {
|
|||||||
.flex_1()
|
.flex_1()
|
||||||
.min_h_0()
|
.min_h_0()
|
||||||
.w_full()
|
.w_full()
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.w_40()
|
|
||||||
.flex_shrink_0()
|
|
||||||
.h_full()
|
|
||||||
.child(self.sidebar.clone()),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.w_64()
|
.w_64()
|
||||||
.flex_shrink_0()
|
.flex_shrink_0()
|
||||||
.h_full()
|
.h_full()
|
||||||
.bg(theme.colors.surface)
|
.bg(theme.colors.surface_chrome)
|
||||||
.border_x_1()
|
|
||||||
.border_color(theme.colors.border)
|
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(self.issue_list.clone()),
|
.child(self.issue_list.clone()),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -160,19 +160,19 @@ impl gpui::RenderOnce for SidebarItem {
|
|||||||
.px_2()
|
.px_2()
|
||||||
.py_1()
|
.py_1()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(font_icon(self.icon).size_3().when(self.is_selected, |it| {
|
.child(
|
||||||
it.text_color(theme.colors.accent_text)
|
font_icon(self.icon)
|
||||||
}))
|
.size_3()
|
||||||
|
.when(self.is_selected, |it| it.text_color(theme.colors.accent_fg)),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
text(self.title)
|
text(self.title)
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.leading_tight()
|
.leading_tight()
|
||||||
.when(self.is_selected, |it| {
|
.when(self.is_selected, |it| it.text_color(theme.colors.accent_fg)),
|
||||||
it.text_color(theme.colors.accent_text)
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.when_some(self.on_click, |it, f| it.on_click(f))
|
.when_some(self.on_click, |it, f| it.on_click(f))
|
||||||
.when(self.is_selected, |it| it.bg(theme.colors.accent))
|
.when(self.is_selected, |it| it.bg(theme.colors.selection_bg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use gpui::{ParentElement, Styled, TitlebarOptions, div};
|
use gpui::{ParentElement, Styled, div};
|
||||||
|
|
||||||
use crate::component::button::button;
|
use crate::component::button::button;
|
||||||
use crate::query::{self, QueryStatus, read_query, use_lazy_query, use_query};
|
use crate::query::{self, QueryStatus, read_query, use_lazy_query};
|
||||||
use crate::{
|
use crate::{
|
||||||
api, app,
|
api, app,
|
||||||
component::{
|
component::{
|
||||||
@@ -32,13 +32,13 @@ impl gpui::Render for TitleBar {
|
|||||||
let user = read_query(&self.fetch_user_query, cx);
|
let user = read_query(&self.fetch_user_query, cx);
|
||||||
|
|
||||||
let user_avatar = match user {
|
let user_avatar = match user {
|
||||||
QueryStatus::Err(api::Error::Unauthenticated) => div().absolute().right_2p5().child(
|
| QueryStatus::Err(api::Error::Unauthenticated) => div().absolute().right_2p5().child(
|
||||||
button("login-btn")
|
button("login-btn")
|
||||||
.leading(font_icon(FontIcon::Github))
|
.leading(font_icon(FontIcon::Github))
|
||||||
.label("Login"),
|
.label("Login"),
|
||||||
),
|
),
|
||||||
|
|
||||||
_ => div(),
|
| _ => div(),
|
||||||
};
|
};
|
||||||
|
|
||||||
div()
|
div()
|
||||||
@@ -50,7 +50,7 @@ impl gpui::Render for TitleBar {
|
|||||||
.flex()
|
.flex()
|
||||||
.px(g.safe_area.size.width)
|
.px(g.safe_area.size.width)
|
||||||
.py_2()
|
.py_2()
|
||||||
.bg(g.current_theme.colors.background)
|
.bg(g.current_theme.colors.surface_chrome)
|
||||||
.text_color(g.current_theme.colors.text)
|
.text_color(g.current_theme.colors.text)
|
||||||
.relative()
|
.relative()
|
||||||
.border_b_1()
|
.border_b_1()
|
||||||
@@ -61,7 +61,7 @@ impl gpui::Render for TitleBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RepoSelector {
|
impl RepoSelector {
|
||||||
pub fn new(cx: &mut gpui::Context<Self>) -> Self {
|
pub fn new(_cx: &mut gpui::Context<Self>) -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ impl GithubStepView {
|
|||||||
let poll_interval = u64::from(*interval);
|
let poll_interval = u64::from(*interval);
|
||||||
|
|
||||||
match read_query(query, cx) {
|
match read_query(query, cx) {
|
||||||
QueryStatus::Loaded(data) => {
|
| QueryStatus::Loaded(data) => {
|
||||||
let auth_tokens = api::AuthTokens {
|
let auth_tokens = api::AuthTokens {
|
||||||
access_token: data.access_token.clone(),
|
access_token: data.access_token.clone(),
|
||||||
};
|
};
|
||||||
@@ -226,7 +226,7 @@ impl GithubStepView {
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryStatus::Err(api::Error::Github(api::GithubError { error, .. })) => {
|
| QueryStatus::Err(api::Error::Github(api::GithubError { error, .. })) => {
|
||||||
if error == "authorization_pending" {
|
if error == "authorization_pending" {
|
||||||
cx.spawn(async move |weak, cx| {
|
cx.spawn(async move |weak, cx| {
|
||||||
Timer::after(Duration::from_secs(poll_interval)).await;
|
Timer::after(Duration::from_secs(poll_interval)).await;
|
||||||
@@ -242,7 +242,7 @@ impl GithubStepView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
| _ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,8 +263,8 @@ impl GithubStepView {
|
|||||||
let theme = app::current_theme(cx);
|
let theme = app::current_theme(cx);
|
||||||
|
|
||||||
let (displayed_code, copyable_code) = match create_device_code_query {
|
let (displayed_code, copyable_code) = match create_device_code_query {
|
||||||
QueryStatus::Loaded(data) => (data.user_code.as_str(), Some(data.user_code.clone())),
|
| QueryStatus::Loaded(data) => (data.user_code.as_str(), Some(data.user_code.clone())),
|
||||||
_ => (self.placeholder_code.as_str(), None),
|
| _ => (self.placeholder_code.as_str(), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let border_color = theme.colors.border.clone();
|
let border_color = theme.colors.border.clone();
|
||||||
@@ -358,14 +358,14 @@ impl gpui::Render for GithubStepView {
|
|||||||
cx: &mut gpui::Context<Self>,
|
cx: &mut gpui::Context<Self>,
|
||||||
) -> impl gpui::IntoElement {
|
) -> impl gpui::IntoElement {
|
||||||
let (can_go_next, header, body) = match self.user_query {
|
let (can_go_next, header, body) = match self.user_query {
|
||||||
None => (false, self.header(), self.device_code_area(cx)),
|
| None => (false, self.header(), self.device_code_area(cx)),
|
||||||
Some(ref q) => {
|
| Some(ref q) => {
|
||||||
let user_query = read_query(q, cx);
|
let user_query = read_query(q, cx);
|
||||||
match user_query {
|
match user_query {
|
||||||
QueryStatus::Loaded(user) => {
|
| QueryStatus::Loaded(user) => {
|
||||||
(true, connected_header(), connected_body(user, cx))
|
(true, connected_header(), connected_body(user, cx))
|
||||||
}
|
}
|
||||||
_ => (false, self.header(), self.device_code_area(cx)),
|
| _ => (false, self.header(), self.device_code_area(cx)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -436,7 +436,7 @@ fn connected_body(user: &api::user::User, cx: &gpui::Context<GithubStepView>) ->
|
|||||||
.rounded_2xl()
|
.rounded_2xl()
|
||||||
.border_1()
|
.border_1()
|
||||||
.w_full()
|
.w_full()
|
||||||
.border_color(theme.colors.surface_elevated)
|
.border_color(theme.colors.border)
|
||||||
.p_4()
|
.p_4()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
@@ -461,9 +461,13 @@ fn connected_body(user: &api::user::User, cx: &gpui::Context<GithubStepView>) ->
|
|||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.rounded_full()
|
.rounded_full()
|
||||||
.bg(theme.colors.accent)
|
.bg(theme.colors.success_solid)
|
||||||
.p_1()
|
.p_1()
|
||||||
.child(font_icon(FontIcon::Check).size_4()),
|
.child(
|
||||||
|
font_icon(FontIcon::Check)
|
||||||
|
.size_4()
|
||||||
|
.text_color(theme.colors.success_on_solid),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ pub fn open_window(screen: Screen, cx: &mut gpui::App) -> anyhow::Result<()> {
|
|||||||
impl Step {
|
impl Step {
|
||||||
pub const fn order(&self) -> usize {
|
pub const fn order(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Step::Welcome => 0,
|
| Step::Welcome => 0,
|
||||||
Step::ConnectToGithub => 1,
|
| Step::ConnectToGithub => 1,
|
||||||
Step::SetupComplete => 2,
|
| Step::SetupComplete => 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ pub(crate) fn from_saved(state: StoredSetupState) -> Screen {
|
|||||||
impl Screen {
|
impl Screen {
|
||||||
fn advance_to_next_step(&mut self, cx: &mut gpui::Context<Self>) {
|
fn advance_to_next_step(&mut self, cx: &mut gpui::Context<Self>) {
|
||||||
let next_step = match self.current_step {
|
let next_step = match self.current_step {
|
||||||
Step::Welcome => Step::ConnectToGithub,
|
| Step::Welcome => Step::ConnectToGithub,
|
||||||
Step::ConnectToGithub => Step::SetupComplete,
|
| Step::ConnectToGithub => Step::SetupComplete,
|
||||||
_ => panic!(),
|
| _ => panic!(),
|
||||||
};
|
};
|
||||||
self.current_step = next_step;
|
self.current_step = next_step;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
@@ -67,8 +67,8 @@ impl Screen {
|
|||||||
cx: &mut gpui::Context<Self>,
|
cx: &mut gpui::Context<Self>,
|
||||||
) -> &gpui::Entity<github_step::GithubStepView> {
|
) -> &gpui::Entity<github_step::GithubStepView> {
|
||||||
match self.github_step_view {
|
match self.github_step_view {
|
||||||
Some(ref v) => v,
|
| Some(ref v) => v,
|
||||||
None => {
|
| None => {
|
||||||
let weak = cx.weak_entity();
|
let weak = cx.weak_entity();
|
||||||
self.github_step_view = Some(cx.new(|cx| {
|
self.github_step_view = Some(cx.new(|cx| {
|
||||||
let mut v = github_step::new(cx);
|
let mut v = github_step::new(cx);
|
||||||
@@ -90,9 +90,9 @@ impl Screen {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, step)| {
|
.map(|(i, step)| {
|
||||||
let label = match step {
|
let label = match step {
|
||||||
Step::Welcome => "Welcome!",
|
| Step::Welcome => "Welcome!",
|
||||||
Step::ConnectToGithub => "Connect to GitHub",
|
| Step::ConnectToGithub => "Connect to GitHub",
|
||||||
Step::SetupComplete => "Complete!",
|
| Step::SetupComplete => "Complete!",
|
||||||
};
|
};
|
||||||
let is_completed = i < self.current_step.order();
|
let is_completed = i < self.current_step.order();
|
||||||
let is_current = self.current_step == *step;
|
let is_current = self.current_step == *step;
|
||||||
@@ -138,16 +138,16 @@ impl gpui::Render for Screen {
|
|||||||
cx: &mut gpui::Context<Self>,
|
cx: &mut gpui::Context<Self>,
|
||||||
) -> impl gpui::IntoElement {
|
) -> impl gpui::IntoElement {
|
||||||
let step_view = match self.current_step {
|
let step_view = match self.current_step {
|
||||||
Step::Welcome => welcome_step()
|
| Step::Welcome => welcome_step()
|
||||||
.on_next(cx.listener(|this, _, _, cx| this.advance_to_next_step(cx)))
|
.on_next(cx.listener(|this, _, _, cx| this.advance_to_next_step(cx)))
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
|
|
||||||
Step::ConnectToGithub => match self.github_step_view {
|
| Step::ConnectToGithub => match self.github_step_view {
|
||||||
Some(ref view) => view.clone().into_any_element(),
|
| Some(ref view) => view.clone().into_any_element(),
|
||||||
None => self.init_github_step_view(cx).clone().into_any_element(),
|
| None => self.init_github_step_view(cx).clone().into_any_element(),
|
||||||
},
|
},
|
||||||
|
|
||||||
Step::SetupComplete => setup_complete_step().into_any_element(),
|
| Step::SetupComplete => setup_complete_step().into_any_element(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let theme = app::current_theme(cx);
|
let theme = app::current_theme(cx);
|
||||||
@@ -165,7 +165,7 @@ impl gpui::Render for Screen {
|
|||||||
.justify_center()
|
.justify_center()
|
||||||
.w_1_3()
|
.w_1_3()
|
||||||
.h_full()
|
.h_full()
|
||||||
.bg(theme.colors.surface)
|
.bg(theme.colors.surface_chrome)
|
||||||
.relative()
|
.relative()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ pub(crate) struct PersistedState {
|
|||||||
|
|
||||||
pub(crate) fn data_dir_path() -> std::path::PathBuf {
|
pub(crate) fn data_dir_path() -> std::path::PathBuf {
|
||||||
match std::env::consts::OS {
|
match std::env::consts::OS {
|
||||||
"macos" => std::env::home_dir()
|
| "macos" => std::env::home_dir()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join("Library")
|
.join("Library")
|
||||||
.join("Application Support")
|
.join("Application Support")
|
||||||
.join("novem"),
|
.join("novem"),
|
||||||
_ => unimplemented!(
|
| _ => unimplemented!(
|
||||||
"data_dir_path is unimplemented for OS: {}",
|
"data_dir_path is unimplemented for OS: {}",
|
||||||
std::env::consts::OS
|
std::env::consts::OS
|
||||||
),
|
),
|
||||||
|
|||||||
102
src/theme.rs
102
src/theme.rs
@@ -1,6 +1,6 @@
|
|||||||
use gpui::Rgba;
|
mod catppuccin;
|
||||||
|
|
||||||
use crate::colors::hex;
|
use gpui::Rgba;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub enum ThemeMode {
|
pub enum ThemeMode {
|
||||||
@@ -28,15 +28,49 @@ pub struct ThemeColors {
|
|||||||
pub background: Rgba,
|
pub background: Rgba,
|
||||||
pub surface: Rgba,
|
pub surface: Rgba,
|
||||||
pub surface_elevated: Rgba,
|
pub surface_elevated: Rgba,
|
||||||
|
pub surface_chrome: Rgba,
|
||||||
|
pub surface_hover: Rgba,
|
||||||
|
pub surface_active: Rgba,
|
||||||
pub border: Rgba,
|
pub border: Rgba,
|
||||||
|
pub border_muted: Rgba,
|
||||||
|
pub border_strong: Rgba,
|
||||||
|
pub focus_ring: Rgba,
|
||||||
pub text: Rgba,
|
pub text: Rgba,
|
||||||
pub text_muted: Rgba,
|
pub text_muted: Rgba,
|
||||||
pub accent: Rgba,
|
pub text_subtle: Rgba,
|
||||||
pub accent_hover: Rgba,
|
pub text_disabled: Rgba,
|
||||||
pub accent_text: Rgba,
|
pub icon_muted: Rgba,
|
||||||
pub success: Rgba,
|
pub link: Rgba,
|
||||||
pub warning: Rgba,
|
pub link_hover: Rgba,
|
||||||
pub danger: Rgba,
|
pub code_bg: Rgba,
|
||||||
|
pub code_border: Rgba,
|
||||||
|
pub selection_bg: Rgba,
|
||||||
|
pub selection_border: Rgba,
|
||||||
|
pub accent_fg: Rgba,
|
||||||
|
pub accent_muted: Rgba,
|
||||||
|
pub accent_border: Rgba,
|
||||||
|
pub accent_solid: Rgba,
|
||||||
|
pub accent_on_solid: Rgba,
|
||||||
|
pub success_fg: Rgba,
|
||||||
|
pub success_muted: Rgba,
|
||||||
|
pub success_border: Rgba,
|
||||||
|
pub success_solid: Rgba,
|
||||||
|
pub success_on_solid: Rgba,
|
||||||
|
pub warning_fg: Rgba,
|
||||||
|
pub warning_muted: Rgba,
|
||||||
|
pub warning_border: Rgba,
|
||||||
|
pub warning_solid: Rgba,
|
||||||
|
pub warning_on_solid: Rgba,
|
||||||
|
pub danger_fg: Rgba,
|
||||||
|
pub danger_muted: Rgba,
|
||||||
|
pub danger_border: Rgba,
|
||||||
|
pub danger_solid: Rgba,
|
||||||
|
pub danger_on_solid: Rgba,
|
||||||
|
pub info_fg: Rgba,
|
||||||
|
pub info_muted: Rgba,
|
||||||
|
pub info_border: Rgba,
|
||||||
|
pub info_solid: Rgba,
|
||||||
|
pub info_on_solid: Rgba,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
@@ -52,13 +86,13 @@ impl ThemeFamily {
|
|||||||
|
|
||||||
pub const fn id(self) -> &'static str {
|
pub const fn id(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
| Self::Catppuccin => "catppuccin",
|
| Self::Catppuccin => catppuccin::FAMILY_ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn label(self) -> &'static str {
|
pub const fn label(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
| Self::Catppuccin => "Catppuccin",
|
| Self::Catppuccin => catppuccin::FAMILY_LABEL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,51 +139,15 @@ impl ThemeVariant {
|
|||||||
|
|
||||||
pub const fn label(self) -> &'static str {
|
pub const fn label(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
| Self::CatppuccinLatte => "Catppuccin Latte",
|
| Self::CatppuccinLatte => catppuccin::LATTE_LABEL,
|
||||||
| Self::CatppuccinMocha => "Catppuccin Mocha",
|
| Self::CatppuccinMocha => catppuccin::MOCHA_LABEL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn theme(self) -> Theme {
|
pub const fn theme(self) -> Theme {
|
||||||
match self {
|
match self {
|
||||||
| Self::CatppuccinLatte => Theme {
|
| Self::CatppuccinLatte => catppuccin::latte(),
|
||||||
id: "catppuccin-latte",
|
| Self::CatppuccinMocha => catppuccin::mocha(),
|
||||||
name: "Catppuccin Latte",
|
|
||||||
mode: ThemeMode::Light,
|
|
||||||
colors: ThemeColors {
|
|
||||||
background: hex(0xeff1f5),
|
|
||||||
surface: hex(0xeff1f5),
|
|
||||||
surface_elevated: hex(0xdce0e8),
|
|
||||||
border: hex(0xccd0da),
|
|
||||||
text: hex(0x4c4f69),
|
|
||||||
text_muted: hex(0x6c6f85),
|
|
||||||
accent: hex(0x8839ef),
|
|
||||||
accent_hover: hex(0x7287fd),
|
|
||||||
accent_text: hex(0xeff1f5),
|
|
||||||
success: hex(0x40a02b),
|
|
||||||
warning: hex(0xdf8e1d),
|
|
||||||
danger: hex(0xd20f39),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
| Self::CatppuccinMocha => Theme {
|
|
||||||
id: "catppuccin-mocha",
|
|
||||||
name: "Catppuccin Mocha",
|
|
||||||
mode: ThemeMode::Dark,
|
|
||||||
colors: ThemeColors {
|
|
||||||
background: hex(0x1e1e2e),
|
|
||||||
surface: hex(0x181825),
|
|
||||||
surface_elevated: hex(0x313244),
|
|
||||||
border: hex(0x45475a),
|
|
||||||
text: hex(0xcdd6f4),
|
|
||||||
text_muted: hex(0xa6adc8),
|
|
||||||
accent: hex(0xcba6f7),
|
|
||||||
accent_hover: hex(0xb4befe),
|
|
||||||
accent_text: hex(0x1e1e2e),
|
|
||||||
success: hex(0xa6e3a1),
|
|
||||||
warning: hex(0xf9e2af),
|
|
||||||
danger: hex(0xf38ba8),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,7 +155,9 @@ impl ThemeVariant {
|
|||||||
impl From<gpui::WindowAppearance> for ThemeMode {
|
impl From<gpui::WindowAppearance> for ThemeMode {
|
||||||
fn from(value: gpui::WindowAppearance) -> Self {
|
fn from(value: gpui::WindowAppearance) -> Self {
|
||||||
match value {
|
match value {
|
||||||
| gpui::WindowAppearance::Light | gpui::WindowAppearance::VibrantLight => ThemeMode::Light,
|
| gpui::WindowAppearance::Light | gpui::WindowAppearance::VibrantLight => {
|
||||||
|
ThemeMode::Light
|
||||||
|
}
|
||||||
| gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => ThemeMode::Dark,
|
| gpui::WindowAppearance::Dark | gpui::WindowAppearance::VibrantDark => ThemeMode::Dark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
121
src/theme/catppuccin.rs
Normal file
121
src/theme/catppuccin.rs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
use crate::colors::{hex, hex_alpha};
|
||||||
|
|
||||||
|
use super::{Theme, ThemeColors, ThemeMode};
|
||||||
|
|
||||||
|
pub(crate) const FAMILY_ID: &str = "catppuccin";
|
||||||
|
pub(crate) const FAMILY_LABEL: &str = "Catppuccin";
|
||||||
|
|
||||||
|
pub(crate) const LATTE_LABEL: &str = "Catppuccin Latte";
|
||||||
|
pub(crate) const MOCHA_LABEL: &str = "Catppuccin Mocha";
|
||||||
|
|
||||||
|
pub(crate) const fn latte() -> Theme {
|
||||||
|
Theme {
|
||||||
|
id: "catppuccin-latte",
|
||||||
|
name: LATTE_LABEL,
|
||||||
|
mode: ThemeMode::Light,
|
||||||
|
colors: ThemeColors {
|
||||||
|
background: hex(0xeff1f5),
|
||||||
|
surface: hex(0xeff1f5),
|
||||||
|
surface_elevated: hex(0xdce0e8),
|
||||||
|
surface_chrome: hex(0xe6e9ef),
|
||||||
|
surface_hover: hex(0xe6e9ef),
|
||||||
|
surface_active: hex(0xdce0e8),
|
||||||
|
border: hex(0xbcc0cc),
|
||||||
|
border_muted: hex(0xccd0da),
|
||||||
|
border_strong: hex(0xacb0be),
|
||||||
|
focus_ring: hex(0x7287fd),
|
||||||
|
text: hex(0x4c4f69),
|
||||||
|
text_muted: hex(0x5c5f77),
|
||||||
|
text_subtle: hex(0x6c6f85),
|
||||||
|
text_disabled: hex(0x9ca0b0),
|
||||||
|
icon_muted: hex(0x6c6f85),
|
||||||
|
link: hex(0x1e66f5),
|
||||||
|
link_hover: hex(0x7287fd),
|
||||||
|
code_bg: hex(0xe6e9ef),
|
||||||
|
code_border: hex(0xccd0da),
|
||||||
|
selection_bg: hex_alpha(0x8839ef, 0.10),
|
||||||
|
selection_border: hex_alpha(0x8839ef, 0.35),
|
||||||
|
accent_fg: hex(0x8839ef),
|
||||||
|
accent_muted: hex_alpha(0x8839ef, 0.12),
|
||||||
|
accent_border: hex_alpha(0x8839ef, 0.28),
|
||||||
|
accent_solid: hex(0x8839ef),
|
||||||
|
accent_on_solid: hex(0xeff1f5),
|
||||||
|
success_fg: hex(0x40a02b),
|
||||||
|
success_muted: hex_alpha(0x40a02b, 0.12),
|
||||||
|
success_border: hex_alpha(0x40a02b, 0.28),
|
||||||
|
success_solid: hex(0x40a02b),
|
||||||
|
success_on_solid: hex(0x1e1e2e),
|
||||||
|
warning_fg: hex(0xdf8e1d),
|
||||||
|
warning_muted: hex_alpha(0xdf8e1d, 0.12),
|
||||||
|
warning_border: hex_alpha(0xdf8e1d, 0.32),
|
||||||
|
warning_solid: hex(0xdf8e1d),
|
||||||
|
warning_on_solid: hex(0x1e1e2e),
|
||||||
|
danger_fg: hex(0xd20f39),
|
||||||
|
danger_muted: hex_alpha(0xd20f39, 0.12),
|
||||||
|
danger_border: hex_alpha(0xd20f39, 0.28),
|
||||||
|
danger_solid: hex(0xd20f39),
|
||||||
|
danger_on_solid: hex(0xeff1f5),
|
||||||
|
info_fg: hex(0x1e66f5),
|
||||||
|
info_muted: hex_alpha(0x1e66f5, 0.12),
|
||||||
|
info_border: hex_alpha(0x1e66f5, 0.28),
|
||||||
|
info_solid: hex(0x1e66f5),
|
||||||
|
info_on_solid: hex(0xeff1f5),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn mocha() -> Theme {
|
||||||
|
Theme {
|
||||||
|
id: "catppuccin-mocha",
|
||||||
|
name: MOCHA_LABEL,
|
||||||
|
mode: ThemeMode::Dark,
|
||||||
|
colors: ThemeColors {
|
||||||
|
background: hex(0x1e1e2e),
|
||||||
|
surface: hex(0x181825),
|
||||||
|
surface_elevated: hex(0x313244),
|
||||||
|
surface_chrome: hex(0x11111b),
|
||||||
|
surface_hover: hex(0x313244),
|
||||||
|
surface_active: hex(0x45475a),
|
||||||
|
border: hex(0x585b70),
|
||||||
|
border_muted: hex(0x45475a),
|
||||||
|
border_strong: hex(0x6c7086),
|
||||||
|
focus_ring: hex(0xb4befe),
|
||||||
|
text: hex(0xcdd6f4),
|
||||||
|
text_muted: hex(0xbac2de),
|
||||||
|
text_subtle: hex(0xa6adc8),
|
||||||
|
text_disabled: hex(0x7f849c),
|
||||||
|
icon_muted: hex(0xa6adc8),
|
||||||
|
link: hex(0x89b4fa),
|
||||||
|
link_hover: hex(0xb4befe),
|
||||||
|
code_bg: hex(0x11111b),
|
||||||
|
code_border: hex(0x45475a),
|
||||||
|
selection_bg: hex_alpha(0xcba6f7, 0.18),
|
||||||
|
selection_border: hex_alpha(0xcba6f7, 0.45),
|
||||||
|
accent_fg: hex(0xcba6f7),
|
||||||
|
accent_muted: hex_alpha(0xcba6f7, 0.18),
|
||||||
|
accent_border: hex_alpha(0xcba6f7, 0.34),
|
||||||
|
accent_solid: hex(0xcba6f7),
|
||||||
|
accent_on_solid: hex(0x1e1e2e),
|
||||||
|
success_fg: hex(0xa6e3a1),
|
||||||
|
success_muted: hex_alpha(0xa6e3a1, 0.18),
|
||||||
|
success_border: hex_alpha(0xa6e3a1, 0.34),
|
||||||
|
success_solid: hex(0xa6e3a1),
|
||||||
|
success_on_solid: hex(0x1e1e2e),
|
||||||
|
warning_fg: hex(0xf9e2af),
|
||||||
|
warning_muted: hex_alpha(0xf9e2af, 0.18),
|
||||||
|
warning_border: hex_alpha(0xf9e2af, 0.38),
|
||||||
|
warning_solid: hex(0xf9e2af),
|
||||||
|
warning_on_solid: hex(0x1e1e2e),
|
||||||
|
danger_fg: hex(0xf38ba8),
|
||||||
|
danger_muted: hex_alpha(0xf38ba8, 0.18),
|
||||||
|
danger_border: hex_alpha(0xf38ba8, 0.34),
|
||||||
|
danger_solid: hex(0xf38ba8),
|
||||||
|
danger_on_solid: hex(0x1e1e2e),
|
||||||
|
info_fg: hex(0x89b4fa),
|
||||||
|
info_muted: hex_alpha(0x89b4fa, 0.18),
|
||||||
|
info_border: hex_alpha(0x89b4fa, 0.34),
|
||||||
|
info_solid: hex(0x89b4fa),
|
||||||
|
info_on_solid: hex(0x1e1e2e),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user