dpv007 commited on
Commit
435fcda
·
1 Parent(s): 717aeec

fix: gallery row memo caching bug, video native controls overlap, and re-add ImageViewer for photo zooming

Browse files
Files changed (1) hide show
  1. keystone-app/app/(tabs)/index.tsx +41 -33
keystone-app/app/(tabs)/index.tsx CHANGED
@@ -33,7 +33,7 @@ import { useAuth } from '../../components/AuthContext';
33
 
34
  export const TRASHED_ASSETS_KEY = '@trashed_assets';
35
  export const CACHED_ASSETS_KEY = '@cached_assets';
36
-
37
  const { width, height } = Dimensions.get('window');
38
  const NUM_COLUMNS = 4;
39
  const SPACING = 2;
@@ -149,6 +149,7 @@ const GalleryRow = React.memo(({
149
  </View>
150
  );
151
  }, (prev, next) => {
 
152
  if (prev.isSelecting !== next.isSelecting) return false;
153
  // If no selection changes affect this row, we can skip render
154
  const prevSelected = prev.row.map(a => prev.selectedIds.has(a.id));
@@ -737,45 +738,52 @@ export default function PhotosScreen() {
737
  </View>
738
  </TouchableWithoutFeedback>
739
 
740
- {/* Custom swipeable viewer — handles both photos and full-screen video */}
741
- <FlatList
742
- ref={viewerRef}
743
- data={allAssets}
744
- horizontal
745
- pagingEnabled
746
- initialScrollIndex={viewerIndex ?? 0}
747
- getItemLayout={(_, index) => ({ length: width, offset: width * index, index })}
748
- keyExtractor={item => item.id}
749
- showsHorizontalScrollIndicator={false}
750
- onMomentumScrollEnd={(e) => {
751
- const newIndex = Math.round(e.nativeEvent.contentOffset.x / width);
752
- setViewerIndex(newIndex);
753
- setIsPlaying(true);
754
  }}
755
- renderItem={({ item, index }) => {
756
- const isCurrentVideo = item.mediaType === 'video';
757
- return (
758
- <View style={{ width, height: '100%', backgroundColor: '#000', justifyContent: 'center' }}>
759
- {isCurrentVideo ? (
 
 
 
 
 
 
 
 
 
760
  <Video
761
- source={{ uri: item.uri }}
762
- style={{ width, height: '100%' }}
763
  resizeMode={ResizeMode.CONTAIN}
764
- useNativeControls={true}
765
- shouldPlay={isPlaying && viewerIndex === index}
 
766
  onPlaybackStatusUpdate={(status) => {
767
  if (status.isLoaded && status.didJustFinish) setIsPlaying(false);
768
  }}
769
  />
770
- ) : (
771
- <Image
772
- source={{ uri: item.uri }}
773
- style={{ width, height: '100%' }}
774
- contentFit="contain"
775
- cachePolicy="memory-disk"
776
- />
777
- )}
778
- </View>
 
 
779
  );
780
  }}
781
  />
 
33
 
34
  export const TRASHED_ASSETS_KEY = '@trashed_assets';
35
  export const CACHED_ASSETS_KEY = '@cached_assets';
36
+ //https://dpv007-keystone.hf.space
37
  const { width, height } = Dimensions.get('window');
38
  const NUM_COLUMNS = 4;
39
  const SPACING = 2;
 
149
  </View>
150
  );
151
  }, (prev, next) => {
152
+ if (prev.row !== next.row) return false;
153
  if (prev.isSelecting !== next.isSelecting) return false;
154
  // If no selection changes affect this row, we can skip render
155
  const prevSelected = prev.row.map(a => prev.selectedIds.has(a.id));
 
738
  </View>
739
  </TouchableWithoutFeedback>
740
 
741
+ {/* ImageViewer handles zooming for photos and swiping for everything */}
742
+ <ImageViewer
743
+ imageUrls={allAssets.map(a => ({ url: a.uri }))}
744
+ index={viewerIndex || 0}
745
+ onChange={(idx) => {
746
+ if (idx !== undefined) {
747
+ setViewerIndex(idx);
748
+ setIsPlaying(true);
749
+ }
 
 
 
 
 
750
  }}
751
+ enableSwipeDown
752
+ onSwipeDown={() => setViewerIndex(null)}
753
+ renderIndicator={() => <View />}
754
+ renderImage={(props) => {
755
+ const uri = props.source.uri;
756
+ const asset = allAssets.find(a => a.uri === uri);
757
+
758
+ if (asset?.mediaType === 'video') {
759
+ return (
760
+ <View
761
+ style={{ width, height, paddingBottom: 80, justifyContent: 'center' }}
762
+ onStartShouldSetResponder={() => true}
763
+ onResponderTerminationRequest={() => false}
764
+ >
765
  <Video
766
+ source={{ uri: asset.uri }}
767
+ style={{ width: '100%', height: '100%' }}
768
  resizeMode={ResizeMode.CONTAIN}
769
+ useNativeControls
770
+ shouldPlay={allAssets[viewerIndex ?? 0]?.id === asset.id && isPlaying}
771
+ isLooping
772
  onPlaybackStatusUpdate={(status) => {
773
  if (status.isLoaded && status.didJustFinish) setIsPlaying(false);
774
  }}
775
  />
776
+ </View>
777
+ );
778
+ }
779
+
780
+ return (
781
+ <Image
782
+ source={{ uri }}
783
+ style={{ width: '100%', height: '100%' }}
784
+ contentFit="contain"
785
+ cachePolicy="memory-disk"
786
+ />
787
  );
788
  }}
789
  />