Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions packages/agent-chat/src/MailboxThumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useEffect, useState } from "react";
import { mailboxIdsFromAttachments, parseMessageAttachments, isReadableAttachmentName } from "./mailbox";
import { colors } from "./ranch-shell/styles";

function joinUrl(base: string, path: string): string {
const b = base.replace(/\/+$/, "");
Expand Down Expand Up @@ -51,7 +52,7 @@ function ListedTag({ n }: { n: number }) {
borderRadius: 999,
background: "rgba(0,0,0,0.72)",
color: "#fff",
fontSize: 11,
fontSize: 12,
lineHeight: 1.4,
pointerEvents: "none",
}}
Expand All @@ -66,18 +67,22 @@ export function MailboxThumbs({
attachments,
gatewayBaseUrl,
getAccessToken,
loadFailedLabel = "Attachment failed to load",
}: {
chatId: string;
attachments?: string[] | string | null;
gatewayBaseUrl: string;
getAccessToken: () => Promise<string | null>;
loadFailedLabel?: string;
}) {
const ids = mailboxIdsFromAttachments(parseMessageAttachments(attachments ?? []));
const [files, setFiles] = useState<FileBlob[]>([]);
const [failedIds, setFailedIds] = useState<string[]>([]);

useEffect(() => {
if (ids.length === 0 || !chatId) {
setFiles([]);
setFailedIds([]);
return;
}
let cancelled = false;
Expand All @@ -86,6 +91,7 @@ export function MailboxThumbs({
const token = await getAccessToken();
if (!token || cancelled) return;
const next: FileBlob[] = [];
const failed: string[] = [];
for (const id of ids) {
try {
const res = await fetch(
Expand All @@ -95,7 +101,10 @@ export function MailboxThumbs({
),
{ headers: { Authorization: `Bearer ${token}` } },
);
if (!res.ok) continue;
if (!res.ok) {
failed.push(id);
continue;
}
const blob = await res.blob();
const url = URL.createObjectURL(blob);
created.push(url);
Expand All @@ -114,10 +123,13 @@ export function MailboxThumbs({
),
});
} catch {
/* skip broken blob */
failed.push(id);
}
}
if (!cancelled) setFiles(next);
if (!cancelled) {
setFiles(next);
setFailedIds(failed);
}
})();
return () => {
cancelled = true;
Expand All @@ -132,7 +144,7 @@ export function MailboxThumbs({
f.contentType.startsWith("image/");
return playable || isReadableAttachmentName(f.name, f.mailboxId);
});
if (visible.length === 0) return null;
if (visible.length === 0 && failedIds.length === 0) return null;
return (
<div
style={{
Expand Down Expand Up @@ -165,7 +177,7 @@ export function MailboxThumbs({
) : (
<img
src={f.url}
alt=""
alt={f.name}
style={{ maxWidth: "100%", borderRadius: 8, display: "block" }}
/>
);
Expand Down Expand Up @@ -194,6 +206,20 @@ export function MailboxThumbs({
</div>
);
})}
{failedIds.map((id) => (
<div
key={`failed-${id}`}
style={{
fontSize: 12,
color: colors.muted,
padding: "8px 10px",
border: `1px dashed ${colors.border}`,
borderRadius: 8,
}}
>
{loadFailedLabel}
</div>
))}
</div>
);
}
75 changes: 20 additions & 55 deletions packages/agent-chat/src/ranch-shell/AccountPanels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
import type { RanchChatAccount } from "../types";
import { AgentOwnerWallet } from "./AgentOwnerWallet";
import type { RanchLocale, RanchMessages } from "./i18n";
import { btnGhost, btnIcon, btnPrimary, colors } from "./styles";
import { btnGhost, btnIcon, btnPrimary, colors, inputStyle } from "./styles";
import { useModalA11y } from "./useModalA11y";
import {
buildWalletCheckoutUrl,
Expand Down Expand Up @@ -86,9 +86,9 @@ function Badge({
}) {
const palette: CSSProperties =
tone === "accent"
? { background: colors.accentSoft, color: "#7aa2f7" }
? { background: colors.accentSoft, color: colors.accentBright }
: tone === "ok"
? { background: "rgba(16,185,129,0.14)", color: "#34d399" }
? { background: "rgba(16,185,129,0.14)", color: colors.success }
: { background: "rgba(255,255,255,0.07)", color: colors.muted };
return (
<span
Expand Down Expand Up @@ -116,7 +116,7 @@ function AvatarDot({ label, size = 34 }: { label: string; size?: number }) {
borderRadius: 999,
flexShrink: 0,
background: colors.accentSoft,
color: "#7aa2f7",
color: colors.accentBright,
display: "grid",
placeItems: "center",
fontSize: Math.round(size * 0.42),
Expand Down Expand Up @@ -358,7 +358,7 @@ function UsageBar({
borderRadius: 999,
background:
tone === "accent"
? "linear-gradient(90deg, #3b82f6, #7aa2f7)"
? `linear-gradient(90deg, ${colors.accent}, ${colors.accentBright})`
: "rgba(232,238,245,0.55)",
transition: "width 240ms ease",
}}
Expand Down Expand Up @@ -914,10 +914,10 @@ export function AccountPlanUsagePanel({
setLimitMode(e.target.value === "fixed" ? "fixed" : "unlimited")
}
style={{
...btnGhost,
...inputStyle,
width: "auto",
padding: "6px 8px",
appearance: "auto",
background: "#121820",
}}
>
<option value="fixed">{t.accountPlanLimitFixed}</option>
Expand All @@ -930,15 +930,7 @@ export function AccountPlanUsagePanel({
step={1}
value={limitInput}
onChange={(e) => setLimitInput(e.target.value)}
style={{
width: 72,
border: `1px solid ${colors.border}`,
background: "#121820",
color: colors.text,
borderRadius: 8,
padding: "6px 8px",
fontSize: 13,
}}
style={{ ...inputStyle, width: 72, padding: "6px 8px" }}
/>
) : null}
<button
Expand Down Expand Up @@ -1029,7 +1021,7 @@ export function AccountPlanUsagePanel({
width: "min(920px, calc(100vw - 32px))",
maxHeight: "min(90vh, 900px)",
overflow: "auto",
background: "#141a22",
background: colors.panelElevated,
borderRadius: 14,
border: `1px solid ${colors.border}`,
padding: "20px 18px 16px",
Expand Down Expand Up @@ -1058,7 +1050,7 @@ export function AccountPlanUsagePanel({
}}
aria-label={t.close}
>
×
✕
</button>
</div>
<div
Expand Down Expand Up @@ -1107,7 +1099,7 @@ export function AccountPlanUsagePanel({
style={{
...planCard,
position: "relative",
background: isCurrent ? "#1a2330" : colors.panel,
background: isCurrent ? colors.panelAlt : colors.panel,
border: isCurrent
? "1px solid rgba(59,130,246,0.45)"
: `1px solid ${colors.border}`,
Expand Down Expand Up @@ -1240,7 +1232,7 @@ export function AccountPlanUsagePanel({
fontSize: 12,
color:
buyMsgTone === "ok"
? "#7dcea0"
? colors.success
: buyMsgTone === "danger"
? colors.danger
: colors.muted,
Expand Down Expand Up @@ -1321,7 +1313,7 @@ function CheckoutEmbedDialog({
style={{
width: "min(420px, 100%)",
height: "min(640px, 92%)",
background: "#0a0a0a",
background: colors.embedBg,
borderRadius: 14,
border: `1px solid ${colors.border}`,
overflow: "hidden",
Expand Down Expand Up @@ -1357,7 +1349,7 @@ function CheckoutEmbedDialog({
onClick={onRequestClose}
aria-label={closeLabel}
>
×
✕
</button>
</div>
</div>
Expand Down Expand Up @@ -1407,7 +1399,7 @@ function CheckoutEmbedDialog({
src={url}
allow="payment"
referrerPolicy="strict-origin-when-cross-origin"
style={{ flex: 1, width: "100%", border: 0, background: "#0a0a0a" }}
style={{ flex: 1, width: "100%", border: 0, background: colors.embedBg }}
/>
</div>
</ViewportOverlay>
Expand Down Expand Up @@ -1482,15 +1474,7 @@ export function ChatCollabBudgetSection({
min={0}
value={capDraft}
onChange={(e) => setCapDraft(e.target.value)}
style={{
flex: 1,
padding: "9px 12px",
borderRadius: 10,
border: `1px solid ${colors.border}`,
background: colors.bg,
color: colors.text,
fontSize: 14,
}}
style={{ ...inputStyle, flex: 1, padding: "9px 12px", fontSize: 14 }}
/>
<button
type="button"
Expand Down Expand Up @@ -1532,15 +1516,7 @@ export function ChatCollabBudgetSection({
min={1}
value={addDraft}
onChange={(e) => setAddDraft(e.target.value)}
style={{
width: 96,
padding: "9px 12px",
borderRadius: 10,
border: `1px solid ${colors.border}`,
background: colors.bg,
color: colors.text,
fontSize: 14,
}}
style={{ ...inputStyle, width: 96, padding: "9px 12px", fontSize: 14 }}
/>
<button
type="button"
Expand Down Expand Up @@ -1662,17 +1638,6 @@ function WalletBillingDocsSection({
const paidOrders = orders.filter((o) => o.status === "paid");
const reqByOrder = new Map(requests.map((r) => [r.payment_order_id, r]));

const inputStyle: CSSProperties = {
width: "100%",
padding: "9px 12px",
borderRadius: 10,
border: `1px solid ${colors.border}`,
background: colors.bg,
color: colors.text,
fontSize: 13,
boxSizing: "border-box",
};

const downloadReceipt = (orderId: string) => {
setDownloading(orderId);
void client
Expand Down Expand Up @@ -2209,7 +2174,7 @@ export function AccountWalletPanel({
height: 8,
borderRadius: 999,
flexShrink: 0,
background: positive ? "#34d399" : negative ? colors.danger : colors.muted,
background: positive ? colors.success : negative ? colors.danger : colors.muted,
}}
/>
<span style={{ flex: 1, minWidth: 0 }}>
Expand All @@ -2236,7 +2201,7 @@ export function AccountWalletPanel({
fontSize: 13,
fontWeight: 700,
fontVariantNumeric: "tabular-nums",
color: positive ? "#34d399" : negative ? colors.danger : colors.text,
color: positive ? colors.success : negative ? colors.danger : colors.text,
flexShrink: 0,
}}
>
Expand Down Expand Up @@ -2365,7 +2330,7 @@ export function AccountKeysPanel({
borderRadius: 10,
flexShrink: 0,
background: colors.accentSoft,
color: "#7aa2f7",
color: colors.accentBright,
display: "grid",
placeItems: "center",
fontSize: 12,
Expand Down
Loading
Loading