Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Improve image cropping on android and introduce aspect ratio field (#1525)

* Fix image cropping on android

* Store and use aspect ratio field in post images (close #1392)

authored by

Paul Frazee and committed by
GitHub
d87c2326 6325eff9

+21 -7
+2
src/lib/api/index.ts
··· 133 133 opts.onStateChange?.(`Uploading image #${images.length + 1}...`) 134 134 await image.compress() 135 135 const path = image.compressed?.path ?? image.path 136 + const {width, height} = image.compressed || image 136 137 const res = await uploadBlob(store, path, 'image/jpeg') 137 138 images.push({ 138 139 image: res.data.blob, 139 140 alt: image.altText ?? '', 141 + aspectRatio: {width, height}, 140 142 }) 141 143 } 142 144
+9 -4
src/state/models/media/image.ts
··· 8 8 import {ActionCrop, FlipType, SaveFormat} from 'expo-image-manipulator' 9 9 import {Position} from 'react-avatar-editor' 10 10 import {Dimensions} from 'lib/media/types' 11 + import {isIOS} from 'platform/detection' 11 12 12 13 export interface ImageManipulationAttributes { 13 14 aspectRatio?: '4:3' | '1:1' | '3:4' | 'None' ··· 164 165 // Mobile 165 166 async crop() { 166 167 try { 167 - // openCropper requires an output width and height hence 168 - // getting upload dimensions before cropping is necessary. 168 + // NOTE 169 + // on ios, react-native-image-cropper gives really bad quality 170 + // without specifying width and height. on android, however, the 171 + // crop stretches incorrectly if you do specify it. these are 172 + // both separate bugs in the library. we deal with that by 173 + // providing width & height for ios only 174 + // -prf 169 175 const {width, height} = this.getUploadDimensions({ 170 176 width: this.width, 171 177 height: this.height, ··· 175 181 mediaType: 'photo', 176 182 path: this.path, 177 183 freeStyleCropEnabled: true, 178 - width, 179 - height, 184 + ...(isIOS ? {width, height} : {}), 180 185 }) 181 186 182 187 runInAction(() => {
+3 -1
src/view/com/util/images/AutoSizedImage.tsx
··· 11 11 interface Props { 12 12 alt?: string 13 13 uri: string 14 + dimensionsHint?: Dimensions 14 15 onPress?: () => void 15 16 onLongPress?: () => void 16 17 onPressIn?: () => void ··· 21 22 export function AutoSizedImage({ 22 23 alt, 23 24 uri, 25 + dimensionsHint, 24 26 onPress, 25 27 onLongPress, 26 28 onPressIn, ··· 29 31 }: Props) { 30 32 const store = useStores() 31 33 const [dim, setDim] = React.useState<Dimensions | undefined>( 32 - store.imageSizes.get(uri), 34 + dimensionsHint || store.imageSizes.get(uri), 33 35 ) 34 36 const [aspectRatio, setAspectRatio] = React.useState<number>( 35 37 dim ? calc(dim) : 1,
+7 -2
src/view/com/util/post-embeds/index.tsx
··· 93 93 const {images} = embed 94 94 95 95 if (images.length > 0) { 96 - const items = embed.images.map(img => ({uri: img.fullsize, alt: img.alt})) 96 + const items = embed.images.map(img => ({ 97 + uri: img.fullsize, 98 + alt: img.alt, 99 + aspectRatio: img.aspectRatio, 100 + })) 97 101 const openLightbox = (index: number) => { 98 102 store.shell.openLightbox(new ImagesLightbox(items, index)) 99 103 } ··· 104 108 } 105 109 106 110 if (images.length === 1) { 107 - const {alt, thumb} = images[0] 111 + const {alt, thumb, aspectRatio} = images[0] 108 112 return ( 109 113 <View style={[styles.imagesContainer, style]}> 110 114 <AutoSizedImage 111 115 alt={alt} 112 116 uri={thumb} 117 + dimensionsHint={aspectRatio} 113 118 onPress={() => openLightbox(0)} 114 119 onPressIn={() => onPressIn(0)} 115 120 style={[