Progress on chat conversation search, scrolling
This commit is contained in:
parent
15df66b234
commit
7a62adea3e
|
@ -7,7 +7,7 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
|
|||
before_action :require_user!
|
||||
before_action :set_account, only: [:block_messenger, :unblock_messenger, :messenger_block_relationships]
|
||||
before_action :check_account_suspension, only: [:block_messenger, :unblock_messenger, :messenger_block_relationships]
|
||||
before_action :set_chat_conversation, except: [:block_messenger, :unblock_messenger, :messenger_block_relationships]
|
||||
before_action :set_chat_conversation, except: [:block_messenger, :unblock_messenger, :messenger_block_relationships, :search]
|
||||
|
||||
def block_messenger
|
||||
@block = BlockChatMessengerService.new.call(current_user.account, @account)
|
||||
|
@ -42,6 +42,13 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
|
|||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||
end
|
||||
|
||||
def search
|
||||
# : todo :
|
||||
search_conversations = [] #ChatConversationAccount.where(account: current_account, is_hidden: false, is_approved: true).map(&:participant_account_ids)
|
||||
# .joins(:account).where("accounts.display_name ILIKE ?", "%#{params[:q]}%")
|
||||
render json: search_conversations, each_serializer: REST::ChatConversationAccountSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
|
|
|
@ -34,13 +34,8 @@ class Api::V1::ChatConversationController < Api::BaseController
|
|||
end
|
||||
|
||||
def mark_chat_conversation_approved
|
||||
approved_conversation_count = ChatConversationAccount.where(account: @account, is_hidden: false, is_approved: true).count
|
||||
if approved_conversation_count >= ChatConversationAccount::PER_ACCOUNT_APPROVED_LIMIT
|
||||
render json: { error: true, message: "You have #{approved_conversation_count} active chat conversations. The limit is #{ChatConversationAccount::PER_ACCOUNT_APPROVED_LIMIT}. Delete some conversations first before approving any more requests." }
|
||||
else
|
||||
@chat_conversation_account.update!(is_approved: true)
|
||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||
end
|
||||
@chat_conversation_account.update!(is_approved: true)
|
||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||
end
|
||||
|
||||
def set_expiration_policy
|
||||
|
|
|
@ -246,4 +246,4 @@ const unmuteChatConversationFail = (accountId, error) => ({
|
|||
showToast: true,
|
||||
accountId,
|
||||
error,
|
||||
})
|
||||
})
|
|
@ -509,40 +509,29 @@ export const setChatConversationExpirationFail = (error) => ({
|
|||
error,
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const fetchChatConversationAccountSuggestions = (query) => (dispatch, getState) => {
|
||||
export const searchApprovedChatConversations = (query) => (dispatch, getState) => {
|
||||
if (!query) return
|
||||
debouncedFetchChatConversationAccountSuggestions(query, dispatch, getState)
|
||||
debouncedSearchApprovedChatConversations(query, dispatch, getState)
|
||||
}
|
||||
|
||||
export const debouncedFetchChatConversationAccountSuggestions = debounce((query, dispatch, getState) => {
|
||||
export const debouncedSearchApprovedChatConversations = debounce((query, dispatch, getState) => {
|
||||
if (!query) return
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', {
|
||||
params: {
|
||||
q: query,
|
||||
resolve: false,
|
||||
limit: 4,
|
||||
},
|
||||
api(getState).get('/api/v1/chat_conversation_accounts/_/search', {
|
||||
params: { q: query },
|
||||
}).then((response) => {
|
||||
// const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||
// const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
|
||||
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
|
||||
// dispatch(importFetchedAccounts(conversationsAccounts))
|
||||
// dispatch(importFetchedChatMessages(conversationsChatMessages))
|
||||
// dispatch(fetchChatConversationsSuccess(response.data, next ? next.uri : null))
|
||||
|
||||
dispatch(fetchChatConversationAccountSuggestionsSuccess(response.data))
|
||||
const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
|
||||
dispatch(searchApprovedChatConversationsSuccess(response.data))
|
||||
}).catch((error) => {
|
||||
//
|
||||
})
|
||||
}, 650, { leading: true })
|
||||
|
||||
const fetchChatConversationAccountSuggestionsSuccess = (chatConversations) => ({
|
||||
const searchApprovedChatConversationsSuccess = (chatConversations) => ({
|
||||
type: CHAT_CONVERSATION_APPROVED_SEARCH_FETCH_SUCCESS,
|
||||
chatConversations,
|
||||
})
|
|
@ -9,6 +9,8 @@ export const CLEAR_CHAT_CONVERSATION_CREATE_SEARCH_ACCOUNTS = 'CLEAR_CHAT_CONVER
|
|||
|
||||
export const SET_CHAT_CONVERSATION_SELECTED = 'SET_CHAT_CONVERSATION_SELECTED'
|
||||
|
||||
export const SET_CHAT_CONVERSATION_SEARCH_VALUE = 'SET_CHAT_CONVERSATION_SEARCH_VALUE'
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -54,4 +56,14 @@ export const setChatConversationSelected = (chatConversationId) => (dispatch) =>
|
|||
type: SET_CHAT_CONVERSATION_SELECTED,
|
||||
chatConversationId,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const onChangeSearch = (value) => (dispatch) => {
|
||||
dispatch({
|
||||
type: SET_CHAT_CONVERSATION_SEARCH_VALUE,
|
||||
value,
|
||||
})
|
||||
}
|
|
@ -62,11 +62,25 @@ class ChatConversationsList extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, { source }) => ({
|
||||
chatConversationIds: state.getIn(['chat_conversation_lists', source, 'items']),
|
||||
hasMore: !!state.getIn(['chat_conversation_lists', source, 'next']),
|
||||
isLoading: state.getIn(['chat_conversation_lists', source, 'isLoading']),
|
||||
})
|
||||
const mapStateToProps = (state, { source }) => {
|
||||
let chatConversationIds
|
||||
if (source === 'approved') {
|
||||
const chatSearchValue = state.getIn(['chats', 'searchValue'], '')
|
||||
if (!!chatSearchValue && chatSearchValue.length > 0) {
|
||||
chatConversationIds = state.getIn(['chat_conversation_lists', 'approved_search', 'items'])
|
||||
} else {
|
||||
chatConversationIds = state.getIn(['chat_conversation_lists', source, 'items'])
|
||||
}
|
||||
} else {
|
||||
chatConversationIds = state.getIn(['chat_conversation_lists', source, 'items'])
|
||||
}
|
||||
|
||||
return {
|
||||
chatConversationIds,
|
||||
hasMore: !!state.getIn(['chat_conversation_lists', source, 'next']),
|
||||
isLoading: state.getIn(['chat_conversation_lists', source, 'isLoading']),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchChatConversations(source) {
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { searchApprovedChatConversations } from '../../../actions/chat_conversations'
|
||||
import { onChangeSearch } from '../../../actions/chats'
|
||||
import Input from '../../../components/input'
|
||||
|
||||
class ChatConversationsSearch extends React.PureComponent {
|
||||
|
||||
state = {
|
||||
value: '',
|
||||
}
|
||||
|
||||
handleOnChange = (value) => {
|
||||
this.setState({ value })
|
||||
this.props.onChange(value)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value } = this.state
|
||||
const { value } = this.props
|
||||
|
||||
return (
|
||||
<div className={[_s.d, _s.h60PX, _s.w100PC, _s.px10, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
|
@ -33,10 +30,20 @@ class ChatConversationsSearch extends React.PureComponent {
|
|||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: state.getIn(['chats', 'searchValue'], ''),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onChange(value) {
|
||||
// dispatch()
|
||||
dispatch(onChangeSearch(value))
|
||||
dispatch(searchApprovedChatConversations(value))
|
||||
}
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(ChatConversationsSearch)
|
||||
ChatConversationsSearch.propTypes = {
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatConversationsSearch)
|
|
@ -45,10 +45,12 @@ class ChatMessagesComposeForm extends React.PureComponent {
|
|||
}
|
||||
|
||||
onBlur = () => {
|
||||
console.log("onBlur")
|
||||
this.setState({ focused: false })
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
console.log("onFocus")
|
||||
this.setState({ focused: true })
|
||||
}
|
||||
|
||||
|
|
|
@ -67,8 +67,8 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
|||
if (prevProps.chatMessageIds.size === 0 && this.props.chatMessageIds.size > 0 && this.scrollContainerRef) {
|
||||
this.scrollToBottom()
|
||||
this.props.onReadChatConversation(this.props.chatConversationId)
|
||||
} else if (prevProps.chatMessageIds.size < this.props.chatMessageIds.size && this.scrollContainerRef) {
|
||||
// this.setScrollTop(this.scrollContainerRef.scrollHeight)
|
||||
} else if (this.props.chatMessageIds.size - prevProps.chatMessageIds.size === 1) {
|
||||
this.scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
|||
|
||||
scrollToBottom = () => {
|
||||
if (this.messagesEnd) {
|
||||
this.messagesEnd.scrollIntoView({ behavior: 'smooth' });
|
||||
this.messagesEnd.scrollIntoView()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,6 +225,11 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
|||
this.containerNode = c
|
||||
}
|
||||
|
||||
setMessagesEnd = (c) => {
|
||||
this.messagesEnd = c
|
||||
this.scrollToBottom()
|
||||
}
|
||||
|
||||
setScrollContainerRef = (c) => {
|
||||
this.scrollContainerRef = c
|
||||
|
||||
|
@ -242,7 +247,6 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
|||
isPartial,
|
||||
hasMore,
|
||||
amITalkingToMyself,
|
||||
onScrollToBottom,
|
||||
onScroll,
|
||||
isXS,
|
||||
} = this.props
|
||||
|
@ -338,11 +342,13 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
|||
</IntersectionObserverArticle>
|
||||
))
|
||||
}
|
||||
<div
|
||||
style={{ float: 'left', clear: 'both' }}
|
||||
ref={(el) => { this.messagesEnd = el }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
key='end-message'
|
||||
style={{ float: 'left', clear: 'both' }}
|
||||
ref={this.setMessagesEnd}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
CHAT_CONVERSATIONS_MUTED_EXPAND_SUCCESS,
|
||||
CHAT_CONVERSATIONS_MUTED_EXPAND_FAIL,
|
||||
CHAT_CONVERSATIONS_CREATE_SUCCESS,
|
||||
CHAT_CONVERSATION_APPROVED_SEARCH_FETCH_SUCCESS,
|
||||
} from '../actions/chat_conversations'
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
|
@ -41,6 +42,9 @@ const initialState = ImmutableMap({
|
|||
isLoading: false,
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
approved_search: ImmutableMap({
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
})
|
||||
|
||||
const normalizeList = (state, source, chatConversations, next) => {
|
||||
|
@ -107,6 +111,9 @@ export default function chat_conversation_lists(state = initialState, action) {
|
|||
case CHAT_CONVERSATIONS_CREATE_SUCCESS:
|
||||
return appendToList(state, 'approved', [action.chatConversation], action.next)
|
||||
|
||||
case CHAT_CONVERSATION_APPROVED_SEARCH_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'approved_search', action.chatConversations, null)
|
||||
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
CHAT_CONVERSATION_REQUEST_APPROVE_SUCCESS,
|
||||
CHAT_CONVERSATION_MARK_READ_SUCCESS,
|
||||
SET_CHAT_CONVERSATION_EXPIRATION_SUCCESS,
|
||||
CHAT_CONVERSATION_APPROVED_SEARCH_FETCH_SUCCESS,
|
||||
} from '../actions/chat_conversations'
|
||||
|
||||
const initialState = ImmutableMap()
|
||||
|
@ -50,6 +51,7 @@ export default function chat_conversations(state = initialState, action) {
|
|||
case CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS:
|
||||
case CHAT_CONVERSATIONS_REQUESTED_FETCH_SUCCESS:
|
||||
case CHAT_CONVERSATIONS_REQUESTED_EXPAND_SUCCESS:
|
||||
case CHAT_CONVERSATION_APPROVED_SEARCH_FETCH_SUCCESS:
|
||||
return importChatConversations(state, action.chatConversations)
|
||||
case CHAT_MESSAGES_SEND_SUCCESS:
|
||||
return setLastChatMessage(state, action.chatMessage)
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
CHAT_CONVERSATION_CREATE_SEARCH_ACCOUNTS_SUCCESS,
|
||||
CLEAR_CHAT_CONVERSATION_CREATE_SEARCH_ACCOUNTS,
|
||||
SET_CHAT_CONVERSATION_SELECTED,
|
||||
SET_CHAT_CONVERSATION_SEARCH_VALUE,
|
||||
} from '../actions/chats'
|
||||
import {
|
||||
CHAT_CONVERSATION_APPROVED_UNREAD_COUNT_FETCH_SUCCESS,
|
||||
|
@ -24,6 +25,7 @@ const initialState = ImmutableMap({
|
|||
selectedChatConversationId: null,
|
||||
chatConversationRequestCount: 0,
|
||||
chatsUnreadCount: 0,
|
||||
searchValue: '',
|
||||
})
|
||||
|
||||
export default function chats(state = initialState, action) {
|
||||
|
@ -42,6 +44,8 @@ export default function chats(state = initialState, action) {
|
|||
const chatConversationUnreadCount = action.chatConversation.get('unread_count')
|
||||
const totalUnreadCount = state.get('chatsUnreadCount')
|
||||
return state.set('chatsUnreadCount', Math.max(totalUnreadCount - chatConversationUnreadCount, 0))
|
||||
case SET_CHAT_CONVERSATION_SEARCH_VALUE:
|
||||
return state.set('searchValue', action.value)
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
|
|
@ -237,6 +237,7 @@ Rails.application.routes.draw do
|
|||
post :unblock_messenger
|
||||
post :mute_chat_conversation
|
||||
post :unmute_chat_conversation
|
||||
get :search
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue