Source

externalCode/socialGroupSingle.js

/**
 * @typedef {Object} Group
 */

/**
 * @typedef {Object} Tab
 * @property {String} icon
 * @property {String} label
 * @property {Number} count Indicates badge value
 * @property {Boolean} loading
 * @property {Function} onPress Default function of the tab
 */

/**
 * @typedef {Function} TransformPrivateGroupIgnoredItemsCallback
 * @param {Array<string>} list - list of items that should not show to non-members if group is private
 * @return {Array<string>}
 */

/**
 * @typedef {Function} TransformGroupActionButtonsCallback
 * @param {Array<Object>} action Contains group's default action
 * @returns {Array<Object>}
 */

/**
 * @typedef {Function} TransformGroupTabListCallback
 * @param {Array<Tab>} tabs Tabs in groups screen
 */

/**
 * @typedef {Object} GroupHeaderAvatarProps
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 */

/**
 * @typedef {Object} BeforeGroupDetailsComponentProps
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 */

/**
 * @typedef {Object} AfterGroupDetailsComponentProps
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 */

/**
 * @typedef {Object} GroupHeaderButtonsProps
 * @property {Function} OldButtonComponent Default button component displayed for the group. Ex: "Request to Join", "Member", etc.
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 * @property {Object} currentUser Details about the currently logged-in user
 * @property {TranslationFunction} t
 * @property {Array<Object>} filteredActions Helper functions used in group details
 * @property {Function} onLinkPress Helper function to be used when a link in html is pressed
 * @property {String} buttonTextColor
 * @property {Object} buttonStyle
 */

/**
 * @typedef {Object} GroupDetailsComponentProps
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 * @property {TranslationFunction} t
 * @property {Array<Object>} filteredActions Helper functions used in group details
 * @property {Function} onLinkPress Helper function to be used when a link in html is pressed
 */

/**
 * @typedef {Object} AfterGroupProfileHeaderProps
 * @property {Object} global App global style
 * @property {Object} color App colors
 * @property {GroupViewModel} group
 */

/**
 * @class
 * Group Single Hooks.
 * Instance name: socialGroupSingleApi
  
   You can customize the Social Group options such as replacing group avatars, adding components before/after the group details, modifying the default group action buttons and much more.
 * @example
 * externalCodeSetup.socialGroupSingleApi.METHOD_NAME
 */
export class SocialGroupSingleApi {
	filterTabs = tabs => tabs;
	/**
	 * You can use it to modify the tab list on the Groups screen.
	 * @method
	 * @param {TransformGroupTabListCallback} tabFilter
	 * @example
	 *   externalCodeSetup.socialGroupSingleApi.setTabFilter((props) => {
	 *
	 *    const customTab = {
	 *      icon: require("@src/assets/img/about.png"),
	 *      label: "About",
	 *      onPress: () => Alert.alert("This group was created by the admin"),
	 *      count: false,
	 *      loading: false
	 *    }
	 *
	 *    return [
	 *      ...props,
	 *      customTab
	 *    ];
	 *  })
	 */
	setTabFilter = tabFilter => (this.filterTabs = tabFilter);

	privateGroupTabIgnoreFilter = tabs => tabs;

	/**
	 * @ignore
	 * Reason for ignore: privateGroupTabIgnoreFilter is not being used in the app
	 * Filters the list of items that should not show to non-members if group is private
	 * @param {TransformPrivateGroupIgnoredItemsCallback} filterFunction
	 */
	setPrivateGroupTabFilter = filterFunction => {
		this.privateGroupTabIgnoreFilter = filterFunction;
	};

	GroupHeaderAvatar = null;

