Skip to content

Commit

Permalink
improve moment on feed
Browse files Browse the repository at this point in the history
  • Loading branch information
aldhosutra committed Dec 4, 2022
1 parent 75d13cb commit 92f4064
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 48 deletions.
7 changes: 6 additions & 1 deletion src/components/atoms/image/AppNetworkImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ export default function AppNetworkImage({
errorComponent ? (
errorComponent
) : (
<AppIconComponent name={iconMap.error} size={30} color={theme.colors.placeholder} style={styles.errorComponent} />
<AppIconComponent
name={iconMap.error}
size={30}
color={theme.colors.placeholder}
style={[styles.errorComponent, style]}
/>
)
) : fallbackError ? (
<AppFastImage url={fallbackUrl!} style={style} onLoad={onLoad} onError={onShowError} loaderSize={loaderSize} />
Expand Down
86 changes: 61 additions & 25 deletions src/components/molecules/comment/AppMentionRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import AppTextBody4 from 'enevti-app/components/atoms/text/AppTextBody4';
import AppTextHeading4 from 'enevti-app/components/atoms/text/AppTextHeading4';
import { Part, isMentionPartType, PartType, parseValue } from 'react-native-controlled-mentions';
import { useTheme } from 'react-native-paper';
import { Theme } from 'enevti-app/theme/default';
Expand All @@ -12,23 +10,37 @@ import { useDispatch } from 'react-redux';
import { showSnackbar } from 'enevti-app/store/slices/ui/global/snackbar';
import { useTranslation } from 'react-i18next';
import { MentionData } from 'react-native-controlled-mentions/dist/types';
import AppTextBodyCustom from 'enevti-app/components/atoms/text/AppTextBodyCustom';
import AppTextHeadingCustom from 'enevti-app/components/atoms/text/AppTextHeadingCustom';

interface AppMentionRendererProps {
navigation: StackNavigationProp<RootStackParamList>;
text: string;
navigation?: StackNavigationProp<RootStackParamList>;
disabled?: boolean;
style?: StyleProp<TextStyle>;
color?: string;
title?: string;
onTitlePress?: () => void;
size?: number;
}

export default function AppMentionRenderer({ navigation, text, style, title, onTitlePress }: AppMentionRendererProps) {
export default function AppMentionRenderer({
navigation,
text,
style,
color,
title,
disabled,
onTitlePress,
size,
}: AppMentionRendererProps) {
const { t } = useTranslation();
const dispatch = useDispatch();
const theme = useTheme() as Theme;

const profileMentionOnPress = React.useCallback(
(data?: MentionData) => {
if (data) {
if (navigation && data) {
navigation.push('Profile', { mode: 'u', arg: data.id });
} else {
dispatch(showSnackbar({ mode: 'info', text: t('error:dataUnavailable') }));
Expand All @@ -39,7 +51,7 @@ export default function AppMentionRenderer({ navigation, text, style, title, onT

const collectionMentionOnPress = React.useCallback(
(data?: MentionData) => {
if (data) {
if (navigation && data) {
navigation.push('Collection', { mode: 's', arg: data.id });
} else {
dispatch(showSnackbar({ mode: 'info', text: t('error:dataUnavailable') }));
Expand All @@ -50,7 +62,7 @@ export default function AppMentionRenderer({ navigation, text, style, title, onT

const nftMentionOnPress = React.useCallback(
(data?: MentionData) => {
if (data) {
if (navigation && data) {
navigation.push('NFTDetails', { mode: 's', arg: data.id });
} else {
dispatch(showSnackbar({ mode: 'info', text: t('error:dataUnavailable') }));
Expand All @@ -62,43 +74,63 @@ export default function AppMentionRenderer({ navigation, text, style, title, onT
const renderPart = React.useCallback(
(part: Part, index: number) => {
if (!part.partType) {
return <AppTextBody4 key={index}>{part.text}</AppTextBody4>;
return (
<AppTextBodyCustom size={size === undefined ? 3.5 : size} key={index} style={{ color }}>
{part.text}
</AppTextBodyCustom>
);
}

if (isMentionPartType(part.partType)) {
if (part.partType.trigger === PROFILE_MENTION_TRIGGER) {
return (
<AppTextBody4
<AppTextBodyCustom
size={size === undefined ? 3.5 : size}
key={`${index}-${part.data?.trigger}`}
style={{ color: theme.colors.link }}
onPress={() => profileMentionOnPress(part.data)}>
style={{ color: disabled ? (color ? color : theme.colors.text) : theme.colors.link }}
onPress={disabled ? undefined : () => profileMentionOnPress(part.data)}>
{part.text}
</AppTextBody4>
</AppTextBodyCustom>
);
} else if (part.partType.trigger === COLLECTION_MENTION_TRIGGER) {
return (
<AppTextBody4
<AppTextBodyCustom
size={size === undefined ? 3.5 : size}
key={`${index}-${part.data?.trigger}`}
style={{ color: theme.colors.link }}
onPress={() => collectionMentionOnPress(part.data)}>
style={{ color: disabled ? (color ? color : theme.colors.text) : theme.colors.link }}
onPress={disabled ? undefined : () => collectionMentionOnPress(part.data)}>
{part.text}
</AppTextBody4>
</AppTextBodyCustom>
);
} else if (part.partType.trigger === NFT_MENTION_TRIGGER) {
return (
<AppTextBody4
<AppTextBodyCustom
size={size === undefined ? 3.5 : size}
key={`${index}-${part.data?.trigger}`}
style={{ color: theme.colors.link }}
onPress={() => nftMentionOnPress(part.data)}>
style={{ color: disabled ? (color ? color : theme.colors.text) : theme.colors.link }}
onPress={disabled ? undefined : () => nftMentionOnPress(part.data)}>
{part.text}
</AppTextBody4>
</AppTextBodyCustom>
);
}
}

return <AppTextBody4 key={`${index}-pattern`}>{part.text}</AppTextBody4>;
return (
<AppTextBodyCustom size={size === undefined ? 3.5 : size} key={`${index}-pattern`}>
{part.text}
</AppTextBodyCustom>
);
},
[collectionMentionOnPress, nftMentionOnPress, profileMentionOnPress, theme.colors.link],
[
collectionMentionOnPress,
color,
disabled,
nftMentionOnPress,
profileMentionOnPress,
size,
theme.colors.link,
theme.colors.text,
],
);

const renderValue = React.useCallback(
Expand All @@ -110,13 +142,17 @@ export default function AppMentionRenderer({ navigation, text, style, title, onT
);

return (
<AppTextBody4 style={style}>
{title ? <AppTextHeading4 onPress={onTitlePress}>{title} </AppTextHeading4> : null}
<AppTextBodyCustom size={size === undefined ? 3.5 : size} style={style}>
{title ? (
<AppTextHeadingCustom size={size === undefined ? 3.5 : size} onPress={onTitlePress}>
{title}{' '}
</AppTextHeadingCustom>
) : null}
{renderValue(text, [
{ trigger: PROFILE_MENTION_TRIGGER },
{ trigger: COLLECTION_MENTION_TRIGGER },
{ trigger: NFT_MENTION_TRIGGER },
])}
</AppTextBody4>
</AppTextBodyCustom>
);
}
6 changes: 2 additions & 4 deletions src/components/molecules/list/AppPortraitOverlayBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { wp, SafeAreaInsets } from 'enevti-app/utils/layout/imageRatio';
import { Theme } from 'enevti-app/theme/default';
import { BlurView } from '@react-native-community/blur';
import AppTextBody5 from 'enevti-app/components/atoms/text/AppTextBody5';
import AppMentionRenderer from '../comment/AppMentionRenderer';

interface AppPortraitOverlayBoxProps {
title: string;
Expand Down Expand Up @@ -33,9 +33,7 @@ export default function AppPortraitOverlayBox({
{background ? <View style={styles.content}>{background}</View> : null}
{blurBackground ? <BlurView blurAmount={10} style={styles.overlay} /> : <View style={styles.overlayColor} />}
{foreground ? <View style={styles.content}>{foreground}</View> : null}
<AppTextBody5 numberOfLines={1} style={styles.textOverlay}>
{title}
</AppTextBody5>
<AppMentionRenderer disabled size={2.2} text={title} style={styles.textOverlay} color={'white'} />
<TouchableRipple style={styles.rippleOverlay} onPress={onPress}>
<View />
</TouchableRipple>
Expand Down
42 changes: 37 additions & 5 deletions src/components/organism/moment/AppMomentItem.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
import React from 'react';
import AppPortraitOverlayBox from 'enevti-app/components/molecules/list/AppPortraitOverlayBox';
import { StyleProp, ViewStyle } from 'react-native';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import AppNetworkImage from 'enevti-app/components/atoms/image/AppNetworkImage';
import { Moment } from 'enevti-app/types/core/chain/moment';
import { fetchIPFS, IPFStoURL } from 'enevti-app/service/ipfs';

interface AppMomentItemProps {
title: string;
url: string;
moment: Moment;
style?: StyleProp<ViewStyle>;
onPress?: () => void;
}

export default function AppMomentItem({ title, url, style, onPress }: AppMomentItemProps) {
export default function AppMomentItem({ moment, style, onPress }: AppMomentItemProps) {
const styles = React.useMemo(() => makeStyles(), []);
const [title, setTitle] = React.useState<string>(() => moment.textPlain ?? '');

const onLoad = React.useCallback(async () => {
if (!moment.textPlain) {
const data = await fetchIPFS(moment.text);
if (data) {
setTitle(data);
}
}
}, [moment.text, moment.textPlain]);

React.useEffect(() => {
onLoad();
}, [onLoad]);

return (
<AppPortraitOverlayBox title={title} style={style} onPress={onPress} background={<AppNetworkImage url={url} />} />
<AppPortraitOverlayBox
title={title}
style={style}
onPress={onPress}
background={<AppNetworkImage url={IPFStoURL(moment.data.cid)} style={styles.image} />}
/>
);
}

const makeStyles = () =>
StyleSheet.create({
image: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
});
11 changes: 3 additions & 8 deletions src/components/organism/moment/AppRecentMoments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import AppTextHeading3 from 'enevti-app/components/atoms/text/AppTextHeading3';
import { hp, wp } from 'enevti-app/utils/layout/imageRatio';
import { useTranslation } from 'react-i18next';
import { Divider } from 'react-native-paper';
import { IPFStoURL } from 'enevti-app/service/ipfs';
import AppActivityIndicator from '../../atoms/loading/AppActivityIndicator';
import { useSelector } from 'react-redux';
import { isMomentUndefined, selectMomentView } from 'enevti-app/store/slices/ui/view/moment';
Expand All @@ -14,6 +13,7 @@ import AppAddMoment from './AppAddMoment';
import AppMomentItem from './AppMomentItem';
import { StackNavigationProp } from '@react-navigation/stack';
import { RootStackParamList } from 'enevti-app/navigation';
import { Moment } from 'enevti-app/types/core/chain/moment';

const center = 'center';

Expand All @@ -32,13 +32,8 @@ export default function AppRecentMoments({ navigation }: AppRecentMomentsProps)
const onMomentsPress = (_id: string) => {};

const renderItem = React.useCallback(
({ item }: any) => (
<AppMomentItem
url={IPFStoURL(item.photo)}
title={item.username}
style={{ marginRight: wp('2%', insets) }}
onPress={() => onMomentsPress(item.id)}
/>
({ item }: { item: Moment }) => (
<AppMomentItem moment={item} style={{ marginRight: wp('2%', insets) }} onPress={() => onMomentsPress(item.id)} />
),
[insets],
);
Expand Down
27 changes: 27 additions & 0 deletions src/service/enevti/dummy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,40 @@ export const requestFaucet = async (address: string) => {
export const getDummyMomentItem = (): MomentItem => {
return {
id: Math.random().toString(),
nftId: Math.random().toString(),
owner: {
username: '',
base32: 'envt7opy8ksve7npbr32dtqxwpvg5u6aa3vtje5qtd',
address: '730917d362b38e434918d4ea1b905f5c159ca053',
photo: '',
},
creator: {
username: '',
base32: 'envt7opy8ksve7npbr32dtqxwpvg5u6aa3vtje5qtd',
address: '730917d362b38e434918d4ea1b905f5c159ca053',
photo: '',
},
cover: {
cid: 'bafybeif42jbs3t3pxjbz4635siv2u5nzxp5h7ffcsrwwvixgsclcn7rgza',
mime: 'image/jpeg',
extension: 'jpg',
size: 0,
protocol: 'ipfs',
},
clubs: 0,
comment: 0,
createdOn: 1648256392852,
data: {
cid: 'bafybeif42jbs3t3pxjbz4635siv2u5nzxp5h7ffcsrwwvixgsclcn7rgza',
mime: 'image/jpeg',
extension: 'jpg',
size: 0,
protocol: 'ipfs',
},
like: 0,
text: 'sample text',
activity: [],
textPlain: 'bafkreid27m2e2yjaaqkbiyjtxgpoyipiatrj7yd5ummrir7j6vqx2uvztm',
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ export const reducePayMintMoment = (): AppThunk => async (dispatch, getState) =>
}

if (meta.coverProtocol === 'ipfs') {
dispatch(setModalLoaderText(i18n.t('payment:uploadingTo', { file: 'data', provider: meta.coverProtocol })));
dispatch(setModalLoaderText(i18n.t('payment:uploadingTo', { file: 'cover', provider: meta.coverProtocol })));
cover = await uploadURItoIPFS(meta.cover);
}

transactionPayload.asset.data = data;
transactionPayload.asset.cover = cover;

dispatch(setModalLoaderText(i18n.t('payment:uploadingTo', { file: 'caption', provider: 'ipfs' })));
transactionPayload.asset.text = await uploadTextToIPFS(meta.text);

dispatch(setModalLoaderText(i18n.t('payment:postingTransaction')));
Expand Down
7 changes: 3 additions & 4 deletions src/types/core/chain/moment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ export type MomentAtAsset = {
moment: MomentIdAsset[];
};

export type MomentBase = {
export interface Moment {
id: string;
cover: NFTContent;
};

export interface Moment extends MomentBase {
nftId: string;
owner: Persona;
creator: Persona;
Expand All @@ -46,6 +43,8 @@ export interface Moment extends MomentBase {
activity?: MomentActivity[];
}

export type MomentBase = Moment;

export interface MomentAsset extends Omit<Moment, 'id' | 'nftId' | 'activity' | 'owner' | 'creator' | 'createdOn'> {
id: MomentIdAsset;
nftId: NFTIdAsset;
Expand Down

0 comments on commit 92f4064

Please sign in to comment.