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
153 changes: 89 additions & 64 deletions echo/frontend/src/locales/de-DE.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion echo/frontend/src/locales/de-DE.ts

Large diffs are not rendered by default.

153 changes: 89 additions & 64 deletions echo/frontend/src/locales/en-US.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion echo/frontend/src/locales/en-US.ts

Large diffs are not rendered by default.

153 changes: 89 additions & 64 deletions echo/frontend/src/locales/es-ES.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion echo/frontend/src/locales/es-ES.ts

Large diffs are not rendered by default.

153 changes: 89 additions & 64 deletions echo/frontend/src/locales/fr-FR.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion echo/frontend/src/locales/fr-FR.ts

Large diffs are not rendered by default.

153 changes: 89 additions & 64 deletions echo/frontend/src/locales/nl-NL.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion echo/frontend/src/locales/nl-NL.ts

Large diffs are not rendered by default.

121 changes: 120 additions & 1 deletion echo/frontend/src/routes/participant/ParticipantConversation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useI18nNavigate } from "@/hooks/useI18nNavigate";
import { I18nLink } from "@/components/common/i18nLink";
import { useProjectSharingLink } from "@/components/project/ProjectQRCode";
import {
useUploadConversationChunk,
useUploadConversationTextChunk,
Expand All @@ -21,6 +22,7 @@ import {
IconPlayerPause,
IconPlayerPlay,
IconPlayerStopFilled,
IconPlus,
IconQuestionMark,
IconReload,
IconTextCaption,
Expand Down Expand Up @@ -66,7 +68,6 @@ export const ParticipantConversationAudioRoute = () => {
const [showMicTest, setShowMicTest] = useState(!savedDeviceId);
const [deviceId, setDeviceId] = useState<string>(savedDeviceId || "");


const projectQuery = useParticipantProjectById(projectId ?? "");
const conversationQuery = useConversationQuery(projectId, conversationId);
const chunks = useConversationChunksQuery(projectId, conversationId);
Expand Down Expand Up @@ -94,10 +95,15 @@ export const ParticipantConversationAudioRoute = () => {
const [lastReplyTime, setLastReplyTime] = useState<Date | null>(null);
const [remainingCooldown, setRemainingCooldown] = useState(0);
const [showCooldownMessage, setShowCooldownMessage] = useState(false);
const [
conversationDeletedDuringRecording,
setConversationDeletedDuringRecording,
] = useState(false);

// Navigation and language
const navigate = useI18nNavigate();
const { iso639_1 } = useLanguage();
const newConversationLink = useProjectSharingLink(projectQuery.data);

// Calculate remaining cooldown time
const getRemainingCooldown = useCallback(() => {
Expand Down Expand Up @@ -140,6 +146,22 @@ export const ParticipantConversationAudioRoute = () => {
permissionError,
} = audioRecorder;

// Monitor conversation status during recording - handle deletion mid-recording
useEffect(() => {
if (isRecording && (conversationQuery.isError || !conversationQuery.data)) {
console.warn(
"Conversation deleted or became unavailable during recording",
);
stopRecording();
setConversationDeletedDuringRecording(true);
}
}, [
isRecording,
conversationQuery.isError,
conversationQuery.data,
stopRecording,
]);

const {
messages: echoMessages,
isLoading,
Expand Down Expand Up @@ -227,6 +249,62 @@ export const ParticipantConversationAudioRoute = () => {
return <LoadingOverlay visible />;
}

// Check if conversation is not present or failed to load
if (
conversationQuery.isError ||
!conversationQuery.data ||
conversationDeletedDuringRecording
) {
return (
<div className="container mx-auto flex h-full max-w-2xl flex-col items-center justify-center">
<div className="p-8 text-center">
<Text size="xl" fw={500} c="red" mb="md">
{conversationDeletedDuringRecording ? (
<Trans>Conversation Ended</Trans>
) : (
<Trans>Something went wrong</Trans>
)}
</Text>
<Text size="md" c="dimmed" mb="lg">
{conversationDeletedDuringRecording ? (
<Trans>
It looks like the conversation was deleted while you were
recording. We've stopped the recording to prevent any issues.
You can start a new one anytime.
</Trans>
) : (
<Trans>
The conversation could not be loaded. Please try again or
contact support.
</Trans>
)}
</Text>
<Group justify="center" gap="md">
<Button
variant="light"
size="md"
onClick={() => window.location.reload()}
leftSection={<IconReload />}
>
<Trans>Reload Page</Trans>
</Button>
{newConversationLink && (
<Button
leftSection={<IconPlus size={16} />}
variant="filled"
size="md"
component="a"
href={newConversationLink}
>
<Trans>Start New Conversation</Trans>
</Button>
)}
</Group>
</div>
</div>
);
}

const textModeUrl = `/${projectId}/conversation/${conversationId}/text`;
const finishUrl = `/${projectId}/conversation/${conversationId}/finish`;

Expand Down Expand Up @@ -534,6 +612,7 @@ export const ParticipantConversationTextRoute = () => {
const conversationQuery = useConversationQuery(projectId, conversationId);
const chunks = useConversationChunksQuery(projectId, conversationId);
const uploadChunkMutation = useUploadConversationTextChunk();
const newConversationLink = useProjectSharingLink(projectQuery.data);

const [text, setText] = useState("");

Expand Down Expand Up @@ -579,6 +658,46 @@ export const ParticipantConversationTextRoute = () => {
return <LoadingOverlay visible />;
}

// Check if conversation is not present or failed to load
if (conversationQuery.isError || !conversationQuery.data) {
return (
<div className="container mx-auto flex h-full max-w-2xl flex-col items-center justify-center">
<div className="p-8 text-center">
<Text size="xl" fw={500} c="red" mb="md">
<Trans>Something went wrong</Trans>
</Text>
<Text size="md" c="dimmed" mb="lg">
<Trans>
The conversation could not be loaded. Please try again or contact
support.
</Trans>
</Text>
<Group justify="center" gap="md">
<Button
variant="light"
size="md"
onClick={() => window.location.reload()}
leftSection={<IconReload />}
>
<Trans>Reload Page</Trans>
</Button>
{newConversationLink && (
<Button
leftSection={<IconPlus size={16} />}
variant="filled"
size="md"
component="a"
href={newConversationLink}
>
<Trans>Start New Conversation</Trans>
</Button>
)}
</Group>
</div>
</div>
);
}

return (
<div className="container mx-auto flex h-full max-w-2xl flex-col">
<Box className={clsx("relative flex-grow px-4 py-12 transition-all")}>
Expand Down