Source

externalCode/forumsScreen.js

/**
 * @typedef {Object} Forum
 */

/**
 * @typedef {Object} ForumsGetParam
 * @see {@link http://www.buddyboss.com/resources/api/#api-Forums-GetBBPForums}
 * @property {Number} page Page to fetch
 * @property {Number} per_page Maximum number of items to be returned in result set
 * @property {String} search Limit results to those matching a string.
 * @property {Array<number>} include An array of forums IDs to retrieve.
 * @property {Boolean} _embed
 */

/**
 * @typedef {Object} FetchForumsFactoryParams
 * @property {Function} provider - Redux state provider, function with no args
 * @property {Number} requiredPage
 * @property {"all"} filter
 * @property {?String} search
 * @property {Boolean} _embed
 */

/**
 * @ignore
 * @typedef {Function} TransformForumFiltersCallback
 * @param {Array<string>} filters
 * @return {Array<string>}
 */

/**
 * @typedef {Function} TransformSubFiltersFilterCallback
 * @param {Array<string>} filters Available filters: `activity`, `date`, `title`, `popular`
 * @return {Array<string>}
 */

/**
 * @typedef {Function} TransformForumParamsCallback
 * @param {ForumsGetParam} ForumsGetParam
 * @return {Object}
 */

/**
 * @typedef {Function} TransformForumViewModelCallback
 * @param {Object} viewModel
 * @param {Forum} forum
 * @return {Object}
 */

/**
 * @typedef {Object} ForumItemProps
 * @property {ForumViewModel} forum
 * @property {Object} colors App colors
 * @property {Object} global App global style
 * @property {Function} formatDateFunc Helper function which can be used to format dates
 * @property {TranslationFunction} t
 * @property {Array<Object>} actionButtons Forum actions from redux
 * @return {?React.ComponentType}
 */

/**
 * @typedef {Boolean} ShowSearchProps Returns `true` if "Allow forum wide search" in BuddyBoss plugin is checked
 * @return {Boolean}
 */

/**
 * @class
 * Forums Index Screen Hooks.
 * Instance name: forumsHooksApi

   It is used to customize the forum options such as modifying/replacing components, adding filters and details to the forum.
 * @example
 * externalCodeSetup.forumsHooksApi.METHOD_NAME
 */
export class ForumsHooksApi {
	/**
	 * @deprecated
	 */
	defaultFilter = "all";
	/**
	 * Change default selected filter on forums screen
	 * @deprecated
	 */
	setDefaultFilter = filter => {
		this.defaultFilter = filter;
	};

	forumsFiltersFilter = filters => filters;

	/**
	 * @ignore Ignoring this since only `all` filter can be used. Adding other than that crashes the app.
	 * Sets the filter function capable of modifying initial forum filters array
	 * @method
	 * @param {TransformForumFiltersCallback} forumsFiltersFilter
	 */
	setForumsFiltersFilter = forumsFiltersFilter => {
		this.forumsFiltersFilter = forumsFiltersFilter;
	};

	subFiltersFilter = filters => filters;

	/**
	 * The filter can be used to set the available sub filter function within the forum.
	 * @method
	 * @param {TransformSubFiltersFilterCallback} subFiltersFilter
	 * @example <caption>User would like to have "Alphabetical" and "Date Created" filters only</caption>
	 * externalCodeSetup.forumsHooksApi.setSubFiltersFilter((filters) => {
	 *   return ["title", "date"]; //available filters include "activity", "date", "title", "popular"
	 * })
	 */
	setSubFiltersFilter = subFiltersFilter => {
		this.subFiltersFilter = subFiltersFilter;
	};

	fetchParamsFilter = (params, args) => params;

