fix(mobile): proper nested-g depth counting for qr-placeholder replacement
This commit is contained in:
@@ -45,24 +45,44 @@ export default function QrScreen() {
|
|||||||
const currentSvgRaw = MOBILE_SVG_TEMPLATES[selectedKey] || MOBILE_SVG_TEMPLATES["qr-4"] || Object.values(MOBILE_SVG_TEMPLATES)[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
|
// Inject the live QR code image directly into the SVG's #qr-placeholder group
|
||||||
// SVG içeriğine başka hiçbir şey dokunulmaz, sadece #qr-placeholder replace edilir
|
// Yorum satırlarını temizle + iç içe <g> taglarını doğru saymak için depth tracking kullan
|
||||||
function buildSvgWithQr(svgRaw: string, pngBase64: string): string {
|
function buildSvgWithQr(svgRaw: string, pngBase64: string): string {
|
||||||
// react-native-svg XML parser <!-- yorum satırlarını --> desteklemez, parse hatası verir
|
// react-native-svg XML parser <!-- yorum satırlarını --> desteklemez
|
||||||
const withoutComments = svgRaw.replace(/<!--[\s\S]*?-->/g, "");
|
const clean = svgRaw.replace(/<!--[\s\S]*?-->/g, "");
|
||||||
|
|
||||||
const qrImgTag = `<g id="qr-placeholder" transform="translate(90, 215)">
|
const startMarker = '<g id="qr-placeholder"';
|
||||||
|
const startIdx = clean.indexOf(startMarker);
|
||||||
|
if (startIdx === -1) return clean;
|
||||||
|
|
||||||
|
// İç içe <g> taglarını sayarak doğru kapanış </g>'yi bul
|
||||||
|
let depth = 0;
|
||||||
|
let i = startIdx;
|
||||||
|
let endIdx = -1;
|
||||||
|
while (i < clean.length - 3) {
|
||||||
|
if (clean[i] === "<") {
|
||||||
|
if (clean[i + 1] === "g" && (clean[i + 2] === " " || clean[i + 2] === ">")) {
|
||||||
|
depth++;
|
||||||
|
} else if (clean[i + 1] === "/" && clean[i + 2] === "g" && clean[i + 3] === ">") {
|
||||||
|
depth--;
|
||||||
|
if (depth === 0) {
|
||||||
|
endIdx = i + 4; // </g> uzunluğu = 4
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endIdx === -1) return clean;
|
||||||
|
|
||||||
|
const qrGroup = `<g id="qr-placeholder" transform="translate(90, 215)">
|
||||||
<rect width="220" height="220" rx="20" fill="#FFFFFF"/>
|
<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"/>
|
<image href="data:image/png;base64,${pngBase64}" x="10" y="10" width="200" height="200" preserveAspectRatio="xMidYMid meet"/>
|
||||||
</g>`;
|
</g>`;
|
||||||
|
|
||||||
return withoutComments.replace(
|
return clean.substring(0, startIdx) + qrGroup + clean.substring(endIdx);
|
||||||
/<g id="qr-placeholder"[\s\S]*?<\/g>/,
|
|
||||||
qrImgTag
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const activeRest = await getActiveRestaurant();
|
const activeRest = await getActiveRestaurant();
|
||||||
@@ -334,10 +354,9 @@ export default function QrScreen() {
|
|||||||
xml={buildSvgWithQr(currentSvgRaw, qr.pngBase64)}
|
xml={buildSvgWithQr(currentSvgRaw, qr.pngBase64)}
|
||||||
width={300}
|
width={300}
|
||||||
height={487.5}
|
height={487.5}
|
||||||
viewBox="0 0 400 650"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</ViewShot>
|
</ViewShot>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user