admin管理员组

文章数量:1415460

I'm having a error on my apk build of my react native expo application, the error just happens on the apk, I can't reply on the development build. The error just happens specifically at least 5 minutes after I call a action, a function called createEvento on a generic componet for all Events, and close the app and then try to run the action again after 15 minutes, and then the app has this strange error, stills loading in loop.

I could catch the error using the LogCat of Android Studio with the apj running on my apk These two errors

E Unhandled SoftException java.lang.RuntimeException: React Native Instance has already disappeared: requested by Timing at com.facebook.react.bridge.BaseJavaModule.getReactApplicationContextIfActiveOrWarn(BaseJavaModule.java:125) at com.facebook.react.modules.core.TimingModule.access$000(TimingModule.java:22) at com.facebook.react.modules.core.TimingModule$BridgeTimerExecutor.callTimers(TimingModule.java:28) at com.facebook.react.modules.core.JavaTimerManager.createAndMaybeCallTimer(JavaTimerManager.java:345) at com.facebook.react.modules.core.TimingModule.createTimer(TimingModule.java:84) at java.lang.reflect.Method.invoke(Native Method) at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372) at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:146) at com.facebook.jni.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27) at android.os.Looper.loop(Looper.java:246) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:233)

Second error:

E Unhandled SoftException com.facebook.react.bridge.ReactNoCrashSoftException: connectAnimatedNodeToView: Animated node could not be connected to UIManager - uiManager disappeared for tag: 797 at com.facebook.react.animated.NativeAnimatedNodesManager.connectAnimatedNodeToView(NativeAnimatedNodesManager.java:438) at com.facebook.react.animated.NativeAnimatedModule$18.execute(NativeAnimatedModule.java:838) at com.facebook.react.animated.NativeAnimatedModule$ConcurrentOperationQueue.executeBatch(NativeAnimatedModule.java:171) at com.facebook.react.animated.NativeAnimatedModule$3.execute(NativeAnimatedModule.java:365) at com.facebook.react.uimanager.UIViewOperationQueue$UIBlockOperation.execute(UIViewOperationQueue.java:557) at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:910) at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1023) at com.facebook.react.uimanager.UIViewOperationQueue.-$$Nest$mflushPendingBatches(Unknown Source:0) at com.facebook.react.uimanager.UIViewOperationQueue$2.runGuarded(UIViewOperationQueue.java:979) at com.facebook.react.bridge.GuardedRunnable.run(GuardedRunnable.java:29) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8653) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

Code:

import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, TextInput, Alert, AppState, AppStateStatus, AlertButton } from 'react-native';
import * as SecureStore from 'expo-secure-store';
import BackgroundCustomColor from '@/components/Jornada/BackgroundCustomColor';
import { MaterialCommunityIcons, Octicons } from '@expo/vector-icons';
import { ScrollView } from 'react-native-gesture-handler';
import { ConfirmationJourney } from '@/components/Jornada/ConfirmationJourneyBackground';
import { Timer } from '@/components/Jornada/Timer';
import EventoService from '@/services/api/eventosService';
import QRCodeReader from '@/components/QRCodeReader';
import { verificarLiberacaoQRCode } from '@/utils/verifyParametros';
import UsuarioService from '@/services/api/usuarioService';
import Loading from '@/components/Loading';
import AlertService from '@/services/api/alertService';
import { useNavigation } from '@react-navigation/native';
import { NavigationProp } from '@/types/navigation';
import { useEventosDatabase } from '@/database/useEventosDatabase';
import deactivateBackButton from '@/utils/deactivateBackButton';
import DropDownPicker from 'react-native-dropdown-picker';
import { LISTA_VEICULOS_KEY } from '@/constants/consts';
import { IVeiculo } from '@/types/Veiculo';
import { useAuth } from '@/services/auth/AuthContext';

interface EventProps {
    title: string;
    color: string;
    startEvent: string;
    endEvent: string;
    icon: React.ReactNode;
    confirmationIcon: React.ReactNode;
    isRefeicao?: boolean;
    isDirecao?: boolean;
    isAbastecimento?: boolean;
}