	/**
	 * It overrides the parameters that are used to fetch forums in the Forums screen so that you can make it as customizable as possible when calling its API.
	 * @method
	 * @param {TransformForumParamsCallback} fetchParamsFilter
	 *
	 * @example <caption> Create a custom filter in forums screen </caption>
	 *
	 * // In custom_code/components/ForumFiltersCustom.js...
	 *
	 * import React, { useState } from "react";
	 * import { TextInput, View, Button, Text, Switch } from 'react-native'
	 * import { useDispatch } from "react-redux";
	 * import { forumsLoadRequest } from "@src/actions/forums";
	 * import { getExternalCodeSetup } from "@src/externalCode/externalRepo";
	 * import withGlobalStyles from "@src/components/hocs/withGlobalStyles";
	 * const hook = getExternalCodeSetup().forumsHooksApi;
	 * const screenName = "forums";
	 *
	 * getExternalCodeSetup().indexScreenApiHooks.setHeaderHeight((defaultHeaderHeight, filterType, navigation) => {
	 *
	 *     if (filterType === screenName){
	 *         return 300
	 *     }
	 *
	 *     return defaultHeaderHeight;
	 *
	 * });
	 *
	 * const filter = "all";
	 * const subfilters = {
	 *     orderby: "name", // "date", "ID", "author", "title", "name", "modified", "parent", "rand", "menu_order", "relevance", "popular", "activity"
	 *     order: "desc"
	 * }
	 *
	 * const refresh = true; //Set to true to refresh list
	 * const searchTerm = ""
	 *
	 * const ForumFiltersCustom = (props) => {
	 *
	 *     const { navigation, route, colors } = props;
	 *
	 *     const dispatch = useDispatch();
	 *
	 *     //If showing the matched screen, show custom filter before displaying list component
	 *     if (route?.params?.item?.object === 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,
	 *                     subscriptions : isEnabled ? true : false
	 *                 }
	 *             })
	 *
	 *             //Dispatch redux action to call api using customized filters
	 *             dispatch(forumsLoadRequest(filter, subfilters, refresh, searchTerm));
	 *
	 *         }
	 *
	 *         return <View style={{ backgroundColor: colors.whiteColor, alignItems: "center", justifyContent: "center" }}>
	 *
	 *             <Text>Subscribed forums only</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(ForumFiltersCustom);
	 *
	 *  //In custom_code/index.js...
	 *
	 *  import ForumFiltersCustom from "./components/ForumFiltersCustom";
	 *  export const applyCustomCode = externalCodeSetup => {
	 *    externalCodeSetup.filterScreenApiHooks.setAfterFilterComponent(ForumFiltersCustom);
	 * }
	 *
	 *
	 * @example <caption>Sort by ascending order</caption>
	 * externalCodeSetup.forumsHooksApi.setFetchParamsFilter(props => {
	 *  return {
	 *   ...props,
	 *   order: "asc",
	 *  }
	 * })
	 */
	setFetchParamsFilter = fetchParamsFilter => {
		this.fetchParamsFilter = fetchParamsFilter;
	};

	/**
	 * @ignore
	 * @private
	 * modify forums View Model
	 */
	forumToViewModelFilter = (viewModel, forum) => viewModel;
	/**
	 * @ignore Ignoring this because hook is not used in the app
	 * Sets the filter function capable of modifying forum view model object
	 * @method
	 * @param {TransformForumViewModelCallback} forumToViewModelFilter
	 */
	setForumToViewModelFilter = forumToViewModelFilter =>
		(this.forumToViewModelFilter = forumToViewModelFilter);

