From edb49837b3bddc24dd7e55ba3628048450b9170a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 14 Sep 2020 21:59:15 +0200 Subject: [PATCH] Move Pages into standalone files --- App.js | 5 +- Pages.js | 491 +----------------------------------------- pages/HomeScreen.js | 178 +++++++++++++++ pages/QRScreen.js | 130 +++++++++++ pages/SendScreen.js | 169 +++++++++++++++ pages/SettingsPage.js | 41 ++++ 6 files changed, 530 insertions(+), 484 deletions(-) create mode 100644 pages/HomeScreen.js create mode 100644 pages/QRScreen.js create mode 100644 pages/SendScreen.js create mode 100644 pages/SettingsPage.js diff --git a/App.js b/App.js index 8f1ef1ae..0de6e153 100644 --- a/App.js +++ b/App.js @@ -9,7 +9,10 @@ import { NavigationContainer } from "@react-navigation/native"; import { createStackNavigator } from "@react-navigation/stack"; /* Pages */ -import { HomeScreen, QRScreen, SendScreen, SettingsPage } from "./Pages.js"; +import { SendScreen } from "./pages/SendScreen"; +import { QRScreen } from "./pages/QRScreen"; +import { HomeScreen } from "./pages/HomeScreen"; +import { SettingsPage } from "./pages/SettingsPage"; /* App component */ diff --git a/Pages.js b/Pages.js index 2bf68fb6..4012dd2b 100644 --- a/Pages.js +++ b/Pages.js @@ -1,49 +1,28 @@ -import Clipboard from "@react-native-community/clipboard"; -import { BarCodeScanner } from "expo-barcode-scanner"; -import { StatusBar } from "expo-status-bar"; -import React, { useEffect, useState } from "react"; import { - Alert, Dimensions, - Image, - Linking, - Modal, - Platform, - Settings, StyleSheet, - Switch, - Text, - TouchableHighlight, - TouchableOpacity, - useColorScheme, - Vibration, - View, - Keyboard, } from "react-native"; -import { Header, Icon, Input } from "react-native-elements"; -import QRCode from "react-native-qrcode-svg"; /* 3rd party libraries */ import { isURL } from "./functions"; -import { iclipUri } from "./Vars"; /* Function and config */ -const checkError = (msg) => { +export const checkError = (msg) => { return msg.includes("Error: ") || msg.includes("400 Bad Request"); }; -const sleep = (milliseconds) => { +export const sleep = (milliseconds) => { return new Promise((resolve) => setTimeout(resolve, milliseconds)); }; -const imgCheck = (url, inval) => { +export const imgCheck = (url, inval) => { if (inval === "") return false; if (typeof url !== "string") return false; return !!url.match(/\w+\.(jpg|jpeg|gif|png|tiff|bmp)$/gi); }; -const ValidationMsg = (txt) => { +export const ValidationMsg = (txt) => { txt = txt.replace(" ", "").toLowerCase(); const diff = config.codeMaxLength - txt.length; if (txt.match(config.charRegex)) { @@ -57,7 +36,7 @@ const ValidationMsg = (txt) => { } }; -const urlValidation = (url) => { +export const urlValidation = (url) => { url = url.split(" ").join("%20"); url = url.split("<").join(">"); url = url.split(">").join("<"); @@ -71,13 +50,13 @@ const urlValidation = (url) => { // const entireScreenHeight = Dimensions.get("window").height; const entireScreenWidth = Dimensions.get("window").width; -const config = { +export const config = { codeMaxLength: 5, // The code's length has to be always 5 characters charRegex: new RegExp("[^A-Za-z0-9]"), // Only allow ascii characters to be entered as the code }; /* Styles */ -const styles = StyleSheet.create({ +export const styles = StyleSheet.create({ container: { alignItems: "center", // Centered horizontally justifyContent: "center", @@ -105,7 +84,7 @@ const styles = StyleSheet.create({ }); /* Colors and stuff */ -const colors = { +export const colors = { bg: "white", headerBg: "#444444", text: "black", @@ -114,457 +93,3 @@ const colors = { darkHeader: "#333333", lightHeader: "#f4f4f4", }; - -export function HomeScreen({ navigation }) { - /* Variable set */ - const [isLoading, setLoading] = useState(true); // Loading status => only show the responce of the API - // after the request completes - const [data, setData] = useState(""); // Dynamically loaded data from the Interclip REST API - const [text, setText] = useState(""); // The code entered in the - // const [progress, setProgress] = useState(""); - - const colorScheme = useColorScheme(); - - useEffect(() => { - if (text.length === config.codeMaxLength) { - setText(text.replace(" ", "").toLowerCase()); - fetch(`http://uni.hys.cz/includes/get-api?user=${text}`) - .then((response) => response.text()) - .then((json) => setData(json)) - .catch((error) => console.error(error)) - .finally(() => setLoading(false)); - } else { - setLoading(true); - } - }, [text]); - return ( - -
- navigation.navigate("QR")} - type="font-awesome" // The icon is loaded from the font awesome icon library - name="qrcode" // Icon fa-qrcode - color={colorScheme === "dark" ? "white" : "black"} // White color for contrast on the Header - /> - - - Interclip - - - { Platform.OS === "ios" && - navigation.navigate("Settings")} - > - - - } -
- - navigation.navigate("Send")}> - - - setText(text)} - defaultValue={text} - errorStyle={{ color: "red" }} - autoCapitalize="none" - autoFocus={true} - value={text.replace(" ", "").toLowerCase()} - enablesReturnKeyAutomatically={true} - onSubmitEditing={() => { - !isLoading - ? Linking.openURL(data) - : alert( - `No URL set yet, make sure your code is ${config.codeMaxLength} characters long!` - ); - }} - /> - {ValidationMsg(text) && ( - - - {ValidationMsg(text)} - - - )} - - {!isLoading && ( - { - /* Handle functionality, when user presses for a longer period of time */ - /* - Clipboard.setString(data); - alert("Copied to Clipboard!"); - */ - }} - onPress={() => { - Linking.openURL(data); - }} - style={{ - color: checkError(data) - ? colors.light - : colorScheme === "dark" - ? "white" - : colors.text, - backgroundColor: - checkError(data) & !ValidationMsg(text) - ? colors.errorColor - : null, - fontSize: 20, - }} - > - {!ValidationMsg(text) && - (checkError(data) - ? "This code doesn't seem to exist 🤔" - : data)} - - )} - - - -
- ); -} - -export function QRScreen({ navigation }) { - const [hasPermission, setHasPermission] = useState(null); - const [scanned, setScanned] = useState(false); - - useEffect(() => { - (async () => { - const { status } = await BarCodeScanner.requestPermissionsAsync(); - setHasPermission(status === "granted"); - })(); - }, []); - - const colorScheme = useColorScheme(); - - const handleBarCodeScanned = ({ _type, data }) => { - setScanned(true); - - const URLArr = data.split("/"); - const result = URLArr[0] + "//" + URLArr[2]; - - if ( - (result === "https://iclip.netlify.com") | - (result === "https://iclip.netlify.app") | - Settings.get("data") - ) { - Vibration.vibrate(); - data.includes("http") - ? Linking.openURL(data) - : Linking.openURL(`http://${data}`) - .then(() => { - navigation.navigate("Home"); - setScanned(false); - }) - .catch((e) => { - Alert.alert( - "An error has occured", - "This link is probably broken or isn't even a link", - [ - { - text: "OK bro", - onPress: () => { - setScanned(false); - }, - }, - { - text: "Copy the error to clipboard", - onPress: () => { - Clipboard.setString(e); - setScanned(false); - }, - }, - ] - ); - }); - } else if (!isURL(data)) { - Alert.alert("This doesn't look like an URL", "Or it's really weird and I have no idea what you're trying to do", [ - { - text: "OK then", - onPress: () => { - setScanned(false); - }, - }, - ]); - } else { - Alert.alert( - "This doesn't appear to be an Interclip URL", - "Do you still want to open it?", - [ - { - text: "Cancel", - onPress: () => { - setScanned(true); - sleep(1000).then(setScanned(false)); - }, - style: "cancel", - }, - { - text: "Sure", - onPress: () => { - Linking.openURL(data); - setScanned(false); - }, - }, - ] - ); - } - }; - - if (hasPermission === null) { - return Requesting for camera permission; - } - - if (hasPermission === false) { - return No access to camera; - } - - return ( - - - - ); -} - -export function SettingsPage() { - const [isEnabled, setIsEnabled] = useState(); - const toggleSwitch = () => { - setIsEnabled((previousState) => !previousState); - storeData({ data: isEnabled }); - }; - const [data, setData] = useState(Settings.get("data")); - const storeData = (data) => { - data.data = !data.data; - Settings.set(data); - setData(Settings.get("data")); - }; - - const colorScheme = useColorScheme(); - - return ( - - - Open all QR Codes automatically - - - - ); -} - -export function SendScreen({ navigation }) { - /* Variable set */ - const [isLoading, setLoading] = useState(true); // Loading status => only show the responce of the API - // after the request completes - const [data, setData] = useState(""); // Dynamically loaded data from the Interclip REST API - const [text, setText] = useState(""); // The code entered in the - const [modalVisible, setModalVisible] = useState(false); - - const colorScheme = useColorScheme(); - - useEffect(() => { - setText(text.replace(" ", "").toLowerCase()); - fetch(`http://uni.hys.cz/includes/api?url=${text}`) - .then((response) => response.text()) - .then((json) => setData(json)) - .catch((error) => console.error(error)) - .finally(() => setLoading(false)); - - setLoading(true); - }, [text]); - return ( - - - - navigation.navigate("Home")}> - - - setText(text)} - defaultValue={text} - errorStyle={{ color: "red" }} - autoCapitalize="none" - autoFocus={true} - enablesReturnKeyAutomatically={true} - onSubmitEditing={() => { - Keyboard.dismiss; - }} - /> - {urlValidation(text) && ( - - - {urlValidation(text)} - - - )} - - {isLoading ? ( - - ) : ( - { - Linking.openURL(data); - }} - style={{ - color: colorScheme === "dark" ? colors.light : colors.text, - backgroundColor: - checkError(data) & !urlValidation(text) - ? colors.errorColor - : null, - fontSize: 40, - marginLeft: "20%", - }} - > - {!urlValidation(text) && data} - - )} - - { - Alert.alert("Modal has been closed."); - }} - > - - - - { - setModalVisible(!modalVisible); - }} - > - Hide QR Code - - - - - {isURL(text) && ( - { - setModalVisible(true); - }} - size={50} - /> - )} - - - - - ); -} diff --git a/pages/HomeScreen.js b/pages/HomeScreen.js new file mode 100644 index 00000000..3405afa3 --- /dev/null +++ b/pages/HomeScreen.js @@ -0,0 +1,178 @@ +import { StatusBar } from "expo-status-bar"; +import React, { useEffect, useState } from "react"; +import { + Image, + Linking, + Platform, + Text, + TouchableOpacity, + useColorScheme, + View, +} from "react-native"; +import { Header, Icon, Input } from "react-native-elements"; +import { + config, + colors, + styles, + imgCheck, + ValidationMsg, + checkError, +} from "../Pages"; + +export function HomeScreen({ navigation }) { + /* Variable set */ + const [isLoading, setLoading] = useState(true); // Loading status => only show the responce of the API + + // after the request completes + const [data, setData] = useState(""); // Dynamically loaded data from the Interclip REST API + const [text, setText] = useState(""); // The code entered in the + + // const [progress, setProgress] = useState(""); + const colorScheme = useColorScheme(); + + useEffect(() => { + if (text.length === config.codeMaxLength) { + setText(text.replace(" ", "").toLowerCase()); + fetch(`http://uni.hys.cz/includes/get-api?user=${text}`) + .then((response) => response.text()) + .then((json) => setData(json)) + .catch((error) => console.error(error)) + .finally(() => setLoading(false)); + } else { + setLoading(true); + } + }, [text]); + return ( + +
+ navigation.navigate("QR")} + type="font-awesome" // The icon is loaded from the font awesome icon library + name="qrcode" // Icon fa-qrcode + color={colorScheme === "dark" ? "white" : "black"} // White color for contrast on the Header + /> + + + Interclip + + + {Platform.OS === "ios" && ( + navigation.navigate("Settings")} + > + + + )} +
+ + navigation.navigate("Send")}> + + + setText(text)} + defaultValue={text} + errorStyle={{ color: "red" }} + autoCapitalize="none" + autoFocus={true} + value={text.replace(" ", "").toLowerCase()} + enablesReturnKeyAutomatically={true} + onSubmitEditing={() => { + !isLoading + ? Linking.openURL(data) + : alert( + `No URL set yet, make sure your code is ${config.codeMaxLength} characters long!` + ); + }} + /> + {ValidationMsg(text) && ( + + + {ValidationMsg(text)} + + + )} + + {!isLoading && ( + { + /* Handle functionality, when user presses for a longer period of time */ + /* + Clipboard.setString(data); + alert("Copied to Clipboard!"); + */ + }} + onPress={() => { + Linking.openURL(data); + }} + style={{ + color: checkError(data) + ? colors.light + : colorScheme === "dark" + ? "white" + : colors.text, + backgroundColor: + checkError(data) & !ValidationMsg(text) + ? colors.errorColor + : null, + fontSize: 20, + }} + > + {!ValidationMsg(text) && + (checkError(data) + ? "This code doesn't seem to exist 🤔" + : data)} + + )} + + + +
+ ); +} diff --git a/pages/QRScreen.js b/pages/QRScreen.js new file mode 100644 index 00000000..d65c94e2 --- /dev/null +++ b/pages/QRScreen.js @@ -0,0 +1,130 @@ +import Clipboard from "@react-native-community/clipboard"; +import { BarCodeScanner } from "expo-barcode-scanner"; +import React, { useEffect, useState } from "react"; +import { + Alert, + Linking, + Settings, + StyleSheet, + Text, + useColorScheme, + Vibration, + View, +} from "react-native"; +import { isURL } from "../functions"; +import { sleep, styles } from "../Pages"; + +export function QRScreen({ navigation }) { + const [hasPermission, setHasPermission] = useState(null); + const [scanned, setScanned] = useState(false); + + useEffect(() => { + (async () => { + const { status } = await BarCodeScanner.requestPermissionsAsync(); + setHasPermission(status === "granted"); + })(); + }, []); + + const colorScheme = useColorScheme(); + + const handleBarCodeScanned = ({ _type, data }) => { + setScanned(true); + + const URLArr = data.split("/"); + const result = URLArr[0] + "//" + URLArr[2]; + + if ( + (result === "https://iclip.netlify.com") | + (result === "https://iclip.netlify.app") | + Settings.get("data") + ) { + Vibration.vibrate(); + data.includes("http") + ? Linking.openURL(data) + : Linking.openURL(`http://${data}`) + .then(() => { + navigation.navigate("Home"); + setScanned(false); + }) + .catch((e) => { + Alert.alert( + "An error has occured", + "This link is probably broken or isn't even a link", + [ + { + text: "OK bro", + onPress: () => { + setScanned(false); + }, + }, + { + text: "Copy the error to clipboard", + onPress: () => { + Clipboard.setString(e); + setScanned(false); + }, + }, + ] + ); + }); + } else if (!isURL(data)) { + Alert.alert( + "This doesn't look like an URL", + "Or it's really weird and I have no idea what you're trying to do", + [ + { + text: "OK then", + onPress: () => { + setScanned(false); + }, + }, + ] + ); + } else { + Alert.alert( + "This doesn't appear to be an Interclip URL", + "Do you still want to open it?", + [ + { + text: "Cancel", + onPress: () => { + setScanned(true); + sleep(1000).then(setScanned(false)); + }, + style: "cancel", + }, + { + text: "Sure", + onPress: () => { + Linking.openURL(data); + setScanned(false); + }, + }, + ] + ); + } + }; + + if (hasPermission === null) { + return Requesting for camera permission; + } + + if (hasPermission === false) { + return No access to camera; + } + + return ( + + + + ); +} diff --git a/pages/SendScreen.js b/pages/SendScreen.js new file mode 100644 index 00000000..bac35781 --- /dev/null +++ b/pages/SendScreen.js @@ -0,0 +1,169 @@ +import { StatusBar } from "expo-status-bar"; +import React, { useEffect, useState } from "react"; +import { + Alert, + Image, + Linking, + Modal, + Platform, + Text, + TouchableHighlight, + TouchableOpacity, + useColorScheme, + View, + Keyboard, +} from "react-native"; +import { Icon, Input } from "react-native-elements"; +import QRCode from "react-native-qrcode-svg"; +import { isURL } from "../functions"; +import { iclipUri } from "../Vars"; +import { styles, imgCheck, urlValidation, colors, checkError } from "../Pages"; + +export function SendScreen({ navigation }) { + /* Variable set */ + const [isLoading, setLoading] = useState(true); // Loading status => only show the responce of the API + + // after the request completes + const [data, setData] = useState(""); // Dynamically loaded data from the Interclip REST API + const [text, setText] = useState(""); // The code entered in the + const [modalVisible, setModalVisible] = useState(false); + + const colorScheme = useColorScheme(); + + useEffect(() => { + setText(text.replace(" ", "").toLowerCase()); + fetch(`http://uni.hys.cz/includes/api?url=${text}`) + .then((response) => response.text()) + .then((json) => setData(json)) + .catch((error) => console.error(error)) + .finally(() => setLoading(false)); + + setLoading(true); + }, [text]); + return ( + + + + navigation.navigate("Home")}> + + + setText(text)} + defaultValue={text} + errorStyle={{ color: "red" }} + autoCapitalize="none" + autoFocus={true} + enablesReturnKeyAutomatically={true} + onSubmitEditing={() => { + Keyboard.dismiss; + }} + /> + {urlValidation(text) && ( + + + {urlValidation(text)} + + + )} + + {isLoading ? ( + + ) : ( + { + Linking.openURL(data); + }} + style={{ + color: colorScheme === "dark" ? colors.light : colors.text, + backgroundColor: + checkError(data) & !urlValidation(text) + ? colors.errorColor + : null, + fontSize: 40, + marginLeft: "20%", + }} + > + {!urlValidation(text) && data} + + )} + + { + Alert.alert("Modal has been closed."); + }} + > + + + + { + setModalVisible(!modalVisible); + }} + > + Hide QR Code + + + + + {isURL(text) && ( + { + setModalVisible(true); + }} + size={50} + /> + )} + + + + + ); +} diff --git a/pages/SettingsPage.js b/pages/SettingsPage.js new file mode 100644 index 00000000..545ee342 --- /dev/null +++ b/pages/SettingsPage.js @@ -0,0 +1,41 @@ +import React, { useState } from "react"; +import { Settings, Switch, Text, useColorScheme, View } from "react-native"; +import { styles } from "../Pages"; + +export function SettingsPage() { + const [isEnabled, setIsEnabled] = useState(); + const toggleSwitch = () => { + setIsEnabled((previousState) => !previousState); + storeData({ data: isEnabled }); + }; + const [data, setData] = useState(Settings.get("data")); + const storeData = (data) => { + data.data = !data.data; + Settings.set(data); + setData(Settings.get("data")); + }; + + const colorScheme = useColorScheme(); + + return ( + + + Open all QR Codes automatically + + + + ); +}