123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- import React, { FC, useEffect, useState } from 'react';
- import { ScrollView, Text, TouchableOpacity, View, Image, StyleSheet } from 'react-native';
- import { NavigationProp } from '@react-navigation/native';
- import ImageView from 'react-native-image-viewing';
- import { storage, StoreType } from 'src/storage';
- import {
- PageWrapper,
- Header,
- Loading,
- Input,
- AvatarWithInitials,
- WarningModal
- } from 'src/components';
- import {
- usePostGetGroupMembersQuery,
- usePostGetGroupSettingsQuery,
- usePostLeaveGroupMutation,
- usePostRemoveGroupFromListMutation,
- usePostSetMuteForGroupMutation
- } from '@api/chat';
- import { Colors } from 'src/theme';
- import { API_HOST } from 'src/constants';
- import GroupIcon from 'assets/icons/messages/group-chat.svg';
- import { getFontSize } from 'src/utils';
- import ExitIcon from 'assets/icons/messages/exit.svg';
- import TrashIcon from 'assets/icons/travels-screens/trash-solid.svg';
- import BellSlashIcon from 'assets/icons/messages/bell-slash.svg';
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
- import EditIcon from 'assets/icons/travels-screens/pen-to-square.svg';
- import UserPlusIcon from 'assets/icons/user-plus.svg';
- import { NAVIGATION_PAGES } from 'src/types';
- import { SheetManager } from 'react-native-actions-sheet';
- import EditGroupModal from '../Components/EditGroupModal';
- type Props = {
- navigation: NavigationProp<any>;
- route: any;
- };
- const GroupSettingScreen: FC<Props> = ({ navigation, route }) => {
- const token = storage.get('token', StoreType.STRING) as string;
- const groupToken = route.params.groupToken;
- const insets = useSafeAreaInsets();
- const [canSeeMembers, setCanSeeMembers] = useState(false);
- const { data, refetch } = usePostGetGroupSettingsQuery(token, groupToken, true);
- const { data: members, refetch: refetchMembers } = usePostGetGroupMembersQuery(
- token,
- groupToken,
- canSeeMembers
- );
- const [fullSizeImageVisible, setFullSizeImageVisible] = useState(false);
- const [muted, setMuted] = useState(false);
- const [modalState, setModalState] = useState({
- isWarningVisible: false,
- title: '',
- buttonTitle: '',
- message: '',
- action: () => {}
- });
- const { mutateAsync: muteGroup } = usePostSetMuteForGroupMutation();
- const { mutateAsync: leaveGroup } = usePostLeaveGroupMutation();
- const { mutateAsync: removeGroupFromList } = usePostRemoveGroupFromListMutation();
- useEffect(() => {
- if (data && data.settings) {
- setCanSeeMembers(data.settings.members_can_see_members === 1 || data.settings.admin === 1);
- setMuted(data.settings.muted === 1);
- }
- }, [data]);
- const handleMute = async () => {
- await muteGroup(
- {
- token,
- value: muted ? 0 : 1,
- group_token: groupToken
- },
- {
- onSuccess: () => {
- setMuted(!muted);
- }
- }
- );
- };
- const handleLeaveGroup = async () => {
- if (!data) return;
- setModalState({
- isWarningVisible: true,
- title: `Leave group ${data.settings.name}`,
- buttonTitle: 'Leave',
- message: `Are you sure you want to leave ${data.settings.name}?`,
- action: async () => {
- await leaveGroup(
- {
- token,
- group_token: groupToken
- },
- {
- onSuccess: () => {
- navigation.navigate(NAVIGATION_PAGES.CHATS_LIST);
- }
- }
- );
- }
- });
- };
- const handleDeleteGroup = async () => {
- if (!data) return;
- setModalState({
- isWarningVisible: true,
- title: `Delete ${data.settings.name}`,
- buttonTitle: 'Delete',
- message: `Are you sure you want to delete this group chat?\nThis action will remove the chat from your history, but it won't affect other participants.`,
- action: async () => {
- await removeGroupFromList(
- {
- token,
- group_token: groupToken
- },
- {
- onSuccess: () => {
- navigation.navigate(NAVIGATION_PAGES.CHATS_LIST);
- }
- }
- );
- }
- });
- };
- const openEditModal = () => {
- if (!data) return;
- SheetManager.show('edit-group-modal', {
- payload: {
- settings: data.settings,
- members: data.settings.admin === 1 ? members?.settings : [],
- token,
- groupToken,
- refetch,
- refetchMembers
- }
- });
- };
- if (!data) return <Loading />;
- return (
- <PageWrapper>
- <Header
- label={data.settings.name}
- rightElement={
- data.settings.members_can_edit_settings === 1 || data.settings.admin === 1 ? (
- <TouchableOpacity style={{ padding: 6 }} onPress={openEditModal}>
- <EditIcon fill={Colors.DARK_BLUE} width={18} height={18} />
- </TouchableOpacity>
- ) : null
- }
- />
- <ScrollView
- showsVerticalScrollIndicator={false}
- style={{ flex: 1 }}
- contentContainerStyle={{
- paddingBottom: insets.bottom,
- justifyContent: 'space-between',
- flex: 1
- }}
- >
- <View style={{ gap: 16 }}>
- <View style={styles.photoContainer}>
- <TouchableOpacity
- style={styles.photoContainer}
- onPress={() => setFullSizeImageVisible(true)}
- disabled={!data.settings.avatar}
- >
- {!data.settings.avatar ? (
- <GroupIcon width={80} height={80} fill={Colors.LIGHT_GRAY} />
- ) : (
- <Image
- source={{ uri: API_HOST + data.settings.avatar }}
- style={{
- width: 80,
- height: 80,
- borderRadius: 40,
- borderWidth: 1,
- borderColor: Colors.FILL_LIGHT
- }}
- />
- )}
- </TouchableOpacity>
- <Text style={styles.bigText}>{data.settings.name}</Text>
- <Text style={{ fontSize: getFontSize(12), fontWeight: '600', color: Colors.DARK_BLUE }}>
- {data.settings.member_count} nomads
- </Text>
- </View>
- {data.settings.description && (
- <Input
- editable={false}
- value={data.settings.description}
- header="Description"
- multiline
- height={58}
- />
- )}
- {canSeeMembers && members ? (
- <View style={{ gap: 8, marginBottom: 16 }}>
- <View
- style={{
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center'
- }}
- >
- <Text style={styles.title}>{members.settings.length} nomads</Text>
- {data.settings.members_can_add_new_members === 1 || data.settings.admin === 1 ? (
- <TouchableOpacity style={{ padding: 6, paddingRight: 0 }}>
- <UserPlusIcon fill={Colors.ORANGE} height={18} width={23} />
- </TouchableOpacity>
- ) : null}
- </View>
- <View style={{ gap: 6 }}>
- {(data.settings.member_count > 4
- ? members.settings.slice(0, 4)
- : members.settings
- ).map((member, index) => (
- <TouchableOpacity key={index} style={styles.userItem} onPress={() => {}}>
- {member.avatar ? (
- <Image source={{ uri: API_HOST + member.avatar }} style={styles.avatar} />
- ) : (
- <AvatarWithInitials
- text={`${member.name?.split(' ')[0][0]}${member.name?.split(' ')[1][0]}`}
- flag={API_HOST + member?.flag}
- size={36}
- fontSize={16}
- borderColor={Colors.LIGHT_GRAY}
- borderWidth={1}
- />
- )}
- <View style={{ flex: 1 }}>
- <Text style={styles.userName}>{member.name}</Text>
- </View>
- <View style={{ justifyContent: 'center', alignItems: 'center' }}>
- {member.admin === 1 && (
- <Text
- style={{
- fontSize: getFontSize(10),
- fontWeight: '600',
- color: Colors.LIGHT_GRAY
- }}
- >
- Admin
- </Text>
- )}
- </View>
- </TouchableOpacity>
- ))}
- {data.settings.member_count > 4 ? (
- <TouchableOpacity style={{ padding: 8, alignItems: 'center' }}>
- <Text
- style={{
- color: Colors.DARK_BLUE,
- fontSize: getFontSize(12),
- fontWeight: '700'
- }}
- >
- All nomads...
- </Text>
- </TouchableOpacity>
- ) : null}
- </View>
- </View>
- ) : null}
- </View>
- <View style={{ gap: 16 }}>
- <View style={styles.optionsContainer}>
- <TouchableOpacity style={styles.option} onPress={handleMute}>
- <Text style={styles.optionText}>{muted ? 'Unmute' : 'Mute'}</Text>
- <BellSlashIcon fill={Colors.DARK_BLUE} />
- </TouchableOpacity>
- </View>
- <View style={[styles.optionsContainer, { paddingVertical: 0, gap: 0 }]}>
- <TouchableOpacity
- style={[styles.option, styles.dangerOption]}
- onPress={handleLeaveGroup}
- >
- <Text style={[styles.optionText, styles.dangerText]}>Leave group chat</Text>
- <ExitIcon fill={Colors.RED} width={16} />
- </TouchableOpacity>
- <TouchableOpacity
- style={[styles.option, styles.dangerOption]}
- onPress={handleDeleteGroup}
- >
- <Text style={[styles.optionText, styles.dangerText]}>Delete group chat</Text>
- <TrashIcon fill={Colors.RED} width={18} height={18} />
- </TouchableOpacity>
- </View>
- </View>
- </ScrollView>
- <WarningModal
- type={'delete'}
- isVisible={modalState.isWarningVisible}
- buttonTitle={modalState.buttonTitle}
- message={modalState.message}
- action={modalState.action}
- onClose={() => setModalState({ ...modalState, isWarningVisible: false })}
- title={modalState.title}
- />
- <ImageView
- images={[{ uri: API_HOST + data.settings.avatar_full }]}
- keyExtractor={(imageSrc, index) => index.toString()}
- imageIndex={0}
- visible={fullSizeImageVisible}
- onRequestClose={() => setFullSizeImageVisible(false)}
- swipeToCloseEnabled={false}
- backgroundColor={Colors.DARK_BLUE}
- doubleTapToZoomEnabled={true}
- />
- <EditGroupModal />
- </PageWrapper>
- );
- };
- const styles = StyleSheet.create({
- photoContainer: {
- alignItems: 'center',
- gap: 8
- },
- groupPhoto: {
- width: 80,
- height: 80,
- borderRadius: 40,
- alignItems: 'center',
- justifyContent: 'center'
- },
- bigText: {
- color: Colors.DARK_BLUE,
- fontSize: getFontSize(18),
- fontFamily: 'montserrat-700'
- },
- userItem: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingVertical: 8,
- paddingHorizontal: 12,
- backgroundColor: Colors.FILL_LIGHT,
- gap: 8,
- borderRadius: 8
- },
- avatar: {
- width: 36,
- height: 36,
- borderRadius: 18,
- borderWidth: 1,
- borderColor: Colors.LIGHT_GRAY
- },
- userName: {
- color: Colors.DARK_BLUE,
- fontSize: getFontSize(14),
- fontFamily: 'montserrat-700'
- },
- title: {
- color: Colors.DARK_BLUE,
- fontSize: getFontSize(14),
- fontFamily: 'redhat-700'
- },
- optionsContainer: {
- paddingVertical: 10,
- paddingHorizontal: 8,
- gap: 16,
- borderRadius: 8,
- backgroundColor: Colors.FILL_LIGHT
- },
- option: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between'
- },
- optionText: {
- fontSize: getFontSize(12),
- fontWeight: '600',
- color: Colors.DARK_BLUE
- },
- dangerOption: {
- paddingVertical: 10,
- borderBottomWidth: 1,
- borderBlockColor: Colors.WHITE
- },
- dangerText: {
- color: Colors.RED
- }
- });
- export default GroupSettingScreen;
|