Source

externalCode/activitiesScreen.js

  1. import * as React from "react";
  2. /**
  3. * @typedef {Object} ActivityViewModel
  4. * @property {Number} id Activity id
  5. * @property {String} action Description of activity update
  6. * @property {String} component Info on where the activity came from such as "groups", "activity"
  7. * @property {Object} user User's id and name
  8. * @property {String} content Html content of activity to display
  9. * @property {String} contentStripped Content of activity to display stripped of html tags
  10. * @property {Number} parentId Used for activity relative id
  11. * @property {Number} firstParentId Used for activity relative id
  12. * @property {String} type Type of activity. Ex: "activity_update"
  13. * @property {String} avatarUrl Url to user's avatar
  14. * @property {Boolean} can_report True if user can report activity
  15. * @property {Boolean} reported True if user has already reported the activity
  16. * @property {Boolean} isMine True if activity is from user
  17. * @property {Boolean} can_comment True if user can comment
  18. * @property {Boolean} can_delete True if user can delete the activity
  19. * @property {Boolean} can_favorite True if user can mark activity as favorite
  20. * @property {Boolean} can_edit True if user can edit the activity
  21. * @property {Boolean} isFavorite True if activity is marked as favorite
  22. * @property {Object} activityData Contains more activity data such as groupName if post came from group activity
  23. * @property {Number} commentCount Number of people commented in the activity
  24. * @property {Function} authorClick Function that will navigate to profile of the user who posted the activity
  25. * @property {String} dateRecorded Ex: "a month ago"
  26. * @property {String} dateRecordedLong Ex: "3 weeks, 6 days ago"
  27. * @property {Array<Object>} children Activity data related to main activity such as if there are comments in the activity
  28. * @property {Array<Object>} media Media attached to activity
  29. * @property {Array} documents Documents attached to activity
  30. * @property {Array} platformMedia Platform media attached to activity
  31. * @property {Object} gif Gif information including preview_url, video_url and rendered html
  32. * @property {Object<Function>} actions Actions for `reply()` and `edit()`
  33. * @property {String} privacy Privacy setting of the activity
  34. *
  35. */
  36. /**
  37. * @typedef {Object} Button
  38. * @param {boolean} permissionField Flag that tells should button show or not
  39. * @param {React.ComponentType<any>} jsx Contains components for Like, Comment and Delete buttons
  40. */
  41. /**
  42. * @typedef {Function} ActivityButtonsFilterCallback
  43. * @param {Array<Button>} buttons Current buttons array
  44. * @param {ActivityViewModel} item Activity view model
  45. * @param {Array<string>} actionsList List of allowed actions
  46. * @param {Object} settings Settings object got from API
  47. * @return {Array<Button>} Changed array of buttons
  48. */
  49. /**
  50. * @typedef {Function} ActivityViewModelFilterCallback
  51. * @property {ActivityViewModel} viewModel Activity view model
  52. * @property {Activity} activity Original activity object
  53. * @property {ActivityModelDependencies} depend Dependencies (functions used to create view model)
  54. * @return {Object} New view model
  55. */
  56. /**
  57. * @typedef {Object} ActivityModelDependencies
  58. * @property {Object} config App configuration object
  59. * @property {TranslationFunction} t Translation function
  60. * @property {Object} actions Object with activity actions
  61. * @property {boolean} isProfileList Flag that tells if it's the current screen under profile
  62. * @property {User} currentUser Logged in user
  63. * @property {ToUserBasedOnSettings} toUserBasedOnSettings Navigate to user function
  64. */
  65. /**
  66. * @typedef {Object} ActivityLikeComponentProps
  67. * @property {LocalImageSource} icon
  68. * @property {Function} pressHandler Mark activity as favorite
  69. * @property {String} tintColor Default tint color of activity like button. Changes value depending on if activity is liked or not.
  70. * @property {Array<Object>} touchableStyle Default styling of the like button container
  71. * @property {Object} style Default styling of the like button
  72. * @property {Function} renderText Returns JSX to display text beside the like button
  73. * @property {ActivityViewModel}
  74. *
  75. */
  76. /**
  77. * @typedef {Object} ActivityHeaderComponentProps
  78. * @property {User} user
  79. * @property {ActivityViewModel} item
  80. * @property {Object} global App global style
  81. * @property {Object} colors App colors
  82. * @property {Object} tagsStyles Tag default styles
  83. * @property {Object} contentWrapperStyle Default content wrapper for activity item
  84. * @property {Object} style Default style for activity item wrapper
  85. * @property {Function} attemptDeepLink Helper function which is used for deep linking when activity is pressed
  86. * @property {Number} avatarSize Returns default size of avatar
  87. * @property {Boolean} hidePrivacy Returns `true` if privacy button should be hidden
  88. * @property {Function} onChangePrivacy Helper function which is used for changing the activity's privacy
  89. * @property {Boolean} privacyModalVisible Returns `true` if modal for setting privacy should be visible
  90. * @property {Object} contentWrapperStyle Returns the default styling for the content wrapper
  91. * @property {Number} avatarSize The default size of the avatar
  92. * @property {Boolean} hidePrivacy Returns `true` if privacy indicator should be shown
  93. * @property {String} profileAvatarType Avatar type to be displayed in the activitypost
  94. * @property {Boolean} enableProfileGravatar Returns `true` if profile gravatar is enabled
  95. * @property {String} defaultProfileAvatarType The default profile avatar type
  96. * @property {String} defaultCustomProfileAvatarImage The default custom profile avatar image
  97. * @property {String} activitiesFilter Active filter in the activities list
  98. * @property {Boolean} isGroupScreen Returns `true` if component is being rendered in a group screen
  99. * @property {Function} renderActivityOptions Function to render activity options
  100. *
  101. */
  102. /**
  103. * @typedef {Function} TransformActivitiesParams
  104. * @param {FetchActivitiesParams}
  105. * @return {Object}
  106. */
  107. /**
  108. * @typedef {Object} FetchActivitiesParams
  109. * @see {@link https://www.buddyboss.com/resources/api/#api-Activity-GetBBActivities}
  110. * @property {String} display_comments Allowed values: `stream`, `threaded`, `false`
  111. * @property {?String} search Limit results to those matching a string.
  112. *
  113. */
  114. /**
  115. * @typedef {Object} TransformActivityCommentButtons
  116. * @property {Array<String>} params Default buttons allowed in the ActivityComment component
  117. */
  118. /**
  119. * @typedef {Object} BeforeActivitySingleComponentProps
  120. * @property {ActivityViewModel} item
  121. * @property {Number} index
  122. * @property {User} currentUser
  123. */
  124. /**
  125. * @typedef {Object} AfterActivitySingleComponentProps
  126. * @property {ActivityViewModel} item
  127. * @property {Number} index
  128. * @property {User} currentUser
  129. */
  130. /**
  131. * @typedef {Object} HeaderActionComponentProps
  132. * @property {Boolean} canCreateActivity Returns `true` if create activity component should be visible
  133. * @property {Function} onPress Navigates user to the create activity post screen
  134. * @property {Object} colors App colors
  135. */
  136. /**
  137. * @typedef {Object} ActivityImageComponentProps
  138. * @property {String} thumbnail Url to image's thumbnail
  139. * @property {String} source Url to image's source
  140. * @property {Object} styles Default styles
  141. * @property {String} resizeMode Default resize mode
  142. */
  143. /**
  144. * @typedef {Object} AfterActivityContentComponentProps
  145. * @property {ActivityViewModel} item
  146. * @property {User} currentUser
  147. */
  148. /**
  149. * @typedef {Object} ActivityCommentHeaderComponentProps
  150. * @property {Object} styles Default styles
  151. * @property {Function} handleAuthorClick Used for navigating to the author's profile
  152. * @property {String} username Author's name
  153. * @property {String} date Comment date
  154. * @property {Object} item Activity comment details
  155. */
  156. /**
  157. * @typedef {Object} ActivityCommentAvatarProps
  158. * @property {Number} userId User id of the comment author
  159. * @property {Function} handleAuthorClick Navigates to the author's profile
  160. * @property {Number} size Default avatar size
  161. * @property {Object} source Default uri for author's image
  162. */
  163. /**
  164. * @class
  165. * Activities Screen Hooks.
  166. * Instance name: activitiesScreenApi
  167. *
  168. * The ActivitiesScreenHooksApi() enables you to modify your activity options on the app activity list screen.
  169. The filters below have a range of options such as adding/changing the action button on or tweaking your ViewModel options in the app.
  170. * @example
  171. * externalCodeSetup.activitiesScreenApi.METHOD_NAME
  172. */
  173. export class ActivitiesScreenHooksApi {
  174. /**
  175. * @private
  176. * @property {ActivityButtonsFilterCallback} activityButtonsFilter
  177. */
  178. activityButtonsFilter = (b, item, a, settings) => b;
  179. /**
  180. * It sets the filter functions so that you can change the "Activity" action buttons/ call-to-action buttons.
  181. * The activity buttons for this filter can be used to add or modify buttons include like, comment, or edit buttons in the activity list screen.
  182. * @method
  183. * @param {ActivityButtonsFilterCallback} activityButtonsFilter Function that changes call-to-action/activity buttons in the activity list screen
  184. * @example
  185. * ...
  186. * import { Text, TouchableOpacity } from 'react-native'
  187. *
  188. * export const applyCustomCode = externalCodeSetup => {
  189. * externalCodeSetup.activitiesScreenApi.setActivityButtonsFilter((buttons, item, actionsList, settings) => {
  190. *
  191. * //Do something onPress
  192. * const onPress = () => {
  193. * //Call api...
  194. * }
  195. *
  196. * return [
  197. * ...buttons,
  198. * {
  199. * // use false if it should be hidden.
  200. * // User can also use data from item. For example, instead of static boolean value, user can use `item.can_comment` if button should show if user can also comment
  201. * permissionField: true,
  202. * jsx: (
  203. * <TouchableOpacity onPress={onPress}>
  204. * <Text>Share</Text>
  205. * </TouchableOpacity>
  206. * )
  207. * }]
  208. * })
  209. * }
  210. */
  211. setActivityButtonsFilter = activityButtonsFilter => {
  212. this.activityButtonsFilter = activityButtonsFilter;
  213. };
  214. // @deprecated
  215. ActivityListHeaderComponent = null;
  216. setActivityListHeaderComponent = ActivityListHeaderComponent => {
  217. this.ActivityListHeaderComponent = ActivityListHeaderComponent;
  218. };
  219. /**
  220. * @private
  221. * @property {ActivityViewModelFilterCallback} activityToViewModelFilter
  222. */
  223. activityToViewModelFilter = (viewModel, activity, depend) => viewModel;
  224. /**
  225. * A ViewModel object contains a field that the app requires when viewing an activity.
  226. * It helps UI-related data to be stored, managed, and configured in a conscious way.
  227. * You can use the filter function below to change the current activity viewModel.
  228. * For example, some of the fields you can change include `content`, `isMine`, `can_edit`, and `commentCount`.
  229. * @method
  230. * @param {ActivityViewModelFilterCallback} activityToViewModelFilter Function that changes activity ViewModel
  231. * @example
  232. * externalCodeSetup.activitiesScreenApi.setActivityToViewModelFilter((viewModel, activity, depend) => {
  233. *
  234. * return {
  235. * ...viewModel,
  236. * //Setting the following below as false will remove the buttons that allows a user to comment, delete, favorite and edit
  237. * can_comment: false,
  238. * can_delete: false,
  239. * can_favorite: false,
  240. * can_edit: false
  241. * }
  242. * return viewModel;
  243. * })
  244. */
  245. setActivityToViewModelFilter = activityToViewModelFilter => {
  246. this.activityToViewModelFilter = activityToViewModelFilter;
  247. };
  248. ActivityLikeComponent = null;
  249. /**
  250. * You can use this hook to replace the default "Like"/"Thumbs up" button to any of your preferred buttons in the Activities List screen.
  251. * @method
  252. * @param {?React.ComponentType<ActivityLikeComponentProps>} ActivityLikeComponent
  253. * @example <caption> Like button changes icon and color when pressed</caption>
  254. *
  255. * //In custom_code/components/ActivityLikeButton.js...
  256. *
  257. * import React from "react";
  258. * import IconButton from "@src/components/IconButton";
  259. *
  260. * const ActivityLikeButton = props => {
  261. *
  262. * const {
  263. * pressHandler,
  264. * tintColor,
  265. * touchableStyle,
  266. * colors,
  267. * style,
  268. * renderText,
  269. * item } = props;
  270. *
  271. * const likedIcon = {fontIconName: "thumbs-up", weight: 300}
  272. * const regularIcon = {fontIconName: "thumbs-up", weight: 400}
  273. *
  274. * return (
  275. * <IconButton
  276. * icon={item.isFavorite ? likedIcon : regularIcon}
  277. * pressHandler={pressHandler}
  278. * tintColor={item.isFavorite ? "#A1DAD9" : tintColor}
  279. * touchableStyle={touchableStyle}
  280. * style={style}
  281. * renderText={renderText}
  282. * />
  283. * );
  284. * };
  285. * export default ActivityLikeButton;
  286. *
  287. * //In custom_code/index.js...
  288. *
  289. * ...
  290. *
  291. * import ActivityLikeButton from './components/ActivityLikeButton';
  292. * export const applyCustomCode = externalCodeSetup => {
  293. * externalCodeSetup.activitiesScreenApi.setActivityLikeComponent(props => <ActivityLikeButton {...props} />)
  294. * }
  295. *
  296. */
  297. setActivityLikeComponent = ActivityLikeComponent => {
  298. this.ActivityLikeComponent = ActivityLikeComponent;
  299. };
  300. ActivityHeaderComponent = null;
  301. /**
  302. * It is used to modify the appearance and structure of the activities header component in the activities list screen.
  303. * @method
  304. * @param {?React.ComponentType<ActivityHeaderComponentProps>} ActivityHeaderComponent
  305. * @example
  306. *
  307. * //In custom_code/components/ActivityHeader.js...
  308. *
  309. * import React from "react";
  310. * import {View, StyleSheet, Text, useWindowDimensions} from "react-native";
  311. * import AppAvatar from "@src/components/AppAvatar";
  312. * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
  313. * import {dateRenderer, spanRenderer} from "@src/utils/htmlRender";
  314. * import {stripActivityTags} from "@src/utils/buddypress";
  315. * import ActivityPrivacyButton from "@src/components/Activity/Privacy/ActivityPrivacyButton";
  316. * import {getProfileImageSource} from "@src/components/Profile/Xprofile/utils";
  317. * import {withDefaultProfileImageSettings} from "@src/components/hocs/withDefaultProfileImageSettings";
  318. * import CustomHTML from "@src/components/HTML";
  319. * import Icon from "@src/components/Icon";
  320. * import {filters} from "@src/reducers/activities";
  321. * import {BuddyPressScopes} from "@src/services/enums/buddyPress";
  322. *
  323. * const ActivityHeader = props => {
  324. * const {
  325. * t,
  326. * user,
  327. * item,
  328. * global,
  329. * colors,
  330. * tagsStyles,
  331. * attemptDeepLink,
  332. * showAvatar,
  333. * style,
  334. * textColor,
  335. * setItemHeight = () => {},
  336. * onChangePrivacy,
  337. * privacyModalVisible,
  338. * contentWrapperStyle,
  339. * avatarSize,
  340. * hidePrivacy,
  341. * profileAvatarType,
  342. * enableProfileGravatar,
  343. * defaultProfileAvatarType,
  344. * defaultCustomProfileAvatarImage,
  345. * activitiesFilter,
  346. * isGroupScreen,
  347. * renderActivityOptions
  348. * } = props;
  349. *
  350. * const lightText = colors.descLightTextColor;
  351. *
  352. * let avatarName = item.user?.name || "";
  353. * const {is_pinned} = item;
  354. * if (item.user?.id === user?.id) avatarName = user.name; // user is unavailable during guest login
  355. *
  356. * const showPrivacy =
  357. * !hidePrivacy &&
  358. * item.can_edit &&
  359. * (item.type === "activity_update" || item.type === "activity_comment") &&
  360. * item.component !== "groups";
  361. *
  362. * const showPin = isGroupScreen
  363. * ? item.component === BuddyPressScopes.groups
  364. * : activitiesFilter === filters[0] && item.isGroupPost === false;
  365. *
  366. * const onLayout = ({
  367. * nativeEvent: {
  368. * layout: {height}
  369. * }
  370. * }) => {
  371. * setItemHeight(height);
  372. * };
  373. *
  374. * const {width} = useWindowDimensions();
  375. *
  376. * const tColor = textColor || colors.textColor;
  377. *
  378. * return (
  379. * <View style={[global.row, styles.header, style]}>
  380. * {showAvatar && (
  381. * <AppTouchableOpacity onPress={item.authorClick}>
  382. * <AppAvatar
  383. * size={avatarSize || 40}
  384. * name={avatarName}
  385. * source={getProfileImageSource(item.user, {
  386. * avatarType: profileAvatarType,
  387. * enableGravatar: enableProfileGravatar,
  388. * defaultAvatarType: defaultProfileAvatarType,
  389. * defaultCustomAvatarImage: defaultCustomProfileAvatarImage
  390. * })}
  391. * />
  392. * </AppTouchableOpacity>
  393. * )}
  394. * <View
  395. * onLayout={onLayout}
  396. * style={[
  397. * styles.text,
  398. * {marginLeft: showAvatar ? 10 : 0},
  399. * contentWrapperStyle
  400. * ]}
  401. * >
  402. * <CustomHTML
  403. * allowedAllTags
  404. * classesStyles={{"activity-to": {marginHorizontal: 3}}}
  405. * tagsStyles={{
  406. * ...tagsStyles,
  407. * rawtext: {
  408. * ...global.activityHtmlrawtext,
  409. * color: tColor
  410. * },
  411. * p: {...global.activityHtmlp, color: tColor},
  412. * a: {
  413. * ...global.activityHtmla,
  414. * color: tColor,
  415. * textDecorationLine: "none"
  416. * }
  417. * }}
  418. * contentWidth={width}
  419. * baseStyle={Object.assign(
  420. * {},
  421. * global.activityHtml,
  422. * textColor ? {color: textColor} : {}
  423. * )}
  424. * renderersProps={{
  425. * a: {onPress: attemptDeepLink(false)}
  426. * }}
  427. * source={{html: stripActivityTags(item.action)}}
  428. * renderers={{
  429. * a: dateRenderer,
  430. * span: spanRenderer
  431. * }}
  432. * />
  433. *
  434. * <View style={[global.row, {marginTop: 3}]}>
  435. * <Text style={[global.activityDate, {color: lightText}]}>
  436. * {item.dateRecorded} {`${item.is_edited ? `(${t("edited")})` : ""}`}
  437. * </Text>
  438. * {showPrivacy &&
  439. * !!item.privacy &&
  440. * item.privacy !== "media" && (
  441. * <ActivityPrivacyButton
  442. * hideBorder={true}
  443. * privacyModalVisible={privacyModalVisible}
  444. * privacy={item.privacy}
  445. * onPress={onChangePrivacy}
  446. * colors={colors}
  447. * global={global}
  448. * />
  449. * )}
  450. * </View>
  451. * </View>
  452. * {showPin &&
  453. * is_pinned && (
  454. * <View style={styles.pinContainer}>
  455. * <Icon
  456. * icon={{fontIconName: "thumbtack", weight: "400"}}
  457. * tintColor={colors.textIconColor}
  458. * size={20}
  459. * />
  460. * </View>
  461. * )}
  462. *
  463. * {renderActivityOptions && renderActivityOptions()}
  464. * </View>
  465. * );
  466. * };
  467. *
  468. * const styles = StyleSheet.create({
  469. * item: {},
  470. * header: {
  471. * alignItems: "flex-start",
  472. * justifyContent: "space-between",
  473. * marginBottom: 11
  474. * },
  475. * pinContainer: {
  476. * alignSelf: "flex-start",
  477. * marginTop: 2,
  478. * height: 26,
  479. * width: 26,
  480. * alignItems: "center",
  481. * justifyContent: "center"
  482. * },
  483. * text: {
  484. * flex: 1
  485. * }
  486. * });
  487. *
  488. * export default withDefaultProfileImageSettings(ActivityHeader);
  489. *
  490. * //In custom_code/index.js..
  491. *
  492. * ...
  493. * import ActivityHeader from "./components/ActivityHeader";
  494. * export const applyCustomCode = externalCodeSetup => {
  495. * externalCodeSetup.activitiesScreenApi.setActivityHeaderComponent(props => <ActivityHeader {...props} />)
  496. * }
  497. *
  498. */
  499. setActivityHeaderComponent = ActivityHeaderComponent => {
  500. this.ActivityHeaderComponent = ActivityHeaderComponent;
  501. };
  502. fetchParamsFilter = params => params;
  503. /**
  504. * It overrides the parameters that are used to fetch activities in the Activities screen and enables you to add more parameters when fetching an activity so that you can make it as customizable as possible when calling its API.
  505. * @method
  506. * @param {TransformActivitiesParams} fetchParamsFilter
  507. *
  508. * @example <caption> Create a custom filter in activities screen </caption>
  509. *
  510. * //In components/ActivitiesBeforeList.js...
  511. *
  512. * import React, { useState } from "react";
  513. * import { TextInput, View, Button } from 'react-native'
  514. * import { useDispatch } from "react-redux";
  515. * import { activitiesRequested } from "@src/actions/activities";
  516. * import { getExternalCodeSetup } from "@src/externalCode/externalRepo";
  517. * import withGlobalStyles from "@src/components/hocs/withGlobalStyles";
  518. *
  519. * const hook = getExternalCodeSetup().activitiesScreenApi;
  520. *
  521. * const screenName = "book";
  522. *
  523. * const filter = "favorites"; //"just-me", "friends", "groups", "favorites", "mentions", "following"
  524. * const subfilters = {type: "new_member"}; // "-1", "new_member", "new_avatar", "updated_profile", "activity_update", "activity_comment", "friendship_accepted", "friendship_created", "created_group", "joined_group", "group_details_updated", "bbp_topic_create", "bbp_reply_create"
  525. *
  526. * const refresh = true; //Set to true to refresh list
  527. * const searchTerm = "Tony"
  528. *
  529. * const ActivitiesBeforeList = (props) => {
  530. *
  531. * const { navigation, route, colors } = props;
  532. *
  533. * const dispatch = useDispatch();
  534. *
  535. * //If showing the matched screen, show custom filter before displaying list component
  536. * if (route?.params?.item?.object === screenName) {
  537. *
  538. * const [act, setAct] = useState('')
  539. *
  540. * const handleSubmit = () => {
  541. *
  542. * //Set custom parameters before fetching
  543. * hook.setFetchParamsFilter((props) => {
  544. *
  545. * //You can add more parameters such as "subject", "keyword" etc...
  546. * return {
  547. * ...props,
  548. * display_comments: false,
  549. * someActivities: act,
  550. * }
  551. * })
  552. *
  553. * //Dispatch redux action to call api using customized filters
  554. * dispatch(activitiesRequested(filter, subfilters, refresh, searchTerm));
  555. *
  556. * }
  557. *
  558. * return <View style={{ backgroundColor: colors.whiteColor}}>
  559. *
  560. * <TextInput
  561. * style={{paddingHorizontal: 20, marginTop: 10, fontSize: 20}}
  562. * autoFocus
  563. * value={act}
  564. * onChangeText={act => setAct(act)}
  565. * placeholder="Search for an Activity"
  566. * />
  567. *
  568. * <Button
  569. * onPress={() => handleSubmit()}
  570. * title="Filter"
  571. * />
  572. * </View>
  573. * }
  574. *
  575. * return null;
  576. *
  577. * }
  578. *
  579. * export default withGlobalStyles(ActivitiesBeforeList);
  580. *
  581. * //In components/MyCustomScreen.js...
  582. * import React from 'react';
  583. * import ActivitiesScreen from "@src/containers/Custom/ActivitiesScreen";
  584. *
  585. * const MyCustomScreen = props => (<ActivitiesScreen {...props} showSearch={false} hideFilters={true} headerHeight={250} />)
  586. *
  587. *
  588. * export default MyCustomScreen;
  589. *
  590. * //In custom_code/index.js...
  591. *
  592. * ...
  593. *
  594. * import ActivitiesBeforeList from "./components/ActivitiesBeforeList";
  595. * export const applyCustomCode = externalCodeSetup => {
  596. *
  597. * externalCodeSetup.filterScreenApiHooks.setAfterFilterComponent(ActivitiesBeforeList);
  598. *
  599. * externalCodeSetup.navigationApi.addNavigationRoute(
  600. * "book",
  601. * "BookScreen",
  602. * MyCustomScreen,
  603. * "All"
  604. * );
  605. * externalCodeSetup.navigationApi.addNavigationRoute(
  606. * "book",
  607. * "BookScreen",
  608. * MyCustomScreen,
  609. * "Main"
  610. * );
  611. * }
  612. */
  613. setFetchParamsFilter = fetchParamsFilter => {
  614. this.fetchParamsFilter = fetchParamsFilter;
  615. };
  616. activityCommentButtonsFilter = params => params;
  617. /**
  618. * It overrides the filters used in the ActivityComment component.
  619. * You can use this together with `setActivityButtonsFilter` to add or remove buttons in the ActivityComment component.
  620. * @method
  621. * @param {TransformActivityCommentButtons} activityCommentButtonsFilter
  622. *
  623. * @example <caption> Add new buttons in the main activity post and comment activity post </caption>
  624. *
  625. * ...
  626. *
  627. * export const applyCustomCode = externalCodeSetup => {
  628. * externalCodeSetup.activitiesScreenApi.setActivityButtonsFilter(
  629. * (buttons, item, actionsList, settings) => {
  630. *
  631. * //Do something onPress
  632. * const onPress = () => {
  633. * console.log(item);
  634. * };
  635. *
  636. * //Add a share "Like" button
  637. * let newButtons = [
  638. * {
  639. * id: "reply",
  640. * permissionField: true,
  641. * jsx: (
  642. * <TouchableOpacity onPress={onPress}>
  643. * <Text>Share</Text>
  644. * </TouchableOpacity>
  645. * )
  646. * },
  647. * ...buttons
  648. * ];
  649. *
  650. * //Replace the "Reply" button and add a new button
  651. * if (item.parentId){
  652. * newButtons = [
  653. * {
  654. * id: "custom",
  655. * permissionField: true,
  656. * jsx: (
  657. * <TouchableOpacity onPress={onPress}>
  658. * <Text>Custom | </Text>
  659. * </TouchableOpacity>
  660. * )
  661. * },
  662. * {
  663. * id: "reply",
  664. * permissionField: true,
  665. * jsx: (
  666. * <TouchableOpacity onPress={onPress}>
  667. * <Text>Reply</Text>
  668. * </TouchableOpacity>
  669. * )
  670. * },
  671. * buttons[1], //Delete button
  672. * buttons[2] //Show more button
  673. * ]
  674. * }
  675. *
  676. * return newButtons;
  677. * }
  678. * );
  679. *
  680. * //Allow ActivityComment to render the button with the 'custom' id
  681. * externalCodeSetup.activitiesScreenApi.setActivityCommentButtonsFilter(filters => {
  682. * return [
  683. * ...filters,
  684. * 'custom'
  685. * ]
  686. * })
  687. * }
  688. */
  689. setActivityCommentButtonsFilter = activityCommentButtonsFilter => {
  690. this.activityCommentButtonsFilter = activityCommentButtonsFilter;
  691. };
  692. BeforeActivitySingleComponent = null;
  693. /**
  694. * You can use this hook to add a component before each ActivitySingle component.
  695. * @method
  696. * @param {?React.ComponentType<BeforeActivitySingleComponentProps>} BeforeActivitySingleComponent
  697. * @example <caption> Add a text before the ActivitySingle component for x page </caption>
  698. *
  699. * ...
  700. *
  701. * export const applyCustomCode = externalCodeSetup => {
  702. * externalCodeSetup.activitiesScreenApi.setBeforeActivitySingleComponent(({
  703. * item,
  704. * index,
  705. * currentUser
  706. * }) => {
  707. *
  708. * const numberPerPage = 10;
  709. * const page = Math.ceil(index / numberPerPage);
  710. *
  711. * if (page < 2){
  712. * return <Text>Hi {currentUser?.name}!</Text>
  713. * }
  714. *
  715. * return null;
  716. *
  717. * })
  718. * }
  719. */
  720. setBeforeActivitySingleComponent = BeforeActivitySingleComponent => {
  721. this.BeforeActivitySingleComponent = BeforeActivitySingleComponent;
  722. };
  723. AfterActivitySingleComponent = null;
  724. /**
  725. * You can use this hook to add a component after each ActivitySingle component.
  726. * @method
  727. * @param {?React.ComponentType<AfterActivitySingleComponentProps>} AfterActivitySingleComponent
  728. * @example
  729. *
  730. * ...
  731. *
  732. * externalCodeSetup.activitiesScreenApi.setAfterActivitySingleComponent(props => <Text>Hello World</Text>)
  733. */
  734. setAfterActivitySingleComponent = AfterActivitySingleComponent => {
  735. this.AfterActivitySingleComponent = AfterActivitySingleComponent;
  736. };
  737. HeaderActionComponent = null;
  738. /**
  739. * You can use this hook to customize the "create post" button located at the upper right section of the activities screen.
  740. * @method
  741. * @param {React.ComponentType<HeaderActionComponentProps>} HeaderActionComponent
  742. * @example
  743. *
  744. * ...
  745. *
  746. * import IconButton from "@src/components/IconButton";
  747. * import AuthWrapper from "@src/components/AuthWrapper";
  748. * export const applyCustomCode = (externalCodeSetup) => {
  749. * externalCodeSetup.activitiesScreenApi.setHeaderActionComponent(
  750. * ({canCreateActivity, onPress, colors}) => {
  751. * return canCreateActivity ? (
  752. * <AuthWrapper>
  753. * <IconButton
  754. * icon={{fontIconName: "pencil", weight: 200}} //pencil, round-filled
  755. * pressHandler={onPress}
  756. * tintColor={colors.headerIconColor}
  757. * style={{
  758. * height: 28
  759. * }}
  760. * />
  761. * </AuthWrapper>
  762. * ) : null;
  763. * }
  764. * );
  765. * }
  766. */
  767. setHeaderActionComponent = HeaderActionComponent => {
  768. this.HeaderActionComponent = HeaderActionComponent;
  769. };
  770. ActivityImageComponent = null;
  771. /**
  772. * You can use this hook to replace an activity image.
  773. * For example, you can use this to change the component's dimensions.
  774. * @method
  775. * @param {?React.ComponentType<ActivityImageComponentProps>} ActivityImageComponent
  776. * @example <caption> Allow image to occupy entire image container</caption>
  777. *
  778. * import ProgressiveImage from "@src/components/ProgressiveImage";
  779. *
  780. * export const applyCustomCode = (externalCodeSetup) => {
  781. *
  782. * externalCodeSetup.activitiesScreenApi.setActivityImageComponent(({
  783. * thumbnail,
  784. * source,
  785. * styles,
  786. * resizeMode
  787. * }) => {
  788. *
  789. * const customStyle = {
  790. * ...styles.container,
  791. * width: '100%'
  792. * }
  793. *
  794. * return (
  795. * <ProgressiveImage
  796. * thumbnailSource={{
  797. * uri: thumbnail
  798. * }}
  799. * source={{
  800. * uri: source
  801. * }}
  802. * style={styles.image}
  803. * containerStyle={customStyle}
  804. * resizeMode='cover'
  805. * />
  806. * );
  807. * });
  808. * }
  809. *
  810. */
  811. setActivityImageComponent = ActivityImageComponent => {
  812. this.ActivityImageComponent = ActivityImageComponent;
  813. };
  814. AfterActivityContentComponent = null;
  815. /**
  816. * You can use this hook to add a component after each ActivityContent component.
  817. * @method
  818. * @param {React.ComponentType<AfterActivityContentComponentProps>} AfterActivityContentComponent
  819. * @example
  820. *
  821. * ...
  822. *
  823. * externalCodeSetup.activitiesScreenApi.setAfterActivityContentComponent(
  824. * props => (
  825. * <TouchableOpacity>
  826. * <View style={{marginVertical: 5}}>
  827. * <Text style={{fontSize: 13}}>John and 35 others liked this post</Text>
  828. * </View>
  829. * </TouchableOpacity>
  830. * )
  831. * );
  832. *
  833. */
  834. setAfterActivityContentComponent = AfterActivityContentComponent => {
  835. this.AfterActivityContentComponent = AfterActivityContentComponent;
  836. };
  837. ActivityCommentHeaderComponent = null;
  838. /**
  839. * You can use this to customize the author name and post date of the activity comments.
  840. * For example, you can add a "verified" badge beside the author's name using this hook.
  841. * @method
  842. * @param {?React.ComponentType<ActivityCommentHeaderComponentProps>} ActivityCommentHeaderComponent
  843. * @example
  844. *
  845. * externalCodeSetup.activitiesScreenApi.setActivityCommentHeaderComponent(
  846. * props => {
  847. * const {styles, handleAuthorClick, username, date} = props;
  848. * return (
  849. * <View style={styles.textContainer}>
  850. * <Text style={styles.textInnerContainer}>
  851. * <Text onPress={handleAuthorClick} style={styles.text}>
  852. * {username}
  853. * </Text>
  854. * {" "}
  855. * {date}
  856. * </Text>
  857. * </View>
  858. * );
  859. * }
  860. * );
  861. *
  862. */
  863. setActivityCommentHeaderComponent = ActivityCommentHeaderComponent => {
  864. this.ActivityCommentHeaderComponent = ActivityCommentHeaderComponent;
  865. };
  866. ActivityCommentAvatar = null;
  867. /**
  868. * You can use this to customize the author avatar of the activity comments.
  869. * @method
  870. * @param {React.ComponentType<ActivityCommentAvatarProps>} ActivityCommentAvatar
  871. * @example
  872. *
  873. * ...
  874. *
  875. * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
  876. * import AppAvatar from "@src/components/AppAvatar";
  877. *
  878. * export const applyCustomCode = (externalCodeSetup) => {
  879. *
  880. * externalCodeSetup.activitiesScreenApi.setActivityCommentAvatar(
  881. * ({handleAuthorClick, userId, size, source}) => (
  882. * <AppTouchableOpacity onPress={handleAuthorClick}>
  883. * <AppAvatar
  884. * userId={userId}
  885. * size={size}
  886. * source={source}
  887. * />
  888. * </AppTouchableOpacity>
  889. * )
  890. * );
  891. * }
  892. *
  893. */
  894. setActivityCommentAvatar = ActivityCommentAvatar => {
  895. this.ActivityCommentAvatar = ActivityCommentAvatar;
  896. };
  897. }