	/**
	 * You can use it to replace the group header avatar. For example, you change the default group avatar if the group does not have an avatar.
	 * @method
	 * @param {React.ComponentType<GroupHeaderAvatarProps>} GroupHeaderAvatar
	 * @example <caption> Change default group avatar if group has not avatar </caption>
	 *
	 * ...
	 * import Animated from "react-native-reanimated";
	 * import AppImage from "@src/components/AppImage";
	 * import {DEVICE_WIDTH} from "@src/styles/global";
	 * export const applyCustomCode = externalCodeSetup => {
	 *
	 *  const GroupHeaderAvatar = (props) => {
	 *
	 *    const { global, colors, group } = props;
	 *    const avatarSize = Math.min(DEVICE_WIDTH * 0.3, 110);
	 *    let customUri = group.avatar;
	 *
	 *    if (group.avatar.includes("mystery-group")) {
	 *      customUri = 'https://link-to-image.png'
	 *    }
	 *
	 *    return <Animated.View
	 *      style={[
	 *        {
	 *          marginBottom: 18,
	 *          marginTop: "auto"
	 *        },
	 *        !!group.coverImage && {
	 *          borderRadius: 18,
	 *          backgroundColor: "#fff",
	 *          borderWidth: 3,
	 *          borderColor: "#fff",
	 *          ...global.shadowBelow
	 *        }
	 *      ]}
	 *    >
	 *      <AppImage
	 *        source={{uri: customUri}}
	 *        style={[{ width: avatarSize, height: avatarSize, borderRadius: 18 }]}
	 *        resizeMode={"contain"}
	 *      />
	 *    </Animated.View>
	 *  }
	 *
	 *  externalCodeSetup.socialGroupSingleApi.setGroupHeaderAvatar(GroupHeaderAvatar);
	 * }
	 */
	setGroupHeaderAvatar = GroupHeaderAvatar => {
		this.GroupHeaderAvatar = GroupHeaderAvatar;
	};

	customHeaderBackground = null;

	/**
	 * Replaces a group's cover image
	 * @method
	 * @param {String} customHeaderBackground
	 * @example
	 * externalCodeSetup.socialGroupSingleApi.setCustomHeaderBackground('https://link-to-image.png')
	 */
	setCustomHeaderBackground = customHeaderBackground => {
		this.customHeaderBackground = customHeaderBackground;
	};

	BeforeDetailsComponent = null;

	/**
	 * You can use it to add a component before the group details such as the title and group description.
	 * @method
	 * @param {React.ComponentType<BeforeGroupDetailsComponentProps>} BeforeDetailsComponent
	 * @example
	 * const BeforeDetailsComponent = (props) => {
	 *  return !props.group.isMember && <Text>You are not a member of this group. To see all available items, please join the group.</Text>
	 * }
	 *
	 * externalCodeSetup.socialGroupSingleApi.setBeforeDetailsComponent(BeforeDetailsComponent)
	 */
	setBeforeDetailsComponent = BeforeDetailsComponent => {
		this.BeforeDetailsComponent = BeforeDetailsComponent;
	};

	AfterDetailsComponent = null;

	/**
	 * You can customize the Social Group options such as replacing group avatars, adding components before/after the group details, modifying the default group action buttons and much more.
	 * @method
	 * @param {React.ComponentType<AfterGroupDetailsComponentProps>} AfterDetailsComponent - jsx to render after details display
	 * @example
	 * const AfterDetailsComponent = (props) => {
	 *  return <Button title="Open this group in a web browser" onPress={() => props.group.navigateToWeb()} />
	 * }
	 * externalCodeSetup.socialGroupSingleApi.setAfterDetailsComponent(AfterDetailsComponent)
	 */
	setAfterDetailsComponent = AfterDetailsComponent => {
		this.AfterDetailsComponent = AfterDetailsComponent;
	};

	GroupDetailsComponent = null;

