Skip to content

Commit eb075d1

Browse files
committed
Heif support
1 parent ab946b5 commit eb075d1

6 files changed

Lines changed: 151 additions & 34 deletions

File tree

apps/polycentric/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"expo-font": "~55.0.4",
4848
"expo-haptics": "~55.0.8",
4949
"expo-image": "~55.0.5",
50+
"expo-image-manipulator": "~55.0.17",
5051
"expo-image-picker": "~55.0.10",
5152
"expo-linking": "~55.0.7",
5253
"expo-notifications": "~55.0.0",

apps/polycentric/src/common/components/composites/Fab.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ export function Fab({ onPress, icon, title = '' }: FabProps) {
2121
const shadow =
2222
Platform.OS === 'web'
2323
? {
24-
boxShadow: `0 6px 16px ${withHexOpacity(
25-
theme.palette.primary_900,
26-
isLight ? '28' : '40',
27-
)}`,
28-
}
24+
boxShadow: `0 6px 16px ${withHexOpacity(
25+
theme.palette.primary_900,
26+
isLight ? '28' : '40',
27+
)}`,
28+
}
2929
: {
30-
shadowColor: theme.palette.primary_900,
31-
shadowOpacity: isLight ? 0.16 : 0.26,
32-
shadowRadius: isLight ? 14 : 10,
33-
shadowOffset: { width: 0, height: isLight ? 3 : 4 },
34-
elevation: isLight ? 4 : 6,
35-
};
30+
shadowColor: theme.palette.primary_900,
31+
shadowOpacity: isLight ? 0.16 : 0.26,
32+
shadowRadius: isLight ? 14 : 10,
33+
shadowOffset: { width: 0, height: isLight ? 3 : 4 },
34+
elevation: isLight ? 4 : 6,
35+
};
3636

3737
return (
3838
<View style={[Atoms.absolute, { bottom: 0, right: 0 }, Atoms.p_lg]}>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ImageManipulator, SaveFormat } from 'expo-image-manipulator';
2+
3+
/**
4+
* Decode `uri` (including HEIC/HEIF, which the Rust core can't read) and
5+
* re-encode it as an upright JPEG, returning a new file/blob URI.
6+
*/
7+
export async function normalizeImage(uri: string): Promise<string> {
8+
const rendered = await ImageManipulator.manipulate(uri).renderAsync();
9+
const result = await rendered.saveAsync({
10+
format: SaveFormat.JPEG,
11+
compress: 1,
12+
});
13+
return result.uri;
14+
}

apps/polycentric/src/common/lib/images/processAndUploadImage.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { v2, type PolycentricClient } from '@polycentric/react-native';
22
import { File } from 'expo-file-system';
33
import { isWeb } from '@/src/common/util/platform';
4+
import { normalizeImage } from './normalizeImage';
45

56
/** Default variant edge lengths. */
67
export const DEFAULT_IMAGE_VARIANT_SIZES = [48, 128, 512];
@@ -25,13 +26,18 @@ export async function processAndUploadImage(
2526
const sizes = options.sizes ?? DEFAULT_IMAGE_VARIANT_SIZES;
2627
const mode = options.mode ?? 'fill';
2728

29+
// Decode via the platform's native image pipeline first: this handles
30+
// formats the core can't (HEIC/HEIF) and bakes EXIF orientation into
31+
// upright pixels, so the core only ever sees an upright JPEG.
32+
const normalizedUri = await normalizeImage(uri);
33+
2834
// RN's `fetch` can't read `file://` URIs on Android (and is
2935
// unreliable on iOS), so go through `expo-file-system` on
3036
// native. Web stays on `fetch` to handle `blob:` / `data:` URIs
3137
// from `<input type="file">`.
3238
const buffer = isWeb
33-
? await (await fetch(uri)).arrayBuffer()
34-
: await new File(uri).arrayBuffer();
39+
? await (await fetch(normalizedUri)).arrayBuffer()
40+
: await new File(normalizedUri).arrayBuffer();
3541
const raw = new Uint8Array(buffer);
3642

3743
const variants = await Promise.all(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import { Platform } from 'react-native';
22

33
export const isWeb = Platform.OS === 'web';
4-
export const isIOS = Platform.OS === 'ios';
4+
export const isIOS = Platform.OS === 'ios';

0 commit comments

Comments
 (0)