diff --git a/android/app/src/main/java/com/lensapp/PdfGeneratorModule.kt b/android/app/src/main/java/com/lensapp/PdfGeneratorModule.kt
index f3674ee..fde28bd 100644
--- a/android/app/src/main/java/com/lensapp/PdfGeneratorModule.kt
+++ b/android/app/src/main/java/com/lensapp/PdfGeneratorModule.kt
@@ -28,6 +28,61 @@ class PdfGeneratorModule(private val reactContext: ReactApplicationContext) :
return out
}
+ @ReactMethod
+ fun generateIdCard(imagePaths: ReadableArray, fileName: String, matrix: ReadableArray, promise: Promise) {
+ try {
+ val count = imagePaths.size()
+ if (count == 0) throw Exception("No images provided")
+ val outDir = File(reactContext.filesDir, "pdfs").also { it.mkdirs() }
+ val outFile = File(outDir, "$fileName.pdf")
+ val doc = PdfDocument()
+
+ // A4 portrait: 595 x 842 points
+ val pageWidth = 595
+ val pageHeight = 842
+ val slotW = 250
+ val slotH = 180
+ val gap = 16
+ val totalW = slotW * 2 + gap
+ val startX = (pageWidth - totalW) / 2f
+ val startY = (pageHeight - slotH) / 2f
+
+ val numPages = (count + 1) / 2
+ for (p in 0 until numPages) {
+ val pageInfo = PdfDocument.PageInfo.Builder(pageWidth, pageHeight, p + 1).create()
+ val page = doc.startPage(pageInfo)
+
+ for (slot in 0 until 2) {
+ val imgIndex = p * 2 + slot
+ if (imgIndex >= count) break
+
+ val path = imagePaths.getString(imgIndex)!!.removePrefix("file://")
+ val raw = BitmapFactory.decodeFile(path) ?: throw Exception("Failed to decode image: $path")
+ val bitmap = applyFilter(raw, matrix)
+ if (raw !== bitmap) raw.recycle()
+
+ val slotLeft = startX + slot * (slotW + gap)
+ val scale = minOf(slotW.toFloat() / bitmap.width, slotH.toFloat() / bitmap.height)
+ val scaledW = bitmap.width * scale
+ val scaledH = bitmap.height * scale
+ val left = slotLeft + (slotW - scaledW) / 2f
+ val top = startY + (slotH - scaledH) / 2f
+
+ page.canvas.drawBitmap(bitmap, null, RectF(left, top, left + scaledW, top + scaledH), null)
+ bitmap.recycle()
+ }
+
+ doc.finishPage(page)
+ }
+
+ FileOutputStream(outFile).use { doc.writeTo(it) }
+ doc.close()
+ promise.resolve("file://${outFile.absolutePath}")
+ } catch (e: Exception) {
+ promise.reject("PDF_ERROR", e.message, e)
+ }
+ }
+
@ReactMethod
fun generate(imagePaths: ReadableArray, fileName: String, matrix: ReadableArray, promise: Promise) {
try {
diff --git a/patches/react-native-document-scanner-plugin+2.0.4.patch b/patches/react-native-document-scanner-plugin+2.0.4.patch
index e7abe22..9b145b3 100644
--- a/patches/react-native-document-scanner-plugin+2.0.4.patch
+++ b/patches/react-native-document-scanner-plugin+2.0.4.patch
@@ -1,3 +1,16 @@
+diff --git a/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerModule.kt b/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerModule.kt
+index fbb6836..e75b6b2 100644
+--- a/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerModule.kt
++++ b/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerModule.kt
+@@ -51,7 +51,7 @@ class DocumentScannerModule(reactContext: ReactApplicationContext) :
+
+ val documentScannerOptionsBuilder = GmsDocumentScannerOptions.Builder()
+ .setResultFormats(GmsDocumentScannerOptions.RESULT_FORMAT_JPEG)
+- .setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_FULL)
++ .setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_BASE)
+
+ if (options.hasKey("maxNumDocuments")) {
+ documentScannerOptionsBuilder.setPageLimit(
diff --git a/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerPackage.kt b/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerPackage.kt
index 84f3fec..54a8f53 100644
--- a/node_modules/react-native-document-scanner-plugin/android/src/main/java/com/documentscanner/DocumentScannerPackage.kt
diff --git a/src/screens/ViewerScreen.tsx b/src/screens/ViewerScreen.tsx
index 09ed081..241317b 100644
--- a/src/screens/ViewerScreen.tsx
+++ b/src/screens/ViewerScreen.tsx
@@ -16,7 +16,7 @@ import {
import Share from 'react-native-share';
import {ColorMatrix} from 'react-native-color-matrix-image-filters';
import {ScannedDocument} from '../types';
-import {generatePdf} from '../utils/generatePdf';
+import {generatePdf, generateIdCardPdf} from '../utils/generatePdf';
import {getFilterMatrix} from '../utils/filterMatrices';
import {useTheme} from '../theme';
@@ -36,6 +36,25 @@ export default function ViewerScreen({document, onBack, onDelete, onRename}: Pro
const [renaming, setRenaming] = useState(false);
const [renameText, setRenameText] = useState('');
+ const shareIdCard = async () => {
+ setGenerating(true);
+ await new Promise(resolve => setTimeout(resolve, 0));
+ try {
+ const label = `${document.name} — ID Card`;
+ const pdfPath = await generateIdCardPdf(document.pages, label, document.filter);
+ await Share.open({
+ title: label,
+ type: 'application/pdf',
+ url: pdfPath,
+ failOnCancel: false,
+ });
+ } catch (err: any) {
+ Alert.alert('Share failed', err?.message ?? 'Could not generate PDF.');
+ } finally {
+ setGenerating(false);
+ }
+ };
+
const sharePdf = async (pageIndices?: number[]) => {
setGenerating(true);
await new Promise(resolve => setTimeout(resolve, 0));
@@ -132,6 +151,10 @@ export default function ViewerScreen({document, onBack, onDelete, onRename}: Pro
📄
Share All
+
+ 🪪
+ ID Card
+
{setRenameText(document.name); setRenaming(true);}}>
diff --git a/src/utils/generatePdf.ts b/src/utils/generatePdf.ts
index 160972e..34f1997 100644
--- a/src/utils/generatePdf.ts
+++ b/src/utils/generatePdf.ts
@@ -9,3 +9,9 @@ export async function generatePdf(pages: ScannedPage[], name: string, filter: Fi
const fileName = name.replace(/[^a-z0-9_\-]/gi, '_');
return PdfGenerator.generate(imagePaths, fileName, getFilterMatrix(filter));
}
+
+export async function generateIdCardPdf(pages: ScannedPage[], name: string, filter: FilterMode = 'original'): Promise {
+ const imagePaths = pages.map(p => p.uri);
+ const fileName = name.replace(/[^a-z0-9_\-]/gi, '_');
+ return PdfGenerator.generateIdCard(imagePaths, fileName, getFilterMatrix(filter));
+}