2024-08-16 07:15:42 -04:00
|
|
|
import { isDesktop } from './isDesktop'
|
2023-08-02 16:23:17 -07:00
|
|
|
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
|
|
|
import { browserSaveFile } from './browserSaveFile'
|
|
|
|
|
2024-03-14 11:50:46 -04:00
|
|
|
import JSZip from 'jszip'
|
2024-08-04 00:51:30 -04:00
|
|
|
import ModelingAppFile from './modelingAppFile'
|
2024-09-17 19:06:06 -04:00
|
|
|
import toast from 'react-hot-toast'
|
|
|
|
import { EXPORT_TOAST_MESSAGES } from './constants'
|
2024-03-14 11:50:46 -04:00
|
|
|
|
2024-09-17 19:06:06 -04:00
|
|
|
const save_ = async (file: ModelingAppFile, toastId: string) => {
|
2023-08-02 16:23:17 -07:00
|
|
|
try {
|
2024-08-16 07:15:42 -04:00
|
|
|
if (isDesktop()) {
|
2024-05-06 13:07:35 -07:00
|
|
|
const extension = file.name.split('.').pop() || null
|
|
|
|
let extensions: string[] = []
|
|
|
|
if (extension !== null) {
|
|
|
|
extensions.push(extension)
|
|
|
|
}
|
|
|
|
|
2024-09-04 13:12:16 -07:00
|
|
|
if (window.electron.process.env.IS_PLAYWRIGHT) {
|
2024-08-19 16:29:44 +10:00
|
|
|
// skip file picker, save to default location
|
|
|
|
await window.electron.writeFile(
|
|
|
|
file.name,
|
|
|
|
new Uint8Array(file.contents)
|
|
|
|
)
|
2024-09-17 19:06:06 -04:00
|
|
|
toast.success(EXPORT_TOAST_MESSAGES.SUCCESS, { id: toastId })
|
2024-08-19 16:29:44 +10:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-03-14 11:50:46 -04:00
|
|
|
// Open a dialog to save the file.
|
2024-08-16 07:15:42 -04:00
|
|
|
const filePathMeta = await window.electron.save({
|
2024-03-14 11:50:46 -04:00
|
|
|
defaultPath: file.name,
|
2024-05-06 13:07:35 -07:00
|
|
|
filters: [
|
|
|
|
{
|
|
|
|
name: 'model',
|
|
|
|
extensions: extensions,
|
|
|
|
},
|
|
|
|
],
|
2024-03-14 11:50:46 -04:00
|
|
|
})
|
|
|
|
|
2024-08-16 07:15:42 -04:00
|
|
|
// The user canceled the save.
|
|
|
|
// Return early.
|
2024-09-17 19:06:06 -04:00
|
|
|
if (filePathMeta.canceled) {
|
|
|
|
toast.dismiss(toastId)
|
|
|
|
return
|
|
|
|
}
|
2024-03-14 11:50:46 -04:00
|
|
|
|
|
|
|
// Write the file.
|
2024-08-16 07:15:42 -04:00
|
|
|
await window.electron.writeFile(
|
|
|
|
filePathMeta.filePath,
|
|
|
|
new Uint8Array(file.contents)
|
|
|
|
)
|
2024-09-17 19:06:06 -04:00
|
|
|
toast.success(EXPORT_TOAST_MESSAGES.SUCCESS, { id: toastId })
|
2024-03-14 11:50:46 -04:00
|
|
|
} else {
|
|
|
|
// Download the file to the user's computer.
|
|
|
|
// Now we need to download the files to the user's downloads folder.
|
|
|
|
// Or the destination they choose.
|
|
|
|
// Iterate over the files.
|
|
|
|
// Create a new blob.
|
|
|
|
const blob = new Blob([new Uint8Array(file.contents)])
|
|
|
|
// Save the file.
|
2024-09-17 19:06:06 -04:00
|
|
|
await browserSaveFile(blob, file.name, toastId)
|
2023-08-02 16:23:17 -07:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// TODO: do something real with the error.
|
2024-08-04 00:51:30 -04:00
|
|
|
console.error('export error', e)
|
2024-09-17 19:06:06 -04:00
|
|
|
toast.error(EXPORT_TOAST_MESSAGES.FAILED, { id: toastId })
|
2023-08-02 16:23:17 -07:00
|
|
|
}
|
|
|
|
}
|
2024-03-14 11:50:46 -04:00
|
|
|
|
|
|
|
// Saves files locally from an export call.
|
2024-09-17 19:06:06 -04:00
|
|
|
export async function exportSave(data: ArrayBuffer, toastId: string) {
|
2024-03-14 11:50:46 -04:00
|
|
|
// This converts the ArrayBuffer to a Rust equivalent Vec<u8>.
|
|
|
|
let uintArray = new Uint8Array(data)
|
|
|
|
|
2024-05-06 13:07:35 -07:00
|
|
|
let files: ModelingAppFile[] = deserialize_files(uintArray)
|
2024-03-14 11:50:46 -04:00
|
|
|
|
|
|
|
if (files.length > 1) {
|
|
|
|
let zip = new JSZip()
|
|
|
|
for (const file of files) {
|
|
|
|
zip.file(file.name, new Uint8Array(file.contents), { binary: true })
|
|
|
|
}
|
|
|
|
return zip.generateAsync({ type: 'array' }).then((contents) => {
|
2024-09-17 19:06:06 -04:00
|
|
|
return save_({ name: 'output.zip', contents }, toastId)
|
2024-03-14 11:50:46 -04:00
|
|
|
})
|
|
|
|
} else {
|
2024-09-17 19:06:06 -04:00
|
|
|
return save_(files[0], toastId)
|
2024-03-14 11:50:46 -04:00
|
|
|
}
|
|
|
|
}
|