react-native#Pressable JavaScript Examples
The following examples show how to use
react-native#Pressable.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
Progress = ({ progress, bufferedProgress, duration }) => {
// const { progress } = usePlayTimeBuffer()
const theme = useGetter('common', 'theme')
// console.log(progress)
const progressStr = progress + '%'
return (
<View style={styles.progress}>
<View>
<DefaultBar />
<BufferedBar bufferedProgress={bufferedProgress} />
<View style={{ ...styles.progressBar, backgroundColor: theme.secondary30, width: progressStr, position: 'absolute', left: 0, top: 0 }}>
<Pressable style={{ ...styles.progressDot, backgroundColor: theme.secondary10 }}></Pressable>
</View>
</View>
<PreassBar duration={duration} />
{/* <View style={{ ...styles.progressBar, height: '100%', width: progressStr }}><Pressable style={styles.progressDot}></Pressable></View> */}
</View>
)
}
Example #2
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
PreassBar = memo(({ duration }) => {
const { onLayout, ...layout } = useLayout()
const setProgress = useDispatch('player', 'setProgress')
const handlePress = event => {
setProgress(event.nativeEvent.locationX / layout.width * duration)
}
return <Pressable onPress={handlePress} onLayout={onLayout} style={styles.pressBar} />
})
Example #3
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
Progress = ({ progress, bufferedProgress, duration }) => {
// const { progress } = usePlayTimeBuffer()
const theme = useGetter('common', 'theme')
// console.log(progress)
const progressStr = progress + '%'
return (
<View style={styles.progress}>
<View>
<DefaultBar />
<BufferedBar bufferedProgress={bufferedProgress} />
<View style={{ ...styles.progressBar, backgroundColor: theme.secondary30, width: progressStr, position: 'absolute', left: 0, top: 0 }}>
<Pressable style={{ ...styles.progressDot, backgroundColor: theme.secondary10 }}></Pressable>
</View>
</View>
<PreassBar duration={duration} />
{/* <View style={{ ...styles.progressBar, height: '100%', width: progressStr }}><Pressable style={styles.progressDot}></Pressable></View> */}
</View>
)
}
Example #4
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
PreassBar = memo(({ duration }) => {
const { onLayout, ...layout } = useLayout()
const setProgress = useDispatch('player', 'setProgress')
const handlePress = event => {
setProgress(event.nativeEvent.locationX / layout.width * duration)
}
return <Pressable onPress={handlePress} onLayout={onLayout} style={styles.pressBar} />
})
Example #5
Source File: Modals.js From filen-mobile with GNU Affero General Public License v3.0 | 6 votes |
FullscreenLoadingModal = memo(() => {
const fullscreenLoadingModalVisible = useStore(useCallback(state => state.fullscreenLoadingModalVisible))
const setFullscreenLoadingModalVisible = useStore(useCallback(state => state.setFullscreenLoadingModalVisible))
const setFullscreenLoadingModalDismissable = useStore(useCallback(state => state.setFullscreenLoadingModalDismissable))
const fullscreenLoadingModalDismissable = useStore(useCallback(state => state.fullscreenLoadingModalDismissable))
if(!fullscreenLoadingModalVisible){
return null
}
return (
<Pressable style={{
position: "absolute",
height: "100%",
width: "100%",
backgroundColor: "rgba(0, 0, 0, 0.4)",
justifyContent: "center",
alignItems: "center"
}} onPress={() => {
if(fullscreenLoadingModalDismissable){
setFullscreenLoadingModalVisible(false)
setFullscreenLoadingModalDismissable(false)
}
}}>
<ActivityIndicator size={"small"} color="white" />
</Pressable>
)
})
Example #6
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
Progress = ({ progress, bufferedProgress, duration }) => {
// const { progress } = usePlayTimeBuffer()
const theme = useGetter('common', 'theme')
// console.log(progress)
const progressStr = progress + '%'
return (
<View style={styles.progress}>
<View>
<DefaultBar />
<BufferedBar bufferedProgress={bufferedProgress} />
<View style={{ ...styles.progressBar, backgroundColor: theme.secondary30, width: progressStr, position: 'absolute', left: 0, top: 0 }}>
<Pressable style={{ ...styles.progressDot, backgroundColor: theme.secondary10 }}></Pressable>
</View>
</View>
<PreassBar duration={duration} />
{/* <View style={{ ...styles.progressBar, height: '100%', width: progressStr }}><Pressable style={styles.progressDot}></Pressable></View> */}
</View>
)
}
Example #7
Source File: Progress.js From lx-music-mobile with Apache License 2.0 | 6 votes |
PreassBar = memo(({ duration }) => {
const { onLayout, ...layout } = useLayout()
const setProgress = useDispatch('player', 'setProgress')
const handlePress = event => {
setProgress(event.nativeEvent.locationX / layout.width * duration)
}
return <Pressable onPress={handlePress} onLayout={onLayout} style={styles.pressBar} />
})
Example #8
Source File: index.js From react-native-in-app-review with MIT License | 6 votes |
ReviewApp = () => {
const {onReview} = useAppReview();
return (
<View style={styles.MainContainer}>
<Text style={styles.CartExampleTxt}>Cart Page Example</Text>
<View style={styles.containerBtn}>
<Pressable
testID={'RATE-ME'}
onPress={onReview}
style={styles.RateMeBtn}>
<Text style={styles.RateMeTxt}>Checkout</Text>
</Pressable>
</View>
</View>
);
}
Example #9
Source File: Button.js From lx-music-mobile with Apache License 2.0 | 6 votes |
Btn = ({ ripple: propsRipple, children, disabled, style, ...props }, ref) => {
const theme = useGetter('common', 'theme')
const btnRef = useRef()
const ripple = useMemo(() => ({
color: theme.secondary30,
...(propsRipple || {}),
}), [theme, propsRipple])
useImperativeHandle(ref, () => ({
measure(callback) {
if (!btnRef.current) return
btnRef.current.measure(callback)
},
}))
return (
<Pressable android_ripple={ripple} disabled={disabled} style={{ opacity: disabled ? 0.3 : 1, ...style }} {...props} ref={btnRef}>
{children}
</Pressable>
)
}
Example #10
Source File: RenderItemCard.js From rn-animation with MIT License | 5 votes |
AnimatedPressable = Animated.createAnimatedComponent(Pressable)
Example #11
Source File: Tabbar1.js From rn-animation with MIT License | 5 votes |
render () {
const backgroundColor = this.aniamte.interpolate({
inputRange: listTab.map((_, index) => index),
outputRange: listTab.map(item => item.color),
});
return (
<Animated.View style={{
flex: 1,
backgroundColor,
}}>
<StatusBar barStyle={'light-content'}/>
<SafeAreaView/>
<Pressable
style={{ marginHorizontal: MARGIN_wScale }}
onPress={() => this.props.navigation.goBack()}>
<BackArrowSvg
size={wScale(25)}
color={'#fff'}
/>
</Pressable>
<View style={{ flex: 1 }}/>
<View style={{
backgroundColor: '#fff',
borderRadius: BORDER_RADIUS * 2,
alignItems: 'center',
width: SCREEN_WIDTH * 0.85,
alignSelf: 'center',
}}>
<FlatList data={listTab}
contentContainerStyle={{ marginVertical: hScale(15) }}
scrollEnabled={false}
horizontal={true}
renderItem={this._renderItem}
extraData={this.state.indexSelected}
/>
</View>
<SafeAreaView/>
</Animated.View>
);
}
Example #12
Source File: ProcessDownload1.js From rn-animation with MIT License | 5 votes |
ProcessDownload1 = () => {
const [isDownload, setDownload] = useState(false);
const startAnimation = useSharedValue(0);
const downloadAnimationStyle = useAnimatedStyle(() => {
return {
opacity: startAnimation.value,
};
});
const btnAnimationStyle = useAnimatedStyle(() => {
return {
opacity: interpolate(startAnimation.value, [0, 1], [1, 0]),
};
});
const start = useCallback(() => {
setDownload(true);
});
return (
<View
style={{
flex: 1,
backgroundColor: Colors.primary.light,
}}>
<SafeAreaView style={{backgroundColor: Colors.accent.general}} />
<Header title={'Process Download 1'} isColor={true} />
<View
style={[
{
flex: 1,
},
ComponentStyles.parentCenter,
]}>
<Animated.View style={downloadAnimationStyle}>
<Download
timeProcess={TIME}
isDownload={isDownload}
setDownload={setDownload}
cancel={() => {
startAnimation.value = withTiming(0, {
duration: 300,
});
}}
/>
</Animated.View>
</View>
<Animated.View style={[{height: BUTTON_HEIGHT * 2}, btnAnimationStyle]}>
<Pressable
onPress={() => {
startAnimation.value = withTiming(
1,
{
duration: 300,
},
(isFinished) => {
if (isFinished) {
runOnJS(start)();
}
},
);
}}
style={styles.btnActive}>
<Text style={[styles.uploadText, {color: '#fff'}]}>
Create download
</Text>
</Pressable>
</Animated.View>
<SafeAreaView />
</View>
);
}
Example #13
Source File: Login1.js From rn-animation with MIT License | 5 votes |
render () {
return (
<View style={styles.container}>
{this._renderBackDrop()}
{this._renderSquare()}
<Animated.FlatList
contentContainerStyle={{ marginBottom: MARGIN_hScale * 2 }}
data={dummyData.listAnimal}
horizontal={true}
showsHorizontalScrollIndicator={false}
pagingEnabled={true}
renderItem={this._renderItem}
keyExtractor={((item, index) => String(index))}
scrollEventThrottle={16}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { x: this.scrollX } } }],
{ useNativeDriver: false },
)}
/>
<View style={{
flexDirection: 'row',
marginBottom: HEADER_HEIGHT + MARGIN_hScale,
justifyContent: 'center',
}}>
<Pressable style={styles.btnWrapper}
onPress={() => this.props.navigation.goBack()}
>
<Text style={styles.textWrapper}>
Login
</Text>
</Pressable>
<Pressable style={styles.btnWrapper}
onPress={() => this.props.navigation.goBack()}
>
<Text style={styles.textWrapper}>
Create Account
</Text>
</Pressable>
</View>
<Indicator scrollX={this.scrollX}/>
</View>
);
}
Example #14
Source File: CardView3Detial.js From rn-animation with MIT License | 5 votes |
CardView3Detail = ({route, navigation}) => {
return (
<View>
<SharedElement id={`itemPhoto.${route.params.item.key}`}>
<Image
source={route.params.item.source}
style={[
{
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
},
]}
/>
</SharedElement>
<View
style={{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
}}>
<SafeAreaView />
<View
style={{
flexDirection: 'row',
marginHorizontal: MARGIN_wScale,
alignItems: 'center',
}}>
<Pressable onPress={() => navigation.goBack()}>
<BackArrowSvg size={wScale(25)} color={Colors.secondary.light} />
</Pressable>
<Text
style={{
color: Colors.secondary.light,
fontFamily: Fonts.ExtraBold,
fontSize: fontScale(25),
marginHorizontal: MARGIN_wScale,
}}>
{route.params.item.key}
</Text>
</View>
</View>
</View>
);
}
Example #15
Source File: CardView1Detail.js From rn-animation with MIT License | 5 votes |
render () {
const { item } = this.props.route.params;
devLog(item);
return (
<View style={styles.container}>
<View style={{}}>
<SharedElement
id={`item.${item.key}.image`}
>
<Image source={item.source}
style={{
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
}}
/>
</SharedElement>
</View>
<View style={{
marginHorizontal: MARGIN_wScale,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
}}>
<SafeAreaView/>
<Pressable onPress={() => this.props.navigation.goBack()}>
<BackArrowSvg
size={wScale(25)}
color={'#fff'}
/>
</Pressable>
<View style={{ flex: 1 }}/>
<SharedElement
id={`item.${item.key}.text`}
>
<Text style={{
fontSize: fontScale(50),
color: Colors.accent.general,
fontFamily: Fonts.ExtraBold,
}}>
{item.key}
</Text>
</SharedElement>
<SafeAreaView/>
</View>
</View>
);
}
Example #16
Source File: BottomBar.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
BottomBar = memo(({ navigation, route }) => {
const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
const currentRoutes = useStore(useCallback(state => state.currentRoutes))
const [lang, setLang] = useMMKVString("lang", storage)
const netInfo = useStore(useCallback(state => state.netInfo))
const setBottomBarHeight = useStore(useCallback(state => state.setBottomBarHeight))
const [userId, setUserId] = useMMKVNumber("userId", storage)
const [defaultDriveOnly, setDefaultDriveOnly] = useMMKVBoolean("defaultDriveOnly:" + userId, storage)
const [defaultDriveUUID, setDefaultDriveUUID] = useMMKVString("defaultDriveUUID:" + userId, storage)
const parent = getParent(route)
const routeURL = getRouteURL(route)
const baseName = defaultDriveOnly ? defaultDriveUUID : "base"
let currentScreenName = "MainScreen"
let isRecentsScreen = false
let isTrashScreen = false
let isSharedScreen = false
let isPhotosScreen = false
let isFavoritesScreen = false
let isBaseScreen = false
let isOfflineScreen = false
if(typeof currentRoutes == "object"){
if(currentRoutes.length > 0){
const currentRoute = currentRoutes[currentRoutes.length - 1]
currentScreenName = currentRoute.name
isRecentsScreen = (routeURL.indexOf("recents") !== -1)
isTrashScreen = (routeURL.indexOf("trash") !== -1)
isPhotosScreen = (routeURL.indexOf("photos") !== -1)
isFavoritesScreen = (routeURL.indexOf("favorites") !== -1)
isSharedScreen = ((routeURL.indexOf("shared-in") !== -1) || (routeURL.indexOf("shared-out") !== -1) || (routeURL.indexOf("links") !== -1))
isBaseScreen = (routeURL.indexOf(baseName) !== -1)
isOfflineScreen = (routeURL.indexOf("offline") !== -1)
}
}
const canOpenBottomAddActionSheet = currentScreenName == "MainScreen"
&& !isOfflineScreen
&& !isTrashScreen
&& !isFavoritesScreen
&& !isPhotosScreen
&& !isRecentsScreen
&& routeURL.indexOf("shared-in") == -1
&& parent !== "shared-out"
&& parent !== "links"
const showCloud = isBaseScreen
&& !isRecentsScreen
&& !isTrashScreen
&& !isSharedScreen
&& currentScreenName !== "SettingsAccountScreen"
&& currentScreenName !== "LanguageScreen"
&& currentScreenName !== "SettingsAdvancedScreen"
&& currentScreenName !== "CameraUploadScreen"
&& currentScreenName !== "SettingsScreen"
&& currentScreenName !== "TransfersScreen"
&& currentScreenName !== "EventsScreen"
&& currentScreenName !== "EventsInfoScreen"
&& currentScreenName !== "GDPRScreen"
&& currentScreenName !== "InviteScreen"
&& currentScreenName !== "TwoFactorScreen"
&& currentScreenName !== "ChangeEmailPasswordScreen"
const showSettings = currentScreenName == "SettingsScreen"
|| currentScreenName == "LanguageScreen"
|| currentScreenName == "SettingsAccountScreen"
|| currentScreenName == "SettingsAdvancedScreen"
|| currentScreenName == "CameraUploadScreen"
|| currentScreenName == "EventsScreen"
|| currentScreenName == "EventsInfoScreen"
|| isTrashScreen
|| currentScreenName == "GDPRScreen"
|| currentScreenName == "InviteScreen"
|| currentScreenName == "TwoFactorScreen"
|| currentScreenName == "ChangeEmailPasswordScreen"
const showHome = isSharedScreen
|| isRecentsScreen
|| isFavoritesScreen
|| isOfflineScreen
return (
<View style={{
paddingTop: 6,
height: 80,
flexDirection: "row",
justifyContent: "space-between",
borderTopColor: getColor(darkMode, "primaryBorder"),
borderTopWidth: 1
}} onLayout={(e) => setBottomBarHeight(e.nativeEvent.layout.height)}>
<Pressable style={{
alignItems: "center",
width: "20%",
}} onPress={() => {
navigationAnimation({ enable: false }).then(() => {
navigation.current.dispatch(CommonActions.reset({
index: 0,
routes: [
{
name: "MainScreen",
params: {
parent: "recents"
}
}
]
}))
})
}}>
<Ionicon name={showHome ? "home" : "home-outline"} size={22} color={showHome ? "#0A84FF" : (darkMode ? "gray" : "gray")} />
<Text style={{
color: showHome ? "#0A84FF" : (darkMode ? "gray" : "gray"),
fontSize: 10,
marginTop: 3
}}>{i18n(lang, "home")}</Text>
</Pressable>
<Pressable style={{
alignItems: "center",
width: "20%",
}} onPress={() => {
navigationAnimation({ enable: false }).then(() => {
navigation.current.dispatch(CommonActions.reset({
index: 0,
routes: [
{
name: "MainScreen",
params: {
parent: (defaultDriveOnly ? defaultDriveUUID : "base")
}
}
]
}))
})
}}>
<Ionicon name={showCloud ? "cloud" : "cloud-outline"} size={22} color={showCloud ? "#0A84FF" : (darkMode ? "gray" : "gray")} />
<Text style={{
color: showCloud ? "#0A84FF" : (darkMode ? "gray" : "gray"),
fontSize: 10,
marginTop: 3
}}>{i18n(lang, "cloud")}</Text>
</Pressable>
<Pressable style={{
alignItems: "center",
width: "20%",
paddingTop: 2
}} onPress={() => {
if(canOpenBottomAddActionSheet && netInfo.isConnected && netInfo.isInternetReachable){
SheetManager.show("BottomBarAddActionSheet")
}
}}>
<Ionicon name={netInfo.isConnected && netInfo.isInternetReachable ? (canOpenBottomAddActionSheet ? "add-circle-outline" : "close-circle-outline") : "cloud-offline-outline"} size={30} color={netInfo.isConnected && netInfo.isInternetReachable && canOpenBottomAddActionSheet ? darkMode ? "white" : "gray" : darkMode ? "gray" : "lightgray"} />
</Pressable>
<Pressable style={{
alignItems: "center",
width: "20%"
}} onPress={() => {
navigationAnimation({ enable: false }).then(() => {
navigation.current.dispatch(CommonActions.reset({
index: 0,
routes: [
{
name: "MainScreen",
params: {
parent: "photos"
}
}
]
}))
})
}}>
<Ionicon name={isPhotosScreen ? "image" : "image-outline"} size={22} color={isPhotosScreen ? "#0A84FF" : (darkMode ? "gray" : "gray")} />
<Text style={{
color: isPhotosScreen ? "#0A84FF" : (darkMode ? "gray" : "gray"),
fontSize: 10,
marginTop: 3
}}>{i18n(lang, "photos")}</Text>
</Pressable>
<Pressable style={{
alignItems: "center",
width: "20%",
}} onPress={() => {
navigationAnimation({ enable: false }).then(() => {
navigation.current.dispatch(CommonActions.reset({
index: 0,
routes: [
{
name: "SettingsScreen"
}
]
}))
})
}}>
<Ionicon name={showSettings ? "settings" : "settings-outline"} size={22} color={showSettings ? "#0A84FF" : (darkMode ? "gray" : "gray")} />
<Text style={{
color: showSettings ? "#0A84FF" : (darkMode ? "gray" : "gray"),
fontSize: 10,
marginTop: 3
}}>{i18n(lang, "settings")}</Text>
</Pressable>
</View>
)
})
Example #17
Source File: Download.js From rn-animation with MIT License | 4 votes |
Download = ({timeProcess, isDownload, setDownload, cancel}) => {
const processing = useValue(0);
const [percentDownload, setPercentDownload] = useState(0);
const transformProcess = useSharedValue(0);
const clock = new Clock();
const downloading = useValue(DOWNLOAD_STATUS.PAUSED);
useCode(() => {
return call([processing], (process) => {
const percent = Math.round((process / WIDTH_PROCESS) * 100);
setPercentDownload(percent);
});
}, [processing]);
// Control download status
useCode(
() =>
block([
set(
downloading,
isDownload ? DOWNLOAD_STATUS.PROCESS : DOWNLOAD_STATUS.PAUSED,
),
]),
[isDownload],
);
// Control process animation download (PROCESS/PAUSED)
useCode(
() =>
block([
cond(eq(downloading, DOWNLOAD_STATUS.PROCESS), [
runTiming(clock, processing, WIDTH_PROCESS, timeProcess),
]),
cond(eq(downloading, DOWNLOAD_STATUS.PAUSED), [stopClock(clock)]),
// cond(eq(processing, WIDTH_PROCESS), set(processing, 0)),
]),
[],
);
return (
<View style={styles.container}>
<View style={styles.lineWrapper}>
<Line transformProcess={transformProcess} />
</View>
<Animated.View
style={[
styles.processBg,
{
transform: [{translateX: processing}],
},
]}
/>
<View style={styles.processWrapper}>
<View>
<Text style={styles.uploadText}>Uploading 3 files</Text>
<Text style={styles.percentText}>
{`${percentDownload}% • ${(
(timeProcess * (1 - percentDownload / 100)) /
1000
).toFixed(0)} seconds left`}
</Text>
</View>
<View />
<Pressable
onPress={() => {
transformProcess.value = withTiming(isDownload ? 1 : 0, {
duration: 500,
});
if (isDownload) {
setDownload(false);
} else {
setDownload(true);
}
}}>
<CircleIcon>
<Ionicons
name={isDownload ? 'pause' : 'play'}
size={wScale(17)}
color={'#fff'}
/>
</CircleIcon>
</Pressable>
<Pressable
onPress={() => {
downloading.setValue(DOWNLOAD_STATUS.PAUSED);
processing.setValue(0);
setDownload(false);
cancel();
}}>
<CircleIcon>
<Fontisto name={'close-a'} size={wScale(12)} color={'#fff'} />
</CircleIcon>
</Pressable>
{/*<AntDesign name={'arrowsalt'} size={wScale(20)}*/}
{/* color={Colors.primary.light}/>*/}
</View>
</View>
);
}
Example #18
Source File: HomeScreen.js From hero with MIT License | 4 votes |
HomeScreen = ({ navigation }) => {
const [XMen, popularHeroes, villains] = useContext(HeroesContext);
const [loading, setLoading] = useState(false);
const insets = useSafeAreaInsets();
const scrollY = new Animated.Value(0);
const translateY = scrollY.interpolate({
inputRange: [40, 100 + insets.top],
outputRange: [40, insets.top - 100],
extrapolate: "clamp",
});
const search = async (item) => {
try {
setLoading(true);
const searchResponse = await fetch(
`https://superheroapi.com/api/${api.key}/${item.id}/`
);
const characterResponse = await fetch(
`https://comicvine.gamespot.com/api/characters/?api_key=${apiComicVine.key}&filter=name:${item.title},publisher${item.publisher}&field_list=deck,publisher,first_appeared_in_issue&format=json`
);
const hero = await searchResponse.json();
const characterInfo = await characterResponse.json();
summary = characterInfo.results[0].deck;
firstIssue = characterInfo.results[0].first_appeared_in_issue;
publisher = characterInfo.results[0].publisher.name;
const firstComicResponse = await fetch(
`https://comicvine.gamespot.com/api/issue/4000-${firstIssue.id}/?api_key=${apiComicVine.key}&format=json`
);
const firstComicInfo = await firstComicResponse.json();
firstIssueURL = firstComicInfo.results.image.original_url;
navigation.navigate("Character", {
hero: hero,
image: item.image,
// publisher: item.publisher,
comicPicture: comicPicture,
summary: summary,
firstIssue: firstIssue,
firstIssueURL: firstIssueURL,
publisher: publisher,
});
// setLoading(false);
} catch (error) {
console.error(error);
setLoading(false);
}
};
const _renderItem = ({ item, index }) => {
return (
<Pressable
key={index}
style={({ pressed }) => [
styles.heroCard,
{ opacity: pressed ? 0.8 : 1.0 },
]}
style={styles.heroCard}
>
<TouchableScale
delayPressIn={50}
activeScale={0.9}
tension={160}
friction={2}
onPress={() => {
search(item);
// console.log(item.id);
}}
>
<MaskedView
maskElement={
<SquircleView
style={StyleSheet.absoluteFill}
squircleParams={{
cornerRadius: 50,
cornerSmoothing: 1,
fillColor: "pink",
}}
/>
}
>
<Image
source={item.image}
resizeMode="cover"
PlaceholderContent={<ActivityIndicator />}
style={{
width: "100%",
height: "100%",
}}
/>
<View
style={{
flex: 1,
position: "absolute",
bottom: -5,
padding: 30,
width: "100%",
justifyContent: "center",
borderRadius: 20,
}}
>
<Text
style={{
...styles.h4,
fontSize: 20,
color: COLORS.beige,
textShadowColor: "rgba(0, 0, 0, 1)",
textShadowOffset: { width: -1, height: 1 },
textShadowRadius: 5,
}}
>
{item.title}
</Text>
</View>
</MaskedView>
</TouchableScale>
</Pressable>
// </Animated.View>
);
};
useEffect(() => {
setLoading(false);
}, []);
useEffect(() => {
const unsubscribe = navigation.addListener("blur", () => {
// Screen was blurred
// Do something
setLoading(false);
});
return unsubscribe;
}, [navigation]);
return (
<>
<View style={styles.appContainer}>
<StatusBar
translucent
backgroundColor="transparent"
barStyle="dark-content"
/>
<SafeAreaView
style={{
flex: 1,
width: Dimensions.get("window").width,
}}
forceInset={{ top: "always" }}
>
<Animated.View
style={{
position: "absolute",
top: 0,
left: 0,
right: 0,
zIndex: 10,
height: 100,
transform: [{ translateY: translateY }],
}}
>
<View style={styles.header}>
<View style={{ justifyContent: "flex-end" }}>
<Text style={styles.appTitle}>hero</Text>
<Text
style={{ ...styles.p, fontSize: 7, marginTop: -2, left: -2 }}
>
the Superhero Encyclopedia
</Text>
</View>
</View>
</Animated.View>
<ScrollView
contentContainerStyle={{
paddingBottom: 80,
width: Dimensions.get("window").width,
}}
onScroll={(e) => {
scrollY.setValue(e.nativeEvent.contentOffset.y);
}}
scrollEventThrottle={6}
>
<View style={styles.popularContainer}>
<View
style={{
flexDirection: "row",
flex: 1,
justifyContent: "flex-start",
alignItems: "center",
}}
>
<Text
style={{
...styles.h4,
marginBottom: 10,
paddingLeft: 15,
}}
>
Popular
</Text>
<Icon
name="trending-up"
type="feather"
color={COLORS.navy}
size={30}
iconStyle={{ bottom: 2, paddingLeft: 5 }}
/>
</View>
<Carousel
data={popularHeroes}
sliderWidth={380}
itemWidth={260}
renderItem={_renderItem}
loop={true}
inactiveSlideShift={0}
inactiveSlideOpacity={Platform.OS === "ios" ? 0.5 : 1}
/>
</View>
<View style={styles.heroContainer}>
<View
style={{
flexDirection: "row",
flex: 1,
justifyContent: "flex-start",
alignItems: "center",
}}
>
<Text
style={{
...styles.h4,
marginBottom: 10,
paddingLeft: 15,
}}
>
Villians
</Text>
<Icon
name="emoticon-devil"
type="material-community"
color={COLORS.navy}
size={30}
iconStyle={{ bottom: 2, paddingLeft: 5, opacity: 0.9 }}
/>
</View>
<Carousel
data={villains}
sliderWidth={380}
itemWidth={260}
renderItem={_renderItem}
loop={true}
// inactiveSlideShift={-24}
inactiveSlideOpacity={Platform.OS === "ios" ? 0.5 : 1}
/>
</View>
<View style={styles.heroContainer}>
<Text
style={{
...styles.h4,
marginBottom: 10,
paddingHorizontal: 15,
}}
>
X-Men
</Text>
<Carousel
data={XMen}
sliderWidth={380}
itemWidth={260}
renderItem={_renderItem}
loop={true}
// inactiveSlideShift={-24}
inactiveSlideOpacity={Platform.OS === "ios" ? 0.5 : 1}
/>
</View>
</ScrollView>
{/* )} */}
<LinearGradient
colors={[COLORS.beige, "#ffffff00"]}
style={styles.scrollGradient}
locations={[0, 1]}
pointerEvents={"none"}
/>
</SafeAreaView>
</View>
{loading === true ? (
<Modal statusBarTranslucent={true}>
<View
style={{
backgroundColor: COLORS.beige,
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
}}
>
<Progress.CircleSnail
color={[COLORS.navy, COLORS.orange, COLORS.blue]}
size={80}
thickness={10}
style={styles.loading}
strokeCap={"round"}
/>
<Text
style={{
...styles.p,
fontFamily: "Flame-Regular",
marginTop: -15,
left: 3,
}}
>
loading...
</Text>
</View>
</Modal>
) : null}
</>
);
}
Example #19
Source File: TwoFactorScreen.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
TwoFactorScreen = memo(({ navigation, route }) => {
const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
const [lang, setLang] = useMMKVString("lang", storage)
const [enabled, setEnabled] = useState(route.params.accountSettings.twoFactorEnabled == 1 ? true : false)
const [accountSettings, setAccountSettings] = useState(route.params.accountSettings)
const dimensions = useStore(useCallback(state => state.dimensions))
const [twoFactorKey, setTwoFactorKey] = useState("")
const setDisable2FATwoFactorDialogVisible = useStore(useCallback(state => state.setDisable2FATwoFactorDialogVisible))
console.log(route.params)
return (
<KeyboardAvoidingView behavior="position">
<View style={{
flexDirection: "row",
justifyContent: "flex-start",
backgroundColor: darkMode ? "black" : "white"
}}>
<TouchableOpacity style={{
marginTop: Platform.OS == "ios" ? 17 : 4,
marginLeft: 15,
}} onPress={() => navigation.goBack()}>
<Ionicon name="chevron-back" size={24} color={darkMode ? "white" : "black"}></Ionicon>
</TouchableOpacity>
<Text style={{
color: darkMode ? "white" : "black",
fontWeight: "bold",
fontSize: 24,
marginLeft: 10,
marginTop: Platform.OS == "ios" ? 15 : 0
}}>
{i18n(lang, "twoFactorAuthentication")}
</Text>
</View>
<View style={{
height: "100%",
width: "100%",
backgroundColor: darkMode ? "black" : "white"
}}>
{
enabled ? (
<>
<SettingsGroup>
<SettingsButtonLinkHighlight onPress={() => {
Alert.alert(i18n(lang, "disable2FA"), i18n(lang, "disable2FAInfo"), [
{
text: i18n(lang, "cancel"),
onPress: () => {
return false
},
style: "cancel"
},
{
text: i18n(lang, "ok"),
onPress: () => {
Alert.alert(i18n(lang, "disable2FA"), i18n(lang, "areYouReallySure"), [
{
text: i18n(lang, "cancel"),
onPress: () => {
return false
},
style: "cancel"
},
{
text: i18n(lang, "ok"),
onPress: () => {
setDisable2FATwoFactorDialogVisible(true)
},
style: "default"
}
], {
cancelable: true
})
},
style: "default"
}
], {
cancelable: true
})
}} title={i18n(lang, "disable2FA")} />
</SettingsGroup>
<View style={{
width: "100%",
height: "auto",
paddingLeft: 8,
paddingRight: 8,
marginTop: 5
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<View>
<Text style={{
color: "gray",
fontSize: 11
}}>
{i18n(lang, "disable2FAInfo")}
</Text>
</View>
</View>
</View>
</>
) : (
<>
<View style={{
backgroundColor: "white",
width: "100%",
height: dimensions.screen.width,
justifyContent: "center",
alignItems: "center",
marginTop: 10
}}>
<QRCode
value={"otpauth://totp/" + encodeURIComponent("Filen") + ":" + encodeURIComponent(accountSettings.email) + "?secret=" + encodeURIComponent(accountSettings.twoFactorKey) + "&issuer=" + encodeURIComponent("Filen") + "&digits=6&period=30"}
size={dimensions.screen.width - 60}
backgroundColor="white"
/>
</View>
<SettingsGroup>
<Pressable style={{
width: "100%",
height: "auto"
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<Text style={{
color: darkMode ? "white" : "black",
width: "70%"
}} numberOfLines={1}>
{accountSettings.twoFactorKey}
</Text>
<TouchableOpacity onPress={() => {
Clipboard.setString(accountSettings.twoFactorKey)
showToast({ message: i18n(lang, "copiedToClipboard") })
}}>
<Text style={{
color: "#0A84FF"
}}>
{i18n(lang, "copy")}
</Text>
</TouchableOpacity>
</View>
</Pressable>
</SettingsGroup>
<SettingsGroup>
<Pressable style={{
width: "100%",
height: "auto"
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<TextInput
onChangeText={setTwoFactorKey}
value={twoFactorKey}
placeholder={i18n(lang, "twoFactorPlaceholder")}
placeholderTextColor={"gray"}
autoCapitalize="none"
autoComplete="off"
returnKeyType="done"
autoCorrect={false}
style={{
height: 35,
width: "80%",
maxWidth: "80%",
padding: 5,
backgroundColor: darkMode ? "#222222" : "lightgray",
color: "gray",
borderRadius: 10,
paddingLeft: 10,
paddingRight: 10
}}
/>
<TouchableOpacity onPress={() => {
const code = twoFactorKey.trim()
if(code.length == 0){
return false
}
useStore.setState({ fullscreenLoadingModalVisible: true })
Keyboard.dismiss()
enable2FA({ code }).then(() => {
useStore.setState({ fullscreenLoadingModalVisible: false })
showToast({ message: i18n(lang, "twoFactorEnabledSuccess") })
navigationAnimation({ enable: false }).then(() => {
navigation.dispatch(CommonActions.reset({
index: 1,
routes: [
{
name: "SettingsScreen"
},
{
name: "SettingsAccountScreen"
}
]
}))
})
}).catch((err) => {
console.log(err)
useStore.setState({ fullscreenLoadingModalVisible: false })
showToast({ message: err.toString() })
})
}}>
<Text style={{
color: "#0A84FF",
paddingTop: 7
}}>
{i18n(lang, "enable")}
</Text>
</TouchableOpacity>
</View>
</Pressable>
</SettingsGroup>
</>
)
}
</View>
</KeyboardAvoidingView>
)
})
Example #20
Source File: SettingsScreen.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
SettingsHeader = memo(({ navigation, route, navigationEnabled = true }) => {
const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
const [userId, setUserId] = useMMKVNumber("userId", storage)
const [email, setEmail] = useMMKVString("email", storage)
const [lang, setLang] = useMMKVString("lang", storage)
const netInfo = useStore(useCallback(state => state.netInfo))
const [userInfo, setUserInfo] = useMMKVObject("userInfo:" + userId, storage)
const [userAvatarCached, setUserAvatarCached] = useMMKVString("userAvatarCached:" + userId, storage)
const cacheUserAvatar = useCallback(() => {
if(typeof userInfo !== "undefined"){
if(userInfo.avatarURL.indexOf("https://down.") !== -1){
const avatarName = getFilenameFromPath(userInfo.avatarURL)
if(userAvatarCached !== avatarName){
hasStoragePermissions().then(() => {
getDownloadPath({ type: "misc" }).then(async (path) => {
const avatarPath = path + avatarName
try{
if((await RNFS.exists(avatarPath))){
await RNFS.unlink(avatarPath)
}
}
catch(e){
//console.log(e)
}
RNFS.downloadFile({
fromUrl: userInfo.avatarURL,
toFile: avatarPath
}).promise.then(async () => {
try{
if(typeof userAvatarCached == "string"){
if(userAvatarCached.length > 4){
if((await RNFS.exists(MISC_BASE_PATH + userAvatarCached))){
await RNFS.unlink(MISC_BASE_PATH + userAvatarCached)
}
}
}
}
catch(e){
//console.log(e)
}
setUserAvatarCached(avatarName)
}).catch((err) => {
console.log(err)
})
}).catch((err) => {
console.log(err)
})
}).catch((err) => {
console.log(err)
})
}
else{
if(typeof userAvatarCached == "string"){
if(userAvatarCached.length > 4){
getDownloadPath({ type: "misc" }).then((path) => {
const avatarPath = path + userAvatarCached
RNFS.exists(avatarPath).then((exists) => {
if(!exists){
setUserAvatarCached("")
setTimeout(() => {
cacheUserAvatar()
}, 500)
}
}).catch((err) => {
console.log(err)
})
}).catch((err) => {
console.log(err)
})
}
}
}
}
}
})
useEffect(() => {
updateUserInfo()
}, [])
useEffect(() => {
cacheUserAvatar()
}, [userInfo])
return (
<Pressable style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 10,
paddingTop: 10,
alignItems: "center"
}} onPress={() => {
if(!navigationEnabled){
return false
}
if(!netInfo.isConnected || !netInfo.isInternetReachable){
return showToast({ message: i18n(lang, "deviceOffline") })
}
navigationAnimation({ enable: true }).then(() => {
navigation.dispatch(StackActions.push("SettingsAccountScreen"))
})
}}>
<TouchableOpacity onPress={() => {
if(Platform.OS == "android"){ // @TODO fix android avatar upload
return false
}
if(!netInfo.isConnected || !netInfo.isInternetReachable){
return showToast({ message: i18n(lang, "deviceOffline") })
}
SheetManager.show("ProfilePictureActionSheet")
}}>
<FastImage source={typeof userAvatarCached == "string" && userAvatarCached.length > 4 ? ({ uri: "file://" + MISC_BASE_PATH + userAvatarCached }) : (typeof userInfo !== "undefined" && userInfo.avatarURL.indexOf("https://down.") !== -1 ? { uri: userInfo.avatarURL } : require("../assets/images/appstore.png"))} style={{
width: 50,
height: 50,
borderRadius: 50
}} />
</TouchableOpacity>
<View style={{
width: "79%",
paddingLeft: 15
}}>
<Text style={{
color: darkMode ? "white" : "black",
fontWeight: "bold",
fontSize: 19
}} numberOfLines={1}>
{email}
</Text>
<Text style={{
color: "gray",
fontSize: 12,
marginTop: 1
}} numberOfLines={1}>
{
typeof userInfo !== "undefined" ?
i18n(lang, "settingsHeaderUsage", true, ["__USAGE__", "__MAX__", "__PERCENT__"], [formatBytes(userInfo.storageUsed), formatBytes(userInfo.maxStorage), (isNaN((userInfo.storageUsed / userInfo.maxStorage * 100)) ? 0 : ((userInfo.storageUsed / userInfo.maxStorage * 100) >= 100) ? 100 : (userInfo.storageUsed / userInfo.maxStorage * 100).toFixed(2))])
:
i18n(lang, "settingsHeaderUsage", true, ["__USAGE__", "__MAX__", "__PERCENT__"], [formatBytes(0), formatBytes(0), 0])
}
</Text>
</View>
<Ionicon name="chevron-forward-outline" size={22} color={navigationEnabled ? "gray" : "transparent"} />
</Pressable>
)
})
Example #21
Source File: Item.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
render(){
const { item, index, darkMode } = this.props
const calcedGridSize = calcPhotosGridSize(this.props.photosGridSize)
const windowWidth = ((this.props.dimensions.window.width || window.width) - (this.props.insets.left + this.props.insets.right))
const imageWidthAndHeight = Math.floor(windowWidth / calcedGridSize) - 1.5
return (
<Pressable key={index.toString()} style={{
height: imageWidthAndHeight,
width: imageWidthAndHeight,
margin: 1,
alignItems: "center",
justifyContent: "center"
}} onPress={() => {
DeviceEventEmitter.emit("event", {
type: "item-onpress",
data: item
})
}} onLongPress={() => {
DeviceEventEmitter.emit("event", {
type: "open-item-actionsheet",
data: item
})
}}>
<FastImage source={this.props.hideThumbnails ? getImageForItem(item) : typeof item.thumbnail !== "undefined" ? { uri: "file://" + THUMBNAIL_BASE_PATH + item.thumbnail } : getImageForItem(item)} style={{
width: typeof item.thumbnail !== "undefined" && !this.props.hideThumbnails ? imageWidthAndHeight : 40,
height: typeof item.thumbnail !== "undefined" && !this.props.hideThumbnails ? imageWidthAndHeight : 40,
zIndex: 2
}} onError={() => {
if(typeof item.thumbnail == "string"){
DeviceEventEmitter.emit("event", {
type: "check-thumbnail",
item
})
}
}} />
{
calcPhotosGridSize(this.props.photosGridSize) <= 5 && (
<>
{
item.favorited == 1 && (
<Ionicon name="heart" size={19} color={"white"} style={{
position: "absolute",
bottom: 3,
left: 3,
zIndex: 100
}} />
)
}
{
item.offline && (
<>
<Ionicon name="arrow-down-circle" size={18} color={"green"} style={{
position: "absolute",
top: 3,
right: 2.8,
zIndex: 100
}} />
<View style={{
position: "absolute",
top: 3,
right: 3,
width: 19,
height: 19,
borderRadius: 19,
zIndex: 10,
backgroundColor: "white"
}}></View>
</>
)
}
{
item.selected && (
<>
<Ionicon name="checkmark-circle" size={18} color="#0A84FF" style={{
position: "absolute",
bottom: 2.5,
right: 2.8,
zIndex: 100
}} />
<View style={{
position: "absolute",
bottom: 3,
right: 3,
width: 19,
height: 19,
borderRadius: 19,
zIndex: 10,
backgroundColor: "white"
}}></View>
</>
)
}
</>
)
}
</Pressable>
)
}
Example #22
Source File: Item.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
render(){
const { item, index, darkMode } = this.props
const windowWidth = ((this.props.dimensions.window.width || window.width) - (this.props.insets.left + this.props.insets.right))
return (
<Pressable key={index.toString()} style={{
margin: 2,
backgroundColor: darkMode ? (item.selected ? "#171717" : "black") : (item.selected ? "lightgray" : "white"),
borderRadius: 5,
height: Math.floor(windowWidth / 2) - 19 + 40,
width: Math.floor(windowWidth / 2) - 19,
borderColor: getColor(darkMode, "primaryBorder"),
borderWidth: 1,
marginTop: index <= 1 ? 10 : 0
}} onPress={() => {
DeviceEventEmitter.emit("event", {
type: "item-onpress",
data: item
})
}} onLongPress={() => {
DeviceEventEmitter.emit("event", {
type: "item-onlongpress",
data: item
})
}}>
<View style={{
width: "100%",
height: "100%"
}}>
<View style={{
width: "100%",
height: Math.floor(windowWidth / 2) - 19,
alignItems: "center",
justifyContent: "center"
}}>
{
item.type == "folder" ? (
<Ionicon name="folder" size={40} color={getFolderColor(item.color)} />
) : (
<>
<FastImage source={this.props.hideThumbnails ? getImageForItem(item) : typeof item.thumbnail !== "undefined" ? { uri: "file://" + THUMBNAIL_BASE_PATH + item.thumbnail } : getImageForItem(item)} style={{
width: item.type == "folder" ? 35 : typeof item.thumbnail !== "undefined" && !this.props.hideThumbnails ? "100%" : 35,
height: item.type == "folder" ? 35 : typeof item.thumbnail !== "undefined" && !this.props.hideThumbnails ? "100%" : 35,
borderTopLeftRadius: 4,
borderTopRightRadius: 4
}} onError={() => {
if(typeof item.thumbnail == "string"){
DeviceEventEmitter.emit("event", {
type: "check-thumbnail",
item
})
}
}} />
{
item.favorited == 1 && (
<Ionicon name="heart" size={19} color={"white"} style={{
position: "absolute",
bottom: 3,
left: 3,
zIndex: 100
}} />
)
}
{
item.offline && (
<>
<Ionicon name="arrow-down-circle" size={18} color={"green"} style={{
position: "absolute",
top: 3,
right: 2.8,
zIndex: 100
}} />
<View style={{
position: "absolute",
top: 3,
right: 3,
width: 19,
height: 19,
borderRadius: 19,
zIndex: 10,
backgroundColor: "white"
}}></View>
</>
)
}
{
item.selected && (
<>
<Ionicon name="checkmark-circle" size={18} color="#0A84FF" style={{
position: "absolute",
bottom: 2.5,
right: 2.8,
zIndex: 100
}} />
<View style={{
position: "absolute",
bottom: 3,
right: 3,
width: 19,
height: 19,
borderRadius: 19,
zIndex: 10,
backgroundColor: "white"
}}></View>
</>
)
}
</>
)
}
</View>
<Pressable style={{
width: "100%",
height: "100%",
flexDirection: "row",
alignItems: "flex-start",
justifyContent: "space-between"
}} onPress={() => {
DeviceEventEmitter.emit("event", {
type: "open-item-actionsheet",
data: item
})
}}>
<View style={{
width: "80%",
paddingTop: 5,
paddingLeft: 8
}}>
<Text style={{
color: darkMode ? "white" : "black",
fontWeight: "bold",
fontSize: 11
}} numberOfLines={1}>{this.props.hideFileNames ? i18n(this.props.lang, item.type == "folder" ? "folder" : "file") : item.name}</Text>
<Text style={{
color: darkMode ? "white" : "black",
fontSize: 10,
paddingTop: 1
}} numberOfLines={1}>
{item.date}
</Text>
</View>
<TouchableOpacity style={{
paddingTop: 9,
paddingRight: 5
}} onPress={() => {
DeviceEventEmitter.emit("event", {
type: "open-item-actionsheet",
data: item
})
}}>
<Ionicon name="ellipsis-horizontal-sharp" size={18} color={darkMode ? "white" : "black"} />
</TouchableOpacity>
</Pressable>
</View>
</Pressable>
)
}
Example #23
Source File: InviteScreen.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
InviteScreen = memo(({ navigation, route }) => {
const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
const [lang, setLang] = useMMKVString("lang", storage)
const [isLoading, setIsLoading] = useState(true)
const [accountData, setAccountData] = useState({})
const isMounted = useMountedState()
useEffect(() => {
getAccount().then((data) => {
if(isMounted()){
setAccountData(data)
setIsLoading(false)
}
}).catch((err) => {
console.log(err)
showToast({ message: err.toString() })
})
}, [])
return (
<>
<View style={{
flexDirection: "row",
justifyContent: "flex-start",
backgroundColor: darkMode ? "black" : "white"
}}>
<TouchableOpacity style={{
marginTop: Platform.OS == "ios" ? 17 : 4,
marginLeft: 15,
}} onPress={() => navigation.goBack()}>
<Ionicon name="chevron-back" size={24} color={darkMode ? "white" : "black"}></Ionicon>
</TouchableOpacity>
<Text style={{
color: darkMode ? "white" : "black",
fontWeight: "bold",
fontSize: 24,
marginLeft: 10,
marginTop: Platform.OS == "ios" ? 15 : 0
}}>
{i18n(lang, "invite")}
</Text>
</View>
<ScrollView style={{
height: "100%",
width: "100%",
backgroundColor: darkMode ? "black" : "white"
}}>
{
isLoading ? (
<ActivityIndicator size={"small"} color={darkMode ? "white" : "black"} style={{
marginTop: "70%"
}} />
) : (
<>
<SettingsGroup>
<View style={{
width: "100%",
height: "auto"
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<View>
<Text style={{
color: darkMode ? "white" : "black"
}}>
{i18n(lang, "inviteInfo")}
</Text>
</View>
</View>
</View>
</SettingsGroup>
<SettingsGroup>
<View style={{
width: "100%",
height: "auto"
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<View>
<Text style={{
color: darkMode ? "white" : "black"
}}>
{i18n(lang, "inviteCount")}
</Text>
</View>
<Text style={{
color: darkMode ? "white" : "black"
}}>
{accountData.referCount > accountData.refLimit ? accountData.refLimit : accountData.referCount}/{accountData.refLimit}
</Text>
</View>
</View>
</SettingsGroup>
<SettingsGroup>
<Pressable style={{
width: "100%",
height: "auto"
}} onPress={() => {
Clipboard.setString("https://filen.io/r/" + accountData.refId)
showToast({ message: i18n(lang, "copiedToClipboard") })
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<Text style={{
color: darkMode ? "white" : "black",
width: "70%"
}} numberOfLines={1}>
https://filen.io/r/{accountData.refId}
</Text>
<TouchableOpacity onPress={() => {
Share.share({
message: i18n(lang, "shareRefLinkMessage"),
url: "https://filen.io/r/" + accountData.refId
})
}}>
<Text style={{
color: "#0A84FF"
}}>
{i18n(lang, "share")}
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
Clipboard.setString("https://filen.io/r/" + accountData.refId)
showToast({ message: i18n(lang, "copiedToClipboard") })
}}>
<Text style={{
color: "#0A84FF"
}}>
{i18n(lang, "copy")}
</Text>
</TouchableOpacity>
</View>
</Pressable>
</SettingsGroup>
<View style={{
width: "100%",
height: "auto",
paddingLeft: 8,
paddingRight: 8,
marginTop: 5
}}>
<View style={{
width: "100%",
height: "auto",
flexDirection: "row",
justifyContent: "space-between",
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10
}}>
<View>
<Text style={{
color: "gray",
fontSize: 10
}}>
{i18n(lang, "inviteInfo2")}
</Text>
</View>
</View>
</View>
</>
)
}
</ScrollView>
</>
)
})
Example #24
Source File: ImageViewerScreen.js From filen-mobile with GNU Affero General Public License v3.0 | 4 votes |
ImageViewerScreen = memo(({ navigation, route }) => {
const screenDimensions = Dimensions.get("screen")
const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
const [lang, setLang] = useMMKVString("lang", storage)
const [imagePreviewModalItems, setImagePreviewModalItems] = useState(route.params.items || [])
const [imagePreviewModalIndex, setImagePreviewModalIndex] = useState(route.params.index || 0)
const setCurrentActionSheetItem = useStore(useCallback(state => state.setCurrentActionSheetItem))
const [images, setImages] = useState({})
const [currentName, setCurrentName] = useState("")
const [isZooming, setIsZooming] = useState(false)
const [isSwiping, setIsSwiping] = useState(false)
const zoomLevel = useRef(minZoom)
const thumbnailListRef = useRef()
const listRef = useRef()
const [currentIndex, setCurrentIndex] = useState(imagePreviewModalIndex)
const [showControls, setShowControls] = useState(true)
const insets = useSafeAreaInsets()
const viewRefs = useRef({}).current
const isMounted = useMountedState()
const tapCount = useRef(0)
const tapTimer = useRef(undefined)
const [portrait, setPortrait] = useState(screenDimensions.height >= screenDimensions.width)
const didNavBack = useRef(false)
const currentImagePreviewDownloads = useRef({}).current
const setListScrollAgain = useRef(false)
const imageActionsContainerHeight = new Animated.Value(120)
const imageActionsVisible = useRef(false)
const loadImage = useCallback((image, index) => {
if(!isMounted()){
return false
}
zoomLevel.current = minZoom
setCurrentName(image.file.name)
setCurrentActionSheetItem(image.file)
setCurrentIndex(index)
thumbnailListRef?.current?.scrollToIndex({
animated: true,
index,
viewPosition: 0.5
})
if(setListScrollAgain.current){
setListScrollAgain.current = false
listRef?.current?.scrollToIndex({
animated: false,
index
})
}
const currentImages = {...images}
if(typeof currentImages[image.uuid] == "string"){
return false
}
if(typeof currentImagePreviewDownloads[image.uuid] !== "undefined"){
return false
}
currentImagePreviewDownloads[image.uuid] = true
downloadWholeFileFSStream({
file: image.file
}).then((path) => {
delete currentImagePreviewDownloads[image.uuid]
if(!isMounted()){
return false
}
generateItemThumbnail({
item: image.file,
skipInViewCheck: true,
callback: (err, thumbPath) => {
if(!isMounted()){
return false
}
if(!err && typeof thumbPath == "string"){
updateItemThumbnail(image.file, thumbPath)
}
return setImages(prev => ({
...prev,
[image.uuid]: path
}))
}
})
}).catch((err) => {
delete currentImagePreviewDownloads[image.uuid]
console.log(err)
return showToast({ message: err.toString() })
})
})
const onViewableItemsChangedRef = useRef(useCallback(({ viewableItems }) => {
const indexItem = viewableItems[viewableItems.length - 1]
if(typeof indexItem !== "object"){
return false
}
if(typeof indexItem.item !== "object"){
return false
}
loadImage(indexItem.item, indexItem.index)
}))
const updateItemThumbnail = useCallback((item, path) => {
if(typeof path !== "string"){
return false
}
if(path.length < 4){
return false
}
if(isMounted()){
setImagePreviewModalItems(prev => [...prev.map(mapItem => mapItem.file.uuid == item.uuid && typeof mapItem.thumbnail == "undefined" ? {...mapItem, thumbnail: item.uuid + ".jpg" } : mapItem)])
}
})
const viewabilityConfigRef = useRef({
minimumViewTime: 0,
viewAreaCoveragePercentThreshold: 95,
viewAreaCoveragePercentThreshold: 95,
waitForInteraction: false
})
useEffect(() => {
if(!isMounted()){
return false
}
setShowControls(isZooming)
}, [isZooming])
useEffect(() => {
if(imagePreviewModalItems.length == 0){
return navigation.goBack()
}
if(Platform.OS == "ios"){
setStatusBarStyle(true)
}
if(Platform.OS == "android"){
hideNavigationBar()
StatusBar.setHidden(true)
}
if(typeof imagePreviewModalItems[imagePreviewModalIndex] !== "undefined"){
setTimeout(() => {
loadImage(imagePreviewModalItems[imagePreviewModalIndex], imagePreviewModalIndex)
}, 50)
}
const dimensionsListener = Dimensions.addEventListener("change", ({ screen }) => {
if(!isMounted()){
return false
}
setPortrait(screen.height >= screen.width)
})
return () => {
dimensionsListener.remove()
if(Platform.OS == "ios"){
setStatusBarStyle(darkMode)
setTimeout(() => setStatusBarStyle(darkMode), 500)
setTimeout(() => setStatusBarStyle(darkMode), 1000)
}
if(Platform.OS == "android"){
showNavigationBar()
StatusBar.setHidden(false)
}
}
}, [])
const renderImage = useCallback((item, index) => {
const image = item
if(typeof image.thumbnail !== "string"){
return (
<View
key={image.uuid}
style={{
width: screenDimensions.width,
height: screenDimensions.height
}}
>
<ActivityIndicator size={"small"} color={"white"} style={{
margin: "auto",
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0
}} />
</View>
)
}
return (
<ReactNativeZoomableView
key={image.uuid}
ref={(ref) => viewRefs[image.uuid] = ref}
maxZoom={3}
minZoom={minZoom}
zoomStep={2}
initialZoom={minZoom}
bindToBorders={true}
contentWidth={screenDimensions.width}
contentHeight={screenDimensions.height}
style={{
width: screenDimensions.width,
height: screenDimensions.height
}}
onZoomBefore={(e, state, view) => {
setIsZooming(view.zoomLevel > 1)
zoomLevel.current = view.zoomLevel
}}
onZoomAfter={(e, state, view) => {
setIsZooming(view.zoomLevel > 1)
zoomLevel.current = view.zoomLevel
if(view.zoomLevel <= 1.05){
listRef?.current?.scrollToIndex({
animated: false,
index
})
thumbnailListRef?.current?.scrollToIndex({
animated: false,
index,
viewPosition: 0.5
})
}
}}
onShiftingBefore={(e, state, view) => {
setIsZooming(view.zoomLevel > 1)
zoomLevel.current = view.zoomLevel
}}
onShiftingAfter={(e, state, view) => {
setIsZooming(view.zoomLevel > 1)
if((view.distanceTop >= 50 || view.distanceBottom >= 50) && !didNavBack.current && zoomLevel.current <= 1 && !isSwiping && !isZooming){
didNavBack.current = true
navigation.goBack()
return true
}
zoomLevel.current = view.zoomLevel
}}
captureEvent={true}
>
<Pressable
onPress={() => {
if(isSwiping){
return false
}
tapCount.current += 1
if(tapCount.current >= 2){
if(zoomLevel.current >= 1.01){
viewRefs[image.uuid]?.zoomTo(1)
zoomLevel.current = 1
setIsZooming(false)
}
else{
viewRefs[image.uuid]?.zoomTo(2)
zoomLevel.current = 2
setIsZooming(true)
}
tapCount.current = 0
return clearTimeout(tapTimer.current)
}
clearTimeout(tapTimer.current)
tapTimer.current = setTimeout(() => {
if(tapCount.current >= 2){
if(zoomLevel.current >= 2){
viewRefs[image.uuid]?.zoomTo(1)
zoomLevel.current = 1
setIsZooming(false)
}
else{
viewRefs[image.uuid]?.zoomTo(2)
zoomLevel.current = 2
setIsZooming(true)
}
}
else{
setShowControls(prev => !prev)
}
tapCount.current = 0
}, 300)
}}
>
<>
<ImageBackground
source={{
uri: decodeURIComponent("file://" + THUMBNAIL_BASE_PATH + image.thumbnail)
}}
resizeMode="contain"
style={{
width: screenDimensions.width,
height: screenDimensions.height
}}
>
{
typeof images[image.uuid] == "string" && (
<Image
source={{
uri: decodeURIComponent(images[image.uuid].startsWith("file://") ? images[image.uuid] : "file://" + images[image.uuid])
}}
resizeMode="contain"
style={{
width: screenDimensions.width,
height: screenDimensions.height
}}
/>
)
}
</ImageBackground>
{
typeof images[image.uuid] !== "string" && (
<ActivityIndicator size={"small"} color={"white"} style={{
margin: "auto",
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0
}} />
)
}
</>
</Pressable>
</ReactNativeZoomableView>
)
})
const renderThumb = useCallback((item, index) => {
const image = item
return (
<View
style={{
width: 30,
height: 50
}}
>
<TouchableOpacity
key={image.uuid}
style={{
width: 30,
height: 50,
backgroundColor: "transparent",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "center"
}}
onPress={async () => {
try{
await viewRefs[imagePreviewModalItems[currentIndex].uuid]?.zoomTo(1)
}
catch(e){
console.log(e)
}
setListScrollAgain.current = true
thumbnailListRef?.current?.scrollToIndex({
animated: false,
index,
viewPosition: 0.5
})
listRef?.current?.scrollToOffset({
animated: false,
offset: screenDimensions.width * index + 1
})
loadImage(imagePreviewModalItems[index], index)
}}
>
{
typeof image.thumbnail !== "string" ? (
<Image
source={getImageForItem(image.file)}
resizeMode="cover"
style={{
width: 25,
height: 35,
marginTop: 2.5,
marginLeft: 2.5
}}
/>
) : (
<Image
source={{
uri: decodeURIComponent("file://" + THUMBNAIL_BASE_PATH + image.thumbnail)
}}
resizeMode="cover"
style={{
width: 30,
height: 40
}}
/>
)
}
<View style={{
backgroundColor: currentIndex == index ? "gray" : "transparent",
width: 15,
height: 5,
borderRadius: 20
}}></View>
</TouchableOpacity>
</View>
)
})
return (
<View style={{
backgroundColor: "black",
height: screenDimensions.height,
width: screenDimensions.width,
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0
}}>
<View style={{
opacity: showControls ? 0 : 1,
flexDirection: "row",
height: "auto",
width: screenDimensions.width,
justifyContent: "space-between",
alignItems: "center",
position: "absolute",
top: 0,
zIndex: showControls ? 0 : 1000,
backgroundColor: "rgba(0, 0, 0, 0.6)",
paddingLeft: 10,
paddingRight: 15,
paddingTop: Platform.OS == "android" ? (insets.top + 5) : ((!portrait ? 10 : insets.top) + 5),
paddingBottom: 10,
marginTop: 0
}}>
<View style={{
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center"
}}>
<TouchableOpacity style={{
marginTop: Platform.OS == "android" ? 1 : 0,
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center"
}} hitSlop={{
top: 10,
left: 10,
bottom: 10,
right: 10
}} onPress={() => {
navigationAnimation({ enable: true }).then(() => {
navigation.goBack()
})
}}>
<Ionicon name="chevron-back" size={24} color={"white"}></Ionicon>
</TouchableOpacity>
<Text numberOfLines={1} style={{
color: "white",
width: "93%",
fontSize: 17,
paddingLeft: 10,
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
fontWeight: "bold"
}}>
{currentName}
</Text>
</View>
<View style={{
display: "none"
}}>
<TouchableOpacity style={{
marginTop: Platform.OS == "android" ? 1 : 0
}} hitSlop={{
top: 10,
left: 10,
bottom: 10,
right: 10
}} onPress={() => {
imageActionsVisible.current = !imageActionsVisible.current
Animated.timing( // Animate over time
imageActionsContainerHeight, // The animated value to drive, this would be a new Animated.Value(0) object.
{
toValue: imageActionsVisible.current ? 300 : 120, // Animate the value
duration: 100, // Make it take a while
useNativeDriver: false
}
).start()
}}>
<Ionicon name="ellipsis-horizontal-sharp" size={24} color={"white"}></Ionicon>
</TouchableOpacity>
</View>
</View>
<FlatList
style={{
position: "absolute",
width: screenDimensions.width,
height: screenDimensions.height,
zIndex: 10
}}
ref={listRef}
data={imagePreviewModalItems}
initialScrollIndex={currentIndex}
renderItem={({ item, index }) => {
return renderImage(item, index)
}}
key={portrait ? "portrait" : "landscape"}
extraData={portrait ? "portrait" : "landscape"}
keyExtractor={(item, index) => item.uuid}
windowSize={3}
initialNumToRender={1}
horizontal={true}
bounces={true}
getItemLayout={(data, index) => ({ length: screenDimensions.width, offset: screenDimensions.width * index, index })}
scrollEnabled={!isZooming}
pagingEnabled={true}
onViewableItemsChanged={onViewableItemsChangedRef?.current}
viewabilityConfig={viewabilityConfigRef?.current}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
onScrollBeginDrag={() => setIsSwiping(true)}
onScrollEndDrag={() => setIsSwiping(false)}
removeClippedSubviews={false}
/>
<Animated.View
style={{
position: "absolute",
bottom: -30,
width: screenDimensions.width,
height: imageActionsContainerHeight,
zIndex: showControls ? 0 : 10000,
backgroundColor: "rgba(0, 0, 0, 1)",
paddingTop: 1,
paddingBottom: insets.bottom + insets.top,
opacity: showControls ? 0 : 1,
paddingBottom: insets.bottom
}}
>
<FlatList
style={{
position: "absolute",
width: screenDimensions.width,
height: 120,
paddingTop: 3
}}
ref={thumbnailListRef}
data={imagePreviewModalItems}
renderItem={({ item, index }) => {
return renderThumb(item, index)
}}
getItemLayout={(data, index) => ({ length: 30, offset: 30 * index, index })}
keyExtractor={(item, index) => item.uuid}
horizontal={true}
scrollEnabled={true}
bounces={false}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
removeClippedSubviews={false}
/>
<View style={{
marginTop: 60,
borderTopColor: "gray",
borderTopWidth: 1,
opacity: 0
}}>
<View style={{
width: "100%",
height: 45,
flexDirection: "row",
justifyContent: "space-between",
borderBottomColor: "gray",
borderBottomWidth: 1,
paddingLeft: 15,
paddingRight: 15
}}>
<Text style={{
color: "white",
paddingTop: 12
}}>
{i18n(lang, "publicLinkEnabled")}
</Text>
<View style={{
paddingTop: Platform.OS == "ios" ? 6 : 8
}}>
</View>
</View>
</View>
</Animated.View>
</View>
)
})