fix(widget): address review on the composer changes

This commit is contained in:
ManishMadan2882 committed 2026-09-10 04:30:04 +05:30
1 parent 7df153a798
commit 4393197802
3 files changed
+45 -6

No files matched your search

@@ -525,6 +525,9 @@ export const VoiceWaveform = ({
const context = canvas?.getContext('2d');
if (!canvas || !context) return;
// Safari exposed webkitSpeechRecognition from 14.1 but roundRect only
// from 16.4, so dictation can run where the rounded path throws.
const canRoundRect = typeof context.roundRect === 'function';
const levels = new Array<number>(WAVEFORM_BARS).fill(0);
// Bare `Uint8Array` widens to ArrayBufferLike, which the analyser
// signature rejects.
@@ -573,9 +576,13 @@ export const VoiceWaveform = ({
const x = index * slot + (slot - barWidth) / 2;
const y = (height - barHeight) / 2;
context.globalAlpha = 0.35 + 0.65 * (index / WAVEFORM_BARS);
context.beginPath();
context.roundRect(x, y, barWidth, barHeight, radius);
context.fill();
if (canRoundRect) {
context.beginPath();
context.roundRect(x, y, barWidth, barHeight, radius);
context.fill();
} else {
context.fillRect(x, y, barWidth, barHeight);
}
}
context.globalAlpha = 1;
};
@@ -1208,7 +1208,7 @@ const SourcesList = styled.div`
gap: 6px;
`;
const SourceChip = styled.span`
const SourceChip = styled.a`
color: ${(props) => props.theme.secondary.text};
background: ${(props) => props.theme.secondary.bg};
border: 1px solid ${(props) => props.theme.hairline};
@@ -1219,6 +1219,21 @@ const SourceChip = styled.span`
align-items: center;
max-width: min(100%, 220px);
line-height: 1.6;
text-decoration: none;
cursor: pointer;
transition:
border-color 0.15s ease,
color 0.15s ease;
&:hover {
color: ${(props) => props.theme.primary.text};
border-color: ${(props) => props.theme.accent!.base};
}
&:focus-visible {
outline: 2px solid ${(props) => props.theme.accent!.base};
outline-offset: 2px;
}
`;
const SourceLabel = styled.span`
min-width: 0;
@@ -1255,7 +1270,13 @@ const SourcesComponent = ({
return (
<SourcesList>
{visibleSources.map((source, idx) => (
<SourceChip key={idx} title={source.title}>
<SourceChip
key={idx}
href={source.source}
target="_blank"
rel="noopener noreferrer"
title={source.title}
>
<SourceLabel>{source.title}</SourceLabel>
</SourceChip>
))}
@@ -1739,7 +1760,10 @@ export const WidgetCore = ({
const isDictating =
recordingState === 'recording' || recordingState === 'transcribing';
const canSubmit =
prompt.trim().length > 0 && !sendBlockedReason && !isDictating;
prompt.trim().length > 0 &&
!sendBlockedReason &&
!isDictating &&
status !== 'loading';
const submitPrompt = async () => {
if (!canSubmit) return;
@@ -5,6 +5,8 @@
* response carries. Auth is the agent key as `api_key` in the multipart body.
*/
const UPLOAD_TIMEOUT_MS = 2 * 60 * 1000;
interface UploadAttachmentOptions {
file: File;
apiKey: string;
@@ -91,7 +93,13 @@ export function uploadAttachment({
reject(new DOMException('Upload aborted', 'AbortError'));
};
xhr.ontimeout = () => {
signal?.removeEventListener('abort', onAbort);
reject(new Error('Upload timed out.'));
};
xhr.open('POST', `${apiHost}/api/store_attachment`);
xhr.timeout = UPLOAD_TIMEOUT_MS;
xhr.send(formData);
});
}