aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/assets/images/mute.pngbin0 -> 1560 bytes
-rw-r--r--src/assets/images/unmute.pngbin0 -> 1279 bytes
-rw-r--r--src/components/common/BadgeDetailView.tsx2
-rw-r--r--src/components/messages/ChannelPreview.tsx144
-rw-r--r--src/components/profile/Content.tsx8
-rw-r--r--src/components/profile/ProfileHeader.tsx7
-rw-r--r--src/components/taggs/Tagg.tsx20
-rw-r--r--src/routes/Routes.tsx4
-rw-r--r--src/routes/main/MainStackScreen.tsx47
-rw-r--r--src/screens/chat/ChatScreen.tsx1
-rw-r--r--src/screens/suggestedPeople/SuggestedPeopleScreen.tsx9
-rw-r--r--src/services/FCMService.ts8
12 files changed, 159 insertions, 91 deletions
diff --git a/src/assets/images/mute.png b/src/assets/images/mute.png
new file mode 100644
index 00000000..b330e259
--- /dev/null
+++ b/src/assets/images/mute.png
Binary files differ
diff --git a/src/assets/images/unmute.png b/src/assets/images/unmute.png
new file mode 100644
index 00000000..7fe1782d
--- /dev/null
+++ b/src/assets/images/unmute.png
Binary files differ
diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx
index 32cc7aa4..437b1914 100644
--- a/src/components/common/BadgeDetailView.tsx
+++ b/src/components/common/BadgeDetailView.tsx
@@ -78,7 +78,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
setTimeout(() => {
setSelectedBadgesWithImage(badgesWithImage);
setIsLoading(false);
- }, 500);
+ }, 250);
}, [selectedBadges]);
const removeBadgeCell = async (badge: string) => {
diff --git a/src/components/messages/ChannelPreview.tsx b/src/components/messages/ChannelPreview.tsx
index 8bd3a745..3d31d42a 100644
--- a/src/components/messages/ChannelPreview.tsx
+++ b/src/components/messages/ChannelPreview.tsx
@@ -1,10 +1,15 @@
import {useNavigation} from '@react-navigation/core';
-import React, {useContext} from 'react';
+import React, {useContext, useState} from 'react';
import {Image, StyleSheet, Text, View} from 'react-native';
-import {TouchableOpacity} from 'react-native-gesture-handler';
+import {
+ RectButton,
+ Swipeable,
+ TouchableOpacity,
+} from 'react-native-gesture-handler';
import {useStore} from 'react-redux';
import {ChannelPreviewMessengerProps} from 'stream-chat-react-native';
import {ChatContext} from '../../App';
+import Trash from '../../assets/ionicons/trash-outline.svg';
import {TAGG_LIGHT_BLUE_2} from '../../constants';
import {
LocalAttachmentType,
@@ -36,41 +41,79 @@ const ChannelPreview: React.FC<
const member = getMember(channel, state);
const online = isOnline(member?.user?.last_active);
const unread = channel.state.unreadCount > 0;
+ const [isMuted, setIsMuted] = useState(channel.muteStatus().muted);
+ const mutedImage = isMuted
+ ? require('../../assets/images/unmute.png')
+ : require('../../assets/images/mute.png');
+
+ // Hide channel if no message was exchanged
+ if (channel.state.messages.length === 0) {
+ return null;
+ }
return (
- <TouchableOpacity
- style={styles.container}
- onPress={() => {
- setChannel(channel);
- navigation.navigate('Chat');
- }}>
- <View>
- <Image
- style={styles.avatar}
- source={
- member
- ? {uri: member.user?.thumbnail_url}
- : require('../../assets/images/avatar-placeholder.png')
- }
- />
- {online && <View style={styles.online} />}
- </View>
- <View style={styles.content}>
- <Text
- style={[styles.name, unread ? styles.unread : {}]}
- numberOfLines={1}>
- {member?.user?.first_name} {member?.user?.last_name}
- </Text>
- <Text
- style={[styles.lastMessage, unread ? styles.unread : {}]}
- numberOfLines={1}>
- {channel.state.messages.length > 0
- ? channel.state.messages[channel.state.messages.length - 1].text
- : ''}
- </Text>
- </View>
- {unread && <View style={styles.purpleDot} />}
- </TouchableOpacity>
+ <Swipeable
+ overshootLeft={false}
+ overshootRight={false}
+ renderRightActions={() => (
+ <View style={styles.swipeableContainer}>
+ <RectButton
+ style={styles.muteButton}
+ onPress={() => {
+ if (isMuted) {
+ channel.unmute();
+ } else {
+ channel.mute();
+ }
+ setIsMuted(!isMuted);
+ }}>
+ <Image source={mutedImage} style={styles.icon} />
+ <Text style={styles.actionText}>{isMuted ? 'Unmute' : 'Mute'}</Text>
+ </RectButton>
+ <RectButton
+ style={styles.deleteButton}
+ onPress={() => {
+ channel.hide();
+ }}>
+ <Trash style={styles.icon} color={'white'} />
+ <Text style={styles.actionText}>Delete</Text>
+ </RectButton>
+ </View>
+ )}>
+ <TouchableOpacity
+ style={styles.container}
+ onPress={() => {
+ setChannel(channel);
+ navigation.navigate('Chat');
+ }}>
+ <View>
+ <Image
+ style={styles.avatar}
+ source={
+ member
+ ? {uri: member.user?.thumbnail_url}
+ : require('../../assets/images/avatar-placeholder.png')
+ }
+ />
+ {online && <View style={styles.online} />}
+ </View>
+ <View style={styles.content}>
+ <Text
+ style={[styles.name, unread ? styles.unread : {}]}
+ numberOfLines={1}>
+ {member?.user?.first_name} {member?.user?.last_name}
+ </Text>
+ <Text
+ style={[styles.lastMessage, unread ? styles.unread : {}]}
+ numberOfLines={1}>
+ {channel.state.messages.length > 0
+ ? channel.state.messages[channel.state.messages.length - 1].text
+ : ''}
+ </Text>
+ </View>
+ {unread && <View style={styles.purpleDot} />}
+ </TouchableOpacity>
+ </Swipeable>
);
};
@@ -128,6 +171,37 @@ const styles = StyleSheet.create({
borderRadius: normalize(10) / 2,
marginLeft: '5%',
},
+ swipeableContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexDirection: 'row',
+ },
+ muteButton: {
+ width: 72,
+ height: '100%',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#C4C4C4',
+ },
+ deleteButton: {
+ width: 72,
+ height: '100%',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#C42634',
+ },
+ actionText: {
+ color: 'white',
+ fontSize: normalize(12),
+ fontWeight: '500',
+ backgroundColor: 'transparent',
+ paddingHorizontal: '5%',
+ marginTop: '5%',
+ },
+ icon: {
+ width: normalize(25),
+ height: normalize(25),
+ },
});
export default ChannelPreview;
diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx
index c70d6df5..8298dc9a 100644
--- a/src/components/profile/Content.tsx
+++ b/src/components/profile/Content.tsx
@@ -145,7 +145,13 @@ const Content: React.FC<ContentProps> = ({userXId, screenType}) => {
<Cover {...{userXId, screenType}} />
<ProfileCutout />
<ProfileHeader
- {...{userXId, screenType, handleBlockUnblock, isBlocked}}
+ {...{
+ userXId,
+ screenType,
+ handleBlockUnblock,
+ isBlocked,
+ isPrivate: !canViewProfile(state, userXId, screenType),
+ }}
/>
<ProfileBody
{...{
diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx
index 90206f8d..82eda258 100644
--- a/src/components/profile/ProfileHeader.tsx
+++ b/src/components/profile/ProfileHeader.tsx
@@ -18,6 +18,7 @@ type ProfileHeaderProps = {
screenType: ScreenType;
isBlocked: boolean;
handleBlockUnblock: () => void;
+ isPrivate?: boolean;
};
const ProfileHeader: React.FC<ProfileHeaderProps> = ({
@@ -25,6 +26,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
screenType,
isBlocked,
handleBlockUnblock,
+ isPrivate,
}) => {
const {
profile: {name = '', university_class = 2021, university},
@@ -109,11 +111,9 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
<View style={styles.friendsAndUniversity}>
<FriendsCount screenType={screenType} userXId={userXId} />
-
<TouchableOpacity
- disabled={userId === loggedInUserId ? false : true}
onPress={() => {
- if (userId === loggedInUserId) {
+ if (!isPrivate) {
setBadgeViewVisible(true);
}
}}>
@@ -126,7 +126,6 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
university,
university_class,
needsShadow: true,
- // textStyle: getTextColor(),
}}
/>
)}
diff --git a/src/components/taggs/Tagg.tsx b/src/components/taggs/Tagg.tsx
index 94011e86..4a58bacb 100644
--- a/src/components/taggs/Tagg.tsx
+++ b/src/components/taggs/Tagg.tsx
@@ -1,31 +1,31 @@
import {useNavigation} from '@react-navigation/native';
import React, {Fragment, useState} from 'react';
import {Alert, Linking, StyleSheet, TouchableOpacity, View} from 'react-native';
+import {useSelector} from 'react-redux';
import PurpleRingPlus from '../../assets/icons/purple_ring+.svg';
import PurpleRing from '../../assets/icons/purple_ring.svg';
import RingPlus from '../../assets/icons/ring+.svg';
-import Ring from '../../assets/icons/ring.svg';
import WhiteRing from '../../assets/icons/ring-white.svg';
+import Ring from '../../assets/icons/ring.svg';
import {
INTEGRATED_SOCIAL_LIST,
SOCIAL_ICON_SIZE_ADJUSTMENT,
TAGG_RING_DIM,
} from '../../constants';
import {
+ ERROR_LINK,
+ ERROR_UNABLE_TO_FIND_PROFILE,
+ SUCCESS_LINK,
+} from '../../constants/strings';
+import {
getNonIntegratedURL,
handlePressForAuthBrowser,
registerNonIntegratedSocialLink,
} from '../../services';
-import {SmallSocialIcon, SocialIcon, SocialLinkModal} from '../common';
+import {RootState} from '../../store/rootReducer';
import {ScreenType, UserType} from '../../types';
-import {
- ERROR_LINK,
- ERROR_UNABLE_TO_FIND_PROFILE,
- SUCCESS_LINK,
-} from '../../constants/strings';
import {canViewProfile, normalize} from '../../utils';
-import {RootState} from '../../store/rootReducer';
-import {useStore} from 'react-redux';
+import {SmallSocialIcon, SocialIcon, SocialLinkModal} from '../common';
interface TaggProps {
social: string;
@@ -51,7 +51,7 @@ const Tagg: React.FC<TaggProps> = ({
whiteRing,
}) => {
const navigation = useNavigation();
- const state: RootState = useStore().getState();
+ const state = useSelector((s: RootState) => s);
const [modalVisible, setModalVisible] = useState(false);
const youMayPass = isLinked || userXId;
diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx
index 6fc766ab..384021bc 100644
--- a/src/routes/Routes.tsx
+++ b/src/routes/Routes.tsx
@@ -52,9 +52,9 @@ const Routes: React.FC = () => {
useEffect(() => {
if (userId) {
fcmService.setUpPushNotifications();
- fcmService.sendFcmTokenToServer();
+ fcmService.sendFcmTokenToServer(chatClient);
}
- }, []);
+ });
useEffect(() => {
if (loggedInUserId) {
diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx
index 37867151..f5100e58 100644
--- a/src/routes/main/MainStackScreen.tsx
+++ b/src/routes/main/MainStackScreen.tsx
@@ -1,7 +1,6 @@
-import AsyncStorage from '@react-native-community/async-storage';
import {RouteProp} from '@react-navigation/native';
import {StackNavigationOptions} from '@react-navigation/stack';
-import React, {useEffect, useState} from 'react';
+import React from 'react';
import {StyleSheet, Text} from 'react-native';
import {normalize} from 'react-native-elements';
import BackIcon from '../../assets/icons/back-arrow.svg';
@@ -56,28 +55,9 @@ interface MainStackProps {
const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
const {screenType} = route.params;
- // const isProfileTab = screenType === ScreenType.Profile;
const isSearchTab = screenType === ScreenType.Search;
const isNotificationsTab = screenType === ScreenType.Notifications;
const isSuggestedPeopleTab = screenType === ScreenType.SuggestedPeople;
- const [respondedToAccessContacts, setRespondedToAccessContacts] = useState(
- 'true',
- );
-
- useEffect(() => {
- loadResponseToAccessContacts();
- }, []);
-
- const loadResponseToAccessContacts = () => {
- AsyncStorage.getItem('respondedToAccessContacts')
- .then((value) => {
- setRespondedToAccessContacts(value ? value : 'false');
- })
- .catch((error) => {
- console.log('Something went wrong', error);
- setRespondedToAccessContacts('true');
- });
- };
const initialRouteName = (() => {
switch (screenType) {
@@ -131,20 +111,13 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
...headerBarOptions('white', ''),
}}
/>
- {isSuggestedPeopleTab &&
- (respondedToAccessContacts && respondedToAccessContacts === 'true' ? (
- <MainStack.Screen
- name="SuggestedPeople"
- component={SuggestedPeopleScreen}
- initialParams={{screenType}}
- />
- ) : (
- <MainStack.Screen
- name="SuggestedPeople"
- component={RequestContactsAccess}
- initialParams={{screenType}}
- />
- ))}
+ {isSuggestedPeopleTab && (
+ <MainStack.Screen
+ name="SuggestedPeople"
+ component={SuggestedPeopleScreen}
+ initialParams={{screenType}}
+ />
+ )}
{isNotificationsTab && (
<MainStack.Screen
name="Notifications"
@@ -271,6 +244,10 @@ const MainStackScreen: React.FC<MainStackProps> = ({route}) => {
name="RequestContactsAccess"
component={RequestContactsAccess}
initialParams={{screenType}}
+ options={{
+ ...modalStyle,
+ gestureEnabled: false,
+ }}
/>
<MainStack.Screen
name="EditProfile"
diff --git a/src/screens/chat/ChatScreen.tsx b/src/screens/chat/ChatScreen.tsx
index 57f2232e..5874b8b6 100644
--- a/src/screens/chat/ChatScreen.tsx
+++ b/src/screens/chat/ChatScreen.tsx
@@ -154,7 +154,6 @@ const ChatScreen: React.FC<ChatScreenProps> = () => {
myMessageTheme={loggedInUsersMessageTheme}
MessageAvatar={MessageAvatar}>
<MessageList onThreadSelect={() => {}} />
- {/* <MessageInput /> */}
<MessageInput Input={ChatInput} />
</Channel>
</Chat>
diff --git a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
index 388a1ba7..f1981111 100644
--- a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
+++ b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx
@@ -1,3 +1,4 @@
+import AsyncStorage from '@react-native-community/async-storage';
import {useFocusEffect, useNavigation} from '@react-navigation/native';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {FlatList, RefreshControl, StatusBar, ViewToken} from 'react-native';
@@ -57,6 +58,14 @@ const SuggestedPeopleScreen: React.FC = () => {
const stausBarRef = useRef(hideStatusBar);
+ useEffect(() => {
+ AsyncStorage.getItem('respondedToAccessContacts').then((value) => {
+ if (value === null) {
+ navigation.navigate('RequestContactsAccess');
+ }
+ });
+ }, []);
+
// loads data and append it to users based on current page
useEffect(() => {
loadMore();
diff --git a/src/services/FCMService.ts b/src/services/FCMService.ts
index 84f30f09..711483ec 100644
--- a/src/services/FCMService.ts
+++ b/src/services/FCMService.ts
@@ -2,8 +2,10 @@ import AsyncStorage from '@react-native-community/async-storage';
import messaging from '@react-native-firebase/messaging';
import {Platform} from 'react-native';
import {getDeviceId, getDeviceName} from 'react-native-device-info';
+import {StreamChat} from 'stream-chat';
import {FCM_ENDPOINT} from '../constants';
import * as RootNavigation from '../RootNavigation';
+
class FCMService {
setUpPushNotifications = () => {
// Requesting user to permit notifications
@@ -78,10 +80,13 @@ class FCMService {
return '';
};
- sendFcmTokenToServer = async () => {
+ sendFcmTokenToServer = async (chatClient: StreamChat) => {
const registration_id: string | null = await AsyncStorage.getItem(
'@fcmToken',
);
+ if (registration_id !== null) {
+ chatClient.addDevice(registration_id, 'firebase');
+ }
const device_id = getDeviceId();
const type = Platform.OS;
let active: boolean = false;
@@ -117,7 +122,6 @@ class FCMService {
console.log('Successfully stored device token!');
} else {
console.log('Failed to store device token!');
- console.log(response);
}
}
};