Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(aws-amplify-react-native): Add S3Text #6594

Closed
wants to merge 9 commits into from
Closed
4 changes: 4 additions & 0 deletions packages/aws-amplify-react-native/src/AmplifyTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,8 @@ export default StyleSheet.create({
textAlign: 'center',
padding: 20,
},
text: {
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
color: '#152939',
ashika01 marked this conversation as resolved.
Show resolved Hide resolved
fontSize: 14,
},
});
162 changes: 162 additions & 0 deletions packages/aws-amplify-react-native/src/Storage/S3Text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React, { useEffect, useState } from 'react';
import { Text, StyleSheet, StyleProp, TextStyle } from 'react-native';
import { Storage, Logger, I18n } from 'aws-amplify';

import AmplifyTheme, { AmplifyThemeType } from '../AmplifyTheme';
import { AccessLevel } from './common/types';

const logger = new Logger('Storage.S3Text');

interface IS3TextProps {
textKey?: string;
path?: string;
body?: string;
contentType?: string;
ashika01 marked this conversation as resolved.
Show resolved Hide resolved
level?: AccessLevel;
track?: boolean;
identityId?: string;
fallbackText?: string;
style?: StyleProp<TextStyle>;
theme?: AmplifyThemeType;
}

export const S3Text = ({
textKey,
path,
body,
contentType = 'text/*',
level = AccessLevel.Public,
track = false,
identityId,
fallbackText = 'Fallback Content',
style,
theme = AmplifyTheme,
}: IS3TextProps) => {
const [text, error] = useS3Text({
textKey,
path,
level,
track,
identityId,
body,
contentType,
});

const textStyle = Object.assign({}, StyleSheet.flatten(theme.text), style);
amhinson marked this conversation as resolved.
Show resolved Hide resolved

return <Text style={textStyle}>{error ? I18n.get(fallbackText) : text}</Text>;
};

interface IUseS3Text {
textKey?: string;
path?: string;
amhinson marked this conversation as resolved.
Show resolved Hide resolved
level: AccessLevel;
track: boolean;
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
identityId?: string;
body?: string;
contentType: string;
}

export const useS3Text = ({
textKey,
path,
level = AccessLevel.Public,
track = false,
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
identityId = '',
body,
contentType = 'text/*',
}: IUseS3Text): [string?, Error?] => {
if (!textKey && !path) {
logger.debug('empty textKey and path');
return [undefined, new Error('empty textKey and path')];
}

const key = (textKey ?? path) as string;

const [text, setText] = useState<string | undefined>();
const [error, setError] = useState<Error | undefined>();
amhinson marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
(async () => {
logger.debug(`loading ${key}...`);

if (body && textKey) {
try {
const data = await Storage.put(textKey, body, {
contentType,
level,
track,
});

logger.debug('uploading data:', data);
} catch (error) {
logger.error(error);
setError(error);
return;
}
}

try {
const source = await getTextSource(
key,
level,
track,
identityId,
logger
);

setText(source);
} catch (error) {
logger.error(error);
setError(error);
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
}
})();
}, [textKey, path, body]);

return [text, error];
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
};

// helper methods from /packages/amplify-ui-components/src/common/storage-helpers.ts

const readFileAsync = (blob: Blob) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();

reader.onload = () => {
resolve(reader.result as string);
};

reader.onerror = () => {
reject('Failed to read file!');
reader.abort();
};

reader.readAsText(blob);
});
};

export const getTextSource = async (
key: string,
level: AccessLevel,
track: boolean,
identityId: string,
logger: Logger
) => {
if (!Storage || typeof Storage.get !== 'function') {
throw new Error();
cedricgrothues marked this conversation as resolved.
Show resolved Hide resolved
}
try {
const textSrc = await Storage.get(key, {
download: true,
level,
track,
identityId,
});

logger.debug(textSrc);
let text = (await readFileAsync(textSrc['Body'])) as string;
return text;
} catch (error) {
throw new Error(error);
}
};
5 changes: 5 additions & 0 deletions packages/aws-amplify-react-native/src/Storage/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum AccessLevel {
Public = 'public',
Private = 'private',
Protected = 'protected',
}
1 change: 1 addition & 0 deletions packages/aws-amplify-react-native/src/Storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

export { default as S3Image } from './S3Image';
export { default as S3Album } from './S3Album';
export { S3Text, useS3Text } from './S3Text';