Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 16 additions & 25 deletions src/hooks/sync-sites/sync-sites-context.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { __, sprintf } from '@wordpress/i18n';
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import React, { createContext, useCallback, useContext, useEffect } from 'react';
import { useListenDeepLinkConnection } from 'src/hooks/sync-sites/use-listen-deep-link-connection';
import { generateStateId } from 'src/hooks/sync-sites/use-pull-push-states';
import { PullStates, UseSyncPull, useSyncPull } from 'src/hooks/sync-sites/use-sync-pull';
import { UseSyncPull, useSyncPull } from 'src/hooks/sync-sites/use-sync-pull';
import {
PushStates,
UseSyncPush,
useSyncPush,
mapImportResponseToPushState,
Expand All @@ -14,7 +13,7 @@ import { useFormatLocalizedTimestamps } from 'src/hooks/use-format-localized-tim
import { useSyncStatesProgressInfo } from 'src/hooks/use-sync-states-progress-info';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { useAppDispatch } from 'src/stores';
import { useConnectedSitesData, useSyncSitesData, connectedSitesActions } from 'src/stores/sync';
import { useConnectedSitesData, useSyncSitesData, connectedSitesActions, syncOperationsActions } from 'src/stores/sync';
import type { ImportResponse } from 'src/hooks/use-sync-states-progress-info';

type GetLastSyncTimeText = ( timestamp: string | null, type: 'pull' | 'push' ) => string;
Expand All @@ -34,7 +33,6 @@ const SyncSitesContext = createContext< SyncSitesContextType | undefined >( unde

export function SyncSitesProvider( { children }: { children: React.ReactNode } ) {
const { formatRelativeTime } = useFormatLocalizedTimestamps();
const [ pullStates, setPullStates ] = useState< PullStates >( {} );

const getLastSyncTimeText = useCallback< GetLastSyncTimeText >(
( timestamp, type ) => {
Expand Down Expand Up @@ -90,17 +88,12 @@ export function SyncSitesProvider( { children }: { children: React.ReactNode } )

const { pullSite, isAnySitePulling, isSiteIdPulling, clearPullState, getPullState, cancelPull } =
useSyncPull( {
pullStates,
setPullStates,
onPullSuccess: ( remoteSiteId, localSiteId ) =>
updateSiteTimestamp( remoteSiteId, localSiteId, 'pull' ),
} );

const [ pushStates, setPushStates ] = useState< PushStates >( {} );
const { pushSite, isAnySitePushing, isSiteIdPushing, clearPushState, getPushState, cancelPush } =
useSyncPush( {
pushStates,
setPushStates,
onPushSuccess: ( remoteSiteId, localSiteId ) =>
updateSiteTimestamp( remoteSiteId, localSiteId, 'push' ),
} );
Expand All @@ -121,8 +114,6 @@ export function SyncSitesProvider( { children }: { children: React.ReactNode } )
const allSites = await getIpcApi().getSiteDetails();
const allConnectedSites = await getIpcApi().getConnectedWpcomSites();

const restoredStates: PushStates = {};

for ( const connectedSite of allConnectedSites ) {
try {
const localSite = allSites.find( ( site ) => site.id === connectedSite.localSiteId );
Expand All @@ -132,43 +123,43 @@ export function SyncSitesProvider( { children }: { children: React.ReactNode } )
continue;
}

const response = await client.req.get< ImportResponse >(
const response = await client.req.get(
`/sites/${ connectedSite.id }/studio-app/sync/import`,
{
apiNamespace: 'wpcom/v2',
}
);
) as ImportResponse;

const status = mapImportResponseToPushState( response, pushStatesProgressInfo );

// Only restore the pushStates if the operation is still in progress
if ( status ) {
const stateId = generateStateId( connectedSite.localSiteId, connectedSite.id );
restoredStates[ stateId ] = {
dispatch( syncOperationsActions.updatePushState( {
selectedSiteId: connectedSite.localSiteId,
remoteSiteId: connectedSite.id,
status,
selectedSite: localSite,
remoteSiteUrl: connectedSite.url,
};
state: {
remoteSiteId: connectedSite.id,
status,
selectedSite: localSite,
remoteSiteUrl: connectedSite.url,
},
} ) );

const stateId = generateStateId( connectedSite.localSiteId, connectedSite.id );
getIpcApi().addSyncOperation( stateId, status );
}
} catch ( error ) {
// Continue checking other sites even if one fails
console.error( `Failed to check push progress for site ${ connectedSite.id }:`, error );
}
}

if ( Object.keys( restoredStates ).length > 0 ) {
setPushStates( ( prev ) => ( { ...prev, ...restoredStates } ) );
}
};

initializePushStates().catch( ( error ) => {
// Initialization is not critical to app functionality, but log the error
console.error( 'Failed to initialize push states from server:', error );
} );
}, [ client, pushStatesProgressInfo ] );
}, [ client, pushStatesProgressInfo, dispatch ] );

