Skip to content
Draft
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
10 changes: 10 additions & 0 deletions src/lib/format-bytes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function formatBytes( bytes: number ): string {
if ( ! Number.isFinite( bytes ) || bytes <= 0 ) {
return '0 Bytes';
}
const k = 1024;
const units = [ 'Bytes', 'KB', 'MB', 'GB', 'TB' ] as const;
const i = Math.min( Math.floor( Math.log( bytes ) / Math.log( k ) ), units.length - 1 );
const value = bytes / Math.pow( k, i );
return `${ Math.round( value * 100 ) / 100 } ${ units[ i ] }`;
}
13 changes: 3 additions & 10 deletions src/modules/add-site/components/import-backup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,12 @@ import { useCallback, useRef, useState } from 'react';
import Button from 'src/components/button';
import { ACCEPTED_IMPORT_FILE_TYPES } from 'src/constants';
import { cx } from 'src/lib/cx';
import { formatBytes } from 'src/lib/format-bytes';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { getLocalizedLink } from 'src/lib/get-localized-link';
import { useI18nLocale } from 'src/stores';

const formatFileSize = ( bytes: number ) => {
if ( bytes === 0 ) return '0 Bytes';
const k = 1024;
const sizes = [ 'Bytes', 'KB', 'MB', 'GB' ];
const i = Math.floor( Math.log( bytes ) / Math.log( k ) );
return Math.round( ( bytes / Math.pow( k, i ) ) * 100 ) / 100 + ' ' + sizes[ i ];
};
// Replaced by shared `formatBytes` util

const truncateMiddle = ( filename: string, maxLength: number = 30 ): string => {
if ( filename.length <= maxLength ) {
Expand Down Expand Up @@ -158,9 +153,7 @@ export default function ImportBackup( {
{ truncateMiddle( selectedFile.name ) }
</Text>
<HStack spacing={ 2 } alignment="center">
<Text className="text-base text-gray-600">
{ formatFileSize( selectedFile.size ) }
</Text>
<Text className="text-base text-gray-600">{ formatBytes( selectedFile.size ) }</Text>
<button
type="button"
className="text-base text-blue-600 hover:text-blue-700 focus:outline-none"
Expand Down
24 changes: 16 additions & 8 deletions src/modules/sync/components/sync-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TreeView, TreeNode, updateNodeById } from 'src/components/tree-view';
import { SYNC_OPTIONS, SYNC_PUSH_SIZE_LIMIT_GB } from 'src/constants';
import { useContentFolders } from 'src/hooks/use-content-folders';
import { cx } from 'src/lib/cx';
import { formatBytes } from 'src/lib/format-bytes';
import { getIpcApi } from 'src/lib/get-ipc-api';
import { getLocalizedLink } from 'src/lib/get-localized-link';
import { SiteNameBox } from 'src/modules/sync/components/site-name-box';
Expand Down Expand Up @@ -133,12 +134,11 @@ export function SyncDialog( {
const [ showAllFiles, setShowAllFiles ] = useState( false );
const [ treeState, setTreeState ] = useState< TreeNode[] >( defaultTree );
const isSubmitDisabled = treeState.every( ( node ) => ! node.checked && ! node.indeterminate );
const { isPushSelectionOverLimit, isLoading: isSizeCheckLoading } = useSelectedItemsPushSize(
localSite.id,
treeState,
type
);

const {
isPushSelectionOverLimit,
isLoading: isSizeCheckLoading,
selectedSizeInBytes,
} = useSelectedItemsPushSize( localSite.id, treeState, type );
const { fetchChildren, rewindId, isLoadingRewindId, isErrorRewindId } = useDynamicTreeState(
type,
localSite.id,
Expand Down Expand Up @@ -212,7 +212,7 @@ export function SyncDialog( {
onRequestClose={ onRequestClose }
title={ syncTexts.title }
>
<div className={ isPushSelectionOverLimit ? 'pb-[140px]' : 'pb-[70px]' }>
<div>
<div className="px-8 pb-6 pt-1">{ syncTexts.description }</div>
<div className="px-8">
<span className="sr-only">
Expand Down Expand Up @@ -308,7 +308,7 @@ export function SyncDialog( {
</div>
</Tooltip>

<div className="px-8 py-4 absolute left-0 right-0 bottom-0 bg-white z-10">
<div className="px-8 py-4 sticky bottom-0 bg-white z-10">
{ type === 'push' && isPushSelectionOverLimit && (
<Notice status="warning" isDismissible={ false } className="mb-4">
<p data-testid="push-selection-over-limit-notice">
Expand All @@ -321,6 +321,14 @@ export function SyncDialog( {
</p>
</Notice>
) }
{ type === 'push' && ! isSizeCheckLoading && selectedSizeInBytes > 0 && (
<div
className="border border-gray-300 rounded-sm py-2 px-3 text-xs text-gray-600 mb-3 w-full"
data-testid="selected-size"
>
{ sprintf( __( 'PUSH LIMIT: %s' ), formatBytes( selectedSizeInBytes ) ) }
</div>
) }
<div className="flex justify-between items-center">
<div>
{ createInterpolateElement( syncTexts.envSync, {
Expand Down
8 changes: 7 additions & 1 deletion src/modules/sync/hooks/use-selected-items-push-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ export function useSelectedItemsPushSize(
) {
const [ isPushSelectionOverLimit, setIsPushSelectionOverLimit ] = useState( false );
const [ isLoading, setIsLoading ] = useState( false );
const [ selectedSizeInBytes, setSelectedSizeInBytes ] = useState( 0 );

const checkSelectedItemsSize = useCallback( async () => {
if ( ! siteId || ! treeState.length || type !== 'push' ) {
setIsPushSelectionOverLimit( false );
setSelectedSizeInBytes( 0 );
return;
}

Expand All @@ -24,6 +26,7 @@ export function useSelectedItemsPushSize(

if ( isEverythingSelected ) {
const size = await getIpcApi().getDirectorySize( siteId, [ 'wp-content' ] );
setSelectedSizeInBytes( size );
setIsPushSelectionOverLimit( size > SYNC_PUSH_SIZE_LIMIT_BYTES );
return;
}
Expand Down Expand Up @@ -75,13 +78,16 @@ export function useSelectedItemsPushSize(
if ( sizePromises.length > 0 ) {
const sizes = await Promise.all( sizePromises );
const totalSize = sizes.reduce( ( sum, size ) => sum + size, 0 );
setSelectedSizeInBytes( totalSize );
setIsPushSelectionOverLimit( totalSize > SYNC_PUSH_SIZE_LIMIT_BYTES );
} else {
setIsPushSelectionOverLimit( false );
setSelectedSizeInBytes( 0 );
}
} catch ( error ) {
console.error( 'Error checking selected items size:', error );
setIsPushSelectionOverLimit( false );
setSelectedSizeInBytes( 0 );
} finally {
setIsLoading( false );
}
Expand All @@ -92,5 +98,5 @@ export function useSelectedItemsPushSize(
void checkSelectedItemsSize();
}, [ checkSelectedItemsSize ] );

return { isPushSelectionOverLimit, isLoading };
return { isPushSelectionOverLimit, isLoading, selectedSizeInBytes };
}