@oxyhq/services
Version:
365 lines (342 loc) • 12.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useUploadFile = exports.useUploadAvatar = exports.useUpdateProfile = exports.useUpdatePrivacySettings = exports.useUpdateAccountSettings = void 0;
var _reactQuery = require("@tanstack/react-query");
var _core = require("@oxyhq/core");
var _queryKeys = require("../queries/queryKeys.js");
var _OxyContext = require("../../context/OxyContext.js");
var _sonner = require("../../../lib/sonner");
var _avatarUtils = require("../../utils/avatarUtils.js");
var _authStore = require("../../stores/authStore.js");
/**
* Update user profile with optimistic updates and offline queue support
*/
const useUpdateProfile = () => {
const {
oxyServices,
activeSessionId,
user
} = (0, _OxyContext.useOxy)();
const queryClient = (0, _reactQuery.useQueryClient)();
return (0, _reactQuery.useMutation)({
mutationFn: async updates => {
return (0, _core.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.updateProfile(updates));
},
// Optimistic update
onMutate: async updates => {
// Cancel outgoing refetches
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.accounts.current()
});
// Snapshot previous value
const previousUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
// Optimistically update
if (previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), {
...previousUser,
...updates
});
// Also update profile query if sessionId is available
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), {
...previousUser,
...updates
});
}
}
return {
previousUser
};
},
// On error, rollback
onError: (error, updates, context) => {
if (context?.previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), context.previousUser);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), context.previousUser);
}
}
_sonner.toast.error(error instanceof Error ? error.message : 'Failed to update profile');
},
// On success, invalidate and refetch
onSuccess: (data, updates) => {
// Update cache with server response
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), data);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), data);
}
// Update authStore so frontend components see the changes immediately
_authStore.useAuthStore.getState().setUser(data);
// If avatar was updated, refresh accountStore with cache-busted URL
if (updates.avatar && activeSessionId && oxyServices) {
(0, _avatarUtils.refreshAvatarInStore)(activeSessionId, updates.avatar, oxyServices);
}
// Invalidate all related queries to refresh everywhere
(0, _queryKeys.invalidateUserQueries)(queryClient);
(0, _queryKeys.invalidateAccountQueries)(queryClient);
}
});
};
/**
* Upload avatar with progress tracking and offline queue support
*/
exports.useUpdateProfile = useUpdateProfile;
const useUploadAvatar = () => {
const {
oxyServices,
activeSessionId
} = (0, _OxyContext.useOxy)();
const queryClient = (0, _reactQuery.useQueryClient)();
return (0, _reactQuery.useMutation)({
mutationFn: async file => {
return (0, _core.authenticatedApiCall)(oxyServices, activeSessionId, async () => {
// Upload file first
const uploadResult = await oxyServices.assetUpload(file, 'public');
const fileId = uploadResult?.file?.id || uploadResult?.id || uploadResult;
if (!fileId || typeof fileId !== 'string') {
throw new Error('Failed to get file ID from upload result');
}
// Update profile with file ID
return await oxyServices.updateProfile({
avatar: fileId
});
});
},
onMutate: async file => {
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.accounts.current()
});
const previousUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
// Optimistically set a temporary avatar (using file URI as placeholder)
if (previousUser) {
const optimisticUser = {
...previousUser,
avatar: file.uri // Temporary, will be replaced with fileId
};
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), optimisticUser);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), optimisticUser);
}
}
return {
previousUser
};
},
onError: (error, file, context) => {
if (context?.previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), context.previousUser);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), context.previousUser);
}
}
_sonner.toast.error(error instanceof Error ? error.message : 'Failed to upload avatar');
},
onSuccess: data => {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), data);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), data);
}
// Update authStore so frontend components see the changes immediately
_authStore.useAuthStore.getState().setUser(data);
// Refresh accountStore with cache-busted URL if avatar was updated
if (data?.avatar && activeSessionId && oxyServices) {
(0, _avatarUtils.refreshAvatarInStore)(activeSessionId, data.avatar, oxyServices);
}
// Invalidate all related queries to refresh everywhere
(0, _queryKeys.invalidateUserQueries)(queryClient);
(0, _queryKeys.invalidateAccountQueries)(queryClient);
_sonner.toast.success('Avatar updated successfully');
}
});
};
/**
* Update account settings
*/
exports.useUploadAvatar = useUploadAvatar;
const useUpdateAccountSettings = () => {
const {
oxyServices,
activeSessionId
} = (0, _OxyContext.useOxy)();
const queryClient = (0, _reactQuery.useQueryClient)();
return (0, _reactQuery.useMutation)({
mutationFn: async settings => {
return await oxyServices.updateProfile({
privacySettings: settings
});
},
onMutate: async settings => {
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.accounts.settings()
});
const previousUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
if (previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), {
...previousUser,
privacySettings: {
...previousUser.privacySettings,
...settings
}
});
}
return {
previousUser
};
},
onError: (error, settings, context) => {
if (context?.previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), context.previousUser);
}
_sonner.toast.error(error instanceof Error ? error.message : 'Failed to update settings');
},
onSuccess: data => {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), data);
// Update authStore so frontend components see the changes immediately
_authStore.useAuthStore.getState().setUser(data);
(0, _queryKeys.invalidateAccountQueries)(queryClient);
_sonner.toast.success('Settings updated successfully');
},
onSettled: () => {
queryClient.invalidateQueries({
queryKey: _queryKeys.queryKeys.accounts.settings()
});
}
});
};
/**
* Update privacy settings with optimistic updates and authentication handling
*/
exports.useUpdateAccountSettings = useUpdateAccountSettings;
const useUpdatePrivacySettings = () => {
const {
oxyServices,
activeSessionId,
user
} = (0, _OxyContext.useOxy)();
const queryClient = (0, _reactQuery.useQueryClient)();
return (0, _reactQuery.useMutation)({
mutationFn: async ({
settings,
userId
}) => {
const targetUserId = userId || user?.id;
if (!targetUserId) {
throw new Error('User ID is required');
}
return (0, _core.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.updatePrivacySettings(settings, targetUserId));
},
// Optimistic update
onMutate: async ({
settings,
userId
}) => {
const targetUserId = userId || user?.id;
if (!targetUserId) return;
// Cancel outgoing refetches
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.privacy.settings(targetUserId)
});
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.accounts.current()
});
// Snapshot previous values
const previousPrivacySettings = queryClient.getQueryData(_queryKeys.queryKeys.privacy.settings(targetUserId));
const previousUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
// Optimistically update privacy settings
if (previousPrivacySettings) {
queryClient.setQueryData(_queryKeys.queryKeys.privacy.settings(targetUserId), {
...previousPrivacySettings,
...settings
});
}
// Also update user query if available
if (previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), {
...previousUser,
privacySettings: {
...previousUser.privacySettings,
...settings
}
});
}
return {
previousPrivacySettings,
previousUser
};
},
// On error, rollback
onError: (error, {
userId
}, context) => {
const targetUserId = userId || user?.id;
if (context?.previousPrivacySettings && targetUserId) {
queryClient.setQueryData(_queryKeys.queryKeys.privacy.settings(targetUserId), context.previousPrivacySettings);
}
if (context?.previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), context.previousUser);
}
_sonner.toast.error(error instanceof Error ? error.message : 'Failed to update privacy settings');
},
// On success, invalidate and refetch
onSuccess: (data, {
userId
}) => {
const targetUserId = userId || user?.id;
if (targetUserId) {
queryClient.setQueryData(_queryKeys.queryKeys.privacy.settings(targetUserId), data);
}
// Also update account query if it contains privacy settings
const currentUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
if (currentUser) {
const updatedUser = {
...currentUser,
privacySettings: data
};
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), updatedUser);
// Update authStore so frontend components see the changes immediately
_authStore.useAuthStore.getState().setUser(updatedUser);
}
(0, _queryKeys.invalidateAccountQueries)(queryClient);
},
// Always refetch after error or success
onSettled: (data, error, {
userId
}) => {
const targetUserId = userId || user?.id;
if (targetUserId) {
queryClient.invalidateQueries({
queryKey: _queryKeys.queryKeys.privacy.settings(targetUserId)
});
}
queryClient.invalidateQueries({
queryKey: _queryKeys.queryKeys.accounts.current()
});
}
});
};
/** Uploaded file data structure from API */
/** Upload result type that supports both single file and batch responses */
exports.useUpdatePrivacySettings = useUpdatePrivacySettings;
/**
* Upload file with authentication handling and progress tracking
*/
const useUploadFile = () => {
const {
oxyServices,
activeSessionId
} = (0, _OxyContext.useOxy)();
return (0, _reactQuery.useMutation)({
mutationFn: async ({
file,
visibility,
metadata,
onProgress
}) => {
return (0, _core.authenticatedApiCall)(oxyServices, activeSessionId, () => oxyServices.assetUpload(file, visibility, metadata, onProgress));
}
});
};
exports.useUploadFile = useUploadFile;
//# sourceMappingURL=useAccountMutations.js.map