UNPKG

mattermost-redux

Version:

Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client

423 lines (374 loc) 12.8 kB
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import {GifTypes} from 'action_types'; import {Client4} from 'client'; import gfycatSdk from 'utils/gfycat_sdk'; import {DispatchFunc, GetStateFunc} from 'types/actions'; import {GlobalState} from 'types/store'; // APP PROPS export function saveAppPropsRequest(props: any) { return { type: GifTypes.SAVE_APP_PROPS, props, }; } export function saveAppProps(appProps: any) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { const {GfycatApiKey, GfycatApiSecret} = getState().entities.general.config; gfycatSdk(GfycatApiKey!, GfycatApiSecret!).authenticate(); dispatch(saveAppPropsRequest(appProps)); }; } // SEARCH export function selectSearchText(searchText: string) { return { type: GifTypes.SELECT_SEARCH_TEXT, searchText, }; } export function updateSearchText(searchText: string) { return { type: GifTypes.UPDATE_SEARCH_TEXT, searchText, }; } export function searchBarTextSave(searchBarText: string) { return { type: GifTypes.SAVE_SEARCH_BAR_TEXT, searchBarText, }; } export function invalidateSearchText(searchText: string) { return { type: GifTypes.INVALIDATE_SEARCH_TEXT, searchText, }; } export function requestSearch(searchText: string) { return { type: GifTypes.REQUEST_SEARCH, searchText, }; } export function receiveSearch({searchText, count, start, json}: {searchText: string; count: number; start: number; json: any}) { return { type: GifTypes.RECEIVE_SEARCH, searchText, ...json, count, start, currentPage: start / count, receivedAt: Date.now(), }; } export function receiveSearchEnd(searchText: string) { return { type: GifTypes.RECEIVE_SEARCH_END, searchText, }; } export function errorSearching(err: any, searchText: string) { return { type: GifTypes.SEARCH_FAILURE, searchText, err, }; } export function receiveCategorySearch({tagName, json}: {tagName: string; json: any}) { return { type: GifTypes.RECEIVE_CATEGORY_SEARCH, searchText: tagName, ...json, receiveAt: Date.now(), }; } export function clearSearchResults() { return { type: GifTypes.CLEAR_SEARCH_RESULTS, }; } export function requestSearchById(gfyId: string) { return { type: GifTypes.SEARCH_BY_ID_REQUEST, payload: { gfyId, }, }; } export function receiveSearchById(gfyId: string, gfyItem: any) { return { type: GifTypes.SEARCH_BY_ID_SUCCESS, payload: { gfyId, gfyItem, }, }; } export function errorSearchById(err: any, gfyId: string) { return { type: GifTypes.SEARCH_BY_ID_FAILURE, err, gfyId, }; } export function searchScrollPosition(scrollPosition: number) { return { type: GifTypes.SAVE_SEARCH_SCROLL_POSITION, scrollPosition, }; } export function searchPriorLocation(priorLocation: number) { return { type: GifTypes.SAVE_SEARCH_PRIOR_LOCATION, priorLocation, }; } export function searchGfycat({searchText, count = 30, startIndex = 0}: { searchText: string; count?: number; startIndex?: number}) { let start = startIndex; return (dispatch: DispatchFunc, getState: GetStateFunc) => { const {GfycatApiKey, GfycatApiSecret} = getState().entities.general.config; const {resultsByTerm} = getState().entities.gifs.search; if (resultsByTerm[searchText]) { start = resultsByTerm[searchText].start + count; } dispatch(requestSearch(searchText)); const sdk = gfycatSdk(GfycatApiKey!, GfycatApiSecret!); sdk.authenticate(); return sdk.search({search_text: searchText, count, start}).then((json: any) => { if (json.errorMessage) { // There was no results before if (resultsByTerm[searchText].items) { dispatch(receiveSearchEnd(searchText)); } else { dispatch(errorSearching(json, searchText)); } } else { dispatch(updateSearchText(searchText)); dispatch(cacheGifsRequest(json.gfycats)); dispatch(receiveSearch({searchText, count, start, json})); const context = getState().entities.gifs.categories.tagsDict[searchText] ? 'category' : 'search'; Client4.trackEvent( 'gfycat', 'views', {context, count: json.gfycats.length, keyword: searchText}, ); } }).catch( (err: any) => dispatch(errorSearching(err, searchText)), ); }; } export function searchCategory({tagName = '', gfyCount = 30, cursorPos = undefined}) { let cursor = cursorPos; return async (dispatch: DispatchFunc, getState: GetStateFunc) => { const {GfycatApiKey, GfycatApiSecret} = getState().entities.general.config; const {resultsByTerm} = getState().entities.gifs.search; if (resultsByTerm[tagName]) { cursor = resultsByTerm[tagName].cursor; } dispatch(requestSearch(tagName)); return gfycatSdk(GfycatApiKey!, GfycatApiSecret!).getTrendingCategories({tagName, gfyCount, cursor}).then( (json: any) => { if (json.errorMessage) { if (resultsByTerm[tagName].gfycats) { dispatch(receiveSearchEnd(tagName)); } else { dispatch(errorSearching(json, tagName)); } } else { dispatch(updateSearchText(tagName)); dispatch(cacheGifsRequest(json.gfycats)); dispatch(receiveCategorySearch({tagName, json})); Client4.trackEvent( 'gfycat', 'views', {context: 'category', count: json.gfycats.length, keyword: tagName}, ); // preload categories list if (tagName === 'trending') { dispatch(requestCategoriesListIfNeeded() as any); } } }, ).catch((err: any) => dispatch(errorSearching(err, tagName))); }; } export function shouldSearch(state: GlobalState, searchText: string) { const resultsByTerm = state.entities.gifs.search.resultsByTerm[searchText]; if (!resultsByTerm) { return true; } else if (resultsByTerm.isFetching) { return false; } else if (resultsByTerm.moreRemaining) { return true; } return resultsByTerm.didInvalidate; } export function searchIfNeeded(searchText: string) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { if (shouldSearch(getState(), searchText)) { if (searchText.toLowerCase() === 'trending') { return dispatch(searchCategory({tagName: searchText})); } return dispatch(searchGfycat({searchText})); } return Promise.resolve(); }; } export function searchIfNeededInitial(searchText: string) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { dispatch(updateSearchText(searchText)); if (shouldSearchInitial(getState(), searchText)) { if (searchText.toLowerCase() === 'trending') { return dispatch(searchCategory({tagName: searchText})); } return dispatch(searchGfycat({searchText})); } return Promise.resolve(); }; } export function shouldSearchInitial(state: GlobalState, searchText: string) { const resultsByTerm = state.entities.gifs.search.resultsByTerm[searchText]; if (!resultsByTerm) { return true; } else if (resultsByTerm.isFetching) { return false; } return false; } export function searchById(gfyId: string) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { const {GfycatApiKey, GfycatApiSecret} = getState().entities.general.config; dispatch(requestSearchById(gfyId)); return gfycatSdk(GfycatApiKey!, GfycatApiSecret!).searchById({id: gfyId}).then( (response: any) => { dispatch(receiveSearchById(gfyId, response.gfyItem)); dispatch(cacheGifsRequest([response.gfyItem])); }, ).catch((err: any) => dispatch(errorSearchById(err, gfyId))); }; } export function shouldSearchById(state: GlobalState, gfyId: string) { return !state.entities.gifs.cache.gifs[gfyId]; //TODO investigate, used to be !state.cache.gifs[gfyId]; } export function searchByIdIfNeeded(gfyId: string) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { if (shouldSearchById(getState(), gfyId)) { return dispatch(searchById(gfyId)); } return Promise.resolve(getState().entities.gifs.cache.gifs[gfyId]); //TODO: investigate, used to be getState().cache.gifs[gfyId] }; } export function saveSearchScrollPosition(scrollPosition: number) { return (dispatch: DispatchFunc) => { dispatch(searchScrollPosition(scrollPosition)); }; } export function saveSearchPriorLocation(priorLocation: number) { return (dispatch: DispatchFunc) => { dispatch(searchPriorLocation(priorLocation)); }; } export function searchTextUpdate(searchText: string) { return (dispatch: DispatchFunc) => { dispatch(updateSearchText(searchText)); }; } export function saveSearchBarText(searchBarText: string) { return (dispatch: DispatchFunc) => { dispatch(searchBarTextSave(searchBarText)); }; } // CATEGORIES export function categoriesListRequest() { return { type: GifTypes.REQUEST_CATEGORIES_LIST, }; } export function categoriesListReceived(json: any) { return { type: GifTypes.CATEGORIES_LIST_RECEIVED, ...json, }; } export function categoriesListFailure(err: any) { return { type: GifTypes.CATEGORIES_LIST_FAILURE, err, }; } export function requestCategoriesList({count = 60} = {}) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { const {GfycatApiKey, GfycatApiSecret} = getState().entities.general.config; const state = getState().entities.gifs.categories; if (!shouldRequestCategoriesList(state)) { return Promise.resolve(); } dispatch(categoriesListRequest()); const {cursor} = state; const options = { ...(count && {count}), ...(cursor && {cursor}), }; return gfycatSdk(GfycatApiKey!, GfycatApiSecret!).getCategories(options).then((json: any) => { const newGfycats = json.tags.reduce((gfycats: any[], tag: any) => { if (tag.gfycats[0] && tag.gfycats[0].width) { return [...gfycats, ...tag.gfycats]; } return gfycats; }, []); dispatch(cacheGifsRequest(newGfycats)); dispatch(categoriesListReceived(json)); }).catch( (err: any) => { dispatch(categoriesListFailure(err)); }, ); }; } export function requestCategoriesListIfNeeded({ count, } = {count: undefined}) { return (dispatch: DispatchFunc, getState: GetStateFunc) => { const state = getState().entities.gifs.categories; if (state.tagsList && state.tagsList.length) { return Promise.resolve(); } return dispatch(requestCategoriesList({count})); }; } export function shouldRequestCategoriesList(state: {hasMore: boolean; isFetching: boolean; tagsList: any[]}) { const {hasMore, isFetching, tagsList} = state; if (!tagsList || !tagsList.length) { return true; } else if (isFetching) { return false; } else if (hasMore) { return true; } return false; } // CACHE export function cacheRequest() { return { type: GifTypes.CACHE_REQUEST, payload: { updating: true, }, }; } export function cacheGifs(gifs: any) { return { type: GifTypes.CACHE_GIFS, gifs, }; } export function cacheGifsRequest(gifs: any) { return async (dispatch: DispatchFunc) => { dispatch(cacheRequest()); dispatch(cacheGifs(gifs)); return {data: true}; }; }