mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-12 05:15:00 +00:00
Move model and remaining tokens to assistant toolbar
This commit is contained in:
parent
d78fbbc63e
commit
a75341db97
3 changed files with 106 additions and 79 deletions
|
@ -85,7 +85,7 @@
|
|||
// Where to dock the assistant. Can be 'left', 'right' or 'bottom'.
|
||||
"dock": "right",
|
||||
// Default width when the assistant is docked to the left or right.
|
||||
"default_width": 450,
|
||||
"default_width": 640,
|
||||
// Default height when the assistant is docked to the bottom.
|
||||
"default_height": 320
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@ use std::{
|
|||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use theme::ui::IconStyle;
|
||||
use theme::{ui::IconStyle, AssistantStyle};
|
||||
use util::{
|
||||
channel::ReleaseChannel, paths::CONVERSATIONS_DIR, post_inc, truncate_and_trailoff, ResultExt,
|
||||
TryFutureExt,
|
||||
|
@ -112,8 +112,8 @@ pub enum AssistantPanelEvent {
|
|||
pub struct AssistantPanel {
|
||||
width: Option<f32>,
|
||||
height: Option<f32>,
|
||||
active_conversation_index: Option<usize>,
|
||||
conversation_editors: Vec<ViewHandle<ConversationEditor>>,
|
||||
active_editor_index: Option<usize>,
|
||||
editors: Vec<ViewHandle<ConversationEditor>>,
|
||||
saved_conversations: Vec<SavedConversationMetadata>,
|
||||
saved_conversations_list_state: UniformListState,
|
||||
zoomed: bool,
|
||||
|
@ -162,8 +162,8 @@ impl AssistantPanel {
|
|||
});
|
||||
|
||||
let mut this = Self {
|
||||
active_conversation_index: Default::default(),
|
||||
conversation_editors: Default::default(),
|
||||
active_editor_index: Default::default(),
|
||||
editors: Default::default(),
|
||||
saved_conversations,
|
||||
saved_conversations_list_state: Default::default(),
|
||||
zoomed: false,
|
||||
|
@ -216,8 +216,12 @@ impl AssistantPanel {
|
|||
self.subscriptions
|
||||
.push(cx.subscribe(&editor, Self::handle_conversation_editor_event));
|
||||
|
||||
self.active_conversation_index = Some(self.conversation_editors.len());
|
||||
self.conversation_editors.push(editor.clone());
|
||||
let conversation = editor.read(cx).conversation.clone();
|
||||
self.subscriptions
|
||||
.push(cx.observe(&conversation, |_, _, cx| cx.notify()));
|
||||
|
||||
self.active_editor_index = Some(self.editors.len());
|
||||
self.editors.push(editor.clone());
|
||||
if self.has_focus(cx) {
|
||||
cx.focus(&editor);
|
||||
}
|
||||
|
@ -271,9 +275,8 @@ impl AssistantPanel {
|
|||
}
|
||||
}
|
||||
|
||||
fn active_conversation_editor(&self) -> Option<&ViewHandle<ConversationEditor>> {
|
||||
self.conversation_editors
|
||||
.get(self.active_conversation_index?)
|
||||
fn active_editor(&self) -> Option<&ViewHandle<ConversationEditor>> {
|
||||
self.editors.get(self.active_editor_index?)
|
||||
}
|
||||
|
||||
fn render_hamburger_button(style: &IconStyle) -> impl Element<Self> {
|
||||
|
@ -284,11 +287,71 @@ impl AssistantPanel {
|
|||
.mouse::<ListConversations>(0)
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
|
||||
this.active_conversation_index = None;
|
||||
this.active_editor_index = None;
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
|
||||
fn render_current_model(
|
||||
&self,
|
||||
style: &AssistantStyle,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<impl Element<Self>> {
|
||||
enum Model {}
|
||||
|
||||
let model = self
|
||||
.active_editor()?
|
||||
.read(cx)
|
||||
.conversation
|
||||
.read(cx)
|
||||
.model
|
||||
.clone();
|
||||
|
||||
Some(
|
||||
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
||||
let style = style.model.style_for(state, false);
|
||||
Label::new(model, style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, |_, this, cx| {
|
||||
if let Some(editor) = this.active_editor() {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.cycle_model(cx);
|
||||
});
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn render_remaining_tokens(
|
||||
&self,
|
||||
style: &AssistantStyle,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<impl Element<Self>> {
|
||||
self.active_editor().and_then(|editor| {
|
||||
editor
|
||||
.read(cx)
|
||||
.conversation
|
||||
.read(cx)
|
||||
.remaining_tokens()
|
||||
.map(|remaining_tokens| {
|
||||
let remaining_tokens_style = if remaining_tokens <= 0 {
|
||||
&style.no_remaining_tokens
|
||||
} else {
|
||||
&style.remaining_tokens
|
||||
};
|
||||
Label::new(
|
||||
remaining_tokens.to_string(),
|
||||
remaining_tokens_style.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(remaining_tokens_style.container)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn render_plus_button(style: &IconStyle) -> impl Element<Self> {
|
||||
enum AddConversation {}
|
||||
Svg::for_style(style.icon.clone())
|
||||
|
@ -337,8 +400,8 @@ impl AssistantPanel {
|
|||
}
|
||||
|
||||
fn open_conversation(&mut self, path: PathBuf, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
|
||||
if let Some(ix) = self.conversation_editor_index_for_path(&path, cx) {
|
||||
self.active_conversation_index = Some(ix);
|
||||
if let Some(ix) = self.editor_index_for_path(&path, cx) {
|
||||
self.active_editor_index = Some(ix);
|
||||
cx.notify();
|
||||
return Task::ready(Ok(()));
|
||||
}
|
||||
|
@ -356,8 +419,8 @@ impl AssistantPanel {
|
|||
this.update(&mut cx, |this, cx| {
|
||||
// If, by the time we've loaded the conversation, the user has already opened
|
||||
// the same conversation, we don't want to open it again.
|
||||
if let Some(ix) = this.conversation_editor_index_for_path(&path, cx) {
|
||||
this.active_conversation_index = Some(ix);
|
||||
if let Some(ix) = this.editor_index_for_path(&path, cx) {
|
||||
this.active_editor_index = Some(ix);
|
||||
} else {
|
||||
let editor = cx
|
||||
.add_view(|cx| ConversationEditor::from_conversation(conversation, fs, cx));
|
||||
|
@ -368,8 +431,8 @@ impl AssistantPanel {
|
|||
})
|
||||
}
|
||||
|
||||
fn conversation_editor_index_for_path(&self, path: &Path, cx: &AppContext) -> Option<usize> {
|
||||
self.conversation_editors
|
||||
fn editor_index_for_path(&self, path: &Path, cx: &AppContext) -> Option<usize> {
|
||||
self.editors
|
||||
.iter()
|
||||
.position(|editor| editor.read(cx).conversation.read(cx).path.as_deref() == Some(path))
|
||||
}
|
||||
|
@ -418,11 +481,13 @@ impl View for AssistantPanel {
|
|||
.aligned()
|
||||
.into_any()
|
||||
} else {
|
||||
let title = self.active_conversation_editor().map(|editor| {
|
||||
let title = self.active_editor().map(|editor| {
|
||||
Label::new(editor.read(cx).title(cx), style.title.text.clone())
|
||||
.contained()
|
||||
.with_style(style.title.container)
|
||||
.aligned()
|
||||
.left()
|
||||
.flex(1., false)
|
||||
});
|
||||
|
||||
Flex::column()
|
||||
|
@ -432,6 +497,14 @@ impl View for AssistantPanel {
|
|||
Self::render_hamburger_button(&style.hamburger_button).aligned(),
|
||||
)
|
||||
.with_children(title)
|
||||
.with_children(
|
||||
self.render_current_model(&style, cx)
|
||||
.map(|current_model| current_model.aligned().flex_float()),
|
||||
)
|
||||
.with_children(
|
||||
self.render_remaining_tokens(&style, cx)
|
||||
.map(|remaining_tokens| remaining_tokens.aligned().flex_float()),
|
||||
)
|
||||
.with_child(
|
||||
Self::render_plus_button(&style.plus_button)
|
||||
.aligned()
|
||||
|
@ -443,7 +516,7 @@ impl View for AssistantPanel {
|
|||
.constrained()
|
||||
.with_height(theme.workspace.tab_bar.height),
|
||||
)
|
||||
.with_child(if let Some(editor) = self.active_conversation_editor() {
|
||||
.with_child(if let Some(editor) = self.active_editor() {
|
||||
ChildView::new(editor, cx).flex(1., true).into_any()
|
||||
} else {
|
||||
UniformList::new(
|
||||
|
@ -466,7 +539,7 @@ impl View for AssistantPanel {
|
|||
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
self.has_focus = true;
|
||||
if cx.is_self_focused() {
|
||||
if let Some(editor) = self.active_conversation_editor() {
|
||||
if let Some(editor) = self.active_editor() {
|
||||
cx.focus(editor);
|
||||
} else if let Some(api_key_editor) = self.api_key_editor.as_ref() {
|
||||
cx.focus(api_key_editor);
|
||||
|
@ -562,7 +635,7 @@ impl Panel for AssistantPanel {
|
|||
}
|
||||
}
|
||||
|
||||
if self.conversation_editors.is_empty() {
|
||||
if self.editors.is_empty() {
|
||||
self.new_conversation(cx);
|
||||
}
|
||||
}
|
||||
|
@ -1700,7 +1773,7 @@ impl ConversationEditor {
|
|||
if let Some(text) = text {
|
||||
panel.update(cx, |panel, cx| {
|
||||
let conversation = panel
|
||||
.active_conversation_editor()
|
||||
.active_editor()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| panel.new_conversation(cx));
|
||||
conversation.update(cx, |conversation, cx| {
|
||||
|
@ -1781,7 +1854,7 @@ impl ConversationEditor {
|
|||
.summary
|
||||
.as_ref()
|
||||
.map(|summary| summary.text.clone())
|
||||
.unwrap_or_else(|| "New Context".into())
|
||||
.unwrap_or_else(|| "New Conversation".into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1795,49 +1868,10 @@ impl View for ConversationEditor {
|
|||
}
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||
enum Model {}
|
||||
let theme = &theme::current(cx).assistant;
|
||||
let conversation = self.conversation.read(cx);
|
||||
let model = conversation.model.clone();
|
||||
let remaining_tokens = conversation.remaining_tokens().map(|remaining_tokens| {
|
||||
let remaining_tokens_style = if remaining_tokens <= 0 {
|
||||
&theme.no_remaining_tokens
|
||||
} else {
|
||||
&theme.remaining_tokens
|
||||
};
|
||||
Label::new(
|
||||
remaining_tokens.to_string(),
|
||||
remaining_tokens_style.text.clone(),
|
||||
)
|
||||
ChildView::new(&self.editor, cx)
|
||||
.contained()
|
||||
.with_style(remaining_tokens_style.container)
|
||||
});
|
||||
|
||||
Stack::new()
|
||||
.with_child(
|
||||
ChildView::new(&self.editor, cx)
|
||||
.contained()
|
||||
.with_style(theme.container),
|
||||
)
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
MouseEventHandler::<Model, _>::new(0, cx, |state, _| {
|
||||
let style = theme.model.style_for(state, false);
|
||||
Label::new(model, style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, |_, this, cx| this.cycle_model(cx)),
|
||||
)
|
||||
.with_children(remaining_tokens)
|
||||
.contained()
|
||||
.with_style(theme.model_info_container)
|
||||
.aligned()
|
||||
.top()
|
||||
.right(),
|
||||
)
|
||||
.with_style(theme.container)
|
||||
.into_any()
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ export default function assistant(colorScheme: ColorScheme) {
|
|||
},
|
||||
},
|
||||
container: {
|
||||
margin: { left: 8 },
|
||||
margin: { left: 12 },
|
||||
}
|
||||
},
|
||||
plusButton: {
|
||||
|
@ -37,11 +37,11 @@ export default function assistant(colorScheme: ColorScheme) {
|
|||
},
|
||||
},
|
||||
container: {
|
||||
margin: { right: 8 },
|
||||
margin: { right: 12 },
|
||||
}
|
||||
},
|
||||
title: {
|
||||
margin: { left: 8 },
|
||||
margin: { left: 12 },
|
||||
...text(layer, "sans", "default", { size: "sm" })
|
||||
},
|
||||
savedConversation: {
|
||||
|
@ -76,28 +76,21 @@ export default function assistant(colorScheme: ColorScheme) {
|
|||
},
|
||||
model: {
|
||||
background: background(layer, "on"),
|
||||
border: border(layer, "on", { overlay: true }),
|
||||
margin: { right: 8 },
|
||||
padding: 4,
|
||||
cornerRadius: 4,
|
||||
...text(layer, "sans", "default", { size: "xs" }),
|
||||
hover: {
|
||||
background: background(layer, "on", "hovered"),
|
||||
border: border(layer, "on", { overlay: true }),
|
||||
},
|
||||
},
|
||||
remainingTokens: {
|
||||
background: background(layer, "on"),
|
||||
border: border(layer, "on", { overlay: true }),
|
||||
padding: 4,
|
||||
margin: { left: 4 },
|
||||
cornerRadius: 4,
|
||||
margin: { right: 12 },
|
||||
...text(layer, "sans", "positive", { size: "xs" }),
|
||||
},
|
||||
noRemainingTokens: {
|
||||
background: background(layer, "on"),
|
||||
border: border(layer, "on", { overlay: true }),
|
||||
padding: 4,
|
||||
margin: { left: 4 },
|
||||
cornerRadius: 4,
|
||||
margin: { right: 12 },
|
||||
...text(layer, "sans", "negative", { size: "xs" }),
|
||||
},
|
||||
errorIcon: {
|
||||
|
|
Loading…
Reference in a new issue