my fork of the bluesky client

Give a more sensible default crop in the post image picker (related #39)

+47 -6
+16
src/lib/images.ts
··· 112 112 maxSize, 113 113 }) 114 114 } 115 + 116 + export interface Dim { 117 + width: number 118 + height: number 119 + } 120 + export function scaleDownDimensions(dim: Dim, max: Dim): Dim { 121 + if (dim.width < max.width && dim.height < max.height) { 122 + return dim 123 + } 124 + let wScale = dim.width > max.width ? max.width / dim.width : 1 125 + let hScale = dim.height > max.height ? max.height / dim.height : 1 126 + if (wScale < hScale) { 127 + return {width: dim.width * wScale, height: dim.height * wScale} 128 + } 129 + return {width: dim.width * hScale, height: dim.height * hScale} 130 + }
+2
src/state/models/user-local-photos.ts
··· 3 3 import {CameraRoll} from '@react-native-camera-roll/camera-roll' 4 4 import {RootStoreModel} from './root-store' 5 5 6 + export type {PhotoIdentifier} from './../../../node_modules/@react-native-camera-roll/camera-roll/src/CameraRoll' 7 + 6 8 export class UserLocalPhotosModel { 7 9 // state 8 10 photos: PhotoIdentifier[] = []
+29 -6
src/view/com/composer/PhotoCarouselPicker.tsx
··· 6 6 openCamera, 7 7 openCropper, 8 8 } from 'react-native-image-crop-picker' 9 - import {compressIfNeeded} from '../../../lib/images' 9 + import { 10 + UserLocalPhotosModel, 11 + PhotoIdentifier, 12 + } from '../../../state/models/user-local-photos' 13 + import {compressIfNeeded, scaleDownDimensions} from '../../../lib/images' 10 14 import {usePalette} from '../../lib/hooks/usePalette' 11 15 import {useStores} from '../../../state' 16 + 17 + const MAX_WIDTH = 1000 18 + const MAX_HEIGHT = 1000 12 19 13 20 const IMAGE_PARAMS = { 14 21 width: 1000, ··· 25 32 }: { 26 33 selectedPhotos: string[] 27 34 onSelectPhotos: (v: string[]) => void 28 - localPhotos: any 35 + localPhotos: UserLocalPhotosModel 29 36 }) => { 30 37 const pal = usePalette('default') 31 38 const store = useStores() ··· 45 52 }, [store.log, selectedPhotos, onSelectPhotos]) 46 53 47 54 const handleSelectPhoto = useCallback( 48 - async (uri: string) => { 55 + async (item: PhotoIdentifier) => { 49 56 try { 57 + // choose target dimensions based on the original 58 + // this causes the photo cropper to start with the full image "selected" 59 + const {width, height} = scaleDownDimensions( 60 + {width: item.node.image.width, height: item.node.image.height}, 61 + {width: MAX_WIDTH, height: MAX_HEIGHT}, 62 + ) 50 63 const cropperRes = await openCropper({ 51 64 mediaType: 'photo', 52 - path: uri, 65 + path: item.node.image.uri, 53 66 ...IMAGE_PARAMS, 67 + width, 68 + height, 54 69 }) 55 70 const img = await compressIfNeeded(cropperRes, 300000) 56 71 onSelectPhotos([img.path, ...selectedPhotos]) ··· 71 86 const result = [] 72 87 73 88 for (const image of items) { 89 + // choose target dimensions based on the original 90 + // this causes the photo cropper to start with the full image "selected" 91 + const {width, height} = scaleDownDimensions( 92 + {width: image.width, height: image.height}, 93 + {width: MAX_WIDTH, height: MAX_HEIGHT}, 94 + ) 74 95 const cropperRes = await openCropper({ 75 96 mediaType: 'photo', 76 97 path: image.path, 77 98 ...IMAGE_PARAMS, 99 + width, 100 + height, 78 101 }) 79 102 const finalImg = await compressIfNeeded(cropperRes, 300000) 80 103 result.push(finalImg.path) ··· 101 124 onPress={handleOpenGallery}> 102 125 <FontAwesomeIcon icon="image" style={pal.link} size={24} /> 103 126 </TouchableOpacity> 104 - {localPhotos.photos.map((item: any, index: number) => ( 127 + {localPhotos.photos.map((item: PhotoIdentifier, index: number) => ( 105 128 <TouchableOpacity 106 129 testID="openSelectPhotoButton" 107 130 key={`local-image-${index}`} 108 131 style={[pal.border, styles.photoButton]} 109 - onPress={() => handleSelectPhoto(item.node.image.uri)}> 132 + onPress={() => handleSelectPhoto(item)}> 110 133 <Image style={styles.photo} source={{uri: item.node.image.uri}} /> 111 134 </TouchableOpacity> 112 135 ))}