feat: support dataUri for android platform (#2396)

# Summary
Closes #1318 
Add support data URI in the Android platform. It already works on the iOS platform.

| Before1 | Before2 | After |
|--------|--------|--------|
|<img
src="https://github.com/user-attachments/assets/4423ae12-0e67-4ff9-9a15-76fc6b707b26"
width="300" height="600" /> | <img
src="https://github.com/user-attachments/assets/a4412e8e-d965-41e9-95f3-06bffc6ebb76"
width="300" height="600" /> | <img
src="https://github.com/user-attachments/assets/69ba40ac-de52-4edf-9850-ea870270f426"
width="300" height="600" /> |

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
This commit is contained in:
Bohdan Artiukhov
2024-08-19 08:55:03 +02:00
committed by GitHub
parent b80f102b09
commit 7cf90f2f10
6 changed files with 66 additions and 13 deletions

View File

@@ -2,7 +2,6 @@ import Shape from './elements/Shape';
import {
AstProps,
camelCase,
fetchText,
JsxAST,
Middleware,
parse,
@@ -19,6 +18,8 @@ import {
XmlState,
} from './xml';
import { fetchText } from './utils/fetchData';
import {
RNSVGCircle,
RNSVGClipPath,

View File

@@ -1,7 +1,6 @@
import {
AstProps,
camelCase,
fetchText,
JsxAST,
Middleware,
parse,
@@ -18,6 +17,8 @@ import {
XmlState,
} from './xml';
import { fetchText } from './utils/fetchData';
export {
inlineStyles,
loadLocalRawResource,

29
src/utils/fetchData.ts Normal file
View File

@@ -0,0 +1,29 @@
import { Platform } from 'react-native';
export async function fetchText(uri?: string): Promise<string | null> {
if (!uri) {
return null;
}
if (uri.startsWith('data:image/svg+xml;utf8') && Platform.OS === 'android') {
return dataUriToXml(uri);
} else {
return fetchUriData(uri);
}
}
function dataUriToXml(uri: string): string | null {
try {
// decode and remove data:image/svg+xml;utf8, prefix
return decodeURIComponent(uri).split(',').slice(1).join(',');
} catch (error) {
throw new Error(`Decoding ${uri} failed with error: ${error}`);
}
}
async function fetchUriData(uri: string) {
const response = await fetch(uri);
if (response.ok || (response.status === 0 && uri.startsWith('file://'))) {
return await response.text();
}
throw new Error(`Fetching ${uri} failed with status ${response.status}`);
}

View File

@@ -1,6 +1,7 @@
import type { ComponentType, ComponentProps } from 'react';
import * as React from 'react';
import { Component, useEffect, useMemo, useState } from 'react';
import { fetchText } from './utils/fetchData';
import type { SvgProps } from './elements/Svg';
import { tags } from './xmlTags';
@@ -78,17 +79,6 @@ export function SvgXml(props: XmlProps) {
}
}
export async function fetchText(uri?: string) {
if (!uri) {
return null;
}
const response = await fetch(uri);
if (response.ok || (response.status === 0 && uri.startsWith('file://'))) {
return await response.text();
}
throw new Error(`Fetching ${uri} failed with status ${response.status}`);
}
export function SvgUri(props: UriProps) {
const { onError = err, uri, onLoad, fallback } = props;
const [xml, setXml] = useState<string | null>(null);