aboutsummaryrefslogtreecommitdiffstats
path: root/apps/mobile/app/signin.tsx
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-12-22 16:36:23 +0200
committerGitHub <noreply@github.com>2025-12-22 14:36:23 +0000
commitece68ed078be3f6d66b5dcd7de8ba9853d48be27 (patch)
treed976591691a8819f5aae1cafee54a4b386910394 /apps/mobile/app/signin.tsx
parentca4bfa4c88287aba23c104a93e4fb6be7b2776da (diff)
downloadkarakeep-ece68ed078be3f6d66b5dcd7de8ba9853d48be27.tar.zst
feat(mobile): Convert server address editing to modal in mobile app (#2290)
* feat: Convert server address editing to modal in mobile app Changed the server address editing experience from an inline button to a modal dialog. This improves UX by forcing users to explicitly save or cancel their changes rather than forgetting to click a save button. Changes: - Created ServerAddressModal component following the CustomHeadersModal pattern - Updated signin page to use the modal instead of inline editing - Enhanced settings page to allow changing server address (was previously read-only) - Added validation and error handling within the modal - Made the settings page server address clickable with visual feedback This resolves the issue where users forget to click the save button after editing the server address. * refactor: Convert server address to screen modal Changed from React Native Modal to Expo Router screen modal presentation. This provides a better native experience with proper navigation stack integration. Changes: - Created server-address.tsx as a screen route with modal presentation - Registered the route in root _layout.tsx - Updated signin.tsx to navigate to the screen modal instead of opening RN modal - Reverted settings page to original (no server address editing from settings) - Removed ServerAddressModal component (no longer needed) Benefits: - Native modal presentation with proper animations - Better integration with the navigation stack - Cleaner separation of concerns * merge the custom headers inside the server-add screen * fix the look of the address UI --------- Co-authored-by: Claude <noreply@anthropic.com>
Diffstat (limited to 'apps/mobile/app/signin.tsx')
-rw-r--r--apps/mobile/app/signin.tsx103
1 files changed, 19 insertions, 84 deletions
diff --git a/apps/mobile/app/signin.tsx b/apps/mobile/app/signin.tsx
index 6a554f89..03cbba5a 100644
--- a/apps/mobile/app/signin.tsx
+++ b/apps/mobile/app/signin.tsx
@@ -7,7 +7,6 @@ import {
View,
} from "react-native";
import { Redirect, useRouter } from "expo-router";
-import { CustomHeadersModal } from "@/components/CustomHeadersModal";
import Logo from "@/components/Logo";
import { TailwindResolver } from "@/components/TailwindResolver";
import { Button } from "@/components/ui/Button";
@@ -15,7 +14,7 @@ import { Input } from "@/components/ui/Input";
import { Text } from "@/components/ui/Text";
import useAppSettings from "@/lib/settings";
import { api } from "@/lib/trpc";
-import { Bug, Check, Edit3 } from "lucide-react-native";
+import { Bug, Edit3 } from "lucide-react-native";
enum LoginType {
Password,
@@ -28,12 +27,6 @@ export default function Signin() {
const [error, setError] = useState<string | undefined>();
const [loginType, setLoginType] = useState<LoginType>(LoginType.Password);
- const [isEditingServerAddress, setIsEditingServerAddress] = useState(false);
- const [tempServerAddress, setTempServerAddress] = useState(
- settings.address ?? "https://cloud.karakeep.app",
- );
- const [isCustomHeadersModalVisible, setIsCustomHeadersModalVisible] =
- useState(false);
const emailRef = useRef<string>("");
const passwordRef = useRef<string>("");
@@ -82,19 +75,15 @@ export default function Signin() {
return <Redirect href="dashboard" />;
}
- const handleSaveCustomHeaders = (headers: Record<string, string>) => {
- setSettings({ ...settings, customHeaders: headers });
- };
-
const onSignin = () => {
- if (!tempServerAddress) {
+ if (!settings.address) {
setError("Server address is required");
return;
}
if (
- !tempServerAddress.startsWith("http://") &&
- !tempServerAddress.startsWith("https://")
+ !settings.address.startsWith("http://") &&
+ !settings.address.startsWith("https://")
) {
setError("Server address must start with http:// or https://");
return;
@@ -137,71 +126,23 @@ export default function Signin() {
)}
<View className="gap-2">
<Text className="font-bold">Server Address</Text>
- {!isEditingServerAddress ? (
- <View className="flex-row items-center gap-2">
- <View className="flex-1 rounded-md border border-border bg-card px-3 py-2">
- <Text>{tempServerAddress}</Text>
- </View>
- <Button
- size="icon"
- variant="secondary"
- onPress={() => {
- setIsEditingServerAddress(true);
- }}
- >
- <TailwindResolver
- comp={(styles) => (
- <Edit3 size={16} color={styles?.color?.toString()} />
- )}
- className="color-foreground"
- />
- </Button>
+ <View className="flex-row items-center gap-2">
+ <View className="flex-1 rounded-md border border-border bg-card px-3 py-2">
+ <Text>{settings.address ?? "https://cloud.karakeep.app"}</Text>
</View>
- ) : (
- <View className="flex-row items-center gap-2">
- <Input
- className="flex-1"
- inputClasses="bg-card"
- placeholder="Server Address"
- value={tempServerAddress}
- autoCapitalize="none"
- keyboardType="url"
- onChangeText={setTempServerAddress}
- autoFocus
+ <Button
+ size="icon"
+ variant="secondary"
+ onPress={() => router.push("/server-address")}
+ >
+ <TailwindResolver
+ comp={(styles) => (
+ <Edit3 size={16} color={styles?.color?.toString()} />
+ )}
+ className="color-foreground"
/>
- <Button
- size="icon"
- variant="primary"
- onPress={() => {
- if (tempServerAddress.trim()) {
- setSettings({
- ...settings,
- address: tempServerAddress.trim().replace(/\/$/, ""),
- });
- }
- setIsEditingServerAddress(false);
- }}
- >
- <TailwindResolver
- comp={(styles) => (
- <Check size={16} color={styles?.color?.toString()} />
- )}
- className="text-white"
- />
- </Button>
- </View>
- )}
- <Pressable
- onPress={() => setIsCustomHeadersModalVisible(true)}
- className="mt-1"
- >
- <Text className="text-xs text-gray-500 underline">
- Configure Custom Headers{" "}
- {settings.customHeaders &&
- Object.keys(settings.customHeaders).length > 0 &&
- `(${Object.keys(settings.customHeaders).length})`}
- </Text>
- </Pressable>
+ </Button>
+ </View>
</View>
{loginType === LoginType.Password && (
<>
@@ -282,12 +223,6 @@ export default function Signin() {
</Pressable>
</View>
</TouchableWithoutFeedback>
- <CustomHeadersModal
- visible={isCustomHeadersModalVisible}
- customHeaders={settings.customHeaders || {}}
- onClose={() => setIsCustomHeadersModalVisible(false)}
- onSave={handleSaveCustomHeaders}
- />
</KeyboardAvoidingView>
);
}