Skip to content

Commit

Permalink
add initial modal for import asset
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoecheza committed Jan 16, 2025
1 parent d10588b commit 39dfee5
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 10 deletions.
3 changes: 3 additions & 0 deletions packages/@dcl/inspector/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface InputRef {
}

export const FileInput = React.forwardRef<InputRef, React.PropsWithChildren<PropTypes>>((props, parentRef) => {
const { onDrop } = props
const { disabled, onDrop } = props
const acceptExtensions = Object.values(props.accept ?? []).flat()
const inputRef = useRef<HTMLInputElement>(null)

Expand All @@ -27,7 +27,7 @@ export const FileInput = React.forwardRef<InputRef, React.PropsWithChildren<Prop
if (onDrop) onDrop(item.files)
},
canDrop(item: { files: File[] }) {
return item.files.every((file) => !!acceptExtensions.find((ext) => file.name.endsWith(ext)))
return !disabled && item.files.every((file) => !!acceptExtensions.find((ext) => file.name.endsWith(ext)))
},
collect: (monitor) => ({
isHover: monitor.canDrop() && monitor.isOver()
Expand Down Expand Up @@ -60,7 +60,7 @@ export const FileInput = React.forwardRef<InputRef, React.PropsWithChildren<Prop
return (
<div ref={drop}>
<input
disabled={props.disabled}
disabled={disabled}
ref={inputRef}
accept={parseAccept(props.accept)}
type="file"
Expand Down
63 changes: 58 additions & 5 deletions packages/@dcl/inspector/src/components/ImportAsset/ImportAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import { TextField } from '../ui/TextField'
import { Block } from '../Block'
import { Button } from '../Button'
import { AssetPreview } from '../AssetPreview'
import { Modal } from '../Modal'
import { Input } from '../Input'
import { InputRef } from '../FileInput/FileInput'

import { processAssets } from './utils'
import { formatFileName, processAssets, getAssetSize, getAssetResources } from './utils'
import { Asset } from './types'

import './ImportAsset.css'
import { InputRef } from '../FileInput/FileInput'

const ACCEPTED_FILE_TYPES = {
'model/gltf-binary': ['.gltf', '.glb', '.bin'],
Expand All @@ -48,6 +50,7 @@ const ImportAsset = React.forwardRef<InputRef, React.PropsWithChildren<PropTypes
const uploadFile = useAppSelector(selectUploadFile)

const [files, setFiles] = useState<Asset[]>([])
const [screenshots, setScreenshots] = useState<Map<string, string>>(new Map())
const [isHover, setIsHover] = useState(false)
const { basePath, assets } = catalog ?? { basePath: '', assets: [] }

Expand All @@ -68,10 +71,20 @@ const ImportAsset = React.forwardRef<InputRef, React.PropsWithChildren<PropTypes
setIsHover(isHover)
}, [])

function removeAsset(asset: Asset) {
const removeAsset = useCallback((asset: Asset) => {
// e.stopPropagation()
setFiles(files.filter((file) => file.name !== asset.name))
}
}, [])

const handleCloseModal = useCallback(() => {
setFiles([])
setScreenshots(new Map())
}, [])

const handleScreenshot = useCallback((file: Asset) => (thumbnail: string) => {
const map = screenshots.set(formatFileName(file), thumbnail)
setScreenshots(new Map(map))
}, [])

return (
<div className={cx("ImportAsset", { ImportAssetHover: isHover })}>
Expand All @@ -83,7 +96,47 @@ const ImportAsset = React.forwardRef<InputRef, React.PropsWithChildren<PropTypes
</div>
<span className="text">Drop {ACCEPTED_FILE_TYPES_STR} files</span>
</>
) : children}
) : (
<>
{files.map(($, i) => {
const resources = getAssetResources($)
return (
<div key={i} style={{ display: 'none' }}>
<AssetPreview value={$.blob} resources={resources} onScreenshot={handleScreenshot($)} />
</div>
)
})}
{children}
</>
)}
<Modal
isOpen={!!files.length}
onRequestClose={handleCloseModal}
className="ImportAssetModal"
overlayClassName="ImportAssetModalOverlay"
>
<h2>Import Assets</h2>
<div className="slider">
{files.length > 1 && <span className="counter">{files.length}</span>}
<div className="content">
{files.length > 1 && <span className="left"></span>}
<div className="slides">
{files.map(($, i) => {
const name = formatFileName($)
return (
<div className="asset" key={i}>
<img className="thumbnail" src={screenshots.get(name)} />
<Input value={name} />
<span className="size">{getAssetSize($)}</span>
</div>
)
})}
</div>
{files.length > 1 && <span className="right"></span>}
</div>
</div>
<Button type="danger" size="big">IMPORT ALL</Button>
</Modal>
</FileInput>
</div>
)
Expand Down
5 changes: 5 additions & 0 deletions packages/@dcl/inspector/src/components/ImportAsset/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ export type BabylonValidationIssue = {
message: string
pointer: string
}

