Class

GroupsListHooksApi

GroupsListHooksApi()

Groups Index Hooks. Instance name: groupsListHooksApi

You can customize Group lists such as replacing list components, adding sub filters to the groups list and more with this hook.

Constructor

# new GroupsListHooksApi()

Example
externalCodeSetup.groupsListHooksApi.METHOD_NAME

Methods

# setActionsFilter(actionsFilter)

Sets the filter function for modifing group action buttons array

Parameters:
Name Type Description
actionsFilter TransformGroupActionsCallback
Example

Remove the "Leave" button

 externalCodeSetup.groupsListHooksApi.setActionsFilter(props => {

   let newButtons = props[1];
   delete newButtons.flow[1];

   return [
       ...props,
       newButtons
   ];

 })

# setFetchParamsFilter(fetchParamsFilter)

It overrides the parameters that are used to fetch groups in the Group screen so that you can make it as customizable as possible when calling its API.

Parameters:
Name Type Description
fetchParamsFilter TransformGroupsParams
Example

Create a custom filter in groups screen

//In components/GroupFiltersCustom.js...

import React, { useState } from "react";
import { TextInput, View, Button, Text, Switch } from 'react-native'
import { useDispatch } from "react-redux";
import { groupsRequested } from "@src/actions/socialGroups";
import { getExternalCodeSetup } from "@src/externalCode/externalRepo";
import withGlobalStyles from "@src/components/hocs/withGlobalStyles";

const hook = getExternalCodeSetup().groupsListHooksApi;

getExternalCodeSetup().indexScreenApiHooks.setHeaderHeight((defaultHeaderHeight, filterType, navigation) => {

   if (filterType === "groups")
     return 300;

   return defaultHeaderHeight;
 });

const screenName = "HomeGroupsScreen";

const filter = "all"; //"all", "personal", "my-groups", "invites"
const subfilters = {type: "active"}; // "active", "newest", "alphabetical", "popular";

const refresh = true; //Set to true to refresh list
const searchTerm = ""


const GroupFiltersCustom = (props) => {

   const { navigation, route, colors } = props;

   const dispatch = useDispatch();

   //If showing the matched screen, show custom filter before displaying list component
   if (navigation?.state?.routeName === screenName) {

       const [isEnabled, setIsEnabled] = useState(false);

       const toggleSwitch = () => setIsEnabled(previousState => !previousState)

       const handleSubmit = () => {

           //Set custom parameters before fetching
           hook.setFetchParamsFilter((props) => {

               //You can add more parameters such as "subject", "keyword" etc...
               return {
                   ...props,
                   show_hidden: isEnabled
               }
           })

           //Dispatch redux action to call api using customized filters
           dispatch(groupsRequested(filter, subfilters, refresh, searchTerm));

       }

       return <View style={{ backgroundColor: colors.whiteColor, flexDirection: "row", alignItems: "center", justifyContent: "center" }}>

           <Text>Show hidden groups?</Text>
           <Switch
               trackColor={{ false: "#767577", true: "#81b0ff" }}
               thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
               ios_backgroundColor="#3e3e3e"
               onValueChange={toggleSwitch}
               value={isEnabled}
           />
           <Button
               onPress={() => handleSubmit()}
               title="Filter"
           />
       </View>
   }

   return null;

}

export default withGlobalStyles(GroupFiltersCustom);

//In custom_code/index.js...

...

import GroupFiltersCustom from "./components/GroupFiltersCustom";
export const applyCustomCode = externalCodeSetup => {
   externalCodeSetup.filterScreenApiHooks.setAfterFilterComponent(GroupFiltersCustom);
}

# setGroupItemComponent(GroupItemComponentnullable)

It used to replace the default group item component in the groups list. For example, you can add a short description of the group or disable avatar to display in the list.

Parameters:
Name Type Attributes Description
GroupItemComponent React.ComponentType.<GroupItemComponentProps> <nullable>
Example

Add a short group description and remove avatar display.

//In custom_code/components/GroupItem.js...

import React from "react";
import {
   View,
   StyleSheet,
   Text,
   Image,
   TouchableOpacity,
} from "react-native";

//Import BuddyBoss components and helper functions...
import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
import { ItemTitle } from "@src/components/TextComponents";
import Icon from "@src/components/Icon";
import AuthWrapper from "@src/components/AuthWrapper";
import {
   groupInviteDescription,
   groupMembersCountTranslation,
   groupStatusTranslation,
} from "@src/utils";
import ActionButtonList from "@src/components/ActionButtons/ActionButtonList";
import GroupActionSheetWrapper from "@src/components/Group/GroupActionSheetWrapper";
import { GUTTER } from "@src/styles/global";
import FontManager from "@src/FontManager";
import { Typographies } from "@src/services/enums/branding";

