refactor(branch-dropdown): drop worktree parent-branch merge shortcut
Remove the parent-branch button shown beside the branch selector along with its supporting API, command, service, model, and i18n strings. Add migration m20260423 to drop the now-unused folder.parent_branch column.
This commit is contained in:
@@ -19,6 +19,7 @@ use tauri::Manager;
|
||||
use crate::app_error::AppCommandError;
|
||||
#[cfg(feature = "tauri-runtime")]
|
||||
use crate::db::error::DbError;
|
||||
#[cfg(feature = "tauri-runtime")]
|
||||
use crate::db::service::folder_service;
|
||||
use crate::db::AppDatabase;
|
||||
use crate::models::GitCredentials;
|
||||
@@ -479,40 +480,6 @@ pub async fn add_folder_to_history(
|
||||
folder_service::add_folder(&db.conn, &path).await
|
||||
}
|
||||
|
||||
pub(crate) async fn set_folder_parent_branch_core(
|
||||
conn: &sea_orm::DatabaseConnection,
|
||||
path: &str,
|
||||
parent_branch: Option<String>,
|
||||
) -> Result<(), AppCommandError> {
|
||||
use crate::db::entities::folder;
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
||||
let row = folder::Entity::find()
|
||||
.filter(folder::Column::Path.eq(path))
|
||||
.filter(folder::Column::DeletedAt.is_null())
|
||||
.one(conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
AppCommandError::database_error("Failed to query folder").with_detail(e.to_string())
|
||||
})?;
|
||||
|
||||
if let Some(folder_model) = row {
|
||||
folder_service::set_folder_parent_branch(conn, folder_model.id, parent_branch)
|
||||
.await
|
||||
.map_err(AppCommandError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "tauri-runtime")]
|
||||
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
||||
pub async fn set_folder_parent_branch(
|
||||
db: tauri::State<'_, AppDatabase>,
|
||||
path: String,
|
||||
parent_branch: Option<String>,
|
||||
) -> Result<(), AppCommandError> {
|
||||
set_folder_parent_branch_core(&db.conn, &path, parent_branch).await
|
||||
}
|
||||
|
||||
#[cfg(feature = "tauri-runtime")]
|
||||
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
||||
pub async fn remove_folder_from_history(
|
||||
|
||||
@@ -15,7 +15,6 @@ pub struct Model {
|
||||
pub updated_at: DateTimeUtc,
|
||||
pub deleted_at: Option<DateTimeUtc>,
|
||||
pub is_open: bool,
|
||||
pub parent_branch: Option<String>,
|
||||
pub sort_order: i32,
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Folder::Table)
|
||||
.drop_column(Folder::ParentBranch)
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Folder::Table)
|
||||
.add_column(ColumnDef::new(Folder::ParentBranch).string().null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Folder {
|
||||
Table,
|
||||
ParentBranch,
|
||||
}
|
||||
@@ -11,6 +11,7 @@ mod m20260404_000001_model_provider;
|
||||
mod m20260406_000001_agent_setting_model_provider;
|
||||
mod m20260420_000001_opened_tabs;
|
||||
mod m20260422_000001_folder_sort_order;
|
||||
mod m20260423_000001_drop_folder_parent_branch;
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -28,6 +29,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260406_000001_agent_setting_model_provider::Migration),
|
||||
Box::new(m20260420_000001_opened_tabs::Migration),
|
||||
Box::new(m20260422_000001_folder_sort_order::Migration),
|
||||
Box::new(m20260423_000001_drop_folder_parent_branch::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ fn to_detail(m: folder::Model) -> FolderDetail {
|
||||
name: m.name,
|
||||
path: m.path,
|
||||
git_branch: m.git_branch,
|
||||
parent_branch: m.parent_branch,
|
||||
default_agent_type,
|
||||
last_opened_at: m.last_opened_at,
|
||||
sort_order: m.sort_order,
|
||||
@@ -85,7 +84,6 @@ pub async fn add_folder(
|
||||
name: Set(name),
|
||||
path: Set(path.to_string()),
|
||||
git_branch: Set(None),
|
||||
parent_branch: Set(None),
|
||||
default_agent_type: Set(None),
|
||||
last_opened_at: Set(now),
|
||||
created_at: Set(now),
|
||||
@@ -127,22 +125,6 @@ pub async fn remove_folder(conn: &DatabaseConnection, path: &str) -> Result<(),
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_folder_parent_branch(
|
||||
conn: &DatabaseConnection,
|
||||
folder_id: i32,
|
||||
parent_branch: Option<String>,
|
||||
) -> Result<(), DbError> {
|
||||
let row = folder::Entity::find_by_id(folder_id).one(conn).await?;
|
||||
|
||||
if let Some(row) = row {
|
||||
let mut active = row.into_active_model();
|
||||
active.parent_branch = Set(parent_branch);
|
||||
active.updated_at = Set(Utc::now());
|
||||
active.update(conn).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_folder_open(
|
||||
conn: &DatabaseConnection,
|
||||
folder_id: i32,
|
||||
|
||||
@@ -225,7 +225,6 @@ mod tauri_app {
|
||||
folders::remove_folder_from_workspace,
|
||||
folders::reorder_folders,
|
||||
folders::add_folder_to_history,
|
||||
folders::set_folder_parent_branch,
|
||||
folders::remove_folder_from_history,
|
||||
folders::create_folder_directory,
|
||||
folders::clone_repository,
|
||||
|
||||
@@ -17,7 +17,6 @@ pub struct FolderDetail {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
pub git_branch: Option<String>,
|
||||
pub parent_branch: Option<String>,
|
||||
pub default_agent_type: Option<AgentType>,
|
||||
pub last_opened_at: DateTime<Utc>,
|
||||
pub sort_order: i32,
|
||||
|
||||
@@ -287,13 +287,6 @@ pub async fn open_push_window(
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SetFolderParentBranchParams {
|
||||
pub path: String,
|
||||
pub parent_branch: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn add_folder_to_history(
|
||||
Extension(state): Extension<Arc<AppState>>,
|
||||
Json(params): Json<AddFolderParams>,
|
||||
@@ -305,16 +298,6 @@ pub async fn add_folder_to_history(
|
||||
Ok(Json(result))
|
||||
}
|
||||
|
||||
pub async fn set_folder_parent_branch(
|
||||
Extension(state): Extension<Arc<AppState>>,
|
||||
Json(params): Json<SetFolderParentBranchParams>,
|
||||
) -> Result<Json<()>, AppCommandError> {
|
||||
let db = &state.db;
|
||||
folder_commands::set_folder_parent_branch_core(&db.conn, ¶ms.path, params.parent_branch)
|
||||
.await?;
|
||||
Ok(Json(()))
|
||||
}
|
||||
|
||||
pub async fn remove_folder_from_history(
|
||||
Extension(state): Extension<Arc<AppState>>,
|
||||
Json(params): Json<AddFolderParams>,
|
||||
|
||||
@@ -114,10 +114,6 @@ pub fn build_router(state: Arc<AppState>, token: String, static_dir: std::path::
|
||||
"/add_folder_to_history",
|
||||
post(handlers::folders::add_folder_to_history),
|
||||
)
|
||||
.route(
|
||||
"/set_folder_parent_branch",
|
||||
post(handlers::folders::set_folder_parent_branch),
|
||||
)
|
||||
.route(
|
||||
"/remove_folder_from_history",
|
||||
post(handlers::folders::remove_folder_from_history),
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
ArchiveRestore,
|
||||
Archive,
|
||||
ArrowDownToLine,
|
||||
ArrowLeftRight,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
FolderGit2,
|
||||
@@ -77,7 +76,6 @@ import {
|
||||
openCommitWindow,
|
||||
openPushWindow,
|
||||
openStashWindow,
|
||||
setFolderParentBranch,
|
||||
} from "@/lib/api"
|
||||
import { openFileDialog, subscribe } from "@/lib/platform"
|
||||
import { RemoteManageDialog } from "@/components/layout/remote-manage-dialog"
|
||||
@@ -130,7 +128,6 @@ export function BranchDropdown() {
|
||||
const branch = activeFolder
|
||||
? (branches.get(activeFolder.id) ?? activeFolder.git_branch ?? null)
|
||||
: null
|
||||
const parentBranch = activeFolder?.parent_branch ?? null
|
||||
|
||||
const [branchList, setBranchList] = useState<GitBranchList>({
|
||||
local: [],
|
||||
@@ -349,15 +346,9 @@ export function BranchDropdown() {
|
||||
await runGitTask(t("tasks.newWorktree", { name }), async () => {
|
||||
await gitWorktreeAdd(folderPath, name, wtPath)
|
||||
await openFolder(wtPath)
|
||||
await setFolderParentBranch(wtPath, branch)
|
||||
})
|
||||
}
|
||||
|
||||
function handleMergeParent() {
|
||||
if (!parentBranch) return
|
||||
setConfirmAction({ type: "merge", branchName: parentBranch })
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
if (!confirmAction) return
|
||||
const { type, branchName } = confirmAction
|
||||
@@ -818,18 +809,6 @@ export function BranchDropdown() {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{parentBranch && (
|
||||
<button
|
||||
className="flex cursor-default select-none items-center gap-1 rounded px-1.5 py-0.5 text-xs text-orange-500 transition-colors hover:bg-accent hover:text-orange-600 dark:text-orange-400 dark:hover:text-orange-300"
|
||||
disabled={loading}
|
||||
onClick={handleMergeParent}
|
||||
title={t("parentBranchHint", { parentBranch })}
|
||||
>
|
||||
<ArrowLeftRight className="h-3 w-3 shrink-0" />
|
||||
<span className="max-w-32 truncate">{parentBranch}</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<AlertDialog
|
||||
open={confirmAction !== null}
|
||||
onOpenChange={(open) => {
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "لا توجد فروع محلية",
|
||||
"remoteBranches": "الفروع البعيدة ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "لا توجد فروع بعيدة",
|
||||
"parentBranchHint": "تم إنشاء الفرع الحالي من {parentBranch}. انقر لدمج {parentBranch} في الفرع الحالي.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "فرع جديد",
|
||||
"newBranchDescription": "إنشاء فرع جديد من الفرع الحالي {branch}",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "Keine lokalen Branches",
|
||||
"remoteBranches": "Remote-Branches ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "Keine Remote-Branches",
|
||||
"parentBranchHint": "Der aktuelle Branch wurde von {parentBranch} erstellt. Klicken, um {parentBranch} in den aktuellen Branch zu mergen.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "Neuer Branch",
|
||||
"newBranchDescription": "Neuen Branch vom aktuellen Branch {branch} erstellen",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "No local branches",
|
||||
"remoteBranches": "Remote branches ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "No remote branches",
|
||||
"parentBranchHint": "Current branch was created from {parentBranch}. Click to merge {parentBranch} into current branch.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "New branch",
|
||||
"newBranchDescription": "Create a new branch from current branch {branch}",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "Sin ramas locales",
|
||||
"remoteBranches": "Ramas remotas ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "Sin ramas remotas",
|
||||
"parentBranchHint": "La rama actual fue creada desde {parentBranch}. Haz clic para fusionar {parentBranch} en la rama actual.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "Nueva rama",
|
||||
"newBranchDescription": "Crear una nueva rama desde la rama actual {branch}",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "Aucune branche locale",
|
||||
"remoteBranches": "Branches distantes ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "Aucune branche distante",
|
||||
"parentBranchHint": "La branche actuelle a été créée depuis {parentBranch}. Cliquez pour fusionner {parentBranch} dans la branche actuelle.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "Nouvelle branche",
|
||||
"newBranchDescription": "Créer une nouvelle branche depuis la branche actuelle {branch}",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "ローカルブランチはありません",
|
||||
"remoteBranches": "リモートブランチ ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "リモートブランチはありません",
|
||||
"parentBranchHint": "現在のブランチは {parentBranch} から作成されました。クリックして {parentBranch} を現在のブランチにマージします。",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "新規ブランチ",
|
||||
"newBranchDescription": "現在のブランチ {branch} から新しいブランチを作成",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "로컬 브랜치가 없습니다",
|
||||
"remoteBranches": "원격 브랜치 ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "원격 브랜치가 없습니다",
|
||||
"parentBranchHint": "현재 브랜치는 {parentBranch}에서 생성되었습니다. 클릭하여 {parentBranch}를 현재 브랜치에 병합하세요.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "새 브랜치",
|
||||
"newBranchDescription": "현재 브랜치 {branch}에서 새 브랜치를 만듭니다",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "Sem branches locais",
|
||||
"remoteBranches": "Branches remotas ({count, plural, one {#} other {#}})",
|
||||
"noRemoteBranches": "Sem branches remotas",
|
||||
"parentBranchHint": "A branch atual foi criada a partir de {parentBranch}. Clique para mesclar {parentBranch} na branch atual.",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "Nova branch",
|
||||
"newBranchDescription": "Criar uma nova branch a partir da branch atual {branch}",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "无本地分支",
|
||||
"remoteBranches": "远程分支 ({count})",
|
||||
"noRemoteBranches": "无远程分支",
|
||||
"parentBranchHint": "当前分支从 {parentBranch} 创建,点击合并 {parentBranch} 到当前分支",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "新建分支",
|
||||
"newBranchDescription": "从当前分支 {branch} 创建新分支",
|
||||
|
||||
@@ -1082,7 +1082,6 @@
|
||||
"noLocalBranches": "無本地分支",
|
||||
"remoteBranches": "遠端分支 ({count})",
|
||||
"noRemoteBranches": "無遠端分支",
|
||||
"parentBranchHint": "目前分支從 {parentBranch} 建立,點擊合併 {parentBranch} 到目前分支",
|
||||
"dialogs": {
|
||||
"newBranchTitle": "新增分支",
|
||||
"newBranchDescription": "從目前分支 {branch} 建立新分支",
|
||||
|
||||
@@ -656,16 +656,6 @@ export async function getFolderConversation(
|
||||
return getTransport().call("get_folder_conversation", { conversationId })
|
||||
}
|
||||
|
||||
export async function setFolderParentBranch(
|
||||
path: string,
|
||||
parentBranch: string | null
|
||||
): Promise<void> {
|
||||
return getTransport().call("set_folder_parent_branch", {
|
||||
path,
|
||||
parentBranch,
|
||||
})
|
||||
}
|
||||
|
||||
export async function removeFolderFromHistory(path: string): Promise<void> {
|
||||
return getTransport().call("remove_folder_from_history", { path })
|
||||
}
|
||||
|
||||
@@ -524,16 +524,6 @@ export async function getFolderConversation(
|
||||
return invoke("get_folder_conversation", { conversationId })
|
||||
}
|
||||
|
||||
export async function setFolderParentBranch(
|
||||
path: string,
|
||||
parentBranch: string | null
|
||||
): Promise<void> {
|
||||
return invoke("set_folder_parent_branch", {
|
||||
path,
|
||||
parentBranch,
|
||||
})
|
||||
}
|
||||
|
||||
export async function removeFolderFromHistory(path: string): Promise<void> {
|
||||
return invoke("remove_folder_from_history", { path })
|
||||
}
|
||||
|
||||
@@ -160,7 +160,6 @@ export interface FolderDetail {
|
||||
name: string
|
||||
path: string
|
||||
git_branch: string | null
|
||||
parent_branch: string | null
|
||||
default_agent_type: AgentType | null
|
||||
last_opened_at: string
|
||||
sort_order: number
|
||||
|
||||
Reference in New Issue
Block a user