feat: allow choosing the default branch when publishing a repo
This commit is contained in:
@@ -2,16 +2,19 @@ use std::path::PathBuf;
|
||||
|
||||
use assets::CustomIconName;
|
||||
use gpui::prelude::*;
|
||||
use gpui::{App, Entity, WeakEntity, Window, px};
|
||||
use gpui::{App, Entity, SharedString, WeakEntity, Window, px};
|
||||
use gpui_base::h_flex;
|
||||
use gpui_base::input::TextareaState;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dialog::{DialogDescription, DialogFooter, DialogHeader, DialogTitle};
|
||||
use gpui_component::form::{field, v_form};
|
||||
use gpui_component::input::{Input, InputState, Textarea};
|
||||
use gpui_component::select::{Select, SelectState};
|
||||
use gpui_component::{ActiveTheme, Disableable, WindowExt};
|
||||
use settings::SettingsStore;
|
||||
use signed_git::Repo;
|
||||
use signed_state::Backend;
|
||||
use signed_ui::SelectOption;
|
||||
|
||||
use super::RepoDetailView;
|
||||
use crate::views::dialog_state::{DialogProgress, error_row};
|
||||
@@ -48,8 +51,11 @@ pub fn open(
|
||||
.auto_grow(3, 5)
|
||||
.placeholder("Short description")
|
||||
});
|
||||
let branch_select: Entity<SelectState<Vec<SelectOption>>> =
|
||||
cx.new(|cx| SelectState::new(Vec::new(), None, window, cx));
|
||||
|
||||
load_user_grasp_servers(grasp_state.clone(), window, cx);
|
||||
load_branches(local_path.clone(), branch_select.clone(), window, cx);
|
||||
|
||||
window.open_dialog(cx, move |dialog, _window, _cx| {
|
||||
const DESC: &str = "Publish this local repository to Nostr.";
|
||||
@@ -57,6 +63,7 @@ pub fn open(
|
||||
let name_input = name_input.clone();
|
||||
let desc_input = desc_input.clone();
|
||||
let relay_input = relay_input.clone();
|
||||
let branch_select = branch_select.clone();
|
||||
let state = state.clone();
|
||||
let grasp_state = grasp_state.clone();
|
||||
let local_path = local_path.clone();
|
||||
@@ -105,6 +112,12 @@ pub fn open(
|
||||
.child(local_path.display().to_string()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
field()
|
||||
.label("Default branch")
|
||||
.description("The local branch to announce as the default")
|
||||
.child(Select::new(&branch_select).w_full()),
|
||||
)
|
||||
.child(grasp_servers_field(&grasp_state, &relay_input, cx)),
|
||||
)
|
||||
.children(error_row(&error, cx))
|
||||
@@ -120,6 +133,7 @@ pub fn open(
|
||||
.on_click({
|
||||
let name_input = name_input.clone();
|
||||
let desc_input = desc_input.clone();
|
||||
let branch_select = branch_select.clone();
|
||||
let state = state.clone();
|
||||
let grasp_state = grasp_state.clone();
|
||||
let local_path = local_path.clone();
|
||||
@@ -129,6 +143,7 @@ pub fn open(
|
||||
init_repository(
|
||||
local_path.clone(),
|
||||
(name_input.clone(), desc_input.clone()),
|
||||
branch_select.clone(),
|
||||
state.clone(),
|
||||
grasp_state.clone(),
|
||||
view.clone(),
|
||||
@@ -143,9 +158,11 @@ pub fn open(
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn init_repository(
|
||||
local_path: PathBuf,
|
||||
inputs: (Entity<InputState>, Entity<TextareaState>),
|
||||
branch_select: Entity<SelectState<Vec<SelectOption>>>,
|
||||
state: Entity<InitRepoState>,
|
||||
grasp_state: Entity<GraspServersState>,
|
||||
view: WeakEntity<RepoDetailView>,
|
||||
@@ -156,6 +173,11 @@ fn init_repository(
|
||||
let name = name_input.read(cx).value().trim().to_owned();
|
||||
let description = desc_input.read(cx).value().trim().to_owned();
|
||||
let servers = grasp_state.read(cx).grasp_servers.clone();
|
||||
let default_branch = branch_select
|
||||
.read(cx)
|
||||
.selected_value()
|
||||
.map(|value| value.trim().to_owned())
|
||||
.filter(|branch| !branch.is_empty());
|
||||
|
||||
if name.is_empty() {
|
||||
state.update(cx, |state, _| state.fail("Repository name is required"));
|
||||
@@ -171,7 +193,14 @@ fn init_repository(
|
||||
|
||||
let backend = Backend::global(cx);
|
||||
let task = backend.update(cx, |backend, cx| {
|
||||
backend.publish_local_repo(local_path.clone(), &name, &description, servers, cx)
|
||||
backend.publish_local_repo(
|
||||
local_path.clone(),
|
||||
&name,
|
||||
&description,
|
||||
servers,
|
||||
default_branch,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let handle = window.window_handle();
|
||||
@@ -199,3 +228,45 @@ fn init_repository(
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
/// Fills the default-branch selector with the repository's local branches,
|
||||
/// preselecting the checked-out one.
|
||||
fn load_branches(
|
||||
local_path: PathBuf,
|
||||
select: Entity<SelectState<Vec<SelectOption>>>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let handle = window.window_handle();
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let loaded = cx
|
||||
.background_spawn(async move {
|
||||
let repo = Repo::open(&local_path)?;
|
||||
let current: Option<SharedString> = repo.current_branch().map(Into::into);
|
||||
Ok::<_, anyhow::Error>((repo.branches()?, current))
|
||||
})
|
||||
.await;
|
||||
|
||||
let _ = cx.update_window(handle, |_, window, cx| {
|
||||
let Ok((branches, current)) = loaded.map_err(|error| {
|
||||
log::warn!("failed to list branches for the default branch selector: {error:#}")
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let options: Vec<SelectOption> = branches
|
||||
.into_iter()
|
||||
.map(|branch| SelectOption::new(branch.clone(), branch))
|
||||
.collect();
|
||||
|
||||
select.update(cx, |state, cx| {
|
||||
state.set_items(options, window, cx);
|
||||
if let Some(current) = current.as_ref() {
|
||||
state.set_selected_value(current, window, cx);
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
@@ -828,10 +828,6 @@ impl RepoDetailView {
|
||||
}
|
||||
|
||||
/// Open the upstream repository, the `u` tag of this fork's announcement.
|
||||
///
|
||||
/// The announcement may not be in the local database yet. The panel opens
|
||||
/// from the address and fills in when the store loads it; the store's
|
||||
/// `subscribe_remote` fetches it from the bootstrap relays.
|
||||
pub(super) fn open_upstream(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let Some(addr) = self
|
||||
.announcement(cx)
|
||||
@@ -1788,6 +1784,12 @@ impl RepoDetailView {
|
||||
/// The Files tab body, or the clone/initial-load spinner.
|
||||
fn render_files_tab(&self, cx: &mut Context<Self>) -> AnyElement {
|
||||
if self.loading {
|
||||
let label = if self.store.read(cx).path.is_some() {
|
||||
"Loading repository..."
|
||||
} else {
|
||||
"Cloning repository..."
|
||||
};
|
||||
|
||||
return v_flex()
|
||||
.flex_1()
|
||||
.size_full()
|
||||
@@ -1799,7 +1801,7 @@ impl RepoDetailView {
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child("Cloning repository..."),
|
||||
.child(label),
|
||||
)
|
||||
.into_any_element();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user