fix(mobile): inject QR directly into SVG XML for pixel-perfect placement

This commit is contained in:
AyrisAI
2026-08-20 23:56:37 +03:00
parent 808097377d
commit fa50e73198
5 changed files with 300 additions and 31 deletions
+25 -31
View File
@@ -3,7 +3,6 @@ import { router } from "expo-router";
import {
ActivityIndicator,
Alert,
Image,
Pressable,
ScrollView,
Share,
@@ -45,6 +44,23 @@ export default function QrScreen() {
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || Object.values(QR_STAND_PRESETS)[0])!;
const currentSvgRaw = MOBILE_SVG_TEMPLATES[selectedKey] || MOBILE_SVG_TEMPLATES["qr-4"] || Object.values(MOBILE_SVG_TEMPLATES)[0] || "";
// Inject the live QR code image directly into the SVG's #qr-placeholder group
function buildSvgWithQr(svgRaw: string, pngBase64: string): string {
const qrImgTag = `<g id="qr-placeholder" transform="translate(90, 215)">
<rect width="220" height="220" rx="20" fill="#FFFFFF"/>
<image href="data:image/png;base64,${pngBase64}" x="10" y="10" width="200" height="200" preserveAspectRatio="xMidYMid meet"/>
</g>`;
// Replace the entire qr-placeholder group
const replaced = svgRaw.replace(
/<g id="qr-placeholder"[\s\S]*?<\/g>/,
qrImgTag
);
// Also ensure the SVG scales properly by setting width/height to 100%
return replaced
.replace(/width="400"/, 'width="100%"')
.replace(/height="650"/, 'height="100%"');
}
useEffect(() => {
(async () => {
const activeRest = await getActiveRestaurant();
@@ -301,47 +317,25 @@ export default function QrScreen() {
}}
>
<ViewShot ref={viewShotRef} options={{ format: "png", quality: 1.0 }}>
{/* SVG with QR code injected directly — no overlay, pixel-perfect */}
<View
style={{
width: 300,
height: 487.5,
borderRadius: 24,
overflow: "hidden",
position: "relative",
backgroundColor: "#0C0C0E",
}}
>
{/* Exact Vector SVG Artwork */}
{currentSvgRaw ? (
<SvgXml xml={currentSvgRaw} width={300} height={487.5} />
) : null}
{/* Centered QR Code Box Overlay */}
<View
style={{
position: "absolute",
top: 161.25, // (215 / 650) * 487.5
left: 67.5, // (90 / 400) * 300
width: 165, // (220 / 400) * 300
height: 165,
borderRadius: 15,
backgroundColor: "#FFFFFF",
padding: 8,
alignItems: "center",
justifyContent: "center",
shadowColor: "#000",
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 4,
}}
>
<Image
source={{ uri: `data:image/png;base64,${qr.pngBase64}` }}
style={{ width: "100%", height: "100%", borderRadius: 8 }}
resizeMode="contain"
<SvgXml
xml={buildSvgWithQr(currentSvgRaw, qr.pngBase64)}
width={300}
height={487.5}
viewBox="0 0 400 650"
preserveAspectRatio="xMidYMid meet"
/>
</View>
) : null}
</View>
</ViewShot>
</View>