Compare commits
2 Commits
update-wor
...
quick-comm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58a7a277df | ||
|
|
5e9f084f12 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -12604,9 +12604,11 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"editor",
|
"editor",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
"menu",
|
||||||
"settings",
|
"settings",
|
||||||
"theme",
|
"theme",
|
||||||
"ui",
|
"ui",
|
||||||
|
"workspace",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ gpui.workspace = true
|
|||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
theme.workspace = true
|
theme.workspace = true
|
||||||
ui.workspace = true
|
ui.workspace = true
|
||||||
|
workspace.workspace = true
|
||||||
|
menu.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(unused, dead_code)]
|
||||||
|
|
||||||
//! # UI – Text Field
|
//! # UI – Text Field
|
||||||
//!
|
//!
|
||||||
//! This crate provides a text field component that can be used to create text fields like search inputs, form fields, etc.
|
//! This crate provides a text field component that can be used to create text fields like search inputs, form fields, etc.
|
||||||
@@ -5,11 +7,14 @@
|
|||||||
//! It can't be located in the `ui` crate because it depends on `editor`.
|
//! It can't be located in the `ui` crate because it depends on `editor`.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::default;
|
||||||
|
|
||||||
use editor::*;
|
use editor::*;
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
use ui::*;
|
use ui::{List, *};
|
||||||
|
use workspace::{ModalView, Workspace};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum FieldLabelLayout {
|
pub enum FieldLabelLayout {
|
||||||
@@ -187,3 +192,243 @@ impl Render for TextField {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
actions!(quick_commit, [ToggleStageAll]);
|
||||||
|
|
||||||
|
pub const MODAL_WIDTH: f32 = 700.0;
|
||||||
|
pub const MODAL_HEIGHT: f32 = 300.0;
|
||||||
|
|
||||||
|
fn test_files() -> Vec<ChangedFile> {
|
||||||
|
vec![
|
||||||
|
ChangedFile {
|
||||||
|
id: 0,
|
||||||
|
state: FileVCSState::Modified,
|
||||||
|
file_name: "file1.txt".into(),
|
||||||
|
file_path: "/path/to/file1.txt".into(),
|
||||||
|
},
|
||||||
|
ChangedFile {
|
||||||
|
id: 1,
|
||||||
|
state: FileVCSState::Deleted,
|
||||||
|
file_name: "file2.txt".into(),
|
||||||
|
file_path: "/path/to/file2.txt".into(),
|
||||||
|
},
|
||||||
|
ChangedFile {
|
||||||
|
id: 2,
|
||||||
|
state: FileVCSState::Created,
|
||||||
|
file_name: "file3.txt".into(),
|
||||||
|
file_path: "/path/to/file3.txt".into(),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
|
enum FileVCSState {
|
||||||
|
Deleted,
|
||||||
|
Modified,
|
||||||
|
Created,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChangedFileId(usize);
|
||||||
|
|
||||||
|
impl ChangedFileId {
|
||||||
|
fn new(id: usize) -> Self {
|
||||||
|
Self(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// placeholder for ui
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct ChangedFile {
|
||||||
|
id: usize,
|
||||||
|
state: FileVCSState,
|
||||||
|
file_name: SharedString,
|
||||||
|
file_path: SharedString,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct QuickCommitState {
|
||||||
|
placeholder_text: SharedString,
|
||||||
|
tracked_files: Vec<ChangedFile>,
|
||||||
|
staged_files: Vec<usize>,
|
||||||
|
active_participant_handles: Vec<SharedString>,
|
||||||
|
editor: View<Editor>,
|
||||||
|
workspace: WeakView<Workspace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuickCommitState {
|
||||||
|
fn init(
|
||||||
|
editor: View<Editor>,
|
||||||
|
workspace: WeakView<Workspace>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Self {
|
||||||
|
let workspace = workspace.clone();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
placeholder_text: "Add a message".into(),
|
||||||
|
tracked_files: Default::default(),
|
||||||
|
staged_files: Default::default(),
|
||||||
|
active_participant_handles: Default::default(),
|
||||||
|
editor,
|
||||||
|
workspace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stage_state(&self) -> Selection {
|
||||||
|
let staged_files = self.staged_files.clone();
|
||||||
|
let tracked_files = self.tracked_files.clone();
|
||||||
|
|
||||||
|
if staged_files.len() == tracked_files.len() {
|
||||||
|
Selection::Selected
|
||||||
|
} else if staged_files.is_empty() {
|
||||||
|
Selection::Unselected
|
||||||
|
} else {
|
||||||
|
Selection::Indeterminate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stage_all(&mut self) -> &mut Self {
|
||||||
|
let tracked_files = self.tracked_files.clone();
|
||||||
|
|
||||||
|
self.staged_files = tracked_files.iter().map(|file| file.id).collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle_stage_all(&mut self) {
|
||||||
|
let stage_state = self.stage_state();
|
||||||
|
|
||||||
|
let staged_files = self.staged_files.clone();
|
||||||
|
let tracked_files = self.tracked_files.clone();
|
||||||
|
|
||||||
|
match stage_state {
|
||||||
|
Selection::Selected => {
|
||||||
|
self.staged_files.clear();
|
||||||
|
}
|
||||||
|
Selection::Unselected | Selection::Indeterminate => {
|
||||||
|
self.stage_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle_file_staged(&mut self, file_id: usize) {
|
||||||
|
if let Some(pos) = self.staged_files.iter().position() {
|
||||||
|
self.staged_files.swap_remove(pos);
|
||||||
|
} else {
|
||||||
|
self.staged_files.push(file_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct QuickCommit {
|
||||||
|
state: Model<QuickCommitState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuickCommit {
|
||||||
|
pub fn init(workspace: WeakView<Workspace>, cx: &mut WindowContext) -> View<Self> {
|
||||||
|
let editor = cx.new_view(|cx| {
|
||||||
|
let mut editor = Editor::multi_line(cx);
|
||||||
|
editor.set_show_gutter(false, cx);
|
||||||
|
editor
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.new_view(|cx| {
|
||||||
|
let state = cx
|
||||||
|
.new_model(move |cx| QuickCommitState::init(editor.clone(), workspace.clone(), cx));
|
||||||
|
|
||||||
|
Self { state }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stage_state(&self, cx: &ViewContext<Self>) -> Selection {
|
||||||
|
self.state.read(cx).stage_state()
|
||||||
|
}
|
||||||
|
fn toggle_stage_all(&mut self, _: &ToggleStageAll, cx: &mut ViewContext<Self>) {
|
||||||
|
self.state.update(cx, |state, _| state.toggle_stage_all());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
|
||||||
|
cx.emit(DismissEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||||
|
self.state.read(cx).editor.focus_handle(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuickCommit {
|
||||||
|
fn render_file_list(&mut self, cx: &mut ViewContext<Self>) -> List {
|
||||||
|
List::new().empty_message("No changes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for QuickCommit {
|
||||||
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
|
let staged_files = self.state.read(cx).staged_files.clone();
|
||||||
|
let total_tracked_files = self.state.read(cx).tracked_files.clone();
|
||||||
|
let staged_state = self.stage_state(cx);
|
||||||
|
|
||||||
|
h_flex()
|
||||||
|
.id("quick_commit_modal")
|
||||||
|
.key_context("quick_commit")
|
||||||
|
.track_focus(&self.focus_handle(cx))
|
||||||
|
.on_action(cx.listener(Self::cancel))
|
||||||
|
.occlude()
|
||||||
|
.h(px(MODAL_HEIGHT))
|
||||||
|
.w(px(MODAL_WIDTH))
|
||||||
|
.child(
|
||||||
|
// commit editor
|
||||||
|
div()
|
||||||
|
.h_full()
|
||||||
|
.flex_1()
|
||||||
|
// .child(self.editor.clone())
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.absolute()
|
||||||
|
.bottom_2()
|
||||||
|
.right_2()
|
||||||
|
.child(Button::new("submit_commit", "Commit")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
// file list
|
||||||
|
div()
|
||||||
|
.w(relative(0.42))
|
||||||
|
.h_full()
|
||||||
|
.border_l_1()
|
||||||
|
.border_color(cx.theme().colors().border)
|
||||||
|
// sticky header
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.h_10()
|
||||||
|
.w_full()
|
||||||
|
.child(Label::new(format!(
|
||||||
|
"Staged Files: {}/{}",
|
||||||
|
staged_files.len(),
|
||||||
|
total_tracked_files.len()
|
||||||
|
)))
|
||||||
|
.child(Checkbox::new("toggle-stage-all", staged_state).on_click(
|
||||||
|
|_, cx| {
|
||||||
|
cx.dispatch_action(ToggleStageAll.boxed_clone());
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
// file list
|
||||||
|
.child(self.render_file_list(cx)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<DismissEvent> for QuickCommit {}
|
||||||
|
|
||||||
|
impl FocusableView for QuickCommit {
|
||||||
|
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||||
|
// TODO: Not sure this is right
|
||||||
|
self.focus_handle(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModalView for QuickCommit {
|
||||||
|
fn fade_out_background(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user