export default function Event({ title, color, startEvent, endEvent, icon, confirmationIcon, isRefeicao, isDirecao, isAbastecimento }: EventProps) {
    const navigation = useNavigation<NavigationProp>();
    const { authState } = useAuth();
    const { createEvento, checkIsUltimoEvento, sendDirecaoData, sendAbastecimentoData } = EventoService();
    const { checkTempoMinRefeicao, checkTempoMaxRefeicao, checkDirecaoTempoMax, checkEncerramentoTurno, checkLimiteEncerramentoTurno } = AlertService();
    const [time, setTime] = useState<number>(0);
    const [startTimer, setStartTimer] = useState<boolean>(false);
    const [confirmationBox, setConfirmationBox] = useState(false);

    const { confirmarLeituraQRCode } = UsuarioService();
    const [QRCodeScanned, setQRCodeScanned] = useState<string | null>();
    const [openScanner, setOpenScanner] = useState<boolean>(false);
    const [loading, setLoading] = useState<boolean>(false);

    const [instanteEvento, setInstanteEvento] = useState<number | null>(null);

    // State para Direcao
    const [dataEvento, setDataEvento] = useState<number>();
    const [dataFimEvento, setDataFimEvento] = useState<number>();
    const [hodometroValue, setHodometroValue] = useState<string>();
    const [hodometroInicial, setHodometroInicial] = useState<string>();
    const [hodometroFinal, setHodometroFinal] = useState<string>();
    const [openFirstDropdown, setOpenFirstDropdown] = useState(false);
    const [itemsFirstDropdown, setItemsFirstDropdown] = useState([
        { label: 'Carregando', value: 1 },
        { label: 'Vazio', value: 2 }
    ]);
    const [valueFirstDropdown, setValueFirstDropdown] = useState(itemsFirstDropdown[0].value);

    const [openSecondDropdown, setOpenSecondDropdown] = useState(false);
    const [itemsSecondDropdown, setItemsSecondDropdown] = useState<{ label: string, value: string | number, hodometro: string | number }[]>([]);
    const [valueSecondDropdown, setValueSecondDropdown] = useState<string>();

    // States para Abastecimento
    const [litrosValue, setLitrosValue] = useState<number | null>(null);
    const [valorPorLitroValue, setValorPorLitroValue] = useState<number | null>(null);
    const [valorTotalValue, setValorTotalValue] = useState<number | null>(null);
    const [openDropdown, setOpenDropdown] = useState(false);
    const [itemsDropdown, setItemsDropdown] = useState([
        { label: 'Alcool', value: 'AL' },
        { label: 'Gasolina', value: 'GA' },
        { label: 'Diesel', value: 'DI' }
    ]);
    const [valueDropdown, setValueDropdown] = useState(itemsDropdown[0].value);

    useEffect(() => {
        deactivateBackButton(startTimer);

        checkIsUltimoEvento(startEvent).then((isLastEvento) => {
            if (isLastEvento?.isUltimoEvento) {
                setStartTimer(true);
                setInstanteEvento(isLastEvento.instanteEvento);
            }
        });

        SecureStore.getItemAsync(LISTA_VEICULOS_KEY).then((result) => {
            const veiculosData = JSON.parse(result!);

            setHodometroValue(veiculosData[0].ultimoHodometro.toString() + ".00");

            if (veiculosData) {
                setItemsSecondDropdown(veiculosData?.map((item: IVeiculo) => {
                    return { label: item.placa, value: item.placa, hodometro: item.ultimoHodometro?.toString() };
                }));

                setValueSecondDropdown(veiculosData[0]?.placa);
            }
        }).catch((error) => console.log("Erro ao buscar lista de veiculos", error));
    }, [startTimer]);

    const handleAppStateChange = (nextAppState: AppStateStatus) => {
        if (nextAppState === 'active') {
            console.log('App has come to the foreground!');
            // Reinitialize or refresh any necessary data here
        }
    };

    useEffect(() => {
        const subscription = AppState.addEventListener('change', handleAppStateChange);
        return () => {
            subscription.remove();
        };
    }, []);

    const handleConfirmJourney = async () => {
        try {
            if (!startTimer) {
                setLoading(true);

                setStartTimer(true);
                const res = await createEvento(startEvent);
                setDataEvento(res);

                setInstanteEvento(res);

                if (isDirecao) {
                    setHodometroInicial(hodometroValue);
                    await checkDirecaoTempoMax();
                }

                await checkTempoMaxRefeicao();
                setLoading(false);
            } else if (startTimer) {
                setLoading(true);

                const res = await createEvento(endEvent);

                setStartTimer(false);
                if (isDirecao) {
                    setDataFimEvento(res);
                    setHodometroFinal(hodometroValue);
                }

                // Enviar dados de direcao
                if (isDirecao && valueFirstDropdown && dataEvento && (res || dataFimEvento) && hodometroValue && valueSecondDropdown) {
                    const data = {
                        tipo: valueFirstDropdown,
                        dataEvento: dataEvento,
                        dataFimEvento: dataFimEvento ?? res,
                        hodometroInicial: Number(hodometroInicial),
                        hodometroFinal: Number(hodometroFinal) ?? Number(hodometroValue),
                        placa: valueSecondDropdown,
                        idVeiculo: authState?.user?.listaDeVeiculos.find((item) => item.placa === valueSecondDropdown)?.id!
                    };
                    await sendDirecaoData(data);
                }

                // Enviar dados de abastecimento
                if (isAbastecimento && litrosValue && valorPorLitroValue && valorTotalValue && valueDropdown) {
                    const data = {
                        quantidadeAbastecida: litrosValue,
                        valorDia: valorPorLitroValue,
                        totalAbastecido: valorTotalValue,
                        tipoCombustivel: valueDropdown
                    };
                    await sendAbastecimentoData(data);
                }

                checkEncerramentoTurno();
                checkLimiteEncerramentoTurno();
                setInstanteEvento(null);

                setLoading(false);
                deactivateBackButton();
                navigation.navigate("Jornada");
            }
        } catch (error) {
            console.log("Erro ao confirmar jornada", error);
            setLoading(false);
        }
        setConfirmationBox(false);
    };

    const handleQRCodeConfirmation = async () => {
        if (await verificarLiberacaoQRCode(title)) {
            if (QRCodeScanned) {
                confirmarLeituraQRCode(QRCodeScanned).then((result) => {
                    if (result?.data.codigoRetorno === 1) {
                        setQRCodeScanned(null);

                        setLoading(false);
                        handleConfirmJourney();
                    } else if (result?.data.codigoRetorno === -1) {
                        Alert.alert(result.data.mensagem + " tente novamente!", undefined, [
                            {
                                text: 'OK', onPress: () => {
                                    setOpenScanner(true);
                                }
                            } as AlertButton,
                        ]);
                        setLoading(false);
                        setQRCodeScanned(null);
                        return;
                    }
                }).catch((error) => {
                    console.log("ERROR", error);
                    alert("Ocorreu um erro. Tente novamente!");
                    setQRCodeScanned(null);
                    setOpenScanner(true);
                    return;
                });
            } else {
                setOpenScanner(true);
            }
        } else {
            handleConfirmJourney();
        }
    };

    if (openScanner) return (
        <QRCodeReader
            setCodeScanned={setQRCodeScanned}
            qrCodeValue={QRCodeScanned}
            onCodeScanned={handleQRCodeConfirmation}
            setLoading={setLoading}
            setOpenScanner={setOpenScanner}
        />
    );

    return (
        <View className='flex-1 w-full'>
            {!confirmationBox ? (<BackgroundCustomColor color={color}>
                <ScrollView contentContainerStyle={{ flex: 1 }}>
                    <View className="flex-1 items-center justify-between py-3">

                        <View className='items-center'>
                            <Text className='text-white text-3xl font-bold uppercase'>{title}</Text>

                            {isDirecao && (
                                <View className='mt-3'>
                                    <DropDownPicker
                                        listMode='SCROLLVIEW'
                                        style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                        dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 20 }}
                                        textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                        labelStyle={{ color: "white" }}
                                        badgeTextStyle={{ color: "black" }}
                                        ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                        ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                        placeholder="Seleciono o tipo"
                                        ListEmptyComponent={() => <Text>Nenhum item</Text>}
                                        open={openFirstDropdown}
                                        value={valueFirstDropdown}
                                        items={itemsFirstDropdown}
                                        setOpen={() => {
                                            setOpenFirstDropdown(!openFirstDropdown);
                                            setOpenSecondDropdown(false);
                                        }}
                                        setValue={setValueFirstDropdown}
                                        setItems={setItemsFirstDropdown}
                                    />
                                    {itemsSecondDropdown.length > 0 && (
                                        <DropDownPicker
                                            listMode='SCROLLVIEW'
                                            style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                            dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 10 }}
                                            textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                            labelStyle={{ color: "white" }}
                                            badgeTextStyle={{ color: "black" }}
                                            ListEmptyComponent={() => <Text className='uppercase text-lg font-bold'>Nenhum item</Text>}
                                            ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                            ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                            placeholder="PLACA"
                                            placeholderStyle={{ color: "white" }}
                                            open={openSecondDropdown}
                                            value={valueSecondDropdown ?? null}
                                            items={itemsSecondDropdown}
                                            setOpen={() => {
                                                setOpenSecondDropdown(!openSecondDropdown);
                                                setOpenFirstDropdown(false);
                                            }}
                                            // @ts-ignore
                                            onSelectItem={(item) => setHodometroValue(item.hodometro + ".00")}
                                            setValue={setValueSecondDropdown}
                                            setItems={setItemsSecondDropdown}
                                        />
                                    )}
                                    <TextInput
                                        value={hodometroValue}
                                        onChangeText={(value) => setHodometroValue(value)}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#745419] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='number-pad'
                                        placeholder='Hodômetro' />
                                </View>
                            )}

                            {isAbastecimento && (
                                <View className='mt-3 gap-5'>
                                    <DropDownPicker
                                        listMode='SCROLLVIEW'
                                        style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                        dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 10 }}
                                        textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                        labelStyle={{ color: "white" }}
                                        badgeTextStyle={{ color: "black" }}
                                        ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                        ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                        placeholder=""
                                        open={openDropdown}
                                        value={valueDropdown}
                                        items={itemsDropdown}
                                        setOpen={() => {
                                            setOpenDropdown(!openDropdown);
                                        }}
                                        setValue={setValueDropdown}
                                        setItems={setItemsDropdown}
                                    />

                                    <TextInput
                                        value={litrosValue?.toString()}
                                        onChangeText={(value) => setLitrosValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Litros Combustível' />

                                    <TextInput
                                        value={valorPorLitroValue?.toString()}
                                        onChangeText={(value) => setValorPorLitroValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Valor por Litro' />

                                    <TextInput
                                        value={valorTotalValue?.toString()}
                                        onChangeText={(value) => setValorTotalValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Valor Total' />
                                </View>
                            )}
                        </View>

                        <View className='items-center gap-4'>
                            {icon}
                            <View className='flex-row items-center gap-4'>
                                <Timer handleSetTime={setTime} startTimer={startTimer} actualTime={time} instanteEvento={instanteEvento} />
                            </View>
                            {startTimer ? (
                                <TouchableOpacity style={{ marginBottom: 15 }} onPress={() => {
                                    setConfirmationBox(true);
                                    isRefeicao && checkTempoMinRefeicao();
                                }}>
                                    <View className='bg-red-soft px-12 py-0.5 text-white font-bold text-center self-center rounded-lg flex-col'>
                                        <Text className='text-lg text-white font-bold text-center uppercase'>ENCERRAR</Text>
                                        <Text className='text-xs text-white font-bold text-center uppercase'> {title}</Text>
                                    </View>
                                </TouchableOpacity>
                            ) : (
                                <TouchableOpacity style={{ marginBottom: 15 }} onPress={() => setConfirmationBox(true)}>
                                    <View className='bg-green-lightdark px-12 py-0.5 text-white font-bold text-center self-center rounded-lg flex-col'>
                                        <Text className='text-lg text-white font-bold text-center uppercase'>INICIAR</Text>
                                        <Text className='text-xs text-white font-bold text-center uppercase'> {title}</Text>
                                    </View>
                                </TouchableOpacity>
                            )}
                        </View>
                    </View>
                </ScrollView>
            </BackgroundCustomColor>) : (
                <ConfirmationJourney onConfirm={() => handleQRCodeConfirmation()} onCancel={() => setConfirmationBox(false)}>
                    <ConfirmationJourney.Text>Deseja {time > 0 ? "ENCERRAR" : "INICIAR"} {title}?</ConfirmationJourney.Text>
                    <ConfirmationJourney.Icon>{confirmationIcon}</ConfirmationJourney.Icon>
                </ConfirmationJourney>
            )}
            {loading && <Loading />}
        </View>
    );
}