	/**
	 * Replaces the group details component and lets you compose your own component to display the group details.
	 * @method
	 * @param {React.ComponentType<GroupDetailsComponentProps>} GroupDetailsComponent - jsx to render a component that replaces the group details
	 * @example <caption> Default component structure </caption>
	 *
	 * //In custom_code/GroupDetailsComponent.js...
	 *
	 * import React from "react";
	 * import {View, Text, Animated} from "react-native";
	 * import HTML from "react-native-render-html";
	 * import htmlclean from "htmlclean";
	 * import {
	 *  groupMembersCountTranslation,
	 *  groupStatusTranslation
	 * } from "@src/utils"; //BuddyBoss translation helper functions
	 * import GroupActionSheetWrapper from "@src/components/Group/GroupActionSheetWrapper";
	 * import {DEVICE_WIDTH, GUTTER} from "@src/styles/global";
	 *
	 * const widthWithGutter = DEVICE_WIDTH - GUTTER * 2;
	 *
	 * const GroupDetailsComponent = ({ global, colors, group, truncated, textStyle, t, filteredActions, onLinkPress }) => (
	 *     <>
	 *        <Text
	 *            numberOfLines={1}
	 *            style={[
	 *                global.textHeaderTitle,
	 *                {
	 *                    textAlign: "center",
	 *                    maxWidth: widthWithGutter,
	 *                    marginTop: 0,
	 *                    marginBottom: 3
	 *                },
	 *                textStyle
	 *            ]}
	 *        >
	 *            {group.title}
	 *        </Text>
	 *        <Animated.View
	 *            style={[
	 *                global.screenMetas,
	 *                {
	 *                    marginTop: 0,
	 *                    marginBottom: 11
	 *                }
	 *            ]}
	 *        >
	 *            <Text
	 *                style={[
	 *                    global.textHeaderMeta,
	 *                    { maxWidth: widthWithGutter, textAlign: "center", opacity: 0.8 },
	 *                    textStyle
	 *                ]}
	 *            >
	 *                {groupStatusTranslation(t, group)} •{" "}
	 *                {groupMembersCountTranslation(t, group)}
	 *            </Text>
	 *        </Animated.View>
	 *        {!!group.shortContent && (
	 *            <Animated.View style={{ maxWidth: 300 }}>
	 *                <GroupActionSheetWrapper
	 *                    actionButtons={filteredActions}
	 *                    {...{
	 *                        global,
	 *                        colors,
	 *                        t,
	 *                        group,
	 *                        onLinkPress
	 *                     }}
	 *                >
	 *                    <View>
	 *                        <HTML
	 *                            html={htmlclean(truncated.html)}
	 *                            tagsStyles={{
	 *                                p: { marginTop: 0 },
	 *                                a: global.textHeaderShortContent
	 *                            }}
	 *                            baseFontStyle={{
	 *                                ...global.textHeaderShortContent,
	 *                                ...textStyle
	 *                            }}
	 *                            onLinkPress={(event, url) => {
	 *                                if (onLinkPress) {
	 *                                    onLinkPress(event, url);
	 *                                }
	 *                            }}
	 *                        />
	 *                    </View>
	 *                </GroupActionSheetWrapper>
	 *            </Animated.View>
	 *        )}
	 *    </>
	 * );
	 *
	 * export default GroupDetailsComponent;
	 *
	 * //In custom_code/index.js...
	 *
	 * ...
	 *
	 * import GroupDetailsComponent from "./GroupDetailsComponent";
	 * export const applyCustomCode = externalCodeSetup => {
	 *   externalCodeSetup.socialGroupSingleApi.setGroupDetailsComponent(GroupDetailsComponent)
	 * }
	 */
	setGroupDetailsComponent = GroupDetailsComponent => {
		this.GroupDetailsComponent = GroupDetailsComponent;
	};

	GroupHeaderButtons = null;

