Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 33 additions & 22 deletions app/(auth)/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@ import { useTheme } from "@/lib/theme/context";
import { BtnText, Button } from "@/components/button";
import { Link, router } from "expo-router";
import { HomeIcon } from "lucide-react-native";
import { StyleSheet, Text, View, useColorScheme, Platform } from "react-native";
import {
StyleSheet,
Text,
View,
useColorScheme,
Platform,
Pressable,
} from "react-native";
import { Image } from "expo-image";
import { Theme } from "@/lib/theme/theme";
import { createT } from "@/i18n";
import { useAppleAuth } from "@/hooks/useAppleAuth";
import * as WebBrowser from "expo-web-browser";
import { BROWSER_OPTS } from "@/lib/web/browserConfig";

export default function Login() {
const { gs, theme } = useTheme();
Expand All @@ -16,12 +25,6 @@ export default function Login() {

const { signInWithApple, loading: appleLoading, error: appleError } = useAppleAuth();

// useEffect(() => {
// router.prefetch("/login/withEmail");
// router.prefetch("/login/withPhoneNumber");
// router.prefetch("/register");
// }, []);

return (
<View style={gs.container}>
<HomeIcon size={48} color={theme.primary} />
Expand Down Expand Up @@ -153,25 +156,33 @@ export default function Login() {
)}

<View>
{/* <Text style={{ fontSize: 12, textAlign: "center", color: theme.text }}>
By continuing, you agree to our{" "}
<Link
href={"/legal/termsOfService"}
style={{ color: theme.primary }}
onPress={() => alert("Terms of Service")}
<Text style={{ fontSize: 12, textAlign: "center", color: theme.text }}>
{t("continuingWith")}{" "}
<Pressable
onPress={() => {
WebBrowser.openBrowserAsync(
"https://mindsofd23b.github.io/Landing-Elysio/termsandconditions/",
BROWSER_OPTS(theme),
);
}}
>
{t("termsOfService")}
</Link>{" "}
<Text style={{ color: theme.primary }}>
{t("termsOfService")}
</Text>
</Pressable>{" "}
{t("and")}{" "}
<Link
href={"/legal/privacyPolicy"}
style={{ color: theme.primary }}
onPress={() => alert("Privacy Policy")}
<Pressable
onPress={() => {
WebBrowser.openBrowserAsync(
"https://mindsofd23b.github.io/Landing-Elysio/privacypolicy/",
BROWSER_OPTS(theme),
);
}}
>
{t("privacyPolicy")}
</Link>
<Text style={{ color: theme.primary }}>{t("privacyPolicy")}</Text>
</Pressable>
.
</Text> */}
</Text>
</View>
</View>
);
Expand Down
14 changes: 7 additions & 7 deletions app/(auth)/update.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { createT } from "@/i18n";
import { View, Text, StyleSheet, Animated, Easing } from "react-native";
import { Settings } from "lucide-react-native";
import { useEffect, useRef } from "react";
import { useTheme } from "@/lib/theme/context";

const t = createT("update");

interface UpdateScreenProps {
duration?: string;
}
Expand Down Expand Up @@ -46,14 +49,11 @@ export default function UpdateScreen({ duration }: UpdateScreenProps) {
<Settings color={theme.primary} />
</Text>
</Animated.View>
<Text style={s.title}>Update in progress</Text>
<Text style={s.body}>
We{"'"}re updating Elysio to bring you new features and improvements. The
app will be back shortly.
</Text>
<Text style={s.title}>{t("title")}</Text>
<Text style={s.body}>{t("body")}</Text>
<View style={s.durationBox}>
<Text style={s.durationLabel}>Estimated time</Text>
<Text style={s.durationValue}>{duration ?? "Unknown"}</Text>
<Text style={s.durationLabel}>{t("estimatedTime")}</Text>
<Text style={s.durationValue}>{duration ?? t("unknown")}</Text>
</View>
</View>
);
Expand Down
40 changes: 22 additions & 18 deletions app/(onboarding)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createT } from "@/i18n";
import { BtnText, Button } from "@/components/button";
import { useTheme } from "@/lib/theme/context";
import { get, store } from "@/utils/store";
Expand All @@ -8,6 +9,8 @@ import { Bell, Heart, Zap } from "lucide-react-native";
import { useEffect, useState } from "react";
import { Text, View } from "react-native";

