Progress on deck, dms

This commit is contained in:
mgabdev 2020-12-10 11:51:45 -05:00
parent c35e651b43
commit de0c977950
40 changed files with 660 additions and 274 deletions

View File

@ -0,0 +1 @@
{}

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::ChatConversationAccounts::BlockedAccountsController < Api::BaseController class Api::V1::ChatConversationAccounts::BlockedChatAccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :'read:blocks' } before_action -> { doorkeeper_authorize! :follow, :'read:blocks' }
before_action :require_user! before_action :require_user!
after_action :insert_pagination_headers after_action :insert_pagination_headers
def index def show
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render json: @accounts, each_serializer: REST::AccountSerializer
end end
@ -32,13 +32,13 @@ class Api::V1::ChatConversationAccounts::BlockedAccountsController < Api::BaseCo
def next_path def next_path
if records_continue? if records_continue?
api_v1_chat_conversation_accounts_blocked_accounts_url pagination_params(max_id: pagination_max_id) api_v1_chat_conversation_accounts_chat_blocked_accounts_url pagination_params(max_id: pagination_max_id)
end end
end end
def prev_path def prev_path
unless paginated_blocks.empty? unless paginated_blocks.empty?
api_v1_chat_conversation_accounts_blocked_accounts_url pagination_params(since_id: pagination_since_id) api_v1_chat_conversation_accounts_blocked_chat_accounts_url pagination_params(since_id: pagination_since_id)
end end
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::ChatConversationAccounts::MutedAccountsController < Api::BaseController class Api::V1::ChatConversationAccounts::MutedChatAccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :'read:mutes' } before_action -> { doorkeeper_authorize! :follow, :'read:mutes' }
before_action :require_user! before_action :require_user!
after_action :insert_pagination_headers after_action :insert_pagination_headers
def index def show
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render json: @accounts, each_serializer: REST::AccountSerializer
end end
@ -32,13 +32,13 @@ class Api::V1::ChatConversationAccounts::MutedAccountsController < Api::BaseCont
def next_path def next_path
if records_continue? if records_continue?
api_v1_chat_conversation_accounts_muted_accounts_url pagination_params(max_id: pagination_max_id) api_v1_chat_conversation_accounts_muted_chat_accounts_url pagination_params(max_id: pagination_max_id)
end end
end end
def prev_path def prev_path
unless paginated_mutes.empty? unless paginated_mutes.empty?
api_v1_chat_conversation_accounts_muted_accounts_url pagination_params(since_id: pagination_since_id) api_v1_chat_conversation_accounts_muted_chat_accounts_url pagination_params(since_id: pagination_since_id)
end end
end end

View File

@ -1,32 +1,36 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::ChatConversationAccountsController < Api::BaseController class Api::V1::ChatConversationAccountsController < Api::BaseController
before_action -> { authorize_if_got_token! :read, :'read:chats' }, except: [:create, :follow, :unfollow, :block, :unblock, :mute, :unmute] before_action -> { authorize_if_got_token! :read, :'read:chats' }
before_action -> { doorkeeper_authorize! :write, :'write:chats' }, only: [:create] before_action -> { doorkeeper_authorize! :write, :'write:chats' }
before_action :require_user! before_action :require_user!
before_action :set_account, except: [:create] before_action :set_account
def show def is_messenger_blocked
# #
end end
def block def is_messenger_muted
#
end
def block_messenger
BlockMessengerService.new.call(current_user.account, @account) BlockMessengerService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end end
def mute def mute_messenger
MuteMessengerService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications)) MuteMessengerService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end end
def unblock def unblock_messenger
UnblockMessengerService.new.call(current_user.account, @account) UnblockMessengerService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end end
def unmute def unmute_messenger
UnmuteMessegerService.new.call(current_user.account, @account) UnmuteMessegerService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end end
@ -34,19 +38,15 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
private private
def set_account def set_account
# @account = Account.find(params[:id]) @account = Account.find(params[:id])
end end
# def relationships(**options)
# AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
# end
def check_account_suspension def check_account_suspension
gone if @account.suspended? gone if @account.suspended?
end end
# def account_params def relationships(**options)
# params.permit(:username, :email, :password, :agreement, :locale) AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
# end end
end end

View File

@ -17,9 +17,9 @@ class Api::V1::ChatConversations::ApprovedConversationsController < Api::BaseCon
end end
def unread_count def unread_count
# : todo : make is_unread into unread_count then count unreads = ChatConversationAccount.where(account: current_account, is_hidden: false, is_approved: true).where('unread_count > 0')
# count = ChatConversationAccount.where(account: current_account, is_hidden: false, is_approved: true, unread_count: true).count sum = unreads.sum('unread_count')
render json: 1 render json: sum.to_i
end end
private private

View File

@ -17,6 +17,7 @@ class Api::V1::ChatMessagesController < Api::BaseController
# : todo : # : todo :
# check if blocked # check if blocked
# update unread_count++ if offline
@chat_conversation_recipients.each do |account| @chat_conversation_recipients.each do |account|
payload = InlineRenderer.render(@chat, account, :chat_message) payload = InlineRenderer.render(@chat, account, :chat_message)

View File