const GroupItem = props => {
   const { item, global, colors, actions, userId, index, t, isInvite } = props;

   const styles = getStyles(colors);

   return (
       <AppTouchableOpacity
           onPress={item.onClick}
           style={[styles.item, index === 0 ? { paddingTop: 0 } : {}]}
       >
           <View
               style={[
                   global.row,
                   { justifyContent: "space-between", flex: 1, alignItems: "flex-start" }
               ]}
           >

               <View style={[global.bottomBorder, {
                   paddingBottom: 15, paddingBottom: 14,
                   marginLeft: 14,
                   flex: 1
               }]}>
                   //Group title
                   <ItemTitle global={global} style={{ marginBottom: 4 }}>
                       {item.title}
                   </ItemTitle>

                   //Show component depending on if user received invitation to join the group
                   {isInvite ? (
                       <View>
                           {groupInviteDescription(item, t, global, { marginBottom: 9 })}
                           {!!item.inviteMessage && <Text>{item.inviteMessage}</Text>}
                       </View>
                   ) : (
                       <View style={[global.row, {
                           flex: 1,
                           flexWrap: "wrap"
                       }]}>
                           <Text style={global.itemMeta}>
                               {groupStatusTranslation(t, item)}
                           </Text>
                           <View style={global.dotSep} />
                           <Text style={global.itemMeta}>
                               {groupMembersCountTranslation(t, item)}
                           </Text>
                       </View>
                   )}

                   <View style={{
                       marginTop: 16,
                       position: "relative"
                   }}>
                       <View style={{ alignItems: "flex-start" }}>

                           // Add short content
                           {item.shortContent != "" && <Text style={{ color: colors.labelTextColor, marginBottom: 10 }}> {item.shortContent} </Text> }

                           //Show a component depending on if user has already joined the group
                           {item.isMember && !isInvite ? (
                               <GroupActionSheetWrapper
                                   group={item}
                                   actionButtons={actions}
                                   {...{
                                       global,
                                       colors,
                                       t
                                   }}
                               >
                                   <View
                                       style={[
                                           global.wrappedButton,
                                           global.wrappedTextButton,
                                           global.row,
                                           { backgroundColor: colors.labelBgColor }
                                       ]}
                                   >
                                       <Icon
                                           icon={{fontIconName: "check", weight: 400}}
                                           tintColor={colors.labelTextColor}
                                           styles={{
                                               width: 16,
                                               height: 16,
                                               marginLeft: -2,
                                               marginRight: 4
                                           }}
                                           rtlStyleFix={"handled"}
                                       />
                                       <Text
                                           style={[
                                               global.wrappedTextButtonLabel,
                                               { color: colors.labelTextColor }
                                           ]}
                                       >
                                           {item.role}
                                       </Text>
                                   </View>
                               </GroupActionSheetWrapper>
                           ) : (
                               <AuthWrapper>
                                   <ActionButtonList
                                       hideIcons={true}
                                       actionButtons={actions}
                                       object={item}
                                       t={t}
                                       color={colors.labelTextColor}
                                       buttonStyle={({ label }) => ({
                                           ...(label.match(/acceptInvite/)
                                               ? styles.inviteAcceptButton
                                               : label.match(/cancelInvite/)
                                                   ? styles.inviteRejectButton
                                                   : { marginRight: 10 }),
                                           backgroundColor: colors.labelBgColor
                                       })}
                                       textStyle={({ label }, color) =>
                                           label.match(/acceptInvite/)
                                               ? {
                                                   ...global.boldText,
                                                   color
                                               }
                                               : label.match(/cancelInvite/)
                                                   ? { ...global.boldText, color: colors.warningColor }
                                                   : { ...global.boldText, color }
                                       }
                                   />
                               </AuthWrapper>
                           )}
                       </View>
                   </View>
               </View>
           </View>
       </AppTouchableOpacity>
   );
};

const getStyles = colors =>
   StyleSheet.create({
       item: {
           flex: 1,
           marginTop: 15,
           paddingHorizontal: GUTTER
       },
       inviteAcceptButton: {
           flex: 0.65,
           marginRight: 4,
           backgroundColor: colors.highlightColor,
           height: FontManager.applyFontHeightAdjustment(36, Typographies.bodyText),
           justifyContent: "center",
           borderRadius: 8
       },
       inviteRejectButton: {
           flex: 1,
           paddingVertical: 5,
           marginLeft: 4,
           height: FontManager.applyFontHeightAdjustment(36, Typographies.bodyText),
           justifyContent: "center",
           borderRadius: 8,
           borderWidth: StyleSheet.hairlineWidth,
           borderColor: colors.borderColor
       }
   });

