From de7928168165f3775fe3e9f1e7efd8af1b2d4e15 Mon Sep 17 00:00:00 2001 From: SindreKjelsrud Date: Sat, 5 Jul 2025 14:05:54 +0200 Subject: [PATCH] feat: Add coordinate-converter Signed-off-by: SindreKjelsrud --- app/_layout.tsx | 1 + app/coordinate-converter.tsx | 193 +++++++++++++++++++++++++++++++++++ app/styles.ts | 120 +++++++++++++++++++++- 3 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 app/coordinate-converter.tsx diff --git a/app/_layout.tsx b/app/_layout.tsx index 2608639..46eac57 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -4,6 +4,7 @@ export default function RootLayout() { return ( + ); } diff --git a/app/coordinate-converter.tsx b/app/coordinate-converter.tsx new file mode 100644 index 0000000..a35b32f --- /dev/null +++ b/app/coordinate-converter.tsx @@ -0,0 +1,193 @@ +import { useRouter } from "expo-router"; +import { useCallback, useState } from "react"; +import { + ImageBackground, + KeyboardAvoidingView, + Platform, + ScrollView, + Text, + TextInput, + TouchableOpacity, + View, +} from "react-native"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { styles } from "./styles"; +const router = useRouter(); + +// Define your background image URI +const converterBgImage = { + uri: "https://s1.qwant.com/thumbr/474x296/1/c/30947af0647acb7b3ef1eb2b5697b5dde49d5468269c918e41bb86286b007e/OIP.MpGUIDhV0CzgCK1mQYFbHQHaEo.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.MpGUIDhV0CzgCK1mQYFbHQHaEo%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0", +}; + +export default function CoordinateConverter() { + const [overworldX, setOverworldX] = useState(""); + const [overworldZ, setOverworldZ] = useState(""); + const [netherX, setNetherX] = useState(""); + const [netherZ, setNetherZ] = useState(""); + + const safeParseFloat = (value: string) => { + const num = parseFloat(value); + return isNaN(num) ? undefined : num; + }; + + const convertOWToNether = useCallback( + (xStr: string, zStr: string) => { + const x = safeParseFloat(xStr); + const z = safeParseFloat(zStr); + if (x !== undefined && z !== undefined) { + setNetherX(Math.floor(x / 8).toString()); + setNetherZ(Math.floor(z / 8).toString()); + } else { + setNetherX(""); + setNetherZ(""); + } + }, + [] + ); + + const convertNetherToOW = useCallback( + (xStr: string, zStr: string) => { + const x = safeParseFloat(xStr); + const z = safeParseFloat(zStr); + if (x !== undefined && z !== undefined) { + setOverworldX(Math.floor(x * 8).toString()); + setOverworldZ(Math.floor(z * 8).toString()); + } else { + setOverworldX(""); + setOverworldZ(""); + } + }, + [] + ); + + const handleOverworldXChange = useCallback( + (text: string) => { + setOverworldX(text); + convertOWToNether(text, overworldZ); + }, + [overworldZ, convertOWToNether] + ); + + const handleOverworldZChange = useCallback( + (text: string) => { + setOverworldZ(text); + convertOWToNether(overworldX, text); + }, + [overworldX, convertOWToNether] + ); + + const handleNetherXChange = useCallback( + (text: string) => { + setNetherX(text); + convertNetherToOW(text, netherZ); + }, + [netherZ, convertNetherToOW] + ); + + const handleNetherZChange = useCallback( + (text: string) => { + setNetherZ(text); + convertNetherToOW(netherX, text); + }, + [netherX, convertNetherToOW] + ); + + const handleClear = useCallback(() => { + setOverworldX(""); + setOverworldZ(""); + setNetherX(""); + setNetherZ(""); + }, []); + + return ( + + + + + router.back()} // Correct! + style={styles.backButton} +> + ← Go Back + + + Coordinate Converter + + {/* Overworld Row */} + + Overworld (X, Z) + + + X: + + + + Z: + + + + + + {/* Nether Row */} + + Nether (X, Z) + + + X: + + + + Z: + + + + + + + Clear All + + + + + + + ); +} \ No newline at end of file diff --git a/app/styles.ts b/app/styles.ts index b198bac..dc5a86e 100644 --- a/app/styles.ts +++ b/app/styles.ts @@ -2,11 +2,12 @@ import { StyleSheet } from "react-native"; export const styles = StyleSheet.create({ - container: { + // --- Global / Reusable Styles (or main index page specific) --- + appContainer: { flex: 1, backgroundColor: "#2e2e2e", }, - title: { + mainTitle: { fontSize: 38, fontWeight: "bold", color: "#fff", @@ -50,4 +51,119 @@ export const styles = StyleSheet.create({ textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 3, }, + + // --- Coordinate Converter Specific Styles (Adjusted and New) --- + converterSafeArea: { + flex: 1, + }, + converterBackgroundImage: { + flex: 1, + width: "100%", + height: "100%", + justifyContent: "center", + alignItems: "center", + }, + converterBackgroundOverlay: { + ...StyleSheet.absoluteFillObject, + backgroundColor: "rgba(0, 0, 0, 0.6)", + }, + converterContainer: { + flex: 1, + width: "100%", + }, + converterScrollContent: { + flexGrow: 1, + padding: 20, + alignItems: "center", + width: "100%", + }, + converterTitle: { + fontSize: 28, + fontWeight: "bold", + color: "#fff", + marginBottom: 30, + marginTop: 20, + textShadowColor: "rgba(0, 0, 0, 0.7)", + textShadowOffset: { width: 1, height: 1 }, + textShadowRadius: 3, + }, + dimensionContainer: { + width: "90%", + backgroundColor: "rgba(58, 58, 58, 0.7)", + borderRadius: 10, + borderColor: "#6a5acd", + borderWidth: 2, + padding: 15, + marginBottom: 20, + alignItems: "center", + }, + dimensionTitle: { + color: "#fff", + fontSize: 20, + fontWeight: "bold", + marginBottom: 15, + textShadowColor: "rgba(0, 0, 0, 0.5)", + textShadowOffset: { width: 1, height: 1 }, + textShadowRadius: 2, + }, + coordinatesRow: { + flexDirection: "row", + justifyContent: "space-between", + width: "100%", + }, + coordInputGroup: { + flex: 1, + marginHorizontal: 5, + alignItems: "center", + }, + coordInputLabel: { + color: "#e0e0e0", + fontSize: 16, + marginBottom: 5, + fontWeight: "500", + textShadowColor: "rgba(0, 0, 0, 0.5)", + textShadowOffset: { width: 1, height: 1 }, + textShadowRadius: 2, + }, + coordTextInput: { + backgroundColor: "rgba(58, 58, 58, 0.8)", + color: "#fff", + paddingVertical: 10, + paddingHorizontal: 10, + borderRadius: 8, + fontSize: 18, + borderWidth: 1, + borderColor: "#555", + width: "100%", + textAlign: "center", + }, + + clearButton: { + backgroundColor: "#d32f2f", + paddingVertical: 12, + paddingHorizontal: 25, + borderRadius: 8, + marginTop: 30, + }, + clearButtonText: { + color: "#fff", + fontSize: 16, + fontWeight: "bold", + }, + + backButton: { + alignSelf: "flex-start", + marginTop: 10, + marginBottom: 20, + paddingVertical: 8, + paddingHorizontal: 15, + backgroundColor: "rgba(106, 90, 205, 0.7)", + borderRadius: 8, + marginLeft: 10, + }, + backButtonText: { + color: "#fff", + fontSize: 16, + fontWeight: "bold", + }, }); \ No newline at end of file