Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: AmityCo/Amity-Chat-UIKit-React-Native-CLI-OpenSource
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: AmityCo/Amity-Chat-UIKit-React-Native-OpenSource
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 7 commits
  • 20 files changed
  • 1 contributor

Commits on Apr 22, 2024

  1. fix ui padding chatroom

    topAmity committed Apr 22, 2024
    Copy the full SHA
    1c919a9 View commit details
  2. improve send message

    topAmity committed Apr 22, 2024
    Copy the full SHA
    f579ca7 View commit details

Commits on May 10, 2024

  1. Copy the full SHA
    607fc38 View commit details

Commits on May 11, 2024

  1. Copy the full SHA
    b77065e View commit details

Commits on May 15, 2024

  1. Copy the full SHA
    1c92e04 View commit details
  2. Merge pull request #5 from AmityCo/add-profile-image-recent-chat

    Add profile image recent chat, promote members
    topAmity authored May 15, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    7b05a70 View commit details

Commits on May 16, 2024

  1. prevent avatar null

    topAmity committed May 16, 2024
    Copy the full SHA
    74026f3 View commit details
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@amityco/react-native-chat-ui-kit",
"version": "0.2.0",
"version": "0.3.0",
"description": "chat uikit for react native",
"main": "lib/commonjs/index",
"module": "lib/module/index",
@@ -171,7 +171,7 @@
]
},
"dependencies": {
"@amityco/ts-sdk-react-native": "^6.19.0",
"@amityco/ts-sdk-react-native": "6.19.0",
"expo-constants": "^14.2.1",
"expo-image-picker": "^14.7.1",
"expo-modules-core": "^1.11.8",
17 changes: 9 additions & 8 deletions src/components/AddMembersModal/index.tsx
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import { SearchIcon } from '../../svg/SearchIcon';
import { CircleCloseIcon } from '../../svg/CircleCloseIcon';
import { useTheme } from 'react-native-paper';
import type { MyMD3Theme } from '../../providers/amity-ui-kit-provider';
import useAuth from '../../hooks/useAuth';
interface IModal {
visible: boolean;
userId?: string;
@@ -34,12 +35,13 @@ export type SelectUserList = {
};
const AddMembersModal = ({ visible, onClose, onFinish, initUserList = [] }: IModal) => {
const theme = useTheme() as MyMD3Theme;
const styles =useStyles();
const styles = useStyles();
const [sectionedUserList, setSectionedUserList] = useState<UserInterface[]>(initUserList);
const [selectedUserList, setSelectedUserList] = useState<UserInterface[]>(initUserList);
const [usersObject, setUsersObject] = useState<Amity.LiveCollection<Amity.User>>();
const [searchTerm, setSearchTerm] = useState('');
const [isShowSectionHeader, setIsShowSectionHeader] = useState<boolean>(false)
const { client } = useAuth()
const { data: userArr = [], onNextPage } = usersObject ?? {};


@@ -128,10 +130,9 @@ const AddMembersModal = ({ visible, onClose, onFinish, initUserList = [] }: IMod


return (
<View>
<View style={styles.sectionItem}>
{isrenderheader && <SectionHeader title={currentLetter} />}

<UserItem showThreeDot={false} user={userObj} isCheckmark={selectedUser} onPress={onUserPressed} />
<UserItem isUserAccount={(client as Amity.Client).userId === userObj.userId ? true : false} showThreeDot={false} user={userObj} isCheckmark={selectedUser} onPress={onUserPressed} />
</View>

);
@@ -187,17 +188,17 @@ const AddMembersModal = ({ visible, onClose, onFinish, initUserList = [] }: IMod
<Text style={[selectedUserList.length > 0 ? styles.doneText : styles.disabledDone]}>Done</Text>
</TouchableOpacity>
</View>
<View style={styles.inputWrap}>
<View style={styles.inputWrap}>
<TouchableOpacity onPress={() => queryAccounts(searchTerm)}>
<SearchIcon color={theme.colors.base}/>
<SearchIcon color={theme.colors.base} />
</TouchableOpacity>
<TextInput
style={styles.input}
value={searchTerm}
onChangeText={handleChange}
/>
<TouchableOpacity onPress={clearButton}>
<CircleCloseIcon color={theme.colors.base}/>
<CircleCloseIcon color={theme.colors.base} />
</TouchableOpacity>
</View>
{selectedUserList.length > 0 ? (
@@ -219,7 +220,7 @@ const AddMembersModal = ({ visible, onClose, onFinish, initUserList = [] }: IMod
ref={flatListRef}
onScroll={handleScroll}
/>
</View>
</View>
</Modal>
);
};
4 changes: 4 additions & 0 deletions src/components/AddMembersModal/styles.ts
Original file line number Diff line number Diff line change
@@ -78,6 +78,10 @@ export const useStyles = () => {
disabledDone: {
opacity: 0.5
},
sectionItem: {
flex: 1
}

});
return styles;
}
20 changes: 17 additions & 3 deletions src/components/ChatList/index.tsx
Original file line number Diff line number Diff line change
@@ -43,8 +43,12 @@ const ChatList: React.FC<IChatListProps> = ({
const { client, apiRegion } = useAuth();
const [oneOnOneChatObject, setOneOnOneChatObject] = useState<Amity.Membership<'channel'>[]>();
const [groupChatObject, setGroupChatObject] = useState<Amity.Membership<'channel'>[]>();
const [channelAvatarFileId, setChannelAvatarFileId] = useState<string | undefined>(avatarFileId)
const [channelDisplayName, setChannelDisplayName] = useState<string>(chatName)

const styles = useStyles();


const handlePress = (
chatMemberNumber: number
) => {
@@ -101,6 +105,16 @@ const ChatList: React.FC<IChatListProps> = ({
);
}, [])

useEffect(() => {
if (oneOnOneChatObject) {
const targetIndex: number = oneOnOneChatObject?.findIndex(
(item) => item.userId !== (client as Amity.Client).userId
);
setChannelAvatarFileId(oneOnOneChatObject[targetIndex]?.user?.avatarFileId ?? avatarFileId)
setChannelDisplayName(oneOnOneChatObject[targetIndex]?.user?.displayName as string)
}
}, [oneOnOneChatObject])


return (

@@ -111,11 +125,11 @@ const ChatList: React.FC<IChatListProps> = ({
<View style={styles.avatarSection}>


{avatarFileId ? <Image
{channelAvatarFileId ? <Image
style={styles.icon}
source={
{
uri: `https://api.${apiRegion}.amity.co/api/v3/files/${avatarFileId}/download?size=small`,
uri: `https://api.${apiRegion}.amity.co/api/v3/files/${channelAvatarFileId}/download?size=small`,
}
}
/> : <View style={styles.icon}>
@@ -129,7 +143,7 @@ const ChatList: React.FC<IChatListProps> = ({
<View style={styles.chatDetailSection}>
<View style={styles.chatNameWrap}>
<CustomText style={styles.chatName} numberOfLines={1}>
{chatName}
{channelDisplayName}
</CustomText>
<CustomText style={styles.chatLightText}>
({chatMemberNumber})
6 changes: 3 additions & 3 deletions src/components/LoadingImage/index.tsx
Original file line number Diff line number Diff line change
@@ -42,14 +42,14 @@ const LoadingImage = ({

const uploadFileToAmity = useCallback(async () => {

if (!isFinish ) {
if (!isFinish) {
const file: Amity.File<any>[] = await uploadImageFile(
source,
(percent: number) => {
setProgress(percent);
console.log('percent:', percent)

},
true
false

);
if (file) {
188 changes: 188 additions & 0 deletions src/components/MemberActionModal/MemberActionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import {
Alert,
Animated,
Modal,
Pressable,
Text,
type TextStyle,
TouchableOpacity,
} from 'react-native';
import React, {
type FC,
memo,
useCallback,
useEffect,
useMemo,
useRef,
} from 'react';
import { useStyles } from './styles';
import { ChannelRepository, createReport } from '@amityco/ts-sdk-react-native';
import useAuth from './../../hooks/useAuth';

interface IMemberActionModal {
isVisible: boolean;
setIsVisible: (isVisible: boolean) => void;
userId: string;
channelId: string;
hasModeratorPermission?: boolean;
isInModeratorTab?: boolean;
isChannelModerator?: boolean;
onFinish?:()=> void;
}

const MemberActionModal: FC<IMemberActionModal> = ({
isVisible,
setIsVisible,
userId,
channelId,
hasModeratorPermission,
isInModeratorTab,
isChannelModerator,
onFinish
}) => {
const styles = useStyles();
const slideAnimation = useRef(new Animated.Value(0)).current;
const { client } = useAuth() as { client: { userId: string } };
const currentUserId = client.userId ?? '';

async function addRole() {
const didAdd = await ChannelRepository.Moderation.addRole(channelId, 'channel-moderator', [
userId
]);
if (didAdd) {
Alert.alert('Promote to moderator ✅')
}
}

async function removeRole() {
const didRemove = await ChannelRepository.Moderation.removeRole(channelId, 'channel-moderator', [
userId
]);

if (didRemove) {
Alert.alert('Remove user from moderator')
}
}
const actionData = useMemo(
() => [
{
id: 'demote',
label: 'Dismiss to member',
shouldShow:
hasModeratorPermission &&
currentUserId !== userId &&
isInModeratorTab,
callBack: async () => {
removeRole()
onFinish && onFinish()
}

},
{
id: 'promote',
label: 'Promote to moderator',
shouldShow:
hasModeratorPermission &&
currentUserId !== userId &&
!isInModeratorTab && !isChannelModerator,
callBack: async () => {
addRole();
onFinish && onFinish();

}
},
{
id: 'report',
label: 'Report User',
shouldShow: currentUserId !== userId,
callBack: async () => {
const isReport = await createReport('user', userId)
if (isReport) {
Alert.alert('Report sent ✅')
onFinish && onFinish();
}
}
},

],
[
channelId,
currentUserId,
hasModeratorPermission,
isInModeratorTab,
userId,
]
);

const closeModal = useCallback(() => {
Animated.timing(slideAnimation, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start(() => setIsVisible(false));
}, [setIsVisible, slideAnimation]);

const onPressAction = useCallback(
async ({ callBack }) => {
try {
await callBack();
} catch (error) { }
closeModal();
},
[closeModal]
);

useEffect(() => {
if (isVisible) {
Animated.timing(slideAnimation, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
}
}, [isVisible, slideAnimation]);

const modalStyle = {
transform: [
{
translateY: slideAnimation.interpolate({
inputRange: [0, 1],
outputRange: [600, 0],
}),
},
],
};

return (
<Modal
animationType="fade"
transparent={true}
visible={isVisible}
onRequestClose={closeModal}
>
<Pressable onPress={closeModal} style={styles.modalContainer}>
<Animated.View style={[styles.modalContent, modalStyle]}>
{actionData.map((data) => {
const warningStyle: TextStyle | null =
data.id === 'remove' ? { color: 'red' } : null;
if (data.shouldShow) {
return (
<TouchableOpacity
key={data.id}
onPress={() => onPressAction(data)}
style={styles.modalRow}
>
<Text style={[styles.actionText, warningStyle]}>
{data.label}
</Text>
</TouchableOpacity>
);
} else return null;
})}
</Animated.View>
</Pressable>
</Modal>
);
};

export default memo(MemberActionModal);
Loading