mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-18 19:01:38 +03:00
Merge pull request #2365 from ecency/sa/cache-in-communities
Implemenetd cache on existing communities structure
This commit is contained in:
commit
e489c2df45
@ -27,6 +27,7 @@ import { getUnreadNotificationCount } from '../../../providers/ecency/ecency';
|
||||
import { decryptKey } from '../../../utils/crypto';
|
||||
import { getPointsSummary} from '../../../providers/ecency/ePoint';
|
||||
import { fetchSubscribedCommunities } from '../../../redux/actions/communitiesAction';
|
||||
import { clearSubscribedCommunitiesCache } from '../../../redux/actions/cacheActions';
|
||||
|
||||
const AccountsBottomSheetContainer = ({ navigation }) => {
|
||||
const intl = useIntl();
|
||||
@ -110,6 +111,7 @@ const AccountsBottomSheetContainer = ({ navigation }) => {
|
||||
_currentAccount.mutes = await getMutes(_currentAccount.username);
|
||||
|
||||
dispatch(updateCurrentAccount(_currentAccount));
|
||||
dispatch(clearSubscribedCommunitiesCache());
|
||||
dispatch(fetchSubscribedCommunities(_currentAccount.username))
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ const CommunitiesList = ({
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
screen,
|
||||
isDiscoversLoading,
|
||||
}) => {
|
||||
const _renderItem = ({ item, index }) => {
|
||||
return (
|
||||
@ -45,28 +46,29 @@ const CommunitiesList = ({
|
||||
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
</>
|
||||
isDiscoversLoading && (
|
||||
<>
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
<CommunitiesPlaceHolder />
|
||||
</>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
{!noResult && (
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={_renderItem}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
/>
|
||||
)}
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={true && _renderItem}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
ListFooterComponent={isDiscoversLoading && <CommunitiesPlaceHolder />}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
@ -28,7 +28,10 @@ const CommunitiesListItem = ({
|
||||
const intl = useIntl();
|
||||
|
||||
const _handleSubscribeButtonPress = () => {
|
||||
handleSubscribeButtonPress({ isSubscribed: isSubscribed, communityId: name }, screen);
|
||||
handleSubscribeButtonPress(
|
||||
{ isSubscribed: isSubscribed, communityId: name, communityTitle: title },
|
||||
screen,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -14,15 +14,18 @@ import {
|
||||
fetchSubscribedCommunities,
|
||||
fetchSubscribedCommunitiesSuccess,
|
||||
} from '../../../../redux/actions/communitiesAction';
|
||||
import { mergeSubCommunitiesCacheInSubList } from '../../../../utils/communitiesUtils';
|
||||
|
||||
const SelectCommunityModalContainer = ({ onPressCommunity, currentAccount, onCloseModal }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [searchedCommunities, setSearchedCommunities] = useState([]);
|
||||
const [showSearchedCommunities, setShowSearchedCommunities] = useState(false);
|
||||
const [subscriptions, setSubscriptions] = useState(null);
|
||||
|
||||
const topCommunities = useSelector((state) => state.communities.communities);
|
||||
const subscribedCommunities = useSelector((state) => state.communities.subscribedCommunities);
|
||||
const subscribedCommunitiesCache = useSelector((state) => state.cache.subscribedCommunities);
|
||||
|
||||
useEffect(() => {
|
||||
callTopCommunities();
|
||||
@ -31,7 +34,22 @@ const SelectCommunityModalContainer = ({ onPressCommunity, currentAccount, onClo
|
||||
|
||||
const callTopCommunities = () => dispatch(fetchCommunities('', 15, '', 'rank'));
|
||||
|
||||
const callSubscribedCommunities = () => dispatch(fetchSubscribedCommunities(currentAccount.name));
|
||||
const callSubscribedCommunities = () => {
|
||||
if (
|
||||
subscribedCommunities &&
|
||||
subscribedCommunities.data &&
|
||||
subscribedCommunities.data.length > 0
|
||||
) {
|
||||
const updatedSubsList = mergeSubCommunitiesCacheInSubList(
|
||||
subscribedCommunities.data,
|
||||
subscribedCommunitiesCache,
|
||||
);
|
||||
if (updatedSubsList && updatedSubsList.length > 0) {
|
||||
setSubscriptions(updatedSubsList.filter((item) => item[4] === true));
|
||||
}
|
||||
}
|
||||
dispatch(fetchSubscribedCommunities(currentAccount.name));
|
||||
};
|
||||
|
||||
const handleChangeSearch = (text) => {
|
||||
if (text.length >= 3) {
|
||||
@ -53,7 +71,7 @@ const SelectCommunityModalContainer = ({ onPressCommunity, currentAccount, onClo
|
||||
<SelectCommunityModalView
|
||||
onPressCommunity={onPressCommunity}
|
||||
topCommunities={topCommunities}
|
||||
subscribedCommunities={subscribedCommunities}
|
||||
subscribedCommunities={subscriptions}
|
||||
onChangeSearch={debounce(handleChangeSearch, 500)}
|
||||
searchedCommunities={searchedCommunities}
|
||||
showSearchedCommunities={showSearchedCommunities}
|
||||
|
@ -60,32 +60,30 @@ const SelectCommunityModalView = ({
|
||||
}}
|
||||
onPress={() => onPressCommunity(null)}
|
||||
/>
|
||||
{!subscribedCommunities.loading &&
|
||||
!subscribedCommunities.error &&
|
||||
subscribedCommunities.data?.length > 0 && (
|
||||
<View>
|
||||
<Text style={[globalStyles.label, styles.title]}>
|
||||
{intl.formatMessage({ id: 'editor.my_communities' }).toUpperCase()}
|
||||
</Text>
|
||||
<FlatList
|
||||
ItemSeparatorComponent={() => <Separator />}
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={subscribedCommunities.data}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item, index, separators }) => {
|
||||
const community = { name: item[0], title: item[1] };
|
||||
return (
|
||||
<CommunityCard
|
||||
community={community}
|
||||
key={community.name}
|
||||
onPress={onPressCommunity}
|
||||
separators={separators}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{subscribedCommunities && (
|
||||
<View>
|
||||
<Text style={[globalStyles.label, styles.title]}>
|
||||
{intl.formatMessage({ id: 'editor.my_communities' }).toUpperCase()}
|
||||
</Text>
|
||||
<FlatList
|
||||
ItemSeparatorComponent={() => <Separator />}
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={subscribedCommunities}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item, index, separators }) => {
|
||||
const community = { name: item[0], title: item[1] };
|
||||
return (
|
||||
<CommunityCard
|
||||
community={community}
|
||||
key={community.name}
|
||||
onPress={onPressCommunity}
|
||||
separators={separators}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{!topCommunities.loading && !topCommunities.error && topCommunities.data?.length > 0 && (
|
||||
<View>
|
||||
<Text style={[globalStyles.label, styles.title]}>
|
||||
|
@ -79,8 +79,11 @@ const SubscribedCommunitiesListView = ({
|
||||
onPress={() =>
|
||||
handleSubscribeButtonPress(
|
||||
{
|
||||
isSubscribed: item[4],
|
||||
communityId: item[0],
|
||||
communityTitle: item[1],
|
||||
userRole: item[2],
|
||||
userLabel: item[3],
|
||||
isSubscribed: item[4],
|
||||
},
|
||||
'communitiesScreenJoinedTab',
|
||||
)
|
||||
|
@ -8,8 +8,11 @@ import {
|
||||
DELETE_COMMENT_CACHE_ENTRY,
|
||||
UPDATE_DRAFT_CACHE,
|
||||
DELETE_DRAFT_CACHE_ENTRY,
|
||||
UPDATE_SUBSCRIBED_COMMUNITY_CACHE,
|
||||
DELETE_SUBSCRIBED_COMMUNITY_CACHE,
|
||||
CLEAR_SUBSCRIBED_COMMUNITIES_CACHE,
|
||||
} from '../constants/constants';
|
||||
import { Comment, Draft, Vote } from '../reducers/cacheReducer';
|
||||
import { Comment, Draft, SubscribedCommunity, Vote } from '../reducers/cacheReducer';
|
||||
|
||||
|
||||
|
||||
@ -87,6 +90,37 @@ export const deleteDraftCacheEntry = (id: string) => ({
|
||||
type: DELETE_DRAFT_CACHE_ENTRY
|
||||
})
|
||||
|
||||
export const updateSubscribedCommunitiesCache = (data: any) => {
|
||||
const path = data.communityId;
|
||||
const created = new Date();
|
||||
const communityTitle = data.communityTitle ? data.communityTitle : '';
|
||||
const userRole = data.userRole ? data.userRole : '';
|
||||
const userLabel = data.userLabel ? data.userLabel : '';
|
||||
|
||||
const subscribedCommunity:SubscribedCommunity = {
|
||||
data : [data.communityId, communityTitle, userRole, userLabel, !data.isSubscribed],
|
||||
expiresAt : created.getTime() + 86400000,
|
||||
};
|
||||
|
||||
return ({
|
||||
payload: {
|
||||
path,
|
||||
subscribedCommunity
|
||||
},
|
||||
type: UPDATE_SUBSCRIBED_COMMUNITY_CACHE
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteSubscribedCommunityCacheEntry = (path: string) => ({
|
||||
payload: path,
|
||||
type: DELETE_SUBSCRIBED_COMMUNITY_CACHE
|
||||
})
|
||||
|
||||
export const clearSubscribedCommunitiesCache = () => ({
|
||||
type: CLEAR_SUBSCRIBED_COMMUNITIES_CACHE
|
||||
})
|
||||
|
||||
|
||||
export const purgeExpiredCache = () => ({
|
||||
type: PURGE_EXPIRED_CACHE
|
||||
})
|
||||
|
@ -45,7 +45,11 @@ export const fetchSubscribedCommunities = (username) => {
|
||||
return (dispatch) => {
|
||||
dispatch({ type: FETCH_SUBSCRIBED_COMMUNITIES });
|
||||
getSubscriptions(username)
|
||||
.then((res) => dispatch(fetchSubscribedCommunitiesSuccess(res)))
|
||||
.then((res) => {
|
||||
res.forEach((item) => item.push(true)); //add true value for subscribe status
|
||||
res.sort((a, b) => a[1].localeCompare(b[1]));
|
||||
dispatch(fetchSubscribedCommunitiesSuccess(res));
|
||||
})
|
||||
.catch((err) => dispatch(fetchSubscribedCommunitiesFail(err)));
|
||||
};
|
||||
};
|
||||
|
6
src/redux/constants/communitiesConstants.ts
Normal file
6
src/redux/constants/communitiesConstants.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export const statusMessage = {
|
||||
PENDING : 'PENDING',
|
||||
SUCCESS : 'SUCCESS',
|
||||
FAIL : 'FAIL',
|
||||
};
|
||||
|
@ -114,6 +114,9 @@ export const DELETE_COMMENT_CACHE_ENTRY = 'DELETE_COMMENT_CACHE_ENTRY';
|
||||
export const UPDATE_DRAFT_CACHE = 'UPDATE_DRAFT_CACHE';
|
||||
export const DELETE_DRAFT_CACHE_ENTRY = 'DELETE_DRAFT_CACHE_ENTRY';
|
||||
export const DEFAULT_USER_DRAFT_ID = 'DEFAULT_USER_DRAFT_ID_';
|
||||
export const UPDATE_SUBSCRIBED_COMMUNITY_CACHE = 'UPDATE_SUBSCRIBED_COMMUNITY_CACHE';
|
||||
export const DELETE_SUBSCRIBED_COMMUNITY_CACHE = 'DELETE_SUBSCRIBED_COMMUNITY_CACHE';
|
||||
export const CLEAR_SUBSCRIBED_COMMUNITIES_CACHE = 'CLEAR_SUBSCRIBED_COMMUNITIES_CACHE';
|
||||
|
||||
// TOOLTIPS
|
||||
export const REGISTER_TOOLTIP = 'REGISTER_TOOLTIP';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PURGE_EXPIRED_CACHE, UPDATE_VOTE_CACHE, UPDATE_COMMENT_CACHE, DELETE_COMMENT_CACHE_ENTRY, DELETE_DRAFT_CACHE_ENTRY, UPDATE_DRAFT_CACHE, } from "../constants/constants";
|
||||
import { PURGE_EXPIRED_CACHE, UPDATE_VOTE_CACHE, UPDATE_COMMENT_CACHE, DELETE_COMMENT_CACHE_ENTRY, DELETE_DRAFT_CACHE_ENTRY, UPDATE_DRAFT_CACHE, UPDATE_SUBSCRIBED_COMMUNITY_CACHE, DELETE_SUBSCRIBED_COMMUNITY_CACHE, CLEAR_SUBSCRIBED_COMMUNITIES_CACHE, } from "../constants/constants";
|
||||
|
||||
export interface Vote {
|
||||
amount:number;
|
||||
@ -37,10 +37,15 @@ export interface Draft {
|
||||
expiresAt?:number;
|
||||
}
|
||||
|
||||
export interface SubscribedCommunity {
|
||||
data: Array<any>,
|
||||
expiresAt?:number;
|
||||
}
|
||||
interface State {
|
||||
votes:Map<string, Vote>
|
||||
comments:Map<string, Comment> //TODO: handle comment array per post, if parent is same
|
||||
drafts: Map<string, Draft>
|
||||
subscribedCommunities: Map<string, SubscribedCommunity>
|
||||
lastUpdate:{
|
||||
postPath:string,
|
||||
updatedAt:number,
|
||||
@ -52,6 +57,7 @@ const initialState:State = {
|
||||
votes:new Map(),
|
||||
comments:new Map(),
|
||||
drafts: new Map(),
|
||||
subscribedCommunities: new Map(),
|
||||
lastUpdate:null,
|
||||
};
|
||||
|
||||
@ -121,6 +127,28 @@ const initialState:State = {
|
||||
}
|
||||
return { ...state }
|
||||
|
||||
case UPDATE_SUBSCRIBED_COMMUNITY_CACHE:
|
||||
if(!state.subscribedCommunities){
|
||||
state.subscribedCommunities = new Map<string, SubscribedCommunity>();
|
||||
}
|
||||
const subscribedCommunities = new Map(state.subscribedCommunities);
|
||||
subscribedCommunities.set(payload.path, payload.subscribedCommunity);
|
||||
return {
|
||||
...state, //spread operator in requried here, otherwise persist do not register change
|
||||
subscribedCommunities: subscribedCommunities
|
||||
};
|
||||
|
||||
case DELETE_SUBSCRIBED_COMMUNITY_CACHE:
|
||||
if (state.subscribedCommunities && state.subscribedCommunities.has(payload)) {
|
||||
state.subscribedCommunities.delete(payload);
|
||||
}
|
||||
return { ...state }
|
||||
|
||||
case CLEAR_SUBSCRIBED_COMMUNITIES_CACHE:
|
||||
state.subscribedCommunities = new Map<string, SubscribedCommunity>();
|
||||
|
||||
return {...state}
|
||||
|
||||
case PURGE_EXPIRED_CACHE:
|
||||
const currentTime = new Date().getTime();
|
||||
|
||||
@ -147,6 +175,14 @@ const initialState:State = {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if(state.subscribedCommunities && state.subscribedCommunities.size){
|
||||
Array.from(state.subscribedCommunities).forEach((entry)=>{
|
||||
if(entry[1].expiresAt < currentTime){
|
||||
state.subscribedCommunities.delete(entry[0]);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...state
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
LEAVE_COMMUNITY_SUCCESS,
|
||||
LEAVE_COMMUNITY_FAIL,
|
||||
} from '../constants/constants';
|
||||
import { statusMessage } from '../constants/communitiesConstants';
|
||||
|
||||
const initialState = {
|
||||
communities: {
|
||||
@ -23,6 +24,7 @@ const initialState = {
|
||||
data: [],
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
subscribingCommunitiesInFeedScreen: {
|
||||
//['name']: {
|
||||
@ -90,6 +92,7 @@ export default function (state = initialState, action) {
|
||||
data: [],
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
};
|
||||
case FETCH_SUBSCRIBED_COMMUNITIES_SUCCESS:
|
||||
@ -99,6 +102,7 @@ export default function (state = initialState, action) {
|
||||
data: action.payload || [],
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
};
|
||||
case FETCH_SUBSCRIBED_COMMUNITIES_FAIL:
|
||||
@ -108,6 +112,7 @@ export default function (state = initialState, action) {
|
||||
data: [],
|
||||
loading: false,
|
||||
error: action.payload,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
};
|
||||
case SUBSCRIBE_COMMUNITY:
|
||||
@ -121,6 +126,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -133,6 +139,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -145,6 +152,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -157,6 +165,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -174,6 +183,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -186,6 +196,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -198,6 +209,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -210,6 +222,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -227,6 +240,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -239,6 +253,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -251,6 +266,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -263,6 +279,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -280,6 +297,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -292,6 +310,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -304,6 +323,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -316,6 +336,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: true,
|
||||
error: false,
|
||||
status: statusMessage.PENDING,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -333,6 +354,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -345,6 +367,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -357,6 +380,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -369,6 +393,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: false,
|
||||
loading: false,
|
||||
error: false,
|
||||
status: statusMessage.SUCCESS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -386,6 +411,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -398,6 +424,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -410,6 +437,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -422,6 +450,7 @@ export default function (state = initialState, action) {
|
||||
isSubscribed: true,
|
||||
loading: false,
|
||||
error: true,
|
||||
status: statusMessage.FAIL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -13,12 +13,14 @@ const transformCacheVoteMap = createTransform(
|
||||
votes : Array.from(inboundState.votes),
|
||||
comments : Array.from(inboundState.comments),
|
||||
drafts : Array.from(inboundState.drafts),
|
||||
subscribedCommunities: Array.from(inboundState.subscribedCommunities)
|
||||
}),
|
||||
(outboundState) => ({
|
||||
...outboundState,
|
||||
votes:new Map(outboundState.votes),
|
||||
comments:new Map(outboundState.comments),
|
||||
drafts: new Map(outboundState.drafts)
|
||||
drafts: new Map(outboundState.drafts),
|
||||
subscribedCommunities: new Map(outboundState.subscribedCommunities)
|
||||
}),
|
||||
{whitelist:['cache']}
|
||||
);
|
||||
|
@ -1,14 +1,27 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { shuffle } from 'lodash';
|
||||
import { shuffle, isEmpty } from 'lodash';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
import { getCommunities, getSubscriptions } from '../../../providers/hive/dhive';
|
||||
|
||||
import { subscribeCommunity, leaveCommunity } from '../../../redux/actions/communitiesAction';
|
||||
import {
|
||||
subscribeCommunity,
|
||||
leaveCommunity,
|
||||
fetchSubscribedCommunitiesSuccess,
|
||||
} from '../../../redux/actions/communitiesAction';
|
||||
import { statusMessage } from '../../../redux/constants/communitiesConstants';
|
||||
import {
|
||||
deleteSubscribedCommunityCacheEntry,
|
||||
updateSubscribedCommunitiesCache,
|
||||
} from '../../../redux/actions/cacheActions';
|
||||
import {
|
||||
mergeSubCommunitiesCacheInDiscoverList,
|
||||
mergeSubCommunitiesCacheInSubList,
|
||||
} from '../../../utils/communitiesUtils';
|
||||
|
||||
const CommunitiesContainer = ({ children, navigation }) => {
|
||||
const dispatch = useDispatch();
|
||||
@ -17,23 +30,67 @@ const CommunitiesContainer = ({ children, navigation }) => {
|
||||
const [discovers, setDiscovers] = useState([]);
|
||||
const [subscriptions, setSubscriptions] = useState([]);
|
||||
const [isSubscriptionsLoading, setIsSubscriptionsLoading] = useState(true);
|
||||
const [isDiscoversLoading, setIsDiscoversLoading] = useState(true);
|
||||
const [selectedCommunityItem, setSelectedCommunityItem] = useState(null);
|
||||
|
||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||
const pinCode = useSelector((state) => state.application.pin);
|
||||
const subscribedCommunities = useSelector((state) => state.communities.subscribedCommunities);
|
||||
const subscribingCommunitiesInDiscoverTab = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
);
|
||||
const subscribingCommunitiesInJoinedTab = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInCommunitiesScreenJoinedTab,
|
||||
);
|
||||
const subscribedCommunitiesCache = useSelector((state) => state.cache.subscribedCommunities);
|
||||
|
||||
useEffect(() => {
|
||||
_getSubscriptions();
|
||||
}, []);
|
||||
|
||||
// handle cache in joined/membership tab
|
||||
useEffect(() => {
|
||||
if (subscribingCommunitiesInJoinedTab && selectedCommunityItem) {
|
||||
const { status } = subscribingCommunitiesInJoinedTab[selectedCommunityItem.communityId];
|
||||
if (status === statusMessage.SUCCESS) {
|
||||
dispatch(updateSubscribedCommunitiesCache(selectedCommunityItem));
|
||||
}
|
||||
}
|
||||
}, [subscribingCommunitiesInJoinedTab]);
|
||||
|
||||
// handle cache in discover tab
|
||||
useEffect(() => {
|
||||
if (subscribingCommunitiesInDiscoverTab && selectedCommunityItem) {
|
||||
const { status } = subscribingCommunitiesInDiscoverTab[selectedCommunityItem.communityId];
|
||||
if (status === statusMessage.SUCCESS) {
|
||||
dispatch(updateSubscribedCommunitiesCache(selectedCommunityItem));
|
||||
}
|
||||
}
|
||||
}, [subscribingCommunitiesInDiscoverTab]);
|
||||
|
||||
// side effect for subscribed communities cache update
|
||||
useEffect(() => {
|
||||
if (
|
||||
subscribedCommunitiesCache &&
|
||||
subscribedCommunitiesCache.size &&
|
||||
subscriptions &&
|
||||
subscriptions.length > 0
|
||||
) {
|
||||
const updatedSubsList = mergeSubCommunitiesCacheInSubList(
|
||||
subscriptions,
|
||||
subscribedCommunitiesCache,
|
||||
);
|
||||
const updatedDiscoversList = mergeSubCommunitiesCacheInDiscoverList(
|
||||
discovers,
|
||||
subscribedCommunitiesCache,
|
||||
);
|
||||
setSubscriptions(updatedSubsList.slice());
|
||||
setDiscovers(updatedDiscoversList);
|
||||
}
|
||||
}, [subscribedCommunitiesCache]);
|
||||
|
||||
useEffect(() => {
|
||||
const discoversData = [...discovers];
|
||||
|
||||
Object.keys(subscribingCommunitiesInDiscoverTab).map((communityId) => {
|
||||
if (!subscribingCommunitiesInDiscoverTab[communityId].loading) {
|
||||
if (!subscribingCommunitiesInDiscoverTab[communityId].error) {
|
||||
@ -58,36 +115,54 @@ const CommunitiesContainer = ({ children, navigation }) => {
|
||||
}, [subscribingCommunitiesInDiscoverTab]);
|
||||
|
||||
useEffect(() => {
|
||||
const subscribedsData = [...subscriptions];
|
||||
|
||||
Object.keys(subscribingCommunitiesInJoinedTab).map((communityId) => {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].loading) {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].error) {
|
||||
if (subscribingCommunitiesInJoinedTab[communityId].isSubscribed) {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = false;
|
||||
}
|
||||
});
|
||||
if (!isEmpty(subscribingCommunitiesInJoinedTab)) {
|
||||
const subscribedsData = mergeSubCommunitiesCacheInSubList(
|
||||
subscribedCommunities.data,
|
||||
subscribedCommunitiesCache,
|
||||
);
|
||||
Object.keys(subscribingCommunitiesInJoinedTab).map((communityId) => {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].loading) {
|
||||
if (!subscribingCommunitiesInJoinedTab[communityId].error) {
|
||||
if (subscribingCommunitiesInJoinedTab[communityId].isSubscribed) {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
subscribedsData.forEach((item) => {
|
||||
if (item[0] === communityId) {
|
||||
item[4] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setSubscriptions(subscribedsData);
|
||||
setSubscriptions(subscribedsData);
|
||||
}
|
||||
}, [subscribingCommunitiesInJoinedTab]);
|
||||
|
||||
const _getSubscriptions = () => {
|
||||
setIsSubscriptionsLoading(true);
|
||||
setIsDiscoversLoading(true);
|
||||
if (
|
||||
subscribedCommunities &&
|
||||
subscribedCommunities.data &&
|
||||
subscribedCommunities.data.length > 0
|
||||
) {
|
||||
const updatedSubsList = mergeSubCommunitiesCacheInSubList(
|
||||
subscribedCommunities.data,
|
||||
subscribedCommunitiesCache,
|
||||
);
|
||||
setSubscriptions(updatedSubsList.slice());
|
||||
setIsSubscriptionsLoading(false);
|
||||
}
|
||||
getSubscriptions(currentAccount.username)
|
||||
.then((subs) => {
|
||||
subs.forEach((item) => item.push(true));
|
||||
_invalidateSubscribedCommunityCache(subs); // invalidate subscribed communities cache item when latest data is available
|
||||
getCommunities('', 50, null, 'rank').then((communities) => {
|
||||
communities.forEach((community) =>
|
||||
Object.assign(community, {
|
||||
@ -97,17 +172,30 @@ const CommunitiesContainer = ({ children, navigation }) => {
|
||||
}),
|
||||
);
|
||||
|
||||
setSubscriptions(subs);
|
||||
setDiscovers(shuffle(communities));
|
||||
setSubscriptions(mergeSubCommunitiesCacheInSubList(subs, subscribedCommunitiesCache)); //merge cache with fetched data
|
||||
setDiscovers(communities);
|
||||
setIsSubscriptionsLoading(false);
|
||||
setIsDiscoversLoading(false);
|
||||
dispatch(
|
||||
fetchSubscribedCommunitiesSuccess(subs.sort((a, b) => a[1].localeCompare(b[1]))),
|
||||
); //register subscribed data in communities store
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('Failed to get subscriptions', err);
|
||||
setIsSubscriptionsLoading(false);
|
||||
setIsDiscoversLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const _invalidateSubscribedCommunityCache = (fetchedList) => {
|
||||
fetchedList.map((listItem) => {
|
||||
let itemExists = subscribedCommunitiesCache.get(listItem[0]);
|
||||
if (itemExists) {
|
||||
dispatch(deleteSubscribedCommunityCacheEntry(listItem[0]));
|
||||
}
|
||||
});
|
||||
};
|
||||
// Component Functions
|
||||
const _handleOnPress = (name) => {
|
||||
navigation.navigate({
|
||||
@ -119,6 +207,7 @@ const CommunitiesContainer = ({ children, navigation }) => {
|
||||
};
|
||||
|
||||
const _handleSubscribeButtonPress = (data, screen) => {
|
||||
setSelectedCommunityItem(data); //set selected item to handle its cache
|
||||
let subscribeAction;
|
||||
let successToastText = '';
|
||||
let failToastText = '';
|
||||
@ -156,6 +245,7 @@ const CommunitiesContainer = ({ children, navigation }) => {
|
||||
subscribingCommunitiesInDiscoverTab,
|
||||
subscribingCommunitiesInJoinedTab,
|
||||
isSubscriptionsLoading,
|
||||
isDiscoversLoading,
|
||||
handleOnPress: _handleOnPress,
|
||||
handleSubscribeButtonPress: _handleSubscribeButtonPress,
|
||||
handleGetSubscriptions: _getSubscriptions,
|
||||
|
@ -47,6 +47,7 @@ const CommunitiesScreen = () => {
|
||||
subscribingCommunitiesInJoinedTab,
|
||||
handleGetSubscriptions,
|
||||
isSubscriptionsLoading,
|
||||
isDiscoversLoading,
|
||||
}) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
@ -87,6 +88,7 @@ const CommunitiesScreen = () => {
|
||||
isLoggedIn={true}
|
||||
noResult={discovers.length === 0}
|
||||
screen="communitiesScreenDiscoverTab"
|
||||
isDiscoversLoading={isDiscoversLoading}
|
||||
/>
|
||||
</View>
|
||||
</ScrollableTabView>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import get from 'lodash/get';
|
||||
import { connect, useDispatch } from 'react-redux';
|
||||
import { connect, useDispatch, useSelector } from 'react-redux';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { getCommunity, getSubscriptions } from '../../../providers/hive/dhive';
|
||||
@ -9,14 +9,32 @@ import { getCommunity, getSubscriptions } from '../../../providers/hive/dhive';
|
||||
import { subscribeCommunity, leaveCommunity } from '../../../redux/actions/communitiesAction';
|
||||
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
import { updateSubscribedCommunitiesCache } from '../../../redux/actions/cacheActions';
|
||||
import { statusMessage } from '../../../redux/constants/communitiesConstants';
|
||||
|
||||
const CommunityContainer = ({ children, navigation, currentAccount, pinCode, isLoggedIn }) => {
|
||||
const [data, setData] = useState(null);
|
||||
const [isSubscribed, setIsSubscribed] = useState(false);
|
||||
const [selectedCommunityItem, setSelectedCommunityItem] = useState(null);
|
||||
|
||||
const tag = get(navigation, 'state.params.tag');
|
||||
const dispatch = useDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const subscribingCommunitiesInDiscoverTab = useSelector(
|
||||
(state) => state.communities.subscribingCommunitiesInCommunitiesScreenDiscoverTab,
|
||||
);
|
||||
const subscribedCommunitiesCache = useSelector((state) => state.cache.subscribedCommunities);
|
||||
|
||||
useEffect(() => {
|
||||
if (subscribingCommunitiesInDiscoverTab && selectedCommunityItem) {
|
||||
const { status } = subscribingCommunitiesInDiscoverTab[selectedCommunityItem.communityId];
|
||||
if (status === statusMessage.SUCCESS) {
|
||||
dispatch(updateSubscribedCommunitiesCache(selectedCommunityItem));
|
||||
}
|
||||
}
|
||||
}, [subscribingCommunitiesInDiscoverTab]);
|
||||
|
||||
useEffect(() => {
|
||||
getCommunity(tag)
|
||||
.then((res) => {
|
||||
@ -29,17 +47,26 @@ const CommunityContainer = ({ children, navigation, currentAccount, pinCode, isL
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
//check and set user role
|
||||
getSubscriptions(currentAccount.username)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
const _isSubscribed = result.some((item) => item[0] === data.name);
|
||||
setIsSubscribed(_isSubscribed);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
if (
|
||||
subscribedCommunitiesCache &&
|
||||
subscribedCommunitiesCache.size &&
|
||||
subscribedCommunitiesCache.get(data.name)
|
||||
) {
|
||||
const itemExistInCache = subscribedCommunitiesCache.get(data.name);
|
||||
setIsSubscribed(itemExistInCache.data[4]); //if item exist in cache, get isSubscribed value from cache
|
||||
} else {
|
||||
//check and set user role
|
||||
getSubscriptions(currentAccount.username)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
const _isSubscribed = result.some((item) => item[0] === data.name);
|
||||
setIsSubscribed(_isSubscribed);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
@ -48,6 +75,7 @@ const CommunityContainer = ({ children, navigation, currentAccount, pinCode, isL
|
||||
isSubscribed: isSubscribed,
|
||||
communityId: data.name,
|
||||
};
|
||||
setSelectedCommunityItem(_data); //set selected item to handle its cache
|
||||
const screen = 'communitiesScreenDiscoverTab';
|
||||
let subscribeAction;
|
||||
let successToastText = '';
|
||||
|
@ -33,7 +33,7 @@ const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => {
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
const [noResult, setNoResult] = useState(false);
|
||||
|
||||
const [isDiscoversLoading, setIsDiscoversLoading] = useState(false);
|
||||
const pinCode = useSelector((state) => state.application.pin);
|
||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
||||
@ -44,7 +44,7 @@ const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => {
|
||||
useEffect(() => {
|
||||
setData([]);
|
||||
setNoResult(false);
|
||||
|
||||
setIsDiscoversLoading(true);
|
||||
getCommunities('', searchValue ? 100 : 20, searchValue || null, 'rank')
|
||||
.then((communities) => {
|
||||
if (currentAccount && currentAccount.username) {
|
||||
@ -78,10 +78,12 @@ const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => {
|
||||
setNoResult(true);
|
||||
}
|
||||
}
|
||||
setIsDiscoversLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
setNoResult(true);
|
||||
setData([]);
|
||||
setIsDiscoversLoading(false);
|
||||
});
|
||||
}, [searchValue]);
|
||||
|
||||
@ -160,6 +162,7 @@ const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => {
|
||||
handleSubscribeButtonPress: _handleSubscribeButtonPress,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
isDiscoversLoading,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ const CommunitiesResultsScreen = ({ navigation, searchValue }) => {
|
||||
handleSubscribeButtonPress,
|
||||
isLoggedIn,
|
||||
noResult,
|
||||
isDiscoversLoading,
|
||||
}) =>
|
||||
noResult ? (
|
||||
<EmptyScreen />
|
||||
@ -30,6 +31,7 @@ const CommunitiesResultsScreen = ({ navigation, searchValue }) => {
|
||||
isLoggedIn={isLoggedIn}
|
||||
noResult={noResult}
|
||||
screen="searchResultsScreen"
|
||||
isDiscoversLoading={isDiscoversLoading}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
47
src/utils/communitiesUtils.ts
Normal file
47
src/utils/communitiesUtils.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { SubscribedCommunity } from '../redux/reducers/cacheReducer';
|
||||
|
||||
/**
|
||||
* Accepts Array of subscription items arrays as 1st argument, community cache map as second argument.
|
||||
* Returns single array with union of both lists, sorted alphabatically
|
||||
* Example subList = [['id', 'title', 'role', 'label', 'true/false'],['id', 'title', 'role', 'label', 'true/false']]
|
||||
*
|
||||
**/
|
||||
export const mergeSubCommunitiesCacheInSubList = (
|
||||
subList: any[],
|
||||
cacheMap: Map<string, SubscribedCommunity>,
|
||||
) => {
|
||||
if (!cacheMap || !cacheMap.size) {
|
||||
return subList.sort((a, b) => a[1].localeCompare(b[1]));
|
||||
}
|
||||
const cacheList = Array.from(cacheMap, ([path, item]) => item.data);
|
||||
cacheList.map((cacheListItem) => {
|
||||
let index = subList.findIndex((subListItem) => subListItem[0] === cacheListItem[0]);
|
||||
if (index !== -1) {
|
||||
subList[index] = [...cacheListItem];
|
||||
} else {
|
||||
subList.push(cacheListItem);
|
||||
}
|
||||
});
|
||||
return subList.sort((a, b) => a[1].localeCompare(b[1]));
|
||||
};
|
||||
|
||||
/**
|
||||
* Accepts Array of discover items arrays as 1st argument, community cache map as second argument.
|
||||
* Returns discovers list with updated isSubscribed status
|
||||
*
|
||||
**/
|
||||
export const mergeSubCommunitiesCacheInDiscoverList = (
|
||||
discoverList: any[],
|
||||
cacheMap: Map<string, SubscribedCommunity>,
|
||||
) => {
|
||||
if (!cacheMap || !cacheMap.size) {
|
||||
return discoverList;
|
||||
}
|
||||
discoverList.forEach((discoverListItem) => {
|
||||
let itemExist = cacheMap.get(discoverListItem.name);
|
||||
if (itemExist) {
|
||||
discoverListItem.isSubscribed = itemExist.data[4];
|
||||
}
|
||||
});
|
||||
return discoverList;
|
||||
};
|
Loading…
Reference in New Issue
Block a user