Merge branch 'improvement.typescript-migration' into improvement.eslint-change-to-ts
This commit is contained in:
commit
7cf55c1f3b
|
@ -3,7 +3,8 @@ defaults: &defaults
|
|||
|
||||
macos: &macos
|
||||
macos:
|
||||
xcode: "12.5.0"
|
||||
xcode: "12.5.0"
|
||||
resource_class: large
|
||||
|
||||
bash-env: &bash-env
|
||||
BASH_ENV: "~/.nvm/nvm.sh"
|
||||
|
@ -143,15 +144,6 @@ commands:
|
|||
fi
|
||||
working_directory: android/app
|
||||
|
||||
- run:
|
||||
name: Config variables
|
||||
command: |
|
||||
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
|
||||
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY_OFFICIAL' };" > ./config.js
|
||||
else
|
||||
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Build App
|
||||
command: |
|
||||
|
@ -170,22 +162,20 @@ commands:
|
|||
name: Upload sourcemaps to Bugsnag
|
||||
command: |
|
||||
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
|
||||
yarn generate-source-maps-android upload \
|
||||
npx bugsnag-source-maps upload-react-native \
|
||||
--api-key=$BUGSNAG_KEY_OFFICIAL \
|
||||
--app-version=$CIRCLE_BUILD_NUM \
|
||||
--minifiedFile=android/app/build/generated/assets/react/officialPlay/release/app.bundle \
|
||||
--app-version-code=$CIRCLE_BUILD_NUM \
|
||||
--platform android \
|
||||
--source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \
|
||||
--minified-url=app.bundle \
|
||||
--upload-sources
|
||||
--bundle android/app/build/generated/assets/react/officialPlay/release/app.bundle
|
||||
fi
|
||||
if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then
|
||||
yarn generate-source-maps-android upload \
|
||||
npx bugsnag-source-maps upload-react-native \
|
||||
--api-key=$BUGSNAG_KEY \
|
||||
--app-version=$CIRCLE_BUILD_NUM \
|
||||
--minifiedFile=android/app/build/generated/assets/react/experimentalPlay/release/app.bundle \
|
||||
--app-version-code=$CIRCLE_BUILD_NUM \
|
||||
--platform android \
|
||||
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \
|
||||
--minified-url=app.bundle \
|
||||
--upload-sources
|
||||
--bundle android/app/build/generated/assets/react/experimentalPlay/release/app.bundle
|
||||
fi
|
||||
|
||||
- store_artifacts:
|
||||
|
@ -216,41 +206,20 @@ commands:
|
|||
echo $GOOGLE_SERVICES_IOS | base64 --decode > GoogleService-Info.plist
|
||||
fi
|
||||
working_directory: ios
|
||||
- run:
|
||||
name: Upload sourcemaps to Bugsnag
|
||||
command: |
|
||||
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
|
||||
yarn generate-source-maps-ios
|
||||
curl https://upload.bugsnag.com/react-native-source-map \
|
||||
-F apiKey=$BUGSNAG_KEY_OFFICIAL \
|
||||
-F appBundleVersion=$CIRCLE_BUILD_NUM \
|
||||
-F dev=false \
|
||||
-F platform=ios \
|
||||
-F sourceMap=@ios-release.bundle.map \
|
||||
-F bundle=@ios-release.bundle
|
||||
fi
|
||||
if [[ $CIRCLE_JOB == "ios-build-experimental" ]]; then
|
||||
yarn generate-source-maps-ios
|
||||
curl https://upload.bugsnag.com/react-native-source-map \
|
||||
-F apiKey=$BUGSNAG_KEY \
|
||||
-F appBundleVersion=$CIRCLE_BUILD_NUM \
|
||||
-F dev=false \
|
||||
-F platform=ios \
|
||||
-F sourceMap=@ios-release.bundle.map \
|
||||
-F bundle=@ios-release.bundle
|
||||
fi
|
||||
- run:
|
||||
name: Fastlane Build
|
||||
no_output_timeout: 40m
|
||||
command: |
|
||||
agvtool new-version -all $CIRCLE_BUILD_NUM
|
||||
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
|
||||
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY_OFFICIAL" ./ShareRocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./ShareRocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./NotificationService/Info.plist
|
||||
else
|
||||
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./ShareRocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./RocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./ShareRocketChatRN/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./NotificationService/Info.plist
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
start: () => '',
|
||||
leaveBreadcrumb: () => '',
|
||||
notify: () => ''
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
export class Client { }
|
||||
|
||||
export default {
|
||||
bugsnag: () => '',
|
||||
leaveBreadcrumb: () => '',
|
||||
notify: () => '',
|
||||
loggerConfig: () => ''
|
||||
};
|
|
@ -4693,7 +4693,7 @@ exports[`Storyshots List pressable 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -6211,7 +6211,7 @@ exports[`Storyshots List with bigger font 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 69,
|
||||
},
|
||||
|
@ -6625,7 +6625,7 @@ exports[`Storyshots List with bigger font 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 69,
|
||||
},
|
||||
|
@ -7080,7 +7080,7 @@ exports[`Storyshots List with black theme 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -7494,7 +7494,7 @@ exports[`Storyshots List with black theme 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -7972,7 +7972,7 @@ exports[`Storyshots List with custom colors 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -8129,7 +8129,7 @@ exports[`Storyshots List with dark theme 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -8543,7 +8543,7 @@ exports[`Storyshots List with dark theme 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 92,
|
||||
},
|
||||
|
@ -10410,7 +10410,7 @@ exports[`Storyshots List with small font 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 36.800000000000004,
|
||||
},
|
||||
|
@ -10824,7 +10824,7 @@ exports[`Storyshots List with small font 1`] = `
|
|||
"justifyContent": "center",
|
||||
"paddingHorizontal": 12,
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
Object {
|
||||
"height": 36.800000000000004,
|
||||
},
|
||||
|
|
|
@ -144,7 +144,7 @@ android {
|
|||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode VERSIONCODE as Integer
|
||||
versionName "4.18.0"
|
||||
versionName "4.19.0"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
if (!isFoss) {
|
||||
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
|
||||
|
|
|
@ -8,8 +8,15 @@ import com.wix.reactnativenotifications.core.AppLifecycleFacade;
|
|||
import com.wix.reactnativenotifications.core.JsIOHelper;
|
||||
import com.wix.reactnativenotifications.core.notification.INotificationsApplication;
|
||||
import com.wix.reactnativenotifications.core.notification.IPushNotification;
|
||||
import com.bugsnag.android.Bugsnag;
|
||||
|
||||
public class MainPlayApplication extends MainApplication implements INotificationsApplication {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Bugsnag.start(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) {
|
||||
return new CustomPushNotification(
|
||||
|
|
|
@ -25,7 +25,7 @@ import * as List from '../List';
|
|||
import I18n from '../../i18n';
|
||||
import { useOrientation, useDimensions, IDimensionsContextProps } from '../../dimensions';
|
||||
|
||||
type TActionSheetData = {
|
||||
interface IActionSheetData {
|
||||
options: any;
|
||||
headerHeight?: number;
|
||||
hasCancel?: boolean;
|
||||
|
@ -48,7 +48,7 @@ const ANIMATION_CONFIG = {
|
|||
|
||||
const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.Element; theme: string}, ref) => {
|
||||
const bottomSheetRef: any = useRef();
|
||||
const [data, setData] = useState<TActionSheetData>({} as TActionSheetData);
|
||||
const [data, setData] = useState<IActionSheetData>({} as IActionSheetData);
|
||||
const [isVisible, setVisible] = useState(false);
|
||||
const { height }: Partial<IDimensionsContextProps> = useDimensions();
|
||||
const { isLandscape } = useOrientation();
|
||||
|
|
|
@ -2,10 +2,12 @@ import React from 'react';
|
|||
import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-native';
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
type TTheme = 'light' | 'dark' | 'black' | string;
|
||||
|
||||
interface IActivityIndicator extends ActivityIndicatorProps{
|
||||
theme?: 'light' | 'dark' | 'black' | string,
|
||||
absolute?: boolean,
|
||||
props?: object
|
||||
theme?: TTheme;
|
||||
absolute?: boolean;
|
||||
props?: object;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
|
|
@ -6,39 +6,12 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk';
|
|||
|
||||
import { avatarURL } from '../../utils/avatar';
|
||||
import Emoji from '../markdown/Emoji';
|
||||
|
||||
export interface IAvatar {
|
||||
server?: string;
|
||||
style?: any,
|
||||
text?: string;
|
||||
avatar?: string;
|
||||
emoji?: string;
|
||||
size?: number;
|
||||
borderRadius?: number;
|
||||
type?: string;
|
||||
children?: JSX.Element;
|
||||
user?: {
|
||||
id: string;
|
||||
token: string;
|
||||
};
|
||||
theme: string;
|
||||
onPress?(): void;
|
||||
getCustomEmoji(): any;
|
||||
avatarETag?: string;
|
||||
isStatic?: boolean;
|
||||
rid?: string;
|
||||
blockUnauthenticatedAccess?: boolean;
|
||||
serverVersion?: string;
|
||||
}
|
||||
import {IAvatar} from './interfaces';
|
||||
|
||||
const Avatar = React.memo(({
|
||||
text,
|
||||
size,
|
||||
server,
|
||||
borderRadius,
|
||||
style,
|
||||
style,
|
||||
avatar,
|
||||
type,
|
||||
children,
|
||||
user,
|
||||
onPress,
|
||||
|
@ -49,8 +22,13 @@ const Avatar = React.memo(({
|
|||
isStatic,
|
||||
rid,
|
||||
blockUnauthenticatedAccess,
|
||||
serverVersion
|
||||
serverVersion,
|
||||
text,
|
||||
size = 25,
|
||||
borderRadius = 4,
|
||||
type = 'd',
|
||||
}: Partial<IAvatar>) => {
|
||||
|
||||
if ((!text && !avatar && !emoji && !rid) || !server) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,19 @@ import { Q } from '@nozbe/watermelondb';
|
|||
|
||||
import database from '../../lib/database';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import Avatar, {IAvatar} from './Avatar';
|
||||
import Avatar from './Avatar';
|
||||
import {IAvatar} from "./interfaces";
|
||||
|
||||
|
||||
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
|
||||
private mounted: boolean;
|
||||
private subscription!: any;
|
||||
|
||||
static defaultProps = {
|
||||
text: '',
|
||||
type: 'd'
|
||||
};
|
||||
|
||||
constructor(props: Partial<IAvatar>) {
|
||||
super(props);
|
||||
this.mounted = false;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
export interface IAvatar {
|
||||
server: string;
|
||||
style: any,
|
||||
text: string;
|
||||
avatar: string;
|
||||
emoji: string;
|
||||
size: number;
|
||||
borderRadius: number;
|
||||
type: string;
|
||||
children: JSX.Element;
|
||||
user: {
|
||||
id: string;
|
||||
token: string;
|
||||
};
|
||||
theme: string;
|
||||
onPress(): void;
|
||||
getCustomEmoji(): any;
|
||||
avatarETag: string;
|
||||
isStatic: boolean;
|
||||
rid: string;
|
||||
blockUnauthenticatedAccess: boolean;
|
||||
serverVersion: string;
|
||||
}
|
|
@ -24,7 +24,7 @@ stories.add('long text', () => (
|
|||
<BackgroundContainer text={longText} />
|
||||
));
|
||||
|
||||
const ThemeStory = ({ theme, ...props }: any) => (
|
||||
const ThemeStory = ({ theme, ...props }) => (
|
||||
<ThemeContext.Provider
|
||||
value={{ theme }}
|
||||
>
|
|
@ -40,6 +40,14 @@ const styles = StyleSheet.create({
|
|||
|
||||
export default class Button extends React.PureComponent<Partial<IButtonProps>, any> {
|
||||
|
||||
static defaultProps = {
|
||||
title: 'Press me!',
|
||||
type: 'primary',
|
||||
onPress: () => alert('It works!'),
|
||||
disabled: false,
|
||||
loading: false
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
title, type, onPress, disabled, backgroundColor, color, loading, style, theme, fontSize, ...otherProps
|
||||
|
|
|
@ -4,9 +4,9 @@ import { StyleSheet } from 'react-native';
|
|||
import { CustomIcon } from '../lib/Icons';
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
type TCheck = {
|
||||
style?: object,
|
||||
theme: string
|
||||
interface ICheck {
|
||||
style?: object;
|
||||
theme: string;
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
|
@ -16,6 +16,6 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const Check = React.memo(({ theme, style }: TCheck) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);
|
||||
const Check = React.memo(({ theme, style }: ICheck) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);
|
||||
|
||||
export default Check;
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
import React from 'react';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import {TEmoji} from "./index";
|
||||
|
||||
interface ICustomEmoji {
|
||||
baseUrl: string,
|
||||
emoji: TEmoji,
|
||||
style: any
|
||||
}
|
||||
import {ICustomEmoji} from "./interfaces";
|
||||
|
||||
const CustomEmoji = React.memo(({ baseUrl, emoji, style }: ICustomEmoji) => (
|
||||
<FastImage
|
||||
|
|
|
@ -5,20 +5,11 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
|||
import styles from './styles';
|
||||
import CustomEmoji from './CustomEmoji';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import {IEmoji, IEmojiCategory} from "./interfaces";
|
||||
|
||||
const EMOJI_SIZE: number = 50;
|
||||
const EMOJI_SIZE = 50;
|
||||
|
||||
interface IEmoji {
|
||||
baseUrl: string;
|
||||
emojis: any;
|
||||
onEmojiSelected({}: any): void;
|
||||
emojisPerRow: number;
|
||||
width: number;
|
||||
style: any;
|
||||
tabLabel: string;
|
||||
}
|
||||
|
||||
const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
|
||||
const renderEmoji = (emoji: IEmoji, size: number, baseUrl: string) => {
|
||||
if (emoji && emoji.isCustom) {
|
||||
return <CustomEmoji style={[styles.customCategoryEmoji, { height: size - 16, width: size - 16 }]} emoji={emoji} baseUrl={baseUrl} />;
|
||||
}
|
||||
|
@ -29,7 +20,7 @@ const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
class EmojiCategory extends React.Component<Partial<IEmoji>> {
|
||||
class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
|
||||
|
||||
renderItem(emoji: any) {
|
||||
const { baseUrl, onEmojiSelected } = this.props;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { View, TouchableOpacity, Text } from 'react-native';
|
|||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
interface ITabBar {
|
||||
interface ITabBarProps {
|
||||
goToPage({}): void;
|
||||
activeTab: number,
|
||||
tabs: [],
|
||||
|
@ -11,7 +11,7 @@ interface ITabBar {
|
|||
theme: string
|
||||
}
|
||||
|
||||
export default class TabBar extends React.Component<Partial<ITabBar>> {
|
||||
export default class TabBar extends React.Component<Partial<ITabBarProps>> {
|
||||
|
||||
shouldComponentUpdate(nextProps: any) {
|
||||
const { activeTab, theme } = this.props;
|
||||
|
|
|
@ -17,18 +17,22 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
|||
import log from '../../utils/log';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import {IEmoji} from "../markdown/Emoji";
|
||||
import {IEmoji} from "./interfaces";
|
||||
|
||||
const scrollProps = {
|
||||
keyboardShouldPersistTaps: 'always',
|
||||
keyboardDismissMode: 'none'
|
||||
};
|
||||
|
||||
export type TEmoji = {
|
||||
content: any;
|
||||
name: string;
|
||||
extension: any;
|
||||
isCustom: boolean;
|
||||
interface IEmojiPickerProps {
|
||||
isMessageContainsOnlyEmoji: boolean;
|
||||
getCustomEmoji?: Function;
|
||||
baseUrl: string;
|
||||
customEmojis?: any;
|
||||
style: object;
|
||||
theme?: string;
|
||||
onEmojiSelected?: Function;
|
||||
tabEmojiStyle?: object;
|
||||
}
|
||||
|
||||
interface IEmojiPickerState {
|
||||
|
@ -38,9 +42,9 @@ interface IEmojiPickerState {
|
|||
width: number | null;
|
||||
}
|
||||
|
||||
class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
|
||||
class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||
|
||||
constructor(props: IEmoji) {
|
||||
constructor(props: IEmojiPickerProps) {
|
||||
super(props);
|
||||
const customEmojis = Object.keys(props.customEmojis)
|
||||
.filter(item => item === props.customEmojis[item].name)
|
||||
|
@ -80,7 +84,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
|
|||
return false;
|
||||
}
|
||||
|
||||
onEmojiSelected = (emoji: TEmoji) => {
|
||||
onEmojiSelected = (emoji: IEmoji) => {
|
||||
try {
|
||||
const { onEmojiSelected } = this.props;
|
||||
if (emoji.isCustom) {
|
||||
|
@ -100,7 +104,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
_addFrequentlyUsed = protectedFunction(async(emoji: TEmoji) => {
|
||||
_addFrequentlyUsed = protectedFunction(async(emoji: IEmoji) => {
|
||||
const db = database.active;
|
||||
const freqEmojiCollection = db.get('frequently_used_emojis');
|
||||
let freqEmojiRecord: any;
|
||||
|
@ -129,7 +133,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
|
|||
const db = database.active;
|
||||
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
|
||||
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
|
||||
frequentlyUsed = frequentlyUsed.map((item: TEmoji) => {
|
||||
frequentlyUsed = frequentlyUsed.map((item: IEmoji) => {
|
||||
if (item.isCustom) {
|
||||
return { content: item.content, extension: item.extension, isCustom: item.isCustom };
|
||||
}
|
||||
|
@ -192,7 +196,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IEmojiPickerState) => ({
|
||||
const mapStateToProps = (state: any) => ({
|
||||
customEmojis: state.customEmojis
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
export interface IEmoji {
|
||||
content: any;
|
||||
name: string;
|
||||
extension: any;
|
||||
isCustom: boolean;
|
||||
}
|
||||
|
||||
export interface ICustomEmoji {
|
||||
baseUrl: string,
|
||||
emoji: IEmoji,
|
||||
style: any
|
||||
}
|
||||
|
||||
export interface IEmojiCategory {
|
||||
baseUrl: string;
|
||||
emojis: IEmoji[];
|
||||
onEmojiSelected({}: any): void;
|
||||
emojisPerRow: number;
|
||||
width: number;
|
||||
style: any;
|
||||
tabLabel: string;
|
||||
}
|
|
@ -29,6 +29,7 @@ export const FormContainerInner = ({ children }: {children: JSX.Element}) => (
|
|||
);
|
||||
|
||||
const FormContainer = ({ children, theme, testID, ...props }: IFormContainer) => (
|
||||
// @ts-ignore
|
||||
<KeyboardView
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
contentContainerStyle={sharedStyles.container}
|
||||
|
|
|
@ -20,7 +20,7 @@ export const getHeaderHeight = (isLandscape: boolean) => {
|
|||
return 56;
|
||||
};
|
||||
|
||||
type THeaderTitlePosition = {
|
||||
interface IHeaderTitlePosition {
|
||||
insets: {
|
||||
left: number;
|
||||
right: number;
|
||||
|
@ -28,7 +28,7 @@ type THeaderTitlePosition = {
|
|||
numIconsRight: number;
|
||||
}
|
||||
|
||||
export const getHeaderTitlePosition = ({ insets, numIconsRight }: THeaderTitlePosition) => ({
|
||||
export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
|
||||
left: insets.left + 60,
|
||||
right: insets.right + Math.max(45 * numIconsRight, 15)
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const Container = ({ children, left }: IHeaderButtonContainer) => (
|
||||
const Container = ({ children, left = false }: IHeaderButtonContainer) => (
|
||||
<View style={[styles.container, left ? styles.left : styles.right]}>
|
||||
{children}
|
||||
</View>
|
||||
|
|
|
@ -9,10 +9,10 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TListContainer = {
|
||||
interface IListContainer {
|
||||
children: JSX.Element;
|
||||
}
|
||||
const ListContainer = React.memo(({ children, ...props }: TListContainer) => (
|
||||
const ListContainer = React.memo(({ children, ...props }: IListContainer) => (
|
||||
// @ts-ignore
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.container}
|
||||
|
|
|
@ -10,12 +10,12 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TListSeparator = {
|
||||
interface IListSeparator {
|
||||
style: object;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const ListSeparator = React.memo(({ style, theme }: TListSeparator) => (
|
||||
const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
|
||||
<View
|
||||
style={[
|
||||
styles.separator,
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View, Modal, Animated } from 'react-native';
|
||||
import { StyleSheet, Modal, Animated , View } from 'react-native';
|
||||
import { withTheme } from '../theme';
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.25)'
|
||||
justifyContent: 'center'
|
||||
},
|
||||
image: {
|
||||
width: 100,
|
||||
|
@ -17,9 +18,10 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface ILoadingProps {
|
||||
visible: boolean;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export default class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||
class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||
|
||||
state = {
|
||||
scale: new Animated.Value(1),
|
||||
|
@ -36,7 +38,7 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
|
|||
opacity,
|
||||
{
|
||||
toValue: 1,
|
||||
duration: 1000,
|
||||
duration: 200,
|
||||
useNativeDriver: true
|
||||
}
|
||||
);
|
||||
|
@ -91,23 +93,40 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
|
|||
|
||||
render() {
|
||||
const { opacity, scale } = this.state;
|
||||
const { visible } = this.props;
|
||||
const { visible, theme } = this.props;
|
||||
|
||||
const scaleAnimation = scale.interpolate({
|
||||
inputRange: [0, 0.5, 1],
|
||||
outputRange: [1, 1.1, 1]
|
||||
});
|
||||
|
||||
const opacityAnimation = opacity.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, themes[theme].backdropOpacity],
|
||||
extrapolate: 'clamp'
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
transparent
|
||||
onRequestClose={() => {}}
|
||||
>
|
||||
<View style={styles.container} testID='loading'>
|
||||
<View
|
||||
style={styles.container}
|
||||
testID='loading'
|
||||
>
|
||||
<Animated.View
|
||||
style={[{
|
||||
// @ts-ignore
|
||||
...StyleSheet.absoluteFill,
|
||||
backgroundColor: themes[theme].backdropColor,
|
||||
opacity: opacityAnimation
|
||||
}]}
|
||||
/>
|
||||
<Animated.Image
|
||||
source={require('../static/images/logo.png')}
|
||||
style={[styles.image, {
|
||||
opacity,
|
||||
transform: [{
|
||||
scale: scaleAnimation
|
||||
}]
|
||||
|
@ -118,3 +137,5 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default (withTheme(Loading));
|
||||
|
|
|
@ -57,19 +57,19 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TOpenOAuth = {
|
||||
interface IOpenOAuth {
|
||||
url?: string;
|
||||
ssoToken?: string;
|
||||
authType?: string;
|
||||
}
|
||||
|
||||
type TService = {
|
||||
interface IService {
|
||||
name: string;
|
||||
service: string;
|
||||
authType: string;
|
||||
buttonColor: string;
|
||||
buttonLabelColor: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ILoginServicesProps {
|
||||
navigation: any;
|
||||
|
@ -93,6 +93,10 @@ interface ILoginServicesProps {
|
|||
class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||
private _animation: any;
|
||||
|
||||
static defaultProps = {
|
||||
separator: true
|
||||
}
|
||||
|
||||
state = {
|
||||
collapsed: true,
|
||||
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
|
||||
|
@ -251,7 +255,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
|||
return Base64.encodeURI(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
openOAuth = ({ url, ssoToken, authType = 'oauth' }: TOpenOAuth) => {
|
||||
openOAuth = ({ url, ssoToken, authType = 'oauth' }: IOpenOAuth) => {
|
||||
const { navigation } = this.props;
|
||||
navigation.navigate('AuthenticationWebView', { url, authType, ssoToken });
|
||||
}
|
||||
|
@ -322,7 +326,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
|||
return null;
|
||||
}
|
||||
|
||||
renderItem = (service: TService) => {
|
||||
renderItem = (service: IService) => {
|
||||
const { CAS_enabled, theme } = this.props;
|
||||
let { name } = service;
|
||||
name = name === 'meteor-developer' ? 'meteor' : name;
|
||||
|
|
|
@ -10,7 +10,7 @@ import database from '../../lib/database';
|
|||
import { Button } from '../ActionSheet';
|
||||
import { useDimensions } from '../../dimensions';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import {TEmoji} from "../EmojiPicker";
|
||||
import {IEmoji} from "../EmojiPicker/interfaces";
|
||||
|
||||
interface IHeader {
|
||||
handleReaction: Function;
|
||||
|
@ -21,7 +21,7 @@ interface IHeader {
|
|||
}
|
||||
|
||||
interface THeaderItem {
|
||||
item: TEmoji;
|
||||
item: IEmoji;
|
||||
onReaction: Function;
|
||||
server: string;
|
||||
theme: string;
|
||||
|
@ -118,7 +118,7 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
|
|||
setEmojis();
|
||||
}, []);
|
||||
|
||||
const onReaction = ({ emoji }: {emoji: TEmoji}) => handleReaction(emoji, message);
|
||||
const onReaction = ({ emoji }: {emoji: IEmoji}) => handleReaction(emoji, message);
|
||||
|
||||
const renderItem = useCallback(({ item }) => <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme} />, []);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { withTheme } from '../../theme';
|
|||
interface IMessageBoxEmojiKeyboard {
|
||||
theme: string
|
||||
}
|
||||
|
||||
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
|
||||
private readonly baseUrl: any;
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@ import shortnameToUnicode from '../../../utils/shortnameToUnicode';
|
|||
import styles from '../styles';
|
||||
import MessageboxContext from '../Context';
|
||||
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
|
||||
import {TEmoji} from "../../EmojiPicker";
|
||||
import {IEmoji} from "../../EmojiPicker/interfaces";
|
||||
|
||||
interface IMessageBoxMentionEmoji {
|
||||
item: TEmoji;
|
||||
item: IEmoji;
|
||||
}
|
||||
|
||||
const MentionEmoji = ({ item }: IMessageBoxMentionEmoji) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import FixedMentionItem from './FixedMentionItem';
|
|||
import MentionEmoji from './MentionEmoji';
|
||||
import { MENTIONS_TRACKING_TYPE_EMOJIS, MENTIONS_TRACKING_TYPE_COMMANDS } from '../constants';
|
||||
import { themes } from '../../../constants/colors';
|
||||
import {TEmoji} from "../../EmojiPicker";
|
||||
import {IEmoji} from "../../EmojiPicker/interfaces";
|
||||
|
||||
interface IMessageBoxMentionItem {
|
||||
item: {
|
||||
|
@ -17,7 +17,7 @@ interface IMessageBoxMentionItem {
|
|||
username: string;
|
||||
t: string;
|
||||
id: string;
|
||||
} & TEmoji;
|
||||
} & IEmoji;
|
||||
trackingType: string;
|
||||
theme: string;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ interface IMessageBoxMentions {
|
|||
trackingType: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Mentions = React.memo(({ mentions, trackingType, theme }: IMessageBoxMentions) => {
|
||||
if (!trackingType) {
|
||||
return null;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { View, Alert, Keyboard, Text } from 'react-native';
|
||||
import {View, Alert, Keyboard, Text, NativeModules} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
||||
import ImagePicker from 'react-native-image-crop-picker';
|
||||
|
@ -111,6 +111,7 @@ interface IMessageBoxProps {
|
|||
sharing: boolean;
|
||||
isActionsEnabled: boolean;
|
||||
}
|
||||
|
||||
interface IMessageBoxState {
|
||||
mentions: any[];
|
||||
showEmojiKeyboard: boolean;
|
||||
|
@ -143,6 +144,16 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
|||
private component: any;
|
||||
private typingTimeout: any;
|
||||
|
||||
static defaultProps = {
|
||||
message: {
|
||||
id: ''
|
||||
},
|
||||
sharing: false,
|
||||
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
|
||||
isActionsEnabled: true,
|
||||
getCustomEmoji: () => {}
|
||||
}
|
||||
|
||||
constructor(props: IMessageBoxProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -958,6 +969,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
|||
//@ts-ignore
|
||||
style={[styles.textBoxInput, { color: themes[theme].bodyText }]}
|
||||
returnKeyType='default'
|
||||
//@ts-ignore
|
||||
keyboardType='twitter'
|
||||
blurOnSubmit={false}
|
||||
placeholder={I18n.t('New_Message')}
|
||||
|
|
|
@ -11,18 +11,18 @@ import Title from './Title';
|
|||
import Subtitle from './Subtitle';
|
||||
import LockIcon from './LockIcon';
|
||||
|
||||
type TPasscodeTimer = {
|
||||
interface IPasscodeTimer {
|
||||
time: string;
|
||||
theme: string;
|
||||
setStatus: Function;
|
||||
};
|
||||
}
|
||||
|
||||
interface IPasscodeLocked {
|
||||
theme: string;
|
||||
setStatus: Function;
|
||||
}
|
||||
|
||||
const Timer = React.memo(({ time, theme, setStatus }: TPasscodeTimer) => {
|
||||
const Timer = React.memo(({ time, theme, setStatus }: IPasscodeTimer) => {
|
||||
const calcTimeLeft = () => {
|
||||
const diff = getDiff(time);
|
||||
if (diff > 0) {
|
||||
|
@ -62,6 +62,8 @@ const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
//TODO - verify if this 'r' it's correct
|
||||
// @ts-ignore
|
||||
<Grid style={[styles.grid, { backgroundColor: themes[theme].passcodeBackground }]} r>
|
||||
<LockIcon theme={theme} />
|
||||
<Title text={I18n.t('Passcode_app_locked_title')} theme={theme} />
|
||||
|
|
|
@ -92,6 +92,7 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
|
|||
}
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Base
|
||||
ref={ref}
|
||||
theme={theme}
|
||||
|
|
|
@ -59,7 +59,7 @@ const styles = StyleSheet.create({
|
|||
const standardEmojiStyle = { fontSize: 20 };
|
||||
const customEmojiStyle = { width: 20, height: 20 };
|
||||
|
||||
type TItem = {
|
||||
interface IItem {
|
||||
item: {
|
||||
usernames: any;
|
||||
emoji: string;
|
||||
|
@ -68,15 +68,15 @@ type TItem = {
|
|||
baseUrl?: string;
|
||||
getCustomEmoji?: Function;
|
||||
theme?: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TModalContent = {
|
||||
interface IModalContent {
|
||||
message: {
|
||||
reactions: any
|
||||
};
|
||||
onClose: Function;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IReactionsModal {
|
||||
isVisible: boolean;
|
||||
|
@ -84,7 +84,7 @@ interface IReactionsModal {
|
|||
theme: string;
|
||||
}
|
||||
|
||||
const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: TItem) => {
|
||||
const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: IItem) => {
|
||||
const count = item.usernames.length;
|
||||
let usernames = item.usernames.slice(0, 3)
|
||||
.map((username: any) => (username === user?.username ? I18n.t('you') : username)).join(', ');
|
||||
|
@ -114,7 +114,7 @@ const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: TItem)
|
|||
);
|
||||
});
|
||||
|
||||
const ModalContent = React.memo(({ message, onClose, ...props }: TModalContent) => {
|
||||
const ModalContent = React.memo(({ message, onClose, ...props }: IModalContent) => {
|
||||
if (message && message.reactions) {
|
||||
return (
|
||||
<SafeAreaView style={styles.safeArea}>
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ThemeContext } from '../../theme';
|
|||
const stories = storiesOf('RoomHeader', module);
|
||||
|
||||
// TODO: refactor after react-navigation v6
|
||||
const HeaderExample = ({ title }: any) => (
|
||||
const HeaderExample = ({ title }) => (
|
||||
<Header
|
||||
headerTitle={() => (
|
||||
<View style={{ flex: 1, paddingHorizontal: 12 }}>
|
||||
|
@ -77,7 +77,7 @@ stories.add('thread', () => (
|
|||
</>
|
||||
));
|
||||
|
||||
const ThemeStory = ({ theme }: any) => (
|
||||
const ThemeStory = ({ theme }) => (
|
||||
<ThemeContext.Provider
|
||||
value={{ theme }}
|
||||
>
|
|
@ -141,7 +141,7 @@ const HeaderTitle = React.memo(({ title, tmid, prid, scale, theme, testID }: TRo
|
|||
});
|
||||
|
||||
const Header = React.memo(({
|
||||
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID
|
||||
title, subtitle, parentTitle, type, status, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID, usersTyping = []
|
||||
}: IRoomHeader) => {
|
||||
const portrait = height > width;
|
||||
let scale = 1;
|
||||
|
|
|
@ -22,7 +22,7 @@ interface IRoomTypeIcon {
|
|||
}
|
||||
|
||||
const RoomTypeIcon = React.memo(({
|
||||
type, size, isGroupChat, status, style, theme, teamMain
|
||||
type, isGroupChat, status, style, theme, teamMain, size = 16
|
||||
}: IRoomTypeIcon) => {
|
||||
if (!type) {
|
||||
return null;
|
||||
|
|
|
@ -8,7 +8,7 @@ interface IStatus {
|
|||
style: any;
|
||||
}
|
||||
|
||||
const Status = React.memo(({ status, size, style, ...props }: IStatus) => {
|
||||
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
|
||||
const name = `status-${ status }`;
|
||||
const isNameValid = CustomIcon.hasIcon(name);
|
||||
const iconName = isNameValid ? name : 'status-offline';
|
||||
|
|
|
@ -72,6 +72,11 @@ interface IRCTextInputProps {
|
|||
|
||||
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, any> {
|
||||
|
||||
static defaultProps = {
|
||||
error: {},
|
||||
theme: 'light'
|
||||
}
|
||||
|
||||
state = {
|
||||
showPassword: false
|
||||
}
|
||||
|
@ -167,6 +172,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
|
|||
inputStyle
|
||||
]}
|
||||
ref={inputRef}
|
||||
/*@ts-ignore*/
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
underlineColorAndroid='transparent'
|
||||
|
|
|
@ -43,7 +43,7 @@ const methods: any = {
|
|||
const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [data, setData] = useState<any>({});
|
||||
const [code, setCode] = useState('');
|
||||
const [code, setCode] = useState<any>('');
|
||||
|
||||
const method = methods[data.method];
|
||||
const isEmail = data.method === 'email';
|
||||
|
@ -102,6 +102,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
|||
<Text style={[styles.title, { color }]}>{I18n.t(method?.title || 'Two_Factor_Authentication')}</Text>
|
||||
{method?.text ? <Text style={[styles.subtitle, { color }]}>{I18n.t(method.text)}</Text> : null}
|
||||
<TextInput
|
||||
/*@ts-ignore*/
|
||||
value={code}
|
||||
theme={theme}
|
||||
inputRef={(e: any) => InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}
|
||||
|
|
|
@ -15,19 +15,19 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TThumb = {
|
||||
interface IThumb {
|
||||
element: {
|
||||
imageUrl: string;
|
||||
};
|
||||
size?: number;
|
||||
};
|
||||
}
|
||||
|
||||
type TMedia = {
|
||||
interface IMedia {
|
||||
element: {
|
||||
imageUrl: string;
|
||||
};
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IImage {
|
||||
element: any;
|
||||
|
@ -37,14 +37,14 @@ interface IImage {
|
|||
|
||||
const ThumbContext = (args: any) => <View style={styles.mediaContext}><Thumb size={20} {...args} /></View>;
|
||||
|
||||
export const Thumb = ({ element, size = 88 }: TThumb) => (
|
||||
export const Thumb = ({ element, size = 88 }: IThumb) => (
|
||||
<FastImage
|
||||
style={[{ width: size, height: size }, styles.image]}
|
||||
source={{ uri: element.imageUrl }}
|
||||
/>
|
||||
);
|
||||
|
||||
export const Media = ({ element, theme }: TMedia) => {
|
||||
export const Media = ({ element, theme }: IMedia) => {
|
||||
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment });
|
||||
const { imageUrl } = element;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { CustomIcon } from '../../../lib/Icons';
|
|||
|
||||
import styles from './styles';
|
||||
|
||||
type TChip = {
|
||||
interface IChip {
|
||||
item: {
|
||||
value: string;
|
||||
imageUrl: string;
|
||||
|
@ -30,7 +30,7 @@ interface IChips {
|
|||
|
||||
const keyExtractor = (item: any) => item.value.toString();
|
||||
|
||||
const Chip = ({ item, onSelect, style, theme }: TChip) => (
|
||||
const Chip = ({ item, onSelect, style, theme }: IChip) => (
|
||||
<Touchable
|
||||
key={item.value}
|
||||
onPress={() => onSelect(item)}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { themes } from '../../../constants/colors';
|
|||
|
||||
import styles from './styles';
|
||||
|
||||
type TItem = {
|
||||
interface IItem {
|
||||
item: {
|
||||
value: { name: string; };
|
||||
text: { text: string; };
|
||||
|
@ -19,7 +19,7 @@ type TItem = {
|
|||
selected: any;
|
||||
onSelect: Function;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IItems {
|
||||
items: [];
|
||||
|
@ -31,7 +31,7 @@ interface IItems {
|
|||
const keyExtractor = (item: any) => item.value.toString();
|
||||
|
||||
// RectButton doesn't work on modal (Android)
|
||||
const Item = ({ item, selected, onSelect, theme }: TItem) => {
|
||||
const Item = ({ item, selected, onSelect, theme }: IItem) => {
|
||||
const itemName = item.value.name || item.text.text.toLowerCase();
|
||||
return (
|
||||
<Touchable
|
||||
|
|
|
@ -54,7 +54,7 @@ export const MultiSelect = React.memo(({
|
|||
value: values,
|
||||
multiselect = false,
|
||||
onSearch,
|
||||
onClose,
|
||||
onClose = () => {},
|
||||
disabled,
|
||||
inputStyle,
|
||||
theme
|
||||
|
@ -129,6 +129,7 @@ export const MultiSelect = React.memo(({
|
|||
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<TextInput
|
||||
testID='multi-select-search'
|
||||
/*@ts-ignore*/
|
||||
onChangeText={onSearch || onSearchChange}
|
||||
placeholder={I18n.t('Search')}
|
||||
theme={theme}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { StyleSheet } from 'react-native';
|
|||
|
||||
import sharedStyles from '../../../views/Styles';
|
||||
|
||||
export default StyleSheet.create({
|
||||
export default StyleSheet.create<any>({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
|
|
|
@ -9,7 +9,7 @@ import { themes } from '../../constants/colors';
|
|||
import { BUTTON_HIT_SLOP } from '../message/utils';
|
||||
import * as List from '../List';
|
||||
|
||||
type TOption = {
|
||||
interface IOption {
|
||||
option: {
|
||||
text: string;
|
||||
value: string;
|
||||
|
@ -17,14 +17,14 @@ type TOption = {
|
|||
onOptionPress: Function;
|
||||
parser: any;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TOptions = {
|
||||
interface IOptions {
|
||||
options: [];
|
||||
onOptionPress: Function;
|
||||
parser: object;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IOverflow {
|
||||
element: any;
|
||||
|
@ -50,7 +50,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOption) => (
|
||||
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: IOption) => (
|
||||
<Touchable
|
||||
onPress={() => onOptionPress({ value })}
|
||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
||||
|
@ -60,7 +60,7 @@ const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOpti
|
|||
</Touchable>
|
||||
);
|
||||
|
||||
const Options = ({ options, onOptionPress, parser, theme }: TOptions) => (
|
||||
const Options = ({ options, onOptionPress, parser, theme }: IOptions) => (
|
||||
<FlatList
|
||||
data={options}
|
||||
renderItem={({ item }) => <Option option={item} onOptionPress={onOptionPress} parser={parser} theme={theme} />}
|
||||
|
|
|
@ -23,14 +23,14 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TAccessory = {
|
||||
interface IAccessory {
|
||||
blockId?: string;
|
||||
appId?: string;
|
||||
element: any;
|
||||
parser: any
|
||||
}
|
||||
|
||||
type TFields = {
|
||||
interface IFields {
|
||||
fields: any;
|
||||
parser: any;
|
||||
theme: string;
|
||||
|
@ -46,13 +46,13 @@ interface ISection {
|
|||
parser: any;
|
||||
}
|
||||
|
||||
const Accessory = ({ blockId, appId, element, parser }: TAccessory) => parser.renderAccessories(
|
||||
const Accessory = ({ blockId, appId, element, parser }: IAccessory) => parser.renderAccessories(
|
||||
{ blockId, appId, ...element },
|
||||
BLOCK_CONTEXT.SECTION,
|
||||
parser
|
||||
);
|
||||
|
||||
const Fields = ({ fields, parser, theme }: TFields) => fields.map((field: any) => (
|
||||
const Fields = ({ fields, parser, theme }: IFields) => fields.map((field: any) => (
|
||||
<Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>
|
||||
{parser.text(field)}
|
||||
</Text>
|
||||
|
|
|
@ -225,6 +225,7 @@ class ModalParser extends UiKitParserModal {
|
|||
const { theme } = useContext(ThemeContext);
|
||||
const { multiline, actionId, placeholder } = element;
|
||||
return (
|
||||
// @ts-ignore
|
||||
<TextInput
|
||||
id={actionId}
|
||||
placeholder={plainText(placeholder)}
|
||||
|
@ -235,6 +236,7 @@ class ModalParser extends UiKitParserModal {
|
|||
inputStyle={multiline && styles.multiline}
|
||||
containerStyle={styles.input}
|
||||
value={value}
|
||||
// @ts-ignore
|
||||
error={{ error }}
|
||||
theme={theme}
|
||||
/>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { themes } from '../../constants/colors';
|
|||
|
||||
import styles from './styles';
|
||||
|
||||
export interface IEmoji {
|
||||
interface IEmoji {
|
||||
literal: string;
|
||||
isMessageContainsOnlyEmoji: boolean;
|
||||
getCustomEmoji?: Function;
|
||||
|
|
|
@ -5,17 +5,15 @@ import { themes } from '../../constants/colors';
|
|||
|
||||
import styles from './styles';
|
||||
|
||||
export type TChannel = {
|
||||
name: string;
|
||||
_id: number;
|
||||
}
|
||||
|
||||
interface IHashtag {
|
||||
hashtag: string;
|
||||
navToRoomInfo: Function;
|
||||
style: [];
|
||||
theme: string;
|
||||
channels: TChannel[];
|
||||
channels: {
|
||||
name: string;
|
||||
_id: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [], theme }: IHashtag) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ interface IList {
|
|||
numberOfLines: number;
|
||||
}
|
||||
|
||||
const List = React.memo(({ children, ordered, start = 1, tight, numberOfLines = 0 }: IList) => {
|
||||
const List = React.memo(({ children, ordered, tight, start = 1, numberOfLines = 0 }: IList) => {
|
||||
let bulletWidth = 15;
|
||||
|
||||
if (ordered) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import MarkdownLink from './Link';
|
|||
import MarkdownList from './List';
|
||||
import MarkdownListItem from './ListItem';
|
||||
import MarkdownAtMention from './AtMention';
|
||||
import MarkdownHashtag, {TChannel} from './Hashtag';
|
||||
import MarkdownHashtag from './Hashtag';
|
||||
import MarkdownBlockQuote from './BlockQuote';
|
||||
import MarkdownEmoji from './Emoji';
|
||||
import MarkdownTable from './Table';
|
||||
|
@ -33,7 +33,10 @@ interface IMarkdownProps {
|
|||
numberOfLines: number;
|
||||
customEmojis: boolean;
|
||||
useRealName: boolean;
|
||||
channels: TChannel[];
|
||||
channels: {
|
||||
name: string;
|
||||
_id: number;
|
||||
}[];
|
||||
mentions: object[];
|
||||
navToRoomInfo: Function;
|
||||
preview: boolean;
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
import React from 'react';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
import {IMessageAttachments} from "./interfaces";
|
||||
|
||||
import Image from './Image';
|
||||
import Audio from './Audio';
|
||||
import Video from './Video';
|
||||
import Reply from './Reply';
|
||||
|
||||
export interface IMessageAttachments {
|
||||
attachments: any;
|
||||
timeFormat: string;
|
||||
showAttachment: Function;
|
||||
getCustomEmoji: Function;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Attachments = React.memo(({
|
||||
attachments, timeFormat, showAttachment, getCustomEmoji, theme
|
||||
}: IMessageAttachments) => {
|
||||
|
|
|
@ -16,12 +16,12 @@ import MessageContext from './Context';
|
|||
import ActivityIndicator from '../ActivityIndicator';
|
||||
import { withDimensions } from '../../dimensions';
|
||||
|
||||
type TButton = {
|
||||
interface IButton {
|
||||
loading: boolean;
|
||||
paused: boolean;
|
||||
theme: string;
|
||||
onPress: Function;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMessageAudioProps {
|
||||
file: {
|
||||
|
@ -88,7 +88,7 @@ const sliderAnimationConfig = {
|
|||
delay: 0
|
||||
};
|
||||
|
||||
const Button = React.memo(({ loading, paused, onPress, theme }: TButton) => (
|
||||
const Button = React.memo(({ loading, paused, onPress, theme }: IButton) => (
|
||||
<Touchable
|
||||
style={styles.playPauseButton}
|
||||
onPress={onPress}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
import React from 'react';
|
||||
import { messageBlockWithContext } from '../UIKit/MessageBlock';
|
||||
|
||||
export interface IMessageBlocks {
|
||||
blocks: any;
|
||||
id: string;
|
||||
rid: string;
|
||||
blockAction: Function;
|
||||
}
|
||||
import {IMessageBlocks} from "./interfaces";
|
||||
|
||||
const Blocks = React.memo(({ blocks, id: mid, rid, blockAction }: IMessageBlocks) => {
|
||||
if (blocks && blocks.length > 0) {
|
||||
|
|
|
@ -8,14 +8,7 @@ import { BUTTON_HIT_SLOP } from './utils';
|
|||
import I18n from '../../i18n';
|
||||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
|
||||
export interface IMessageBroadcast {
|
||||
author: {
|
||||
_id: string
|
||||
};
|
||||
broadcast: boolean;
|
||||
theme: string
|
||||
}
|
||||
import {IMessageBroadcast} from "./interfaces";
|
||||
|
||||
const Broadcast = React.memo(({ author, broadcast, theme }: IMessageBroadcast) => {
|
||||
const { user, replyBroadcast } = useContext(MessageContext);
|
||||
|
|
|
@ -7,11 +7,7 @@ import styles from './styles';
|
|||
import I18n from '../../i18n';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
export interface IMessageCallButton {
|
||||
theme: string;
|
||||
callJitsi: Function;
|
||||
}
|
||||
import {IMessageCallButton} from "./interfaces";
|
||||
|
||||
const CallButton = React.memo(({ theme, callJitsi }: IMessageCallButton) => (
|
||||
<View style={styles.buttonContainer}>
|
||||
|
|
|
@ -11,25 +11,7 @@ import { themes } from '../../constants/colors';
|
|||
import MessageContext from './Context';
|
||||
import Encrypted from './Encrypted';
|
||||
import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants';
|
||||
import {TChannel} from "../markdown/Hashtag";
|
||||
|
||||
export interface IMessageContent {
|
||||
isTemp: boolean;
|
||||
isInfo: boolean;
|
||||
tmid: string;
|
||||
isThreadRoom: boolean;
|
||||
msg: string;
|
||||
theme: string;
|
||||
isEdited: boolean;
|
||||
isEncrypted: boolean;
|
||||
getCustomEmoji: Function;
|
||||
channels: TChannel[];
|
||||
mentions: object[];
|
||||
navToRoomInfo: Function;
|
||||
useRealName: boolean;
|
||||
isIgnored: boolean;
|
||||
type: string;
|
||||
}
|
||||
import {IMessageContent} from "./interfaces";
|
||||
|
||||
const Content = React.memo((props: IMessageContent) => {
|
||||
if (props.isInfo) {
|
||||
|
|
|
@ -10,13 +10,8 @@ import { DISCUSSION } from './constants';
|
|||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
import { formatDateThreads } from '../../utils/room';
|
||||
import {IMessageDiscussion} from "./interfaces";
|
||||
|
||||
export interface IMessageDiscussion {
|
||||
msg: string;
|
||||
dcount: number;
|
||||
dlm: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Discussion = React.memo(({ msg, dcount, dlm, theme }: IMessageDiscussion) => {
|
||||
let time;
|
||||
|
|
|
@ -3,14 +3,7 @@ import { Text } from 'react-native';
|
|||
|
||||
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||
import CustomEmoji from '../EmojiPicker/CustomEmoji';
|
||||
|
||||
interface IMessageEmoji {
|
||||
content: any;
|
||||
baseUrl: string;
|
||||
standardEmojiStyle: object;
|
||||
customEmojiStyle: object;
|
||||
getCustomEmoji: Function;
|
||||
}
|
||||
import {IMessageEmoji} from "./interfaces";
|
||||
|
||||
const Emoji = React.memo(({ content, baseUrl, standardEmojiStyle, customEmojiStyle, getCustomEmoji }: IMessageEmoji) => {
|
||||
const parsedContent = content.replace(/^:|:$/g, '');
|
||||
|
|
|
@ -69,7 +69,6 @@ const ImageContainer = React.memo(({file, imageUrl, showAttachment, getCustomEmo
|
|||
<Button theme={theme} onPress={onPress}>
|
||||
<View>
|
||||
<MessageImage img={img} theme={theme} />
|
||||
//TODO - fix the required fields for the Markdown
|
||||
{/*@ts-ignore*/}
|
||||
<Markdown msg={file.description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||
</View>
|
||||
|
|
|
@ -6,59 +6,22 @@ import MessageContext from './Context';
|
|||
|
||||
import User from './User';
|
||||
import styles from './styles';
|
||||
import RepliedThread, {IMessageRepliedThread} from './RepliedThread';
|
||||
import MessageAvatar, {IMessageAvatar} from './MessageAvatar';
|
||||
import Attachments, {IMessageAttachments} from './Attachments';
|
||||
import RepliedThread from './RepliedThread';
|
||||
import MessageAvatar from './MessageAvatar';
|
||||
import Attachments from './Attachments';
|
||||
import Urls from './Urls';
|
||||
import Thread, {IMessageThread} from './Thread';
|
||||
import Blocks, {IMessageBlocks} from './Blocks';
|
||||
import Thread from './Thread';
|
||||
import Blocks from './Blocks';
|
||||
import Reactions from './Reactions';
|
||||
import Broadcast, {IMessageBroadcast} from './Broadcast';
|
||||
import Discussion, {IMessageDiscussion} from './Discussion';
|
||||
import Content, {IMessageContent} from './Content';
|
||||
import Broadcast from './Broadcast';
|
||||
import Discussion from './Discussion';
|
||||
import Content from './Content';
|
||||
import ReadReceipt from './ReadReceipt';
|
||||
import CallButton, {IMessageCallButton} from './CallButton';
|
||||
import CallButton from './CallButton';
|
||||
import { themes } from '../../constants/colors';
|
||||
import {IMessage, IMessageInner, IMessageTouchable} from "./interfaces";
|
||||
|
||||
|
||||
type TMessageInner = {
|
||||
type: string;
|
||||
blocks: [];
|
||||
} & IMessageDiscussion & IMessageContent & IMessageCallButton & IMessageBlocks
|
||||
& IMessageThread & IMessageAttachments & IMessageBroadcast;
|
||||
|
||||
type TMessage = {
|
||||
isThreadReply: boolean;
|
||||
isThreadSequential: boolean;
|
||||
isInfo: boolean;
|
||||
isTemp: boolean;
|
||||
isHeader: boolean;
|
||||
hasError: boolean;
|
||||
style: any;
|
||||
onLongPress: Function;
|
||||
isReadReceiptEnabled: boolean;
|
||||
unread: boolean;
|
||||
theme: string;
|
||||
isIgnored: boolean;
|
||||
} & IMessageRepliedThread & IMessageAvatar & IMessageContent & TMessageInner;
|
||||
|
||||
interface IMessageTouchable {
|
||||
hasError: boolean;
|
||||
isInfo: boolean;
|
||||
isThreadReply: boolean;
|
||||
isTemp: boolean;
|
||||
archived: boolean;
|
||||
highlighted: boolean;
|
||||
theme: string;
|
||||
ts?: any
|
||||
urls?: any;
|
||||
reactions?: any;
|
||||
alias?: any;
|
||||
role?: any;
|
||||
drid?: any;
|
||||
}
|
||||
|
||||
const MessageInner = React.memo((props: TMessageInner) => {
|
||||
const MessageInner = React.memo((props: IMessageInner) => {
|
||||
if (props.type === 'discussion-created') {
|
||||
return (
|
||||
<>
|
||||
|
@ -100,7 +63,7 @@ const MessageInner = React.memo((props: TMessageInner) => {
|
|||
});
|
||||
MessageInner.displayName = 'MessageInner';
|
||||
|
||||
const Message = React.memo((props: TMessage) => {
|
||||
const Message = React.memo((props: IMessage) => {
|
||||
if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) {
|
||||
const thread = props.isThreadReply ? <RepliedThread {...props} /> : null;
|
||||
return (
|
||||
|
@ -144,7 +107,7 @@ const Message = React.memo((props: TMessage) => {
|
|||
});
|
||||
Message.displayName = 'Message';
|
||||
|
||||
const MessageTouchable = React.memo((props: IMessageTouchable & TMessage) => {
|
||||
const MessageTouchable = React.memo((props: IMessageTouchable & IMessage) => {
|
||||
if (props.hasError) {
|
||||
return (
|
||||
<View>
|
||||
|
|
|
@ -3,20 +3,7 @@ import React, { useContext } from 'react';
|
|||
import Avatar from '../Avatar';
|
||||
import styles from './styles';
|
||||
import MessageContext from './Context';
|
||||
|
||||
export interface IMessageAvatar {
|
||||
isHeader: boolean;
|
||||
avatar: string;
|
||||
emoji: string;
|
||||
author: {
|
||||
username: string
|
||||
_id: string;
|
||||
};
|
||||
small?: boolean;
|
||||
navToRoomInfo: Function;
|
||||
getCustomEmoji(): void;
|
||||
theme: string;
|
||||
}
|
||||
import {IMessageAvatar} from "./interfaces";
|
||||
|
||||
const MessageAvatar = React.memo(({
|
||||
isHeader, avatar, author, small, navToRoomInfo, emoji, getCustomEmoji, theme
|
||||
|
|
|
@ -10,18 +10,18 @@ import { themes } from '../../constants/colors';
|
|||
import { withTheme } from '../../theme';
|
||||
import MessageContext from './Context';
|
||||
|
||||
type TMessageAddReaction = {
|
||||
interface IMessageAddReaction {
|
||||
theme: string
|
||||
};
|
||||
}
|
||||
|
||||
type TMessageReaction = {
|
||||
interface IMessageReaction {
|
||||
reaction: {
|
||||
usernames: [];
|
||||
emoji: object;
|
||||
};
|
||||
getCustomEmoji: Function;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMessageReactions {
|
||||
reactions: object[];
|
||||
|
@ -29,7 +29,7 @@ interface IMessageReactions {
|
|||
theme: string;
|
||||
}
|
||||
|
||||
const AddReaction = React.memo(({ theme }: TMessageAddReaction) => {
|
||||
const AddReaction = React.memo(({ theme }: IMessageAddReaction) => {
|
||||
const { reactionInit } = useContext(MessageContext);
|
||||
return (
|
||||
<Touchable
|
||||
|
@ -47,9 +47,9 @@ const AddReaction = React.memo(({ theme }: TMessageAddReaction) => {
|
|||
);
|
||||
});
|
||||
|
||||
const Reaction = React.memo(({reaction, getCustomEmoji, theme}: TMessageReaction) => {
|
||||
const Reaction = React.memo(({reaction, getCustomEmoji, theme}: IMessageReaction) => {
|
||||
const { onReactionPress, onReactionLongPress, baseUrl, user } = useContext(MessageContext);
|
||||
const reacted = reaction.usernames.findIndex((item: TMessageReaction) => item === user.username) !== -1;
|
||||
const reacted = reaction.usernames.findIndex((item: IMessageReaction) => item === user.username) !== -1;
|
||||
return (
|
||||
<Touchable
|
||||
onPress={() => onReactionPress(reaction.emoji)}
|
||||
|
|
|
@ -6,16 +6,7 @@ import styles from './styles';
|
|||
import { themes } from '../../constants/colors';
|
||||
import I18n from '../../i18n';
|
||||
import Markdown from '../markdown';
|
||||
|
||||
export interface IMessageRepliedThread {
|
||||
tmid: string;
|
||||
tmsg: string;
|
||||
id: string;
|
||||
isHeader: boolean;
|
||||
theme: string;
|
||||
fetchThreadName: Function;
|
||||
isEncrypted: boolean;
|
||||
}
|
||||
import {IMessageRepliedThread} from "./interfaces";
|
||||
|
||||
const RepliedThread = memo(({
|
||||
tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted, theme
|
||||
|
|
|
@ -68,7 +68,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TAttachment = {
|
||||
interface IMessageReplyAttachment {
|
||||
author_name: string;
|
||||
message_link: string;
|
||||
ts: string;
|
||||
|
@ -81,36 +81,36 @@ type TAttachment = {
|
|||
type: string;
|
||||
color: string;
|
||||
description: string;
|
||||
fields: TAttachment[];
|
||||
fields: IMessageReplyAttachment[];
|
||||
}
|
||||
|
||||
type TMessageTitle = {
|
||||
attachment: Partial<TAttachment>
|
||||
interface IMessageTitle {
|
||||
attachment: Partial<IMessageReplyAttachment>
|
||||
timeFormat: string;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TMessageDescription = {
|
||||
attachment: Partial<TAttachment>
|
||||
interface IMessageDescription {
|
||||
attachment: Partial<IMessageReplyAttachment>
|
||||
getCustomEmoji: Function;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TMessageFields = {
|
||||
attachment: Partial<TAttachment>;
|
||||
interface IMessageFields {
|
||||
attachment: Partial<IMessageReplyAttachment>;
|
||||
theme: string;
|
||||
getCustomEmoji: Function;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMessageReply {
|
||||
attachment: Partial<TAttachment>
|
||||
attachment: Partial<IMessageReplyAttachment>
|
||||
timeFormat: string;
|
||||
index: number;
|
||||
theme: string;
|
||||
getCustomEmoji: Function;
|
||||
}
|
||||
|
||||
const Title = React.memo(({ attachment, timeFormat, theme }: TMessageTitle) => {
|
||||
const Title = React.memo(({ attachment, timeFormat, theme }: IMessageTitle) => {
|
||||
if (!attachment.author_name) {
|
||||
return null;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ const Title = React.memo(({ attachment, timeFormat, theme }: TMessageTitle) => {
|
|||
);
|
||||
});
|
||||
|
||||
const Description = React.memo(({ attachment, getCustomEmoji, theme }: TMessageDescription) => {
|
||||
const Description = React.memo(({ attachment, getCustomEmoji, theme }: IMessageDescription) => {
|
||||
const text = attachment.text || attachment.title;
|
||||
if (!text) {
|
||||
return null;
|
||||
|
@ -152,7 +152,7 @@ const Description = React.memo(({ attachment, getCustomEmoji, theme }: TMessageD
|
|||
return true;
|
||||
});
|
||||
|
||||
const Fields = React.memo(({ attachment, theme, getCustomEmoji }: TMessageFields) => {
|
||||
const Fields = React.memo(({ attachment, theme, getCustomEmoji }: IMessageFields) => {
|
||||
if (!attachment.fields) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -6,15 +6,7 @@ import { themes } from '../../constants/colors';
|
|||
import MessageContext from './Context';
|
||||
import ThreadDetails from '../ThreadDetails';
|
||||
import I18n from '../../i18n';
|
||||
|
||||
export interface IMessageThread {
|
||||
msg: string;
|
||||
tcount: number;
|
||||
theme: string;
|
||||
tlm: string;
|
||||
isThreadRoom: boolean;
|
||||
id: string;
|
||||
}
|
||||
import {IMessageThread} from "./interfaces";
|
||||
|
||||
const Thread = React.memo(({ msg, tcount, tlm, isThreadRoom, theme, id }: IMessageThread) => {
|
||||
if (!tlm || isThreadRoom || tcount === 0) {
|
||||
|
|
|
@ -49,13 +49,13 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
type TMessageUrlContent = {
|
||||
interface IMessageUrlContent {
|
||||
title: string;
|
||||
description: string;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TMessageUrl = {
|
||||
interface IMessageUrl {
|
||||
url: {
|
||||
ignoreParse: boolean;
|
||||
url: string;
|
||||
|
@ -65,7 +65,7 @@ type TMessageUrl = {
|
|||
};
|
||||
index: number;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMessageUrls {
|
||||
urls: any;
|
||||
|
@ -81,7 +81,7 @@ const UrlImage = React.memo(({ image }: {image: string}) => {
|
|||
return <FastImage source={{ uri: image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />;
|
||||
}, (prevProps, nextProps) => prevProps.image === nextProps.image);
|
||||
|
||||
const UrlContent = React.memo(({ title, description, theme }: TMessageUrlContent) => (
|
||||
const UrlContent = React.memo(({ title, description, theme }: IMessageUrlContent) => (
|
||||
<View style={styles.textContainer}>
|
||||
{title ? <Text style={[styles.title, { color: themes[theme].tintColor }]} numberOfLines={2}>{title}</Text> : null}
|
||||
{description ? <Text style={[styles.description, { color: themes[theme].auxiliaryText }]} numberOfLines={2}>{description}</Text> : null}
|
||||
|
@ -99,7 +99,7 @@ const UrlContent = React.memo(({ title, description, theme }: TMessageUrlContent
|
|||
return true;
|
||||
});
|
||||
|
||||
const Url = React.memo(({ url, index, theme }: TMessageUrl) => {
|
||||
const Url = React.memo(({ url, index, theme }: IMessageUrl) => {
|
||||
if (!url || url?.ignoreParse) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,28 @@ interface IMessageContainerProps {
|
|||
|
||||
class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
||||
|
||||
static defaultProps = {
|
||||
getCustomEmoji: () => {},
|
||||
onLongPress: () => {},
|
||||
onReactionPress: () => {},
|
||||
onEncryptedPress: () => {},
|
||||
onDiscussionPress: () => {},
|
||||
onThreadPress: () => {},
|
||||
errorActionsShow: () => {},
|
||||
replyBroadcast: () => {},
|
||||
reactionInit: () => {},
|
||||
fetchThreadName: () => {},
|
||||
showAttachment: () => {},
|
||||
onReactionLongPress: () => {},
|
||||
navToRoomInfo: () => {},
|
||||
callJitsi: () => {},
|
||||
blockAction: () => {},
|
||||
archived: false,
|
||||
broadcast: false,
|
||||
isIgnored: false,
|
||||
theme: 'light'
|
||||
}
|
||||
|
||||
state = { isManualUnignored: false };
|
||||
private subscription: any;
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
export interface IMessageAttachments {
|
||||
attachments: any;
|
||||
timeFormat: string;
|
||||
showAttachment: Function;
|
||||
getCustomEmoji: Function;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export interface IMessageAvatar {
|
||||
isHeader: boolean;
|
||||
avatar: string;
|
||||
emoji: string;
|
||||
author: {
|
||||
username: string
|
||||
_id: string;
|
||||
};
|
||||
small?: boolean;
|
||||
navToRoomInfo: Function;
|
||||
getCustomEmoji(): void;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export interface IMessageBlocks {
|
||||
blocks: any;
|
||||
id: string;
|
||||
rid: string;
|
||||
blockAction: Function;
|
||||
}
|
||||
|
||||
export interface IMessageBroadcast {
|
||||
author: {
|
||||
_id: string
|
||||
};
|
||||
broadcast: boolean;
|
||||
theme: string
|
||||
}
|
||||
|
||||
export interface IMessageCallButton {
|
||||
theme: string;
|
||||
callJitsi: Function;
|
||||
}
|
||||
|
||||
export interface IMessageContent {
|
||||
isTemp: boolean;
|
||||
isInfo: boolean;
|
||||
tmid: string;
|
||||
isThreadRoom: boolean;
|
||||
msg: string;
|
||||
theme: string;
|
||||
isEdited: boolean;
|
||||
isEncrypted: boolean;
|
||||
getCustomEmoji: Function;
|
||||
channels: {
|
||||
name: string;
|
||||
_id: number;
|
||||
}[];
|
||||
mentions: object[];
|
||||
navToRoomInfo: Function;
|
||||
useRealName: boolean;
|
||||
isIgnored: boolean;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface IMessageDiscussion {
|
||||
msg: string;
|
||||
dcount: number;
|
||||
dlm: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export interface IMessageEmoji {
|
||||
content: any;
|
||||
baseUrl: string;
|
||||
standardEmojiStyle: object;
|
||||
customEmojiStyle: object;
|
||||
getCustomEmoji: Function;
|
||||
}
|
||||
|
||||
export interface IMessageThread {
|
||||
msg: string;
|
||||
tcount: number;
|
||||
theme: string;
|
||||
tlm: string;
|
||||
isThreadRoom: boolean;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IMessageTouchable {
|
||||
hasError: boolean;
|
||||
isInfo: boolean;
|
||||
isThreadReply: boolean;
|
||||
isTemp: boolean;
|
||||
archived: boolean;
|
||||
highlighted: boolean;
|
||||
theme: string;
|
||||
ts?: any
|
||||
urls?: any;
|
||||
reactions?: any;
|
||||
alias?: any;
|
||||
role?: any;
|
||||
drid?: any;
|
||||
}
|
||||
|
||||
export interface IMessageRepliedThread {
|
||||
tmid: string;
|
||||
tmsg: string;
|
||||
id: string;
|
||||
isHeader: boolean;
|
||||
theme: string;
|
||||
fetchThreadName: Function;
|
||||
isEncrypted: boolean;
|
||||
}
|
||||
|
||||
export interface IMessageInner extends IMessageDiscussion, IMessageContent, IMessageCallButton, IMessageBlocks,
|
||||
IMessageThread, IMessageAttachments, IMessageBroadcast {
|
||||
type: string;
|
||||
blocks: [];
|
||||
}
|
||||
|
||||
export interface IMessage extends IMessageRepliedThread, IMessageInner {
|
||||
isThreadReply: boolean;
|
||||
isThreadSequential: boolean;
|
||||
isInfo: boolean;
|
||||
isTemp: boolean;
|
||||
isHeader: boolean;
|
||||
hasError: boolean;
|
||||
style: any;
|
||||
onLongPress: Function;
|
||||
isReadReceiptEnabled: boolean;
|
||||
unread: boolean;
|
||||
theme: string;
|
||||
isIgnored: boolean;
|
||||
}
|
|
@ -761,5 +761,12 @@
|
|||
"Move_to_Team_Warning": "Nachdem du die vorherigen Anleitungen zu diesem Verhalten gelesen hast, möchtest du diesen Kanal immer noch in das ausgewählte Team verschieben?",
|
||||
"Load_More": "Mehr laden",
|
||||
"Load_Newer": "Neuere laden",
|
||||
"Load_Older": "Ältere laden"
|
||||
"Load_Older": "Ältere laden",
|
||||
"Left_The_Room_Successfully": "Raum erfolgreich verlassen",
|
||||
"Deleted_The_Team_Successfully": "Team erfolgreich gelöscht",
|
||||
"Deleted_The_Room_Successfully": "Raum erfolgreich gelöscht",
|
||||
"Convert_to_Channel": "In Kanal umwandeln",
|
||||
"Converting_Team_To_Channel": "Team in Kanal umwandeln",
|
||||
"Select_Team_Channels_To_Delete": "Wähle die Kanäle des Teams aus, die du löschen möchtest. Die Kanäle, die du nicht auswählst, werden in den Arbeitsbereich verschoben \n\nBeachte, dass öffentliche Kanäle öffentlich und für alle sichtbar sind.",
|
||||
"You_are_converting_the_team": "Du wandelst dieses Team in einen Raum um"
|
||||
}
|
|
@ -761,5 +761,12 @@
|
|||
"Move_to_Team_Warning": "После прочтения предыдущих инструкций об этом поведении, вы все еще хотите переместить этот канал в выбранную Команду?",
|
||||
"Load_More": "Загрузить еще",
|
||||
"Load_Newer": "Загрузить более позднее",
|
||||
"Load_Older": "Загрузить более раннее"
|
||||
"Load_Older": "Загрузить более раннее",
|
||||
"Left_The_Room_Successfully": "Успешно покинул комнату",
|
||||
"Deleted_The_Team_Successfully": "Команда успешно удалена",
|
||||
"Deleted_The_Room_Successfully": "Комната успешно удалена",
|
||||
"Convert_to_Channel": "Преобразовать в канал",
|
||||
"Converting_Team_To_Channel": "Преобразование Команды в канал",
|
||||
"Select_Team_Channels_To_Delete": "Выберите каналы Команды, которые вы хотите удалить, те, которые вы не выбрали, будут перемещены в рабочую область \n\nОбратите внимание, что публичные каналы будут открытыми и видимыми для всех.",
|
||||
"You_are_converting_the_team": "Вы преобразуете эту Команду в канал"
|
||||
}
|
|
@ -33,12 +33,13 @@ import { isFDroidBuild } from './constants/environment';
|
|||
|
||||
RNScreens.enableScreens();
|
||||
|
||||
type TDimensions = {
|
||||
interface IDimensions {
|
||||
width: number,
|
||||
height: number,
|
||||
scale: number,
|
||||
fontScale: number
|
||||
}
|
||||
|
||||
interface IProps {}
|
||||
interface IState {
|
||||
theme: string,
|
||||
|
@ -163,7 +164,7 @@ export default class Root extends React.Component<IProps, IState> {
|
|||
window: {
|
||||
width, height, scale, fontScale
|
||||
}
|
||||
}: {window: TDimensions}) => {
|
||||
}: {window: IDimensions}) => {
|
||||
this.setDimensions({
|
||||
width, height, scale, fontScale
|
||||
});
|
||||
|
@ -179,7 +180,7 @@ export default class Root extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
setDimensions = ({width, height, scale, fontScale}: TDimensions) => {
|
||||
setDimensions = ({width, height, scale, fontScale}: IDimensions) => {
|
||||
this.setState({width, height, scale, fontScale});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Touch from '../../utils/touch';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
|
@ -10,7 +9,26 @@ import { themes } from '../../constants/colors';
|
|||
|
||||
export { ROW_HEIGHT };
|
||||
|
||||
const DirectoryItemLabel = React.memo(({ text, theme }) => {
|
||||
interface IDirectoryItemLabel {
|
||||
text: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IDirectoryItem {
|
||||
title: string;
|
||||
description: string;
|
||||
avatar: string;
|
||||
type: string;
|
||||
onPress(): void;
|
||||
testID: string;
|
||||
style: any;
|
||||
rightLabel: string;
|
||||
rid: string;
|
||||
theme: string;
|
||||
teamMain: boolean;
|
||||
}
|
||||
|
||||
const DirectoryItemLabel = React.memo(({ text, theme }: IDirectoryItemLabel) => {
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
|
@ -19,7 +37,7 @@ const DirectoryItemLabel = React.memo(({ text, theme }) => {
|
|||
|
||||
const DirectoryItem = ({
|
||||
title, description, avatar, onPress, testID, style, rightLabel, type, rid, theme, teamMain
|
||||
}) => (
|
||||
}: IDirectoryItem) => (
|
||||
<Touch
|
||||
onPress={onPress}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
|
@ -46,23 +64,4 @@ const DirectoryItem = ({
|
|||
</Touch>
|
||||
);
|
||||
|
||||
DirectoryItem.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
avatar: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
testID: PropTypes.string.isRequired,
|
||||
style: PropTypes.any,
|
||||
rightLabel: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
teamMain: PropTypes.bool
|
||||
};
|
||||
|
||||
DirectoryItemLabel.propTypes = {
|
||||
text: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default DirectoryItem;
|
|
@ -1,6 +1,6 @@
|
|||
import { types } from './types';
|
||||
|
||||
export const ImageComponent = (type) => {
|
||||
export const ImageComponent = (type: string) => {
|
||||
let Component;
|
||||
if (type === types.REACT_NATIVE_IMAGE) {
|
||||
const { Image } = require('react-native');
|
|
@ -1,11 +1,6 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
PanGestureHandler,
|
||||
State,
|
||||
PinchGestureHandler
|
||||
} from 'react-native-gesture-handler';
|
||||
import { PanGestureHandler, State, PinchGestureHandler } from 'react-native-gesture-handler';
|
||||
import Animated, { Easing } from 'react-native-reanimated';
|
||||
import { ImageComponent } from './ImageComponent';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
@ -44,13 +39,13 @@ const {
|
|||
event
|
||||
} = Animated;
|
||||
|
||||
function scaleDiff(value) {
|
||||
function scaleDiff(value: any) {
|
||||
const tmp = new Value(1);
|
||||
const prev = new Value(1);
|
||||
return [set(tmp, divide(value, prev)), set(prev, value), tmp];
|
||||
}
|
||||
|
||||
function dragDiff(value, updating) {
|
||||
function dragDiff(value: any, updating: any) {
|
||||
const tmp = new Value(0);
|
||||
const prev = new Value(0);
|
||||
return cond(
|
||||
|
@ -63,7 +58,7 @@ function dragDiff(value, updating) {
|
|||
// returns linear friction coeff. When `value` is 0 coeff is 1 (no friction), then
|
||||
// it grows linearly until it reaches `MAX_FRICTION` when `value` is equal
|
||||
// to `MAX_VALUE`
|
||||
function friction(value) {
|
||||
function friction(value: any) {
|
||||
const MAX_FRICTION = 5;
|
||||
const MAX_VALUE = 100;
|
||||
return max(
|
||||
|
@ -72,7 +67,7 @@ function friction(value) {
|
|||
);
|
||||
}
|
||||
|
||||
function speed(value) {
|
||||
function speed(value: any) {
|
||||
const clock = new Clock();
|
||||
const dt = diff(clock);
|
||||
return cond(lessThan(dt, 1), 0, multiply(1000, divide(diff(value), dt)));
|
||||
|
@ -81,7 +76,7 @@ function speed(value) {
|
|||
const MIN_SCALE = 1;
|
||||
const MAX_SCALE = 2;
|
||||
|
||||
function scaleRest(value) {
|
||||
function scaleRest(value: any) {
|
||||
return cond(
|
||||
lessThan(value, MIN_SCALE),
|
||||
MIN_SCALE,
|
||||
|
@ -89,7 +84,7 @@ function scaleRest(value) {
|
|||
);
|
||||
}
|
||||
|
||||
function scaleFriction(value, rest, delta) {
|
||||
function scaleFriction(value: any, rest: any, delta: any) {
|
||||
const MAX_FRICTION = 20;
|
||||
const MAX_VALUE = 0.5;
|
||||
const res = multiply(value, delta);
|
||||
|
@ -105,7 +100,7 @@ function scaleFriction(value, rest, delta) {
|
|||
);
|
||||
}
|
||||
|
||||
function runTiming(clock, value, dest, startStopClock = true) {
|
||||
function runTiming(clock: any, value: any, dest: any, startStopClock: any = true) {
|
||||
const state = {
|
||||
finished: new Value(0),
|
||||
position: new Value(0),
|
||||
|
@ -134,7 +129,7 @@ function runTiming(clock, value, dest, startStopClock = true) {
|
|||
];
|
||||
}
|
||||
|
||||
function runDecay(clock, value, velocity) {
|
||||
function runDecay(clock: any, value: any, velocity: any) {
|
||||
const state = {
|
||||
finished: new Value(0),
|
||||
velocity: new Value(0),
|
||||
|
@ -160,13 +155,13 @@ function runDecay(clock, value, velocity) {
|
|||
}
|
||||
|
||||
function bouncyPinch(
|
||||
value,
|
||||
gesture,
|
||||
gestureActive,
|
||||
focalX,
|
||||
displacementX,
|
||||
focalY,
|
||||
displacementY
|
||||
value: any,
|
||||
gesture: any,
|
||||
gestureActive: any,
|
||||
focalX: any,
|
||||
displacementX: any,
|
||||
focalY: any,
|
||||
displacementY: any
|
||||
) {
|
||||
const clock = new Clock();
|
||||
|
||||
|
@ -212,12 +207,12 @@ function bouncyPinch(
|
|||
}
|
||||
|
||||
function bouncy(
|
||||
value,
|
||||
gestureDiv,
|
||||
gestureActive,
|
||||
lowerBound,
|
||||
upperBound,
|
||||
f
|
||||
value: any,
|
||||
gestureDiv: any,
|
||||
gestureActive: any,
|
||||
lowerBound: any,
|
||||
upperBound: any,
|
||||
f: any
|
||||
) {
|
||||
const timingClock = new Clock();
|
||||
const decayClock = new Clock();
|
||||
|
@ -260,13 +255,14 @@ function bouncy(
|
|||
const WIDTH = 300;
|
||||
const HEIGHT = 300;
|
||||
|
||||
class Image extends React.PureComponent {
|
||||
static propTypes = {
|
||||
imageComponentType: PropTypes.string
|
||||
}
|
||||
interface IImageProps {
|
||||
imageComponentType: string
|
||||
}
|
||||
|
||||
class Image extends React.PureComponent<IImageProps, any> {
|
||||
|
||||
render() {
|
||||
const { imageComponentType } = this.props;
|
||||
const { imageComponentType }: any = this.props;
|
||||
|
||||
const Component = ImageComponent(imageComponentType);
|
||||
|
||||
|
@ -277,16 +273,25 @@ const AnimatedImage = Animated.createAnimatedComponent(Image);
|
|||
|
||||
// it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer
|
||||
// and changed to use FastImage animated component
|
||||
export class ImageViewer extends React.Component {
|
||||
static propTypes = {
|
||||
uri: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
theme: PropTypes.string,
|
||||
imageComponentType: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
interface IImageViewerProps {
|
||||
uri: string;
|
||||
width: number;
|
||||
height: number;
|
||||
theme: string;
|
||||
imageComponentType: string;
|
||||
}
|
||||
|
||||
export class ImageViewer extends React.Component<IImageViewerProps, any> {
|
||||
private _onPinchEvent: any;
|
||||
private _focalDisplacementX: any;
|
||||
private _focalDisplacementY: any;
|
||||
private _scale: any;
|
||||
private _onPanEvent: any;
|
||||
private _panTransX: any;
|
||||
private _panTransY: any;
|
||||
|
||||
constructor(props: IImageViewerProps) {
|
||||
super(props);
|
||||
|
||||
// DECLARE TRANSX
|
||||
|
@ -351,7 +356,7 @@ export class ImageViewer extends React.Component {
|
|||
]);
|
||||
|
||||
const panActive = eq(panState, State.ACTIVE);
|
||||
const panFriction = value => friction(value);
|
||||
const panFriction = (value: any) => friction(value);
|
||||
|
||||
// X
|
||||
const panUpX = cond(
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { ImageComponent } from './ImageComponent';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
@ -15,12 +14,21 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IImageViewer {
|
||||
uri: string;
|
||||
imageComponentType: string;
|
||||
width: number;
|
||||
height: number;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export const ImageViewer = ({
|
||||
uri, imageComponentType, theme, width, height, ...props
|
||||
}) => {
|
||||
}: IImageViewer) => {
|
||||
const backgroundColor = themes[theme].previewBackground;
|
||||
const Component = ImageComponent(imageComponentType);
|
||||
return (
|
||||
// @ts-ignore
|
||||
<ScrollView
|
||||
style={{ backgroundColor }}
|
||||
contentContainerStyle={[
|
||||
|
@ -41,11 +49,3 @@ export const ImageViewer = ({
|
|||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
ImageViewer.propTypes = {
|
||||
uri: PropTypes.string,
|
||||
imageComponentType: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
theme: PropTypes.string
|
||||
};
|
|
@ -1,19 +1,16 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
|
||||
export default class KeyboardView extends React.PureComponent {
|
||||
static propTypes = {
|
||||
style: PropTypes.any,
|
||||
contentContainerStyle: PropTypes.any,
|
||||
keyboardVerticalOffset: PropTypes.number,
|
||||
scrollEnabled: PropTypes.bool,
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node
|
||||
])
|
||||
}
|
||||
interface IKeyboardViewProps {
|
||||
style: any,
|
||||
contentContainerStyle: any,
|
||||
keyboardVerticalOffset: number,
|
||||
scrollEnabled: boolean,
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
export default class KeyboardView extends React.PureComponent<IKeyboardViewProps, any> {
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -28,6 +25,7 @@ export default class KeyboardView extends React.PureComponent {
|
|||
scrollEnabled={scrollEnabled}
|
||||
alwaysBounceVertical={false}
|
||||
extraHeight={keyboardVerticalOffset}
|
||||
// @ts-ignore
|
||||
behavior='position'
|
||||
>
|
||||
{children}
|
|
@ -1,18 +1,34 @@
|
|||
import React from 'react';
|
||||
import { Animated, View, Text } from 'react-native';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import I18n, { isRTL } from '../../i18n';
|
||||
import styles, { ACTION_WIDTH, LONG_SWIPE } from './styles';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
interface ILeftActions {
|
||||
theme: string;
|
||||
transX: any;
|
||||
isRead: boolean;
|
||||
width: number;
|
||||
onToggleReadPress(): void;
|
||||
}
|
||||
|
||||
interface IRightActions {
|
||||
theme: string;
|
||||
transX: any;
|
||||
favorite: boolean;
|
||||
width: number;
|
||||
toggleFav(): void;
|
||||
onHidePress(): void;
|
||||
}
|
||||
|
||||
const reverse = new Animated.Value(isRTL() ? -1 : 1);
|
||||
|
||||
export const LeftActions = React.memo(({
|
||||
theme, transX, isRead, width, onToggleReadPress
|
||||
}) => {
|
||||
}: ILeftActions) => {
|
||||
const translateX = Animated.multiply(
|
||||
transX.interpolate({
|
||||
inputRange: [0, ACTION_WIDTH],
|
||||
|
@ -51,7 +67,7 @@ export const LeftActions = React.memo(({
|
|||
|
||||
export const RightActions = React.memo(({
|
||||
transX, favorite, width, toggleFav, onHidePress, theme
|
||||
}) => {
|
||||
}: IRightActions) => {
|
||||
const translateXFav = Animated.multiply(
|
||||
transX.interpolate({
|
||||
inputRange: [-width / 2, -ACTION_WIDTH * 2, 0],
|
||||
|
@ -113,20 +129,3 @@ export const RightActions = React.memo(({
|
|||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
LeftActions.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
transX: PropTypes.object,
|
||||
isRead: PropTypes.bool,
|
||||
width: PropTypes.number,
|
||||
onToggleReadPress: PropTypes.func
|
||||
};
|
||||
|
||||
RightActions.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
transX: PropTypes.object,
|
||||
favorite: PropTypes.bool,
|
||||
width: PropTypes.number,
|
||||
toggleFav: PropTypes.func,
|
||||
onHidePress: PropTypes.func
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
|
@ -8,9 +7,27 @@ import Markdown from '../../containers/markdown';
|
|||
import { themes } from '../../constants/colors';
|
||||
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/encryption/constants';
|
||||
|
||||
interface ILastMessage {
|
||||
theme: string;
|
||||
lastMessage: {
|
||||
u: any;
|
||||
pinned: boolean;
|
||||
t: string;
|
||||
attachments: any;
|
||||
msg: string;
|
||||
e2e: string;
|
||||
|
||||
};
|
||||
type: string;
|
||||
showLastMessage: boolean;
|
||||
username: string;
|
||||
useRealName: boolean;
|
||||
alert: boolean;
|
||||
}
|
||||
|
||||
const formatMsg = ({
|
||||
lastMessage, type, showLastMessage, username, useRealName
|
||||
}) => {
|
||||
}: Partial<ILastMessage>) => {
|
||||
if (!showLastMessage) {
|
||||
return '';
|
||||
}
|
||||
|
@ -45,11 +62,12 @@ const formatMsg = ({
|
|||
return `${ prefix }${ lastMessage.msg }`;
|
||||
};
|
||||
|
||||
const arePropsEqual = (oldProps, newProps) => dequal(oldProps, newProps);
|
||||
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
|
||||
|
||||
const LastMessage = React.memo(({
|
||||
lastMessage, type, showLastMessage, username, alert, useRealName, theme
|
||||
}) => (
|
||||
}: ILastMessage) => (
|
||||
// @ts-ignore
|
||||
<Markdown
|
||||
msg={formatMsg({
|
||||
lastMessage, type, showLastMessage, username, useRealName
|
||||
|
@ -63,14 +81,4 @@ const LastMessage = React.memo(({
|
|||
/>
|
||||
), arePropsEqual);
|
||||
|
||||
LastMessage.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
lastMessage: PropTypes.object,
|
||||
type: PropTypes.string,
|
||||
showLastMessage: PropTypes.bool,
|
||||
username: PropTypes.string,
|
||||
useRealName: PropTypes.bool,
|
||||
alert: PropTypes.bool
|
||||
};
|
||||
|
||||
export default LastMessage;
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View } from 'react-native';
|
||||
|
||||
import styles from './styles';
|
||||
|
@ -13,6 +12,53 @@ import Touchable from './Touchable';
|
|||
import Tag from './Tag';
|
||||
import I18n from '../../i18n';
|
||||
|
||||
interface IRoomItem {
|
||||
rid: string;
|
||||
type: string;
|
||||
prid: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
showLastMessage: boolean;
|
||||
username: string;
|
||||
avatarSize: number;
|
||||
testID: string;
|
||||
width: number;
|
||||
status: string;
|
||||
useRealName: boolean;
|
||||
theme: string;
|
||||
isFocused: boolean;
|
||||
isGroupChat: boolean;
|
||||
isRead: boolean;
|
||||
teamMain: boolean;
|
||||
date: string;
|
||||
accessibilityLabel: string;
|
||||
lastMessage: {
|
||||
u: any;
|
||||
pinned: boolean;
|
||||
t: string;
|
||||
attachments: any;
|
||||
msg: string;
|
||||
e2e: string;
|
||||
};
|
||||
favorite: boolean;
|
||||
alert: boolean;
|
||||
hideUnreadStatus: boolean;
|
||||
unread: number;
|
||||
userMentions: number;
|
||||
groupMentions: number;
|
||||
tunread: [];
|
||||
tunreadUser: [];
|
||||
tunreadGroup: [];
|
||||
swipeEnabled: boolean;
|
||||
toggleFav(): void;
|
||||
toggleRead(): void;
|
||||
onPress(): void;
|
||||
onLongPress(): void;
|
||||
hideChannel(): void;
|
||||
autoJoin: boolean;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
const RoomItem = ({
|
||||
rid,
|
||||
type,
|
||||
|
@ -20,10 +66,10 @@ const RoomItem = ({
|
|||
name,
|
||||
avatar,
|
||||
width,
|
||||
avatarSize,
|
||||
avatarSize = 48,
|
||||
username,
|
||||
showLastMessage,
|
||||
status,
|
||||
status = 'offline',
|
||||
useRealName,
|
||||
theme,
|
||||
isFocused,
|
||||
|
@ -42,7 +88,7 @@ const RoomItem = ({
|
|||
tunreadUser,
|
||||
tunreadGroup,
|
||||
testID,
|
||||
swipeEnabled,
|
||||
swipeEnabled = true,
|
||||
onPress,
|
||||
onLongPress,
|
||||
toggleFav,
|
||||
|
@ -50,7 +96,7 @@ const RoomItem = ({
|
|||
hideChannel,
|
||||
teamMain,
|
||||
autoJoin
|
||||
}) => (
|
||||
}: IRoomItem) => (
|
||||
<Touchable
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
|
@ -158,49 +204,4 @@ const RoomItem = ({
|
|||
</Touchable>
|
||||
);
|
||||
|
||||
RoomItem.propTypes = {
|
||||
rid: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
prid: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
avatar: PropTypes.string.isRequired,
|
||||
showLastMessage: PropTypes.bool,
|
||||
username: PropTypes.string,
|
||||
avatarSize: PropTypes.number,
|
||||
testID: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
useRealName: PropTypes.bool,
|
||||
theme: PropTypes.string,
|
||||
isFocused: PropTypes.bool,
|
||||
isGroupChat: PropTypes.bool,
|
||||
isRead: PropTypes.bool,
|
||||
teamMain: PropTypes.bool,
|
||||
date: PropTypes.string,
|
||||
accessibilityLabel: PropTypes.string,
|
||||
lastMessage: PropTypes.object,
|
||||
favorite: PropTypes.bool,
|
||||
alert: PropTypes.bool,
|
||||
hideUnreadStatus: PropTypes.bool,
|
||||
unread: PropTypes.number,
|
||||
userMentions: PropTypes.number,
|
||||
groupMentions: PropTypes.number,
|
||||
tunread: PropTypes.array,
|
||||
tunreadUser: PropTypes.array,
|
||||
tunreadGroup: PropTypes.array,
|
||||
swipeEnabled: PropTypes.bool,
|
||||
toggleFav: PropTypes.func,
|
||||
toggleRead: PropTypes.func,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
hideChannel: PropTypes.func,
|
||||
autoJoin: PropTypes.bool
|
||||
};
|
||||
|
||||
RoomItem.defaultProps = {
|
||||
avatarSize: 48,
|
||||
status: 'offline',
|
||||
swipeEnabled: true
|
||||
};
|
||||
|
||||
export default RoomItem;
|
|
@ -1,13 +1,17 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { useTheme } from '../../theme';
|
||||
import styles from './styles';
|
||||
|
||||
const Tag = React.memo(({ name, testID }) => {
|
||||
const { theme } = useTheme();
|
||||
interface ITag {
|
||||
name: string;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const Tag = React.memo(({ name, testID }: ITag) => {
|
||||
const { theme }: any = useTheme();
|
||||
|
||||
return (
|
||||
<View style={[styles.tagContainer, { backgroundColor: themes[theme].borderColor }]}>
|
||||
|
@ -24,9 +28,4 @@ const Tag = React.memo(({ name, testID }) => {
|
|||
);
|
||||
});
|
||||
|
||||
Tag.propTypes = {
|
||||
name: PropTypes.string,
|
||||
testID: PropTypes.string
|
||||
};
|
||||
|
||||
export default Tag;
|
|
@ -1,13 +1,17 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
||||
const Title = React.memo(({
|
||||
name, theme, hideUnreadStatus, alert
|
||||
}) => (
|
||||
interface ITitle {
|
||||
name: string;
|
||||
theme: string;
|
||||
hideUnreadStatus: boolean;
|
||||
alert: boolean;
|
||||
}
|
||||
|
||||
const Title = React.memo(({ name, theme, hideUnreadStatus, alert }: ITitle) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.title,
|
||||
|
@ -21,11 +25,4 @@ const Title = React.memo(({
|
|||
</Text>
|
||||
));
|
||||
|
||||
Title.propTypes = {
|
||||
name: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
hideUnreadStatus: PropTypes.bool,
|
||||
alert: PropTypes.bool
|
||||
};
|
||||
|
||||
export default Title;
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Animated } from 'react-native';
|
||||
import {
|
||||
LongPressGestureHandler, PanGestureHandler, State
|
||||
|
@ -15,26 +14,34 @@ import { isRTL } from '../../i18n';
|
|||
import { themes } from '../../constants/colors';
|
||||
import { LeftActions, RightActions } from './Actions';
|
||||
|
||||
class Touchable extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
testID: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
favorite: PropTypes.bool,
|
||||
isRead: PropTypes.bool,
|
||||
rid: PropTypes.string,
|
||||
toggleFav: PropTypes.func,
|
||||
toggleRead: PropTypes.func,
|
||||
hideChannel: PropTypes.func,
|
||||
children: PropTypes.element,
|
||||
theme: PropTypes.string,
|
||||
isFocused: PropTypes.bool,
|
||||
swipeEnabled: PropTypes.bool
|
||||
}
|
||||
interface ITouchableProps {
|
||||
children: JSX.Element;
|
||||
type: string;
|
||||
onPress(): void;
|
||||
onLongPress(): void;
|
||||
testID: string;
|
||||
width: number;
|
||||
favorite: boolean;
|
||||
isRead: boolean;
|
||||
rid: string;
|
||||
toggleFav: Function;
|
||||
toggleRead: Function;
|
||||
hideChannel: Function;
|
||||
theme: string;
|
||||
isFocused: boolean;
|
||||
swipeEnabled: boolean;
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
class Touchable extends React.Component<ITouchableProps, any> {
|
||||
private dragX: Animated.Value;
|
||||
private rowOffSet: Animated.Value;
|
||||
private reverse: Animated.Value;
|
||||
private transX: Animated.AnimatedAddition;
|
||||
private transXReverse: Animated.AnimatedMultiplication;
|
||||
private _onGestureEvent: (...args: any[]) => void;
|
||||
private _value: number;
|
||||
|
||||
constructor(props: ITouchableProps) {
|
||||
super(props);
|
||||
this.dragX = new Animated.Value(0);
|
||||
this.rowOffSet = new Animated.Value(0);
|
||||
|
@ -56,20 +63,20 @@ class Touchable extends React.Component {
|
|||
this._value = 0;
|
||||
}
|
||||
|
||||
_onHandlerStateChange = ({ nativeEvent }) => {
|
||||
_onHandlerStateChange = ({ nativeEvent }: any) => {
|
||||
if (nativeEvent.oldState === State.ACTIVE) {
|
||||
this._handleRelease(nativeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
onLongPressHandlerStateChange = ({ nativeEvent }) => {
|
||||
onLongPressHandlerStateChange = ({ nativeEvent }: any) => {
|
||||
if (nativeEvent.state === State.ACTIVE) {
|
||||
this.onLongPress();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_handleRelease = (nativeEvent) => {
|
||||
_handleRelease = (nativeEvent: any) => {
|
||||
const { translationX } = nativeEvent;
|
||||
const { rowState } = this.state;
|
||||
this._value += translationX;
|
||||
|
@ -152,7 +159,7 @@ class Touchable extends React.Component {
|
|||
this._animateRow(toValue);
|
||||
}
|
||||
|
||||
_animateRow = (toValue) => {
|
||||
_animateRow = (toValue: any) => {
|
||||
this.rowOffSet.setValue(this._value);
|
||||
this._value = toValue;
|
||||
this.dragX.setValue(0);
|
|
@ -1,18 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||
|
||||
const TypeIcon = React.memo(({
|
||||
type, prid, status, isGroupChat, teamMain
|
||||
}) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />);
|
||||
|
||||
TypeIcon.propTypes = {
|
||||
type: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
prid: PropTypes.string,
|
||||
isGroupChat: PropTypes.bool,
|
||||
teamMain: PropTypes.bool
|
||||
};
|
||||
|
||||
export default TypeIcon;
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||
|
||||
interface ITypeIcon {
|
||||
type: string;
|
||||
status: string;
|
||||
prid: string;
|
||||
isGroupChat: boolean;
|
||||
teamMain: boolean;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const TypeIcon = React.memo(({
|
||||
type, prid, status, isGroupChat, teamMain
|
||||
}: ITypeIcon) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />);
|
||||
|
||||
export default TypeIcon;
|
|
@ -1,14 +1,18 @@
|
|||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { capitalize } from '../../utils/room';
|
||||
|
||||
const UpdatedAt = React.memo(({
|
||||
date, theme, hideUnreadStatus, alert
|
||||
}) => {
|
||||
interface IUpdatedAt {
|
||||
date: string;
|
||||
theme: string;
|
||||
hideUnreadStatus: boolean;
|
||||
alert: boolean;
|
||||
}
|
||||
|
||||
const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdatedAt) => {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
@ -38,11 +42,4 @@ const UpdatedAt = React.memo(({
|
|||
);
|
||||
});
|
||||
|
||||
UpdatedAt.propTypes = {
|
||||
date: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
hideUnreadStatus: PropTypes.bool,
|
||||
alert: PropTypes.bool
|
||||
};
|
||||
|
||||
export default UpdatedAt;
|
|
@ -1,11 +1,20 @@
|
|||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import styles from './styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
|
||||
interface IWrapper {
|
||||
accessibilityLabel: string;
|
||||
avatar: string;
|
||||
avatarSize: number;
|
||||
type: string;
|
||||
theme: string;
|
||||
rid: string;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
const Wrapper = ({
|
||||
accessibilityLabel,
|
||||
avatar,
|
||||
|
@ -14,7 +23,7 @@ const Wrapper = ({
|
|||
theme,
|
||||
rid,
|
||||
children
|
||||
}) => (
|
||||
}: IWrapper) => (
|
||||
<View
|
||||
style={styles.container}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
|
@ -39,14 +48,4 @@ const Wrapper = ({
|
|||
</View>
|
||||
);
|
||||
|
||||
Wrapper.propTypes = {
|
||||
accessibilityLabel: PropTypes.string,
|
||||
avatar: PropTypes.string,
|
||||
avatarSize: PropTypes.number,
|
||||
type: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
children: PropTypes.element
|
||||
};
|
||||
|
||||
export default Wrapper;
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
|
@ -9,6 +8,32 @@ import RoomItem from './RoomItem';
|
|||
|
||||
export { ROW_HEIGHT };
|
||||
|
||||
interface IRoomItemContainerProps {
|
||||
item: any;
|
||||
showLastMessage: boolean;
|
||||
id: string;
|
||||
onPress({}?): void;
|
||||
onLongPress({}?): void;
|
||||
username: string;
|
||||
avatarSize: number;
|
||||
width: number;
|
||||
status: string;
|
||||
toggleFav(): void;
|
||||
toggleRead(): void;
|
||||
hideChannel(): void;
|
||||
useRealName: boolean;
|
||||
getUserPresence: Function;
|
||||
connected: boolean;
|
||||
theme: string;
|
||||
isFocused: boolean;
|
||||
getRoomTitle: Function;
|
||||
getRoomAvatar: Function;
|
||||
getIsGroupChat: Function;
|
||||
getIsRead: Function;
|
||||
swipeEnabled: boolean;
|
||||
autoJoin: boolean;
|
||||
}
|
||||
|
||||
const attrs = [
|
||||
'width',
|
||||
'status',
|
||||
|
@ -20,32 +45,9 @@ const attrs = [
|
|||
'autoJoin'
|
||||
];
|
||||
|
||||
class RoomItemContainer extends React.Component {
|
||||
static propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
showLastMessage: PropTypes.bool,
|
||||
id: PropTypes.string,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
username: PropTypes.string,
|
||||
avatarSize: PropTypes.number,
|
||||
width: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
toggleFav: PropTypes.func,
|
||||
toggleRead: PropTypes.func,
|
||||
hideChannel: PropTypes.func,
|
||||
useRealName: PropTypes.bool,
|
||||
getUserPresence: PropTypes.func,
|
||||
connected: PropTypes.bool,
|
||||
theme: PropTypes.string,
|
||||
isFocused: PropTypes.bool,
|
||||
getRoomTitle: PropTypes.func,
|
||||
getRoomAvatar: PropTypes.func,
|
||||
getIsGroupChat: PropTypes.func,
|
||||
getIsRead: PropTypes.func,
|
||||
swipeEnabled: PropTypes.bool,
|
||||
autoJoin: PropTypes.bool
|
||||
};
|
||||
class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
|
||||
private mounted: boolean;
|
||||
private roomSubscription: any;
|
||||
|
||||
static defaultProps = {
|
||||
avatarSize: 48,
|
||||
|
@ -58,7 +60,7 @@ class RoomItemContainer extends React.Component {
|
|||
swipeEnabled: true
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: IRoomItemContainerProps) {
|
||||
super(props);
|
||||
this.mounted = false;
|
||||
this.init();
|
||||
|
@ -72,12 +74,12 @@ class RoomItemContainer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { props } = this;
|
||||
shouldComponentUpdate(nextProps: any) {
|
||||
const { props }: any = this;
|
||||
return !attrs.every(key => props[key] === nextProps[key]);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: any) {
|
||||
const { connected, getUserPresence, id } = this.props;
|
||||
if (prevProps.connected !== connected && connected && this.isDirect) {
|
||||
getUserPresence(id);
|
||||
|
@ -96,7 +98,7 @@ class RoomItemContainer extends React.Component {
|
|||
}
|
||||
|
||||
get isDirect() {
|
||||
const { item: { t }, id } = this.props;
|
||||
const { item: { t }, id }: any = this.props;
|
||||
return t === 'd' && id && !this.isGroupChat;
|
||||
}
|
||||
|
||||
|
@ -165,6 +167,7 @@ class RoomItemContainer extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<RoomItem
|
||||
name={name}
|
||||
avatar={avatar}
|
||||
|
@ -207,7 +210,7 @@ class RoomItemContainer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const mapStateToProps = (state: any, ownProps: any) => {
|
||||
let status = 'loading';
|
||||
const { id, type, visitor = {} } = ownProps;
|
||||
if (state.meteor.connected) {
|
|
@ -7,7 +7,7 @@ export const ACTION_WIDTH = 80;
|
|||
export const SMALL_SWIPE = ACTION_WIDTH / 2;
|
||||
export const LONG_SWIPE = ACTION_WIDTH * 3;
|
||||
|
||||
export default StyleSheet.create({
|
||||
export default StyleSheet.create<any>({
|
||||
flex: {
|
||||
flex: 1
|
||||
},
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
// @ts-ignore
|
||||
import { View, Text, Pressable } from 'react-native';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
|
@ -11,11 +11,23 @@ import { withTheme } from '../../theme';
|
|||
|
||||
export { ROW_HEIGHT };
|
||||
|
||||
interface IServerItem {
|
||||
item: {
|
||||
id: string;
|
||||
iconURL: string;
|
||||
name: string;
|
||||
};
|
||||
onPress(): void;
|
||||
onLongPress(): void;
|
||||
hasCheck: boolean;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const defaultLogo = require('../../static/images/logo.png');
|
||||
|
||||
const ServerItem = React.memo(({
|
||||
item, onPress, onLongPress, hasCheck, theme
|
||||
}) => (
|
||||
}: IServerItem) => (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
onLongPress={() => onLongPress?.()}
|
||||
|
@ -23,7 +35,7 @@ const ServerItem = React.memo(({
|
|||
android_ripple={{
|
||||
color: themes[theme].bannerBackground
|
||||
}}
|
||||
style={({ pressed }) => ({
|
||||
style={({ pressed }: any) => ({
|
||||
backgroundColor: isIOS && pressed
|
||||
? themes[theme].bannerBackground
|
||||
: themes[theme].backgroundColor
|
||||
|
@ -37,6 +49,7 @@ const ServerItem = React.memo(({
|
|||
uri: item.iconURL,
|
||||
priority: FastImage.priority.high
|
||||
}}
|
||||
// @ts-ignore
|
||||
defaultSource={defaultLogo}
|
||||
style={styles.serverIcon}
|
||||
onError={() => console.log('err_loading_server_icon')}
|
||||
|
@ -58,12 +71,4 @@ const ServerItem = React.memo(({
|
|||
</Pressable>
|
||||
));
|
||||
|
||||
ServerItem.propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
hasCheck: PropTypes.bool,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default withTheme(ServerItem);
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { TextInput, StyleSheet, I18nManager } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
|
@ -12,7 +11,12 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const ThemedTextInput = React.forwardRef(({ style, theme, ...props }, ref) => (
|
||||
interface IThemedTextInput {
|
||||
style: object;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const ThemedTextInput = React.forwardRef(({ style, theme, ...props }: IThemedTextInput, ref: any) => (
|
||||
<TextInput
|
||||
ref={ref}
|
||||
style={[{ color: themes[theme].titleText }, style, styles.input]}
|
||||
|
@ -22,9 +26,4 @@ const ThemedTextInput = React.forwardRef(({ style, theme, ...props }, ref) => (
|
|||
/>
|
||||
));
|
||||
|
||||
ThemedTextInput.propTypes = {
|
||||
style: PropTypes.object,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default ThemedTextInput;
|
|
@ -2,7 +2,7 @@ import { themes } from '../../constants/colors';
|
|||
|
||||
export const getUnreadStyle = ({
|
||||
unread, userMentions, groupMentions, theme, tunread, tunreadUser, tunreadGroup
|
||||
}) => {
|
||||
}: any) => {
|
||||
if ((!unread || unread <= 0) && (!tunread?.length)) {
|
||||
return {};
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
|
@ -30,9 +29,21 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IUnreadBadge {
|
||||
theme: string;
|
||||
unread: number;
|
||||
userMentions: number;
|
||||
groupMentions: number;
|
||||
style: object;
|
||||
tunread: [];
|
||||
tunreadUser: [];
|
||||
tunreadGroup: [];
|
||||
small: boolean;
|
||||
}
|
||||
|
||||
const UnreadBadge = React.memo(({
|
||||
theme, unread, userMentions, groupMentions, style, tunread, tunreadUser, tunreadGroup, small
|
||||
}) => {
|
||||
}: IUnreadBadge) => {
|
||||
if ((!unread || unread <= 0) && (!tunread?.length)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -43,7 +54,7 @@ const UnreadBadge = React.memo(({
|
|||
if (!backgroundColor) {
|
||||
return null;
|
||||
}
|
||||
let text = unread || tunread?.length;
|
||||
let text: any = unread || tunread?.length;
|
||||
if (small && text >= 100) {
|
||||
text = '+99';
|
||||
}
|
||||
|
@ -78,16 +89,4 @@ const UnreadBadge = React.memo(({
|
|||
);
|
||||
});
|
||||
|
||||
UnreadBadge.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
unread: PropTypes.number,
|
||||
userMentions: PropTypes.number,
|
||||
groupMentions: PropTypes.number,
|
||||
style: PropTypes.object,
|
||||
tunread: PropTypes.array,
|
||||
tunreadUser: PropTypes.array,
|
||||
tunreadGroup: PropTypes.array,
|
||||
small: PropTypes.bool
|
||||
};
|
||||
|
||||
export default withTheme(UnreadBadge);
|
|
@ -1,8 +1,6 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
Text, View, StyleSheet, Pressable
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
// @ts-ignore
|
||||
import { Text, View, StyleSheet, Pressable } from 'react-native';
|
||||
|
||||
import Avatar from '../containers/Avatar';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
|
@ -41,9 +39,20 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IUserItem {
|
||||
name: string;
|
||||
username: string;
|
||||
onPress(): void;
|
||||
testID: string;
|
||||
onLongPress(): void;
|
||||
style: any;
|
||||
icon: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const UserItem = ({
|
||||
name, username, onPress, testID, onLongPress, style, icon, theme
|
||||
}) => (
|
||||
}: IUserItem) => (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
|
@ -51,7 +60,7 @@ const UserItem = ({
|
|||
android_ripple={{
|
||||
color: themes[theme].bannerBackground
|
||||
}}
|
||||
style={({ pressed }) => ({
|
||||
style={({ pressed }: any) => ({
|
||||
backgroundColor: isIOS && pressed
|
||||
? themes[theme].bannerBackground
|
||||
: 'transparent'
|
||||
|
@ -68,15 +77,4 @@ const UserItem = ({
|
|||
</Pressable>
|
||||
);
|
||||
|
||||
UserItem.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
username: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
testID: PropTypes.string.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
style: PropTypes.any,
|
||||
icon: PropTypes.string,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
||||
export default UserItem;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue