Files
han-app/VM4_Expo-mobile/app/dialogs/index.tsx
T

85 lines
3.0 KiB
TypeScript

import { useQuery } from "@tanstack/react-query";
import * as Crypto from "expo-crypto";
import { useRouter } from "expo-router";
import React, { useEffect, useState } from "react";
import { Text, View } from "react-native";
import { useApp } from "../../src/app-context";
import { AppHeader } from "../../src/components/AppHeader";
import { ChatScreenHeader } from "../../src/components/ChatScreenHeader";
import { GuestAuthGate } from "../../src/components/GuestAuthGate";
import { ScreenShell } from "../../src/components/ScreenShell";
import {
bindPendingFileIntent,
bindPendingTextIntent,
loadPendingTextIntent,
pendingDialogKey,
} from "../../src/pending-intent";
import { dialogApi } from "../../src/services";
import { ErrorNotice, Loading, styles } from "../../src/ui";
import { spacing } from "../../src/theme";
export default function DialogsScreen() {
const app = useApp();
const router = useRouter();
const [requestKey, setRequestKey] = useState<string>();
const [bindError, setBindError] = useState<unknown>();
const [bindAttempt, setBindAttempt] = useState(0);
useEffect(() => {
if (app.authStatus === "authenticated" && !requestKey) {
setRequestKey(pendingDialogKey() ?? Crypto.randomUUID());
}
}, [app.authStatus, requestKey]);
const chat = useQuery({
queryKey: ["current-dialog", requestKey],
queryFn: () => dialogApi.create(requestKey!),
enabled: app.authStatus === "authenticated" && Boolean(requestKey),
});
useEffect(() => {
if (chat.data) {
const bindAndOpen = async () => {
const intent = loadPendingTextIntent();
if (intent && !intent.dialogId) {
await bindPendingTextIntent(intent, chat.data.dialog_id);
}
await bindPendingFileIntent(chat.data.dialog_id);
router.replace(`/dialogs/${chat.data.dialog_id}`);
};
void bindAndOpen().catch(setBindError);
}
}, [bindAttempt, chat.data, router]);
if (app.authStatus !== "authenticated") {
return (
<ScreenShell>
<ChatScreenHeader title="Чат" subtitle="Требуется вход" />
<GuestAuthGate
icon="message-circle"
title="Чат доступен после входа"
description="Авторизуйтесь, чтобы переписываться с оператором и получать ответы."
/>
</ScreenShell>
);
}
return (
<ScreenShell>
<AppHeader />
<View style={{ flex: 1, padding: spacing.lg, justifyContent: "center" }}>
<Text accessibilityRole="header" style={styles.title}>Открываем чат…</Text>
{chat.isLoading && <Loading />}
{Boolean(chat.error || bindError) && (
<ErrorNotice
error={chat.error ?? bindError}
retry={() => {
setBindError(undefined);
if (chat.error) void chat.refetch();
else setBindAttempt((attempt) => attempt + 1);
}}
/>
)}
</View>
</ScreenShell>
);
}