chore: add location debug helpers
This commit is contained in:
parent
40b27bff29
commit
5398f94f49
3 changed files with 200 additions and 1 deletions
110
src/location/emulatorService.js
Normal file
110
src/location/emulatorService.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
import BackgroundGeolocation from "react-native-background-geolocation";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { createLogger } from "~/lib/logger";
|
||||
import { BACKGROUND_SCOPES } from "~/lib/logger/scopes";
|
||||
|
||||
const EMULATOR_MODE_KEY = "emulator_mode_enabled";
|
||||
|
||||
// Global variables
|
||||
let emulatorIntervalId = null;
|
||||
let isEmulatorModeEnabled = false;
|
||||
|
||||
// Create a logger for the emulator service
|
||||
const emulatorLogger = createLogger({
|
||||
module: BACKGROUND_SCOPES.GEOLOCATION,
|
||||
feature: "emulator",
|
||||
});
|
||||
|
||||
// Initialize emulator mode based on stored preference
|
||||
export const initEmulatorMode = async () => {
|
||||
try {
|
||||
const storedValue = await AsyncStorage.getItem(EMULATOR_MODE_KEY);
|
||||
emulatorLogger.debug("Initializing emulator mode", { storedValue });
|
||||
|
||||
if (storedValue === "true") {
|
||||
await enableEmulatorMode();
|
||||
}
|
||||
} catch (error) {
|
||||
emulatorLogger.error("Failed to initialize emulator mode", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Enable emulator mode
|
||||
export const enableEmulatorMode = async () => {
|
||||
emulatorLogger.info("Enabling emulator mode");
|
||||
|
||||
// Clear existing interval if any
|
||||
if (emulatorIntervalId) {
|
||||
clearInterval(emulatorIntervalId);
|
||||
}
|
||||
|
||||
try {
|
||||
// Call immediately once
|
||||
await BackgroundGeolocation.changePace(true);
|
||||
emulatorLogger.debug("Initial changePace call successful");
|
||||
|
||||
// Then set up interval
|
||||
emulatorIntervalId = setInterval(
|
||||
() => {
|
||||
BackgroundGeolocation.changePace(true);
|
||||
emulatorLogger.debug("Interval changePace call executed");
|
||||
},
|
||||
30 * 60 * 1000,
|
||||
); // 30 minutes
|
||||
|
||||
isEmulatorModeEnabled = true;
|
||||
|
||||
// Persist the setting
|
||||
await AsyncStorage.setItem(EMULATOR_MODE_KEY, "true");
|
||||
emulatorLogger.debug("Emulator mode setting saved");
|
||||
} catch (error) {
|
||||
emulatorLogger.error("Failed to enable emulator mode", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Disable emulator mode
|
||||
export const disableEmulatorMode = async () => {
|
||||
emulatorLogger.info("Disabling emulator mode");
|
||||
|
||||
if (emulatorIntervalId) {
|
||||
clearInterval(emulatorIntervalId);
|
||||
emulatorIntervalId = null;
|
||||
}
|
||||
|
||||
isEmulatorModeEnabled = false;
|
||||
|
||||
// Persist the setting
|
||||
try {
|
||||
await AsyncStorage.setItem(EMULATOR_MODE_KEY, "false");
|
||||
emulatorLogger.debug("Emulator mode setting saved");
|
||||
} catch (error) {
|
||||
emulatorLogger.error("Failed to save emulator mode setting", {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Get current emulator mode state
|
||||
export const getEmulatorModeState = () => {
|
||||
return isEmulatorModeEnabled;
|
||||
};
|
||||
|
||||
// Toggle emulator mode
|
||||
export const toggleEmulatorMode = async (enabled) => {
|
||||
emulatorLogger.info("Toggling emulator mode", { enabled });
|
||||
|
||||
if (enabled) {
|
||||
await enableEmulatorMode();
|
||||
} else {
|
||||
await disableEmulatorMode();
|
||||
}
|
||||
|
||||
return isEmulatorModeEnabled;
|
||||
};
|
|
@ -3,6 +3,7 @@ import { TRACK_MOVE } from "~/misc/devicePrefs";
|
|||
import { createLogger } from "~/lib/logger";
|
||||
import { BACKGROUND_SCOPES } from "~/lib/logger/scopes";
|
||||
import jwtDecode from "jwt-decode";
|
||||
import { initEmulatorMode } from "./emulatorService";
|
||||
|
||||
import {
|
||||
getAuthState,
|
||||
|
@ -271,4 +272,7 @@ export default async function trackLocation() {
|
|||
|
||||
// Check for pending records after a short delay to ensure everything is initialized
|
||||
setTimeout(checkPendingRecords, 5000);
|
||||
|
||||
// Initialize emulator mode if previously enabled
|
||||
initEmulatorMode();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { View, StyleSheet, ScrollView } from "react-native";
|
||||
import * as Sentry from "@sentry/react-native";
|
||||
import BackgroundGeolocation from "react-native-background-geolocation";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
|
@ -12,6 +13,11 @@ import {
|
|||
import { createStyles } from "~/theme";
|
||||
import env, { setStaging } from "~/env";
|
||||
import { authActions } from "~/stores";
|
||||
import {
|
||||
getEmulatorModeState,
|
||||
toggleEmulatorMode as toggleEmulatorModeService,
|
||||
initEmulatorMode,
|
||||
} from "~/location/emulatorService";
|
||||
|
||||
const reset = async () => {
|
||||
await authActions.logout();
|
||||
|
@ -29,7 +35,50 @@ const Section = ({ title, children }) => {
|
|||
|
||||
export default function Developer() {
|
||||
const styles = useStyles();
|
||||
const { colors } = useTheme();
|
||||
const [isStaging, setIsStaging] = useState(env.IS_STAGING);
|
||||
const [emulatorMode, setEmulatorMode] = useState(false);
|
||||
const [syncStatus, setSyncStatus] = useState(null); // null, 'syncing', 'success', 'error'
|
||||
const [syncResult, setSyncResult] = useState("");
|
||||
|
||||
// Initialize emulator mode when component mounts
|
||||
useEffect(() => {
|
||||
// Initialize the emulator service
|
||||
initEmulatorMode();
|
||||
|
||||
// Set the initial state based on the global service
|
||||
setEmulatorMode(getEmulatorModeState());
|
||||
}, []);
|
||||
|
||||
// Handle toggling emulator mode
|
||||
const handleEmulatorModeToggle = async (enabled) => {
|
||||
const newState = await toggleEmulatorModeService(enabled);
|
||||
setEmulatorMode(newState);
|
||||
};
|
||||
|
||||
// Function to trigger geolocation sync
|
||||
const triggerGeolocSync = async () => {
|
||||
try {
|
||||
setSyncStatus("syncing");
|
||||
setSyncResult("");
|
||||
|
||||
// Get the count of pending records first
|
||||
const count = await BackgroundGeolocation.getCount();
|
||||
|
||||
// Perform the sync
|
||||
const records = await BackgroundGeolocation.sync();
|
||||
|
||||
const result = `Synced ${
|
||||
records?.length || 0
|
||||
} records (${count} pending)`;
|
||||
setSyncResult(result);
|
||||
setSyncStatus("success");
|
||||
} catch (error) {
|
||||
console.error("Geolocation sync failed:", error);
|
||||
setSyncResult(`Sync failed: ${error.message}`);
|
||||
setSyncStatus("error");
|
||||
}
|
||||
};
|
||||
const triggerNullError = () => {
|
||||
try {
|
||||
// Wrap the null error in try-catch
|
||||
|
@ -101,6 +150,13 @@ export default function Developer() {
|
|||
}}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.settingRow}>
|
||||
<Text variant="bodyLarge">Emulator Mode</Text>
|
||||
<Switch
|
||||
value={emulatorMode}
|
||||
onValueChange={handleEmulatorModeToggle}
|
||||
/>
|
||||
</View>
|
||||
</Section>
|
||||
|
||||
<Section title="Environment URLs">
|
||||
|
@ -150,6 +206,35 @@ export default function Developer() {
|
|||
|
||||
<Divider style={styles.divider} />
|
||||
|
||||
<Section title="Location Controls">
|
||||
<Button
|
||||
onPress={triggerGeolocSync}
|
||||
style={styles.button}
|
||||
contentStyle={styles.buttonContent}
|
||||
labelStyle={styles.buttonLabel}
|
||||
loading={syncStatus === "syncing"}
|
||||
disabled={syncStatus === "syncing"}
|
||||
>
|
||||
Trigger Geolocation Sync
|
||||
</Button>
|
||||
|
||||
{syncStatus && syncResult && (
|
||||
<Text
|
||||
style={[
|
||||
styles.statusText,
|
||||
{
|
||||
color: syncStatus === "success" ? colors.primary : colors.error,
|
||||
marginTop: 8,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{syncResult}
|
||||
</Text>
|
||||
)}
|
||||
</Section>
|
||||
|
||||
<Divider style={styles.divider} />
|
||||
|
||||
<Section title="Error Testing">
|
||||
<Button
|
||||
onPress={triggerNullError}
|
||||
|
|
Loading…
Add table
Reference in a new issue