update issue panel
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
||||||
|
<path d="M21.25 6.75C21.25 5.64543 20.3546 4.75 19.25 4.75H4.75C3.64543 4.75 2.75 5.64543 2.75 6.75V17.25C2.75 18.3546 3.64543 19.25 4.75 19.25H19.25C20.3546 19.25 21.25 18.3546 21.25 17.25V6.75Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.75 14.25V9.75L9 12L11.25 9.75V14.25" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M15.75 9.75V14.25L14 12.5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M15.75 14.25L17.5 12.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 731 B |
@@ -87,6 +87,7 @@ pub enum CustomIconName {
|
|||||||
GitClone,
|
GitClone,
|
||||||
GitBranch,
|
GitBranch,
|
||||||
Tag,
|
Tag,
|
||||||
|
Markdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IconNamed for CustomIconName {
|
impl IconNamed for CustomIconName {
|
||||||
@@ -108,6 +109,7 @@ impl IconNamed for CustomIconName {
|
|||||||
CustomIconName::GitClone => "icons/git-clone.svg",
|
CustomIconName::GitClone => "icons/git-clone.svg",
|
||||||
CustomIconName::GitBranch => "icons/git-branch.svg",
|
CustomIconName::GitBranch => "icons/git-branch.svg",
|
||||||
CustomIconName::Tag => "icons/tag.svg",
|
CustomIconName::Tag => "icons/tag.svg",
|
||||||
|
CustomIconName::Markdown => "icons/markdown.svg",
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use assets::CustomIconName;
|
||||||
use dock::{BasePanel, Panel, PanelEvent};
|
use dock::{BasePanel, Panel, PanelEvent};
|
||||||
use gpui::prelude::*;
|
use gpui::prelude::*;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -9,7 +10,7 @@ use gpui_component::button::{Button, ButtonVariants};
|
|||||||
use gpui_component::input::{Textarea, TextareaState};
|
use gpui_component::input::{Textarea, TextareaState};
|
||||||
use gpui_component::scroll::ScrollableElement;
|
use gpui_component::scroll::ScrollableElement;
|
||||||
use gpui_component::tag::Tag;
|
use gpui_component::tag::Tag;
|
||||||
use gpui_component::{ActiveTheme, Sizable, StyledExt, h_flex, v_flex};
|
use gpui_component::{ActiveTheme, Icon, Sizable, StyledExt, h_flex, v_flex};
|
||||||
use nostr::prelude::{Event, EventId, PublicKey};
|
use nostr::prelude::{Event, EventId, PublicKey};
|
||||||
use signed_core::activity_subject;
|
use signed_core::activity_subject;
|
||||||
use signed_state::{ProfileStore, RepoStore};
|
use signed_state::{ProfileStore, RepoStore};
|
||||||
@@ -84,7 +85,7 @@ impl IssueDetailView {
|
|||||||
let picture = profile.picture();
|
let picture = profile.picture();
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_1()
|
||||||
.items_center()
|
.items_center()
|
||||||
.child(
|
.child(
|
||||||
Avatar::new()
|
Avatar::new()
|
||||||
@@ -107,7 +108,7 @@ impl IssueDetailView {
|
|||||||
div()
|
div()
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.text_color(cx.theme().muted_foreground)
|
.text_color(cx.theme().muted_foreground)
|
||||||
.child("No labels"),
|
.child("None yet."),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this.child(h_flex().gap_1().children({
|
this.child(h_flex().gap_1().children({
|
||||||
@@ -133,9 +134,11 @@ impl IssueDetailView {
|
|||||||
fn render_comments(&mut self, id: &EventId, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render_comments(&mut self, id: &EventId, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let store = self.store.read(cx);
|
let store = self.store.read(cx);
|
||||||
let comments: Vec<&Event> = store.comments_of(id).collect();
|
let comments: Vec<&Event> = store.comments_of(id).collect();
|
||||||
|
let title = SharedString::from(format!("Discussions {}", comments.len()));
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_3()
|
.gap_4()
|
||||||
|
.child(div().text_xs().font_semibold().child(title))
|
||||||
.children(comments.iter().map(|comment| {
|
.children(comments.iter().map(|comment| {
|
||||||
let profile = ProfileStore::global(cx).read(cx).get(&comment.pubkey);
|
let profile = ProfileStore::global(cx).read(cx).get(&comment.pubkey);
|
||||||
let author = profile.name();
|
let author = profile.name();
|
||||||
@@ -144,6 +147,10 @@ impl IssueDetailView {
|
|||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
.p_3()
|
||||||
|
.border_1()
|
||||||
|
.border_color(cx.theme().border)
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
@@ -156,10 +163,15 @@ impl IssueDetailView {
|
|||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius)
|
||||||
.xsmall(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(author),
|
.child(author),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_color(cx.theme().muted_foreground)
|
||||||
|
.child("commented"),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.text_color(cx.theme().muted_foreground)
|
.text_color(cx.theme().muted_foreground)
|
||||||
@@ -175,42 +187,57 @@ impl IssueDetailView {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_form(&mut self, id: &EventId, _cx: &mut Context<Self>) -> impl IntoElement {
|
fn render_form(&mut self, id: &EventId, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let comment_input = self.comment_input.clone();
|
let comment_input = self.comment_input.clone();
|
||||||
let store = self.store.clone();
|
let store = self.store.clone();
|
||||||
let id = id.to_owned();
|
let id = id.to_owned();
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(Textarea::new(&self.comment_input).h(px(96.)))
|
|
||||||
.child(
|
.child(
|
||||||
h_flex().justify_end().child(
|
Textarea::new(&self.comment_input)
|
||||||
Button::new("comment")
|
.h_24()
|
||||||
.primary()
|
.text_color(cx.theme().muted_foreground)
|
||||||
.label("Comment")
|
.bg(cx.theme().muted),
|
||||||
.tooltip("Post comment")
|
)
|
||||||
.on_click(move |_event, window, cx| {
|
.child(
|
||||||
let content = comment_input.read(cx).value().trim().to_string();
|
h_flex()
|
||||||
if content.is_empty() {
|
.justify_between()
|
||||||
return;
|
.child(
|
||||||
}
|
h_flex()
|
||||||
let Some(root) = store
|
.gap_1()
|
||||||
.read(cx)
|
.text_xs()
|
||||||
.issues
|
.text_color(cx.theme().muted_foreground)
|
||||||
.iter()
|
.child(Icon::new(CustomIconName::Markdown).small())
|
||||||
.find(|issue| issue.id == id)
|
.child("Markdown is supported"),
|
||||||
.cloned()
|
)
|
||||||
else {
|
.child(
|
||||||
return;
|
Button::new("comment")
|
||||||
};
|
.primary()
|
||||||
store.update(cx, |store, cx| {
|
.label("Comment")
|
||||||
store.comment(&root, content, cx);
|
.tooltip("Post comment")
|
||||||
});
|
.on_click(move |_event, window, cx| {
|
||||||
comment_input.update(cx, |input, cx| {
|
let content = comment_input.read(cx).value().trim().to_string();
|
||||||
input.set_value("", window, cx);
|
if content.is_empty() {
|
||||||
});
|
return;
|
||||||
}),
|
}
|
||||||
),
|
let Some(root) = store
|
||||||
|
.read(cx)
|
||||||
|
.issues
|
||||||
|
.iter()
|
||||||
|
.find(|issue| issue.id == id)
|
||||||
|
.cloned()
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
store.update(cx, |store, cx| {
|
||||||
|
store.comment(&root, content, cx);
|
||||||
|
});
|
||||||
|
comment_input.update(cx, |input, cx| {
|
||||||
|
input.set_value("", window, cx);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user