Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
b6eeaab1
Unverified
提交
b6eeaab1
authored
5月 09, 2025
作者:
Will Chen
提交者:
GitHub
5月 09, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
migrate current branch to query pattern (#116)
上级
7839d6bd
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
65 行增加
和
77 行删除
+65
-77
ChatHeader.tsx
src/components/chat/ChatHeader.tsx
+29
-48
useCurrentBranch.ts
src/hooks/useCurrentBranch.ts
+30
-0
version_handlers.ts
src/ipc/handlers/version_handlers.ts
+4
-16
ipc_client.ts
src/ipc/ipc_client.ts
+1
-2
ipc_types.ts
src/ipc/ipc_types.ts
+1
-11
没有找到文件。
src/components/chat/ChatHeader.tsx
浏览文件 @
b6eeaab1
...
...
@@ -22,8 +22,8 @@ import { selectedChatIdAtom } from "@/atoms/chatAtoms";
import
{
useChats
}
from
"@/hooks/useChats"
;
import
{
showError
}
from
"@/lib/toast"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
BranchResult
}
from
"@/ipc/ipc_types"
;
import
{
useStreamChat
}
from
"@/hooks/useStreamChat"
;
import
{
useCurrentBranch
}
from
"@/hooks/useCurrentBranch"
;
interface
ChatHeaderProps
{
isPreviewOpen
:
boolean
;
...
...
@@ -37,55 +37,35 @@ export function ChatHeader({
onVersionClick
,
}:
ChatHeaderProps
)
{
const
appId
=
useAtomValue
(
selectedAppIdAtom
);
const
{
versions
,
loading
}
=
useVersions
(
appId
);
const
{
versions
,
loading
:
versionsLoading
}
=
useVersions
(
appId
);
const
{
navigate
}
=
useRouter
();
const
[
selectedChatId
,
setSelectedChatId
]
=
useAtom
(
selectedChatIdAtom
);
const
{
refreshChats
}
=
useChats
(
appId
);
const
[
branchInfo
,
setBranchInfo
]
=
useState
<
BranchResult
|
null
>
(
null
);
const
[
checkingOutMain
,
setCheckingOutMain
]
=
useState
(
false
);
const
{
isStreaming
}
=
useStreamChat
();
// Fetch the current branch when appId changes
useEffect
(()
=>
{
if
(
!
appId
)
return
;
const
fetchBranch
=
async
()
=>
{
try
{
const
result
=
await
IpcClient
.
getInstance
().
getCurrentBranch
(
appId
);
if
(
result
.
success
)
{
setBranchInfo
(
result
);
}
else
{
showError
(
"Failed to get current branch: "
+
result
.
errorMessage
);
}
}
catch
(
error
)
{
showError
(
`Failed to get current branch:
${
error
}
`
);
}
};
const
{
branchInfo
,
isLoading
:
branchInfoLoading
,
refetchBranchInfo
,
}
=
useCurrentBranch
(
appId
);
fetchBranch
();
// The use of selectedChatId and isStreaming is a hack to ensure that
// the branch info is relatively up to date.
},
[
appId
,
selectedChatId
,
isStreaming
]);
useEffect
(()
=>
{
if
(
appId
)
{
refetchBranchInfo
();
}
},
[
appId
,
selectedChatId
,
isStreaming
,
refetchBranchInfo
]);
const
handleCheckoutMainBranch
=
async
()
=>
{
if
(
!
appId
)
return
;
try
{
setCheckingOutMain
(
true
);
// Find the latest commit on main branch
// For simplicity, we'll just checkout to "main" directly
await
IpcClient
.
getInstance
().
checkoutVersion
({
appId
,
versionId
:
"main"
,
});
// Refresh branch info
const
result
=
await
IpcClient
.
getInstance
().
getCurrentBranch
(
appId
);
if
(
result
.
success
)
{
setBranchInfo
(
result
);
}
else
{
showError
(
result
.
errorMessage
);
}
await
refetchBranchInfo
();
}
catch
(
error
)
{
showError
(
`Failed to checkout main branch:
${
error
}
`
);
}
finally
{
...
...
@@ -94,36 +74,29 @@ export function ChatHeader({
};
const
handleNewChat
=
async
()
=>
{
// Only create a new chat if an app is selected
if
(
appId
)
{
try
{
// Create a new chat with an empty title for now
const
chatId
=
await
IpcClient
.
getInstance
().
createChat
(
appId
);
// Navigate to the new chat
setSelectedChatId
(
chatId
);
navigate
({
to
:
"/chat"
,
search
:
{
id
:
chatId
},
});
// Refresh the chat list
await
refreshChats
();
}
catch
(
error
)
{
// DO A TOAST
showError
(
`Failed to create new chat:
${(
error
as
any
).
toString
()}
`
);
}
}
else
{
// If no app is selected, navigate to home page
navigate
({
to
:
"/"
});
}
};
// TODO: KEEP UP TO DATE WITH app_handlers.ts
// REMINDER: KEEP UP TO DATE WITH app_handlers.ts
const
versionPostfix
=
versions
.
length
===
10
_000
?
`+`
:
""
;
// Check if we're not on the main branch
const
isNotMainBranch
=
branchInfo
?.
success
&&
branchInfo
.
data
.
branch
!==
"main"
;
const
isNotMainBranch
=
branchInfo
&&
branchInfo
.
branch
!==
"main"
;
const
currentBranchName
=
branchInfo
?.
branch
;
return
(
<
div
className=
"flex flex-col w-full @container"
>
...
...
@@ -132,7 +105,7 @@ export function ChatHeader({
<
div
className=
"flex items-center gap-2 text-sm"
>
<
GitBranch
size=
{
16
}
/>
<
span
>
{
branchInfo
?.
data
.
branch
===
"<no-branch>"
&&
(
{
currentBranchName
===
"<no-branch>"
&&
(
<>
<
TooltipProvider
>
<
Tooltip
>
...
...
@@ -153,13 +126,19 @@ export function ChatHeader({
</
TooltipProvider
>
</>
)
}
{
currentBranchName
&&
currentBranchName
!==
"<no-branch>"
&&
(
<
span
>
You are on branch:
<
strong
>
{
currentBranchName
}
</
strong
>
.
</
span
>
)
}
{
branchInfoLoading
&&
<
span
>
Checking branch...
</
span
>
}
</
span
>
</
div
>
<
Button
variant=
"outline"
size=
"sm"
onClick=
{
handleCheckoutMainBranch
}
disabled=
{
checkingOutMain
}
disabled=
{
checkingOutMain
||
branchInfoLoading
}
>
{
checkingOutMain
?
"Checking out..."
:
"Switch to main branch"
}
</
Button
>
...
...
@@ -182,7 +161,9 @@ export function ChatHeader({
className=
"hidden @6xs:flex cursor-pointer items-center gap-1 text-sm px-2 py-1 rounded-md"
>
<
History
size=
{
16
}
/>
{
loading
?
"..."
:
`Version ${versions.length}${versionPostfix}`
}
{
versionsLoading
?
"..."
:
`Version ${versions.length}${versionPostfix}`
}
</
Button
>
</
div
>
...
...
src/hooks/useCurrentBranch.ts
0 → 100644
浏览文件 @
b6eeaab1
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
import
{
useQuery
}
from
"@tanstack/react-query"
;
import
type
{
BranchResult
}
from
"@/ipc/ipc_types"
;
export
function
useCurrentBranch
(
appId
:
number
|
null
)
{
const
{
data
:
branchInfo
,
isLoading
,
refetch
:
refetchBranchInfo
,
}
=
useQuery
<
BranchResult
,
Error
>
({
queryKey
:
[
"currentBranch"
,
appId
],
queryFn
:
async
():
Promise
<
BranchResult
>
=>
{
if
(
appId
===
null
)
{
// This case should ideally be handled by the `enabled` option
// but as a safeguard, and to ensure queryFn always has a valid appId if called.
throw
new
Error
(
"appId is null, cannot fetch current branch."
);
}
const
ipcClient
=
IpcClient
.
getInstance
();
return
ipcClient
.
getCurrentBranch
(
appId
);
},
enabled
:
appId
!==
null
,
meta
:
{
showErrorToast
:
false
},
});
return
{
branchInfo
,
isLoading
,
refetchBranchInfo
,
};
}
src/ipc/handlers/version_handlers.ts
浏览文件 @
b6eeaab1
...
...
@@ -59,20 +59,14 @@ export function registerVersionHandlers() {
});
if
(
!
app
)
{
return
{
success
:
false
,
errorMessage
:
"App not found"
,
};
throw
new
Error
(
"App not found"
);
}
const
appPath
=
getDyadAppPath
(
app
.
path
);
// Return appropriate result if the app is not a git repo
if
(
!
fs
.
existsSync
(
path
.
join
(
appPath
,
".git"
)))
{
return
{
success
:
false
,
errorMessage
:
"Not a git repository"
,
};
throw
new
Error
(
"Not a git repository"
);
}
try
{
...
...
@@ -83,17 +77,11 @@ export function registerVersionHandlers() {
});
return
{
success
:
true
,
data
:
{
branch
:
currentBranch
||
"<no-branch>"
,
},
branch
:
currentBranch
||
"<no-branch>"
,
};
}
catch
(
error
:
any
)
{
logger
.
error
(
`Error getting current branch for app
${
appId
}
:`
,
error
);
return
{
success
:
false
,
errorMessage
:
`Failed to get current branch:
${
error
.
message
}
`
,
};
throw
new
Error
(
`Failed to get current branch:
${
error
.
message
}
`
);
}
},
);
...
...
src/ipc/ipc_client.ts
浏览文件 @
b6eeaab1
...
...
@@ -493,10 +493,9 @@ export class IpcClient {
// Get the current branch of an app
public
async
getCurrentBranch
(
appId
:
number
):
Promise
<
BranchResult
>
{
const
result
=
await
this
.
ipcRenderer
.
invoke
(
"get-current-branch"
,
{
return
this
.
ipcRenderer
.
invoke
(
"get-current-branch"
,
{
appId
,
});
return
result
;
}
// Get user settings
...
...
src/ipc/ipc_types.ts
浏览文件 @
b6eeaab1
...
...
@@ -76,17 +76,7 @@ export interface Version {
timestamp
:
number
;
}
export
type
Result
<
T
>
=
|
{
success
:
true
;
data
:
T
;
}
|
{
success
:
false
;
errorMessage
:
string
;
};
export
type
BranchResult
=
Result
<
{
branch
:
string
}
>
;
export
type
BranchResult
=
{
branch
:
string
};
export
interface
SandboxConfig
{
files
:
Record
<
string
,
string
>
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论