mirror of
https://github.com/urosran/cally.git
synced 2026-10-23 09:37:54 +00:00
Syncing rework
This commit is contained in:
@@ -1,41 +1,144 @@
|
||||
import {useMutation, useQueryClient} from "react-query";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {useCreateEventsFromProvider} from "@/hooks/firebase/useCreateEvent";
|
||||
import {fetchMicrosoftCalendarEvents} from "@/calendar-integration/microsoft-calendar-utils";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import { useSetUserData } from "@/hooks/firebase/useSetUserData";
|
||||
import functions from '@react-native-firebase/functions';
|
||||
import * as AuthSession from 'expo-auth-session';
|
||||
|
||||
export const useFetchAndSaveOutlookEvents = () => {
|
||||
const queryClient = useQueryClient()
|
||||
const {profileData} = useAuthContext();
|
||||
const {mutateAsync: createEventsFromProvider} = useCreateEventsFromProvider();
|
||||
interface SyncResponse {
|
||||
success: boolean;
|
||||
eventCount: number;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
return useMutation({
|
||||
interface SyncError extends Error {
|
||||
code?: string;
|
||||
details?: {
|
||||
requiresReauth?: boolean;
|
||||
message?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const microsoftConfig = {
|
||||
clientId: "13c79071-1066-40a9-9f71-b8c4b138b4af",
|
||||
scopes: [
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
"offline_access",
|
||||
"Calendars.ReadWrite",
|
||||
"User.Read",
|
||||
],
|
||||
redirectUri: AuthSession.makeRedirectUri({path: "settings"})
|
||||
};
|
||||
|
||||
export const useFetchAndSaveMicrosoftEvents = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { profileData } = useAuthContext();
|
||||
const { mutateAsync: setUserData } = useSetUserData();
|
||||
|
||||
const handleReauth = async (email: string) => {
|
||||
try {
|
||||
const authRequest = new AuthSession.AuthRequest({
|
||||
clientId: microsoftConfig.clientId,
|
||||
scopes: microsoftConfig.scopes,
|
||||
redirectUri: microsoftConfig.redirectUri,
|
||||
responseType: AuthSession.ResponseType.Code,
|
||||
usePKCE: true,
|
||||
});
|
||||
|
||||
const result = await authRequest.promptAsync({
|
||||
authorizationEndpoint: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
||||
});
|
||||
|
||||
if (result.type === 'success' && result.params?.code) {
|
||||
const tokenResponse = await fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
client_id: microsoftConfig.clientId,
|
||||
scope: microsoftConfig.scopes.join(' '),
|
||||
code: result.params.code,
|
||||
redirect_uri: microsoftConfig.redirectUri,
|
||||
grant_type: 'authorization_code',
|
||||
code_verifier: authRequest.codeVerifier || '',
|
||||
}),
|
||||
});
|
||||
|
||||
const tokens = await tokenResponse.json();
|
||||
|
||||
await setUserData({
|
||||
newUserData: {
|
||||
microsoftAccounts: {
|
||||
...profileData?.microsoftAccounts,
|
||||
[email]: {
|
||||
accessToken: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token,
|
||||
email,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Microsoft reauth error:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return useMutation<SyncResponse, SyncError, { email?: string }>({
|
||||
mutationKey: ["fetchAndSaveOutlookEvents", "sync"],
|
||||
mutationFn: async ({token, email, date}: { token?: string; email?: string, date?: Date }) => {
|
||||
const baseDate = date || new Date();
|
||||
const timeMin = new Date(new Date(baseDate).setFullYear(new Date(baseDate).getMonth() - 1));
|
||||
const timeMax = new Date(new Date(baseDate).setFullYear(new Date(baseDate).getMonth() + 1));
|
||||
mutationFn: async ({ email }: { email?: string }) => {
|
||||
if (!email) {
|
||||
throw new Error("Email is required");
|
||||
}
|
||||
|
||||
console.log("Token: ", token ?? profileData?.microsoftToken);
|
||||
if (!profileData?.microsoftAccounts?.[email]) {
|
||||
throw new Error("No valid Microsoft account found");
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetchMicrosoftCalendarEvents(
|
||||
token ?? profileData?.microsoftToken,
|
||||
email ?? profileData?.outlookMail,
|
||||
profileData?.familyId,
|
||||
timeMin.toISOString().slice(0, -5) + "Z",
|
||||
timeMax.toISOString().slice(0, -5) + "Z"
|
||||
);
|
||||
const response = await functions()
|
||||
.httpsCallable('triggerMicrosoftSync')({ email });
|
||||
|
||||
return response.data as SyncResponse;
|
||||
} catch (error: any) {
|
||||
console.error("Microsoft sync error:", error);
|
||||
|
||||
// Check if we need to reauthenticate
|
||||
if (error.details?.requiresReauth ||
|
||||
error.code === 'functions/failed-precondition' ||
|
||||
error.code === 'functions/unauthenticated') {
|
||||
|
||||
console.log('Attempting Microsoft reauth...');
|
||||
const reauthSuccessful = await handleReauth(email);
|
||||
|
||||
if (reauthSuccessful) {
|
||||
// Retry the sync with new tokens
|
||||
console.log('Retrying sync after reauth...');
|
||||
const retryResponse = await functions()
|
||||
.httpsCallable('triggerMicrosoftSync')({ email });
|
||||
return retryResponse.data as SyncResponse;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(response);
|
||||
const items = response ?? [];
|
||||
await createEventsFromProvider(items);
|
||||
} catch (error) {
|
||||
console.error("Error fetching and saving Outlook events: ", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(["events"])
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries(["events"]);
|
||||
console.log(`Successfully synced ${data.eventCount} Microsoft events`);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Microsoft sync failed:', {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
details: error.details
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user