[IMPROVE] - migrating the UIKit container (in progress)

This commit is contained in:
AlexAlexandre 2021-07-26 19:33:27 -03:00
parent 369b3f2ef6
commit 9a1b705471
14 changed files with 170 additions and 148 deletions

View File

@ -1,31 +1,29 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import Button from '../Button';
import I18n from '../../i18n';
export const Actions = ({
blockId, appId, elements, parser, theme
}) => {
interface IActions {
blockId: string;
appId: string;
elements: any[];
parser: any;
theme: string;
}
export const Actions = ({ blockId, appId, elements, parser, theme }: IActions) => {
const [showMoreVisible, setShowMoreVisible] = useState(() => elements.length > 5);
const renderedElements = showMoreVisible ? elements.slice(0, 5) : elements;
const Elements = () => renderedElements
.map(element => parser.renderActions({ blockId, appId, ...element }, BLOCK_CONTEXT.ACTION, parser));
.map((element: any) => parser.renderActions({ blockId, appId, ...element }, BLOCK_CONTEXT.ACTION, parser));
return (
<>
{/*@ts-ignore*/}
<Elements />
{showMoreVisible && (<Button theme={theme} title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />)}
</>
);
};
Actions.propTypes = {
blockId: PropTypes.string,
appId: PropTypes.string,
elements: PropTypes.array,
parser: PropTypes.object,
theme: PropTypes.string
};

View File

@ -11,11 +11,12 @@ const styles = StyleSheet.create({
}
});
export const Context = ({ elements, parser }) => (
export const Context = ({ elements, parser }: any) => (
<View style={styles.container}>
{elements.map(element => parser.renderContext(element, BLOCK_CONTEXT.CONTEXT, parser))}
{elements.map((element: any) => parser.renderContext(element, BLOCK_CONTEXT.CONTEXT, parser))}
</View>
);
Context.propTypes = {
elements: PropTypes.array,
parser: PropTypes.object

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import PropTypes from 'prop-types';
import DateTimePicker from '@react-native-community/datetimepicker';
import Touchable from 'react-native-platform-touchable';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
@ -37,14 +36,28 @@ const styles = StyleSheet.create({
}
});
interface IDatePicker {
element: {
initial_date: any;
placeholder: string;
};
language: string;
action: Function;
context: number;
loading: boolean;
theme: string;
value: string;
error: string;
}
export const DatePicker = ({
element, language, action, context, theme, loading, value, error
}) => {
}: IDatePicker) => {
const [show, onShow] = useState(false);
const { initial_date, placeholder } = element;
const [currentDate, onChangeDate] = useState(new Date(initial_date || value));
const onChange = ({ nativeEvent: { timestamp } }, date) => {
const onChange = ({ nativeEvent: { timestamp } }: any, date: any) => {
const newDate = date || new Date(timestamp);
onChangeDate(newDate);
action({ value: moment(newDate).format('YYYY-MM-DD') });
@ -105,13 +118,3 @@ export const DatePicker = ({
</>
);
};
DatePicker.propTypes = {
element: PropTypes.object,
language: PropTypes.string,
action: PropTypes.func,
context: PropTypes.number,
loading: PropTypes.bool,
theme: PropTypes.string,
value: PropTypes.string,
error: PropTypes.string
};

View File

@ -1,7 +1,6 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import FastImage from '@rocket.chat/react-native-fast-image';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import ImageContainer from '../message/Image';
@ -16,21 +15,37 @@ const styles = StyleSheet.create({
}
});
const ThumbContext = args => <View style={styles.mediaContext}><Thumb size={20} {...args} /></View>;
type TThumb = {
element: {
imageUrl: string;
};
size?: number;
};
export const Thumb = ({ element, size = 88 }) => (
type TMedia = {
element: {
imageUrl: string;
};
theme: string;
};
interface IImage {
element: any;
context: any;
theme: string;
}
const ThumbContext = (args: any) => <View style={styles.mediaContext}><Thumb size={20} {...args} /></View>;
export const Thumb = ({ element, size = 88 }: TThumb) => (
<FastImage
style={[{ width: size, height: size }, styles.image]}
source={{ uri: element.imageUrl }}
/>
);
Thumb.propTypes = {
element: PropTypes.object,
size: PropTypes.number
};
export const Media = ({ element, theme }) => {
const showAttachment = attachment => Navigation.navigate('AttachmentView', { attachment });
export const Media = ({ element, theme }: TMedia) => {
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment });
const { imageUrl } = element;
return (
@ -42,12 +57,8 @@ export const Media = ({ element, theme }) => {
/>
);
};
Media.propTypes = {
element: PropTypes.object,
theme: PropTypes.string
};
const genericImage = (element, context, theme) => {
const genericImage = (element: any, context: any, theme: string) => {
switch (context) {
case BLOCK_CONTEXT.SECTION:
return <Thumb element={element} />;
@ -58,4 +69,4 @@ const genericImage = (element, context, theme) => {
}
};
export const Image = ({ element, context, theme }) => genericImage(element, context, theme);
export const Image = ({ element, context, theme }: IImage) => genericImage(element, context, theme);

View File

@ -1,6 +1,5 @@
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import sharedStyles from '../../views/Styles';
@ -32,9 +31,19 @@ const styles = StyleSheet.create({
}
});
interface IInput {
element: object;
parser: any;
label: string;
description: string;
error: string;
hint: string;
theme: string;
}
export const Input = ({
element, parser, label, description, error, hint, theme
}) => (
}: IInput) => (
<View style={styles.container}>
{label ? <Text style={[styles.label, { color: error ? themes[theme].dangerColor : themes[theme].titleText }]}>{label}</Text> : null}
{description ? <Text style={[styles.description, { color: themes[theme].auxiliaryText }]}>{description}</Text> : null}
@ -43,13 +52,3 @@ export const Input = ({
{hint ? <Text style={[styles.hint, { color: themes[theme].auxiliaryText }]}>{hint}</Text> : null}
</View>
);
Input.propTypes = {
element: PropTypes.object,
parser: PropTypes.object,
label: PropTypes.string,
description: PropTypes.string,
error: PropTypes.string,
hint: PropTypes.string,
theme: PropTypes.string
};

View File

@ -1,27 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { UiKitMessage, UiKitModal } from './index';
import { KitContext } from './utils';
export const messageBlockWithContext = context => props => (
<KitContext.Provider value={context}>
<MessageBlock {...props} />
</KitContext.Provider>
);
const MessageBlock = ({ blocks }) => UiKitMessage(blocks);
MessageBlock.propTypes = {
blocks: PropTypes.any
};
export const modalBlockWithContext = context => data => (
<KitContext.Provider value={{ ...context, ...data }}>
<ModalBlock {...data} />
</KitContext.Provider>
);
const ModalBlock = ({ blocks }) => UiKitModal(blocks);
ModalBlock.propTypes = {
blocks: PropTypes.any
};

View File

@ -0,0 +1,20 @@
import React from 'react';
import { UiKitMessage, UiKitModal } from './index';
import { KitContext } from './utils';
export const messageBlockWithContext = (context: any) => (props: any) => (
<KitContext.Provider value={context}>
<MessageBlock {...props} />
</KitContext.Provider>
);
const MessageBlock = ({ blocks }: any) => UiKitMessage(blocks);
export const modalBlockWithContext = (context: any) => (data: any) => (
<KitContext.Provider value={{ ...context, ...data }}>
<ModalBlock {...data} />
</KitContext.Provider>
);
const ModalBlock = ({ blocks }: any) => UiKitModal(blocks);

View File

@ -10,7 +10,32 @@ import { themes } from '../../constants/colors';
import { BUTTON_HIT_SLOP } from '../message/utils';
import * as List from '../List';
const keyExtractor = item => item.value;
type TOption = {
option: {
text: string;
value: string;
};
onOptionPress: Function;
parser: any;
theme: string;
};
type TOptions = {
options: [];
onOptionPress: Function;
parser: object;
theme: string;
};
interface IOverflow {
element: any;
action: Function;
loading: boolean;
parser: object;
theme: string;
}
const keyExtractor = (item: any) => item.value;
const styles = StyleSheet.create({
menu: {
@ -25,9 +50,7 @@ const styles = StyleSheet.create({
}
});
const Option = ({
option: { text, value }, onOptionPress, parser, theme
}) => (
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOption) => (
<Touchable
onPress={() => onOptionPress({ value })}
background={Touchable.Ripple(themes[theme].bannerBackground)}
@ -36,16 +59,8 @@ const Option = ({
<Text>{parser.text(text)}</Text>
</Touchable>
);
Option.propTypes = {
option: PropTypes.object,
onOptionPress: PropTypes.func,
parser: PropTypes.object,
theme: PropTypes.string
};
const Options = ({
options, onOptionPress, parser, theme
}) => (
const Options = ({ options, onOptionPress, parser, theme }: TOptions) => (
<FlatList
data={options}
renderItem={({ item }) => <Option option={item} onOptionPress={onOptionPress} parser={parser} theme={theme} />}
@ -53,22 +68,14 @@ const Options = ({
ItemSeparatorComponent={List.Separator}
/>
);
Options.propTypes = {
options: PropTypes.array,
onOptionPress: PropTypes.func,
parser: PropTypes.object,
theme: PropTypes.string
};
const touchable = {};
export const Overflow = ({
element, loading, action, parser, theme
}) => {
export const Overflow = ({ element, loading, action, parser, theme }: IOverflow) => {
const { options, blockId } = element;
const [show, onShow] = useState(false);
const onOptionPress = ({ value }) => {
const onOptionPress = ({ value }: any) => {
onShow(false);
action({ value });
};
@ -76,6 +83,7 @@ export const Overflow = ({
return (
<>
<Touchable
/*@ts-ignore*/
ref={ref => touchable[blockId] = ref}
background={Touchable.Ripple(themes[theme].bannerBackground)}
onPress={() => onShow(!show)}
@ -86,6 +94,7 @@ export const Overflow = ({
</Touchable>
<Popover
isVisible={show}
/*@ts-ignore*/
fromView={touchable[blockId]}
onRequestClose={() => onShow(false)}
>
@ -94,10 +103,3 @@ export const Overflow = ({
</>
);
};
Overflow.propTypes = {
element: PropTypes.any,
action: PropTypes.func,
loading: PropTypes.bool,
parser: PropTypes.object,
theme: PropTypes.string
};

View File

@ -1,6 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import { themes } from '../../constants/colors';
@ -24,15 +23,36 @@ const styles = StyleSheet.create({
}
});
const Accessory = ({
blockId, appId, element, parser
}) => parser.renderAccessories(
type TAccessory = {
blockId?: string;
appId?: string;
element: any;
parser: any
}
type TFields = {
fields: any;
parser: any;
theme: string;
}
interface ISection {
blockId: string;
appId: string;
text: object;
fields: [];
accessory: any;
theme: string;
parser: any;
}
const Accessory = ({ blockId, appId, element, parser }: TAccessory) => parser.renderAccessories(
{ blockId, appId, ...element },
BLOCK_CONTEXT.SECTION,
parser
);
const Fields = ({ fields, parser, theme }) => fields.map(field => (
const Fields = ({ fields, parser, theme }: TFields) => fields.map((field: any) => (
<Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>
{parser.text(field)}
</Text>
@ -40,9 +60,7 @@ const Fields = ({ fields, parser, theme }) => fields.map(field => (
const accessoriesRight = ['image', 'overflow'];
export const Section = ({
blockId, appId, text, fields, accessory, parser, theme
}) => (
export const Section = ({ blockId, appId, text, fields, accessory, parser, theme }: ISection) => (
<View
style={[
styles.content,
@ -54,12 +72,3 @@ export const Section = ({
{accessory ? <Accessory element={{ blockId, appId, ...accessory }} parser={parser} /> : null}
</View>
);
Section.propTypes = {
blockId: PropTypes.string,
appId: PropTypes.string,
text: PropTypes.object,
fields: PropTypes.array,
accessory: PropTypes.any,
theme: PropTypes.string,
parser: PropTypes.object
};

View File

@ -34,6 +34,19 @@ const styles = StyleSheet.create({
}
});
interface ISelect {
options: {
text: string;
value: string;
}[];
placeholder: string;
onChange: Function;
loading: boolean;
disabled: boolean;
value: [];
theme: string;
}
export const Select = ({
options = [],
placeholder,
@ -42,7 +55,7 @@ export const Select = ({
disabled,
value: initialValue,
theme
}) => {
}: ISelect) => {
const [selected, setSelected] = useState(!Array.isArray(initialValue) && initialValue);
const items = options.map(option => ({ label: textParser([option.text]), value: option.value }));
const pickerStyle = {
@ -74,16 +87,8 @@ export const Select = ({
inputAndroidContainer: pickerStyle
}}
Icon={Icon}
// @ts-ignore
textInputProps={{ style: { ...styles.pickerText, color: selected ? themes[theme].titleText : themes[theme].auxiliaryText } }}
/>
);
};
Select.propTypes = {
options: PropTypes.array,
placeholder: PropTypes.string,
onChange: PropTypes.func,
loading: PropTypes.bool,
disabled: PropTypes.bool,
value: PropTypes.array,
theme: PropTypes.string
};

View File

@ -2,10 +2,10 @@
import React, { useContext, useState } from 'react';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
export const textParser = ([{ text }]) => text;
export const textParser = ([{ text }]: any) => text;
export const defaultContext = {
action: (...args) => console.log(args),
export const defaultContext: any = {
action: (...args: any) => console.log(args),
state: console.log,
appId: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
errors: {}
@ -15,7 +15,7 @@ export const KitContext = React.createContext(defaultContext);
export const useBlockContext = ({
blockId, actionId, appId, initialValue
}, context) => {
}: any, context: any) => {
const {
action, appId: appIdFromContext, viewId, state, language, errors, values = {}
} = useContext(KitContext);
@ -27,7 +27,7 @@ export const useBlockContext = ({
if ([BLOCK_CONTEXT.SECTION, BLOCK_CONTEXT.ACTION].includes(context)) {
return [{
loading, setLoading, error, value, language
}, async({ value }) => {
}, async({ value }: any) => {
setLoading(true);
try {
await action({
@ -46,7 +46,7 @@ export const useBlockContext = ({
return [{
loading, setLoading, value, error, language
}, async({ value }) => {
}, async({ value }: any) => {
setLoading(true);
try {
await state({

View File

@ -24,11 +24,11 @@ type TMessageImage = {
}
interface IMessageImage {
file: { image_url: string; description: string; };
file: { image_url: string; description?: string; };
imageUrl?: string;
showAttachment: Function;
theme: string;
getCustomEmoji: Function;
getCustomEmoji?: Function;
}
const ImageProgress = createImageProgress(FastImage);

View File

@ -4,4 +4,5 @@ declare module 'commonmark-react-renderer';
declare module 'remove-markdown';
declare module 'react-native-image-progress';
declare module 'react-native-platform-touchable';
declare module 'react-native-ui-lib/keyboard';
declare module 'react-native-ui-lib/keyboard';
declare module '@rocket.chat/ui-kit';