feat: add source download functionality to builds and profiles

This commit is contained in:
Ben Allfree
2025-11-26 10:10:03 -08:00
parent 306be69033
commit 828782bf22
3 changed files with 180 additions and 44 deletions
+31
View File
@@ -18,7 +18,13 @@ export default function BuildProgress() {
const generateDownloadUrl = useMutation(
api.builds.generateAnonymousDownloadUrl
)
const generateSourceDownloadUrl = useMutation(
api.builds.generateAnonymousSourceDownloadUrl
)
const [downloadError, setDownloadError] = useState<string | null>(null)
const [sourceDownloadError, setSourceDownloadError] = useState<string | null>(
null
)
if (!buildHash) {
return (
@@ -87,6 +93,21 @@ export default function BuildProgress() {
}
}
const handleSourceDownload = async () => {
setSourceDownloadError(null)
try {
const url = await generateSourceDownloadUrl({
build: pick(build, Object.keys(buildFields) as (keyof BuildFields)[]),
slug: `quick-build`,
})
window.location.href = url
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
setSourceDownloadError('Failed to generate source download link.')
console.error('Source download error', message)
}
}
const getStatusIcon = () => {
if (status === 'success') {
return <CheckCircle className="w-6 h-6 text-green-500" />
@@ -176,6 +197,16 @@ export default function BuildProgress() {
{downloadError && (
<p className="text-sm text-red-400">{downloadError}</p>
)}
<Button
onClick={handleSourceDownload}
className="w-full bg-slate-700 hover:bg-slate-600"
variant="outline"
>
Download source
</Button>
{sourceDownloadError && (
<p className="text-sm text-red-400">{sourceDownloadError}</p>
)}
</div>
)}
+25 -1
View File
@@ -30,6 +30,9 @@ export default function ProfileFlash() {
id ? { id: id as Id<'profiles'> } : 'skip'
)
const generateDownloadUrl = useMutation(api.builds.generateDownloadUrl)
const generateSourceDownloadUrl = useMutation(
api.builds.generateSourceDownloadUrl
)
useEffect(() => {
if (id && target && profile) {
@@ -104,6 +107,20 @@ export default function ProfileFlash() {
}
}
const handleSourceDownload = async () => {
if (!id) return
try {
const url = await generateSourceDownloadUrl({
buildId: build._id,
profileId: id as Id<'profiles'>,
})
window.location.href = url
} catch (error) {
console.error('Failed to generate source download URL', error)
}
}
const getStatusColor = (status: string) => {
if (status === 'success') return 'text-green-400'
if (status === 'failure') return 'text-red-400'
@@ -216,13 +233,20 @@ export default function ProfileFlash() {
</div>
{build.status === 'success' && build.artifactPath && (
<div>
<div className="space-y-2">
<Button
onClick={handleDownload}
className="bg-cyan-600 hover:bg-cyan-700 w-full"
>
Download Firmware
</Button>
<Button
onClick={handleSourceDownload}
className="bg-slate-700 hover:bg-slate-600 w-full"
variant="outline"
>
Download Source
</Button>
</div>
)}
</div>