	/**
	 * You can add new components near the default group button section.
	 * @method
	 * @param {React.ComponentType<GroupHeaderButtonsProps>} GroupHeaderButtons
	 * @example <caption> Add buttons that can open the group in a web browser </caption>
	 * const GroupHeaderButtons = (props) => {
	 *
	 *    const {OldButtonComponent, group} = props;
	 *
	 *    const NavigateToForum = () => <TouchableOpacity onPress={() => group.navigateToForum()}>
	 *      <Text> Go to forum </Text>
	 *    </TouchableOpacity>
	 *
	 *    const OpenInWeb = () => <TouchableOpacity onPress={() => group.navigateToWeb()}>
	 *      <Text> Open in browser </Text>
	 *    </TouchableOpacity>
	 *
	 *    return (
	 *      <View style={{flexDirection: "column"}}>
	 *        <NavigateToForum />
	 *        <OpenInWeb />
	 *        <OldButtonComponent />
	 *      </View>
	 *    )
	 *
	 * }
	 *
	 * externalCodeSetup.socialGroupSingleApi.setGroupHeaderButtons(GroupHeaderButtons);
	 *
	 * @example <caption> Default component structure </caption>
	 *
	 * //In custom_code/GroupHeaderButton.js...
	 *
	 * import React from "react";
	 * import GroupActionSheetWrapper from "@src/components/Group/GroupActionSheetWrapper";
	 * import AvatarActionButton from "@src/components/ActionButtons/AvatarActionButton";
	 * import AuthWrapper from "@src/components/AuthWrapper";
	 * import ActionButtonList from "@src/components/ActionButtons/ActionButtonList";
	 *
	 * const GroupHeaderButton = ({group, currentUser, global, colors, t, onLinkPress, filteredActions, buttonTextColor, buttonStyle}) => {
	 *
	 *  return group.isMember ? (
	 *    <GroupActionSheetWrapper
	 *      actionButtons={filteredActions}
	 *      {...{
	 *        global,
	 *        colors,
	 *        t,
	 *        group,
	 *        onLinkPress
	 *      }}
	 *    >
	 *      <AvatarActionButton
	 *        user={currentUser}
	 *        style={{
	 *          ...buttonStyle,
	 *          paddingLeft: 3,
	 *          paddingRight: 13
	 *        }}
	 *        {...{
	 *          global,
	 *          colors,
	 *          t,
	 *          title: group.role,
	 *          titleStyle: {
	 *            ...global.textHeaderActionButton,
	 *            color: colors.primaryColor
	 *          },
	 *          color: buttonTextColor
	 *        }}
	 *      />
	 *      </GroupActionSheetWrapper>
	 *    ) : (
	 *      <AuthWrapper>
	 *        <ActionButtonList
	 *          hideIcons={true}
	 *          actionButtons={filteredActions}
	 *          object={group}
	 *          color={buttonTextColor}
	 *          t={t}
	 *          buttonStyle={{
	 *            ...buttonStyle,
	 *            marginHorizontal: 5,
	 *            paddingVertical: 0
	 *          }}
	 *          textStyle={global.textHeaderActionButton}
	 *        />
	 *      </AuthWrapper>
	 *    );
	 *
	 * }
	 *
	 * export default GroupHeaderButton;
	 *
	 * //In custom_code/index.js...
	 *
	 * import GroupHeaderButton from "./components/GroupHeaderButton";
	 * export const applyCustomCode = externalCodeSetup => {
	 *   externalCodeSetup.socialGroupSingleApi.setGroupHeaderButtons(GroupHeaderButton)
	 * }
	 */
	setGroupHeaderButtons = GroupHeaderButtons => {
		this.GroupHeaderButtons = GroupHeaderButtons;
	};

	AfterProfileHeader = null;

	/**
	 * It adds a component after the group header but places it before the group items list.
	 * @method
	 * @param {React.ComponentType<AfterGroupProfileHeaderProps>} AfterProfileHeader
	 * @example
	 * const AfterProfileHeader = (props) => {
	 *  const {group} = props;
	 *	return group.hasForum && <View style={{margin: 10}}>
	 *    <Button onPress={() => group.subscribeClick()} title="Subscribe/Unsubscribe to group forum" />
	 *  </View>
	 * }
	 *
	 * externalCodeSetup.socialGroupSingleApi.setAfterProfileHeader(AfterProfileHeader)
	 */
	setAfterProfileHeader = AfterProfileHeader => {
		this.AfterProfileHeader = AfterProfileHeader;
	};

	filteredGroupActionButtons = actions => actions;

	/**
	 * Append or prepend action buttons.
	 * You can use this to modify the group's default action buttons.
	 * `doFunction` can be used to dispatch a redux action.
	 * @method
	 * @param {TransformGroupActionButtonsCallback} filteredGroupActionButtons
	 * @example
	 *
	 * externalCodeSetup.socialGroupSingleApi.setFilteredGroupActionButtons((action) => {
	 *
	 *    const requestDeliveryRedux = {
	 *      label: 'Request for food delivery',
	 *      isNavigation: true,
	 *      doFunction: () => ({ type: "FOOD_DELIVERY_REQUEST" }) //Call custom redux action FOOD_DELIVERY_REQUEST
	 *    }
	 *
	 *    return [...action, requestDeliveryRedux];
	 *
	 * })
	 */
	setFilteredGroupActionButtons = filteredGroupActionButtons => {
		this.filteredGroupActionButtons = filteredGroupActionButtons;
	};
}