Skip to content

Commit 5cca4db

Browse files
committed
Merge branch 'dev'
2 parents 746b269 + 9d535b4 commit 5cca4db

29 files changed

Lines changed: 891 additions & 339 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zero-limit",
3-
"version": "1.0.7",
3+
"version": "1.0.9",
44
"private": true,
55
"type": "module",
66
"scripts": {

public/copilot/copilot.png

3.08 KB
Loading

src-tauri/src/commands/cli_proxy.rs

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -124,47 +124,3 @@ pub async fn is_cli_proxy_running() -> CommandResult<bool> {
124124

125125
Ok(false)
126126
}
127-
128-
/// Run Kiro CLI authentication
129-
/// This spawns the CLI proxy binary with auth flags and waits for completion
130-
#[command]
131-
pub async fn run_kiro_auth(exe_path: String, auth_method: String) -> CommandResult<String> {
132-
// Map auth method to CLI flag
133-
let auth_flag = match auth_method.as_str() {
134-
"google" => "-kiro-google-login",
135-
"aws" => "-kiro-aws-login",
136-
"aws-authcode" => "-kiro-aws-authcode",
137-
"import" => "-kiro-import",
138-
_ => return Err(CommandError::General(format!("Unknown auth method: {}", auth_method))),
139-
};
140-
141-
// Get working directory from exe path
142-
let exe = std::path::PathBuf::from(&exe_path);
143-
let work_dir = exe.parent()
144-
.ok_or_else(|| CommandError::General("Invalid path".into()))?;
145-
146-
// Spawn process and wait for completion
147-
#[cfg(windows)]
148-
let output = Command::new(&exe_path)
149-
.arg(auth_flag)
150-
.current_dir(work_dir)
151-
.creation_flags(CREATE_NO_WINDOW)
152-
.output()
153-
.map_err(|e| CommandError::General(format!("Failed to start auth: {}", e)))?;
154-
155-
#[cfg(not(windows))]
156-
let output = Command::new(&exe_path)
157-
.arg(auth_flag)
158-
.current_dir(work_dir)
159-
.output()
160-
.map_err(|e| CommandError::General(format!("Failed to start auth: {}", e)))?;
161-
162-
if output.status.success() {
163-
Ok("Authentication completed successfully".to_string())
164-
} else {
165-
let stderr = String::from_utf8_lossy(&output.stderr);
166-
let stdout = String::from_utf8_lossy(&output.stdout);
167-
let message = if !stderr.is_empty() { stderr.to_string() } else { stdout.to_string() };
168-
Err(CommandError::General(format!("Auth failed: {}", message.trim())))
169-
}
170-
}

src-tauri/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ pub fn run() {
9090
start_cli_proxy,
9191
stop_cli_proxy,
9292
is_cli_proxy_running,
93-
run_kiro_auth,
9493
])
9594
.build(tauri::generate_context!())
9695
.expect("error while building tauri application")

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "ZeroLimit",
4-
"version": "1.0.8",
4+
"version": "1.0.9",
55
"identifier": "com.0xtbug.zero-limit",
66
"build": {
77
"beforeDevCommand": "pnpm dev",

src/components/quota/CompactQuotaCard.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import { Card } from '@/components/ui/card';
66
import { Badge } from '@/components/ui/badge';
7-
import { Clock, RefreshCw, Eye, List, ChevronDown } from 'lucide-react';
7+
import { Clock, RefreshCw, Eye, List, ChevronDown, Ban } from 'lucide-react';
88
import { useMemo, useState } from 'react';
99
import {
1010
Dialog,
@@ -40,11 +40,15 @@ export function CompactQuotaCard({
4040
loading,
4141
error,
4242
items,
43+
plan,
4344
onRefresh,
4445
isPrivacyMode
4546
}: CompactQuotaCardProps) {
4647
const [isExpanded, setIsExpanded] = useState(true);
4748

49+
// Check if account is suspended
50+
const isSuspended = plan?.toLowerCase() === 'suspended';
51+
4852
// Apply masking
4953
const displayEmail = isPrivacyMode ? maskEmail(email || '') : (email || '********@*****.com');
5054

@@ -94,7 +98,7 @@ export function CompactQuotaCard({
9498
};
9599

96100
return (
97-
<Card className="p-4 space-y-3 hover:shadow-md transition-shadow">
101+
<Card className="p-4 space-y-3 hover:shadow-md transition-shadow h-full flex flex-col">
98102
{/* Email with expand/collapse toggle */}
99103
<div className="flex items-center justify-between min-w-0">
100104
<div className="flex items-center gap-2 min-w-0 flex-1">
@@ -119,9 +123,17 @@ export function CompactQuotaCard({
119123
<div className="text-xs text-destructive truncate">{error}</div>
120124
)}
121125

126+
{/* Suspended State - centered icon and text */}
127+
{!loading && !error && isSuspended && (
128+
<div className="flex flex-col items-center justify-center py-6 gap-2 flex-1">
129+
<Ban className="h-10 w-10 text-yellow-500" />
130+
<span className="text-sm font-semibold text-yellow-600">Temporarily Suspended</span>
131+
</div>
132+
)}
133+
122134
{/* Model badges grid with progress bars - expanded view */}
123-
{!loading && !error && isExpanded && (
124-
<div className="grid grid-cols-1 gap-2">
135+
{!loading && !error && !isSuspended && isExpanded && (
136+
<div className="grid grid-cols-1 gap-2 flex-1">
125137
{groupedItems.map((group, idx) => (
126138
<div key={idx} className="space-y-1">
127139
{/* Model info row */}
@@ -150,7 +162,7 @@ export function CompactQuotaCard({
150162
)}
151163

152164
{/* Collapsed compact summary view - simple inline text */}
153-
{!loading && !error && !isExpanded && (
165+
{!loading && !error && !isSuspended && !isExpanded && (
154166
<div className="text-xs text-muted-foreground space-y-1">
155167
{groupedItems.map((group, idx) => (
156168
<div key={idx} className="flex items-center justify-between gap-2 min-w-0">
@@ -172,7 +184,7 @@ export function CompactQuotaCard({
172184
)}
173185

174186
{/* Footer Row */}
175-
<div className="flex items-center justify-between pt-2 border-t text-xs text-muted-foreground">
187+
<div className="flex items-center justify-between pt-2 border-t text-xs text-muted-foreground mt-auto">
176188
<span>{new Date().toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })}, {new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false })}</span>
177189
<div className="flex items-center gap-1">
178190
{/* View Details Dialog */}

src/components/quota/ProviderFilter.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface ProviderFilterItem {
77
label: string;
88
count: number;
99
icon?: string;
10+
iconNeedsInvert?: boolean;
1011
}
1112

1213
interface ProviderFilterProps {
@@ -33,7 +34,11 @@ export function ProviderFilter({ items, activeId, onSelect }: ProviderFilterProp
3334
)}
3435
>
3536
{item.icon && (
36-
<img src={item.icon} alt={item.label} className="h-4 w-4 object-contain" />
37+
<img
38+
src={item.icon}
39+
alt={item.label}
40+
className={cn("h-4 w-4 object-contain", item.iconNeedsInvert && "invert-on-dark")}
41+
/>
3742
)}
3843

3944
<span className="text-sm font-medium">{item.label}</span>

src/components/quota/ProviderQuotaCard.tsx

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Card, CardContent } from '@/components/ui/card';
22
import { Badge } from '@/components/ui/badge';
3-
import { RefreshCw, User, Clock, Search, Folder, List } from 'lucide-react';
3+
import { RefreshCw, User, Clock, Search, Folder, List, Ban } from 'lucide-react';
44
import { useTranslation } from 'react-i18next';
55
import { Button } from '@/components/ui/button';
66
import {
@@ -28,6 +28,7 @@ interface ProviderQuotaCardProps {
2828
loading: boolean;
2929
error?: string;
3030
items: QuotaItem[];
31+
plan?: string;
3132
onRefresh: () => void;
3233
isPrivacyMode: boolean;
3334
}
@@ -39,6 +40,7 @@ export function ProviderQuotaCard({
3940
loading,
4041
error,
4142
items,
43+
plan,
4244
onRefresh,
4345
isPrivacyMode
4446
}: ProviderQuotaCardProps) {
@@ -81,15 +83,27 @@ export function ProviderQuotaCard({
8183
// Determine icon based on group name
8284
let icon: string | undefined;
8385
const lowerName = name.toLowerCase();
86+
const lowerProvider = provider.toLowerCase();
87+
8488
if (lowerName.includes('claude')) {
8589
icon = '/claude/claude.png';
8690
} else if (lowerName.includes('gemini')) {
8791
icon = '/gemini/gemini.png';
8892
} else if (lowerName.includes('gpt') || lowerName.includes('o1')) {
8993
icon = '/openai/openai.png';
90-
} else if (isAntigravity) {
91-
// For Antigravity "Other" group, default to OpenAI icon
92-
icon = '/openai/openai.png';
94+
} else if (lowerName === 'other' || !icon) {
95+
// For "Other" group, use provider-specific icon
96+
if (lowerProvider.includes('antigravity')) {
97+
icon = '/openai/openai.png';
98+
} else if (lowerProvider.includes('codex')) {
99+
icon = '/openai/openai.png';
100+
} else if (lowerProvider.includes('kiro')) {
101+
icon = '/kiro/kiro.png';
102+
} else if (lowerProvider.includes('copilot') || lowerProvider.includes('github')) {
103+
icon = '/github/github.png';
104+
} else {
105+
icon = '/openai/openai.png'; // Default fallback
106+
}
93107
}
94108

95109
return {
@@ -102,10 +116,13 @@ export function ProviderQuotaCard({
102116
}).sort((a, b) => a.name.localeCompare(b.name));
103117
}, [items, provider]);
104118

119+
// Check if account is suspended
120+
const isSuspended = plan?.toLowerCase() === 'suspended';
121+
105122
return (
106-
<Card className="mb-4 overflow-hidden border bg-card text-card-foreground p-0">
123+
<Card className="mb-4 overflow-hidden border bg-card text-card-foreground p-0 py-0 gap-1">
107124
{/* Header Section */}
108-
<div className="flex flex-col gap-3 border-b p-2 pt-4 bg-muted/20">
125+
<div className="flex flex-col gap-2 border-b p-2 pb-2 pt-3 bg-muted/20">
109126
<div className="flex items-center justify-between">
110127
<div className="flex flex-col gap-2">
111128
{/* Top Row: List Icon + Email */}
@@ -210,24 +227,31 @@ export function ProviderQuotaCard({
210227
</div>
211228

212229
{/* Summary Content Section */}
213-
<CardContent className="p-2 space-y-4">
230+
<CardContent className="px-2 py-1 space-y-2">
214231
{error ? (
215232
<div className="py-2 text-sm text-destructive flex items-center gap-2">
216233
<div className="h-2 w-2 rounded-full bg-destructive"></div>
217234
{error}
218235
</div>
219236
) : (
220-
<div className="space-y-4">
237+
<div className="space-y-2">
221238
<div className="text-xs font-semibold uppercase tracking-wider text-muted-foreground flex items-center gap-2">
222239
{t('quotaCard.usage')}
223240
</div>
224241

225-
{groupedItems.length === 0 && !loading && (
242+
{groupedItems.length === 0 && !loading && !isSuspended && (
226243
<div className="text-sm italic text-muted-foreground">{t('quotaCard.noUsage')}</div>
227244
)}
228245

246+
{/* Suspended State */}
247+
{isSuspended && (
248+
<div className="flex flex-col items-center justify-center py-8 gap-3">
249+
<Ban className="h-12 w-12 text-yellow-500" />
250+
<span className="text-lg font-semibold text-yellow-600">Temporarily Suspended</span>
251+
</div>
252+
)}
229253

230-
{groupedItems.map((group, idx) => (
254+
{!isSuspended && groupedItems.map((group, idx) => (
231255
<div key={idx} className="space-y-2">
232256
<div className="flex items-center justify-between text-sm">
233257
<div className="flex items-center gap-2">

src/i18n/locales/en.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@
6666
"completeLogin": "Complete the login in your browser",
6767
"openLink": "Open Link",
6868
"verify": "Verify",
69-
"manualCallback": "If valid callback is not detected automatically:"
69+
"manualCallback": "If valid callback is not detected automatically:",
70+
"authSuccess": "Provider connected successfully!"
71+
},
72+
"oauth": {
73+
"pasteCallback": "Paste callback URL here..."
7074
},
7175
"quota": {
7276
"title": "Quota",
@@ -134,6 +138,10 @@
134138
},
135139
"usageStats": {
136140
"title": "Usage Statistics",
141+
"settingsDesc": "Configure usage statistics collection and display",
142+
"enabled": "Enable Usage Statistics",
143+
"enabledDesc": "Collect and display usage statistics in the Dashboard",
144+
"disabledMessage": "Usage statistics are disabled. Enable them in Settings to view your usage data.",
137145
"totalRequests": "Total Requests",
138146
"successfulRequests": "Success Requests",
139147
"failedRequests": "Failed Requests",

src/i18n/locales/id.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@
6666
"completeLogin": "Selesaikan login di browser Anda",
6767
"openLink": "Buka Tautan",
6868
"verify": "Verifikasi",
69-
"manualCallback": "Jika callback valid tidak terdeteksi otomatis:"
69+
"manualCallback": "Jika callback valid tidak terdeteksi otomatis:",
70+
"authSuccess": "Penyedia berhasil terhubung!"
71+
},
72+
"oauth": {
73+
"pasteCallback": "Tempelkan URL callback di sini..."
7074
},
7175
"quota": {
7276
"title": "Kuota",
@@ -134,6 +138,10 @@
134138
},
135139
"usageStats": {
136140
"title": "Statistik Penggunaan",
141+
"settingsDesc": "Konfigurasi pengumpulan dan tampilan statistik penggunaan",
142+
"enabled": "Aktifkan Statistik Penggunaan",
143+
"enabledDesc": "Kumpulkan dan tampilkan statistik penggunaan di Dasbor",
144+
"disabledMessage": "Statistik penggunaan dinonaktifkan. Aktifkan di Pengaturan untuk melihat data penggunaan Anda.",
137145
"totalRequests": "Total Permintaan",
138146
"successfulRequests": "Permintaan Berhasil",
139147
"failedRequests": "Permintaan Gagal",

0 commit comments

Comments
 (0)