@ -0,0 +1,340 @@
import api, { getLinks } from '../api'
import { importFetchedAccounts } from './importer'
import { me } from '../initial_state'
//
export const CHAT_MESSENGER_BLOCKS_FETCH_REQUEST = 'CHAT_MESSENGER_BLOCKS_FETCH_REQUEST'
export const CHAT_MESSENGER_BLOCKS_FETCH_SUCCESS = 'CHAT_MESSENGER_BLOCKS_FETCH_SUCCESS'
export const CHAT_MESSENGER_BLOCKS_FETCH_FAIL = 'CHAT_MESSENGER_BLOCKS_FETCH_FAIL'
export const CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST = 'CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST'
export const CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS = 'CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS'
export const CHAT_MESSENGER_BLOCKS_EXPAND_FAIL = 'CHAT_MESSENGER_BLOCKS_EXPAND_FAIL'
export const BLOCK_CHAT_MESSAGER_REQUEST = 'BLOCK_CHAT_MESSAGER_REQUEST'
export const BLOCK_CHAT_MESSAGER_SUCCESS = 'BLOCK_CHAT_MESSAGER_SUCCESS'
export const BLOCK_CHAT_MESSAGER_FAIL = 'BLOCK_CHAT_MESSAGER_FAIL'
export const UNBLOCK_CHAT_MESSAGER_REQUEST = 'UNBLOCK_CHAT_MESSAGER_REQUEST'
export const UNBLOCK_CHAT_MESSAGER_SUCCESS = 'UNBLOCK_CHAT_MESSAGER_SUCCESS'
export const UNBLOCK_CHAT_MESSAGER_FAIL = 'UNBLOCK_CHAT_MESSAGER_FAIL'
export const IS_CHAT_MESSENGER_BLOCKED_SUCCESS = 'IS_CHAT_MESSENGER_BLOCKED_SUCCESS'
//
export const CHAT_MESSENGER_MUTES_FETCH_REQUEST = 'CHAT_MESSENGER_MUTES_FETCH_REQUEST'
export const CHAT_MESSENGER_MUTES_FETCH_SUCCESS = 'CHAT_MESSENGER_MUTES_FETCH_SUCCESS'
export const CHAT_MESSENGER_MUTES_FETCH_FAIL = 'CHAT_MESSENGER_MUTES_FETCH_FAIL'
export const CHAT_MESSENGER_MUTES_EXPAND_REQUEST = 'CHAT_MESSENGER_MUTES_EXPAND_REQUEST'
export const CHAT_MESSENGER_MUTES_EXPAND_SUCCESS = 'CHAT_MESSENGER_MUTES_EXPAND_SUCCESS'
export const CHAT_MESSENGER_MUTES_EXPAND_FAIL = 'CHAT_MESSENGER_MUTES_EXPAND_FAIL'
export const MUTE_CHAT_MESSAGER_REQUEST = 'MUTE_CHAT_MESSAGER_REQUEST'
export const MUTE_CHAT_MESSAGER_SUCCESS = 'MUTE_CHAT_MESSAGER_SUCCESS'
export const MUTE_CHAT_MESSAGER_FAIL = 'MUTE_CHAT_MESSAGER_FAIL'
export const UNMUTE_CHAT_MESSAGER_REQUEST = 'UNMUTE_CHAT_MESSAGER_REQUEST'
export const UNMUTE_CHAT_MESSAGER_SUCCESS = 'UNMUTE_CHAT_MESSAGER_SUCCESS'
export const UNMUTE_CHAT_MESSAGER_FAIL = 'UNMUTE_CHAT_MESSAGER_FAIL'
export const IS_CHAT_MESSENGER_MUTED_SUCCESS = 'IS_CHAT_MESSENGER_MUTED_SUCCESS'
/**
*
*/
export const blockChatMessenger = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
dispatch(blockChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/block_messenger`).then((response) => {
dispatch(blockChatMessengerSuccess())
}).catch((error) => {
dispatch(blockChatMessengerFail(accountId, error))
})
}
const blockChatMessengerRequest = (accountId) => ({
type: BLOCK_CHAT_MESSAGER_REQUEST,
accountId,
})
const blockChatMessengerSuccess = () => ({
type: BLOCK_CHAT_MESSAGER_SUCCESS,
showToast: true,
})
const blockChatMessengerFail = (accountId, error) => ({
type: BLOCK_CHAT_MESSAGER_FAIL,
showToast: true,
accountId,
error,
})
/**
*
*/
export const unblockChatMessenger = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
dispatch(unblockChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/unblock_messenger`).then((response) => {
dispatch(unblockChatMessengerSuccess())
}).catch((error) => {
dispatch(unblockChatMessengerFail(accountId, error))
})
}
const unblockChatMessengerRequest = (accountId) => ({
type: UNBLOCK_CHAT_MESSAGER_REQUEST,
accountId,
})
const unblockChatMessengerSuccess = () => ({
type: UNBLOCK_CHAT_MESSAGER_REQUEST,
showToast: true,
})
const unblockChatMessengerFail = (accountId, error) => ({
type: UNBLOCK_CHAT_MESSAGER_REQUEST,
showToast: true,
accountId,
error,
})
/**
* @description Check if a chat messenger is blocked by the current user account.
* @param {String} accountId
*/
export const isChatMessengerBlocked = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/is_messenger_blocked`).then((response) => {
dispatch(isChatMessengerBlockedSuccess(response.data))
})
}
const isChatMessengerBlockedSuccess = (data) => ({
type: IS_CHAT_MESSENGER_BLOCKED_SUCCESS,
data,
})
/**
*
*/
export const fetchChatMessengerBlocks = () => (dispatch, getState) => {
if (!me) return
dispatch(fetchChatMessengerBlocksRequest())
api(getState).get('/api/v1/chat_conversation_accounts/blocked_chat_accounts').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(fetchChatMessengerBlocksSuccess(response.data, next ? next.uri : null))
}).catch(error => dispatch(fetchChatMessengerBlocksFail(error)))
}
export const fetchChatMessengerBlocksRequest = () => ({
type: CHAT_MESSENGER_BLOCKS_FETCH_REQUEST,
})
export const fetchChatMessengerBlocksSuccess = (accounts, next) => ({
type: CHAT_MESSENGER_BLOCKS_FETCH_SUCCESS,
accounts,
next,
})
export const fetchChatMessengerBlocksFail = (error) => ({
type: CHAT_MESSENGER_BLOCKS_FETCH_FAIL,
showToast: true,
error,
})
/**
*
*/
export const expandChatMessengerBlocks = () => (dispatch, getState) => {
if (!me) return
const url = getState().getIn(['user_lists', 'chat_blocks', me, 'next'])
const isLoading = getState().getIn(['user_lists', 'chat_blocks', me, 'isLoading'])
if (url === null || isLoading) return
dispatch(expandChatMessengerBlocksRequest())
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(expandChatMessengerBlocksSuccess(response.data, next ? next.uri : null))
}).catch(error => dispatch(expandChatMessengerBlocksFail(error)))
}
export const expandChatMessengerBlocksRequest = () => ({
type: CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST,
})
export const expandChatMessengerBlocksSuccess = (accounts, next) => ({
type: CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS,
accounts,
next,
})
export const expandChatMessengerBlocksFail = (error) => ({
type: CHAT_MESSENGER_BLOCKS_EXPAND_FAIL,
error,
})
//
/**
*
*/
export const muteChatMessenger = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
dispatch(muteChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/mute_messenger`).then((response) => {
dispatch(muteChatMessengerSuccess())
}).catch((error) => {
dispatch(muteChatMessengerFail(accountId, error))
})
}
const muteChatMessengerRequest = (accountId) => ({
type: MUTE_CHAT_MESSAGER_REQUEST,
accountId,
})
const muteChatMessengerSuccess = () => ({
type: MUTE_CHAT_MESSAGER_SUCCESS,
showToast: true,
})
const muteChatMessengerFail = (accountId, error) => ({
type: MUTE_CHAT_MESSAGER_FAIL,
showToast: true,
accountId,
error,
})
/**
*
*/
export const unmuteChatMessenger = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
dispatch(unmuteChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/unmute_messenger`).then((response) => {
dispatch(unmuteChatMessengerSuccess())
}).catch((error) => {
dispatch(unmuteChatMessengerFail(accountId, error))
})
}
const unmuteChatMessengerRequest = (accountId) => ({
type: UNMUTE_CHAT_MESSAGER_REQUEST,
accountId,
})
const unmuteChatMessengerSuccess = () => ({
type: UNMUTE_CHAT_MESSAGER_REQUEST,
showToast: true,
})
const unmuteChatMessengerFail = (accountId, error) => ({
type: UNMUTE_CHAT_MESSAGER_REQUEST,
showToast: true,
accountId,
error,
})
/**
* @description Check if a chat messenger is muted by the current user account.
* @param {String} accountId
*/
export const isChatMessengerMuted = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/is_messenger_muted`).then((response) => {
dispatch(isChatMessengerMutedSuccess(response.data))
})
}
const isChatMessengerMutedSuccess = (data) => ({
type: IS_CHAT_MESSENGER_MUTED_SUCCESS,
data,
})
/**
*
*/
export const fetchChatMessengerMutes = () => (dispatch, getState) => {
if (!me) return
dispatch(fetchChatMessengerMutesRequest())
api(getState).get('/api/v1/chat_conversation_accounts/muted_chat_accounts').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(fetchChatMessengerMutesSuccess(response.data, next ? next.uri : null))
}).catch(error => dispatch(fetchChatMessengerMutesFail(error)))
}
export const fetchChatMessengerMutesRequest = () => ({
type: CHAT_MESSENGER_MUTES_FETCH_REQUEST,
})
export const fetchChatMessengerMutesSuccess = (accounts, next) => ({
type: CHAT_MESSENGER_MUTES_FETCH_SUCCESS,
accounts,
next,
})
export const fetchChatMessengerMutesFail = (error) => ({
type: CHAT_MESSENGER_MUTES_FETCH_FAIL,
showToast: true,
error,
})
/**
*
*/
export const expandChatMessengerMutes = () => (dispatch, getState) => {
if (!me) return
const url = getState().getIn(['user_lists', 'chat_mutes', me, 'next'])
const isLoading = getState().getIn(['user_lists', 'chat_mutes', me, 'isLoading'])
if (url === null || isLoading) return
dispatch(expandChatMessengerMutesRequest())
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(expandChatMessengerMutesSuccess(response.data, next ? next.uri : null))
}).catch(error => dispatch(expandChatMessengerMutesFail(error)))
}
export const expandChatMessengerMutesRequest = () => ({
type: CHAT_MESSENGER_MUTES_EXPAND_REQUEST,
})
export const expandChatMessengerMutesSuccess = (accounts, next) => ({
type: CHAT_MESSENGER_MUTES_EXPAND_SUCCESS,
accounts,
next,
})
export const expandChatMessengerMutesFail = (error) => ({
type: CHAT_MESSENGER_MUTES_EXPAND_FAIL,
error,
})

View File

