release: 0.1.10 — balance widget actually shows + avatar ring
Balance pill was rendering nothing for admin/root accounts because mcp-server's §4 returns HEICODE_USER_NOT_FOUND for users that never came through from-agnet onboarding. Fall back to Heicode NewAPI's own /api/user/self when that happens; reshape into the same envelope so the UI is path-agnostic. New balanceStore (zustand) — single polling loop, BalanceBar + avatar ring share it. AppShell starts it once auth bootstraps. BalanceBar now shows a "loading…" placeholder on first fetch so the widget is visible from frame one. SidebarUserCard avatar wears an SVG ring whose arc length tracks remaining/(remaining+used) and color hits the same green→amber→red thresholds as the bar. Manager: /desktop-client drops the manifest-notes wall of text, the old HEICODE_DESKTOP_FILE_* subtitle goes away, and a Mac fallback entry is always spliced in when the live manifest is Win-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -124,6 +124,19 @@ func filenameFromURL(rawURL string) string {
|
||||
return rawURL
|
||||
}
|
||||
|
||||
// Fallback URLs for platforms the live manifest doesn't currently carry.
|
||||
// We ship Win and Mac on different cadences (Mac builds depend on physical
|
||||
// hardware access). When a release goes out Win-only, the manifest only
|
||||
// names windows-x86_64 — but the Manager download page should still show
|
||||
// the latest Mac binary that ever shipped to blob, so Mac users aren't
|
||||
// stranded.
|
||||
//
|
||||
// Update these constants whenever a NEW Mac binary is uploaded to blob.
|
||||
const (
|
||||
fallbackMacArmVersion = "0.1.5"
|
||||
fallbackMacArmURL = "https://heicodeblob.blob.core.windows.net/msi/desktop/0.1.5/HeiCode.app.tar.gz"
|
||||
)
|
||||
|
||||
// GetDesktopDownloads returns the latest released desktop client metadata
|
||||
// (per platform) for authenticated users.
|
||||
func GetDesktopDownloads(c *gin.Context) {
|
||||
@@ -136,7 +149,7 @@ func GetDesktopDownloads(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
items := make([]desktopDownloadItem, 0, len(manifest.Platforms))
|
||||
items := make([]desktopDownloadItem, 0, 3)
|
||||
add := func(id, label, key string) {
|
||||
p, ok := manifest.Platforms[key]
|
||||
if !ok || strings.TrimSpace(p.URL) == "" {
|
||||
@@ -153,12 +166,26 @@ func GetDesktopDownloads(c *gin.Context) {
|
||||
add("macos_arm64", "macOS (Apple silicon)", "darwin-aarch64")
|
||||
add("macos_x64", "macOS (Intel)", "darwin-x86_64")
|
||||
|
||||
// If the live manifest doesn't carry a Mac arm64 entry (Win-only
|
||||
// release), splice in the last known Mac binary so the download
|
||||
// page never goes blank on Mac users.
|
||||
if _, hasMac := manifest.Platforms["darwin-aarch64"]; !hasMac {
|
||||
items = append(items, desktopDownloadItem{
|
||||
ID: "macos_arm64",
|
||||
Label: "macOS (Apple silicon, " + fallbackMacArmVersion + ")",
|
||||
Filename: filenameFromURL(fallbackMacArmURL),
|
||||
DownloadURL: fallbackMacArmURL,
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
// `Notes` deliberately dropped here — the download page is for the
|
||||
// download links + version number only; users don't want a wall of
|
||||
// release-note text below it.
|
||||
"data": desktopDownloadsPayload{
|
||||
Version: manifest.Version,
|
||||
Notes: manifest.Notes,
|
||||
Items: items,
|
||||
},
|
||||
})
|
||||
|
||||
+1
-6
@@ -41,7 +41,7 @@ export function DesktopClientDownloadPage() {
|
||||
</SectionPageLayout.Title>
|
||||
<SectionPageLayout.Description>
|
||||
{t(
|
||||
'Installers are served only after you sign in. Place files on the server and set HEICODE_DESKTOP_FILE_* environment variables.',
|
||||
'Sign in required to access the installers.',
|
||||
)}
|
||||
</SectionPageLayout.Description>
|
||||
<SectionPageLayout.Content>
|
||||
@@ -58,11 +58,6 @@ export function DesktopClientDownloadPage() {
|
||||
<p className='text-muted-foreground text-sm'>
|
||||
{t('Version: {{version}}', { version: payload.version })}
|
||||
</p>
|
||||
{payload.notes ? (
|
||||
<p className='text-muted-foreground whitespace-pre-wrap text-sm'>
|
||||
{payload.notes}
|
||||
</p>
|
||||
) : null}
|
||||
<ul className='flex flex-col gap-3'>
|
||||
{payload.items.map((item) => (
|
||||
<li
|
||||
|
||||
Reference in New Issue
Block a user