Video of the error I'm burning out my head to solve this very strange error, any help?

I'm having a error on my apk build of my react native expo application, the error just happens on the apk, I can't reply on the development build. The error just happens specifically at least 5 minutes after I call a action, a function called createEvento on a generic componet for all Events, and close the app and then try to run the action again after 15 minutes, and then the app has this strange error, stills loading in loop.

I could catch the error using the LogCat of Android Studio with the apj running on my apk These two errors

E Unhandled SoftException java.lang.RuntimeException: React Native Instance has already disappeared: requested by Timing at com.facebook.react.bridge.BaseJavaModule.getReactApplicationContextIfActiveOrWarn(BaseJavaModule.java:125) at com.facebook.react.modules.core.TimingModule.access$000(TimingModule.java:22) at com.facebook.react.modules.core.TimingModule$BridgeTimerExecutor.callTimers(TimingModule.java:28) at com.facebook.react.modules.core.JavaTimerManager.createAndMaybeCallTimer(JavaTimerManager.java:345) at com.facebook.react.modules.core.TimingModule.createTimer(TimingModule.java:84) at java.lang.reflect.Method.invoke(Native Method) at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372) at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:146) at com.facebook.jni.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27) at android.os.Looper.loop(Looper.java:246) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:233)

Second error:

E Unhandled SoftException com.facebook.react.bridge.ReactNoCrashSoftException: connectAnimatedNodeToView: Animated node could not be connected to UIManager - uiManager disappeared for tag: 797 at com.facebook.react.animated.NativeAnimatedNodesManager.connectAnimatedNodeToView(NativeAnimatedNodesManager.java:438) at com.facebook.react.animated.NativeAnimatedModule$18.execute(NativeAnimatedModule.java:838) at com.facebook.react.animated.NativeAnimatedModule$ConcurrentOperationQueue.executeBatch(NativeAnimatedModule.java:171) at com.facebook.react.animated.NativeAnimatedModule$3.execute(NativeAnimatedModule.java:365) at com.facebook.react.uimanager.UIViewOperationQueue$UIBlockOperation.execute(UIViewOperationQueue.java:557) at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:910) at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1023) at com.facebook.react.uimanager.UIViewOperationQueue.-$$Nest$mflushPendingBatches(Unknown Source:0) at com.facebook.react.uimanager.UIViewOperationQueue$2.runGuarded(UIViewOperationQueue.java:979) at com.facebook.react.bridge.GuardedRunnable.run(GuardedRunnable.java:29) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8653) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