const t = createT("onboarding");

const MAX_PAGE = 3;

export default function OnboardingScreen() {
Expand Down Expand Up @@ -104,7 +107,7 @@ export default function OnboardingScreen() {
lineHeight: 42,
}}
>
Find your{"\n"}person.
{t("page0.title")}
</Text>
<Text
style={{
Expand All @@ -115,11 +118,11 @@ export default function OnboardingScreen() {
lineHeight: 22,
}}
>
Dating, reimagined. Connect with people who truly match you.
{t("page0.subtitle")}
</Text>
<View style={{ height: 32 }} />
<Button onPress={continueToApp}>
<BtnText>Get Started</BtnText>
<BtnText>{t("page0.cta")}</BtnText>
</Button>
</>
)}
Expand Down Expand Up @@ -157,7 +160,7 @@ export default function OnboardingScreen() {
fontSize: 14,
}}
>
You have a new match
{t("page1.notificationTitle")}
</Text>
<Text
style={{
Expand All @@ -167,7 +170,7 @@ export default function OnboardingScreen() {
marginTop: 2,
}}
>
Someone liked your profile — say hi!
{t("page1.notificationSubtitle")}
</Text>
</View>
</View>
Expand All @@ -181,7 +184,7 @@ export default function OnboardingScreen() {
lineHeight: 36,
}}
>
Never miss a{"\n"}connection.
{t("page1.title")}
</Text>
<Text
style={{
Expand All @@ -192,20 +195,21 @@ export default function OnboardingScreen() {
lineHeight: 22,
}}
>
We{"'"}ll notify you when you get a new match or message — so
you never leave someone waiting.
{t("page1.subtitle")}
</Text>

<View style={{ height: 24 }} />
<Button onPress={continueToApp}>
<BtnText>Enable Notifications</BtnText>
<BtnText>{t("page1.enable")}</BtnText>
</Button>
<Button
variante="outline"
style={{ marginTop: 10 }}
onPress={() => setCurrentPage(2)}
>
<BtnText style={{ color: theme.primary }}>Not now</BtnText>
<BtnText style={{ color: theme.primary }}>
{t("page1.notNow")}
</BtnText>
</Button>
</>
)}
Expand All @@ -232,7 +236,7 @@ export default function OnboardingScreen() {
fontWeight: "600",
}}
>
Real connections
{t("page2.realConnections")}
</Text>
</View>
<View
Expand All @@ -254,7 +258,7 @@ export default function OnboardingScreen() {
fontWeight: "600",
}}
>
No ghosting
{t("page2.noGhosting")}
</Text>
</View>
</View>
Expand All @@ -268,7 +272,7 @@ export default function OnboardingScreen() {
lineHeight: 36,
}}
>
Modern dating{"\n"}is broken.
{t("page2.title")}
</Text>
<Text
style={{
Expand All @@ -279,21 +283,21 @@ export default function OnboardingScreen() {
lineHeight: 22,
}}
>
Endless swiping, shallow profiles, ghosting — you deserve
better. Elysio is built around real conversations and genuine
matches.
{t("page2.subtitle")}
</Text>

<View style={{ height: 24 }} />
<Button onPress={continueToApp}>
<BtnText>Let{"'"}s fix that</BtnText>
<BtnText>{t("page2.cta")}</BtnText>
</Button>
<Button
variante="outline"
style={{ marginTop: 10 }}
onPress={() => setCurrentPage(currentPage - 1)}
>
<BtnText style={{ color: theme.primary }}>Back</BtnText>
<BtnText style={{ color: theme.primary }}>
{t("page2.back")}
</BtnText>
</Button>
</>
)}
Expand Down
23 changes: 13 additions & 10 deletions app/(protected)/(tabs)/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createT } from "@/i18n";
import {
ActivityIndicator,
Pressable,
Expand All @@ -20,6 +21,8 @@ import { useAuthFetch } from "@/hooks/useAuthFetch";
import { useAuth } from "@/lib/auth/AuthProvider";
import { useSafeAreaControl } from "@/components/SafeArea";

const t = createT("chat");

// Design made with Pinterest and ChatGPT
interface ChatResponse {
room: {
Expand Down Expand Up @@ -64,17 +67,17 @@ async function mapChatResponses(data: ChatResponse[], userId: string): Promise<C
if (!chat.lastMessage) {
lastMessageText = "";
} else if (chat.lastMessage.type !== "text") {
lastMessageText = "🎤 Voice message";
lastMessageText = t("voiceMessage");
} else if (!chat.lastMessage.encryptedKeys) {
lastMessageText = "[Encrypted message]";
lastMessageText = t("encryptedMessage");
} else {
try {
const myKey = chat.lastMessage.encryptedKeys?.find(
(k) => k.userId === userId,
);

if (!myKey) {
lastMessageText = "[Encrypted message]";
lastMessageText = t("encryptedMessage");
} else {
try {
lastMessageText = await decryptMessage({
Expand All @@ -84,11 +87,11 @@ async function mapChatResponses(data: ChatResponse[], userId: string): Promise<C
encryptedKey: myKey.encryptedKey,
});
} catch {
lastMessageText = "[Unable to decrypt]";
lastMessageText = t("unableToDecrypt");
}
}
} catch {
lastMessageText = "[Unable to decrypt]";
lastMessageText = t("unableToDecrypt");
}
}

Expand Down Expand Up @@ -249,7 +252,7 @@ function SearchBarComponent({ value, onChangeText }: ISearchBarComponent) {
<View style={styles.inputContainer}>
<Search size={18} color={theme.grayscale} style={{ marginBottom: -1 }} />
<TextInput
placeholder="Search"
placeholder={t("search")}
value={value}
onChangeText={onChangeText}
style={styles.input}
Expand Down Expand Up @@ -324,18 +327,18 @@ function EmptyChatsState({ isSearching, onPrimaryPress }: EmptyChatsStateProps)
</View>

<Text style={styles.emptyTitle}>
{isSearching ? "Keine Chats gefunden" : "Noch keine Chats"}
{isSearching ? t("empty.noChatsFound") : t("empty.noChats")}
</Text>

<Text style={styles.emptySubtitle}>
{isSearching
? "Zu deiner Suche konnten wir keine Unterhaltung finden. Versuche es mit einem anderen Namen."
: "Hier erscheinen deine Matches und Nachrichten. Starte einen neuen Kontakt und bringe das erste Gespraech ins Rollen."}
? t("empty.noChatsFoundSubtitle")
: t("empty.noChatsSubtitle")}
</Text>

<Pressable style={styles.emptyButton} onPress={onPrimaryPress}>
<Text style={styles.emptyButtonText}>
{isSearching ? "Suche zuruecksetzen" : "Neue Leute entdecken"}
{isSearching ? t("empty.resetSearch") : t("empty.discover")}
</Text>
</Pressable>
</View>
Expand Down
9 changes: 6 additions & 3 deletions app/(protected)/(tabs)/favorites.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Made with the help of Claude.ai and ChatGPT

import { createT } from "@/i18n";
import { router, useFocusEffect } from "expo-router";
import { CategoryGridCard } from "@/components/favorites/CategoryCard";
import { DateIdeaCard } from "@/components/favorites/DateIdeaCard";
Expand Down Expand Up @@ -57,6 +58,8 @@ const CATEGORIES = [
{ label: "CHILL", icon: Armchair },
];

const t = createT("favorites");

export default function Favorites() {
const { theme } = useTheme();
const s = makeStyles(theme);
Expand Down Expand Up @@ -129,9 +132,9 @@ export default function Favorites() {
{/* ── Explore Categories ── */}
<View style={s.section}>
<View style={s.sectionHeader}>
<Text style={s.sectionTitle}>Explore Categories</Text>
<Text style={s.sectionTitle}>{t("exploreCategories")}</Text>
<Pressable onPress={() => router.push("/favorites/allcategories")}>
<Text style={s.viewAll}>View All</Text>
<Text style={s.viewAll}>{t("viewAll")}</Text>
</Pressable>
</View>
<View style={s.categoryRow}>
Expand All @@ -148,7 +151,7 @@ export default function Favorites() {

{/* ── Winning Tips ── */}
<View style={s.tipsSection}>
<Text style={s.sectionTitle}>Winning Tips</Text>
<Text style={s.sectionTitle}>{t("winningTips")}</Text>
<View style={s.tipsCol}>
{TIPS.map((tip, i) => (
<TipRow
Expand Down
Loading
Loading