UNPKG

@oxyhq/services

Version:

OxyHQ Expo/React Native SDK — UI components, screens, and native features

365 lines (342 loc) 12.7 kB
"use strict"; 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