Code:

import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, TextInput, Alert, AppState, AppStateStatus, AlertButton } from 'react-native';
import * as SecureStore from 'expo-secure-store';
import BackgroundCustomColor from '@/components/Jornada/BackgroundCustomColor';
import { MaterialCommunityIcons, Octicons } from '@expo/vector-icons';
import { ScrollView } from 'react-native-gesture-handler';
import { ConfirmationJourney } from '@/components/Jornada/ConfirmationJourneyBackground';
import { Timer } from '@/components/Jornada/Timer';
import EventoService from '@/services/api/eventosService';
import QRCodeReader from '@/components/QRCodeReader';
import { verificarLiberacaoQRCode } from '@/utils/verifyParametros';
import UsuarioService from '@/services/api/usuarioService';
import Loading from '@/components/Loading';
import AlertService from '@/services/api/alertService';
import { useNavigation } from '@react-navigation/native';
import { NavigationProp } from '@/types/navigation';
import { useEventosDatabase } from '@/database/useEventosDatabase';
import deactivateBackButton from '@/utils/deactivateBackButton';
import DropDownPicker from 'react-native-dropdown-picker';
import { LISTA_VEICULOS_KEY } from '@/constants/consts';
import { IVeiculo } from '@/types/Veiculo';
import { useAuth } from '@/services/auth/AuthContext';