@ -1,5 +1,4 @@
import api, { getLinks } from '../api' import api, { getLinks } from '../api'
import { fetchRelationships } from './accounts'
import { importFetchedAccounts } from './importer' import { importFetchedAccounts } from './importer'
import { me } from '../initial_state' import { me } from '../initial_state'
@ -27,42 +26,6 @@ export const CHAT_CONVERSATIONS_DELETE_FAIL = 'CHAT_CONVERSATIONS_DELETE_FAIL
// //
export const CHAT_CONVERSATION_BLOCKS_FETCH_REQUEST = 'CHAT_CONVERSATION_BLOCKS_FETCH_REQUEST'
export const CHAT_CONVERSATION_BLOCKS_FETCH_SUCCESS = 'CHAT_CONVERSATION_BLOCKS_FETCH_SUCCESS'
export const CHAT_CONVERSATION_BLOCKS_FETCH_FAIL = 'CHAT_CONVERSATION_BLOCKS_FETCH_FAIL'
export const CHAT_CONVERSATION_BLOCKS_EXPAND_REQUEST = 'CHAT_CONVERSATION_BLOCKS_EXPAND_REQUEST'
export const CHAT_CONVERSATION_BLOCKS_EXPAND_SUCCESS = 'CHAT_CONVERSATION_BLOCKS_EXPAND_SUCCESS'
export const CHAT_CONVERSATION_BLOCKS_EXPAND_FAIL = 'CHAT_CONVERSATION_BLOCKS_EXPAND_FAIL'
export const BLOCK_MESSAGER_REQUEST = 'BLOCK_MESSAGER_REQUEST'
export const BLOCK_MESSAGER_SUCCESS = 'BLOCK_MESSAGER_SUCCESS'
export const BLOCK_MESSAGER_FAIL = 'BLOCK_MESSAGER_FAIL'
export const UNBLOCK_MESSAGER_REQUEST = 'UNBLOCK_MESSAGER_REQUEST'
export const UNBLOCK_MESSAGER_SUCCESS = 'UNBLOCK_MESSAGER_SUCCESS'
export const UNBLOCK_MESSAGER_FAIL = 'UNBLOCK_MESSAGER_FAIL'
//
export const CHAT_CONVERSATION_MUTES_FETCH_REQUEST = 'CHAT_CONVERSATION_MUTES_FETCH_REQUEST'
export const CHAT_CONVERSATION_MUTES_FETCH_SUCCESS = 'CHAT_CONVERSATION_MUTES_FETCH_SUCCESS'
export const CHAT_CONVERSATION_MUTES_FETCH_FAIL = 'CHAT_CONVERSATION_MUTES_FETCH_FAIL'
export const CHAT_CONVERSATION_MUTES_EXPAND_REQUEST = 'CHAT_CONVERSATION_MUTES_EXPAND_REQUEST'
export const CHAT_CONVERSATION_MUTES_EXPAND_SUCCESS = 'CHAT_CONVERSATION_MUTES_EXPAND_SUCCESS'
export const CHAT_CONVERSATION_MUTES_EXPAND_FAIL = 'CHAT_CONVERSATION_MUTES_EXPAND_FAIL'
export const MUTE_MESSAGER_REQUEST = 'BLOCK_MESSAGER_REQUEST'
export const MUTE_MESSAGER_SUCCESS = 'BLOCK_MESSAGER_SUCCESS'
export const MUTE_MESSAGER_FAIL = 'BLOCK_MESSAGER_FAIL'
export const UNMUTE_MESSAGER_REQUEST = 'UNMUTE_MESSAGER_REQUEST'
export const UNMUTE_MESSAGER_SUCCESS = 'UNMUTE_MESSAGER_SUCCESS'
export const UNMUTE_MESSAGER_FAIL = 'UNMUTE_MESSAGER_FAIL'
//
export const CHAT_CONVERSATION_REQUESTED_COUNT_FETCH_SUCCESS = 'CHAT_CONVERSATION_REQUESTED_COUNT_FETCH_SUCCESS' export const CHAT_CONVERSATION_REQUESTED_COUNT_FETCH_SUCCESS = 'CHAT_CONVERSATION_REQUESTED_COUNT_FETCH_SUCCESS'
export const CHAT_CONVERSATIONS_REQUESTED_FETCH_REQUEST = 'CHAT_CONVERSATIONS_REQUESTED_FETCH_REQUEST' export const CHAT_CONVERSATIONS_REQUESTED_FETCH_REQUEST = 'CHAT_CONVERSATIONS_REQUESTED_FETCH_REQUEST'
@ -83,7 +46,7 @@ export const CHAT_CONVERSATION_DELETE_SUCCESS = 'CHAT_CONVERSATION_DELETE_SUCCES
export const CHAT_CONVERSATION_DELETE_FAIL = 'CHAT_CONVERSATION_DELETE_FAIL' export const CHAT_CONVERSATION_DELETE_FAIL = 'CHAT_CONVERSATION_DELETE_FAIL'
/** /**
* * @description Fetch paginated active chat conversations, import accounts and set chat converations
*/ */
export const fetchChatConversations = () => (dispatch, getState) => { export const fetchChatConversations = () => (dispatch, getState) => {
if (!me) return if (!me) return
@ -91,17 +54,14 @@ export const fetchChatConversations = () => (dispatch, getState) => {
dispatch(fetchChatConversationsRequest()) dispatch(fetchChatConversationsRequest())
api(getState).get('/api/v1/chat_conversations/approved_conversations').then((response) => { api(getState).get('/api/v1/chat_conversations/approved_conversations').then((response) => {
console.log("chat_conversations response: ", response)
const next = getLinks(response).refs.find(link => link.rel === 'next') const next = getLinks(response).refs.find(link => link.rel === 'next')
const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts)) const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
const conversationsChatMessages = response.data.map((c) => c.last_chat_message) // const conversationsChatMessages = response.data.map((c) => c.last_chat_message)
dispatch(importFetchedAccounts(conversationsAccounts)) dispatch(importFetchedAccounts(conversationsAccounts))
// dispatch(importFetchedChatMessages(conversationsChatMessages)) // dispatch(importFetchedChatMessages(conversationsChatMessages))
dispatch(fetchChatConversationsSuccess(response.data, next ? next.uri : null)) dispatch(fetchChatConversationsSuccess(response.data, next ? next.uri : null))
}).catch((error) => { }).catch((error) => {
console.log("fetchChatConversationsFail:", error)
dispatch(fetchChatConversationsFail(error)) dispatch(fetchChatConversationsFail(error))
}) })
} }
@ -118,11 +78,12 @@ export const fetchChatConversationsSuccess = (chatConversations, next) => ({
export const fetchChatConversationsFail = (error) => ({ export const fetchChatConversationsFail = (error) => ({
type: CHAT_CONVERSATIONS_APPROVED_FETCH_FAIL, type: CHAT_CONVERSATIONS_APPROVED_FETCH_FAIL,
showToast: true,
error, error,
}) })
/** /**
* * @description Expand paginated active chat conversations, import accounts and set chat converations
*/ */
export const expandChatConversations = () => (dispatch, getState) => { export const expandChatConversations = () => (dispatch, getState) => {
if (!me) return if (!me) return
@ -137,12 +98,12 @@ export const expandChatConversations = () => (dispatch, getState) => {
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next') const next = getLinks(response).refs.find(link => link.rel === 'next')
const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts)) const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
const conversationsChatMessages = response.data.map((c) => c.last_chat_message) // const conversationsChatMessages = response.data.map((c) => c.last_chat_message)
dispatch(importFetchedAccounts(conversationsAccounts)) dispatch(importFetchedAccounts(conversationsAccounts))
// dispatch(importFetchedChatMessages(conversationsChatMessages)) // dispatch(importFetchedChatMessages(conversationsChatMessages))
dispatch(expandChatConversationsSuccess(response.data, next ? next.uri : null)) dispatch(expandChatConversationsSuccess(response.data, next ? next.uri : null))
}).catch(error => dispatch(expandChatConversationsFail(error))) }).catch((error) => dispatch(expandChatConversationsFail(error)))
} }
export const expandChatConversationsRequest = () => ({ export const expandChatConversationsRequest = () => ({
@ -157,11 +118,12 @@ export const expandChatConversationsSuccess = (chatConversations, next) => ({
export const expandChatConversationsFail = (error) => ({ export const expandChatConversationsFail = (error) => ({
type: CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS, type: CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS,
showToast: true,
error, error,
}) })
/** /**
* * @description Fetch paginated requested chat conversations, import accounts and set chat converations
*/ */
export const fetchChatConversationRequested = () => (dispatch, getState) => { export const fetchChatConversationRequested = () => (dispatch, getState) => {
if (!me) return if (!me) return
@ -171,13 +133,12 @@ export const fetchChatConversationRequested = () => (dispatch, getState) => {
api(getState).get('/api/v1/chat_conversations/requested_conversations').then((response) => { api(getState).get('/api/v1/chat_conversations/requested_conversations').then((response) => {
const next = getLinks(response).refs.find(link => link.rel === 'next') const next = getLinks(response).refs.find(link => link.rel === 'next')
const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts)) const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
const conversationsChatMessages = response.data.map((c) => c.last_chat_message) // const conversationsChatMessages = response.data.map((c) => c.last_chat_message)
dispatch(importFetchedAccounts(conversationsAccounts)) dispatch(importFetchedAccounts(conversationsAccounts))
// dispatch(importFetchedChatMessages(conversationsChatMessages)) // dispatch(importFetchedChatMessages(conversationsChatMessages))
dispatch(fetchChatConversationRequestedSuccess(response.data, next ? next.uri : null)) dispatch(fetchChatConversationRequestedSuccess(response.data, next ? next.uri : null))
}).catch((error) => { }).catch((error) => {
console.log("error:", error)
dispatch(fetchChatConversationRequestedFail(error)) dispatch(fetchChatConversationRequestedFail(error))
}) })
} }
@ -194,11 +155,12 @@ export const fetchChatConversationRequestedSuccess = (chatConversations, next) =
export const fetchChatConversationRequestedFail = (error) => ({ export const fetchChatConversationRequestedFail = (error) => ({
type: CHAT_CONVERSATIONS_REQUESTED_FETCH_FAIL, type: CHAT_CONVERSATIONS_REQUESTED_FETCH_FAIL,
showToast: true,
error, error,
}) })
/** /**
* * @description Expand paginated requested chat conversations, import accounts and set chat converations
*/ */
export const expandChatConversationRequested = () => (dispatch, getState) => { export const expandChatConversationRequested = () => (dispatch, getState) => {
if (!me) return if (!me) return
@ -213,7 +175,7 @@ export const expandChatConversationRequested = () => (dispatch, getState) => {
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next') const next = getLinks(response).refs.find(link => link.rel === 'next')
const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts)) const conversationsAccounts = [].concat.apply([], response.data.map((c) => c.other_accounts))
const conversationsChatMessages = response.data.map((c) => c.last_chat_message) // const conversationsChatMessages = response.data.map((c) => c.last_chat_message)
dispatch(importFetchedAccounts(conversationsAccounts)) dispatch(importFetchedAccounts(conversationsAccounts))
// dispatch(importFetchedChatMessages(conversationsChatMessages)) // dispatch(importFetchedChatMessages(conversationsChatMessages))
@ -233,11 +195,13 @@ export const expandChatConversationRequestedSuccess = (chatConversations, next)
export const expandChatConversationRequestedFail = (error) => ({ export const expandChatConversationRequestedFail = (error) => ({
type: CHAT_CONVERSATIONS_REQUESTED_EXPAND_FAIL, type: CHAT_CONVERSATIONS_REQUESTED_EXPAND_FAIL,
showToast: true,
error, error,
}) })
/** /**
* * @description Create a chat conversation with given accountId. May fail because of blocks.
* @param {String} accountId
*/ */
export const createChatConversation = (accountId) => (dispatch, getState) => { export const createChatConversation = (accountId) => (dispatch, getState) => {
if (!me || !accountId) return if (!me || !accountId) return
@ -257,18 +221,22 @@ export const createChatConversationRequest = () => ({
export const createChatConversationSuccess = (chatConversation) => ({ export const createChatConversationSuccess = (chatConversation) => ({
type: CHAT_CONVERSATIONS_CREATE_SUCCESS, type: CHAT_CONVERSATIONS_CREATE_SUCCESS,
showToast: true,
chatConversation, chatConversation,
}) })
export const createChatConversationFail = (error) => ({ export const createChatConversationFail = (error) => ({
type: CHAT_CONVERSATIONS_CREATE_FAIL, type: CHAT_CONVERSATIONS_CREATE_FAIL,
showToast: true,
error, error,
}) })
/** /**
* * @description Delete a chat conversation with given chatConversationId.
* @param {String} chatConversationId
*/ */
export const deleteChatConversation = (chatConversationId) => (dispatch, getState) => { export const deleteChatConversation = (chatConversationId) => (dispatch, getState) => {
// : todo :
if (!me || !chatConversationId) return if (!me || !chatConversationId) return
dispatch(deleteChatConversationRequest(conversationId)) dispatch(deleteChatConversationRequest(conversationId))
@ -295,136 +263,6 @@ export const deleteChatConversationFail = (error) => ({
error, error,
}) })
/**
*
*/
export const blockMessenger = (accountId) => (dispatch, getState) => {
if (!accountId) return
dispatch(blockMessengerRequest(accountId))
api(getState).post(`/api/v1/messages/accounts/${accountId}/block`).then((response) => {
dispatch(blockMessengerSuccess(response.data))
}).catch((error) => {
dispatch(blockMessengerFail(accountId, error))
})
}
const blockMessengerRequest = (accountId) => ({
type: BLOCK_MESSAGER_REQUEST,
accountId,
})
const blockMessengerSuccess = (data) => ({
type: BLOCK_MESSAGER_REQUEST,
data,
})
const blockMessengerFail = (accountId, error) => ({
type: BLOCK_MESSAGER_REQUEST,
accountId,
error,
})
/**
*
*/
export const unblockMessenger = (accountId) => (dispatch, getState) => {
if (!accountId) return
dispatch(unblockMessengerRequest(accountId))
api(getState).post(`/api/v1/messages/accounts/${accountId}/unblock`).then((response) => {
dispatch(unblockMessengerSuccess(response.data))
}).catch((error) => {
dispatch(unblockMessengerFail(accountId, error))
})
}
const unblockMessengerRequest = (accountId) => ({
type: UNBLOCK_MESSAGER_REQUEST,
accountId,
})
const unblockMessengerSuccess = (data) => ({
type: UNBLOCK_MESSAGER_REQUEST,
data,
})
const unblockMessengerFail = (accountId, error) => ({
type: UNBLOCK_MESSAGER_REQUEST,
accountId,
error,
})
/**
*
*/
export const fetchBlocks = () => (dispatch, getState) => {
if (!me) return
dispatch(fetchBlocksRequest())
api(getState).get('/api/v1/blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null))
dispatch(fetchRelationships(response.data.map(item => item.id)))
}).catch(error => dispatch(fetchBlocksFail(error)))
}
// export const fetchBlocksRequest = () => ({
// type: BLOCKS_FETCH_REQUEST,
// })
// export const fetchBlocksSuccess = (accounts, next) => ({
// type: BLOCKS_FETCH_SUCCESS,
// accounts,
// next,
// })
// export const fetchBlocksFail = (error) => ({
// type: BLOCKS_FETCH_FAIL,
// error,
// })
/**
*
*/
export const expandBlocks = () => (dispatch, getState) => {
if (!me) return
const url = getState().getIn(['user_lists', 'blocks', me, 'next'])
const isLoading = getState().getIn(['user_lists', 'blocks', me, 'isLoading'])
if (url === null || isLoading) return
dispatch(expandBlocksRequest())
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next')
dispatch(importFetchedAccounts(response.data))
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null))
dispatch(fetchRelationships(response.data.map(item => item.id)))
}).catch(error => dispatch(expandBlocksFail(error)))
}
// export const expandBlocksRequest = () => ({
// type: BLOCKS_EXPAND_REQUEST,
// })
// export const expandBlocksSuccess = (accounts, next) => ({
// type: BLOCKS_EXPAND_SUCCESS,
// accounts,
// next,
// })
// export const expandBlocksFail = (error) => ({
// type: BLOCKS_EXPAND_FAIL,
// error,
// })
/** /**
* *
*/ */

View File

@ -12,6 +12,10 @@ export const CHAT_MESSAGES_DELETE_REQUEST = 'CHAT_MESSAGES_DELETE_REQUEST'
export const CHAT_MESSAGES_DELETE_SUCCESS = 'CHAT_MESSAGES_DELETE_SUCCESS' export const CHAT_MESSAGES_DELETE_SUCCESS = 'CHAT_MESSAGES_DELETE_SUCCESS'
export const CHAT_MESSAGES_DELETE_FAIL = 'CHAT_MESSAGES_DELETE_FAIL' export const CHAT_MESSAGES_DELETE_FAIL = 'CHAT_MESSAGES_DELETE_FAIL'
export const CHAT_MESSAGES_PURGE_REQUEST = 'CHAT_MESSAGES_PURGE_REQUEST'
export const CHAT_MESSAGES_PURGE_SUCCESS = 'CHAT_MESSAGES_PURGE_SUCCESS'
export const CHAT_MESSAGES_PURGE_FAIL = 'CHAT_MESSAGES_PURGE_FAIL'
/** /**
* *
*/ */
@ -85,4 +89,35 @@ const deleteChatMessageFail = (error) => ({
type: CHAT_MESSAGES_DELETE_FAIL, type: CHAT_MESSAGES_DELETE_FAIL,
showToast: true, showToast: true,
error, error,
})
/**
*
*/
export const purgeChatMessages = (chatConversationId) => (dispatch, getState) => {
if (!me || !chatConversationId) return
dispatch(deleteChatMessagesRequest(chatConversationId))
api(getState).delete(`/api/v1/chat_conversations/${chatConversationId}/messages/destroy_all`).then((response) => {
dispatch(deleteChatMessagesSuccess(response.data))
}).catch((error) => {
dispatch(deleteChatMessagesFail(error))
})
}
const deleteChatMessagesRequest = () => ({
type: CHAT_MESSAGES_PURGE_REQUEST,
})
const deleteChatMessagesSuccess = (chatConversationId) => ({
type: CHAT_MESSAGES_PURGE_SUCCESS,
chatConversationId,
showToast: true,
})
const deleteChatMessagesFail = (error) => ({
type: CHAT_MESSAGES_PURGE_FAIL,
showToast: true,
error,
}) })

View File

@ -5,10 +5,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import { openModal } from '../../actions/modal' import { openModal } from '../../actions/modal'
import { cancelReplyCompose } from '../../actions/compose' import { cancelReplyCompose } from '../../actions/compose'
import ComposeFormSubmitButton from '../../features/compose/components/compose_form_submit_button'
import TimelineComposeBlock from '../timeline_compose_block' import TimelineComposeBlock from '../timeline_compose_block'
import Block from '../block' import Block from '../block'
import Heading from '../heading' import Heading from '../heading'
import Text from '../text'
import Button from '../button' import Button from '../button'
class ComposeModal extends ImmutablePureComponent { class ComposeModal extends ImmutablePureComponent {
@ -51,27 +51,23 @@ class ComposeModal extends ImmutablePureComponent {
return ( return (
<div style={{width: '512px'}} className={[_s.d, _s.modal].join(' ')}> <div style={{width: '512px'}} className={[_s.d, _s.modal].join(' ')}>
<Block> <Block>
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.jcCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.h53PX, _s.px15].join(' ')}> <div className={[_s.d, _s.flexRow, _s.aiCenter, _s.jcCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.h53PX, _s.pl10, _s.pr15].join(' ')}>
<Button <div className={[_s.d, _s.w115PX, _s.aiStart, _s.jcCenter, _s.mrAuto].join(' ')}>
backgroundColor='none' <Button
title={intl.formatMessage(messages.close)} backgroundColor='none'
onClick={this.onClickClose} title={intl.formatMessage(messages.close)}
color='secondary' onClick={this.onClickClose}
icon='close' color='secondary'
iconSize='10px' icon='close'
/> iconSize='10px'
/>
</div>
<Heading size='h2'> <Heading size='h2'>
{intl.formatMessage(title)} {intl.formatMessage(title)}
</Heading> </Heading>
<Button <div className={[_s.d, _s.w115PX, _s.aiEnd, _s.jcCenter, _s.mlAuto].join(' ')}>
backgroundColor='none' <ComposeFormSubmitButton type='header' />
title={intl.formatMessage(messages.close)} </div>
className={_s.mlAuto}
onClick={this.onHandleSubmit}
color='secondary'
>
<Text>Post</Text>
</Button>
</div> </div>
<div className={[_s.d].join(' ')}> <div className={[_s.d].join(' ')}>
<TimelineComposeBlock isModal /> <TimelineComposeBlock isModal />
@ -92,7 +88,6 @@ const messages = defineMessages({
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
const status = state.getIn(['statuses', state.getIn(['compose', 'id'])]) const status = state.getIn(['statuses', state.getIn(['compose', 'id'])])
return { return {
composeText: state.getIn(['compose', 'text']), composeText: state.getIn(['compose', 'text']),
isEditing: !!status, isEditing: !!status,

View File

@ -5,6 +5,14 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { closePopover } from '../../actions/popover' import { closePopover } from '../../actions/popover'
import { openModal } from '../../actions/modal' import { openModal } from '../../actions/modal'
import {
isChatMessengerBlocked,
isChatMessengerMuted,
blockChatMessenger,
unblockChatMessenger,
muteChatMessenger,
unmuteChatMessenger,
} from '../../actions/chat_conversation_accounts'
import { MODAL_PRO_UPGRADE } from '../../constants' import { MODAL_PRO_UPGRADE } from '../../constants'
import { me } from '../../initial_state' import { me } from '../../initial_state'
import { makeGetChatConversation } from '../../selectors' import { makeGetChatConversation } from '../../selectors'
@ -14,24 +22,39 @@ import List from '../list'
class ChatConversationOptionsPopover extends ImmutablePureComponent { class ChatConversationOptionsPopover extends ImmutablePureComponent {
handleOnBlock = () => { handleOnHide = () => {
// this.props.onHide()
this.handleOnClosePopover()
} }
handleOnHide = () => { handleOnBlock = () => {
this.props.onBlock()
this.handleOnClosePopover()
}
handleOnUnblock = () => {
this.props.onUnblock()
this.handleOnClosePopover()
} }
handleOnMute = () => { handleOnMute = () => {
this.props.onMute()
this.handleOnClosePopover()
}
handleOnUnmute = () => {
this.props.onUnute()
this.handleOnClosePopover()
} }
handleOnPurge = () => { handleOnPurge = () => {
if (!this.props.isPro) { if (!this.props.isPro) {
this.props.openProUpgradeModal() this.props.openProUpgradeModal()
} else { } else {
// this.props.onPurge()
} }
this.handleOnClosePopover()
} }
handleOnClosePopover = () => { handleOnClosePopover = () => {

View File

@ -92,6 +92,7 @@ class DeckSidebar extends ImmutablePureComponent {
<Divider isSmall /> <Divider isSmall />
<NavigationBarButton attrTitle='Chat' icon='chat' to='/messages' />
<NavigationBarButton attrTitle='Dark/Muted/Light/White Mode' icon='light-bulb' onClick={this.handleOnClickLightBulb} /> <NavigationBarButton attrTitle='Dark/Muted/Light/White Mode' icon='light-bulb' onClick={this.handleOnClickLightBulb} />
<button <button

View File

@ -6,7 +6,11 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import { me } from '../initial_state' import { me } from '../initial_state'
import { fetchBlocks, expandBlocks } from '../actions/blocks' import {
fetchChatMessengerBlocks,
expandChatMessengerBlocks,
unblockChatMessenger,
} from '../actions/chat_conversation_accounts'
import Account from '../components/account' import Account from '../components/account'
import Block from '../components/block' import Block from '../components/block'
import BlockHeading from '../components/block_heading' import BlockHeading from '../components/block_heading'
@ -14,7 +18,7 @@ import Divider from '../components/divider'
import ScrollableList from '../components/scrollable_list' import ScrollableList from '../components/scrollable_list'
import AccountPlaceholder from '../components/placeholder/account_placeholder' import AccountPlaceholder from '../components/placeholder/account_placeholder'
class MessagesBlockedAccounts extends ImmutablePureComponent { class ChatConversationBlockedAccounts extends ImmutablePureComponent {
componentDidMount() { componentDidMount() {
this.props.onFetchBlocks() this.props.onFetchBlocks()
@ -40,7 +44,7 @@ class MessagesBlockedAccounts extends ImmutablePureComponent {
<BlockHeading title={intl.formatMessage(messages.blocks)} /> <BlockHeading title={intl.formatMessage(messages.blocks)} />
</div> </div>
<ScrollableList <ScrollableList
scrollKey='blocked_accounts' scrollKey='chat_blocked_accounts'
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
hasMore={hasMore} hasMore={hasMore}
isLoading={isLoading} isLoading={isLoading}
@ -55,6 +59,9 @@ class MessagesBlockedAccounts extends ImmutablePureComponent {
key={`blocked-accounts-${id}`} key={`blocked-accounts-${id}`}
id={id} id={id}
compact compact
actionIcon='subtract'
onActionClick={() => this.props.onRemove(id)}
actionTitle='Remove'
/> />
)) ))
} }
@ -66,22 +73,23 @@ class MessagesBlockedAccounts extends ImmutablePureComponent {
} }
const messages = defineMessages({ const messages = defineMessages({
empty: { id: 'empty_column.blocks', defaultMessage: 'You haven\'t blocked any users yet.' }, empty: { id: 'empty_column.chat_blocks', defaultMessage: 'You haven\'t blocked any chat users yet.' },
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, blocks: { id: 'navigation_bar.chat_blocks', defaultMessage: 'Blocked chat users' },
}) })
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
accountIds: state.getIn(['user_lists', 'blocks', me, 'items']), accountIds: state.getIn(['user_lists', 'chat_blocks', me, 'items']),
hasMore: !!state.getIn(['user_lists', 'blocks', me, 'next']), hasMore: !!state.getIn(['user_lists', 'chat_blocks', me, 'next']),
isLoading: state.getIn(['user_lists', 'blocks', me, 'isLoading']), isLoading: state.getIn(['user_lists', 'chat_blocks', me, 'isLoading']),
}) })
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onFetchBlocks: () => dispatch(fetchBlocks()), onFetchBlocks: () => dispatch(fetchChatMessengerBlocks()),
onExpandBlocks: () => dispatch(expandBlocks()), onExpandBlocks: () => dispatch(expandChatMessengerBlocks()),
onRemove: (accountId) => dispatch(unblockChatMessenger(accountId)),
}) })
MessagesBlockedAccounts.propTypes = { ChatConversationBlockedAccounts.propTypes = {
accountIds: ImmutablePropTypes.list, accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool, hasMore: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
@ -90,4 +98,4 @@ MessagesBlockedAccounts.propTypes = {
onFetchBlocks: PropTypes.func.isRequired, onFetchBlocks: PropTypes.func.isRequired,
} }
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(MessagesBlockedAccounts)) export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ChatConversationBlockedAccounts))

View File

@ -6,13 +6,17 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import { me } from '../initial_state' import { me } from '../initial_state'
import { fetchMutes, expandMutes } from '../actions/mutes' import {
fetchChatMessengerMutes,
expandChatMessengerMutes,
unmuteChatMessenger,
} from '../actions/chat_conversation_accounts'
import Account from '../components/account' import Account from '../components/account'
import Block from '../components/block' import Block from '../components/block'
import BlockHeading from '../components/block_heading' import BlockHeading from '../components/block_heading'
import ScrollableList from '../components/scrollable_list' import ScrollableList from '../components/scrollable_list'
class MessagesMutedAccounts extends ImmutablePureComponent { class ChatConversationMutedAccounts extends ImmutablePureComponent {
componentWillMount() { componentWillMount() {
this.props.onFetchMutes() this.props.onFetchMutes()
@ -32,14 +36,14 @@ class MessagesMutedAccounts extends ImmutablePureComponent {
return ( return (
<div className={[_s.d, _s.w100PC, _s.boxShadowNone].join(' ')}> <div className={[_s.d, _s.w100PC, _s.boxShadowNone].join(' ')}>
<div className={[_s.d, _s.h60PX, _s.w100PC, _s.px10, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}> <div className={[_s.d, _s.h60PX, _s.w100PC, _s.px10, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
<BlockHeading title={<FormattedMessage id='navigation_bar.mutes' defaultMessage='Muted users' />} /> <BlockHeading title={<FormattedMessage id='navigation_bar.chat_mutes' defaultMessage='Muted chat users' />} />
</div> </div>
<ScrollableList <ScrollableList
scrollKey='mutes' scrollKey='chat_muted_accounts'
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
hasMore={hasMore} hasMore={hasMore}
isLoading={isLoading} isLoading={isLoading}
emptyMessage={<FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />} emptyMessage={<FormattedMessage id='empty_column.chat_mutes' defaultMessage="You haven't muted any chat users yet." />}
> >
{ {
accountIds && accountIds.map((id) => accountIds && accountIds.map((id) =>
@ -47,6 +51,9 @@ class MessagesMutedAccounts extends ImmutablePureComponent {
key={`mutes-${id}`} key={`mutes-${id}`}
id={id} id={id}
compact compact
actionIcon='subtract'
onActionClick={() => this.props.onRemove(id)}
actionTitle='Remove'
/> />
) )
} }
@ -58,17 +65,18 @@ class MessagesMutedAccounts extends ImmutablePureComponent {
} }
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
accountIds: state.getIn(['user_lists', 'mutes', me, 'items']), accountIds: state.getIn(['user_lists', 'chat_mutes', me, 'items']),
hasMore: !!state.getIn(['user_lists', 'mutes', me, 'next']), hasMore: !!state.getIn(['user_lists', 'chat_mutes', me, 'next']),
isLoading: state.getIn(['user_lists', 'mutes', me, 'isLoading']), isLoading: state.getIn(['user_lists', 'chat_mutes', me, 'isLoading']),
}) })
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onFetchMutes: () => dispatch(fetchMutes()), onFetchMutes: () => dispatch(fetchChatMessengerMutes()),
onExpandMutes: () => dispatch(expandMutes()), onExpandMutes: () => dispatch(expandChatMessengerMutes()),
onRemove: (accountId) => dispatch(unmuteChatMessenger(accountId)),
}) })
MessagesMutedAccounts.propTypes = { ChatConversationMutedAccounts.propTypes = {
accountIds: ImmutablePropTypes.list, accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool, hasMore: PropTypes.bool,
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
@ -76,4 +84,4 @@ MessagesMutedAccounts.propTypes = {
onFetchMutes: PropTypes.func.isRequired, onFetchMutes: PropTypes.func.isRequired,
} }
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(MessagesMutedAccounts)) export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ChatConversationMutedAccounts))

View File

@ -17,6 +17,7 @@ class ComposeExtraButton extends React.PureComponent {
buttonRef, buttonRef,
isLast, isLast,
small, small,
iconClassName,
} = this.props } = this.props
const containerClasses = CX({ const containerClasses = CX({
@ -42,7 +43,7 @@ class ComposeExtraButton extends React.PureComponent {
px10: 1, px10: 1,
}) })
const iconClasses = CX({ const iconClasses = CX(iconClassName, {
cSecondary: !active, cSecondary: !active,
cWhite: active, cWhite: active,
mr10: 1, mr10: 1,
@ -89,6 +90,7 @@ ComposeExtraButton.propTypes = {
active: PropTypes.bool, active: PropTypes.bool,
buttonRef: PropTypes.func, buttonRef: PropTypes.func,
small: PropTypes.bool, small: PropTypes.bool,
iconClassName: PropTypes.string,
} }
export default ComposeExtraButton export default ComposeExtraButton

View File

@ -43,10 +43,16 @@ class ComposeExtraButtonList extends React.PureComponent {
render() { render() {
const { isMatch, edit, hidePro, isModal } = this.props const {
isMatch,
edit,
hidePro,
isModal,
isStandalone,
} = this.props
const { height } = this.state const { height } = this.state
const small = height <= 660 || isModal const small = (height <= 660 || isModal) && !isStandalone
const containerClasses = CX({ const containerClasses = CX({
d: 1, d: 1,
@ -84,6 +90,7 @@ ComposeExtraButtonList.propTypes = {
edit: PropTypes.bool, edit: PropTypes.bool,
isMatch: PropTypes.bool, isMatch: PropTypes.bool,
isModal: PropTypes.bool, isModal: PropTypes.bool,
isStandalone: PropTypes.bool,
} }
export default ComposeExtraButtonList export default ComposeExtraButtonList

View File

@ -28,6 +28,7 @@ import ExpiresPostButton from './expires_post_button'
import RichTextEditorButton from './rich_text_editor_button' import RichTextEditorButton from './rich_text_editor_button'
import StatusContainer from '../../../containers/status_container' import StatusContainer from '../../../containers/status_container'
import StatusVisibilityButton from './status_visibility_button' import StatusVisibilityButton from './status_visibility_button'
import MoreButton from './more_button'
import UploadButton from './media_upload_button' import UploadButton from './media_upload_button'
import UploadForm from './upload_form' import UploadForm from './upload_form'
import Input from '../../../components/input' import Input from '../../../components/input'
@ -82,6 +83,8 @@ class ComposeForm extends ImmutablePureComponent {
if (!this.form.contains(e.target)) { if (!this.form.contains(e.target)) {
this.handleClickOutside() this.handleClickOutside()
} else { } else {
// : todo :
// if mobile go to /compose else openModal
if (!isStandalone && !isModalOpen && !shouldCondense) { if (!isStandalone && !isModalOpen && !shouldCondense) {
this.props.openComposeModal() this.props.openComposeModal()
return false return false
@ -395,7 +398,7 @@ class ComposeForm extends ImmutablePureComponent {
{ !isModalOpen && <ComposeFormSubmitButton /> } { !isModalOpen && <ComposeFormSubmitButton /> }
<ComposeExtraButtonList isMatch={isMatch} hidePro={hidePro} edit={edit} isModal={isModalOpen} /> <ComposeExtraButtonList isStandalone={isStandalone} isMatch={isMatch} hidePro={hidePro} edit={edit} isModal={isModalOpen} />
</div> </div>
) )
} }
@ -413,6 +416,7 @@ class ComposeForm extends ImmutablePureComponent {
<UploadButton /> <UploadButton />
<EmojiPickerButton isMatch={isMatch} /> <EmojiPickerButton isMatch={isMatch} />
<PollButton /> <PollButton />
<MoreButton />
<ComposeFormSubmitButton /> <ComposeFormSubmitButton />
</div> </div>
<div className={[_s.d, _s.posAbs, _s.z2, _s.left0, _s.right0, _s.bottom0, _s.top0].join(' ')} /> <div className={[_s.d, _s.posAbs, _s.z2, _s.left0, _s.right0, _s.bottom0, _s.top0].join(' ')} />

View File

@ -12,6 +12,7 @@ class ComposeFormSubmitButton extends React.PureComponent {
active, active,
small, small,
disabledButton, disabledButton,
type,
} = this.props } = this.props
const containerClasses = CX({ const containerClasses = CX({
@ -72,7 +73,7 @@ class ComposeFormSubmitButton extends React.PureComponent {
// {intl.formatMessage(scheduledAt ? messages.schedulePost : edit ? messages.postEdit : messages.post)} // {intl.formatMessage(scheduledAt ? messages.schedulePost : edit ? messages.postEdit : messages.post)}
ComposeFormSubmitButton.propTypes = { ComposeFormSubmitButton.propTypes = {
type: PropTypes.oneOf(['header', 'block', 'comment'])
} }
export default ComposeFormSubmitButton export default ComposeFormSubmitButton

View File

@ -32,6 +32,7 @@ class EmojiPickerButton extends React.PureComponent {
active={active && isMatch} active={active && isMatch}
buttonRef={this.setButton} buttonRef={this.setButton}
small={small} small={small}
iconClassName={_s.cIconComposeEmoji}
/> />
) )
} }

View File

@ -40,6 +40,7 @@ class ExpiresPostButton extends React.PureComponent {
onClick={this.handleToggle} onClick={this.handleToggle}
small={small} small={small}
title={intl.formatMessage(messages.expires)} title={intl.formatMessage(messages.expires)}
iconClassName={_s.cIconComposeExpires}
/> />
) )
} }

View File

@ -42,6 +42,7 @@ class UploadButton extends ImmutablePureComponent {
onClick={this.handleClick} onClick={this.handleClick}
small={small} small={small}
icon='media' icon='media'
iconClassName={_s.cIconComposeMedia}
> >
<label> <label>
<span className={_s.displayNone}>{intl.formatMessage(messages.upload)}</span> <span className={_s.displayNone}>{intl.formatMessage(messages.upload)}</span>

View File

@ -0,0 +1,10 @@
import React from 'react'
import ComposeExtraButton from './compose_extra_button'
class MoreButton extends React.PureComponent {
render () {
return <ComposeExtraButton title='More' icon='more' iconClassName={_s.cTertiary} />
}
}
export default MoreButton

View File

@ -30,6 +30,7 @@ class PollButton extends React.PureComponent {
icon='poll' icon='poll'
small={small} small={small}
active={active} active={active}
iconClassName={_s.cIconComposePoll}
/> />
) )
} }

View File

@ -28,6 +28,7 @@ class RichTextEditorButton extends React.PureComponent {
onClick={this.handleClick} onClick={this.handleClick}
small={small} small={small}
active={active} active={active}
iconClassName={_s.cIconComposeRichText}
/> />
) )
} }

View File

@ -41,6 +41,7 @@ class SchedulePostButton extends React.PureComponent {
onClick={this.handleToggle} onClick={this.handleToggle}
small={small} small={small}
title={intl.formatMessage(messages.schedule_status)} title={intl.formatMessage(messages.schedule_status)}
iconClassName={_s.cIconComposeSchedule}
/> />
) )
} }

View File

@ -22,6 +22,7 @@ class SpoilerButton extends React.PureComponent {
onClick={this.handleClick} onClick={this.handleClick}
small={small} small={small}
active={active} active={active}
iconClassName={_s.cIconComposeSpoiler}
/> />
) )
} }

View File

@ -42,6 +42,7 @@ class StatusVisibilityButton extends React.PureComponent {
onClick={this.handleOnClick} onClick={this.handleOnClick}
small={small} small={small}
buttonRef={this.setButton} buttonRef={this.setButton}
iconClassName={_s.cIconComposeSensitive}
/> />
) )
} }