export const isGltfAsset = (asset: Asset): asset is GltfAsset => {
const _asset = asset as any
return _asset.buffers && _asset.images
}

Check warning on line 33 in packages/@dcl/inspector/src/components/ImportAsset/types.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/types.ts#L31-L33

Added lines #L31 - L33 were not covered by tests
29 changes: 27 additions & 2 deletions packages/@dcl/inspector/src/components/ImportAsset/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GLTFValidation } from '@babylonjs/loaders'

import { FileAsset, GltfAsset, BabylonValidationIssue, ValidationError, Asset, Uri, GltfFile } from './types'
import { FileAsset, GltfAsset, BabylonValidationIssue, ValidationError, Asset, Uri, GltfFile, isGltfAsset } from './types'

const sampleIndex = (list: any[]) => Math.floor(Math.random() * list.length)

Expand Down Expand Up @@ -148,7 +148,7 @@ function extractFileInfo(fileName: string): [string, string] {
return match ? [match[1], match[2]?.toLowerCase() || ""] : [fileName, ""]
}

Check warning on line 149 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L146-L149

Added lines #L146 - L149 were not covered by tests

function formatFileName(file: FileAsset): string {
export function formatFileName(file: FileAsset): string {
return `${file.name}.${file.extension}`
}

Check warning on line 153 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L151-L153

Added lines #L151 - L153 were not covered by tests

Expand Down Expand Up @@ -225,3 +225,28 @@ export async function processAssets(files: File[]): Promise<Asset[]> {
const processedFiles = await Promise.all(files.map(processFile))
return processGltfAssets(processedFiles)
}

Check warning on line 227 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L225-L227

Added lines #L225 - L227 were not covered by tests

export function normalizeBytes(bytes: number): string {
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
let value = bytes;
let unitIndex = 0;

while (value >= 1024 && unitIndex < units.length - 1) {
value /= 1024;
unitIndex++;
}

const roundedValue = Math.round(value * 100) / 100;
return `${roundedValue} ${units[unitIndex]}`;
}

Check warning on line 241 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L229-L241

Added lines #L229 - L241 were not covered by tests

export function getAssetSize(asset: Asset): string {
const resources = getAssetResources(asset)
const sumSize = resources.reduce((size, resource) => size + resource.size, asset.blob.size)
return normalizeBytes(sumSize)
}

Check warning on line 247 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L243-L247

Added lines #L243 - L247 were not covered by tests

export function getAssetResources(asset: Asset): File[] {
if (!isGltfAsset(asset)) return []
return [...asset.buffers, ...asset.images].map(($) => $.blob)
}

Check warning on line 252 in packages/@dcl/inspector/src/components/ImportAsset/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/components/ImportAsset/utils.ts#L249-L252

Added lines #L249 - L252 were not covered by tests

0 comments on commit 39dfee5

Please sign in to comment.