Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
f25f6c76
Unverified
提交
f25f6c76
authored
6月 17, 2025
作者:
Will Chen
提交者:
GitHub
6月 17, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
debounce GitHub repo name check & show create repo error details (#418)
Fixes #366
上级
d6d6918d
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
80 行增加
和
24 行删除
+80
-24
GitHubConnector.tsx
src/components/GitHubConnector.tsx
+42
-22
github_handlers.ts
src/ipc/handlers/github_handlers.ts
+38
-2
没有找到文件。
src/components/GitHubConnector.tsx
浏览文件 @
f25f6c76
import
{
useState
,
useEffect
}
from
"react"
;
import
{
useState
,
useEffect
,
useCallback
,
useRef
}
from
"react"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
Github
,
Clipboard
,
Check
}
from
"lucide-react"
;
import
{
IpcClient
}
from
"@/ipc/ipc_client"
;
...
...
@@ -126,26 +126,45 @@ export function GitHubConnector({ appId, folderName }: GitHubConnectorProps) {
// TODO: After device flow, fetch and store the GitHub username/org in settings for use here
const
githubOrg
=
""
;
// Use empty string for now (GitHub API will default to the authenticated user)
const
handleRepoNameBlur
=
async
()
=>
{
setRepoCheckError
(
null
);
setRepoAvailable
(
null
);
if
(
!
repoName
)
return
;
setIsCheckingRepo
(
true
);
try
{
const
result
=
await
IpcClient
.
getInstance
().
checkGithubRepoAvailable
(
githubOrg
,
repoName
,
);
setRepoAvailable
(
result
.
available
);
if
(
!
result
.
available
)
{
setRepoCheckError
(
result
.
error
||
"Repository name is not available."
);
const
debounceTimeoutRef
=
useRef
<
NodeJS
.
Timeout
|
null
>
(
null
);
const
checkRepoAvailability
=
useCallback
(
async
(
name
:
string
)
=>
{
setRepoCheckError
(
null
);
setRepoAvailable
(
null
);
if
(
!
name
)
return
;
setIsCheckingRepo
(
true
);
try
{
const
result
=
await
IpcClient
.
getInstance
().
checkGithubRepoAvailable
(
githubOrg
,
name
,
);
setRepoAvailable
(
result
.
available
);
if
(
!
result
.
available
)
{
setRepoCheckError
(
result
.
error
||
"Repository name is not available."
,
);
}
}
catch
(
err
:
any
)
{
setRepoCheckError
(
err
.
message
||
"Failed to check repo availability."
);
}
finally
{
setIsCheckingRepo
(
false
);
}
}
catch
(
err
:
any
)
{
setRepoCheckError
(
err
.
message
||
"Failed to check repo availability."
);
}
finally
{
setIsCheckingRepo
(
false
);
}
};
},
[
githubOrg
],
);
const
debouncedCheckRepoAvailability
=
useCallback
(
(
name
:
string
)
=>
{
if
(
debounceTimeoutRef
.
current
)
{
clearTimeout
(
debounceTimeoutRef
.
current
);
}
debounceTimeoutRef
.
current
=
setTimeout
(()
=>
{
checkRepoAvailability
(
name
);
},
500
);
},
[
checkRepoAvailability
],
);
const
handleCreateRepo
=
async
(
e
:
React
.
FormEvent
)
=>
{
e
.
preventDefault
();
...
...
@@ -401,11 +420,12 @@ export function GitHubConnector({ appId, folderName }: GitHubConnectorProps) {
className=
"w-full border rounded px-2 py-1"
value=
{
repoName
}
onChange=
{
(
e
)
=>
{
setRepoName
(
e
.
target
.
value
);
const
newValue
=
e
.
target
.
value
;
setRepoName
(
newValue
);
setRepoAvailable
(
null
);
setRepoCheckError
(
null
);
debouncedCheckRepoAvailability
(
newValue
);
}
}
onBlur=
{
handleRepoNameBlur
}
disabled=
{
isCreatingRepo
}
/>
{
isCheckingRepo
&&
(
...
...
src/ipc/handlers/github_handlers.ts
浏览文件 @
f25f6c76
...
...
@@ -356,8 +356,44 @@ async function handleCreateRepo(
}),
});
if
(
!
res
.
ok
)
{
const
data
=
await
res
.
json
();
throw
new
Error
(
data
.
message
||
"Failed to create repo"
);
let
errorMessage
=
`Failed to create repository (
${
res
.
status
}
${
res
.
statusText
}
)`
;
try
{
const
data
=
await
res
.
json
();
logger
.
error
(
"GitHub API error when creating repo:"
,
{
status
:
res
.
status
,
statusText
:
res
.
statusText
,
response
:
data
,
});
// Handle specific GitHub API error cases
if
(
data
.
message
)
{
errorMessage
=
data
.
message
;
}
// Handle validation errors with more details
if
(
data
.
errors
&&
Array
.
isArray
(
data
.
errors
))
{
const
errorDetails
=
data
.
errors
.
map
((
err
:
any
)
=>
{
if
(
typeof
err
===
"string"
)
return
err
;
if
(
err
.
message
)
return
err
.
message
;
if
(
err
.
code
)
return
`
${
err
.
field
||
"field"
}
:
${
err
.
code
}
`
;
return
JSON
.
stringify
(
err
);
})
.
join
(
", "
);
errorMessage
=
`
${
data
.
message
||
"Repository creation failed"
}
:
${
errorDetails
}
`
;
}
}
catch
(
jsonError
)
{
// If response is not JSON, fall back to status text
logger
.
error
(
"Failed to parse GitHub API error response:"
,
{
status
:
res
.
status
,
statusText
:
res
.
statusText
,
jsonError
:
jsonError
instanceof
Error
?
jsonError
.
message
:
String
(
jsonError
),
});
errorMessage
=
`GitHub API error:
${
res
.
status
}
${
res
.
statusText
}
`
;
}
throw
new
Error
(
errorMessage
);
}
// Store org and repo in the app's DB row (apps table)
await
updateAppGithubRepo
(
appId
,
owner
,
repo
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论