View File

@ -114,7 +114,7 @@ class ChatMessagesComposeForm extends React.PureComponent {
disabled={disabled} disabled={disabled}
onClick={this.handleOnSendChatMessage} onClick={this.handleOnSendChatMessage}
> >
<Text color='inherit' className={_s.px10}>Send</Text> <Text color='inherit' weight='medium' className={_s.px10}>Send</Text>
</Button> </Button>
) )

View File

@ -130,7 +130,7 @@ class MessagesLayout extends React.PureComponent {
}, },
]} ]}
> >
<div className={[_s.d, _s.flexRow, _s.w100PC, _s.calcH53PX].join(' ')}> <div className={[_s.d, _s.flexRow, _s.boxShadowNone, _s.w100PC, _s.calcH53PX].join(' ')}>
<ResponsiveClassesComponent <ResponsiveClassesComponent
classNames={[_s.d, _s.flexShrink1, _s.flexGrow1].join(' ')} classNames={[_s.d, _s.flexShrink1, _s.flexGrow1].join(' ')}
classNamesSmall={[_s.d, _s.flexShrink1, _s.flexGrow1].join(' ')} classNamesSmall={[_s.d, _s.flexShrink1, _s.flexGrow1].join(' ')}
@ -159,7 +159,6 @@ class MessagesLayout extends React.PureComponent {
</Layout> </Layout>
) )
} }
} }
const mapStateToProps = (state) => { const mapStateToProps = (state) => {

View File

@ -95,10 +95,10 @@ const reducers = {
status_revisions, status_revisions,
suggestions, suggestions,
timelines, timelines,
// timeline_injections, timeline_injections,
// toasts, toasts,
// user, user,
// user_lists, user_lists,
} }
export default combineReducers(reducers) export default combineReducers(reducers)

View File

@ -7,12 +7,14 @@ import {
FOLLOWERS_FETCH_FAIL, FOLLOWERS_FETCH_FAIL,
FOLLOWERS_EXPAND_REQUEST, FOLLOWERS_EXPAND_REQUEST,
FOLLOWERS_EXPAND_FAIL, FOLLOWERS_EXPAND_FAIL,
FOLLOWING_FETCH_REQUEST, FOLLOWING_FETCH_REQUEST,
FOLLOWING_FETCH_FAIL, FOLLOWING_FETCH_FAIL,
FOLLOWING_EXPAND_REQUEST, FOLLOWING_EXPAND_REQUEST,
FOLLOWING_FETCH_SUCCESS, FOLLOWING_FETCH_SUCCESS,
FOLLOWING_EXPAND_SUCCESS, FOLLOWING_EXPAND_SUCCESS,
FOLLOWING_EXPAND_FAIL, FOLLOWING_EXPAND_FAIL,
FOLLOW_REQUESTS_FETCH_REQUEST, FOLLOW_REQUESTS_FETCH_REQUEST,
FOLLOW_REQUESTS_FETCH_FAIL, FOLLOW_REQUESTS_FETCH_FAIL,
FOLLOW_REQUESTS_EXPAND_REQUEST, FOLLOW_REQUESTS_EXPAND_REQUEST,
@ -29,6 +31,7 @@ import {
REPOSTS_EXPAND_REQUEST, REPOSTS_EXPAND_REQUEST,
REPOSTS_EXPAND_SUCCESS, REPOSTS_EXPAND_SUCCESS,
REPOSTS_EXPAND_FAIL, REPOSTS_EXPAND_FAIL,
LIKES_FETCH_REQUEST, LIKES_FETCH_REQUEST,
LIKES_FETCH_SUCCESS, LIKES_FETCH_SUCCESS,
LIKES_FETCH_FAIL, LIKES_FETCH_FAIL,
@ -52,12 +55,28 @@ import {
MUTES_EXPAND_SUCCESS, MUTES_EXPAND_SUCCESS,
MUTES_EXPAND_FAIL, MUTES_EXPAND_FAIL,
} from '../actions/mutes' } from '../actions/mutes'
import {
CHAT_MESSENGER_BLOCKS_FETCH_REQUEST,
CHAT_MESSENGER_BLOCKS_FETCH_SUCCESS,
CHAT_MESSENGER_BLOCKS_FETCH_FAIL,
CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST,
CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS,
CHAT_MESSENGER_BLOCKS_EXPAND_FAIL,
CHAT_MESSENGER_MUTES_FETCH_REQUEST,
CHAT_MESSENGER_MUTES_FETCH_SUCCESS,
CHAT_MESSENGER_MUTES_FETCH_FAIL,
CHAT_MESSENGER_MUTES_EXPAND_REQUEST,
CHAT_MESSENGER_MUTES_EXPAND_SUCCESS,
CHAT_MESSENGER_MUTES_EXPAND_FAIL,
} from '../actions/chat_conversation_accounts'
import { import {
GROUP_MEMBERS_FETCH_SUCCESS, GROUP_MEMBERS_FETCH_SUCCESS,
GROUP_MEMBERS_EXPAND_SUCCESS, GROUP_MEMBERS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS, GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS, GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS, GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
GROUP_JOIN_REQUESTS_FETCH_SUCCESS, GROUP_JOIN_REQUESTS_FETCH_SUCCESS,
GROUP_JOIN_REQUESTS_EXPAND_SUCCESS, GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
GROUP_JOIN_REQUESTS_APPROVE_SUCCESS, GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
@ -73,6 +92,8 @@ const initialState = ImmutableMap({
follow_requests: ImmutableMap(), follow_requests: ImmutableMap(),
blocks: ImmutableMap(), blocks: ImmutableMap(),
mutes: ImmutableMap(), mutes: ImmutableMap(),
chat_blocks: ImmutableMap(),
chat_mutes: ImmutableMap(),
groups: ImmutableMap(), groups: ImmutableMap(),
group_removed_accounts: ImmutableMap(), group_removed_accounts: ImmutableMap(),
group_join_requests: ImmutableMap(), group_join_requests: ImmutableMap(),
@ -210,6 +231,29 @@ export default function userLists(state = initialState, action) {
case GROUP_JOIN_REQUESTS_APPROVE_SUCCESS: case GROUP_JOIN_REQUESTS_APPROVE_SUCCESS:
case GROUP_JOIN_REQUESTS_REJECT_SUCCESS: case GROUP_JOIN_REQUESTS_REJECT_SUCCESS:
return state.updateIn(['group_join_requests', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId)); return state.updateIn(['group_join_requests', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId));
case CHAT_MESSENGER_BLOCKS_FETCH_REQUEST:
case CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST:
return state.setIn(['chat_blocks', me, 'isLoading'], true)
case CHAT_MESSENGER_BLOCKS_FETCH_SUCCESS:
return normalizeList(state, 'chat_blocks', me, action.accounts, action.next)
case CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS:
return appendToList(state, 'chat_blocks', me, action.accounts, action.next)
case CHAT_MESSENGER_BLOCKS_FETCH_FAIL:
case CHAT_MESSENGER_BLOCKS_EXPAND_FAIL:
return setListFailed(state, 'chat_blocks', me)
case CHAT_MESSENGER_MUTES_FETCH_REQUEST:
case CHAT_MESSENGER_MUTES_EXPAND_REQUEST:
return state.setIn(['chat_mutes', me, 'isLoading'], true)
case CHAT_MESSENGER_MUTES_FETCH_SUCCESS:
return normalizeList(state, 'chat_mutes', me, action.accounts, action.next)
case CHAT_MESSENGER_MUTES_EXPAND_SUCCESS:
return appendToList(state, 'chat_mutes', me, action.accounts, action.next)
case CHAT_MESSENGER_MUTES_FETCH_FAIL:
case CHAT_MESSENGER_MUTES_EXPAND_FAIL:
return setListFailed(state, 'chat_mutes', me)
default: default:
return state; return state;
} }

View File

@ -490,6 +490,17 @@ pre {
/* */ /* */
.cIconComposeEmoji { color: #F6B83C; }
.cIconComposeExpires { color: #EE2C4D; }
.cIconComposeMedia { color: #4BBC66; }
.cIconComposePoll { color: #F87E3A; }
.cIconComposeRichText { color: #227BEF; }
.cIconComposeSchedule { color: #ff0000; }
.cIconComposeSpoiler { color: #8C75C9; }
.cIconComposeSensitive { color: #35BBA7; }
/* */
.topNeg50PX { top: -50px; } .topNeg50PX { top: -50px; }
.topNeg20PX { top: -20px; } .topNeg20PX { top: -20px; }
.top0 { top: 0; } .top0 { top: 0; }

View File

@ -16,6 +16,7 @@
# chat_message_expiration_policy :string # chat_message_expiration_policy :string
# #
# : todo : expires
class ChatConversationAccount < ApplicationRecord class ChatConversationAccount < ApplicationRecord
include Paginable include Paginable

View File

@ -71,6 +71,18 @@ module AccountInteractions
has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account
has_many :muted_by_relationships, class_name: 'Mute', foreign_key: :target_account_id, dependent: :destroy has_many :muted_by_relationships, class_name: 'Mute', foreign_key: :target_account_id, dependent: :destroy
has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account
# Chat block relationships
has_many :chat_block_relationships, class_name: 'ChatBlock', foreign_key: 'account_id', dependent: :destroy
has_many :chat_blocking, -> { order('chat_blocks.id desc') }, through: :chat_block_relationships, source: :target_account
has_many :chat_blocked_by_relationships, class_name: 'ChatBlock', foreign_key: :target_account_id, dependent: :destroy
has_many :chat_blocked_by, -> { order('chat_blocks.id desc') }, through: :chat_blocked_by_relationships, source: :account
# Chat mute relationships
has_many :chat_mute_relationships, class_name: 'ChatMute', foreign_key: 'account_id', dependent: :destroy
has_many :chat_muting, -> { order('chat_mutes.id desc') }, through: :chat_mute_relationships, source: :target_account
has_many :chat_muted_by_relationships, class_name: 'ChatMute', foreign_key: :target_account_id, dependent: :destroy
has_many :chat_muted_by, -> { order('chat_mutes.id desc') }, through: :chat_muted_by_relationships, source: :account
end end
def follow!(other_account, reblogs: nil, uri: nil) def follow!(other_account, reblogs: nil, uri: nil)

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class BlockChatMessengerService < BaseService
def call(account, target_account)
return if account.id == target_account.id
block = account.chat_block!(target_account)
block
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class MuteChatMessengerService < BaseService
def call(account, target_account)
return if account.id == target_account.id
mute = account.chat_mute!(target_account)
mute
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class UnblockChatMessengerService < BaseService
def call(account, target_account)
return unless account.chat_blocking?(target_account)
unblock = account.chat_unblock!(target_account)
unblock
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class UnmuteChatMessengerService < BaseService
def call(account, target_account)
return unless account.chat_muting?(target_account)
account.chat_unmute!(target_account)
end
end

View File

@ -222,11 +222,13 @@ Rails.application.routes.draw do
resource :explore, only: :show, controller: :explore resource :explore, only: :show, controller: :explore
end end
resources :chat_conversation_accounts, only: :show do resource :chat_conversation_accounts, only: :show do
resources :blocked_accounts, only: :index resource :blocked_chat_accounts, only: :show, controller: 'chat_conversation_accounts/blocked_chat_accounts'
resources :muted_accounts, only: :index resource :muted_chat_accounts, only: :show, controller: 'chat_conversation_accounts/muted_chat_accounts'
member do member do
get :is_messenger_blocked
get :is_messenger_muted
post :block_messenger post :block_messenger
post :unblock_messenger post :unblock_messenger
post :mute_messenger post :mute_messenger