Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sheet component not opening properly on Android #2344

Closed
therealpurplemana opened this issue Feb 26, 2024 · 1 comment
Closed

Sheet component not opening properly on Android #2344

therealpurplemana opened this issue Feb 26, 2024 · 1 comment

Comments

@therealpurplemana
Copy link

Current Behavior

Current behavior: On Android only, the Sheet component does not trigger an open as expected. It works properly on iOS. If I edit the modal to a "fit" type using HMR, it will sometimes popup on the Android device (while still working on iOS).

Expected Behavior

Expected behavior: Sheet component should popup as expected

Tamagui Version

1.90.8

Platform (Web, iOS, Android)

Android only

Reproduction

import { H1, ScrollView, YStack, Toast, useToastController, Sheet, View, Text, Image, Button } from '@my/ui';
import { useIsFocused } from '@react-navigation/native';
import { X, Aperture } from '@tamagui/lucide-icons'
import { useSupabase } from 'app/utils/supabase/useSupabase';
import React, { useEffect, useState, useRef } from 'react';
import { useRouter } from 'solito/router';
import {
  Camera,
  useCameraDevice,
  useCameraPermission,
  useFrameProcessor,
} from 'react-native-vision-camera'
import { useResizePlugin } from 'vision-camera-resize-plugin'
import { Pressable } from 'react-native'; // or from '@tamagui/core' if it provides a Pressable equivalent

export default function App(): React.ReactNode {

  const supabase = useSupabase()
  const [jwt, setJwt] = useState<string | null>(null);
  const [isActive, setIsActive] = useState(true); // New state to control camera activity
  const isFocused = useIsFocused(); // Use the hook to determine focus status
  const [sheetVisible, setSheetVisible] = useState(false);
  const [resultData, setResultData] = useState([]);

  const handleResponse = (data) => {
    console.log('Handling response:', data); // Add this line to check if the function is called
    setResultData(data);
    setSheetVisible(true);
    console.log("Sheet visible:", sheetVisible)
  };

  useEffect(() => {
    const fetchSession = async () => {
      const session = await supabase.auth.getSession()
      // Assuming session.data.session.access_token exists and is valid
      const accessToken = session.data.session.access_token;
      setJwt(accessToken); // Update the jwt state with the fetched access token
    };
  
    fetchSession();
  }, [supabase]);

  useEffect(() => {
    setIsActive(isFocused); // Set isActive based on the focus status
  }, [isFocused]); // Re-run this effect when isFocused changes

  const { hasPermission, requestPermission } = useCameraPermission()
  const device = useCameraDevice('back')

  const { resize } = useResizePlugin()

  const frameProcessor = useFrameProcessor(
    (frame) => {
      'worklet'
      
      console.log(`Running frame processor`)
      const resized = resize(frame, {
        scale: {
          width: 1280,
          height: 1280,
        },
        pixelFormat: 'rgb',
        dataType: 'uint8',
      })
      console.log("Resized frame")
    },
    []
  )

  React.useEffect(() => {
    requestPermission()
  }, [requestPermission])

  const cameraRef = useRef<Camera>(null);

  const takeAndSendPhoto = async () => {
    if (cameraRef.current) {
      console.log('Taking photo')
      const photo = await cameraRef.current.takePhoto()
      console.log('Photo taken: ', photo)
      sendPhotoToAPI(photo)
    }
  };
  const sendPhotoToAPI = async (photo) => {
    console.log('Sending photo to API');
    const photoUri = photo.path;

    // Use rn-fetch-blob to read the file as base64
    const RNFetchBlob = require('rn-fetch-blob').default;
    RNFetchBlob.fs.readFile(photoUri, 'base64')
      .then((base64Data) => {
        // Construct the request body
        const body = JSON.stringify({
          jwt: jwt, // Pass the JWT here
          image: `data:image/jpeg;base64,${base64Data}`, // Pass the base64 encoded image here
        });
  
        // read image endpoint from EXPO_PUBLIC_PMX_IMAGE_ENDPOINT variable
        const pmx_image_endpoint = process.env.EXPO_PUBLIC_PMX_IMAGE_ENDPOINT || 'your_fallback_endpoint_here';
  
        // Use rn-fetch-blob to send the request
        RNFetchBlob.fetch('POST', pmx_image_endpoint, {
          'Content-Type': 'application/json',
        }, body)
        .then(response => response.json())
        .then(data => {
          console.log('Success:', data);
          handleResponse(data);
        })
        .catch((error) => {
          console.error('Error:', error);
        });
      })
      .catch((error) => {
        console.error('Error reading file as base64:', error);
      });
  };

  const router = useRouter(); // Use this to navigate back

  // Method to handle closing the camera
  const handleCloseCamera = () => {
    setIsActive(false); // Deactivate the camera
    router.push('/'); // Navigate away after deactivating the camera
  };

  const ResultSheet = ({ open, data, onClose }) => {
    const snapPoints = [85, 50, 20]; // Example snap points, adjust based on your UI needs

    return (
      <Sheet
        open={open}
        onOpenChange={setSheetVisible} // This will handle opening and closing of the sheet
        snapPoints={snapPoints}
        modal={true} // Assuming you want the Sheet to behave as a modal
        zIndex={100_000}
        animation="medium"
      >
        <Sheet.Overlay />
        <Sheet.Handle />
        <Sheet.Frame>
          <YStack>
            {data.map((item) => (
              <YStack key={item.id}>
                <Image source={{ uri: item.front_image_url }} style={{ width: 100, height: 100 }} />
                <Text>Name: {item.name}</Text>
                <Text>Set: {item.set}</Text>
              </YStack>
            ))}
            <Button onPress={onClose}>Close</Button>
          </YStack>
        </Sheet.Frame>
      </Sheet>
    );
  };

  return (
    <YStack flex={1} alignItems="center" justifyContent="center">
      {hasPermission && device != null ? (
        <>
        <Camera
          ref={cameraRef}
          device={device}
          style={{ width: '100%', height: '100%' }}
          isActive={isActive}
          pixelFormat="rgb"
          photo={true}
        />
        <Aperture
          size={96}
          color="purple"
          onPress={takeAndSendPhoto}
          style={{
            position: 'absolute',
            left: '50%',
            bottom: '10%',
            transform: [{ translateX: -50 }], // Updated line
            zIndex: 1,
          }}
        />
        <X
          size={48}
          color="purple"
          onPress={handleCloseCamera}
          style={{
            position: 'absolute',
            top: '5%',
            right: '5%',
            zIndex: 2,
          }}
        />
        </>
      ) : (
        <Text>No Camera available.</Text>
      )}
      <ResultSheet open={sheetVisible} data={resultData} onClose={() => setSheetVisible(false)} />
    </YStack>
  )
}

System Info

Tested on Android Pixel 6 device
@therealpurplemana
Copy link
Author

Closing this issue. I implemented the Sheet example and tested natively on iOS and Android (web too). It works as intended. I'm not sure why the above Camera screen isn't working but TBD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant