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}...`)
|
opts.onStateChange?.(`Uploading image #${images.length + 1}...`)
|
||||||
await image.compress()
|
await image.compress()
|
||||||
const path = image.compressed?.path ?? image.path
|
const path = image.compressed?.path ?? image.path
|
||||||
|
const {width, height} = image.compressed || image
|
||||||
const res = await uploadBlob(store, path, 'image/jpeg')
|
const res = await uploadBlob(store, path, 'image/jpeg')
|
||||||
images.push({
|
images.push({
|
||||||
image: res.data.blob,
|
image: res.data.blob,
|
||||||
alt: image.altText ?? '',
|
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 {ActionCrop, FlipType, SaveFormat} from 'expo-image-manipulator'
|
||||||
import {Position} from 'react-avatar-editor'
|
import {Position} from 'react-avatar-editor'
|
||||||
import {Dimensions} from 'lib/media/types'
|
import {Dimensions} from 'lib/media/types'
|
||||||
|
import {isIOS} from 'platform/detection'
|
||||||
|
|
||||||
export interface ImageManipulationAttributes {
|
export interface ImageManipulationAttributes {
|
||||||
aspectRatio?: '4:3' | '1:1' | '3:4' | 'None'
|
aspectRatio?: '4:3' | '1:1' | '3:4' | 'None'
|
||||||
|
@ -164,8 +165,13 @@ export class ImageModel implements Omit<RNImage, 'size'> {
|
||||||
// Mobile
|
// Mobile
|
||||||
async crop() {
|
async crop() {
|
||||||
try {
|
try {
|
||||||
// openCropper requires an output width and height hence
|
// NOTE
|
||||||
// getting upload dimensions before cropping is necessary.
|
// 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({
|
const {width, height} = this.getUploadDimensions({
|
||||||
width: this.width,
|
width: this.width,
|
||||||
height: this.height,
|
height: this.height,
|
||||||
|
@ -175,8 +181,7 @@ export class ImageModel implements Omit<RNImage, 'size'> {
|
||||||
mediaType: 'photo',
|
mediaType: 'photo',
|
||||||
path: this.path,
|
path: this.path,
|
||||||
freeStyleCropEnabled: true,
|
freeStyleCropEnabled: true,
|
||||||
width,
|
...(isIOS ? {width, height} : {}),
|
||||||
height,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
|
|
|
@ -11,6 +11,7 @@ const MAX_ASPECT_RATIO = 5 // 5/1
|
||||||
interface Props {
|
interface Props {
|
||||||
alt?: string
|
alt?: string
|
||||||
uri: string
|
uri: string
|
||||||
|
dimensionsHint?: Dimensions
|
||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
onLongPress?: () => void
|
onLongPress?: () => void
|
||||||
onPressIn?: () => void
|
onPressIn?: () => void
|
||||||
|
@ -21,6 +22,7 @@ interface Props {
|
||||||
export function AutoSizedImage({
|
export function AutoSizedImage({
|
||||||
alt,
|
alt,
|
||||||
uri,
|
uri,
|
||||||
|
dimensionsHint,
|
||||||
onPress,
|
onPress,
|
||||||
onLongPress,
|
onLongPress,
|
||||||
onPressIn,
|
onPressIn,
|
||||||
|
@ -29,7 +31,7 @@ export function AutoSizedImage({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const [dim, setDim] = React.useState<Dimensions | undefined>(
|
const [dim, setDim] = React.useState<Dimensions | undefined>(
|
||||||
store.imageSizes.get(uri),
|
dimensionsHint || store.imageSizes.get(uri),
|
||||||
)
|
)
|
||||||
const [aspectRatio, setAspectRatio] = React.useState<number>(
|
const [aspectRatio, setAspectRatio] = React.useState<number>(
|
||||||
dim ? calc(dim) : 1,
|
dim ? calc(dim) : 1,
|
||||||
|
|
|
@ -93,7 +93,11 @@ export function PostEmbeds({
|
||||||
const {images} = embed
|
const {images} = embed
|
||||||
|
|
||||||
if (images.length > 0) {
|
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) => {
|
const openLightbox = (index: number) => {
|
||||||
store.shell.openLightbox(new ImagesLightbox(items, index))
|
store.shell.openLightbox(new ImagesLightbox(items, index))
|
||||||
}
|
}
|
||||||
|
@ -104,12 +108,13 @@ export function PostEmbeds({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (images.length === 1) {
|
if (images.length === 1) {
|
||||||
const {alt, thumb} = images[0]
|
const {alt, thumb, aspectRatio} = images[0]
|
||||||
return (
|
return (
|
||||||
<View style={[styles.imagesContainer, style]}>
|
<View style={[styles.imagesContainer, style]}>
|
||||||
<AutoSizedImage
|
<AutoSizedImage
|
||||||
alt={alt}
|
alt={alt}
|
||||||
uri={thumb}
|
uri={thumb}
|
||||||
|
dimensionsHint={aspectRatio}
|
||||||
onPress={() => openLightbox(0)}
|
onPress={() => openLightbox(0)}
|
||||||
onPressIn={() => onPressIn(0)}
|
onPressIn={() => onPressIn(0)}
|
||||||
style={[
|
style={[
|
||||||
|
|
Loading…
Reference in New Issue