as-app/src/updates/index.js
2025-07-02 00:54:30 +02:00

123 lines
3.5 KiB
JavaScript

import { useCallback, useEffect, useState } from "react";
import { Alert } from "react-native";
import * as Updates from "expo-updates";
import AsyncStorage from "~/storage/memoryAsyncStorage";
import { STORAGE_KEYS } from "~/storage/storageKeys";
import useNow from "~/hooks/useNow";
import * as Sentry from "@sentry/react-native";
import env from "~/env";
import { treeActions } from "~/stores";
const UPDATE_CHECK_INTERVAL = 24 * 60 * 60 * 1000;
const applyUpdate = async () => {
treeActions.suspendTree();
try {
await Updates.fetchUpdateAsync();
// await Updates.reloadAsync();
} catch (error) {
Sentry.captureException(error);
console.log("Error applying update:", error);
// await Updates.reloadAsync(); // https://github.com/expo/expo/issues/14359#issuecomment-1159558604
}
};
const checkForUpdate = async () => {
if (env.LOCAL_DEV) {
return;
}
try {
const lastCheckString = await AsyncStorage.getItem(
STORAGE_KEYS.LAST_UPDATE_CHECK_TIME,
);
const lastCheck = lastCheckString ? new Date(lastCheckString) : null;
const nowDate = new Date();
if (!lastCheck || nowDate - lastCheck > UPDATE_CHECK_INTERVAL) {
await AsyncStorage.setItem(
STORAGE_KEYS.LAST_UPDATE_CHECK_TIME,
nowDate.toISOString(),
);
const update = await Updates.checkForUpdateAsync();
if (!update.isAvailable) {
return false;
}
const remoteUpdate = update.manifest;
const remoteCreatedAt = new Date(remoteUpdate.createdAt).getTime();
// const currentCreatedAt = Updates.manifest.commitTime; // buggy commitTime
const currentCreatedAt = env.BUILD_TIME;
// console.log(
// "DEBUG_AS remoteUpdate",
// `${remoteCreatedAt} > ${currentCreatedAt}`,
// remoteCreatedAt > currentCreatedAt,
// );
// console.log("DEBUG_AS Updates.manifest", Updates.manifest);
if (remoteCreatedAt > currentCreatedAt) {
return true;
} else {
return false;
}
}
} catch (error) {
console.log("Error checking for updates:", error);
}
};
export function useUpdatesCheck() {
const [updateAvailable, setUpdateAvailable] = useState(false);
const now = useNow();
useEffect(() => {
const updateAvailability = async () => {
const isAvailable = await checkForUpdate();
setUpdateAvailable(isAvailable);
};
updateAvailability();
}, [now]); // trigger every minute
return { updateAvailable, setUpdateAvailable };
}
export function useUpdates() {
const { isUpdatePending } = Updates.useUpdates();
useEffect(() => {
if (isUpdatePending) {
// Update has successfully downloaded; apply it now
(async () => {
await Updates.reloadAsync();
treeActions.triggerReload();
})();
}
}, [isUpdatePending]);
const { updateAvailable, setUpdateAvailable } = useUpdatesCheck();
const showAlert = useCallback(() => {
Alert.alert(
"Mise à jour disponible",
"Une nouvelle mise à jour est disponible. Souhaitez vous l'appliquer ?",
[
{
text: "Me rappeler plus tard",
onPress: () => setUpdateAvailable(false),
},
{ text: "Mettre à jour maintenant", onPress: applyUpdate },
],
);
}, [setUpdateAvailable]);
useEffect(() => {
if (updateAvailable) {
showAlert();
}
}, [showAlert, updateAvailable]);
}
// export async function installUpdateIfAvailable() {
// if (await checkForUpdate()) {
// await applyUpdate();
// }
// }