import * as React from "react";
/**
* @typedef {Object} User Logged-in user's data
*/
/**
* @typedef {"xprofile" | "courses" | "certificates" | "gamipress_points" | "gamipress_achievements" | "gamipress_ranks" | "badgeos_points" | "badgeos_achievements" | "badgeos_ranks" | "results" | "favourites" | "subscribed" | "replies" | "topics" | "activities" | "forums" | "friends" | "blocked_users" | "groups" | "documents"} ProfileTab
*/
/**
* @typedef { "just-me" | "friends" | "groups" | "favorites" | "mentions" | "following" } ActivitiesFilter
*/
/**
* @typedef { "-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"} ActivitiesSubFilter
*/
/**
* Image resource (via request('...src'))
* @typedef {number} LocalImageSource
*/
/**
* @typedef {Object} RemoteImageSource
*/
/**
* @typedef {LocalImageSource | RemoteImageSource} ImageSource
*/
/**
* @typedef {Object} SubscreenObject
* @param {LocalImageSource} icon
* @param {String} label
* @param {?Number} count
* @param {Function} onPress
*/
/**
* @typedef {Function} TransformProfileIgnoredSubscreensCallback
* @param {Array<ProfileTab>} list Ignored subscreens list
* @param {Boolean} isOwnAccount Returns `true` if profile displayed in screen is logged-in user's own account
* @return {Array<string>} New list of ignored subscreens
*/
/**
* @typedef {Function} TransformProfileActivityFilters
* @param {Array<ActivitiesFilter>} list
* @return {Array<string>} - New list
*/
/**
* @typedef {Function} TransformProfileSubscreensListCallback
* @param {Array<SubscreenObject>} list Subscreens list
* @param {NavigationService} navigation
* @param {User} user
* @param {Boolean} isOwnAccount Returns `true` if profile displayed in screen is logged-in user's own account
* @return {Array<SubscreenObject>} New subscreens list
*/
/**
* @typedef {Object} BeforeProfileDetailsComponentProps
* @property { Object } colors App colors
* @property { Object } global App global style
* @property { MemberViewModel } user
*/
/**
* @typedef {Object} AfterProfileDetailsComponentProps
* @property { MemberViewModel } user
*/
/**
* @typedef {Object} UserFullNameComponentProps
* @property { MemberViewModel } user
* @property { Object } global App global style
* @property { Object } textStyle
* @property { ?Object } topicLoading
*/
/**
* @typedef {Object} UserTypeComponentProps
* @property { Boolean } isUserProfile
* @property { MemberViewModel } user
* @property { Object } global App global style
* @property { Object } textStyle
*/
/**
* @typedef {Object} UserHandleComponentProps
* @property { MemberViewModel } user
* @property { Object } global App global style
* @property { Object } textStyle
* @property { Boolean } hideHandle Returns `true` if a setting to hide the handle was set
*/
/**
* @typedef {Object} UserRegisteredComponentProps
* @property { MemberViewModel } user
* @property { Object } global App global style
* @property { TranslationFunction } t
* @property {Function} formatDateFunc Helper function for parsing dates
*/
/**
* @typedef {Object} UserFollowingComponentProps
* @property { MemberViewModel } user
* @property { Object } global App global style
* @property { Object } colors App colors
* @property { TranslationFunction } t
*/
/**
* @typedef {Object} UserAvatarProps
* @property { Boolean } isOwnAccount Returns `true` if the logged-in user is viewing their own account
* @property { TranslationFunction } t
* @property { Object } global
* @property { MemberViewModel } user
*/
/**
* @typedef {Object} AfterProfileHeaderProps
* @property { MemberViewModel } user
*/
/**
* @typedef {Object} ActionButtonProps
* @property {Object} global App global style
* @property {Object} button Default actions when button is pressed
* @property {Object} color Color for icon
* @property {Object} style
* @property {TranslationFunction} t
* @property {Boolean} withLabel Returns `true` if button has label
* @property {Object} labelStyle
* @property {Boolean} loading Returns `true` if component is still loading
* @property {Boolean} first Returns `true` if button is first in the list
* @property {Boolean} last Returns `true` if button is last in the list
* @property {Boolean} highlight Returns `true` if button is highlighted
*/
/**
* @typedef {Function} OnChangeEventListenerCallback
* @param {Number} id Field id
* @param {Number} groupKey Group key
* @param {Boolean} required Returns `true` if value for field is required
* @param {Boolean} isDate Returns `true` if input is date
* @param {String} newValue Returns value of input
*/
/**
* @typedef {Function} TransformEditProfileFieldSetsFilterCallback
* @param {Array<Object>} list List of filters
* @return {Array<Object>} New list of filters
*/
/**
* @typedef {Object} FieldSetObject
* @property {Number} id id of field set
* @property {String} name
* @property {Object} description
* @property {Number} group_order
* @property {Boolean} can_delete Returns `true` if field set can be deleted
* @property {Boolean} repeater_enabled Returns `true` if repeater is enabled
* @property {Array<Object>} fields Fields in a field set
*/
/**
* @typedef {Function} TransformEditProfileFieldSetsCallback
* @param {Array<FieldSetObject>} fieldSets List of field sets
* @return {Array<FieldSetObject>} New list of field sets
*/
/**
* @typedef {Function} TransformViewProfileFieldSetsCallback
* @param {Array<FieldSetObject>} fieldSets List of field sets
* @return {Array<FieldSetObject>} New list of field sets
*/
/**
* @typedef {Function} EditProfileComponentDidUpdateCallback
* @param {Object} prevProps
* @param {Object} prevState
* @param {Object} props
* @param {Object} state
* @param {Function} updateStoreValues Helper function which you can use to update the Edit Profile screen's field values
*/
/**
* @class
* ProfileScreen Hooks.
* Instance name: profileScreenHooksApi
You can use this hook to personalize the profile screen by adding components before/after profile headers, blog details, custom header backgrounds and more.
* @example
* externalCodeSetup.profileScreenHooksApi.METHOD_NAME
*/
export class ProfileScreenHooksApi {
/**
* @deprecated
*/
activityFiltersSubFilter = list => list;
setActivityFiltersSubFilter = activityFiltersSubFilter => {
this.activityFiltersSubFilter = activityFiltersSubFilter;
};
/**
* Sets a default cover
* @private
*/
baseCover;
/**
* @ignore
* Reason for ignore: Function is not used anywhere in the app
* Sets a default cover image. It will override Platform settings.
* @param {LocalImageSource} baseCover
*/
setBaseCover = baseCover => {
this.baseCover = baseCover;
};
/**
* @private
*/
headerBgSource = null;
/**
* @ignore
* Reason for ignore: Hook not being used to replace header background.
* There are some instances where `headerBgSource` is used to check for a condition but it should be replaced by `customHeaderBackground`.
* Set image for Profile Screen header background
* @param {ImageSource}
*/
setHeaderBgSource = source => {
this.headerBgSource = source;
};
profileActivityFiltersFilter = list => list;
/**
* @ignore
* Reason for ignore: Variable assignment is incorrect and filter is not being used in profile activities screen
* Sets the function that can change filters array
* @param {TransformProfileActivityFilters} activityFiltersFilter
* @example
* externalCodeSetup.profileScreenHooksApi.setProfileActivityFiltersFilter((
* list,
* ) => ([
* ...list,
* "followers",
* ]))
*/
setProfileActivityFiltersFilter = activityFiltersFilter => {
this.activityFiltersFilter = activityFiltersFilter;
};
customHeaderBackground = null;
/**
* Replaces cover image for all profiles in the profile screen
* @method
* @param {String} customHeaderBackground Resource to replace cover image
* @example
* externalCodeSetup.profileScreenHooksApi.setCustomHeaderBackground('https://link-to-image.png')
*/
setCustomHeaderBackground = customHeaderBackground => {
this.customHeaderBackground = customHeaderBackground;
};
tabsList = list => list;
/**
* You can use this hook to add or modify existing tabs in the profile screen.
* For example, you can add a new route in profile screen tab list
* @method
* @param {TransformProfileSubscreensListCallback} tabsList
* @example <caption> Add a new route in profile screen tab list </caption>
* ...
* import { CommonActions } from "@react-navigation/native";
* export const applyCustomCode = externalCodeSetup => {
*
* //Register a new route
* externalCodeSetup.navigationApi.addNavigationRoute(
* "book",
* "BookScreen",
* () => <Text>Custom Book Screen</Text>,
* "All"
* );
*
* //Add new menu item to profile screen tab list
* externalCodeSetup.profileScreenHooksApi.setTabsList((
* list,
* navigation,
* user,
* isOwnAccount
* ) => {
* return [
* ...list,
* {
* icon: require("@src/assets/img/about.png"), //Set icon
* label: "Book", //Set label of menu
* onPress: () => navigation.navigate(
* CommonActions.navigate({
* name: "book",
* params: { //Pass params if needed
* user,
* isOwnAccount
* },
* key: user.id
* })
* )
* }
* ]
* })
* }
*/
setTabsList = tabsList => {
this.tabsList = tabsList;
};
/**
* Hides user handle in profile header
* @private
*/
hideHandle = false;
/**
* Hides user handle in profile header by passing it as a `true` value.
* @method
* @param {Boolean} hideHandle
* @example
* externalCodeSetup.profileScreenHooksApi.setHideHandle(true)
*/
setHideHandle = hideHandle => {
this.hideHandle = hideHandle;
};
/**
* filter ignored tabs on profile
* @private
*/
ignoreTabsFilter = (tabs, own) => tabs;
/**
* You can use this to set a function that is capable of hiding specific profile menu items.
* @method
* @param {TransformProfileIgnoredSubscreensCallback} ignoreTabsFilter
* @example
* externalCodeSetup.profileScreenHooksApi.setIgnoreTabsFilter((
* list,
* isOwnAccount
* ) => [
* ...list,
* "activities",
* "friends"
* ])
*/
setIgnoreTabsFilter = ignoreTabsFilter => {
this.ignoreTabsFilter = ignoreTabsFilter;
};
BeforeDetailsComponent = null;
/**
* You can use it to add a component before the profile details.
* @method
* @param {React.ComponentType<BeforeProfileDetailsComponentProps>} BeforeDetailsComponent
* @example
* const BeforeDetailsComponent = ({user}) => (
* <Text>User Type: {user.type}</Text>
* )
*
* externalCodeSetup.profileScreenHooksApi.setBeforeDetailsComponent(BeforeDetailsComponent)
*/
setBeforeDetailsComponent = BeforeDetailsComponent => {
this.BeforeDetailsComponent = BeforeDetailsComponent;
};
AfterDetailsComponent = null;
/**
* You can use this to add a component after the profile details. For example, you can add more information about your profile in the custom component.
* @method
* @param {React.ComponentType<AfterProfileDetailsComponentProps>} AfterDetailsComponent
* @example
* const AfterDetailsComponent = ({ user }) => (
* <Text>Last activity: {user.lastActivity}</Text>
* )
*
* externalCodeSetup.profileScreenHooksApi.setAfterDetailsComponent(AfterDetailsComponent)
*/
setAfterDetailsComponent = AfterDetailsComponent => {
this.AfterDetailsComponent = AfterDetailsComponent;
};
UserFullNameComponent = null;
/**
* You can use this to replace the user full name component and customize the name display according to your app preferences.
* @method
* @param {React.ComponentType<UserFullNameComponentProps>} UserFullNameComponent
* @example
* const UserFullNameComponent = (props) => (
* <View>
* <Text style={{fontSize: 20, color: "red"}}>
* {props.user.fullname}
* </Text>
* </View>
* )
*
* externalCodeSetup.profileScreenHooksApi.setUserFullNameComponent(UserFullNameComponent)
*/
setUserFullNameComponent = UserFullNameComponent => {
this.UserFullNameComponent = UserFullNameComponent;
};
UserTypeComponent = null;
/**
* You can use this to replace the user type component for the various app users.
* @method
* @param {React.ComponentType<UserTypeComponentProps>} UserTypeComponent
* @example
*
* const UserTypeComponent = (props) => (
* <View>
* <Text>
* User type: {props.user.type}
* </Text>
* </View>
* )
* externalCodeSetup.profileScreenHooksApi.setUserTypeComponent(UserTypeComponent);
*/
setUserTypeComponent = UserTypeComponent => {
this.UserTypeComponent = UserTypeComponent;
};
UserHandleComponent = null;
/**
* It is used to replace the default user handle component.
* @method
* @param {React.ComponentType<UserHandleComponentProps>} UserHandleComponent
* @example
*
* const UserHandleComponent = (props) => (
* <Text style={{color: "blue", fontSize: 30}}> @{props.user.nicename} </Text>
* )
*
* externalCodeSetup.profileScreenHooksApi.setUserHandleComponent(UserHandleComponent)
*/
setUserHandleComponent = UserHandleComponent => {
this.UserHandleComponent = UserHandleComponent;
};
UserRegisteredComponent = null;
/**
* It is used to replace user registration details component.
* @method
* @param {React.ComponentType<UserRegisteredComponentProps>} UserRegisteredComponent
* @example
*
* const UserRegisteredComponent = (props) => (
* <View style={{ marginVertical: 5 }}>
* <Text>Date registered: {props.formatDateFunc(props.user.registeredDate)}</Text>
* </View>
* )
*
* externalCodeSetup.profileScreenHooksApi.setUserRegisteredComponent(UserRegisteredComponent)
*/
setUserRegisteredComponent = UserRegisteredComponent => {
this.UserRegisteredComponent = UserRegisteredComponent;
};
UserFollowingComponent = null;
/**
* You can use this to replace the user's following and/or follower details component.
* @param {React.ComponentType<UserFollowingComponentProps>} UserFollowingComponent
* @example
*
* const UserFollowingComponent = (props) => (
* <View style={{ flexDirection: "row" }}>
* <Text> {props.user.followers} Followers </Text>
* <Text> {props.user.following} Following </Text>
* </View>
* )
*
* externalCodeSetup.profileScreenHooksApi.setUserFollowingComponent(UserFollowingComponent)
*/
setUserFollowingComponent = UserFollowingComponent => {
this.UserFollowingComponent = UserFollowingComponent;
};
UserAvatar = null;
/**
* You can use it to replace the user avatar component.
* @method
* @param {React.ComponentType<UserAvatarProps>} UserAvatar
* @example
* ...
* import AvatarImageUpload from "@src/components/AvatarImageUpload"
* export const applyCustomCode = externalCodeSetup => {
*
* const UserAvatar = (props) => {
* return (
* <>
* <Text>Tap avatar to edit</Text>
* <AvatarImageUpload
* isOwnAccount={props.isOwnAccount}
* user={props.user}
* size={100}
* imagePickerProps={{ cropping: true, cropperCircleOverlay: true }}
* />
* </>
* )
* }
*
* externalCodeSetup.profileScreenHooksApi.setUserAvatar(UserAvatar)
*
*/
setUserAvatar = UserAvatar => {
this.UserAvatar = UserAvatar;
};
AfterProfileHeader = null;
/**
* It adds a component after the profile header.
* @method
* @param {React.ComponentType<AfterProfileHeaderProps>} AfterProfileHeader
* @example
*
* const AfterProfileHeader = (props) => (
* <View style={{ marginLeft: 20 }}>
* <Text> User Points: {props.user.points} </Text>
* </View>
* )
*
* externalCodeSetup.profileScreenHooksApi.setAfterProfileHeader(AfterProfileHeader)
*
*/
setAfterProfileHeader = AfterProfileHeader => {
this.AfterProfileHeader = AfterProfileHeader;
};
HeaderRightComponent = null;
/**
* You can use it to add a component on the top right corner of the profile screen for users.
* @method
* @param {React.ComponentType<HeaderRightComponent>} HeaderRightComponent
* @example
*
* //In custom_code/components/ProfileHeaderButton.js
*
* ...
*
* import { Alert } from "react-native";
* import IconButton from "@src/components/IconButton";
* import { globalStyle } from "@src/styles/global";
* import { useSelector } from "react-redux"; //use useSelector to get state from redux
*
* export const ProfileHeaderButton = () => {
*
* const globalStyles = useSelector((state) => globalStyle(state.config.styles)) // Get style from redux
* const user = useSelector((state) => state.user.userObject); // Get user from redux
* const { colors } = globalStyles;
* return (
* <IconButton
* icon={require("@src/assets/img/plus-circle.png")}
* pressHandler={() => Alert.alert(`Hello ${user.nicename}!`) }// Do something here such as call api requests
* tintColor={colors.headerIconColor}
* style={{
* height: 28
* }}
* />
* )
*
* }
*
*
* //In custom_code/index.js
*
* ...
*
* import { ProfileHeaderButton } from "./components/ProfileHeaderButton";
*
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.profileScreenHooksApi.setHeaderRightComponent(() => <ProfileHeaderButton />)
* };
*/
setHeaderRightComponent = HeaderRightComponent => {
this.HeaderRightComponent = HeaderRightComponent;
};
ActionButton = null;
/**
* You can use this hook to replace the action button in the profile header component.
* @method
* @param {React.ComponentType<ActionButtonProps>} ActionButton
* @example
* ...
*
* export const applyCustomCode = externalCodeSetup => {
* const RoundIconButton = ({
* global,
* button,
* color,
* style,
* t,
* withLabel,
* labelStyle,
* loading,
* first,
* last,
* highlight
* }) => (
* <>
* <View
* style={[
* {justifyContent: "center", alignItems: "center"},
* highlight
* ? global.wrappedIconButtonHighlight
* : styles.roundActionButton,
* !first && !withLabel && {marginLeft: 10},
* !last && !withLabel && {marginRight: 10},
* style
* ]}
* activeOpacity={1}
* >
* {!loading &&
* button.icon && (
* <Icon
* tintColor={highlight ? "#fff" : color || "#000"}
* icon={button.icon}
* styles={{height: 26, width: 26}}
* />
* )}
* {loading && (
* <ActivityIndicator
* animating={true}
* style={styles.indicator}
* color={color}
* size="small"
* />
* )}
* </View>
* {withLabel && (
* <View style={{height: 40, paddingTop: 10}}>
* <Text
* ellipsizeMode="tail"
* numberOfLines={2}
* style={
* [global.actionIconText, {textAlign: "center"}, labelStyle]
* }
* >
* {t(button.label)}
* </Text>
* </View>
* )}
* </>
* );
*
* const styles = StyleSheet.create({
* indicator: {opacity: 0.45},
* roundActionButton: {
* backgroundColor: "#EDEEF2",
* borderRadius: 24,
* width: 48,
* height: 48,
* justifyContent: "center",
* alignItems: "center",
* marginHorizontal: 5
* }
* });
*
* externalCodeSetup.profileScreenHooksApi.setActionButton((props) => <RoundIconButton {...props} />)
* }
*/
setActionButton = ActionButton => {
this.ActionButton = ActionButton;
};
editProfileFieldSetsFilter = list => list;
/**
* Sets the filters available on the Edit Profile screen as the filter tabs.
* For example, you can use this hook to remove a specific filter. However, this does not remove the corresponding field set of the removed filter.
* @method
* @param {TransformEditProfileFieldSetsFilterCallback} editProfileFieldSetsFilter
* @example <caption> Change name of filter with id 1 </caption>
*
* export const applyCustomCode = externalCodeSetup => {
*
* externalCodeSetup.profileScreenHooksApi.setEditProfileFieldSetsFilter(props => {
* if (Array.isArray(props.filters)){
*
* const modifiedFilters = props.filters.map(obj => {
*
* if (obj.id === 1){
* return {
* ...obj,
* name: "New name"
* }
* }
*
* return obj;
* })
*
* return {
* ...props,
* filters: modifiedFilters
* };
*
* }
*
* return props;
*
* });
* }
*/
setEditProfileFieldSetsFilter = editProfileFieldSetsFilter => {
this.editProfileFieldSetsFilter = editProfileFieldSetsFilter;
};
handleInputFieldCallback = null;
/**
* You can use this hook to add a callback to a function when an input field on the profile Edit screen is changed.
* For example, you can add a function to display a prompt whenever the word 'Bar' is typed in a specific profile field.
* @method
* @param {OnChangeEventListenerCallback} onHandledInput
* @example <caption> If "Food" is selected when editing the value in a profile field, change the available field sets in the edit profile screen </caption>
*
* export const applyCustomCode = externalCodeSetup => {
*
* externalCodeSetup.profileScreenHooksApi.addHandleInputFieldCallback(props => {
*
* const { id, newValue } = props;
*
* if (id === 24) {
*
* if (newValue.includes("Food")) {
*
* //If "Food" is selected, display the first field set only
* externalCodeSetup.profileScreenHooksApi.setEditProfileFieldSets(fieldSets => {
* return [...fieldSets].splice(0,1);
* });
*
* } else {
*
* //Reset field sets
* externalCodeSetup.profileScreenHooksApi.setEditProfileFieldSets(fieldSets => fieldSets);
* }
*
* }
* })
* }
*/
addHandleInputFieldCallback = onHandledInput => {
this.handleInputFieldCallback = onHandledInput;
};
editProfileFieldSets = fieldSets => fieldSets;
/**
* Sets the field sets and the filters available on the Edit Profile screen.
* @method
* @param {TransformEditProfileFieldSetsCallback} editProfileFieldSets
* @example <caption>Delete a field from a field set</caption>
*
* export const applyCustomCode = externalCodeSetup => {
*
* externalCodeSetup.profileScreenHooksApi.setEditProfileFieldSets(fieldSets => {
*
* const modifiedFieldSets = fieldSets.map(obj => {
*
* if (obj.id === 1){
*
* //Delete a field from the field set
* const fields = obj.fields.slice(1);
*
* return {
* ...obj,
* fields: fields
* }
* }
* return obj;
* });
*
* return modifiedFieldSets;
* });
* }
*/
setEditProfileFieldSets = editProfileFieldSets => {
this.editProfileFieldSets = editProfileFieldSets;
};
viewProfileFieldSets = fieldSets => fieldSets;
/**
* Used to set and modify the field sets in the View Profile screen.
* You can show/hide the field sets in the View Profile screen.
* @method
* @param {TransformViewProfileFieldSetsCallback} viewProfileFieldSets
* @example
*
* export const applyCustomCode = externalCodeSetup => {
*
* externalCodeSetup.profileScreenHooksApi.setViewProfileFieldSets(fieldSets => {
*
* if (Array.isArray(fieldSets)){
* const modifiedFieldSets = [...fieldSets].slice(1);
*
* return modifiedFieldSets;
* }
*
* return fieldSets;
*
* })
* }
*/
setViewProfileFieldSets = viewProfileFieldSets => {
this.viewProfileFieldSets = viewProfileFieldSets;
};
editProfileComponentDidUpdateCallback = null;
/**
* You can use this hook to set a callback function in the Edit Profile screen's componentDidUpdate function.
* For example, you can use this to make a network request (or call an API) if a state's value is changed.
* @method
* @param {EditProfileComponentDidUpdateCallback} onComponentDidUpdate
* @example <caption>Change edit profile field values based on WebView's message</caption>
*
* //In custom_code/MyCustomScreen.js...
*
* import React, { useState } from 'react';
* import { View, Text, StyleSheet, Button, Modal, TouchableOpacity } from "react-native";
* import isEqual from 'lodash.isequal';
* import { WebView } from 'react-native-webview';
* import EditScreen from "@src/containers/Custom/Profile/Xprofile/Edit";
* import { backButton } from "@src/utils";
* import { getExternalCodeSetup } from '../../src/externalCode/externalRepo';
*
* const MyHTML = require('./../html/sample.html');
*
* const MyModal = ({ modalVisible, setModalVisible, updateStoreValues }) => {
*
* //You can change this according to the message sent by the webview's source
* const matchedMessage = "Clicked!";
*
* return <View style={styles.centeredView}>
* <Modal
* animationType="slide"
* transparent={true}
* visible={modalVisible}
* onRequestClose={() => {
* setModalVisible(!modalVisible);
* }}
* style={{
* margin: 15
* }}
* >
* <WebView
* source={MyHTML}
* onMessage={event => {
*
* const message = event.nativeEvent.data;
*
* if (message == matchedMessage) {
* updateStoreValues()
* }
* }}
*
* />
* <TouchableOpacity
* style={[styles.button, styles.buttonClose]}
* onPress={() => setModalVisible(!modalVisible)}
* >
* <Text style={styles.textStyle}>Hide Modal</Text>
* </TouchableOpacity>
* </Modal>
* </View>
* }
*
* const MyCustomScreen = (props) => {
*
* const matchedValue = "gmap";
*
* const [modalVisible, setModalVisible] = useState(false);
* const [callbackUpdateStoreValues, setCallbackUpdateStoreValues] = useState(null);
*
*
* //Set condition when to open modal. If the field matches the value of matchedValue, then it will open the modal.
* getExternalCodeSetup().profileScreenHooksApi.addHandleInputFieldCallback(props => {
* const { id, newValue, groupKey } = props;
* if (groupKey === 1 && id === 3) {
* if (newValue === matchedValue) {
* setModalVisible(true)
* }
* }
* })
*
* getExternalCodeSetup().profileScreenHooksApi.setEditProfileComponentDidUpdateCallback(paramProps => {
*
* const {
* prevProps,
* prevState,
* props,
* state,
* updateStoreValues } = paramProps;
*
* //Update callbackUpdateStoreValues only when there are updates in the EditProfile component
* if (!isEqual(state.updates, prevState.updates) && Object.keys(prevState.updates).length !== 0) {
*
* const updateValues = () => {
*
* //You can get the appropriate groupKey and id by doing a console.log for state and/or prevState.
* //In this case, we're updating the store values of groupKey = 1 and id = 1 with a the webViewInput value.
* const groupKey = 1,
* id = 1,
* property = "value",
* webViewInput = "Updated from web view";
*
* updateStoreValues(groupKey, id, property, webViewInput);
*
* }
*
* setCallbackUpdateStoreValues(() => () => updateValues());
* }
*
* });
*
* return <>
* <EditScreen />
* <MyModal
* modalVisible={modalVisible}
* setModalVisible={setModalVisible}
* updateStoreValues={callbackUpdateStoreValues}
* />
* </>
* }
*
* MyCustomScreen.navigationOptions = ({ navigation, screenProps }) => {
* const { t, colors, calcFontSize, global } = screenProps;
* const { borderColor } = colors;
* const { params = {} } = navigation.state;
*
* const hideBackButton = true;
*
* let headerLeft = params.renderHeaderLeft
* ? params.renderHeaderLeft()
* : backButton({
* navigation,
* headerColor: colors.headerIconColor,
* text: t("common:back"),
* textStyle: global.headerText,
* colors
* });
*
* if (hideBackButton) {
* headerLeft = null;
* }
*
* return {
* headerTitle: (
* <Text
* ellipsizeMode="tail"
* numberOfLines={1}
* style={global.appHeaderTitle}
* >
* {t("profile:editXprofile")}
* </Text>
* ),
* tabBarVisible: false,
* headerLeft: headerLeft,
* headerRight: params.renderHeaderRight ? params.renderHeaderRight() : null,
* headerStyle: {
* ...StyleSheet.flatten(global.header),
* borderBottomColor: borderColor,
* borderBottomWidth: StyleSheet.hairlineWidth
* }
* };
* };
*
* export default MyCustomScreen;
*
* const styles = StyleSheet.create({
* centeredView: {
* justifyContent: "center",
* alignItems: "center",
* },
* button: {
* position: "absolute",
* bottom: 80,
* width: "50%",
* borderRadius: 20,
* padding: 10,
* elevation: 2,
* alignSelf: "center"
* },
* buttonClose: {
* backgroundColor: "#2196F3",
* },
* textStyle: {
* color: "white",
* fontWeight: "bold",
* textAlign: "center"
* }
* });
*
* //In custom_code/html/sample.html...
* <!DOCTYPE html>
* <html>
* <meta name="viewport" content="width=device-width, initial-scale=1">
*
* <head>
* <style>
* body {
* background-color: #18222d;
* height: 100vh;
* display: flex;
* justify-content: center;
* align-items: center;
* }
* </style>
* </head>
* <body>
* <div>
* <button type="button" onclick="clicked()">Click Me!</button>
* </div>
* <script>
* const OS = "ios";
* const sendMessageToRN = (message) => {
* if (OS === "ios") {
* if (window.ReactNativeWebView.postMessage.length !== 1) {
* setTimeout(sendMessageToRN(message), 200);
* } else {
* window.ReactNativeWebView.postMessage(message);
* }
* } else {
* window.ReactNativeWebView.postMessage(message);
* setTimeout(() => window.ReactNativeWebView.postMessage(message), 50);
* }
* }
* const clicked = () => {
* sendMessageToRN("Clicked!")
* }
* </script>
* </body>
*
* </html>
*
* //In custom_code/index.js...
*
* ...
*
* import MyCustomScreen from "./components/MyCustomScreen";
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.navigationApi.replaceScreenComponent("EditXprofile", MyCustomScreen);
* }
*
*
*/
setEditProfileComponentDidUpdateCallback = onComponentDidUpdate => {
this.editProfileComponentDidUpdateCallback = onComponentDidUpdate;
};
}
Source