chore: migrate AttachmentView to hooks (#5003)
* migrate AttachmentView to hooks * fix types * fix types * fix lint
This commit is contained in:
parent
01577d9534
commit
47fbde566d
|
@ -0,0 +1,43 @@
|
||||||
|
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
import { TNavigation } from '../../stacks/stackType';
|
||||||
|
import {
|
||||||
|
AdminPanelStackParamList,
|
||||||
|
ChatsStackParamList,
|
||||||
|
DisplayPrefStackParamList,
|
||||||
|
DrawerParamList,
|
||||||
|
E2EEnterYourPasswordStackParamList,
|
||||||
|
E2ESaveYourPasswordStackParamList,
|
||||||
|
InsideStackParamList,
|
||||||
|
NewMessageStackParamList,
|
||||||
|
OutsideModalParamList,
|
||||||
|
OutsideParamList,
|
||||||
|
ProfileStackParamList,
|
||||||
|
SettingsStackParamList
|
||||||
|
} from '../../stacks/types';
|
||||||
|
|
||||||
|
type TRoutes =
|
||||||
|
| ChatsStackParamList
|
||||||
|
| ProfileStackParamList
|
||||||
|
| SettingsStackParamList
|
||||||
|
| AdminPanelStackParamList
|
||||||
|
| DisplayPrefStackParamList
|
||||||
|
| DrawerParamList
|
||||||
|
| NewMessageStackParamList
|
||||||
|
| E2ESaveYourPasswordStackParamList
|
||||||
|
| E2EEnterYourPasswordStackParamList
|
||||||
|
| InsideStackParamList
|
||||||
|
| OutsideParamList
|
||||||
|
| OutsideModalParamList
|
||||||
|
| TNavigation;
|
||||||
|
|
||||||
|
export function useAppNavigation<ParamList extends TRoutes, RouteName extends keyof ParamList = keyof ParamList>() {
|
||||||
|
const navigation = useNavigation<StackNavigationProp<ParamList, RouteName>>();
|
||||||
|
return navigation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAppRoute<ParamList extends TRoutes, RouteName extends keyof ParamList = keyof ParamList>() {
|
||||||
|
const route = useRoute<RouteProp<ParamList, RouteName>>();
|
||||||
|
return route;
|
||||||
|
}
|
|
@ -82,6 +82,7 @@ import {
|
||||||
SettingsStackParamList
|
SettingsStackParamList
|
||||||
} from './types';
|
} from './types';
|
||||||
import { isIOS } from '../lib/methods/helpers';
|
import { isIOS } from '../lib/methods/helpers';
|
||||||
|
import { TNavigation } from './stackType';
|
||||||
|
|
||||||
// ChatsStackNavigator
|
// ChatsStackNavigator
|
||||||
const ChatsStack = createStackNavigator<ChatsStackParamList>();
|
const ChatsStack = createStackNavigator<ChatsStackParamList>();
|
||||||
|
@ -306,7 +307,7 @@ const E2EEnterYourPasswordStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
const InsideStack = createStackNavigator<InsideStackParamList>();
|
const InsideStack = createStackNavigator<InsideStackParamList & TNavigation>();
|
||||||
const InsideStackNavigator = () => {
|
const InsideStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ import {
|
||||||
ModalStackParamList
|
ModalStackParamList
|
||||||
} from './types';
|
} from './types';
|
||||||
import { isIOS } from '../../lib/methods/helpers';
|
import { isIOS } from '../../lib/methods/helpers';
|
||||||
|
import { TNavigation } from '../stackType';
|
||||||
|
|
||||||
// ChatsStackNavigator
|
// ChatsStackNavigator
|
||||||
const ChatsStack = createStackNavigator<MasterDetailChatsStackParamList>();
|
const ChatsStack = createStackNavigator<MasterDetailChatsStackParamList>();
|
||||||
|
@ -206,7 +207,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
const InsideStack = createStackNavigator<MasterDetailInsideStackParamList>();
|
const InsideStack = createStackNavigator<MasterDetailInsideStackParamList & TNavigation>();
|
||||||
const InsideStackNavigator = React.memo(() => {
|
const InsideStackNavigator = React.memo(() => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -207,9 +207,6 @@ export type ModalStackParamList = {
|
||||||
export type MasterDetailInsideStackParamList = {
|
export type MasterDetailInsideStackParamList = {
|
||||||
DrawerNavigator: NavigatorScreenParams<Partial<MasterDetailDrawerParamList>>; // TODO: Change
|
DrawerNavigator: NavigatorScreenParams<Partial<MasterDetailDrawerParamList>>; // TODO: Change
|
||||||
ModalStackNavigator: NavigatorScreenParams<ModalStackParamList>;
|
ModalStackNavigator: NavigatorScreenParams<ModalStackParamList>;
|
||||||
AttachmentView: {
|
|
||||||
attachment: IAttachment;
|
|
||||||
};
|
|
||||||
ModalBlockView: {
|
ModalBlockView: {
|
||||||
data: any; // TODO: Change
|
data: any; // TODO: Change
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { IAttachment } from '../definitions';
|
||||||
|
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
||||||
|
|
||||||
|
export type TNavigation = {
|
||||||
|
PickerView: {
|
||||||
|
title: string;
|
||||||
|
data: IOptionsField[];
|
||||||
|
value?: string;
|
||||||
|
onSearch: (text?: string, offset?: number) => Promise<any>;
|
||||||
|
onEndReached?: (text?: string, offset?: number) => Promise<any>;
|
||||||
|
total?: number;
|
||||||
|
onChangeValue: Function;
|
||||||
|
};
|
||||||
|
ForwardLivechatView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
AttachmentView: {
|
||||||
|
attachment: IAttachment;
|
||||||
|
};
|
||||||
|
};
|
|
@ -288,9 +288,6 @@ export type InsideStackParamList = {
|
||||||
NewMessageStackNavigator: NavigatorScreenParams<NewMessageStackParamList>;
|
NewMessageStackNavigator: NavigatorScreenParams<NewMessageStackParamList>;
|
||||||
E2ESaveYourPasswordStackNavigator: NavigatorScreenParams<E2ESaveYourPasswordStackParamList>;
|
E2ESaveYourPasswordStackNavigator: NavigatorScreenParams<E2ESaveYourPasswordStackParamList>;
|
||||||
E2EEnterYourPasswordStackNavigator: NavigatorScreenParams<E2EEnterYourPasswordStackParamList>;
|
E2EEnterYourPasswordStackNavigator: NavigatorScreenParams<E2EEnterYourPasswordStackParamList>;
|
||||||
AttachmentView: {
|
|
||||||
attachment: IAttachment;
|
|
||||||
};
|
|
||||||
StatusView: undefined;
|
StatusView: undefined;
|
||||||
ShareView: {
|
ShareView: {
|
||||||
attachments: IAttachment[];
|
attachments: IAttachment[];
|
||||||
|
|
|
@ -1,83 +1,114 @@
|
||||||
import React from 'react';
|
|
||||||
import { PermissionsAndroid, StyleSheet, View } from 'react-native';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { RouteProp } from '@react-navigation/native';
|
|
||||||
import CameraRoll from '@react-native-community/cameraroll';
|
import CameraRoll from '@react-native-community/cameraroll';
|
||||||
import * as mime from 'react-native-mime-types';
|
import { HeaderBackground, useHeaderHeight } from '@react-navigation/elements';
|
||||||
import RNFetchBlob from 'rn-fetch-blob';
|
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||||
import { Video, ResizeMode } from 'expo-av';
|
import { ResizeMode, Video } from 'expo-av';
|
||||||
import { sha256 } from 'js-sha256';
|
import { sha256 } from 'js-sha256';
|
||||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
import React from 'react';
|
||||||
import { HeaderBackground, HeaderHeightContext } from '@react-navigation/elements';
|
import { PermissionsAndroid, useWindowDimensions, View } from 'react-native';
|
||||||
|
import * as mime from 'react-native-mime-types';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
import { shallowEqual } from 'react-redux';
|
||||||
|
import RNFetchBlob from 'rn-fetch-blob';
|
||||||
|
|
||||||
import { LISTENER } from '../containers/Toast';
|
|
||||||
import EventEmitter from '../lib/methods/helpers/events';
|
|
||||||
import I18n from '../i18n';
|
|
||||||
import { TSupportedThemes, withTheme } from '../theme';
|
|
||||||
import { ImageViewer } from '../containers/ImageViewer';
|
|
||||||
import { themes } from '../lib/constants';
|
|
||||||
import RCActivityIndicator from '../containers/ActivityIndicator';
|
import RCActivityIndicator from '../containers/ActivityIndicator';
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import { isAndroid, formatAttachmentUrl } from '../lib/methods/helpers';
|
import { ImageViewer } from '../containers/ImageViewer';
|
||||||
import { getUserSelector } from '../selectors/login';
|
|
||||||
import { withDimensions } from '../dimensions';
|
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { InsideStackParamList } from '../stacks/types';
|
import { LISTENER } from '../containers/Toast';
|
||||||
import { IApplicationState, IUser, IAttachment } from '../definitions';
|
import { IAttachment } from '../definitions';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
import { useAppSelector } from '../lib/hooks';
|
||||||
|
import { useAppNavigation, useAppRoute } from '../lib/hooks/navigation';
|
||||||
|
import { formatAttachmentUrl, isAndroid } from '../lib/methods/helpers';
|
||||||
|
import EventEmitter from '../lib/methods/helpers/events';
|
||||||
|
import { getUserSelector } from '../selectors/login';
|
||||||
|
import { TNavigation } from '../stacks/stackType';
|
||||||
|
import { useTheme } from '../theme';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const RenderContent = ({
|
||||||
container: {
|
setLoading,
|
||||||
flex: 1
|
attachment
|
||||||
}
|
}: {
|
||||||
});
|
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
|
||||||
interface IAttachmentViewState {
|
|
||||||
attachment: IAttachment;
|
attachment: IAttachment;
|
||||||
loading: boolean;
|
}) => {
|
||||||
}
|
const videoRef = React.useRef<Video>(null);
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
const { width, height } = useWindowDimensions();
|
||||||
|
const headerHeight = useHeaderHeight();
|
||||||
|
const navigation = useAppNavigation<TNavigation, 'AttachmentView'>();
|
||||||
|
const { baseUrl, user } = useAppSelector(
|
||||||
|
state => ({
|
||||||
|
baseUrl: state.server.server,
|
||||||
|
user: { id: getUserSelector(state).id, token: getUserSelector(state).token }
|
||||||
|
}),
|
||||||
|
shallowEqual
|
||||||
|
);
|
||||||
|
|
||||||
interface IAttachmentViewProps {
|
React.useLayoutEffect(() => {
|
||||||
navigation: StackNavigationProp<InsideStackParamList, 'AttachmentView'>;
|
const blurSub = navigation.addListener('blur', () => {
|
||||||
route: RouteProp<InsideStackParamList, 'AttachmentView'>;
|
if (videoRef.current && videoRef.current.stopAsync) {
|
||||||
theme?: TSupportedThemes;
|
videoRef.current.stopAsync();
|
||||||
baseUrl: string;
|
|
||||||
width?: number;
|
|
||||||
height?: number;
|
|
||||||
insets?: { left: number; bottom: number; right: number; top: number };
|
|
||||||
user: IUser;
|
|
||||||
Allow_Save_Media_to_Gallery: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AttachmentView extends React.Component<IAttachmentViewProps, IAttachmentViewState> {
|
|
||||||
private unsubscribeBlur: (() => void) | undefined;
|
|
||||||
private videoRef: any;
|
|
||||||
|
|
||||||
constructor(props: IAttachmentViewProps) {
|
|
||||||
super(props);
|
|
||||||
const attachment = props.route.params?.attachment;
|
|
||||||
this.state = { attachment, loading: true };
|
|
||||||
this.setHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { navigation } = this.props;
|
|
||||||
this.unsubscribeBlur = navigation.addListener('blur', () => {
|
|
||||||
if (this.videoRef && this.videoRef.stopAsync) {
|
|
||||||
this.videoRef.stopAsync();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
return () => {
|
||||||
|
blurSub();
|
||||||
|
};
|
||||||
|
}, [navigation]);
|
||||||
|
|
||||||
componentWillUnmount() {
|
if (attachment.image_url) {
|
||||||
if (this.unsubscribeBlur) {
|
const url = formatAttachmentUrl(attachment.title_link || attachment.image_url, user.id, user.token, baseUrl);
|
||||||
this.unsubscribeBlur();
|
const uri = encodeURI(url);
|
||||||
}
|
return (
|
||||||
|
<ImageViewer
|
||||||
|
uri={uri}
|
||||||
|
onLoadEnd={() => setLoading(false)}
|
||||||
|
width={width}
|
||||||
|
height={height - insets.top - insets.bottom - (headerHeight || 0)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
if (attachment.video_url) {
|
||||||
|
const url = formatAttachmentUrl(attachment.video_url, user.id, user.token, baseUrl);
|
||||||
|
const uri = encodeURI(url);
|
||||||
|
return (
|
||||||
|
<Video
|
||||||
|
source={{ uri }}
|
||||||
|
rate={1.0}
|
||||||
|
volume={1.0}
|
||||||
|
isMuted={false}
|
||||||
|
resizeMode={ResizeMode.CONTAIN}
|
||||||
|
shouldPlay
|
||||||
|
isLooping={false}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
useNativeControls
|
||||||
|
onLoad={() => setLoading(false)}
|
||||||
|
onError={console.log}
|
||||||
|
ref={videoRef}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
setHeader = () => {
|
const AttachmentView = (): React.ReactElement => {
|
||||||
const { route, navigation, theme, Allow_Save_Media_to_Gallery } = this.props;
|
const navigation = useAppNavigation<TNavigation, 'AttachmentView'>();
|
||||||
const attachment = route.params?.attachment;
|
const {
|
||||||
|
params: { attachment }
|
||||||
|
} = useAppRoute<TNavigation, 'AttachmentView'>();
|
||||||
|
const [loading, setLoading] = React.useState(true);
|
||||||
|
const { colors } = useTheme();
|
||||||
|
|
||||||
|
const { baseUrl, user, Allow_Save_Media_to_Gallery } = useAppSelector(
|
||||||
|
state => ({
|
||||||
|
baseUrl: state.server.server,
|
||||||
|
user: { id: getUserSelector(state).id, token: getUserSelector(state).token },
|
||||||
|
Allow_Save_Media_to_Gallery: (state.settings.Allow_Save_Media_to_Gallery as boolean) ?? true
|
||||||
|
}),
|
||||||
|
shallowEqual
|
||||||
|
);
|
||||||
|
|
||||||
|
const setHeader = () => {
|
||||||
let { title } = attachment;
|
let { title } = attachment;
|
||||||
try {
|
try {
|
||||||
if (title) {
|
if (title) {
|
||||||
|
@ -89,30 +120,30 @@ class AttachmentView extends React.Component<IAttachmentViewProps, IAttachmentVi
|
||||||
const options: StackNavigationOptions = {
|
const options: StackNavigationOptions = {
|
||||||
title: title || '',
|
title: title || '',
|
||||||
headerTitleAlign: 'center',
|
headerTitleAlign: 'center',
|
||||||
headerTitleStyle: { color: themes[theme!].previewTintColor },
|
headerTitleStyle: { color: colors.previewTintColor },
|
||||||
headerTintColor: themes[theme!].previewTintColor,
|
headerTintColor: colors.previewTintColor,
|
||||||
headerTitleContainerStyle: { flex: 1, maxWidth: undefined },
|
headerTitleContainerStyle: { flex: 1, maxWidth: undefined },
|
||||||
headerLeftContainerStyle: { flexGrow: undefined, flexBasis: undefined },
|
headerLeftContainerStyle: { flexGrow: undefined, flexBasis: undefined },
|
||||||
headerRightContainerStyle: { flexGrow: undefined, flexBasis: undefined },
|
headerRightContainerStyle: { flexGrow: undefined, flexBasis: undefined },
|
||||||
headerLeft: () => (
|
headerLeft: () => (
|
||||||
<HeaderButton.CloseModal testID='close-attachment-view' navigation={navigation} color={themes[theme!].previewTintColor} />
|
<HeaderButton.CloseModal testID='close-attachment-view' navigation={navigation} color={colors.previewTintColor} />
|
||||||
),
|
),
|
||||||
headerRight: () =>
|
headerRight: () =>
|
||||||
Allow_Save_Media_to_Gallery ? (
|
Allow_Save_Media_to_Gallery ? (
|
||||||
<HeaderButton.Download testID='save-image' onPress={this.handleSave} color={themes[theme!].previewTintColor} />
|
<HeaderButton.Download testID='save-image' onPress={handleSave} color={colors.previewTintColor} />
|
||||||
) : null,
|
) : null,
|
||||||
headerBackground: () => (
|
headerBackground: () => (
|
||||||
<HeaderBackground style={{ backgroundColor: themes[theme!].previewBackground, shadowOpacity: 0, elevation: 0 }} />
|
<HeaderBackground style={{ backgroundColor: colors.previewBackground, shadowOpacity: 0, elevation: 0 }} />
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
navigation.setOptions(options);
|
navigation.setOptions(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
getVideoRef = (ref: Video) => (this.videoRef = ref);
|
React.useLayoutEffect(() => {
|
||||||
|
setHeader();
|
||||||
|
}, [navigation]);
|
||||||
|
|
||||||
handleSave = async () => {
|
const handleSave = async () => {
|
||||||
const { attachment } = this.state;
|
|
||||||
const { user, baseUrl } = this.props;
|
|
||||||
const { title_link, image_url, image_type, video_url, video_type } = attachment;
|
const { title_link, image_url, image_type, video_url, video_type } = attachment;
|
||||||
const url = title_link || image_url || video_url;
|
const url = title_link || image_url || video_url;
|
||||||
|
|
||||||
|
@ -133,7 +164,7 @@ class AttachmentView extends React.Component<IAttachmentViewProps, IAttachmentVi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ loading: true });
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const extension = image_url
|
const extension = image_url
|
||||||
? `.${mime.extension(image_type) || 'jpg'}`
|
? `.${mime.extension(image_type) || 'jpg'}`
|
||||||
|
@ -141,77 +172,24 @@ class AttachmentView extends React.Component<IAttachmentViewProps, IAttachmentVi
|
||||||
// The return of mime.extension('video/quicktime') is .qt,
|
// The return of mime.extension('video/quicktime') is .qt,
|
||||||
// this format the iOS isn't recognize and can't save on gallery
|
// this format the iOS isn't recognize and can't save on gallery
|
||||||
const documentDir = `${RNFetchBlob.fs.dirs.DocumentDir}/`;
|
const documentDir = `${RNFetchBlob.fs.dirs.DocumentDir}/`;
|
||||||
const path = `${documentDir + sha256(url!) + extension}`;
|
const path = `${documentDir + sha256(url) + extension}`;
|
||||||
const file = await RNFetchBlob.config({ path }).fetch('GET', mediaAttachment);
|
const file = await RNFetchBlob.config({ path }).fetch('GET', mediaAttachment);
|
||||||
await CameraRoll.save(path, { album: 'Rocket.Chat' });
|
await CameraRoll.save(path, { album: 'Rocket.Chat' });
|
||||||
await file.flush();
|
file.flush();
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t('saved_to_gallery') });
|
EventEmitter.emit(LISTENER, { message: I18n.t('saved_to_gallery') });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t(image_url ? 'error-save-image' : 'error-save-video') });
|
EventEmitter.emit(LISTENER, { message: I18n.t(image_url ? 'error-save-image' : 'error-save-video') });
|
||||||
}
|
}
|
||||||
this.setState({ loading: false });
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderImage = (uri: string) => {
|
return (
|
||||||
const { width, height, insets } = this.props;
|
<View style={{ backgroundColor: colors.backgroundColor, flex: 1 }}>
|
||||||
return (
|
<StatusBar barStyle='light-content' backgroundColor={colors.previewBackground} />
|
||||||
<HeaderHeightContext.Consumer>
|
<RenderContent attachment={attachment} setLoading={setLoading} />
|
||||||
{headerHeight => (
|
{loading ? <RCActivityIndicator absolute size='large' /> : null}
|
||||||
<ImageViewer
|
</View>
|
||||||
uri={uri}
|
|
||||||
onLoadEnd={() => this.setState({ loading: false })}
|
|
||||||
width={width!}
|
|
||||||
height={height! - insets!.top - insets!.bottom - (headerHeight || 0)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</HeaderHeightContext.Consumer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
renderVideo = (uri: string) => (
|
|
||||||
<Video
|
|
||||||
source={{ uri }}
|
|
||||||
rate={1.0}
|
|
||||||
volume={1.0}
|
|
||||||
isMuted={false}
|
|
||||||
resizeMode={ResizeMode.CONTAIN}
|
|
||||||
shouldPlay
|
|
||||||
isLooping={false}
|
|
||||||
style={styles.container}
|
|
||||||
useNativeControls
|
|
||||||
onLoad={() => this.setState({ loading: false })}
|
|
||||||
onError={console.log}
|
|
||||||
ref={this.getVideoRef}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
export default AttachmentView;
|
||||||
const { loading, attachment } = this.state;
|
|
||||||
const { theme, user, baseUrl } = this.props;
|
|
||||||
let content = null;
|
|
||||||
|
|
||||||
if (attachment && attachment.image_url) {
|
|
||||||
const uri = formatAttachmentUrl(attachment.title_link || attachment.image_url, user.id, user.token, baseUrl);
|
|
||||||
content = this.renderImage(encodeURI(uri));
|
|
||||||
} else if (attachment && attachment.video_url) {
|
|
||||||
const uri = formatAttachmentUrl(attachment.video_url, user.id, user.token, baseUrl);
|
|
||||||
content = this.renderVideo(encodeURI(uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[styles.container, { backgroundColor: themes[theme!].backgroundColor }]}>
|
|
||||||
<StatusBar barStyle='light-content' backgroundColor={themes[theme!].previewBackground} />
|
|
||||||
{content}
|
|
||||||
{loading ? <RCActivityIndicator absolute size='large' /> : null}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapStateToProps = (state: IApplicationState) => ({
|
|
||||||
baseUrl: state.server.server,
|
|
||||||
user: getUserSelector(state),
|
|
||||||
Allow_Save_Media_to_Gallery: (state.settings.Allow_Save_Media_to_Gallery as boolean) ?? true
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(withDimensions(withSafeAreaInsets(AttachmentView))));
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
ICustomEmoji
|
ICustomEmoji
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
|
import { TNavigation } from '../../stacks/stackType';
|
||||||
|
|
||||||
interface IMessagesViewProps {
|
interface IMessagesViewProps {
|
||||||
user: {
|
user: {
|
||||||
|
@ -43,7 +44,7 @@ interface IMessagesViewProps {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
navigation: CompositeNavigationProp<
|
navigation: CompositeNavigationProp<
|
||||||
StackNavigationProp<ChatsStackParamList, 'MessagesView'>,
|
StackNavigationProp<ChatsStackParamList, 'MessagesView'>,
|
||||||
StackNavigationProp<MasterDetailInsideStackParamList>
|
StackNavigationProp<MasterDetailInsideStackParamList & TNavigation>
|
||||||
>;
|
>;
|
||||||
route: RouteProp<ChatsStackParamList, 'MessagesView'>;
|
route: RouteProp<ChatsStackParamList, 'MessagesView'>;
|
||||||
customEmojis: { [key: string]: ICustomEmoji };
|
customEmojis: { [key: string]: ICustomEmoji };
|
||||||
|
|
|
@ -39,6 +39,7 @@ import {
|
||||||
ICustomEmoji
|
ICustomEmoji
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
|
import { TNavigation } from '../../stacks/stackType';
|
||||||
|
|
||||||
const QUERY_SIZE = 50;
|
const QUERY_SIZE = 50;
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ export interface IRoomInfoParam {
|
||||||
interface INavigationOption {
|
interface INavigationOption {
|
||||||
navigation: CompositeNavigationProp<
|
navigation: CompositeNavigationProp<
|
||||||
StackNavigationProp<ChatsStackParamList, 'SearchMessagesView'>,
|
StackNavigationProp<ChatsStackParamList, 'SearchMessagesView'>,
|
||||||
StackNavigationProp<InsideStackParamList>
|
StackNavigationProp<InsideStackParamList & TNavigation>
|
||||||
>;
|
>;
|
||||||
route: RouteProp<ChatsStackParamList, 'SearchMessagesView'>;
|
route: RouteProp<ChatsStackParamList, 'SearchMessagesView'>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue