feat: add gallery service and ML depth estimation placeholder

Media library access via new expo-media-library Query API,
image resize for wallpaper export, and MiDaS depth map
service stub for V1.5.
This commit is contained in:
Mathis Pruvot
2026-05-28 11:49:23 +00:00
parent bf9649d8fd
commit da5602f3b4
2 changed files with 96 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import * as MediaLibrary from "expo-media-library";
import * as ImageManipulator from "expo-image-manipulator";
import { Dimensions } from "react-native";
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
export async function requestGalleryPermission(): Promise<boolean> {
const { status } = await MediaLibrary.requestPermissionsAsync();
return status === "granted";
}
export async function getRecentPhotos(
count: number = 50,
offset: number = 0
): Promise<{ assets: MediaLibrary.Asset[]; hasMore: boolean }> {
const query = new MediaLibrary.Query()
.eq(MediaLibrary.AssetField.MEDIA_TYPE, MediaLibrary.MediaType.IMAGE)
.orderBy({
key: MediaLibrary.AssetField.CREATION_TIME,
ascending: false,
})
.limit(count)
.offset(offset);
const assets = await query.exe();
return {
assets,
hasMore: assets.length === count,
};
}
export async function prepareImageForWallpaper(
uri: string
): Promise<string> {
const result = await ImageManipulator.manipulateAsync(
uri,
[
{
resize: {
width: SCREEN_WIDTH * 2,
height: SCREEN_HEIGHT * 2,
},
},
],
{ compress: 0.95, format: ImageManipulator.SaveFormat.JPEG }
);
return result.uri;
}

View File

@@ -0,0 +1,46 @@
import { Platform } from "react-native";
// Depth estimation service — V1.5 feature
// Uses MiDaS v2.1 small (TFLite) for on-device depth map generation
// Model size: ~17MB, inference: ~50-80ms on mid-range devices
export interface DepthMapResult {
uri: string; // Path to grayscale depth map PNG
width: number;
height: number;
inferenceTimeMs: number;
}
export async function isDepthEstimationAvailable(): Promise<boolean> {
// Will check for TFLite model availability
// For now, return false — not yet implemented
return false;
}
export async function generateDepthMap(
imageUri: string
): Promise<DepthMapResult> {
// TODO V1.5: Implement with react-native-fast-tflite or ONNX Runtime
//
// Pipeline:
// 1. Load image, resize to MiDaS input size (256x256 or 384x384)
// 2. Normalize to [0,1] float tensor
// 3. Run MiDaS inference
// 4. Resize output to original image dimensions
// 5. Normalize depth values to [0,255] grayscale
// 6. Save as PNG, return URI
//
// The depth map will be cached in MMKV keyed by image URI hash
// to avoid recomputation.
throw new Error(
"Depth estimation not yet available. Coming in V1.5 with MiDaS on-device inference."
);
}
export async function downloadDepthModel(): Promise<void> {
// TODO: Download MiDaS TFLite model from Cloudflare R2
// Model is not bundled in the app to keep binary size down
// Download on first use of depth-parallax animation
throw new Error("Model download not yet implemented.");
}