interface EventProps {
    title: string;
    color: string;
    startEvent: string;
    endEvent: string;
    icon: React.ReactNode;
    confirmationIcon: React.ReactNode;
    isRefeicao?: boolean;
    isDirecao?: boolean;
    isAbastecimento?: boolean;
}

export default function Event({ title, color, startEvent, endEvent, icon, confirmationIcon, isRefeicao, isDirecao, isAbastecimento }: EventProps) {
    const navigation = useNavigation<NavigationProp>();
    const { authState } = useAuth();
    const { createEvento, checkIsUltimoEvento, sendDirecaoData, sendAbastecimentoData } = EventoService();
    const { checkTempoMinRefeicao, checkTempoMaxRefeicao, checkDirecaoTempoMax, checkEncerramentoTurno, checkLimiteEncerramentoTurno } = AlertService();
    const [time, setTime] = useState<number>(0);
    const [startTimer, setStartTimer] = useState<boolean>(false);
    const [confirmationBox, setConfirmationBox] = useState(false);

    const { confirmarLeituraQRCode } = UsuarioService();
    const [QRCodeScanned, setQRCodeScanned] = useState<string | null>();
    const [openScanner, setOpenScanner] = useState<boolean>(false);
    const [loading, setLoading] = useState<boolean>(false);

    const [instanteEvento, setInstanteEvento] = useState<number | null>(null);

    // State para Direcao
    const [dataEvento, setDataEvento] = useState<number>();
    const [dataFimEvento, setDataFimEvento] = useState<number>();
    const [hodometroValue, setHodometroValue] = useState<string>();
    const [hodometroInicial, setHodometroInicial] = useState<string>();
    const [hodometroFinal, setHodometroFinal] = useState<string>();
    const [openFirstDropdown, setOpenFirstDropdown] = useState(false);
    const [itemsFirstDropdown, setItemsFirstDropdown] = useState([
        { label: 'Carregando', value: 1 },
        { label: 'Vazio', value: 2 }
    ]);
    const [valueFirstDropdown, setValueFirstDropdown] = useState(itemsFirstDropdown[0].value);

    const [openSecondDropdown, setOpenSecondDropdown] = useState(false);
    const [itemsSecondDropdown, setItemsSecondDropdown] = useState<{ label: string, value: string | number, hodometro: string | number }[]>([]);
    const [valueSecondDropdown, setValueSecondDropdown] = useState<string>();

    // States para Abastecimento
    const [litrosValue, setLitrosValue] = useState<number | null>(null);
    const [valorPorLitroValue, setValorPorLitroValue] = useState<number | null>(null);
    const [valorTotalValue, setValorTotalValue] = useState<number | null>(null);
    const [openDropdown, setOpenDropdown] = useState(false);
    const [itemsDropdown, setItemsDropdown] = useState([
        { label: 'Alcool', value: 'AL' },
        { label: 'Gasolina', value: 'GA' },
        { label: 'Diesel', value: 'DI' }
    ]);
    const [valueDropdown, setValueDropdown] = useState(itemsDropdown[0].value);

    useEffect(() => {
        deactivateBackButton(startTimer);

        checkIsUltimoEvento(startEvent).then((isLastEvento) => {
            if (isLastEvento?.isUltimoEvento) {
                setStartTimer(true);
                setInstanteEvento(isLastEvento.instanteEvento);
            }
        });

        SecureStore.getItemAsync(LISTA_VEICULOS_KEY).then((result) => {
            const veiculosData = JSON.parse(result!);

            setHodometroValue(veiculosData[0].ultimoHodometro.toString() + ".00");

            if (veiculosData) {
                setItemsSecondDropdown(veiculosData?.map((item: IVeiculo) => {
                    return { label: item.placa, value: item.placa, hodometro: item.ultimoHodometro?.toString() };
                }));

                setValueSecondDropdown(veiculosData[0]?.placa);
            }
        }).catch((error) => console.log("Erro ao buscar lista de veiculos", error));
    }, [startTimer]);

    const handleAppStateChange = (nextAppState: AppStateStatus) => {
        if (nextAppState === 'active') {
            console.log('App has come to the foreground!');
            // Reinitialize or refresh any necessary data here
        }
    };

    useEffect(() => {
        const subscription = AppState.addEventListener('change', handleAppStateChange);
        return () => {
            subscription.remove();
        };
    }, []);

    const handleConfirmJourney = async () => {
        try {
            if (!startTimer) {
                setLoading(true);

                setStartTimer(true);
                const res = await createEvento(startEvent);
                setDataEvento(res);

                setInstanteEvento(res);

                if (isDirecao) {
                    setHodometroInicial(hodometroValue);
                    await checkDirecaoTempoMax();
                }

                await checkTempoMaxRefeicao();
                setLoading(false);
            } else if (startTimer) {
                setLoading(true);

                const res = await createEvento(endEvent);

                setStartTimer(false);
                if (isDirecao) {
                    setDataFimEvento(res);
                    setHodometroFinal(hodometroValue);
                }

                // Enviar dados de direcao
                if (isDirecao && valueFirstDropdown && dataEvento && (res || dataFimEvento) && hodometroValue && valueSecondDropdown) {
                    const data = {
                        tipo: valueFirstDropdown,
                        dataEvento: dataEvento,
                        dataFimEvento: dataFimEvento ?? res,
                        hodometroInicial: Number(hodometroInicial),
                        hodometroFinal: Number(hodometroFinal) ?? Number(hodometroValue),
                        placa: valueSecondDropdown,
                        idVeiculo: authState?.user?.listaDeVeiculos.find((item) => item.placa === valueSecondDropdown)?.id!
                    };
                    await sendDirecaoData(data);
                }

                // Enviar dados de abastecimento
                if (isAbastecimento && litrosValue && valorPorLitroValue && valorTotalValue && valueDropdown) {
                    const data = {
                        quantidadeAbastecida: litrosValue,
                        valorDia: valorPorLitroValue,
                        totalAbastecido: valorTotalValue,
                        tipoCombustivel: valueDropdown
                    };
                    await sendAbastecimentoData(data);
                }

                checkEncerramentoTurno();
                checkLimiteEncerramentoTurno();
                setInstanteEvento(null);

                setLoading(false);
                deactivateBackButton();
                navigation.navigate("Jornada");
            }
        } catch (error) {
            console.log("Erro ao confirmar jornada", error);
            setLoading(false);
        }
        setConfirmationBox(false);
    };

    const handleQRCodeConfirmation = async () => {
        if (await verificarLiberacaoQRCode(title)) {
            if (QRCodeScanned) {
                confirmarLeituraQRCode(QRCodeScanned).then((result) => {
                    if (result?.data.codigoRetorno === 1) {
                        setQRCodeScanned(null);

                        setLoading(false);
                        handleConfirmJourney();
                    } else if (result?.data.codigoRetorno === -1) {
                        Alert.alert(result.data.mensagem + " tente novamente!", undefined, [
                            {
                                text: 'OK', onPress: () => {
                                    setOpenScanner(true);
                                }
                            } as AlertButton,
                        ]);
                        setLoading(false);
                        setQRCodeScanned(null);
                        return;
                    }
                }).catch((error) => {
                    console.log("ERROR", error);
                    alert("Ocorreu um erro. Tente novamente!");
                    setQRCodeScanned(null);
                    setOpenScanner(true);
                    return;
                });
            } else {
                setOpenScanner(true);
            }
        } else {
            handleConfirmJourney();
        }
    };

    if (openScanner) return (
        <QRCodeReader
            setCodeScanned={setQRCodeScanned}
            qrCodeValue={QRCodeScanned}
            onCodeScanned={handleQRCodeConfirmation}
            setLoading={setLoading}
            setOpenScanner={setOpenScanner}
        />
    );

    return (
        <View className='flex-1 w-full'>
            {!confirmationBox ? (<BackgroundCustomColor color={color}>
                <ScrollView contentContainerStyle={{ flex: 1 }}>
                    <View className="flex-1 items-center justify-between py-3">

                        <View className='items-center'>
                            <Text className='text-white text-3xl font-bold uppercase'>{title}</Text>

                            {isDirecao && (
                                <View className='mt-3'>
                                    <DropDownPicker
                                        listMode='SCROLLVIEW'
                                        style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                        dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 20 }}
                                        textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                        labelStyle={{ color: "white" }}
                                        badgeTextStyle={{ color: "black" }}
                                        ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                        ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                        placeholder="Seleciono o tipo"
                                        ListEmptyComponent={() => <Text>Nenhum item</Text>}
                                        open={openFirstDropdown}
                                        value={valueFirstDropdown}
                                        items={itemsFirstDropdown}
                                        setOpen={() => {
                                            setOpenFirstDropdown(!openFirstDropdown);
                                            setOpenSecondDropdown(false);
                                        }}
                                        setValue={setValueFirstDropdown}
                                        setItems={setItemsFirstDropdown}
                                    />
                                    {itemsSecondDropdown.length > 0 && (
                                        <DropDownPicker
                                            listMode='SCROLLVIEW'
                                            style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                            dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 10 }}
                                            textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                            labelStyle={{ color: "white" }}
                                            badgeTextStyle={{ color: "black" }}
                                            ListEmptyComponent={() => <Text className='uppercase text-lg font-bold'>Nenhum item</Text>}
                                            ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                            ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                            placeholder="PLACA"
                                            placeholderStyle={{ color: "white" }}
                                            open={openSecondDropdown}
                                            value={valueSecondDropdown ?? null}
                                            items={itemsSecondDropdown}
                                            setOpen={() => {
                                                setOpenSecondDropdown(!openSecondDropdown);
                                                setOpenFirstDropdown(false);
                                            }}
                                            // @ts-ignore
                                            onSelectItem={(item) => setHodometroValue(item.hodometro + ".00")}
                                            setValue={setValueSecondDropdown}
                                            setItems={setItemsSecondDropdown}
                                        />
                                    )}
                                    <TextInput
                                        value={hodometroValue}
                                        onChangeText={(value) => setHodometroValue(value)}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#745419] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='number-pad'
                                        placeholder='Hodômetro' />
                                </View>
                            )}

                            {isAbastecimento && (
                                <View className='mt-3 gap-5'>
                                    <DropDownPicker
                                        listMode='SCROLLVIEW'
                                        style={{ backgroundColor: color, borderColor: "transparent", paddingLeft: 0, zIndex: 1 }}
                                        dropDownContainerStyle={{ borderColor: "transparent", width: '70%', borderRadius: 0, zIndex: 10 }}
                                        textStyle={{ color: "black", fontSize: 20, textTransform: "uppercase" }}
                                        labelStyle={{ color: "white" }}
                                        badgeTextStyle={{ color: "black" }}
                                        ArrowUpIconComponent={() => (<Octicons name="triangle-up" size={24} color="black" />)}
                                        ArrowDownIconComponent={() => (<Octicons name="triangle-down" size={24} color="black" />)}
                                        placeholder=""
                                        open={openDropdown}
                                        value={valueDropdown}
                                        items={itemsDropdown}
                                        setOpen={() => {
                                            setOpenDropdown(!openDropdown);
                                        }}
                                        setValue={setValueDropdown}
                                        setItems={setItemsDropdown}
                                    />

                                    <TextInput
                                        value={litrosValue?.toString()}
                                        onChangeText={(value) => setLitrosValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Litros Combustível' />

                                    <TextInput
                                        value={valorPorLitroValue?.toString()}
                                        onChangeText={(value) => setValorPorLitroValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Valor por Litro' />

                                    <TextInput
                                        value={valorTotalValue?.toString()}
                                        onChangeText={(value) => setValorTotalValue(Number(value))}
                                        className='min-w-[90%] p-1 border-b-[1px] border-b-[#431242] focus:border-b-[#008577] text-2xl text-white uppercase'
                                        placeholderTextColor={"white"}
                                        keyboardType='numeric'
                                        placeholder='Valor Total' />
                                </View>
                            )}
                        </View>

                        <View className='items-center gap-4'>
                            {icon}
                            <View className='flex-row items-center gap-4'>
                                <Timer handleSetTime={setTime} startTimer={startTimer} actualTime={time} instanteEvento={instanteEvento} />
                            </View>
                            {startTimer ? (
                                <TouchableOpacity style={{ marginBottom: 15 }} onPress={() => {
                                    setConfirmationBox(true);
                                    isRefeicao && checkTempoMinRefeicao();
                                }}>
                                    <View className='bg-red-soft px-12 py-0.5 text-white font-bold text-center self-center rounded-lg flex-col'>
                                        <Text className='text-lg text-white font-bold text-center uppercase'>ENCERRAR</Text>
                                        <Text className='text-xs text-white font-bold text-center uppercase'> {title}</Text>
                                    </View>
                                </TouchableOpacity>
                            ) : (
                                <TouchableOpacity style={{ marginBottom: 15 }} onPress={() => setConfirmationBox(true)}>
                                    <View className='bg-green-lightdark px-12 py-0.5 text-white font-bold text-center self-center rounded-lg flex-col'>
                                        <Text className='text-lg text-white font-bold text-center uppercase'>INICIAR</Text>
                                        <Text className='text-xs text-white font-bold text-center uppercase'> {title}</Text>
                                    </View>
                                </TouchableOpacity>
                            )}
                        </View>
                    </View>
                </ScrollView>
            </BackgroundCustomColor>) : (
                <ConfirmationJourney onConfirm={() => handleQRCodeConfirmation()} onCancel={() => setConfirmationBox(false)}>
                    <ConfirmationJourney.Text>Deseja {time > 0 ? "ENCERRAR" : "INICIAR"} {title}?</ConfirmationJourney.Text>
                    <ConfirmationJourney.Icon>{confirmationIcon}</ConfirmationJourney.Icon>
                </ConfirmationJourney>
            )}
            {loading && <Loading />}
        </View>
    );
}

Video of the error https://drive.google/file/d/1r3a8nXSTkm_rePZk_ohVkRJHXM8avngO/view?usp=sharing I'm burning out my head to solve this very strange error, any help?

Share Improve this question edited Feb 26 at 14:11 Carlos Curcino asked Feb 21 at 4:01 Carlos CurcinoCarlos Curcino 691 silver badge7 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

As no one answered this I racked my brains a little more and investigated the CatLog logs and discovered that the problem was a TaskManager for startLocationUpdatesAsync that was initialized inside a component, moving the initialization outside solved it for me.

Tip: Look at the logs, my log didn't have an indication of what it was, but the previous logs showed me what it could be, and the time periods that the error occurred (30 seconds specifically) indicated what it was. Sometimes the log itself can show for example how when the problem is with react-native-reanimated the logs will have a reference to com.swmansion.reanimated

本文标签: