Glazzes / react-native-zoom-toolkit

Zoom anything you want! Most complete pinch to zoom utilities for React Native
https://glazzes.github.io/react-native-zoom-toolkit/
MIT License
187 stars 11 forks source link

[Question]: Is there a way to integrate the Gallery Component with react-native-modal? #26

Closed enzobocalon closed 5 months ago

enzobocalon commented 5 months ago

Summary

I've been trying to use it with react-native-modal to achieve the same result as the Twitter/Facebook Gallery, where I can close modal by swiping down. But every time I try to use it I end up having a conflict between swipes. Is there a way to fix it? Or even achieve the result using react-native's own modal? Ty

Currently code, using the example provided

import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Text, View } from 'react-native';
import { useSharedValue } from 'react-native-reanimated';
import { Gallery, type GalleryType } from 'react-native-zoom-toolkit';
import {
  getAssetsAsync,
  requestPermissionsAsync,
  type Asset,
} from 'expo-media-library';

import GalleryImage from './GalleryImage';
import { StyleSheet } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import Modal from 'react-native-modal';

type SizeVector = { width: number; height: number };

const GalleryExample = () => {
  const ref = useRef<GalleryType>(null);

  const [assets, setAssets] = useState<Asset[]>([]);
  const [scales, setScales] = useState<SizeVector[]>([]);
  const [open, setOpen] = useState<boolean>(false);

  const activeIndex = useSharedValue<number>(0);

  const renderItem = useCallback(
    (item: Asset, index: number) => {
      return (
        <GalleryImage asset={item} index={index} activeIndex={activeIndex} />
      );
    },
    [activeIndex]
  );

  useEffect(() => {
    const requestAssets = async () => {
      const { granted } = await requestPermissionsAsync();
      if (granted) {
        const page = await getAssetsAsync({
          first: 100,
          mediaType: 'photo',
          sortBy: 'creationTime',
        });

        const pageScales: SizeVector[] = [];
        for (let asset of page.assets) {
          pageScales.push({ width: asset.width, height: asset.height });
        }

        setAssets(page.assets);
        setScales(pageScales);
      }
    };

    requestAssets();
  }, []);

  if (assets.length === 0 || scales.length === 0) {
    return null;
  }

  return (
    <View style={styles.container}>
      <Text>Open</Text>
      <TouchableOpacity onPress={() => setOpen(true)}>
        <Text>Open</Text>
      </TouchableOpacity>
      <Modal
        isVisible={open}
        style={styles.root}
        onSwipeComplete={() => setOpen(false)}
        onBackButtonPress={() => setOpen(false)}
      >
        <Gallery
          ref={ref}
          data={assets}
          keyExtractor={(item, index) => `${item.uri}-${index}`}
          renderItem={renderItem}
          maxScale={scales}
          onIndexChange={(idx) => {
            activeIndex.value = idx;
          }}
        />
      </Modal>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    flex: 1,
    backgroundColor: '#000000',
    margin: 0,
  },
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'white',
  },
});

export default GalleryExample;
Glazzes commented 5 months ago

This is a problem that raised my attention as mentioned by a reddit user, the problem with swipes is that they are nothing but pan gestures with a set of let's call them "boundaries" and Gesture Handler by being nested within the modal will take a higher priority over the modal's touches.

At this precise moment I can not offer you a solution, however this will be addressed in the next release in the form of a onSwipe property capable of detecting all four directions.

Glazzes commented 4 months ago

Just Released version 2.0.1, give it a try it does have the new onSwipe property you could use for this use case.

enzobocalon commented 4 months ago

Just Released version 2.0.1, give it a try it does the new onSwipe property you could use for this use case.

Working flawless, thank you. Just a question to know if its possible, since I don't know too much of react native. Can I achieve an animation similar to Twitter/Facebook dismiss? When I scroll down it starts to move down and if I scroll pass a threshold, then it finishes the animation and closes?

Again, thank you so much for the new onSwipe property

Glazzes commented 4 months ago

@enzobocalon It's difficult to tell for me as I don't have such applications, if you can provide a video of what's that you're actively trying to achieve I may give you a possible solution if any.

enzobocalon commented 4 months ago

https://github.com/Glazzes/react-native-zoom-toolkit/assets/41443984/9bcd950b-1b3c-49e5-92d2-1b53beea8721

Something like this.

Glazzes commented 4 months ago

I see what you mean, that's definitively a common pattern among mobile apps and sadly for the moment that's something I have never done myself in previous projects in contrast to all the other features the library provides.

It may require some research and experimentation from my part, and at least for the moment I'd like to rest for a while from this library, I'm pretty burn out from all the changes in this latest release, nonetheless this may be doable.

enzobocalon commented 4 months ago

I understand. Again, thank you so much for the changes, specially for the onSwipe prop.

Glazzes commented 3 months ago

Sorry sent you the wrong release, it was 2.1.0, but since it introduced a new bug by accident install 2.1.1 instead.

enzobocalon commented 3 months ago

Working perfect. Thank you so much for your efforts