return (
<SyncSitesContext.Provider
Expand Down
46 changes: 35 additions & 11 deletions src/hooks/sync-sites/use-sync-pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
generateStateId,
GetState,
UpdateState,
usePullPushStates,
} from 'src/hooks/sync-sites/use-pull-push-states';
import { useAuth } from 'src/hooks/use-auth';
import { useImportExport } from 'src/hooks/use-import-export';
Expand All @@ -20,6 +19,8 @@ import {
} from 'src/hooks/use-sync-states-progress-info';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { getHostnameFromUrl } from 'src/lib/url-utils';
import { useAppDispatch, useRootSelector } from 'src/stores';
import { syncOperationsActions, syncOperationsSelectors } from 'src/stores/sync';
import type { SyncSite } from 'src/hooks/use-fetch-wpcom-sites/types';
import type { SyncOption } from 'src/types';

Expand Down Expand Up @@ -47,8 +48,6 @@ type PullSite = (
type IsSiteIdPulling = ( selectedSiteId: string, remoteSiteId?: number ) => boolean;

type UseSyncPullProps = {
pullStates: PullStates;
setPullStates: React.Dispatch< React.SetStateAction< PullStates > >;
onPullSuccess?: OnPullSuccess;
};

Expand All @@ -65,10 +64,8 @@ export type UseSyncPull = {
};

export function useSyncPull( {
pullStates,
setPullStates,
onPullSuccess,
}: UseSyncPullProps ): UseSyncPull {
}: UseSyncPullProps = {} ): UseSyncPull {
const { __ } = useI18n();
const { client } = useAuth();
const { importFile, clearImportState } = useImportExport();
Expand All @@ -80,11 +77,38 @@ export function useSyncPull( {
isKeyCancelled,
getBackupStatusWithProgress,
} = useSyncStatesProgressInfo();
const {
updateState,
getState: getPullState,
clearState,
} = usePullPushStates< SyncBackupState >( pullStates, setPullStates );

const dispatch = useAppDispatch();
const pullStates = useRootSelector( syncOperationsSelectors.selectPullStates );

const updateState = useCallback< UpdateState< SyncBackupState > >(
( selectedSiteId, remoteSiteId, state ) => {
dispatch( syncOperationsActions.updatePullState( {
selectedSiteId,
remoteSiteId,
state,
} ) );
},
[ dispatch ]
);

const getPullState = useCallback< GetState< SyncBackupState > >(
( selectedSiteId, remoteSiteId ) => {
const stateId = generateStateId( selectedSiteId, remoteSiteId );
return pullStates[ stateId ];
},
[ pullStates ]
);

const clearState = useCallback< ClearState >(
( selectedSiteId, remoteSiteId ) => {
dispatch( syncOperationsActions.clearPullState( {
selectedSiteId,
remoteSiteId,
} ) );
},
[ dispatch ]
);

const updatePullState = useCallback< UpdateState< SyncBackupState > >(
( selectedSiteId, remoteSiteId, state ) => {
Expand Down
52 changes: 39 additions & 13 deletions src/hooks/sync-sites/use-sync-push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
generateStateId,
GetState,
UpdateState,
usePullPushStates,
} from 'src/hooks/sync-sites/use-pull-push-states';
import { useAuth } from 'src/hooks/use-auth';
import {
Expand All @@ -17,6 +16,8 @@ import {
} from 'src/hooks/use-sync-states-progress-info';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { getHostnameFromUrl } from 'src/lib/url-utils';
import { useAppDispatch, useRootSelector } from 'src/stores';
import { syncOperationsActions, syncOperationsSelectors } from 'src/stores/sync';
import type { SyncSite } from 'src/hooks/use-fetch-wpcom-sites/types';
import type { ImportResponse } from 'src/hooks/use-sync-states-progress-info';
import type { SyncOption } from 'src/types';
Expand All @@ -43,8 +44,6 @@ type PushSite = (
type IsSiteIdPushing = ( selectedSiteId: string, remoteSiteId?: number ) => boolean;

type UseSyncPushProps = {
pushStates: PushStates;
setPushStates: React.Dispatch< React.SetStateAction< PushStates > >;
onPushSuccess?: OnPushSuccess;
};

Expand Down Expand Up @@ -83,18 +82,45 @@ export function mapImportResponseToPushState(
return null;
}

export function useSyncPush( {
pushStates,
setPushStates,
onPushSuccess,
}: UseSyncPushProps ): UseSyncPush {
export function useSyncPush( { onPushSuccess }: UseSyncPushProps = {} ): UseSyncPush {
const { __ } = useI18n();
const { client } = useAuth();
const {
updateState,
getState: getPushState,
clearState,
} = usePullPushStates< SyncPushState >( pushStates, setPushStates );

const dispatch = useAppDispatch();
const pushStates = useRootSelector( syncOperationsSelectors.selectPushStates );

const updateState = useCallback< UpdateState< SyncPushState > >(
( selectedSiteId, remoteSiteId, state ) => {
dispatch(
syncOperationsActions.updatePushState( {
selectedSiteId,
remoteSiteId,
state,
} )
);
},
[ dispatch ]
);

const getPushState = useCallback< GetState< SyncPushState > >(
( selectedSiteId, remoteSiteId ) => {
const stateId = generateStateId( selectedSiteId, remoteSiteId );
return pushStates[ stateId ];
},
[ pushStates ]
);

const clearState = useCallback< ClearState >(
( selectedSiteId, remoteSiteId ) => {
dispatch(
syncOperationsActions.clearPushState( {
selectedSiteId,
remoteSiteId,
} )
);
},
[ dispatch ]
);
const {
pushStatesProgressInfo,
isKeyPushing,
Expand Down
13 changes: 8 additions & 5 deletions src/hooks/use-sync-states-progress-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,14 @@ export function useSyncStatesProgressInfo() {
: response.status;
let newProgressInfo: PullStateProgressInfo | null = null;
if ( response.status === 'in-progress' ) {
newProgressInfo = pullStatesProgressInfo[ frontendStatus ];
// Update progress from the initial value to the new step proportionally to the response.progress
// on every update of the response.progress
newProgressInfo.progress =
IN_PROGRESS_INITIAL_VALUE + IN_PROGRESS_TO_DOWNLOADING_STEP * ( response.percent / 100 );
newProgressInfo = {
...pullStatesProgressInfo[ frontendStatus ],
// Update progress from the initial value to the new step proportionally to the response.progress
// on every update of the response.progress
progress:
IN_PROGRESS_INITIAL_VALUE +
IN_PROGRESS_TO_DOWNLOADING_STEP * ( response.percent / 100 ),
};
}
const statusWithProgress = newProgressInfo || pullStatesProgressInfo[ frontendStatus ];

Expand Down
3 changes: 3 additions & 0 deletions src/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
connectedSitesReducer,
loadAllConnectedSites,
} from 'src/stores/sync/connected-sites-slice';
import { syncOperationsReducer } from 'src/stores/sync/sync-operations-slice';
import { wpcomApi, wpcomPublicApi } from 'src/stores/wpcom-api';
import { wordpressVersionsApi } from './wordpress-versions-api';
import type { SupportedLocale } from 'common/lib/locale';
Expand All @@ -42,6 +43,7 @@ export type RootState = {
snapshot: ReturnType< typeof snapshotReducer >;
sync: ReturnType< typeof syncReducer >;
connectedSites: ReturnType< typeof connectedSitesReducer >;
syncOperations: ReturnType< typeof syncOperationsReducer >;
wordpressVersionsApi: ReturnType< typeof wordpressVersionsApi.reducer >;
wpcomApi: ReturnType< typeof wpcomApi.reducer >;
wpcomPublicApi: ReturnType< typeof wpcomPublicApi.reducer >;
Expand Down Expand Up @@ -98,6 +100,7 @@ export const rootReducer = combineReducers( {
snapshot: snapshotReducer,
sync: syncReducer,
connectedSites: connectedSitesReducer,
syncOperations: syncOperationsReducer,
wordpressVersionsApi: wordpressVersionsApi.reducer,
wpcomApi: wpcomApi.reducer,
wpcomPublicApi: wpcomPublicApi.reducer,
Expand Down
5 changes: 5 additions & 0 deletions src/stores/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ export {
useSyncSitesData,
useConnectedSitesOperations,
} from './connected-sites-hooks';
export {
syncOperationsReducer,
syncOperationsActions,
syncOperationsSelectors,
} from './sync-operations-slice';
export * from './sync-types';
Loading