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)zio/stable
parent
6325eff938
commit
d87c232660
|
@ -133,10 +133,12 @@ export async function post(store: RootStoreModel, opts: PostOpts) {
|
|||
opts.onStateChange?.(`Uploading image #${images.length + 1}...`)
|
||||
await image.compress()
|
||||
const path = image.compressed?.path ?? image.path
|
||||
const {width, height} = image.compressed || image
|
||||
const res = await uploadBlob(store, path, 'image/jpeg')
|
||||
images.push({
|
||||
image: res.data.blob,
|
||||
alt: image.altText ?? '',
|
||||
aspectRatio: {width, height},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import {openCropper} from 'lib/media/picker'
|
|||
import {ActionCrop, FlipType, SaveFormat} from 'expo-image-manipulator'
|
||||
import {Position} from 'react-avatar-editor'
|
||||
import {Dimensions} from 'lib/media/types'
|
||||
import {isIOS} from 'platform/detection'
|
||||
|
||||
export interface ImageManipulationAttributes {
|
||||
aspectRatio?: '4:3' | '1:1' | '3:4' | 'None'
|
||||
|
@ -164,8 +165,13 @@ export class ImageModel implements Omit<RNImage, 'size'> {
|
|||
// Mobile
|
||||
async crop() {
|
||||
try {
|
||||
// openCropper requires an output width and height hence
|
||||
// getting upload dimensions before cropping is necessary.
|
||||
// NOTE
|
||||
// on ios, react-native-image-cropper gives really bad quality
|
||||
// without specifying width and height. on android, however, the
|
||||
// crop stretches incorrectly if you do specify it. these are
|
||||
// both separate bugs in the library. we deal with that by
|
||||
// providing width & height for ios only
|
||||
// -prf
|
||||
const {width, height} = this.getUploadDimensions({
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
@ -175,8 +181,7 @@ export class ImageModel implements Omit<RNImage, 'size'> {
|
|||
mediaType: 'photo',
|
||||
path: this.path,
|
||||
freeStyleCropEnabled: true,
|
||||
width,
|
||||
height,
|
||||
...(isIOS ? {width, height} : {}),
|
||||
})
|
||||
|
||||
runInAction(() => {
|
||||
|
|
|
@ -11,6 +11,7 @@ const MAX_ASPECT_RATIO = 5 // 5/1
|
|||
interface Props {
|
||||
alt?: string
|
||||
uri: string
|
||||
dimensionsHint?: Dimensions
|
||||
onPress?: () => void
|
||||
onLongPress?: () => void
|
||||
onPressIn?: () => void
|
||||
|
@ -21,6 +22,7 @@ interface Props {
|
|||
export function AutoSizedImage({
|
||||
alt,
|
||||
uri,
|
||||
dimensionsHint,
|
||||
onPress,
|
||||
onLongPress,
|
||||
onPressIn,
|
||||
|
@ -29,7 +31,7 @@ export function AutoSizedImage({
|
|||
}: Props) {
|
||||
const store = useStores()
|
||||
const [dim, setDim] = React.useState<Dimensions | undefined>(
|
||||
store.imageSizes.get(uri),
|
||||
dimensionsHint || store.imageSizes.get(uri),
|
||||
)
|
||||
const [aspectRatio, setAspectRatio] = React.useState<number>(
|
||||
dim ? calc(dim) : 1,
|
||||
|
|
|
@ -93,7 +93,11 @@ export function PostEmbeds({
|
|||
const {images} = embed
|
||||
|
||||
if (images.length > 0) {
|
||||
const items = embed.images.map(img => ({uri: img.fullsize, alt: img.alt}))
|
||||
const items = embed.images.map(img => ({
|
||||
uri: img.fullsize,
|
||||
alt: img.alt,
|
||||
aspectRatio: img.aspectRatio,
|
||||
}))
|
||||
const openLightbox = (index: number) => {
|
||||
store.shell.openLightbox(new ImagesLightbox(items, index))
|
||||
}
|
||||
|
@ -104,12 +108,13 @@ export function PostEmbeds({
|
|||
}
|
||||
|
||||
if (images.length === 1) {
|
||||
const {alt, thumb} = images[0]
|
||||
const {alt, thumb, aspectRatio} = images[0]
|
||||
return (
|
||||
<View style={[styles.imagesContainer, style]}>
|
||||
<AutoSizedImage
|
||||
alt={alt}
|
||||
uri={thumb}
|
||||
dimensionsHint={aspectRatio}
|
||||
onPress={() => openLightbox(0)}
|
||||
onPressIn={() => onPressIn(0)}
|
||||
style={[
|
||||
|
|
Loading…
Reference in New Issue