Zoom the FRAME preview instead of the photo, and save to DCIM/Camera

- FRAME tab now pinches the whole view (frame + photo + watermark) in both
  camera and library; one finger pans that view. Preview only: the exported
  file is identical at 1x and while the view is magnified.
- Watermark pinch/drag stay relative and keep priority while the WATERMARK
  row is open, so they still work after returning from the FRAME tab.
- Exports go through a native MediaStore insert into DCIM/Camera, falling
  back to expo-media-library when the native save fails.
This commit is contained in:
2026-09-11 23:09:26 +07:00
parent 40c91d2a75
commit 1d84fe8a4a
4 changed files with 348 additions and 69 deletions
+12
View File
@@ -11,6 +11,9 @@ import { drawFrameOnCanvas, polaroidLayout, POLAROID_CARD, POLAROID_WIN_W, wallf
import { patchJpegDpi } from './jpegDpi';
import { writeJpegExif } from './exifWrite';
import { nextPhotoPath, readPhotoBytes, getDeviceIdentity } from './photoMeta';
import RecipescamExport from '../../modules/recipescam-export';
const stripScheme = (uri: string) => uri.replace(/^file:\/\//, '');
import { applyPhotoRotation } from './skiaImage';
export interface ExportResult {
@@ -746,6 +749,15 @@ export async function processAndExportPhoto(
// viewer; the OS cache purge reclaims them eventually.
const mediaPermission = await MediaLibrary.requestPermissionsAsync();
if (mediaPermission.granted) {
// DCIM/Camera (stock camera location) first: expo-media-library can only
// reach DCIM (root) or Pictures/Camera, so the native module does the
// MediaStore insert. Falls back to the plain expo save if that fails.
try {
const assetId = await RecipescamExport.saveToCameraRollAsync(stripScheme(exportFile), 'image/jpeg');
if (assetId) return { uri: exportFile, savedToLibrary: true, assetId };
} catch (e) {
console.warn('Native DCIM/Camera save failed, falling back to MediaLibrary:', e);
}
try {
const asset = await MediaLibrary.createAssetAsync(exportFile);
return { uri: exportFile, savedToLibrary: true, assetId: asset.id };