	ForumItemComponent = null;
	/**
	 * Replaces the forum item component in the forums list.
	 * @method
	 * @param {?React.ComponentType<ForumItemProps>} ForumItemComponent
	 * @example <caption>Add more details in each forum items</caption>
	 * //In custom_code/components/ForumItem.js...
	 *
	 * import React from "react";
	 * import { View, Text } from "react-native";
	 * //Load BuddyBoss components and helper functions
	 * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
	 * import AppAvatar from "@src/components/AppAvatar";
	 * import ActionSheetButton from "@src/components/ActionButtons/ActionSheetButton";
	 * import { getForumAvatarSource, shortContent } from "@src/utils";
	 * import AuthWrapper from "@src/components/AuthWrapper";
	 * const ForumItem = ({
	 *    forum,
	 *    colors,
	 *    formatDateFunc,
	 *    global,
	 *    actionButtons,
	 *    t
	 * }) => {
	 *    const avatarSource = getForumAvatarSource(forum);
	 *    const verticalSpacing = 18;
	 *    return (
	 *        <AppTouchableOpacity
	 *            style={[global.forumListItem, { flexDirection: "row" }]}
	 *            onPress={forum.toSingle}
	 *        >
	 *            <AppAvatar
	 *                size={50}
	 *                source={avatarSource}
	 *                style={{ marginVertical: verticalSpacing }}
	 *            />
	 *            <View
	 *                style={{
	 *                    flex: 1,
	 *                    flexDirection: "row",
	 *                    marginLeft: 13,
	 *                    ...global.bottomBorder,
	 *                    paddingVertical: verticalSpacing
	 *                }}
	 *            >
	 *                <View
	 *                    style={{
	 *                        flex: 1
	 *                    }}
	 *                >
	 *                    <View>
	 *                        <Text style={[global.itemTitle, { marginBottom: 4, marginTop: 1 }]}>
	 *                            {forum.title}
	 *                        </Text>
	 *                        //Load short content if there forum has any
	 *                        {forum.shortContent ? (
	 *                            <Text
	 *                                style={[global.itemDesc, { marginBottom: 8 }]}
	 *                                numberOfLines={2}
	 *                                ellipsizeMode={"tail"}
	 *                            >
	 *                                {shortContent(forum.shortContent)}
	 *                            </Text>
	 *                        ) : null}
	 *                    </View>
	 *                    <View style={[global.itemFooter]}>
	 *                        <Text style={global.itemMeta}>{forum.topicCount}</Text>
	 *                    </View>
	 *
	 *                    //Include more forum details...
	 *                    <View>
	 *                        <Text style={global.itemMeta}>Created {formatDateFunc(forum.date)}</Text>
	 *                        {forum?.group?.id && <Text style={global.itemMeta}>Associated group: {forum.group?.name}</Text>}
	 *                    </View>
	 *                </View>
	 *                //Use an action sheet to display buttons such as toggle subscription to forum
	 *                <AuthWrapper actionOnGuestLogin={"hide"}>
	 *                    <ActionSheetButton
	 *                        touchableStyle={{ alignSelf: "center", marginLeft: 10 }}
	 *                        object={forum}
	 *                        colors={colors}
	 *                        actionButtons={actionButtons}
	 *                        headerProps={{
	 *                            id: forum.id,
	 *                            onClick: forum.toSingle,
	 *                            title: forum.title,
	 *                            description: shortContent(forum.shortContent),
	 *                            avatarSource
	 *                        }}
	 *                        global={global}
	 *                        color={colors.textIconColor}
	 *                        t={t}
	 *                    />
	 *                </AuthWrapper>
	 *            </View>
	 *        </AppTouchableOpacity>
	 *    );
	 * };
	 *
	 * export default ForumItem;
	 *
	 * //In custom_code/index.js
	 *
	 * ...
	 *
	 * import ForumItem from "./components/ForumItem";
	 * export const applyCustomCode = externalCodeSetup => {
	 *   externalCodeSetup.forumsHooksApi.setForumItemComponent(props => <ForumItem {...props} />)
	 * }
	 */
	setForumItemComponent = ForumItemComponent => {
		this.ForumItemComponent = ForumItemComponent;
	};

	showSearch = setting => setting;

	/**
	 * Use this to hide or show the search component.
	 * This will override the setting in BuddyBoss > Settings > Forums > Forum Features > Search within the app only.
	 * For example, you can have your website allow forum wide search but hide the forum component in the app by using this hook.
	 * @param {ShowSearchProps} showSearch
	 * @method
	 * @example
	 * externalCodeSetup.forumsHooksApi.setShowSearch((bbSetting) => false);
	 */
	setShowSearch = showSearch => {
		this.showSearch = showSearch;
	};
}