Revize 6020775f
Přidáno uživatelem Fantič před více než 1 rok
src/components/item/ItemView.tsx | ||
---|---|---|
1 |
import { Center, Box, VStack, Button, HStack, Text, Image, ScrollView, View, Spacer, Card, Heading, Switch, Flex, ChevronLeftIcon, ChevronRightIcon, Divider, Pressable, CircleIcon, IconButton } from "native-base" |
|
1 |
import { Center, Box, VStack, Button, HStack, Text, Image, ScrollView, View, Spacer, Card, Heading, Switch, Flex, ChevronLeftIcon, ChevronRightIcon, Divider, Pressable, CircleIcon, IconButton, useToast } from "native-base"
|
|
2 | 2 |
import React, { useCallback, useEffect, useState } from "react" |
3 | 3 |
import { Certainty, Item, RelationshipType } from "../../types/item" |
4 | 4 |
import { Note } from "../../types/note" |
... | ... | |
18 | 18 |
import { CertaintyWithColors } from "../../stores/reducers/itemSlice" |
19 | 19 |
import { LeftArrowIcon, RightArrowIcon } from "../general/Icons" |
20 | 20 |
import { ZoomableImage } from "./ZoomableImage" |
21 |
import { InfoToast } from "../toast/InfoToast" |
|
21 | 22 |
|
22 | 23 |
interface ItemDetailProps { |
23 | 24 |
item: Item, |
... | ... | |
29 | 30 |
|
30 | 31 |
const ItemDetail = (props: ItemDetailProps) => { |
31 | 32 |
const item = props.item; |
32 |
|
|
33 |
const toast = useToast(); |
|
33 | 34 |
const [selectedImage, setSelectedImage] = useState<number>(0); |
34 | 35 |
|
35 | 36 |
const [images, setImages] = useState<{ imageUrl: string, title: string }[]>([]); |
... | ... | |
48 | 49 |
: |
49 | 50 |
( |
50 | 51 |
<ScrollView flex="1" paddingLeft={2.5} paddingRight={2.5} marginTop={2.5}> |
52 |
|
|
51 | 53 |
<VStack> |
52 |
<HStack marginLeft={2.5} alignItems={"center"}> |
|
53 |
<VStack flex={1} marginTop={3.5}> |
|
54 |
|
|
55 |
<VStack flex={1} marginTop={3.5} marginLeft={1.5} > |
|
56 |
<HStack alignItems="center" height="auto"> |
|
54 | 57 |
<Text fontSize={13} color="#4D4D4D"> |
55 | 58 |
{item.authorDisplayName ? item.authorDisplayName : item.authorName} |
56 | 59 |
</Text> |
57 |
<Heading marginTop={1} fontSize={18} color="#4D4D4D"> |
|
60 |
<HStack marginRight={0} marginLeft="auto" width={70}> |
|
61 |
<Button disabled={!item.prevItem} padding={1} marginLeft="auto" variant="ghost" size="xs" |
|
62 |
onPress={() => { |
|
63 |
if (item.prevItem) { |
|
64 |
console.log(item.prevItem) |
|
65 |
props.navigation.navigate("Item", { itemId: item.prevItem.toString() }) |
|
66 |
} |
|
67 |
else { |
|
68 |
toast.show({ |
|
69 |
render: ({ |
|
70 |
id |
|
71 |
}) => { |
|
72 |
return <InfoToast text={"No previous item..."} onClose={() => toast.close(id)} />; |
|
73 |
}, |
|
74 |
duration: 3000 |
|
75 |
}); |
|
76 |
} |
|
77 |
}} |
|
78 |
leftIcon={<ChevronLeftIcon size="md" />}> |
|
79 |
</Button> |
|
80 |
<Button disabled={!item.nextItem} marginLeft="auto" padding={1} marginRight={2.5} variant="ghost" size="xs" |
|
81 |
onPress={() => { |
|
82 |
|
|
83 |
if (item.nextItem) { |
|
84 |
props.navigation.navigate("Item", { itemId: item.nextItem.toString() }) |
|
85 |
} |
|
86 |
else { |
|
87 |
toast.show({ |
|
88 |
render: ({ |
|
89 |
//@ts-ignore |
|
90 |
id |
|
91 |
}) => { |
|
92 |
return <InfoToast text={"No next item..."} onClose={() => toast.close(id)} />; |
|
93 |
}, |
|
94 |
duration: 3000 |
|
95 |
}); |
|
96 |
} |
|
97 |
}} |
|
98 |
leftIcon={<ChevronRightIcon size="md" />}> |
|
99 |
</Button> |
|
100 |
</HStack> |
|
101 |
</HStack> |
|
102 |
<HStack alignItems="center" height="auto" marginTop={1}> |
|
103 |
<Heading marginBottom="auto" fontSize={18} color="#4D4D4D"> |
|
58 | 104 |
{item.workName} |
59 | 105 |
</Heading> |
60 |
|
|
61 |
</VStack> |
|
62 |
<Box marginLeft="auto" marginTop={1.5} alignItems={"end"}> {/* marginLeft: "auto" pushes the Box to the right */} |
|
63 |
<Button variant="outline" backgroundColor={"#F4DFAB"} borderRadius={8} size="sm" padding={0.5} paddingLeft={2} paddingRight={2} > |
|
106 |
<Button marginLeft="auto" marginTop="auto" marginRight={2.5} variant="outline" backgroundColor={"#F4DFAB"} borderRadius={8} size="sm" padding={0.5} paddingLeft={2} paddingRight={2} > |
|
64 | 107 |
<Text color="#654B07" fontSize={12}> |
65 | 108 |
{item?.concordances?.[0]?.id} |
66 | 109 |
</Text> |
67 | 110 |
</Button> |
68 |
</Box> |
|
69 |
</HStack> |
|
70 |
|
|
71 |
|
|
72 |
|
|
111 |
</HStack> |
|
112 |
</VStack> |
|
73 | 113 |
|
74 | 114 |
<View marginTop={5} backgroundColor="#F5F4F1" borderRadius={10} borderColor="#F5F4F1" padding={2}> |
75 | 115 |
{item.inventoryItem && |
src/components/item/ZoomableImage.tsx | ||
---|---|---|
1 | 1 |
import React, { useState, useEffect, useRef } from "react"; |
2 | 2 |
|
3 |
import { Flex, Image, Pressable, View } from "native-base"
|
|
3 |
import { Box, Flex, Text, Image, Popover, Pressable, VStack, View, Modal, Overlay } from "native-base"
|
|
4 | 4 |
import { PinchGestureHandler, PanGestureHandler, State } from "react-native-gesture-handler"; |
5 | 5 |
import Animated, { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue } from "react-native-reanimated"; |
6 | 6 |
import Svg, { SvgXml, Path } from "react-native-svg"; |
7 | 7 |
import { FullscreenIcon, ExitfullscreenIcon } from "../general/Icons"; |
8 |
import { Dimensions } from "react-native"; |
|
8 |
import { Button, Dimensions } from "react-native";
|
|
9 | 9 |
|
10 | 10 |
export const ZoomableImage = (props: { size: number, imageUri: string, fullScreen?: boolean }) => { |
11 | 11 |
const DEFAULT_SCALE = 1 |
... | ... | |
91 | 91 |
}); |
92 | 92 |
|
93 | 93 |
|
94 |
console.log(viewSize) |
|
95 |
console.log(fullScreenMode) |
|
94 | 96 |
return ( |
95 |
<View |
|
96 |
// height={viewSize.height} |
|
97 |
width={viewSize.width} |
|
98 |
// @ts-ignore |
|
99 |
style={ |
|
100 |
fullScreenMode ? { |
|
101 |
position: "absolute", |
|
102 |
top: -230, |
|
103 |
left: 0, |
|
104 |
zIndex: 1000, |
|
105 |
backgroundColor: "white", |
|
106 |
} |
|
107 |
: |
|
108 |
{ |
|
109 |
overflow: "hidden", |
|
110 |
} |
|
111 |
} |
|
112 |
borderColor={fullScreenMode ? "light.300" : undefined} |
|
113 |
borderRadius={fullScreenMode ? 10 : 0} |
|
114 |
borderWidth={fullScreenMode ? 0 : 1} |
|
115 |
> |
|
116 |
{/* control panel */} |
|
117 |
<Flex direction="row" alignItems="center" justify="flex-end" style={{ height: 50, width: 100, top: fullScreenMode ? 10 : 0, right: fullScreenMode ? 20 : 15, position: "absolute", zIndex: 5 }}> |
|
118 |
{ |
|
119 |
fullScreenMode && |
|
120 |
<Pressable padding={1.5} backgroundColor={"#654B07"} borderRadius={5} marginRight={-2} onPress={() => setFullScreenMode(false)}> |
|
121 |
<FullscreenIcon color="white" /> |
|
122 |
</Pressable> |
|
123 |
} |
|
124 |
|
|
125 |
</Flex> |
|
126 |
|
|
127 |
<PinchGestureHandler |
|
128 |
ref={pinchRef} |
|
129 |
// @ts-ignore |
|
130 |
onGestureEvent={onGestureEvent} |
|
131 |
simultaneousHandlers={[panRef]}> |
|
132 |
<Animated.View style={[{ flex: 1 }, animatedStyle]}> |
|
133 |
<PanGestureHandler |
|
134 |
ref={panRef} |
|
135 |
simultaneousHandlers={[pinchRef]} |
|
136 |
onGestureEvent={onPanEvent} |
|
137 |
onHandlerStateChange={(nativeEvent: any) => { |
|
138 |
if (nativeEvent.state === State.END) { |
|
139 |
console.log(nativeEvent) |
|
140 |
} |
|
141 |
}} |
|
97 |
<View> |
|
98 |
<Pressable onPress={() => setFullScreenMode(true)}> |
|
99 |
<Image size={viewSize.width} source={{ uri: props.imageUri }} alt="image" resizeMode={"contain"} /> |
|
100 |
</Pressable> |
|
101 |
|
|
102 |
<Modal isOpen={fullScreenMode} onClose={() => setFullScreenMode(false)} size="full"> |
|
103 |
<Box |
|
104 |
flex={1} |
|
105 |
justifyContent="center" |
|
106 |
alignItems="center" |
|
107 |
backgroundColor="transparent" // Make the background transparent |
|
108 |
> |
|
109 |
<Pressable |
|
110 |
position="absolute" |
|
111 |
bottom={20} |
|
112 |
right={0} |
|
113 |
padding={2} |
|
114 |
zIndex={1000} |
|
115 |
onPress={() => setFullScreenMode(false)} |
|
142 | 116 |
> |
143 |
<Animated.View style={[{ |
|
144 |
flex: 1, |
|
145 |
}]}> |
|
146 |
<Pressable onPress={() => console.log("toggle fullscreen image")}> |
|
147 |
<Image size={viewSize.width} source={{uri: props.imageUri}} resizeMode={"contain"} /> |
|
148 |
</Pressable> |
|
149 |
</Animated.View> |
|
150 |
</PanGestureHandler> |
|
151 |
</Animated.View> |
|
152 |
</PinchGestureHandler > |
|
153 |
</View > |
|
117 |
{/* Your close button (you can replace this with an icon) */} |
|
118 |
<Box style={{width: 70, height: 30, backgroundColor:"white", borderRadius: 10}} alignItems={"center"} justifyContent="center"> |
|
119 |
<Text>Close</Text> |
|
120 |
</Box> |
|
121 |
</Pressable> |
|
122 |
<Image |
|
123 |
height={viewSize.height} |
|
124 |
width={viewSize.width} |
|
125 |
alt="image" |
|
126 |
source={{ uri: props.imageUri }} |
|
127 |
resizeMode={"contain"} |
|
128 |
/> |
|
129 |
</Box> |
|
130 |
</Modal> |
|
131 |
</View> |
|
132 |
// <Flex direction="row" alignItems="center" justify="flex-end" style={{ height: 50, width: 100, top: fullScreenMode ? 10 : 0, right: fullScreenMode ? 20 : 15, position: "absolute", zIndex: 5 }}> |
|
133 |
// { |
|
134 |
// fullScreenMode && |
|
135 |
// <Pressable padding={1.5} backgroundColor={"#654B07"} borderRadius={5} marginRight={-2} onPress={() => setFullScreenMode(false)}> |
|
136 |
// <FullscreenIcon color="white" /> |
|
137 |
// </Pressable> |
|
138 |
// } |
|
139 |
|
|
140 |
// </Flex> |
|
154 | 141 |
) |
155 | 142 |
|
156 | 143 |
} |
Také k dispozici: Unified diff
re #10917: ZoomableImage init