Official URL migration preserves sessions, shortcuts prefs, and last clock-in client; auth screens match web with legal links; time clock and invoice editor/send flows are updated for the new domain and UI patterns. Co-authored-by: Cursor <cursoragent@cursor.com>
45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
|
|
import { invalidServerUrlMessage } from "@/lib/config";
|
|
|
|
const STORAGE_KEY = "beenvoice:instance-url";
|
|
|
|
export function normalizeInstanceUrl(input: string): string | null {
|
|
const trimmed = input.trim().replace(/\/$/, "");
|
|
if (!trimmed) return null;
|
|
|
|
let url = trimmed;
|
|
if (!/^https?:\/\//i.test(url)) {
|
|
const isLocal =
|
|
/^(localhost|127\.|192\.168\.|10\.|172\.(1[6-9]|2\d|3[01])\.)/i.test(url);
|
|
url = `${isLocal ? "http" : "https"}://${url}`;
|
|
}
|
|
|
|
try {
|
|
const parsed = new URL(url);
|
|
if (!parsed.hostname) return null;
|
|
return `${parsed.protocol}//${parsed.host}`;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function loadStoredInstanceUrl(): Promise<string | null> {
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
if (!stored) return null;
|
|
return normalizeInstanceUrl(stored) ?? stored.replace(/\/$/, "");
|
|
}
|
|
|
|
export async function saveStoredInstanceUrl(url: string): Promise<string> {
|
|
const normalized = normalizeInstanceUrl(url);
|
|
if (!normalized) {
|
|
throw new Error(invalidServerUrlMessage());
|
|
}
|
|
await AsyncStorage.setItem(STORAGE_KEY, normalized);
|
|
return normalized;
|
|
}
|
|
|
|
export async function clearStoredInstanceUrl(): Promise<void> {
|
|
await AsyncStorage.removeItem(STORAGE_KEY);
|
|
}
|