Git推送成功后现在会自动关闭推送窗口
This commit is contained in:
@@ -194,6 +194,13 @@ struct GitCommitSucceededEvent {
|
|||||||
committed_files: usize,
|
committed_files: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
struct GitPushSucceededEvent {
|
||||||
|
folder_id: i32,
|
||||||
|
pushed_commits: usize,
|
||||||
|
upstream_set: bool,
|
||||||
|
}
|
||||||
|
|
||||||
struct FileWatchEntry {
|
struct FileWatchEntry {
|
||||||
root_canonical: PathBuf,
|
root_canonical: PathBuf,
|
||||||
root_display: String,
|
root_display: String,
|
||||||
@@ -841,10 +848,11 @@ pub async fn git_fetch(
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn git_push(
|
pub async fn git_push(
|
||||||
|
app: tauri::AppHandle,
|
||||||
|
window: tauri::WebviewWindow,
|
||||||
path: String,
|
path: String,
|
||||||
credentials: Option<GitCredentials>,
|
credentials: Option<GitCredentials>,
|
||||||
db: tauri::State<'_, AppDatabase>,
|
db: tauri::State<'_, AppDatabase>,
|
||||||
app_handle: tauri::AppHandle,
|
|
||||||
) -> Result<GitPushResult, AppCommandError> {
|
) -> Result<GitPushResult, AppCommandError> {
|
||||||
let pushed_commits = estimate_push_commit_count(&path).await;
|
let pushed_commits = estimate_push_commit_count(&path).await;
|
||||||
|
|
||||||
@@ -873,12 +881,12 @@ pub async fn git_push(
|
|||||||
let mut cmd = crate::process::tokio_command("git");
|
let mut cmd = crate::process::tokio_command("git");
|
||||||
cmd.args(["push", "--set-upstream", "origin", &branch])
|
cmd.args(["push", "--set-upstream", "origin", &branch])
|
||||||
.current_dir(&path);
|
.current_dir(&path);
|
||||||
prepare_remote_git_cmd(&mut cmd, &path, credentials.as_ref(), &db, &app_handle).await;
|
prepare_remote_git_cmd(&mut cmd, &path, credentials.as_ref(), &db, &app).await;
|
||||||
cmd.output().await.map_err(AppCommandError::io)?
|
cmd.output().await.map_err(AppCommandError::io)?
|
||||||
} else {
|
} else {
|
||||||
let mut cmd = crate::process::tokio_command("git");
|
let mut cmd = crate::process::tokio_command("git");
|
||||||
cmd.args(["push"]).current_dir(&path);
|
cmd.args(["push"]).current_dir(&path);
|
||||||
prepare_remote_git_cmd(&mut cmd, &path, credentials.as_ref(), &db, &app_handle).await;
|
prepare_remote_git_cmd(&mut cmd, &path, credentials.as_ref(), &db, &app).await;
|
||||||
cmd.output().await.map_err(AppCommandError::io)?
|
cmd.output().await.map_err(AppCommandError::io)?
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -886,9 +894,26 @@ pub async fn git_push(
|
|||||||
return Err(classify_remote_git_error("push", &output.stderr));
|
return Err(classify_remote_git_error("push", &output.stderr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let upstream_set = !has_upstream;
|
||||||
|
|
||||||
|
if let Some(folder_id) = window
|
||||||
|
.label()
|
||||||
|
.strip_prefix("push-")
|
||||||
|
.and_then(|value| value.parse::<i32>().ok())
|
||||||
|
{
|
||||||
|
let _ = app.emit(
|
||||||
|
"folder://git-push-succeeded",
|
||||||
|
GitPushSucceededEvent {
|
||||||
|
folder_id,
|
||||||
|
pushed_commits,
|
||||||
|
upstream_set,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(GitPushResult {
|
Ok(GitPushResult {
|
||||||
pushed_commits,
|
pushed_commits,
|
||||||
upstream_set: !has_upstream,
|
upstream_set,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Suspense, useEffect, useState } from "react"
|
import { Suspense, useCallback, useEffect, useState } from "react"
|
||||||
import { useSearchParams } from "next/navigation"
|
import { useSearchParams } from "next/navigation"
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
|
import { getCurrentWindow } from "@tauri-apps/api/window"
|
||||||
import { Loader2 } from "lucide-react"
|
import { Loader2 } from "lucide-react"
|
||||||
import { PushWorkspace } from "@/components/layout/push-workspace"
|
import { PushWorkspace } from "@/components/layout/push-workspace"
|
||||||
import { AppTitleBar } from "@/components/layout/app-title-bar"
|
import { AppTitleBar } from "@/components/layout/app-title-bar"
|
||||||
@@ -27,6 +28,14 @@ function PushPageInner() {
|
|||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const closeWindow = useCallback(() => {
|
||||||
|
getCurrentWindow()
|
||||||
|
.close()
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("[PushPage] failed to close window:", err)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
const folderId = Number(searchParams.get("folderId") ?? "0")
|
const folderId = Number(searchParams.get("folderId") ?? "0")
|
||||||
const normalizedFolderId = Number.isFinite(folderId) ? folderId : 0
|
const normalizedFolderId = Number.isFinite(folderId) ? folderId : 0
|
||||||
const hasValidFolderId = normalizedFolderId > 0
|
const hasValidFolderId = normalizedFolderId > 0
|
||||||
@@ -89,7 +98,11 @@ function PushPageInner() {
|
|||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
) : folder ? (
|
) : folder ? (
|
||||||
<PushWorkspace folderPath={folder.path} folderName={folder.name} />
|
<PushWorkspace
|
||||||
|
folderPath={folder.path}
|
||||||
|
folderName={folder.name}
|
||||||
|
onPushed={closeWindow}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ interface GitCommitSucceededEventPayload {
|
|||||||
committed_files: number
|
committed_files: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GitPushSucceededEventPayload {
|
||||||
|
folder_id: number
|
||||||
|
pushed_commits: number
|
||||||
|
upstream_set: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export function BranchDropdown({
|
export function BranchDropdown({
|
||||||
branch,
|
branch,
|
||||||
parentBranch,
|
parentBranch,
|
||||||
@@ -187,6 +193,43 @@ export function BranchDropdown({
|
|||||||
}
|
}
|
||||||
}, [folder, onBranchChange, t])
|
}, [folder, onBranchChange, t])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!folder) return
|
||||||
|
|
||||||
|
let unlisten: UnlistenFn | null = null
|
||||||
|
|
||||||
|
listen<GitPushSucceededEventPayload>(
|
||||||
|
"folder://git-push-succeeded",
|
||||||
|
(event) => {
|
||||||
|
if (event.payload.folder_id !== folder.id) return
|
||||||
|
const { pushed_commits, upstream_set } = event.payload
|
||||||
|
let description: string
|
||||||
|
if (upstream_set) {
|
||||||
|
description =
|
||||||
|
pushed_commits === 0
|
||||||
|
? t("toasts.upstreamSet")
|
||||||
|
: t("toasts.upstreamSetAndPushed", { count: pushed_commits })
|
||||||
|
} else if (pushed_commits === 0) {
|
||||||
|
description = t("toasts.noCommitsToPush")
|
||||||
|
} else {
|
||||||
|
description = t("toasts.pushedCommits", { count: pushed_commits })
|
||||||
|
}
|
||||||
|
toast.success(t("toasts.pushCodeCompleted"), { description })
|
||||||
|
onBranchChange()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((fn) => {
|
||||||
|
unlisten = fn
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("[BranchDropdown] failed to listen push event:", err)
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposeTauriListener(unlisten, "BranchDropdown.gitPushSucceeded")
|
||||||
|
}
|
||||||
|
}, [folder, onBranchChange, t])
|
||||||
|
|
||||||
async function runGitTask<T>(
|
async function runGitTask<T>(
|
||||||
label: string,
|
label: string,
|
||||||
action: () => Promise<T>,
|
action: () => Promise<T>,
|
||||||
|
|||||||
@@ -266,9 +266,14 @@ function parseDate(dateStr: string): Date | null {
|
|||||||
interface PushWorkspaceProps {
|
interface PushWorkspaceProps {
|
||||||
folderPath: string
|
folderPath: string
|
||||||
folderName: string
|
folderName: string
|
||||||
|
onPushed?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PushWorkspace({ folderPath, folderName }: PushWorkspaceProps) {
|
export function PushWorkspace({
|
||||||
|
folderPath,
|
||||||
|
folderName,
|
||||||
|
onPushed,
|
||||||
|
}: PushWorkspaceProps) {
|
||||||
const t = useTranslations("Folder.pushWindow")
|
const t = useTranslations("Folder.pushWindow")
|
||||||
const tLog = useTranslations("Folder.gitLogTab")
|
const tLog = useTranslations("Folder.gitLogTab")
|
||||||
const { withCredentialRetry } = useGitCredential()
|
const { withCredentialRetry } = useGitCredential()
|
||||||
@@ -327,30 +332,10 @@ export function PushWorkspace({ folderPath, folderName }: PushWorkspaceProps) {
|
|||||||
async function handlePush() {
|
async function handlePush() {
|
||||||
setPushing(true)
|
setPushing(true)
|
||||||
try {
|
try {
|
||||||
const result = await withCredentialRetry(
|
await withCredentialRetry((creds) => gitPush(folderPath, creds), {
|
||||||
(creds) => gitPush(folderPath, creds),
|
folderPath,
|
||||||
{ folderPath }
|
})
|
||||||
)
|
onPushed?.()
|
||||||
let description: string | undefined
|
|
||||||
if (result.upstream_set) {
|
|
||||||
description =
|
|
||||||
result.pushed_commits === 0
|
|
||||||
? t("toasts.upstreamSet")
|
|
||||||
: t("toasts.upstreamSetAndPushed", {
|
|
||||||
count: result.pushed_commits,
|
|
||||||
})
|
|
||||||
} else if (result.pushed_commits === 0) {
|
|
||||||
description = t("toasts.noCommitsToPush")
|
|
||||||
} else {
|
|
||||||
description = t("toasts.pushedCommits", {
|
|
||||||
count: result.pushed_commits,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
toast.success(t("toasts.pushSuccess"), { description })
|
|
||||||
await loadCommits()
|
|
||||||
setSelectedFile(null)
|
|
||||||
setSelectedCommit(null)
|
|
||||||
setOpenByCommit({})
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.error(t("toasts.pushFailed"), {
|
toast.error(t("toasts.pushFailed"), {
|
||||||
description: toErrorMessage(err),
|
description: toErrorMessage(err),
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "اكتمل التزام الكود",
|
"commitCodeCompleted": "اكتمل التزام الكود",
|
||||||
|
"pushCodeCompleted": "اكتمل دفع الكود",
|
||||||
"committedFiles": "{count, plural, one {# ملف تم الالتزام به} other {# ملفات تم الالتزام بها}}",
|
"committedFiles": "{count, plural, one {# ملف تم الالتزام به} other {# ملفات تم الالتزام بها}}",
|
||||||
"taskCompleted": "اكتمل {label}",
|
"taskCompleted": "اكتمل {label}",
|
||||||
"taskFailed": "فشل {label}",
|
"taskFailed": "فشل {label}",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "Code-Commit abgeschlossen",
|
"commitCodeCompleted": "Code-Commit abgeschlossen",
|
||||||
|
"pushCodeCompleted": "Code-Push abgeschlossen",
|
||||||
"committedFiles": "{count, plural, one {# Datei committet} other {# Dateien committet}}",
|
"committedFiles": "{count, plural, one {# Datei committet} other {# Dateien committet}}",
|
||||||
"taskCompleted": "{label} abgeschlossen",
|
"taskCompleted": "{label} abgeschlossen",
|
||||||
"taskFailed": "{label} fehlgeschlagen",
|
"taskFailed": "{label} fehlgeschlagen",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "Code commit completed",
|
"commitCodeCompleted": "Code commit completed",
|
||||||
|
"pushCodeCompleted": "Code push completed",
|
||||||
"committedFiles": "Committed {count, plural, one {# file} other {# files}}",
|
"committedFiles": "Committed {count, plural, one {# file} other {# files}}",
|
||||||
"taskCompleted": "{label} completed",
|
"taskCompleted": "{label} completed",
|
||||||
"taskFailed": "{label} failed",
|
"taskFailed": "{label} failed",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "Commit de código completado",
|
"commitCodeCompleted": "Commit de código completado",
|
||||||
|
"pushCodeCompleted": "Push de código completado",
|
||||||
"committedFiles": "{count, plural, one {# archivo confirmado} other {# archivos confirmados}}",
|
"committedFiles": "{count, plural, one {# archivo confirmado} other {# archivos confirmados}}",
|
||||||
"taskCompleted": "{label} completado",
|
"taskCompleted": "{label} completado",
|
||||||
"taskFailed": "{label} falló",
|
"taskFailed": "{label} falló",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "Commit de code terminé",
|
"commitCodeCompleted": "Commit de code terminé",
|
||||||
|
"pushCodeCompleted": "Push de code terminé",
|
||||||
"committedFiles": "{count, plural, one {# fichier commit} other {# fichiers commit}}",
|
"committedFiles": "{count, plural, one {# fichier commit} other {# fichiers commit}}",
|
||||||
"taskCompleted": "{label} terminé",
|
"taskCompleted": "{label} terminé",
|
||||||
"taskFailed": "{label} échoué",
|
"taskFailed": "{label} échoué",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "コードコミットが完了しました",
|
"commitCodeCompleted": "コードコミットが完了しました",
|
||||||
|
"pushCodeCompleted": "コードプッシュが完了しました",
|
||||||
"committedFiles": "{count, plural, one {# 個のファイルをコミット} other {# 個のファイルをコミット}}",
|
"committedFiles": "{count, plural, one {# 個のファイルをコミット} other {# 個のファイルをコミット}}",
|
||||||
"taskCompleted": "{label} が完了しました",
|
"taskCompleted": "{label} が完了しました",
|
||||||
"taskFailed": "{label} が失敗しました",
|
"taskFailed": "{label} が失敗しました",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "코드 커밋이 완료되었습니다",
|
"commitCodeCompleted": "코드 커밋이 완료되었습니다",
|
||||||
|
"pushCodeCompleted": "코드 푸시가 완료되었습니다",
|
||||||
"committedFiles": "{count, plural, one {#개 파일 커밋됨} other {#개 파일 커밋됨}}",
|
"committedFiles": "{count, plural, one {#개 파일 커밋됨} other {#개 파일 커밋됨}}",
|
||||||
"taskCompleted": "{label} 완료",
|
"taskCompleted": "{label} 완료",
|
||||||
"taskFailed": "{label} 실패",
|
"taskFailed": "{label} 실패",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "Commit de código concluído",
|
"commitCodeCompleted": "Commit de código concluído",
|
||||||
|
"pushCodeCompleted": "Push de código concluído",
|
||||||
"committedFiles": "{count, plural, one {# arquivo commitado} other {# arquivos commitados}}",
|
"committedFiles": "{count, plural, one {# arquivo commitado} other {# arquivos commitados}}",
|
||||||
"taskCompleted": "{label} concluído",
|
"taskCompleted": "{label} concluído",
|
||||||
"taskFailed": "{label} falhou",
|
"taskFailed": "{label} falhou",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "提交代码完成",
|
"commitCodeCompleted": "提交代码完成",
|
||||||
|
"pushCodeCompleted": "推送代码完成",
|
||||||
"committedFiles": "已提交 {count} 个文件",
|
"committedFiles": "已提交 {count} 个文件",
|
||||||
"taskCompleted": "{label} 完成",
|
"taskCompleted": "{label} 完成",
|
||||||
"taskFailed": "{label} 失败",
|
"taskFailed": "{label} 失败",
|
||||||
|
|||||||
@@ -875,6 +875,7 @@
|
|||||||
"branchDropdown": {
|
"branchDropdown": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"commitCodeCompleted": "提交程式碼完成",
|
"commitCodeCompleted": "提交程式碼完成",
|
||||||
|
"pushCodeCompleted": "推送程式碼完成",
|
||||||
"committedFiles": "已提交 {count} 個檔案",
|
"committedFiles": "已提交 {count} 個檔案",
|
||||||
"taskCompleted": "{label} 完成",
|
"taskCompleted": "{label} 完成",
|
||||||
"taskFailed": "{label} 失敗",
|
"taskFailed": "{label} 失敗",
|
||||||
|
|||||||
Reference in New Issue
Block a user