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