release: 0.1.9 — balance progress bar + roll up of 0.1.6-0.1.8
Today's 0.1.6/0.1.7/0.1.8 all built but never shipped a manifest
(some were superseded mid-iteration; 0.1.8 had Win binary on blob
but Mac wasn't ready). 0.1.9 ships the full stack as one release:
- BalanceBar under the composer now has a real progress bar (was
text only). Fill = remaining/(remaining+used); color shifts
green → amber → red below 30%/10%.
- (from 0.1.8) AskUserQuestion early-return moved below all hooks
so the render order is stable across input mutations.
- (from 0.1.8) chatStore content_delta throttle is now per-session
(Map<sessionId, {pending, timer}>); no more cross-tab text bleed.
- (from 0.1.8) endpoints array trimmed to blob-only — SWA URL gone
so a fallback failure no longer flashes a third-party domain.
- (from 0.1.7) new app icon — already on disk in icons/ + public/.
- (from 0.1.6) Manager desktop_download.go reads blob manifest so
the /desktop-client page tracks releases without env wrangling.
- Build pipeline: `tauri build --bundles nsis` is the release path
(skips MSI/WiX, ~2-3 min/build saved). sccache wired into
~/.cargo/config.toml; next build is the first with warm cache.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "heicode-desktop",
|
"name": "heicode-desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.8",
|
"version": "0.1.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Generated
+1
-1
@@ -1525,7 +1525,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heicode-desktop"
|
name = "heicode-desktop"
|
||||||
version = "0.1.6"
|
version = "0.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"portable-pty",
|
"portable-pty",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "heicode-desktop"
|
name = "heicode-desktop"
|
||||||
version = "0.1.8"
|
version = "0.1.9"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-schema-v2.json",
|
"$schema": "https://raw.githubusercontent.com/nicegui/nicegui/main/nicegui/static/tauri-schema-v2.json",
|
||||||
"productName": "HeiCode",
|
"productName": "HeiCode",
|
||||||
"version": "0.1.8",
|
"version": "0.1.9",
|
||||||
"identifier": "com.heicode.desktop",
|
"identifier": "com.heicode.desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../dist",
|
"frontendDist": "../dist",
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
"updater": {
|
"updater": {
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEI3Q0FBOUQ2MTgwRkM4NjQKUldSa3lBOFkxcW5LdDhLUFZnNUlEdmllY0ZudjFhb2VXTUpSWmpkUmM1cjdoNDFwRW1MZTN5Yi8K",
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEI3Q0FBOUQ2MTgwRkM4NjQKUldSa3lBOFkxcW5LdDhLUFZnNUlEdmllY0ZudjFhb2VXTUpSWmpkUmM1cjdoNDFwRW1MZTN5Yi8K",
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
"https://heicodeblob.blob.core.windows.net/msi/updater/latest.json",
|
"https://heicodeblob.blob.core.windows.net/msi/updater/latest.json"
|
||||||
"https://ashy-dune-0e22d7b00.7.azurestaticapps.net/updater/latest.json"
|
|
||||||
],
|
],
|
||||||
"windows": {
|
"windows": {
|
||||||
"installMode": "passive"
|
"installMode": "passive"
|
||||||
|
|||||||
@@ -11,14 +11,33 @@ const POLL_MS = 60_000
|
|||||||
|
|
||||||
function formatUsd(quota: number): string {
|
function formatUsd(quota: number): string {
|
||||||
const usd = quota / QUOTA_PER_USD
|
const usd = quota / QUOTA_PER_USD
|
||||||
// Show 2 decimals up to $100, 4 decimals below to make pennies legible.
|
|
||||||
return `$${usd >= 100 ? usd.toFixed(2) : usd >= 1 ? usd.toFixed(2) : usd.toFixed(4)}`
|
return `$${usd >= 100 ? usd.toFixed(2) : usd >= 1 ? usd.toFixed(2) : usd.toFixed(4)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compact balance pill that lives right under the chat composer. Renders
|
* Bar fill semantics: `remaining / (remaining + used)` — how much of the
|
||||||
* nothing until we have a positive answer — silent on logged-out / failed
|
* lifetime-funded total is still in the wallet. 100% = brand-new account
|
||||||
* states so the layout doesn't flash an error strip.
|
* that hasn't spent anything; 0% = quota fully consumed.
|
||||||
|
*
|
||||||
|
* Color thresholds:
|
||||||
|
* ≥ 30% → green (healthy)
|
||||||
|
* ≥ 10% → amber (getting low)
|
||||||
|
* < 10% → red (top up soon)
|
||||||
|
*/
|
||||||
|
function healthOf(remainingFraction: number): { color: string; bg: string } {
|
||||||
|
if (remainingFraction >= 0.3) {
|
||||||
|
return { color: 'var(--color-success)', bg: 'rgba(34,197,94,0.16)' }
|
||||||
|
}
|
||||||
|
if (remainingFraction >= 0.1) {
|
||||||
|
return { color: 'var(--color-warning)', bg: 'rgba(245,158,11,0.18)' }
|
||||||
|
}
|
||||||
|
return { color: 'var(--color-error)', bg: 'rgba(239,68,68,0.18)' }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compact balance pill with progress bar that lives right under the chat
|
||||||
|
* composer. Renders nothing until we have a positive answer — silent on
|
||||||
|
* logged-out / failed states so the layout doesn't flash an error strip.
|
||||||
*/
|
*/
|
||||||
export function BalanceBar() {
|
export function BalanceBar() {
|
||||||
const [balance, setBalance] = useState<HeicodeBalance | null>(null)
|
const [balance, setBalance] = useState<HeicodeBalance | null>(null)
|
||||||
@@ -41,27 +60,49 @@ export function BalanceBar() {
|
|||||||
|
|
||||||
if (!balance) return null
|
if (!balance) return null
|
||||||
|
|
||||||
|
const total = balance.quota + balance.usedQuota
|
||||||
|
const remainingFraction = total > 0 ? balance.quota / total : 1
|
||||||
|
const fillPercent = Math.max(0, Math.min(1, remainingFraction)) * 100
|
||||||
|
const health = healthOf(remainingFraction)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto mb-2 mt-1 flex w-fit max-w-full items-center gap-2 rounded-full border border-[var(--color-border)]/40 bg-[var(--color-surface-container-low)]/60 px-3 py-1 text-[11px] text-[var(--color-text-secondary)]">
|
<div
|
||||||
<span className="material-symbols-outlined text-[14px] text-[var(--color-brand)]">
|
className="mx-auto mb-2 mt-1 w-fit min-w-[280px] max-w-full rounded-[14px] border border-[var(--color-border)]/40 bg-[var(--color-surface-container-low)]/70 px-3 py-1.5 backdrop-blur-sm"
|
||||||
|
title={t('balance.tooltip')}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2 text-[11px] text-[var(--color-text-secondary)]">
|
||||||
|
<span
|
||||||
|
className="material-symbols-outlined text-[14px]"
|
||||||
|
style={{ color: health.color }}
|
||||||
|
>
|
||||||
account_balance_wallet
|
account_balance_wallet
|
||||||
</span>
|
</span>
|
||||||
<span className="font-medium text-[var(--color-text-primary)]">
|
<span className="font-semibold text-[var(--color-text-primary)] tabular-nums">
|
||||||
{formatUsd(balance.quota)}
|
{formatUsd(balance.quota)}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-[var(--color-text-tertiary)]">{t('balance.remaining')}</span>
|
<span className="text-[var(--color-text-tertiary)]">{t('balance.remaining')}</span>
|
||||||
<span className="h-3 w-px bg-[var(--color-border)]/70" aria-hidden />
|
<span className="ml-auto tabular-nums text-[var(--color-text-tertiary)]">
|
||||||
<span className="tabular-nums text-[var(--color-text-tertiary)]">
|
|
||||||
{t('balance.usedPrefix')}{formatUsd(balance.usedQuota)}
|
{t('balance.usedPrefix')}{formatUsd(balance.usedQuota)}
|
||||||
</span>
|
|
||||||
{typeof balance.requestCount === 'number' && balance.requestCount > 0 && (
|
{typeof balance.requestCount === 'number' && balance.requestCount > 0 && (
|
||||||
<>
|
<> · {balance.requestCount} {t('balance.requestsSuffix')}</>
|
||||||
<span className="h-3 w-px bg-[var(--color-border)]/70" aria-hidden />
|
|
||||||
<span className="tabular-nums text-[var(--color-text-tertiary)]">
|
|
||||||
{balance.requestCount} {t('balance.requestsSuffix')}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/* Progress bar — fills with remaining / total. The full track is the
|
||||||
|
lifetime-funded amount; the filled portion is what's still in the
|
||||||
|
wallet. Color tracks the same green/amber/red health bands. */}
|
||||||
|
<div
|
||||||
|
className="mt-1.5 h-1.5 w-full overflow-hidden rounded-full"
|
||||||
|
style={{ backgroundColor: health.bg }}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="h-full rounded-full transition-[width] duration-500 ease-out"
|
||||||
|
style={{
|
||||||
|
width: `${fillPercent}%`,
|
||||||
|
backgroundColor: health.color,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const en = {
|
|||||||
'balance.remaining': 'left',
|
'balance.remaining': 'left',
|
||||||
'balance.usedPrefix': 'used ',
|
'balance.usedPrefix': 'used ',
|
||||||
'balance.requestsSuffix': 'reqs',
|
'balance.requestsSuffix': 'reqs',
|
||||||
|
'balance.tooltip': 'Balance from Heicode platform · bar shows remaining / total',
|
||||||
'sidebar.collapse': 'Collapse sidebar',
|
'sidebar.collapse': 'Collapse sidebar',
|
||||||
'sidebar.expand': 'Expand sidebar',
|
'sidebar.expand': 'Expand sidebar',
|
||||||
'sidebar.logout': 'Log out',
|
'sidebar.logout': 'Log out',
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export const zh: Record<TranslationKey, string> = {
|
|||||||
'balance.remaining': '剩余',
|
'balance.remaining': '剩余',
|
||||||
'balance.usedPrefix': '已用 ',
|
'balance.usedPrefix': '已用 ',
|
||||||
'balance.requestsSuffix': '次',
|
'balance.requestsSuffix': '次',
|
||||||
|
'balance.tooltip': '余额来自 Heicode 平台 · 进度条为剩余 / 总额',
|
||||||
'sidebar.collapse': '折叠侧边栏',
|
'sidebar.collapse': '折叠侧边栏',
|
||||||
'sidebar.expand': '展开侧边栏',
|
'sidebar.expand': '展开侧边栏',
|
||||||
'sidebar.logout': '退出登录',
|
'sidebar.logout': '退出登录',
|
||||||
|
|||||||
Reference in New Issue
Block a user