export default GroupItem;

//In custom_code/index.js...

...

import GroupItem from "./components/GroupItem";
export const applyCustomCode = externalCodeSetup => {
 externalCodeSetup.groupsListHooksApi.setGroupItemComponent(props => <GroupItem {...props} />)
}

# setGroupPendingMemberItemComponent(GroupPendingMemberItemComponentnullable)

Replaces group item component in the pending invites group list.

Parameters:
Name Type Attributes Description
GroupPendingMemberItemComponent React.ComponentType.<GroupPendingMemberItemComponentProps> <nullable>
Example

You can add a component to redirect users in the pending invites list.

//In custom_code/components/PendingMemberItem.js

import React, {useEffect, useState} from "react";
import {
   View,
   StyleSheet,
   Text,
   ActivityIndicator,
   TouchableOpacity
} from "react-native";

//Load BuddyBoss components...
import AppAvatar from "@src/components/AppAvatar";
import IconButton from "@src/components/IconButton";
import {GUTTER, FontWeights} from "@src/styles/global";
import {groupInviteModify} from "@src/actions/groupInvites";
import {connect} from "react-redux"; // Will be used to connect to redux for dispatching an action
import {usePrevious} from "@src/components/hooks";

const MemberItem = props => {
   const {
       item,
       global,
       groupInvite,
       loading,
       groupInviteModify,
       index,
       colors,
       settings,
       t
   } = props;

   const [active, setActive] = useState(false);
   const prevloading = usePrevious(loading);

   useEffect(
       () => {
           if (prevloading === true && loading === false) {
               setActive(false);
           }
       },
       [loading]
   );

   return (
       <View
           style={[
               global.row,
               styles.itemInner,
               styles.item,
               index === 0 ? {paddingTop: 0} : {}
           ]}
       >
           <AppAvatar
               size={50}
               name={item.fullname}
               source={{
                   uri: item.avatarUrl
               }}
           />
           <View style={[global.row, global.bottomBorder, styles.text]}>
               <View>
                   <Text
                           style={[
                           global.text,
                           {marginBottom: 5, fontWeight: FontWeights.medium}
                       ]}
                   >
                       {item.fullname}
                   </Text>
               </View>

               //Add component to redirect to user profile
               <TouchableOpacity onPress={() => item.onClick()}>
                   <Text>Go to user profile</Text>
               </TouchableOpacity>

               {loading && active ? (
                   <ActivityIndicator />
               ) : (
                   <IconButton
                       pressHandler={() => {
                           setActive(true);
                           groupInviteModify(groupInvite);
                       }}
                       icon={{fontIconName: "times", weight: 300}}
                       tintColor="#C6C6C8"
                   />
               )}
           </View>
       </View>
   );
};

const styles = StyleSheet.create({
   item: {
       paddingHorizontal: GUTTER
   },
   itemInner: {
       flex: 1,
       justifyContent: "space-between"
   },
   text: {
       paddingVertical: 20,
       marginLeft: 14,
       justifyContent: "space-between",
       flex: 1
   }
});

const mapStateToProps = (state, ownProps) => {
   const groupId = ownProps.groupId;
   return {
       loading: state.groupInvites.modify.cancelLoading
   };
};

const mapDispatchToProps = (dispatch, ownProps) => {
   return {
       //Dispatch `cancel` action to reject the invitation
       groupInviteModify: groupInvite =>
           dispatch(
               groupInviteModify("cancel", groupInvite.group_id, groupInvite.id)
           )
   };
};

export default connect(
   mapStateToProps,
   mapDispatchToProps
)(MemberItem);

//In custom_code/index.js

...

import PendingMemberItem from "./components/PendingMemberItem";
export const applyCustomCode = externalCodeSetup => {

 externalCodeSetup.groupsListHooksApi.setGroupPendingMemberItemComponent(props => <PendingMemberItem {...props} />)
}

# setSubFiltersFilter(subFilterProps)

Sets the available sub filter function. As shown in the example below, it's one of the ways you can modify the existing subfilter and customize it according to your preferences.

Parameters:
Name Type Description
subFilterProps TransformGroupSubFiltersFilterCallback
Example

You can add a "Recently Active" subfilter; remove the "All Group Types" subfilter; and change the labels of the group types sub filters.

 externalCodeSetup.groupsListHooksApi.setSubFiltersFilter((filters) => {
   return {
     type: [{ value: "active", label: "Recently Active Groups" }],
     group_type: [
       { value: "beagle", label: "Beagle Dogs" },
       { value: "japanese-spitz", label: "Japanese Spitz Dogs" }
     ]
   }

 });