import {
ScrollView,
View,
Text,
TouchableOpacity,
ActivityIndicator,
RefreshControl,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { MaterialIcons } from "@expo/vector-icons";
import { useCodexUsage } from "@/hooks/useCodexUsage";
import { UsageStat } from "@/components/UsageStat";
import { ErrorMessage } from "@/components/ErrorMessage";
import { LastUpdated } from "@/components/LastUpdated";
import { ScreenErrorBoundary } from "@/components/ScreenErrorBoundary";
import { COLORS } from "@/lib/constants";
import { windowLabel } from "@/lib/timeUtils";
import type { CodexResetCredit } from "@/types/codex";
function formatResetStatus(status?: string) {
if (!status) return "Unknown";
return status.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
}
function ResetCreditRow({ credit }: { credit: CodexResetCredit }) {
return (
Credit {credit.index}
{formatResetStatus(credit.status)}
{credit.timeUntilExpiry && (
Expires in {credit.timeUntilExpiry}
)}
{credit.expiresAtLocal && (
Expires {credit.expiresAtLocal}
)}
{credit.grantedAtLocal && (
Granted {credit.grantedAtLocal}
)}
);
}
function CodexTabContent() {
const {
auth,
usage,
lastFetchedAt,
status,
error,
importAuthFile,
refresh,
clearAuth,
} =
useCodexUsage();
const resetCoupons = usage?.resetCoupons;
const availableResetCredits =
resetCoupons?.credits?.filter((credit) => credit.status === "available") ?? [];
return (
}
>
{/* Header */}
Codex CLI
Rate limits & credits
{/* Configuration card */}
Configuration
{auth ? (
Connected
{auth.accountId && (
{auth.accountId.slice(0, 10)}…
)}
Clear
) : (
Import auth.json
Located at ~/.codex/auth.json
)}
{/* Usage card */}
Usage
{status === "idle" && !auth && (
Import auth.json to see your rate limits
)}
{status === "loading" && !usage && (
)}
{status === "error" && error && }
{usage && (
{/* Plan badge */}
{usage.planType ?? "codex"}
{usage.primary && (
)}
{usage.secondary && (
)}
{/* Credits */}
Credits
{usage.credits.unlimited ? (
Unlimited
) : usage.credits.hasCredits ? (
${Number(usage.credits.balance).toFixed(2)} remaining
) : (
No credits
)}
{resetCoupons && (
Reset Credits
{resetCoupons.availableCount ?? 0} available
{typeof resetCoupons.totalEarnedCount === "number" && (
{resetCoupons.totalEarnedCount} earned total
)}
{resetCoupons.nextExpiringCredit?.expiresAtLocal && (
Next expires {resetCoupons.nextExpiringCredit.expiresAtLocal}
)}
{resetCoupons.nextExpiringCredit?.timeUntilExpiry && (
In {resetCoupons.nextExpiringCredit.timeUntilExpiry}
)}
{availableResetCredits.length > 0 && (
Available Now
{availableResetCredits.map((credit) => (
))}
)}
{resetCoupons.source !== "live_api" && (
Source: {resetCoupons.sourceDescription}
)}
)}
)}
);
}
export default function CodexTab() {
return (
);
}