mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at patch-version 165 lines 3.9 kB view raw
1import {Image as RNImage} from 'react-native-image-crop-picker' 2 3import {Dimensions} from './types' 4import {blobToDataUri, getDataUriSize} from './util' 5 6export async function compressIfNeeded( 7 img: RNImage, 8 maxSize: number, 9): Promise<RNImage> { 10 if (img.size < maxSize) { 11 return img 12 } 13 return await doResize(img.path, { 14 width: img.width, 15 height: img.height, 16 mode: 'stretch', 17 maxSize, 18 }) 19} 20 21export interface DownloadAndResizeOpts { 22 uri: string 23 width: number 24 height: number 25 mode: 'contain' | 'cover' | 'stretch' 26 maxSize: number 27 timeout: number 28} 29 30export async function downloadAndResize(opts: DownloadAndResizeOpts) { 31 const controller = new AbortController() 32 const to = setTimeout(() => controller.abort(), opts.timeout || 5e3) 33 const res = await fetch(opts.uri) 34 const resBody = await res.blob() 35 clearTimeout(to) 36 37 const dataUri = await blobToDataUri(resBody) 38 return await doResize(dataUri, opts) 39} 40 41export async function shareImageModal(_opts: {uri: string}) { 42 // TODO 43 throw new Error('TODO') 44} 45 46export async function saveImageToAlbum(_opts: {uri: string; album: string}) { 47 // TODO 48 throw new Error('TODO') 49} 50 51export async function getImageDim(path: string): Promise<Dimensions> { 52 var img = document.createElement('img') 53 const promise = new Promise((resolve, reject) => { 54 img.onload = resolve 55 img.onerror = reject 56 }) 57 img.src = path 58 await promise 59 return {width: img.width, height: img.height} 60} 61 62// internal methods 63// = 64 65interface DoResizeOpts { 66 width: number 67 height: number 68 mode: 'contain' | 'cover' | 'stretch' 69 maxSize: number 70} 71 72async function doResize(dataUri: string, opts: DoResizeOpts): Promise<RNImage> { 73 let newDataUri 74 75 for (let i = 0; i <= 10; i++) { 76 newDataUri = await createResizedImage(dataUri, { 77 width: opts.width, 78 height: opts.height, 79 quality: 1 - i * 0.1, 80 mode: opts.mode, 81 }) 82 if (getDataUriSize(newDataUri) < opts.maxSize) { 83 break 84 } 85 } 86 if (!newDataUri) { 87 throw new Error('Failed to compress image') 88 } 89 return { 90 path: newDataUri, 91 mime: 'image/jpeg', 92 size: getDataUriSize(newDataUri), 93 width: opts.width, 94 height: opts.height, 95 } 96} 97 98function createResizedImage( 99 dataUri: string, 100 { 101 width, 102 height, 103 quality, 104 mode, 105 }: { 106 width: number 107 height: number 108 quality: number 109 mode: 'contain' | 'cover' | 'stretch' 110 }, 111): Promise<string> { 112 return new Promise((resolve, reject) => { 113 const img = document.createElement('img') 114 img.addEventListener('load', () => { 115 const canvas = document.createElement('canvas') 116 const ctx = canvas.getContext('2d') 117 if (!ctx) { 118 return reject(new Error('Failed to resize image')) 119 } 120 121 let scale = 1 122 if (mode === 'cover') { 123 scale = img.width < img.height ? width / img.width : height / img.height 124 } else if (mode === 'contain') { 125 scale = img.width > img.height ? width / img.width : height / img.height 126 } 127 let w = img.width * scale 128 let h = img.height * scale 129 130 canvas.width = w 131 canvas.height = h 132 133 ctx.drawImage(img, 0, 0, w, h) 134 resolve(canvas.toDataURL('image/jpeg', quality)) 135 }) 136 img.addEventListener('error', ev => { 137 reject(ev.error) 138 }) 139 img.src = dataUri 140 }) 141} 142 143export async function saveBytesToDisk( 144 filename: string, 145 bytes: Uint8Array, 146 type: string, 147) { 148 const blob = new Blob([bytes], {type}) 149 const url = URL.createObjectURL(blob) 150 await downloadUrl(url, filename) 151 // Firefox requires a small delay 152 setTimeout(() => URL.revokeObjectURL(url), 100) 153 return true 154} 155 156async function downloadUrl(href: string, filename: string) { 157 const a = document.createElement('a') 158 a.href = href 159 a.download = filename 160 a.click() 161} 162 163export async function safeDeleteAsync() { 164 // no-op 165}