Methods
# setFetchParamsFilter(fetchParamsFilter)
It overrides the parameters that are used to fetch topics in the Topics screen so that you can make it as customizable as possible when calling its API.
Parameters:
Name | Type | Description |
---|---|---|
fetchParamsFilter |
TransformTopicsParams |
Example
//In custom_code/components/TopicsFiltersCustom.js...
import React, { useState } from "react";
import { TextInput, View, Button, Text, Switch } from 'react-native'
import { useDispatch } from "react-redux";
import { topicsLoadRequest } from "@src/actions/topics";
import { getExternalCodeSetup } from "@src/externalCode/externalRepo";
import withGlobalStyles from "@src/components/hocs/withGlobalStyles";
const hook = getExternalCodeSetup().topicsApi;
const screenName = "topics";
getExternalCodeSetup().indexScreenApiHooks.setHeaderHeight((defaultHeaderHeight, filterType, navigation) => {
if (filterType === "topics"){
return 300
}
return defaultHeaderHeight;
});
const filter = "all";
const subfilters = {
orderby: "activity", //"meta_value", "date", "ID", "author", "title", "modified", "parent", "rand", "popular", "activity"
order: "desc"
}
const refresh = true; //Set to true to refresh list
const searchTerm = ""
const TopicsFiltersCustom = (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 [tag, setTag] = useState(false);
const handleSubmit = () => {
//Set custom parameters before fetching
hook.setFetchParamsFilter((props) => {
//You can add more parameters such as "subject", "keyword" etc...
return {
...props,
tag
}
})
//Dispatch redux action to call api using customized filters
dispatch(topicsLoadRequest(filter, subfilters, refresh, searchTerm));
}
return <View style={{ backgroundColor: colors.whiteColor, alignItems: "center", justifyContent: "center" }}>
<TextInput
style={{paddingHorizontal: 20, marginTop: 10, fontSize: 20}}
autoFocus
value={tag}
onChangeText={tag => setTag(tag)}
placeholder="Search for tag..."
/>
<Button
onPress={() => handleSubmit()}
title="Filter"
/>
</View>
}
return null;
}
export default withGlobalStyles(TopicsFiltersCustom);
//In custom_code/index.js...
...
import TopicsFiltersCustom from "./components/TopicsFiltersCustom";
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.filterScreenApiHooks.setAfterFilterComponent(TopicsFiltersCustom);
}
# setReplyItemAvatar()
You can use this hook to customize the reply item avatar in the topic single screen. For example, you can add a "verified" icon or text beside the avatar.
- Deprecated:
- Please use the equivalent hook: topicSingleApi.setReplyItemAvatar()
Example
...
import AppAvatar from "@src/components/AppAvatar";
import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.topicsApi.setReplyItemAvatar(props => {
const { reply, global, isNested } = props
return <AppTouchableOpacity
onPress={reply.navigateToProfile ? reply.navigateToProfile : () => { }}
style={global.avatarWrap}
>
<AppAvatar
size={isNested ? 30 : 40}
name={reply.author.fullname}
source={{
uri: reply.author.avatarUrl
}}
/>
<Text>Verified</Text>
</AppTouchableOpacity>
})
}
# setReplyItemContent()
You can use this hook to customize the reply item content.
- Deprecated:
- Please use the equivalent hook: topicSingleApi.setReplyItemContent()
Example
//In custom_code/components/ReplyItemContent.js...
import React from "react";
import {View} from "react-native";
import HTML from "react-native-render-html";
import ReadMore from "@src/components/ReadMore";
import AutoSizeImage from "@src/components/AutoSizeImage";
import ImageCollection from "@src/components/ImageCollection";
import {GifVideoPlayer} from "@src/components/Gif";
import EmbeddedDocumentItem from "@src/components/Documents/EmbeddedDocumentItem";
import {
documentToViewModel
} from "@src/utils";
const ReplyItemContent = ({
content,
readMoreContentSize,
attachmentMarginTop,
formatTextForDisplay,
filterContentCss,
reply,
colors,
t,
global,
tagsStyles,
imagesInitialDimensions,
computedWidth,
referer,
alterChildrenHTML,
attemptDeepLink,
aTagRenderer,
iframeRender
}) => (
<View style={{flex: 1, marginTop: 6}}>
<ReadMore
content={content}
size={readMoreContentSize}
colors={colors}
t={t}
global={global}
>
{content => (
<HTML
tagsStyles={{
...tagsStyles,
div: {
...tagsStyles.p,
},
iframe: {
marginTop: 10
}
}}
baseFontStyle={global.textHtml}
html={content}
imagesInitialDimensions={imagesInitialDimensions}
staticContentMaxWidth={computedWidth}
alterChildren={alterChildrenHTML(computedWidth)}
onLinkPress={attemptDeepLink}
renderers={{
a: aTagRenderer(computedWidth),
iframe: iframeRender(referer),
img: (htmlAttribs, children, convertedCSSStyles, passProps) => {
return (
<AutoSizeImage
url={htmlAttribs.src}
wrapperStyle={{
marginTop: convertedCSSStyles.marginTop,
marginBottom: convertedCSSStyles.marginBottom
}}
style={{
...convertedCSSStyles,
paddingVertical: 100
}}
/>
);
}
}}
/>
)}
</ReadMore>
{!!reply.media && (
<ImageCollection
item={reply}
containerStyle={{marginTop: attachmentMarginTop}}
colors={colors}
global={global}
t={t}
toUserBasedOnSettings={() => reply.navigateToProfile()}
showActionButtons={false}
/>
)}
{!!reply.videos && (
<ImageCollection
item={reply}
containerStyle={{marginTop: attachmentMarginTop}}
colors={colors}
global={global}
t={t}
toUserBasedOnSettings={() => reply.navigateToProfile()}
showActionButtons={false}
/>
)}
{!!reply.gif?.preview_url ? (
<View style={{marginTop: attachmentMarginTop}}>
<GifVideoPlayer
url={reply.gif?.video_url}
poster={reply.gif?.preview_url}
width={computedWidth - 30}
containerStyle={{backgroundColor: "#F9F9F9"}}
/>
</View>
) : null}
{reply?.documents?.length > 0 &&
reply.documents.map(item => {
const viewModel = documentToViewModel(item);
return (
<EmbeddedDocumentItem
{...{
t,
colors,
global,
token,
viewModel,
navigation
}}
/>
);
})}
</View>
);
export default ReplyItemContent
//In custom_code/index.js...
import ReplyItemContent from "./components/ReplyItemContent"
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.topicsApi.setReplyItemContent(props => <ReplyItemContent {...props} />)
}
# setReplyItemHeader()
You can use this hook to customize the reply item header which by default contains the author of the reply and its date.
- Deprecated:
- Please use the equivalent hook: topicSingleApi.setReplyItemHeader()
Example
...
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.topicsApi.setReplyItemHeader(props => {
const { global, headerTitleStyle, reply, formatDateFunc } = props;
return <View style={global.row}>
<Text style={[global.itemName, headerTitleStyle, { marginBottom: 0 }]}>
{reply.author.fullname}
</Text>
{!reply.author.reported && (
<Text style={[global.itemLightMeta, { marginLeft: 8 }]}>
//{formatDateFunc(reply.date)}
{reply.date}
</Text>
)}
</View>
})
}
# setSubFiltersFilter(subFiltersFilter)
You can use this to set the subfilter function to rearrange the order of the filters in the Discussion screen. For example, you can rearrange the labels such as "Date created", "Last Active" and more on the discussions screen under the search bar.
Parameters:
Name | Type | Description |
---|---|---|
subFiltersFilter |
TransformTopicSubFiltersFilterCallback |
Example
externalCodeSetup.topicsApi.setSubFiltersFilter((filters) => {
return ["date"]; //available filters include "activity", "date", "title", "popular"
})
# setTopicItemComponent(TopicItemComponentnullable)
It renders a custom topic item component in the topic list.
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
TopicItemComponent |
React.ComponentType.<TopicItemProps> |
<nullable> |
Example
//In custom_code/components/TopicItem.js
import React from 'react';
import { View, Text, StyleSheet, Animated } from 'react-native';
import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
import {getAvatar} from "@src/utils";
import AppAvatar from "@src/components/AppAvatar";
import AuthWrapper from "@src/components/AuthWrapper";
import ActionSheetButton from "@src/components/ActionButtons/ActionSheetButton";
import {GUTTER} from "@src/styles/global";
const TopicItem = (props) => {
const {topic, styles, actionButtons, formatDateFunc, t} = props;
const global = styles.global;
const colors = styles.colors;
let rootStyle;
if (topic.actionStates.sticky) rootStyle = [global.itemSticky];
if (!topic.actionStates.open) rootStyle = [global.itemClosed];
const Item = <AppTouchableOpacity onPress={topic.toSingle} style={[rootStyle]}>
<Animated.View
style={{
...StyleSheet.absoluteFillObject
}}
/>
<View
style={{
...global.row,
flex: 1,
marginHorizontal: GUTTER
}}
>
<AppAvatar
size={42}
name={topic.author.name}
source={{
uri: getAvatar(topic.author.avatar, 96)
}}
style={{ marginTop: 15, alignSelf: "flex-start" }}
/>
<View
style={{
...global.bottomBorder,
...global.row,
flex: 1,
marginLeft: 10
}}
>
<View
style={[
{
flex: 1,
paddingTop: 15,
paddingBottom: 14,
paddingLeft: 0,
paddingRight: 0
}
]}
>
<Text
style={{
...global.itemTitle,
paddingRight: 40,
marginBottom: 3
}}
numberOfLines={2}
ellipsizeMode={"tail"}
>
{topic.title}
</Text>
<Text numberOfLines={1} ellipsizeMode={"tail"}>{topic.shortContent}</Text>
<View style={{ ...global.row, marginBottom: 5 }}>
<Text style={global.itemMeta}>{topic.voiceCount}</Text>
<View style={global.dotSep} />
<Text style={global.itemMeta}>{topic.replyCount}</Text>
</View>
<Text style={{ ...global.textAlt, color: colors.descTextColor }}>
{t("topics:lastActive", {
date: formatDateFunc(topic.lastActive)
})}
</Text>
</View>
<AuthWrapper actionOnGuestLogin={"hide"}>
<ActionSheetButton
color={colors.textIconColor}
object={topic}
colors={colors}
actionButtons={actionButtons}
headerProps={{
onClick: topic.toSingle,
title: topic.title,
description: t("topics:lastActive", {
date: formatDateFunc(topic.lastActive)
}),
avatarSource: {
uri: getAvatar(topic.author.avatar, 96)
}
}}
global={global}
t={t}
/>
</AuthWrapper>
</View>
</View>
</AppTouchableOpacity>
return Item;
}
export default TopicItem;
//In custom_code/index.js...
...
import TopicItem from "./components/TopicItem";
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.topicsApi.setTopicItemComponent(props => {
return <TopicItem {...props} />;
})
}
# setTopicItemHeader()
You can use this to customize the author name and date in the topic single screen.
- Deprecated:
- Please use the equivalent hook: topicSingleApi.setTopicItemHeader()
Example
//In custom_code/components/TopicItemHeader.js...
import React from "react";
import {View, Text, TouchableOpacity} from "react-native";
import {getAvatar} from "@src/utils";
import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
import AppAvatar from "@src/components/AppAvatar";
const renderVerified = (author) => {
if(author.id === 1){
return <Text style={{fontSize: 10}}>Verified</Text>
}
return null;
}
const ItemHeader = ({
item,
global,
formatDateFunc,
textColor,
linkColor,
light,
alignItems,
avatarSize,
titleStyle,
actionButtons
}) => {
let lightStyle = {};
if (light) lightStyle = {color: "#ffffff"};
let alignStyle = {};
if (alignItems) alignStyle = {alignItems: alignItems};
return (
<View style={[global.itemHeader, alignStyle]}>
<View style={[global.itemLeft, {alignItems: "center"}]}>
<AppTouchableOpacity
onPress={item.navigateToProfile ? item.navigateToProfile : () => {}}
style={global.avatarWrap}
>
<AppAvatar
size={avatarSize}
name={item.author.name}
source={{
uri: getAvatar(item.author.avatar, 96)
}}
/>
</AppTouchableOpacity>
{!!item.author.name && (
<View style={{flex: 1}}>
<Text
style={[
global.itemName,
lightStyle,
titleStyle
]}
>
{item.author.name} {renderVerified(item.author)}
</Text>
<View style={{flexDirection: "row", flexWrap: "wrap"}}>
<Text style={[global.itemMeta, lightStyle]}>
{formatDateFunc(item.lastActive)}
</Text>
</View>
</View>
)}
</View>
</View>
);
};
export default ItemHeader;
//In custom_code/index.js...
...
import TopicItemHeader from "./components/TopicItemHeader";
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.topicsApi.setTopicItemHeader( (props) => <TopicItemHeader {...props} />);
}
# setTopicToViewModelFilter(topicToViewModelFilter)
You can use it to set the callback function that can change an existing topic's view model object.
Parameters:
Name | Type | Description |
---|---|---|
topicToViewModelFilter |
TransformTopicViewModelCallback |
Example
externalCodeSetup.topicsApi.setTopicToViewModelFilter((props, topic) => {
return {
...props,
topicUpvotes: 30
};
})