|
import { |
|
fileOpen, |
|
fileSave, |
|
FileWithHandle, |
|
FirstFileOpenOptions, |
|
} from 'browser-fs-access' |
|
|
|
export function download(href: string, title: string) { |
|
const a = document.createElement('a') |
|
a.setAttribute('href', href) |
|
a.setAttribute('download', title) |
|
a.click() |
|
} |
|
|
|
export function downloadJson(data: string, fileName: string) { |
|
const blob = new Blob([data], { type: 'text/json' }) |
|
const href = window.URL.createObjectURL(blob) |
|
download(href, fileName) |
|
URL.revokeObjectURL(href) |
|
} |
|
|
|
async function fileOpenLegacy<M extends boolean | undefined = false>( |
|
_options: FirstFileOpenOptions<M> = {} |
|
): Promise<FileWithHandle | FileWithHandle[]> { |
|
let options: FirstFileOpenOptions<M>[] |
|
if (!Array.isArray(_options)) { |
|
options = [_options] |
|
} else options = _options |
|
return new Promise((resolve, reject) => { |
|
const input = document.createElement('input') as HTMLInputElement |
|
input.type = 'file' |
|
const accept = [ |
|
...options.map((option) => option.mimeTypes || []), |
|
...options.map((option) => option.extensions || []), |
|
].join() |
|
input.multiple = options[0].multiple || false |
|
|
|
input.accept = accept || '' |
|
|
|
|
|
input.style.display = 'none' |
|
document.body.append(input) |
|
|
|
const _reject = () => cleanupListenersAndMaybeReject?.(reject) |
|
const _resolve = (value: FileWithHandle | FileWithHandle[]) => { |
|
if (typeof cleanupListenersAndMaybeReject === 'function') { |
|
cleanupListenersAndMaybeReject() |
|
} |
|
resolve(value) |
|
} |
|
|
|
|
|
const cleanupListenersAndMaybeReject = |
|
options[0].legacySetup && |
|
options[0].legacySetup(_resolve, _reject, input) |
|
|
|
const cancelDetector = () => { |
|
window.removeEventListener('focus', cancelDetector) |
|
input.remove() |
|
} |
|
|
|
input.addEventListener('click', () => { |
|
window.addEventListener('focus', cancelDetector) |
|
}) |
|
|
|
input.addEventListener('change', () => { |
|
window.removeEventListener('focus', cancelDetector) |
|
input.remove() |
|
|
|
if (input.files) |
|
_resolve( |
|
input.multiple ? Array.from(input.files) : input.files[0] |
|
) |
|
else { |
|
_reject() |
|
} |
|
}) |
|
|
|
if ('showPicker' in HTMLInputElement.prototype) { |
|
input.showPicker() |
|
} else { |
|
input.click() |
|
} |
|
}) |
|
} |
|
|
|
export async function uploadJson() { |
|
try { |
|
const file = await fileOpenLegacy({ |
|
mimeTypes: ['application/json'], |
|
legacySetup: (_, rejectionHandler) => { |
|
const timeoutId = setTimeout(rejectionHandler, 10_000) |
|
return (reject) => { |
|
clearTimeout(timeoutId) |
|
if (reject) { |
|
console.error('reject') |
|
reject('Failed to Open file') |
|
} |
|
} |
|
}, |
|
}) |
|
|
|
return await new Promise<string>((resolve, reject) => { |
|
const reader = new FileReader() |
|
reader.onload = function () { |
|
resolve(reader.result as string) |
|
} |
|
|
|
reader.onerror = function () { |
|
reject(reader.error) |
|
} |
|
|
|
if (Array.isArray(file) == false) |
|
reader.readAsText(file as FileWithHandle) |
|
else reject("Don't select multiple files") |
|
}) |
|
} catch (error) { |
|
console.log(error) |
|
return null |
|
} |
|
} |
|
|
|
export async function uploadImage() { |
|
try { |
|
const file = await fileOpenLegacy({ |
|
mimeTypes: ['image/*'], |
|
legacySetup: (_, rejectionHandler) => { |
|
const timeoutId = setTimeout(rejectionHandler, 10_000) |
|
return (reject) => { |
|
clearTimeout(timeoutId) |
|
console.log('reject') |
|
if (reject) { |
|
reject('Open file timeout') |
|
} |
|
} |
|
}, |
|
}) |
|
|
|
return await new Promise<string>((resolve, reject) => { |
|
const reader = new FileReader() |
|
reader.onload = function () { |
|
resolve(reader.result as string) |
|
} |
|
|
|
reader.onerror = function () { |
|
reject(reader.error) |
|
} |
|
|
|
if (Array.isArray(file) == false) |
|
reader.readAsDataURL(file as FileWithHandle) |
|
else reject("Don't select multiple files") |
|
}) |
|
} catch (error) { |
|
console.log(error) |
|
return null |
|
} |
|
} |
|
|
|
export async function CopyTextToClipboard(text: string) { |
|
try { |
|
await navigator.clipboard.writeText(text) |
|
} catch (error) { |
|
|
|
const input = document.createElement('input') as HTMLInputElement |
|
input.type = 'text' |
|
input.style.display = 'none' |
|
input.value = text |
|
input.ariaHidden = 'true' |
|
|
|
input.style.all = 'unset' |
|
|
|
input.style.position = 'fixed' |
|
input.style.top = '0' |
|
input.style.clip = 'rect(0, 0, 0, 0)' |
|
|
|
document.body.append(input) |
|
|
|
input.select() |
|
const successful = document.execCommand('copy') |
|
|
|
input.remove() |
|
|
|
if (!successful) { |
|
throw new Error('copy command was unsuccessful') |
|
} |
|
} |
|
} |
|
|