Spaces:
Configuration error
Configuration error
| import { SyntheticEvent, useEffect, useState } from 'react' | |
| export function dataURItoBlob(dataURI: string) { | |
| const mime = dataURI.split(',')[0].split(':')[1].split(';')[0] | |
| const binary = atob(dataURI.split(',')[1]) | |
| const array = [] | |
| for (let i = 0; i < binary.length; i += 1) { | |
| array.push(binary.charCodeAt(i)) | |
| } | |
| return new Blob([new Uint8Array(array)], { type: mime }) | |
| } | |
| // const dataURItoBlob = (dataURI: string) => { | |
| // const bytes = | |
| // dataURI.split(',')[0].indexOf('base64') >= 0 | |
| // ? atob(dataURI.split(',')[1]) | |
| // : unescape(dataURI.split(',')[1]) | |
| // const mime = dataURI.split(',')[0].split(':')[1].split(';')[0] | |
| // const max = bytes.length | |
| // const ia = new Uint8Array(max) | |
| // for (var i = 0; i < max; i++) ia[i] = bytes.charCodeAt(i) | |
| // return new Blob([ia], { type: mime }) | |
| // } | |
| export function downloadImage(uri: string, name: string) { | |
| const link = document.createElement('a') | |
| link.href = uri | |
| link.download = name | |
| // this is necessary as link.click() does not work on the latest firefox | |
| link.dispatchEvent( | |
| new MouseEvent('click', { | |
| bubbles: true, | |
| cancelable: true, | |
| view: window, | |
| }) | |
| ) | |
| setTimeout(() => { | |
| // For Firefox it is necessary to delay revoking the ObjectURL | |
| // window.URL.revokeObjectURL(base64) | |
| link.remove() | |
| }, 100) | |
| } | |
| export function shareImage(base64: string, name: string) { | |
| const blob = dataURItoBlob(base64) | |
| const filesArray = [new File([blob], name, { type: 'image/jpeg' })] | |
| const shareData = { | |
| files: filesArray, | |
| } | |
| // eslint-disable-nextline | |
| const nav: any = navigator | |
| const canShare = nav.canShare && nav.canShare(shareData) | |
| const userAgent = navigator.userAgent || navigator.vendor | |
| const isMobile = /android|iPad|iPhone|iPod/i.test(userAgent) | |
| if (canShare && isMobile) { | |
| navigator.share(shareData) | |
| return true | |
| } | |
| return false | |
| } | |
| export function loadImage(image: HTMLImageElement, src: string) { | |
| return new Promise((resolve, reject) => { | |
| const initSRC = image.src | |
| const img = image | |
| img.onload = resolve | |
| img.onerror = err => { | |
| img.src = initSRC | |
| reject(err) | |
| } | |
| img.src = src | |
| }) | |
| } | |
| export function useImage(file?: File): [HTMLImageElement, boolean] { | |
| const [image] = useState(new Image()) | |
| const [isLoaded, setIsLoaded] = useState(false) | |
| useEffect(() => { | |
| if (file === undefined) { | |
| return | |
| } | |
| image.onload = () => { | |
| setIsLoaded(true) | |
| } | |
| setIsLoaded(false) | |
| image.src = URL.createObjectURL(file) | |
| return () => { | |
| image.onload = null | |
| } | |
| }, [file, image]) | |
| return [image, isLoaded] | |
| } | |
| // https://stackoverflow.com/questions/23945494/use-html5-to-resize-an-image-before-upload | |
| interface ResizeImageFileResult { | |
| file: File | |
| resized: boolean | |
| originalWidth?: number | |
| originalHeight?: number | |
| } | |
| export function resizeImageFile( | |
| file: File, | |
| maxSize: number | |
| ): Promise<ResizeImageFileResult> { | |
| const reader = new FileReader() | |
| const image = new Image() | |
| const canvas = document.createElement('canvas') | |
| const resize = (): ResizeImageFileResult => { | |
| let { width, height } = image | |
| if (width > height) { | |
| if (width > maxSize) { | |
| height *= maxSize / width | |
| width = maxSize | |
| } | |
| } else if (height > maxSize) { | |
| width *= maxSize / height | |
| height = maxSize | |
| } | |
| if (width === image.width && height === image.height) { | |
| return { file, resized: false } | |
| } | |
| canvas.width = width | |
| canvas.height = height | |
| const ctx = canvas.getContext('2d') | |
| if (!ctx) { | |
| throw new Error('could not get context') | |
| } | |
| canvas.getContext('2d')?.drawImage(image, 0, 0, width, height) | |
| const dataUrl = canvas.toDataURL('image/jpeg') | |
| const blob = dataURItoBlob(dataUrl) | |
| const f = new File([blob], file.name, { | |
| type: file.type, | |
| }) | |
| return { | |
| file: f, | |
| resized: true, | |
| originalWidth: image.width, | |
| originalHeight: image.height, | |
| } | |
| } | |
| return new Promise((resolve, reject) => { | |
| if (!file.type.match(/image.*/)) { | |
| reject(new Error('Not an image')) | |
| return | |
| } | |
| reader.onload = (readerEvent: any) => { | |
| image.onload = () => resolve(resize()) | |
| image.src = readerEvent.target.result | |
| } | |
| reader.readAsDataURL(file) | |
| }) | |
| } | |
| export function keepGUIAlive() { | |
| async function getRequest(url = '') { | |
| const response = await fetch(url, { | |
| method: 'GET', | |
| cache: 'no-cache', | |
| }) | |
| return response.json() | |
| } | |
| const keepAliveServer = () => { | |
| const url = document.location | |
| const route = '/flaskwebgui-keep-server-alive' | |
| getRequest(url + route).then(data => { | |
| return data | |
| }) | |
| } | |
| const intervalRequest = 3 * 1000 | |
| keepAliveServer() | |
| setInterval(keepAliveServer, intervalRequest) | |
| } | |
| export function isRightClick(ev: SyntheticEvent) { | |
| const mouseEvent = ev.nativeEvent as MouseEvent | |
| return mouseEvent.button === 2 | |
| } | |
| export function isMidClick(ev: SyntheticEvent) { | |
| const mouseEvent = ev.nativeEvent as MouseEvent | |
| return mouseEvent.button === 1 | |
| } | |
| export function srcToFile(src: string, fileName: string, mimeType: string) { | |
| return fetch(src) | |
| .then(function (res) { | |
| return res.arrayBuffer() | |
| }) | |
| .then(function (buf) { | |
| return new File([buf], fileName, { type: mimeType }) | |
| }) | |
| } | |
| export async function askWritePermission() { | |
| try { | |
| // The clipboard-write permission is granted automatically to pages | |
| // when they are the active tab. So it's not required, but it's more safe. | |
| const { state } = await navigator.permissions.query({ | |
| name: 'clipboard-write' as PermissionName, | |
| }) | |
| return state === 'granted' | |
| } catch (error) { | |
| // Browser compatibility / Security error (ONLY HTTPS) ... | |
| return false | |
| } | |
| } | |
| function canvasToBlob(canvas: HTMLCanvasElement, mime: string): Promise<any> { | |
| return new Promise((resolve, reject) => | |
| canvas.toBlob(async d => { | |
| if (d) { | |
| resolve(d) | |
| } else { | |
| reject(new Error('Expected toBlob() to be defined')) | |
| } | |
| }, mime) | |
| ) | |
| } | |
| const setToClipboard = async (blob: any) => { | |
| const data = [new ClipboardItem({ [blob.type]: blob })] | |
| await navigator.clipboard.write(data) | |
| } | |
| export async function copyCanvasImage(canvas: HTMLCanvasElement) { | |
| const blob = await canvasToBlob(canvas, 'image/png') | |
| try { | |
| await setToClipboard(blob) | |
| } catch { | |
| console.log('Copy image failed!') | |
| } | |
| } | |