Chore: Migrate methods/actions to Typescript and refactor UiKit folder (#3716)
* Chore: Migrate methods/actions to Typescript * tweak in actions * Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com> * refactor sdk.current * interface and uikit done * refactor interface, index and utils from UiKit * minor tweak * minor tweak Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
This commit is contained in:
parent
f98f2a46d9
commit
823d4c658c
|
@ -3,25 +3,18 @@ import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
|||
|
||||
import Button from '../Button';
|
||||
import I18n from '../../i18n';
|
||||
|
||||
interface IActions {
|
||||
blockId: string;
|
||||
appId: string;
|
||||
elements: any[];
|
||||
parser: any;
|
||||
theme: string;
|
||||
}
|
||||
import { IActions } from './interfaces';
|
||||
|
||||
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 [showMoreVisible, setShowMoreVisible] = useState(() => elements && elements.length > 5);
|
||||
const renderedElements = showMoreVisible ? elements?.slice(0, 5) : elements;
|
||||
|
||||
const Elements = () =>
|
||||
renderedElements.map((element: any) => parser.renderActions({ blockId, appId, ...element }, BLOCK_CONTEXT.ACTION, parser));
|
||||
const Elements = () => (
|
||||
<>{renderedElements?.map(element => 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)} />}
|
||||
</>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||
|
||||
import { IContext } from './interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
minHeight: 36,
|
||||
|
@ -11,13 +12,6 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
export const Context = ({ elements, parser }: any) => (
|
||||
<View style={styles.container}>
|
||||
{elements.map((element: any) => parser.renderContext(element, BLOCK_CONTEXT.CONTEXT, parser))}
|
||||
</View>
|
||||
export const Context = ({ elements, parser }: IContext) => (
|
||||
<View style={styles.container}>{elements?.map(element => parser?.renderContext(element, BLOCK_CONTEXT.CONTEXT, parser))}</View>
|
||||
);
|
||||
|
||||
Context.propTypes = {
|
||||
elements: PropTypes.array,
|
||||
parser: PropTypes.object
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ import sharedStyles from '../../views/Styles';
|
|||
import { CustomIcon } from '../../lib/Icons';
|
||||
import { isAndroid } from '../../utils/deviceInfo';
|
||||
import ActivityIndicator from '../ActivityIndicator';
|
||||
import { IDatePicker } from './interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
input: {
|
||||
|
@ -35,23 +36,11 @@ 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 initial_date = element?.initial_date;
|
||||
const placeholder = element?.placeholder;
|
||||
|
||||
const [currentDate, onChangeDate] = useState(new Date(initial_date || value));
|
||||
|
||||
const onChange = ({ nativeEvent: { timestamp } }: any, date: any) => {
|
||||
|
|
|
@ -5,6 +5,8 @@ import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
|||
|
||||
import ImageContainer from '../message/Image';
|
||||
import Navigation from '../../lib/Navigation';
|
||||
import { IThumb, IImage, IElement } from './interfaces';
|
||||
import { TThemeMode } from '../../definitions/ITheme';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
|
@ -15,44 +17,25 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IThumb {
|
||||
element: {
|
||||
imageUrl: string;
|
||||
};
|
||||
size?: number;
|
||||
}
|
||||
|
||||
interface IMedia {
|
||||
element: {
|
||||
imageUrl: string;
|
||||
};
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IImage {
|
||||
element: any;
|
||||
context: any;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const ThumbContext = (args: any) => (
|
||||
const ThumbContext = (args: IThumb) => (
|
||||
<View style={styles.mediaContext}>
|
||||
<Thumb size={20} {...args} />
|
||||
</View>
|
||||
);
|
||||
|
||||
export const Thumb = ({ element, size = 88 }: IThumb) => (
|
||||
<FastImage style={[{ width: size, height: size }, styles.image]} source={{ uri: element.imageUrl }} />
|
||||
<FastImage style={[{ width: size, height: size }, styles.image]} source={{ uri: element?.imageUrl }} />
|
||||
);
|
||||
|
||||
export const Media = ({ element, theme }: IMedia) => {
|
||||
export const Media = ({ element, theme }: IImage) => {
|
||||
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment });
|
||||
const { imageUrl } = element;
|
||||
const imageUrl = element?.imageUrl ?? '';
|
||||
// @ts-ignore
|
||||
// TODO: delete ts-ignore after refactor Markdown and ImageContainer
|
||||
return <ImageContainer file={{ image_url: imageUrl }} imageUrl={imageUrl} showAttachment={showAttachment} theme={theme} />;
|
||||
};
|
||||
|
||||
const genericImage = (element: any, context: any, theme: string) => {
|
||||
const genericImage = (theme: TThemeMode, element: IElement, context?: number) => {
|
||||
switch (context) {
|
||||
case BLOCK_CONTEXT.SECTION:
|
||||
return <Thumb element={element} />;
|
||||
|
@ -63,4 +46,4 @@ const genericImage = (element: any, context: any, theme: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const Image = ({ element, context, theme }: IImage) => genericImage(element, context, theme);
|
||||
export const Image = ({ element, context, theme }: IImage) => genericImage(theme, element, context);
|
||||
|
|
|
@ -4,6 +4,7 @@ import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
|||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { IInput } from './interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -31,16 +32,6 @@ 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 ? (
|
||||
|
|
|
@ -8,32 +8,7 @@ import ActivityIndicator from '../ActivityIndicator';
|
|||
import { themes } from '../../constants/colors';
|
||||
import { BUTTON_HIT_SLOP } from '../message/utils';
|
||||
import * as List from '../List';
|
||||
|
||||
interface IOption {
|
||||
option: {
|
||||
text: string;
|
||||
value: string;
|
||||
};
|
||||
onOptionPress: Function;
|
||||
parser: any;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IOptions {
|
||||
options: [];
|
||||
onOptionPress: Function;
|
||||
parser: object;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IOverflow {
|
||||
element: any;
|
||||
action: Function;
|
||||
loading: boolean;
|
||||
parser: object;
|
||||
theme: string;
|
||||
context: any;
|
||||
}
|
||||
import { IOption, IOptions, IOverflow } from './interfaces';
|
||||
|
||||
const keyExtractor = (item: any) => item.value;
|
||||
|
||||
|
@ -68,10 +43,11 @@ const Options = ({ options, onOptionPress, parser, theme }: IOptions) => (
|
|||
/>
|
||||
);
|
||||
|
||||
const touchable = {};
|
||||
const touchable: { [key: string]: any } = {};
|
||||
|
||||
export const Overflow = ({ element, loading, action, parser, theme }: IOverflow) => {
|
||||
const { options, blockId } = element;
|
||||
const options = element?.options || [];
|
||||
const blockId = element?.blockId || '';
|
||||
const [show, onShow] = useState(false);
|
||||
|
||||
const onOptionPress = ({ value }: any) => {
|
||||
|
@ -82,8 +58,7 @@ export const Overflow = ({ element, loading, action, parser, theme }: IOverflow)
|
|||
return (
|
||||
<>
|
||||
<Touchable
|
||||
/* @ts-ignore*/
|
||||
ref={ref => (touchable[blockId] = ref)}
|
||||
ref={(ref: any) => (touchable[blockId] = ref)}
|
||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
||||
onPress={() => onShow(!show)}
|
||||
hitSlop={BUTTON_HIT_SLOP}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { StyleSheet, Text, View } from 'react-native';
|
|||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { IAccessoryComponent, IFields, ISection } from './interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
|
@ -23,36 +24,16 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IAccessory {
|
||||
blockId?: string;
|
||||
appId?: string;
|
||||
element: any;
|
||||
parser: any;
|
||||
}
|
||||
const Accessory = ({ element, parser }: IAccessoryComponent) =>
|
||||
parser.renderAccessories({ ...element }, BLOCK_CONTEXT.SECTION, parser);
|
||||
|
||||
interface IFields {
|
||||
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 }: IAccessory) =>
|
||||
parser.renderAccessories({ blockId, appId, ...element }, BLOCK_CONTEXT.SECTION, parser);
|
||||
|
||||
const Fields = ({ fields, parser, theme }: IFields) =>
|
||||
fields.map((field: any) => (
|
||||
<Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>{parser.text(field)}</Text>
|
||||
));
|
||||
const Fields = ({ fields, parser, theme }: IFields) => (
|
||||
<>
|
||||
{fields.map(field => (
|
||||
<Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>{parser.text(field)}</Text>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
const accessoriesRight = ['image', 'overflow'];
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Input } from './Input';
|
|||
import { DatePicker } from './DatePicker';
|
||||
import { Overflow } from './Overflow';
|
||||
import { ThemeContext } from '../../theme';
|
||||
import { BlockContext, IButton, IInputIndex, IParser, IText } from './interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
input: {
|
||||
|
@ -42,8 +43,12 @@ const styles = StyleSheet.create({
|
|||
const plainText = ({ text } = { text: '' }) => text;
|
||||
|
||||
class MessageParser extends UiKitParserMessage {
|
||||
text({ text, type }: any = { text: '' }, context: any) {
|
||||
const { theme }: any = useContext(ThemeContext);
|
||||
get current() {
|
||||
return this as unknown as IParser;
|
||||
}
|
||||
|
||||
text({ text, type }: Partial<IText> = { text: '' }, context: BlockContext) {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
if (type !== 'mrkdwn') {
|
||||
return <Text style={[styles.text, { color: themes[theme].bodyText }]}>{text}</Text>;
|
||||
}
|
||||
|
@ -55,9 +60,9 @@ class MessageParser extends UiKitParserMessage {
|
|||
return <Markdown msg={text} theme={theme} style={[isContext && { color: themes[theme].auxiliaryText }]} />;
|
||||
}
|
||||
|
||||
button(element: any, context: any) {
|
||||
button(element: IButton, context: BlockContext) {
|
||||
const { text, value, actionId, style } = element;
|
||||
const [{ loading }, action]: any = useBlockContext(element, context);
|
||||
const [{ loading }, action] = useBlockContext(element, context);
|
||||
const { theme } = useContext(ThemeContext);
|
||||
return (
|
||||
<Button
|
||||
|
@ -73,7 +78,7 @@ class MessageParser extends UiKitParserMessage {
|
|||
}
|
||||
|
||||
divider() {
|
||||
const { theme }: any = useContext(ThemeContext);
|
||||
const { theme } = useContext(ThemeContext);
|
||||
// @ts-ignore
|
||||
return <Divider theme={theme} />;
|
||||
}
|
||||
|
@ -91,7 +96,7 @@ class MessageParser extends UiKitParserMessage {
|
|||
overflow(element: any, context: any) {
|
||||
const [{ loading }, action]: any = useBlockContext(element, context);
|
||||
const { theme }: any = useContext(ThemeContext);
|
||||
return <Overflow element={element} context={context} loading={loading} action={action} theme={theme} parser={this} />;
|
||||
return <Overflow element={element} context={context} loading={loading} action={action} theme={theme} parser={this.current} />;
|
||||
}
|
||||
|
||||
datePicker(element: any, context: any) {
|
||||
|
@ -150,12 +155,16 @@ class ModalParser extends UiKitParserModal {
|
|||
});
|
||||
}
|
||||
|
||||
input({ element, blockId, appId, label, description, hint }: any, context: any) {
|
||||
get current() {
|
||||
return this as unknown as IParser;
|
||||
}
|
||||
|
||||
input({ element, blockId, appId, label, description, hint }: IInputIndex, context: number) {
|
||||
const [{ error }]: any = useBlockContext({ ...element, appId, blockId }, context);
|
||||
const { theme }: any = useContext(ThemeContext);
|
||||
return (
|
||||
<Input
|
||||
parser={this}
|
||||
parser={this.current}
|
||||
element={{ ...element, appId, blockId }}
|
||||
label={plainText(label)}
|
||||
description={plainText(description)}
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
import { TThemeMode } from '../../definitions/ITheme';
|
||||
|
||||
export enum ElementTypes {
|
||||
IMAGE = 'image',
|
||||
BUTTON = 'button',
|
||||
STATIC_SELECT = 'static_select',
|
||||
MULTI_STATIC_SELECT = 'multi_static_select',
|
||||
CONVERSATION_SELECT = 'conversations_select',
|
||||
CHANNEL_SELECT = 'channels_select',
|
||||
USER_SELECT = 'users_select',
|
||||
OVERFLOW = 'overflow',
|
||||
DATEPICKER = 'datepicker',
|
||||
PLAIN_TEXT_INPUT = 'plain_text_input',
|
||||
SECTION = 'section',
|
||||
DIVIDER = 'divider',
|
||||
ACTIONS = 'actions',
|
||||
CONTEXT = 'context',
|
||||
FIELDS = 'fields',
|
||||
INPUT = 'input',
|
||||
PLAIN_TEXT = 'plain_text',
|
||||
TEXT = 'text',
|
||||
MARKDOWN = 'mrkdwn'
|
||||
}
|
||||
|
||||
export enum BlockContext {
|
||||
BLOCK,
|
||||
SECTION,
|
||||
ACTION,
|
||||
FORM,
|
||||
CONTEXT
|
||||
}
|
||||
|
||||
export enum ActionTypes {
|
||||
ACTION = 'blockAction',
|
||||
SUBMIT = 'viewSubmit',
|
||||
CLOSED = 'viewClosed'
|
||||
}
|
||||
|
||||
export enum ContainerTypes {
|
||||
VIEW = 'view',
|
||||
MESSAGE = 'message'
|
||||
}
|
||||
|
||||
export enum ModalActions {
|
||||
MODAL = 'modal',
|
||||
OPEN = 'modal.open',
|
||||
CLOSE = 'modal.close',
|
||||
UPDATE = 'modal.update',
|
||||
ERRORS = 'errors'
|
||||
}
|
||||
|
||||
export interface IStateView {
|
||||
[key: string]: { [settings: string]: string | number };
|
||||
}
|
||||
|
||||
export interface IView {
|
||||
appId: string;
|
||||
type: ModalActions;
|
||||
id: string;
|
||||
title: IText;
|
||||
submit: IButton;
|
||||
close: IButton;
|
||||
blocks: Block[];
|
||||
showIcon: boolean;
|
||||
state?: IStateView;
|
||||
}
|
||||
|
||||
export interface Block {
|
||||
type: ElementTypes;
|
||||
blockId: string;
|
||||
element?: IElement;
|
||||
label?: string;
|
||||
appId: string;
|
||||
optional?: boolean;
|
||||
elements?: IElement[];
|
||||
}
|
||||
|
||||
export interface IElement {
|
||||
type: ElementTypes;
|
||||
placeholder?: IText;
|
||||
actionId: string;
|
||||
initialValue?: string;
|
||||
options?: Option[];
|
||||
text?: IText;
|
||||
value?: string;
|
||||
initial_date?: any;
|
||||
imageUrl?: string;
|
||||
appId?: string;
|
||||
blockId?: string;
|
||||
}
|
||||
|
||||
export interface IText {
|
||||
type: ElementTypes;
|
||||
text: string;
|
||||
emoji?: boolean;
|
||||
}
|
||||
|
||||
export interface Option {
|
||||
text: IText;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface IButton {
|
||||
type: ElementTypes;
|
||||
text: IText;
|
||||
actionId: string;
|
||||
value?: any;
|
||||
style?: any;
|
||||
}
|
||||
|
||||
export interface IContainer {
|
||||
type: ContainerTypes;
|
||||
id: string;
|
||||
}
|
||||
|
||||
// methods/actions
|
||||
export interface IUserInteraction {
|
||||
triggerId: string;
|
||||
appId?: string;
|
||||
viewId?: string;
|
||||
view: IView;
|
||||
}
|
||||
|
||||
export interface IEmitUserInteraction extends IUserInteraction {
|
||||
type: ModalActions;
|
||||
}
|
||||
|
||||
export interface ITriggerAction {
|
||||
type: ActionTypes;
|
||||
actionId?: string;
|
||||
appId?: string;
|
||||
container?: IContainer;
|
||||
value?: number;
|
||||
blockId?: string;
|
||||
rid?: string;
|
||||
mid?: string;
|
||||
viewId?: string;
|
||||
payload?: any;
|
||||
view?: IView;
|
||||
}
|
||||
|
||||
export interface ITriggerBlockAction {
|
||||
container: IContainer;
|
||||
actionId: string;
|
||||
appId: string;
|
||||
value: number;
|
||||
blockId?: string;
|
||||
mid?: string;
|
||||
rid?: string;
|
||||
}
|
||||
|
||||
export interface ITriggerSubmitView {
|
||||
viewId: string;
|
||||
appId: string;
|
||||
payload: {
|
||||
view: {
|
||||
id: string;
|
||||
state: IStateView;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface ITriggerCancel {
|
||||
view: IView;
|
||||
appId: string;
|
||||
viewId: string;
|
||||
isCleared: boolean;
|
||||
}
|
||||
|
||||
// UiKit components
|
||||
export interface IParser {
|
||||
renderAccessories: (data: TElementAccessory, context: BlockContext, parser: IParser) => JSX.Element;
|
||||
renderActions: (data: Block, context: BlockContext, parser: IParser) => JSX.Element;
|
||||
renderContext: (data: IElement, context: BlockContext, parser: IParser) => JSX.Element;
|
||||
renderInputs: (data: Partial<IElement>, context: BlockContext, parser: IParser) => JSX.Element;
|
||||
text: (data: IText) => JSX.Element;
|
||||
}
|
||||
export interface IActions extends Block {
|
||||
parser?: IParser;
|
||||
theme: TThemeMode;
|
||||
}
|
||||
|
||||
export interface IContext extends Block {
|
||||
parser: IParser;
|
||||
}
|
||||
|
||||
export interface IDatePicker extends Partial<Block> {
|
||||
language: string;
|
||||
action: Function;
|
||||
context: number;
|
||||
loading: boolean;
|
||||
value: string;
|
||||
error: string;
|
||||
theme: TThemeMode;
|
||||
}
|
||||
|
||||
export interface IInput extends Partial<Block> {
|
||||
parser: IParser;
|
||||
description: string;
|
||||
error: string;
|
||||
hint: string;
|
||||
theme: TThemeMode;
|
||||
}
|
||||
|
||||
export interface IInputIndex {
|
||||
element: IElement;
|
||||
blockId: string;
|
||||
appId: string;
|
||||
label: IText;
|
||||
description: IText;
|
||||
hint: IText;
|
||||
}
|
||||
|
||||
export interface IThumb {
|
||||
element: IElement;
|
||||
size?: number;
|
||||
}
|
||||
export interface IImage {
|
||||
element: IElement;
|
||||
theme: TThemeMode;
|
||||
context?: number;
|
||||
}
|
||||
|
||||
// UiKit/Overflow
|
||||
export interface IOverflow extends Partial<Block> {
|
||||
action: Function;
|
||||
loading: boolean;
|
||||
parser: IParser;
|
||||
theme: TThemeMode;
|
||||
context: number;
|
||||
}
|
||||
|
||||
interface PropsOption {
|
||||
onOptionPress: Function;
|
||||
parser: IParser;
|
||||
theme: TThemeMode;
|
||||
}
|
||||
export interface IOptions extends PropsOption {
|
||||
options: Option[];
|
||||
}
|
||||
|
||||
export interface IOption extends PropsOption {
|
||||
option: Option;
|
||||
}
|
||||
|
||||
// UiKit/Section
|
||||
interface IAccessory {
|
||||
type: ElementTypes;
|
||||
actionId: string;
|
||||
value: number;
|
||||
text: IText;
|
||||
}
|
||||
|
||||
type TElementAccessory = IAccessory & { blockId: string; appId: string };
|
||||
export interface IAccessoryComponent {
|
||||
element: TElementAccessory;
|
||||
parser: IParser;
|
||||
}
|
||||
export interface ISection {
|
||||
blockId: string;
|
||||
appId: string;
|
||||
text?: IText;
|
||||
accessory?: IAccessory;
|
||||
parser: IParser;
|
||||
theme: TThemeMode;
|
||||
fields?: any[];
|
||||
}
|
||||
|
||||
export interface IFields {
|
||||
parser: IParser;
|
||||
theme: TThemeMode;
|
||||
fields: any[];
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
import React, { useContext, useState } from 'react';
|
||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||
|
||||
import { BlockContext } from './interfaces';
|
||||
|
||||
export const textParser = ([{ text }]: any) => text;
|
||||
|
||||
export const defaultContext: any = {
|
||||
|
@ -13,7 +15,19 @@ export const defaultContext: any = {
|
|||
|
||||
export const KitContext = React.createContext(defaultContext);
|
||||
|
||||
export const useBlockContext = ({ blockId, actionId, appId, initialValue }: any, context: any) => {
|
||||
type TObjectReturn = {
|
||||
loading: boolean;
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
error: any;
|
||||
value: any;
|
||||
language: any;
|
||||
};
|
||||
|
||||
type TFunctionReturn = (value: any) => Promise<void>;
|
||||
|
||||
type TReturn = [TObjectReturn, TFunctionReturn];
|
||||
|
||||
export const useBlockContext = ({ blockId, actionId, appId, initialValue }: any, context: BlockContext): TReturn => {
|
||||
const { action, appId: appIdFromContext, viewId, state, language, errors, values = {} } = useContext(KitContext);
|
||||
const { value = initialValue } = values[actionId] || {};
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
|
@ -2,42 +2,37 @@ import random from '../../utils/random';
|
|||
import EventEmitter from '../../utils/events';
|
||||
import fetch from '../../utils/fetch';
|
||||
import Navigation from '../Navigation';
|
||||
|
||||
const ACTION_TYPES = {
|
||||
ACTION: 'blockAction',
|
||||
SUBMIT: 'viewSubmit',
|
||||
CLOSED: 'viewClosed'
|
||||
};
|
||||
|
||||
export const MODAL_ACTIONS = {
|
||||
MODAL: 'modal',
|
||||
OPEN: 'modal.open',
|
||||
CLOSE: 'modal.close',
|
||||
UPDATE: 'modal.update',
|
||||
ERRORS: 'errors'
|
||||
};
|
||||
|
||||
export const CONTAINER_TYPES = {
|
||||
VIEW: 'view',
|
||||
MESSAGE: 'message'
|
||||
};
|
||||
import sdk from '../rocketchat/services/sdk';
|
||||
import {
|
||||
ActionTypes,
|
||||
ITriggerAction,
|
||||
ITriggerBlockAction,
|
||||
ITriggerCancel,
|
||||
ITriggerSubmitView,
|
||||
IUserInteraction,
|
||||
ModalActions
|
||||
} from '../../containers/UIKit/interfaces';
|
||||
import { TRocketChat } from '../../definitions/IRocketChat';
|
||||
|
||||
const triggersId = new Map();
|
||||
|
||||
const invalidateTriggerId = id => {
|
||||
const invalidateTriggerId = (id: string) => {
|
||||
const appId = triggersId.get(id);
|
||||
triggersId.delete(id);
|
||||
return appId;
|
||||
};
|
||||
|
||||
export const generateTriggerId = appId => {
|
||||
export const generateTriggerId = (appId?: string): string => {
|
||||
const triggerId = random(17);
|
||||
triggersId.set(triggerId, appId);
|
||||
|
||||
return triggerId;
|
||||
};
|
||||
|
||||
export const handlePayloadUserInteraction = (type, { triggerId, ...data }) => {
|
||||
export const handlePayloadUserInteraction = (
|
||||
type: ModalActions,
|
||||
{ triggerId, ...data }: IUserInteraction
|
||||
): ModalActions | undefined => {
|
||||
if (!triggersId.has(triggerId)) {
|
||||
return;
|
||||
}
|
||||
|
@ -58,7 +53,7 @@ export const handlePayloadUserInteraction = (type, { triggerId, ...data }) => {
|
|||
return;
|
||||
}
|
||||
|
||||
if ([MODAL_ACTIONS.ERRORS].includes(type)) {
|
||||
if ([ModalActions.ERRORS].includes(type)) {
|
||||
EventEmitter.emit(viewId, {
|
||||
type,
|
||||
triggerId,
|
||||
|
@ -66,10 +61,10 @@ export const handlePayloadUserInteraction = (type, { triggerId, ...data }) => {
|
|||
appId,
|
||||
...data
|
||||
});
|
||||
return MODAL_ACTIONS.ERRORS;
|
||||
return ModalActions.ERRORS;
|
||||
}
|
||||
|
||||
if ([MODAL_ACTIONS.UPDATE].includes(type)) {
|
||||
if ([ModalActions.UPDATE].includes(type)) {
|
||||
EventEmitter.emit(viewId, {
|
||||
type,
|
||||
triggerId,
|
||||
|
@ -77,10 +72,10 @@ export const handlePayloadUserInteraction = (type, { triggerId, ...data }) => {
|
|||
appId,
|
||||
...data
|
||||
});
|
||||
return MODAL_ACTIONS.UPDATE;
|
||||
return ModalActions.UPDATE;
|
||||
}
|
||||
|
||||
if ([MODAL_ACTIONS.OPEN].includes(type) || [MODAL_ACTIONS.MODAL].includes(type)) {
|
||||
if ([ModalActions.OPEN].includes(type) || [ModalActions.MODAL].includes(type)) {
|
||||
Navigation.navigate('ModalBlockView', {
|
||||
data: {
|
||||
triggerId,
|
||||
|
@ -89,21 +84,24 @@ export const handlePayloadUserInteraction = (type, { triggerId, ...data }) => {
|
|||
...data
|
||||
}
|
||||
});
|
||||
return MODAL_ACTIONS.OPEN;
|
||||
return ModalActions.OPEN;
|
||||
}
|
||||
|
||||
return MODAL_ACTIONS.CLOSE;
|
||||
return ModalActions.CLOSE;
|
||||
};
|
||||
|
||||
export function triggerAction({ type, actionId, appId, rid, mid, viewId, container, ...rest }) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
export function triggerAction(
|
||||
this: TRocketChat,
|
||||
{ type, actionId, appId, rid, mid, viewId, container, ...rest }: ITriggerAction
|
||||
) {
|
||||
return new Promise<ModalActions | undefined | void>(async (resolve, reject) => {
|
||||
const triggerId = generateTriggerId(appId);
|
||||
|
||||
const payload = rest.payload || rest;
|
||||
|
||||
try {
|
||||
const { userId, authToken } = this.sdk.currentLogin;
|
||||
const { host } = this.sdk.client;
|
||||
const { userId, authToken } = sdk.current.currentLogin;
|
||||
const { host } = sdk.current.client;
|
||||
|
||||
// we need to use fetch because this.sdk.post add /v1 to url
|
||||
const result = await fetch(`${host}/api/apps/ui.interaction/${appId}/`, {
|
||||
|
@ -142,17 +140,17 @@ export function triggerAction({ type, actionId, appId, rid, mid, viewId, contain
|
|||
});
|
||||
}
|
||||
|
||||
export default function triggerBlockAction(options) {
|
||||
return triggerAction.call(this, { type: ACTION_TYPES.ACTION, ...options });
|
||||
export default function triggerBlockAction(this: TRocketChat, options: ITriggerBlockAction) {
|
||||
return triggerAction.call(this, { type: ActionTypes.ACTION, ...options });
|
||||
}
|
||||
|
||||
export async function triggerSubmitView({ viewId, ...options }) {
|
||||
const result = await triggerAction.call(this, { type: ACTION_TYPES.SUBMIT, viewId, ...options });
|
||||
if (!result || MODAL_ACTIONS.CLOSE === result) {
|
||||
export async function triggerSubmitView(this: TRocketChat, { viewId, ...options }: ITriggerSubmitView) {
|
||||
const result = await triggerAction.call(this, { type: ActionTypes.SUBMIT, viewId, ...options });
|
||||
if (!result || ModalActions.CLOSE === result) {
|
||||
Navigation.back();
|
||||
}
|
||||
}
|
||||
|
||||
export function triggerCancel({ view, ...options }) {
|
||||
return triggerAction.call(this, { type: ACTION_TYPES.CLOSED, view, ...options });
|
||||
export function triggerCancel(this: TRocketChat, { view, ...options }: ITriggerCancel) {
|
||||
return triggerAction.call(this, { type: ActionTypes.CLOSED, view, ...options });
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { IEmitUserInteraction } from '../containers/UIKit/interfaces';
|
||||
import { ICommand } from '../definitions/ICommand';
|
||||
import log from './log';
|
||||
|
||||
|
@ -11,7 +12,8 @@ type TEventEmitterEmmitArgs =
|
|||
| { hasBiometry: boolean }
|
||||
| { event: string | ICommand }
|
||||
| { cancel: () => void }
|
||||
| { submit: (param: string) => void };
|
||||
| { submit: (param: string) => void }
|
||||
| IEmitUserInteraction;
|
||||
|
||||
class EventEmitter {
|
||||
private events: { [key: string]: any };
|
||||
|
|
|
@ -4,9 +4,21 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk';
|
|||
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
export type TMethods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put';
|
||||
|
||||
interface CustomHeaders {
|
||||
'User-Agent': string;
|
||||
'User-Agent'?: string;
|
||||
Authorization?: string;
|
||||
'Content-Type'?: string;
|
||||
'X-Auth-Token'?: string;
|
||||
'X-User-Id'?: string;
|
||||
}
|
||||
|
||||
interface IOptions {
|
||||
headers?: CustomHeaders;
|
||||
signal?: AbortSignal;
|
||||
method?: TMethods;
|
||||
body?: any;
|
||||
}
|
||||
|
||||
// this form is required by Rocket.Chat's parser in "app/statistics/server/lib/UAParserCustom.js"
|
||||
|
@ -29,7 +41,7 @@ export const BASIC_AUTH_KEY = 'BASIC_AUTH_KEY';
|
|||
|
||||
RocketChatSettings.customHeaders = headers;
|
||||
|
||||
export default (url: string, options: { headers?: Headers; signal?: AbortSignal } = {}): Promise<Response> => {
|
||||
export default (url: string, options: IOptions = {}): Promise<Response> => {
|
||||
let customOptions = { ...options, headers: RocketChatSettings.customHeaders };
|
||||
if (options && options.headers) {
|
||||
customOptions = { ...customOptions, headers: { ...options.headers, ...customOptions.headers } };
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import RNFetchBlob from 'rn-fetch-blob';
|
||||
|
||||
import { TMethods } from '../fetch';
|
||||
import { IFileUpload } from './interfaces';
|
||||
|
||||
type TMethods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put';
|
||||
|
||||
class FileUpload {
|
||||
fetch = (method: TMethods, url: string, headers: { [key: string]: string }, data: IFileUpload[]) => {
|
||||
const formData = data.map(item => {
|
||||
|
|
|
@ -12,10 +12,10 @@ import * as HeaderButton from '../containers/HeaderButton';
|
|||
import { modalBlockWithContext } from '../containers/UIKit/MessageBlock';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import ActivityIndicator from '../containers/ActivityIndicator';
|
||||
import { CONTAINER_TYPES, MODAL_ACTIONS } from '../lib/methods/actions';
|
||||
import { textParser } from '../containers/UIKit/utils';
|
||||
import Navigation from '../lib/Navigation';
|
||||
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
|
||||
import { ContainerTypes, ModalActions } from '../containers/UIKit/interfaces';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -161,8 +161,8 @@ class ModalBlockView extends React.Component<IModalBlockViewProps, IModalBlockVi
|
|||
});
|
||||
};
|
||||
|
||||
handleUpdate = ({ type, ...data }: { type: string }) => {
|
||||
if ([MODAL_ACTIONS.ERRORS].includes(type)) {
|
||||
handleUpdate = ({ type, ...data }: { type: ModalActions }) => {
|
||||
if ([ModalActions.ERRORS].includes(type)) {
|
||||
const { errors }: any = data;
|
||||
this.setState({ errors });
|
||||
} else {
|
||||
|
@ -232,7 +232,7 @@ class ModalBlockView extends React.Component<IModalBlockViewProps, IModalBlockVi
|
|||
const { mid, appId, viewId } = data;
|
||||
await RocketChat.triggerBlockAction({
|
||||
container: {
|
||||
type: CONTAINER_TYPES.VIEW,
|
||||
type: ContainerTypes.VIEW,
|
||||
id: viewId
|
||||
},
|
||||
actionId,
|
||||
|
|
|
@ -44,7 +44,6 @@ import {
|
|||
import { Review } from '../../utils/review';
|
||||
import RoomClass from '../../lib/methods/subscriptions/room';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import { CONTAINER_TYPES } from '../../lib/methods/actions';
|
||||
import Navigation from '../../lib/Navigation';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
|
@ -55,6 +54,7 @@ import Loading from '../../containers/Loading';
|
|||
import { goRoom, TGoRoomItem } from '../../utils/goRoom';
|
||||
import getThreadName from '../../lib/methods/getThreadName';
|
||||
import getRoomInfo from '../../lib/methods/getRoomInfo';
|
||||
import { ContainerTypes } from '../../containers/UIKit/interfaces';
|
||||
import RoomServices from './services';
|
||||
import LoadMore from './LoadMore';
|
||||
import Banner from './Banner';
|
||||
|
@ -1104,7 +1104,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
rid,
|
||||
appId,
|
||||
container: {
|
||||
type: CONTAINER_TYPES.MESSAGE,
|
||||
type: ContainerTypes.MESSAGE,
|
||||
id: mid
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue