parent
47cd60f851
commit
7ec426e3d8
|
@ -18,12 +18,12 @@ class Api::V1::ChatConversationAccounts::BlockedChatAccountsController < Api::Ba
|
||||||
|
|
||||||
def paginated_blocks
|
def paginated_blocks
|
||||||
@paginated_blocks ||= ChatBlock.eager_load(target_account: :account_stat)
|
@paginated_blocks ||= ChatBlock.eager_load(target_account: :account_stat)
|
||||||
.where(account: current_account)
|
.where(account: current_account)
|
||||||
.paginate_by_max_id(
|
.paginate_by_max_id(
|
||||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
params[:max_id],
|
params[:max_id],
|
||||||
params[:since_id]
|
params[:since_id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_pagination_headers
|
def insert_pagination_headers
|
||||||
|
|
|
@ -5,43 +5,47 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :write, :'write:chats' }
|
before_action -> { doorkeeper_authorize! :write, :'write:chats' }
|
||||||
|
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_account
|
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]
|
||||||
|
|
||||||
def block_messenger
|
def block_messenger
|
||||||
BlockMessengerService.new.call(current_user.account, @account)
|
@block = BlockChatMessengerService.new.call(current_user.account, @account)
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account,
|
||||||
|
serializer: REST::ChatMessengerBlockedSerializer,
|
||||||
|
chat_blocking: true
|
||||||
end
|
end
|
||||||
|
|
||||||
def unblock_messenger
|
def unblock_messenger
|
||||||
UnblockMessengerService.new.call(current_user.account, @account)
|
UnblockChatMessengerService.new.call(current_user.account, @account)
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account,
|
||||||
|
serializer: REST::ChatMessengerBlockedSerializer,
|
||||||
|
chat_blocking: false
|
||||||
|
end
|
||||||
|
|
||||||
|
def messenger_block_relationships
|
||||||
|
chat_blocking = current_user.account.chat_blocking?(@account)
|
||||||
|
chat_blocked_by = current_user.account.chat_blocked_by?(@account, current_account)
|
||||||
|
render json: @account,
|
||||||
|
serializer: REST::ChatMessengerBlockedSerializer,
|
||||||
|
chat_blocking: chat_blocking,
|
||||||
|
chat_blocked_by: chat_blocked_by
|
||||||
end
|
end
|
||||||
|
|
||||||
def mute_chat_conversation
|
def mute_chat_conversation
|
||||||
@chat_conversation_account.is_muted = true
|
@chat_conversation_account.update!(is_muted: true)
|
||||||
@chat_conversation_account.save!
|
|
||||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmute_chat_conversation
|
def unmute_chat_conversation
|
||||||
@chat_conversation_account.is_muted = false
|
@chat_conversation_account.update!(is_muted: false)
|
||||||
@chat_conversation_account.save!
|
|
||||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_expiration_policy
|
|
||||||
if current_user.account.is_pro
|
|
||||||
# : todo :
|
|
||||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
|
||||||
else
|
|
||||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_account
|
def set_account
|
||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:account_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_chat_conversation
|
def set_chat_conversation
|
||||||
|
|
|
@ -6,7 +6,13 @@ class Api::V1::ChatConversationController < Api::BaseController
|
||||||
|
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_account, only: :create
|
before_action :set_account, only: :create
|
||||||
before_action :set_chat_conversation, only: [:show, :mark_chat_conversation_approved, :mark_chat_conversation_hidden, :mark_chat_conversation_read]
|
before_action :set_chat_conversation, only: [
|
||||||
|
:show,
|
||||||
|
:mark_chat_conversation_approved,
|
||||||
|
:mark_chat_conversation_hidden,
|
||||||
|
:mark_chat_conversation_read,
|
||||||
|
:set_expiration_policy
|
||||||
|
]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render json: {}, each_serializer: REST::ChatConversationAccountSerializer
|
render json: {}, each_serializer: REST::ChatConversationAccountSerializer
|
||||||
|
@ -43,6 +49,33 @@ class Api::V1::ChatConversationController < Api::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_expiration_policy
|
||||||
|
if current_user.account.is_pro
|
||||||
|
case params[:expiration]
|
||||||
|
when 'five_minutes'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:five_minutes]
|
||||||
|
when 'one_hour'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_hour]
|
||||||
|
when 'six_hours'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:six_hours]
|
||||||
|
when 'one_day'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_day]
|
||||||
|
when 'three_days'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:three_days]
|
||||||
|
when 'one_week'
|
||||||
|
@expires_at = ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_week]
|
||||||
|
else
|
||||||
|
@expires_at = nil
|
||||||
|
end
|
||||||
|
puts "tilly @expires_at: " + @expires_at.inspect
|
||||||
|
@chat_conversation_account.chat_message_expiration_policy = @expires_at
|
||||||
|
@chat_conversation_account.save!
|
||||||
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
|
else
|
||||||
|
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_or_create_conversation
|
def find_or_create_conversation
|
||||||
|
|
|
@ -16,7 +16,11 @@ class Api::V1::ChatConversations::MessagesController < Api::BaseController
|
||||||
|
|
||||||
def destroy_all
|
def destroy_all
|
||||||
if current_user.account.is_pro
|
if current_user.account.is_pro
|
||||||
@chat_conversation_account = PurgeChatMessagesService.new.call(current_user.account, @chat_conversation)
|
PurgeChatMessagesService.new.call(current_user.account, @chat_conversation)
|
||||||
|
@chat_conversation_account = ChatConversationAccount.where(
|
||||||
|
account: current_user.account,
|
||||||
|
chat_conversation: @chat_conversation
|
||||||
|
).first
|
||||||
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
else
|
else
|
||||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Api::V1::ChatMessagesController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :write, :'write:chats' }
|
before_action -> { doorkeeper_authorize! :write, :'write:chats' }
|
||||||
|
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
before_action :set_chat_message, only: :destroy
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@chat_conversation = ChatConversation.find(chat_params[:chat_conversation_id])
|
@chat_conversation = ChatConversation.find(chat_params[:chat_conversation_id])
|
||||||
|
@ -13,8 +14,9 @@ class Api::V1::ChatMessagesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@chat = DeleteChatMessageService.new.call(current_user.account, params[:id])
|
return not_found if @chatMessage.nil?
|
||||||
render json: @chat, serializer: REST::ChatMessageSerializer
|
DeleteChatMessageService.new.call(@chatMessage)
|
||||||
|
render json: @chatMessage, serializer: REST::ChatMessageSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -23,4 +25,8 @@ class Api::V1::ChatMessagesController < Api::BaseController
|
||||||
params.permit(:text, :chat_conversation_id)
|
params.permit(:text, :chat_conversation_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_chat_message
|
||||||
|
@chatMessage = ChatMessage.where(from_account: current_user.account).find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,7 @@ 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_SUCCESS = 'UNBLOCK_CHAT_MESSAGER_SUCCESS'
|
||||||
export const UNBLOCK_CHAT_MESSAGER_FAIL = 'UNBLOCK_CHAT_MESSAGER_FAIL'
|
export const UNBLOCK_CHAT_MESSAGER_FAIL = 'UNBLOCK_CHAT_MESSAGER_FAIL'
|
||||||
|
|
||||||
export const IS_CHAT_MESSENGER_BLOCKED_SUCCESS = 'IS_CHAT_MESSENGER_BLOCKED_SUCCESS'
|
export const FETCH_CHAT_MESSENGER_BLOCKING_RELATIONSHIPS_SUCCESS = 'FETCH_CHAT_MESSENGER_BLOCKING_RELATIONSHIPS_SUCCESS'
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -36,13 +36,12 @@ export const UNMUTE_CHAT_CONVERSATION_FAIL = 'UNMUTE_CHAT_CONVERSATION_FAIL'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const blockChatMessenger = (accountId) => (dispatch, getState) => {
|
export const blockChatMessenger = (accountId) => (dispatch, getState) => {
|
||||||
console.log("blockChatMessenger:", accountId)
|
|
||||||
if (!me || !accountId) return
|
if (!me || !accountId) return
|
||||||
|
|
||||||
dispatch(blockChatMessengerRequest(accountId))
|
dispatch(blockChatMessengerRequest(accountId))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/block_messenger`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/_/block_messenger`, { account_id: accountId }).then((response) => {
|
||||||
dispatch(blockChatMessengerSuccess())
|
dispatch(blockChatMessengerSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(blockChatMessengerFail(accountId, error))
|
dispatch(blockChatMessengerFail(accountId, error))
|
||||||
})
|
})
|
||||||
|
@ -53,8 +52,9 @@ const blockChatMessengerRequest = (accountId) => ({
|
||||||
accountId,
|
accountId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const blockChatMessengerSuccess = () => ({
|
const blockChatMessengerSuccess = (data) => ({
|
||||||
type: BLOCK_CHAT_MESSAGER_SUCCESS,
|
type: BLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
|
data,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ export const unblockChatMessenger = (accountId) => (dispatch, getState) => {
|
||||||
|
|
||||||
dispatch(unblockChatMessengerRequest(accountId))
|
dispatch(unblockChatMessengerRequest(accountId))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/unblock_messenger`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/_/unblock_messenger`, { account_id: accountId }).then((response) => {
|
||||||
dispatch(unblockChatMessengerSuccess())
|
dispatch(unblockChatMessengerSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unblockChatMessengerFail(accountId, error))
|
dispatch(unblockChatMessengerFail(accountId, error))
|
||||||
})
|
})
|
||||||
|
@ -85,8 +85,9 @@ const unblockChatMessengerRequest = (accountId) => ({
|
||||||
accountId,
|
accountId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const unblockChatMessengerSuccess = () => ({
|
const unblockChatMessengerSuccess = (data) => ({
|
||||||
type: UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
type: UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
|
data,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -101,16 +102,16 @@ const unblockChatMessengerFail = (accountId, error) => ({
|
||||||
* @description Check if a chat messenger is blocked by the current user account.
|
* @description Check if a chat messenger is blocked by the current user account.
|
||||||
* @param {String} accountId
|
* @param {String} accountId
|
||||||
*/
|
*/
|
||||||
export const isChatMessengerBlocked = (accountId) => (dispatch, getState) => {
|
export const fetchMessengerBlockingRelationships = (accountId) => (dispatch, getState) => {
|
||||||
if (!me || !accountId) return
|
if (!me || !accountId) return
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/is_messenger_blocked`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/_/messenger_block_relationships`, { account_id: accountId }).then((response) => {
|
||||||
dispatch(isChatMessengerBlockedSuccess(response.data))
|
dispatch(fetchMessengerBlockingRelationshipsSuccess(response.data))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChatMessengerBlockedSuccess = (data) => ({
|
const fetchMessengerBlockingRelationshipsSuccess = (data) => ({
|
||||||
type: IS_CHAT_MESSENGER_BLOCKED_SUCCESS,
|
type: FETCH_CHAT_MESSENGER_BLOCKING_RELATIONSHIPS_SUCCESS,
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ export const muteChatConversation = (chatConversationId) => (dispatch, getState)
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${chatConversationId}/mute_chat_conversation`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/${chatConversationId}/mute_chat_conversation`).then((response) => {
|
||||||
dispatch(muteChatConversationSuccess(response.data))
|
dispatch(muteChatConversationSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(muteChatMessengerFail(error))
|
dispatch(muteChatConversationFail(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -389,9 +389,9 @@ export const readChatConversationFail = () => ({
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const setChatConversationExpiration = (chatConversationId, expiration) => (dispatch, getState) => {
|
export const setChatConversationExpiration = (chatConversationId, expiration) => (dispatch, getState) => {
|
||||||
if (!me|| !chatConversationId || !expiration) return
|
if (!me|| !chatConversationId) return
|
||||||
|
|
||||||
dispatch(setChatConversationExpirationFetch(chatConversation))
|
dispatch(setChatConversationExpirationFetch(chatConversationId))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation/${chatConversationId}/set_expiration_policy`, {
|
api(getState).post(`/api/v1/chat_conversation/${chatConversationId}/set_expiration_policy`, {
|
||||||
expiration,
|
expiration,
|
||||||
|
@ -400,18 +400,18 @@ export const setChatConversationExpiration = (chatConversationId, expiration) =>
|
||||||
}).catch((error) => dispatch(setChatConversationExpirationFail(error)))
|
}).catch((error) => dispatch(setChatConversationExpirationFail(error)))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setChatConversationExpirationFetch = (chatConversation) => ({
|
export const setChatConversationExpirationFetch = (chatConversationId) => ({
|
||||||
type: SET_CHAT_CONVERSATION_EXPIRATION_REQUEST,
|
type: SET_CHAT_CONVERSATION_EXPIRATION_REQUEST,
|
||||||
chatConversation,
|
chatConversationId,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const setChatConversationExpirationSuccess = (chatConversation) => ({
|
export const setChatConversationExpirationSuccess = (chatConversation) => ({
|
||||||
type: SET_CHAT_CONVERSATION_EXPIRATION_REQUEST,
|
type: SET_CHAT_CONVERSATION_EXPIRATION_SUCCESS,
|
||||||
chatConversation,
|
chatConversation,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const setChatConversationExpirationFail = (error) => ({
|
export const setChatConversationExpirationFail = (error) => ({
|
||||||
type: SET_CHAT_CONVERSATION_EXPIRATION_REQUEST,
|
type: SET_CHAT_CONVERSATION_EXPIRATION_FAIL,
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -113,12 +113,12 @@ const deleteChatMessageFail = (error) => ({
|
||||||
export const purgeChatMessages = (chatConversationId) => (dispatch, getState) => {
|
export const purgeChatMessages = (chatConversationId) => (dispatch, getState) => {
|
||||||
if (!me || !chatConversationId) return
|
if (!me || !chatConversationId) return
|
||||||
|
|
||||||
dispatch(deleteChatMessagesRequest(chatConversationId))
|
dispatch(purgeChatMessagesRequest(chatConversationId))
|
||||||
|
|
||||||
api(getState).delete(`/api/v1/chat_conversations/messages/${chatConversationId}/destroy_all`).then((response) => {
|
api(getState).delete(`/api/v1/chat_conversations/messages/${chatConversationId}/destroy_all`).then((response) => {
|
||||||
dispatch(deleteChatMessagesSuccess(response.data))
|
dispatch(purgeChatMessagesSuccess(chatConversationId))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(deleteChatMessagesFail(error))
|
dispatch(purgeChatMessagesFail(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@ import { openModal, closeModal } from './modal'
|
||||||
import {
|
import {
|
||||||
MODAL_COMPOSE,
|
MODAL_COMPOSE,
|
||||||
EXPIRATION_OPTION_5_MINUTES,
|
EXPIRATION_OPTION_5_MINUTES,
|
||||||
EXPIRATION_OPTION_60_MINUTES,
|
EXPIRATION_OPTION_1_HOUR,
|
||||||
EXPIRATION_OPTION_6_HOURS,
|
EXPIRATION_OPTION_6_HOURS,
|
||||||
EXPIRATION_OPTION_24_HOURS,
|
EXPIRATION_OPTION_1_DAY,
|
||||||
EXPIRATION_OPTION_3_DAYS,
|
EXPIRATION_OPTION_3_DAYS,
|
||||||
EXPIRATION_OPTION_7_DAYS,
|
EXPIRATION_OPTION_7_DAYS,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
|
@ -345,23 +345,7 @@ export const submitCompose = (groupId, replyToId = null, router, isStandalone, a
|
||||||
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null)
|
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null)
|
||||||
if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate()
|
if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate()
|
||||||
|
|
||||||
let expires_at = getState().getIn(['compose', 'expires_at'], null)
|
const expires_at = getState().getIn(['compose', 'expires_at'], null)
|
||||||
|
|
||||||
if (expires_at) {
|
|
||||||
if (expires_at === EXPIRATION_OPTION_5_MINUTES) {
|
|
||||||
expires_at = moment.utc().add('5', 'minute').toDate()
|
|
||||||
} else if (expires_at === EXPIRATION_OPTION_60_MINUTES) {
|
|
||||||
expires_at = moment.utc().add('60', 'minute').toDate()
|
|
||||||
} else if (expires_at === EXPIRATION_OPTION_6_HOURS) {
|
|
||||||
expires_at = moment.utc().add('6', 'hour').toDate()
|
|
||||||
} else if (expires_at === EXPIRATION_OPTION_24_HOURS) {
|
|
||||||
expires_at = moment.utc().add('24', 'hour').toDate()
|
|
||||||
} else if (expires_at === EXPIRATION_OPTION_3_DAYS) {
|
|
||||||
expires_at = moment.utc().add('3', 'day').toDate()
|
|
||||||
} else if (expires_at === EXPIRATION_OPTION_7_DAYS) {
|
|
||||||
expires_at = moment.utc().add('7', 'day').toDate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMobile(window.innerWidth) && router && isStandalone) {
|
if (isMobile(window.innerWidth) && router && isStandalone) {
|
||||||
router.history.goBack()
|
router.history.goBack()
|
||||||
|
|
|
@ -3,12 +3,12 @@ import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { closePopover } from '../../actions/popover'
|
import { closePopover } from '../../actions/popover'
|
||||||
import { changeExpiresAt } from '../../actions/compose'
|
import { setChatConversationExpiration } from '../../actions/chat_conversations'
|
||||||
import {
|
import {
|
||||||
EXPIRATION_OPTION_5_MINUTES,
|
EXPIRATION_OPTION_5_MINUTES,
|
||||||
EXPIRATION_OPTION_60_MINUTES,
|
EXPIRATION_OPTION_1_HOUR,
|
||||||
EXPIRATION_OPTION_6_HOURS,
|
EXPIRATION_OPTION_6_HOURS,
|
||||||
EXPIRATION_OPTION_24_HOURS,
|
EXPIRATION_OPTION_1_DAY,
|
||||||
EXPIRATION_OPTION_3_DAYS,
|
EXPIRATION_OPTION_3_DAYS,
|
||||||
EXPIRATION_OPTION_7_DAYS,
|
EXPIRATION_OPTION_7_DAYS,
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
|
@ -19,7 +19,7 @@ import Text from '../text'
|
||||||
class ChatConversationExpirationOptionsPopover extends React.PureComponent {
|
class ChatConversationExpirationOptionsPopover extends React.PureComponent {
|
||||||
|
|
||||||
handleOnSetExpiration = (expiresAt) => {
|
handleOnSetExpiration = (expiresAt) => {
|
||||||
this.props.onChangeExpiresAt(expiresAt)
|
this.props.onSetChatConversationExpiration(expiresAt)
|
||||||
this.handleOnClosePopover()
|
this.handleOnClosePopover()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,66 +29,62 @@ class ChatConversationExpirationOptionsPopover extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
chatConversationId,
|
||||||
expiresAtValue,
|
expiresAtValue,
|
||||||
intl,
|
intl,
|
||||||
isXS,
|
isXS,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
console.log("expiresAtValue:", expiresAtValue)
|
||||||
|
if (!chatConversationId) return <div/>
|
||||||
|
|
||||||
const listItems = [
|
const listItems = [
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: 'None',
|
title: 'None',
|
||||||
onClick: () => this.handleOnSetStatusExpiration(null),
|
onClick: () => this.handleOnSetExpiration(null),
|
||||||
isActive: !expiresAtValue,
|
isActive: !expiresAtValue,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.minutes, { number: 5 }),
|
title: intl.formatMessage(messages.minutes, { number: 5 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_5_MINUTES),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_5_MINUTES),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_5_MINUTES,
|
isActive: expiresAtValue === EXPIRATION_OPTION_5_MINUTES,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.minutes, { number: 60 }),
|
title: intl.formatMessage(messages.minutes, { number: 60 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_60_MINUTES),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_1_HOUR),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_60_MINUTES,
|
isActive: expiresAtValue === EXPIRATION_OPTION_1_HOUR,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: '6 hours',
|
title: '6 hours',
|
||||||
title: intl.formatMessage(messages.hours, { number: 6 }),
|
title: intl.formatMessage(messages.hours, { number: 6 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_6_HOURS),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_6_HOURS),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_6_HOURS,
|
isActive: expiresAtValue === EXPIRATION_OPTION_6_HOURS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.hours, { number: 24 }),
|
title: intl.formatMessage(messages.hours, { number: 24 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_24_HOURS),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_1_DAY),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_24_HOURS,
|
isActive: expiresAtValue === EXPIRATION_OPTION_1_DAY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: '3 days',
|
title: '3 days',
|
||||||
title: intl.formatMessage(messages.days, { number: 3 }),
|
title: intl.formatMessage(messages.days, { number: 3 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_3_DAYS),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_3_DAYS),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_3_DAYS,
|
isActive: expiresAtValue === EXPIRATION_OPTION_3_DAYS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.days, { number: 7 }),
|
title: intl.formatMessage(messages.days, { number: 7 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_7_DAYS),
|
onClick: () => this.handleOnSetExpiration(EXPIRATION_OPTION_7_DAYS),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_7_DAYS,
|
isActive: expiresAtValue === EXPIRATION_OPTION_7_DAYS,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
if (expiresAtValue) {
|
|
||||||
listItems.unshift({
|
|
||||||
hideArrow: true,
|
|
||||||
title: 'Remove expiration',
|
|
||||||
onClick: () => this.handleOnSetStatusExpiration(null),
|
|
||||||
},)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PopoverLayout
|
<PopoverLayout
|
||||||
width={210}
|
width={210}
|
||||||
|
@ -113,24 +109,24 @@ const messages = defineMessages({
|
||||||
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state, { chatConversationId }) => ({
|
||||||
expiresAtValue: state.getIn(['compose', 'expires_at']),
|
expiresAtValue: state.getIn(['chat_conversations', chatConversationId, 'chat_message_expiration_policy']),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch, { chatConversationId }) => ({
|
||||||
onChangeExpiresAt(expiresAt) {
|
|
||||||
dispatch(changeExpiresAt(expiresAt))
|
|
||||||
},
|
|
||||||
onClosePopover() {
|
onClosePopover() {
|
||||||
dispatch(closePopover())
|
dispatch(closePopover())
|
||||||
},
|
},
|
||||||
|
onSetChatConversationExpiration(expiration) {
|
||||||
|
dispatch(setChatConversationExpiration(chatConversationId, expiration))
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
ChatConversationExpirationOptionsPopover.defaultProps = {
|
ChatConversationExpirationOptionsPopover.defaultProps = {
|
||||||
expiresAtValue: PropTypes.string.isRequired,
|
expiresAtValue: PropTypes.string.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
isXS: PropTypes.bool,
|
isXS: PropTypes.bool,
|
||||||
onChangeExpiresAt: PropTypes.func.isRequired,
|
onSetChatConversationExpiration: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ChatConversationExpirationOptionsPopover))
|
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ChatConversationExpirationOptionsPopover))
|
|
@ -6,6 +6,10 @@ 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 { hideChatConversation } from '../../actions/chat_conversations'
|
import { hideChatConversation } from '../../actions/chat_conversations'
|
||||||
|
import {
|
||||||
|
muteChatConversation,
|
||||||
|
unmuteChatConversation,
|
||||||
|
} from '../../actions/chat_conversation_accounts'
|
||||||
import { purgeChatMessages } from '../../actions/chat_messages'
|
import { purgeChatMessages } from '../../actions/chat_messages'
|
||||||
import { MODAL_PRO_UPGRADE } from '../../constants'
|
import { MODAL_PRO_UPGRADE } from '../../constants'
|
||||||
import { me } from '../../initial_state'
|
import { me } from '../../initial_state'
|
||||||
|
@ -21,8 +25,12 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
this.handleOnClosePopover()
|
this.handleOnClosePopover()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnUnmute = () => {
|
handleOnMute = () => {
|
||||||
this.props.onUnute()
|
if (this.props.isMuted) {
|
||||||
|
this.props.onUnmute()
|
||||||
|
} else {
|
||||||
|
this.props.onMute()
|
||||||
|
}
|
||||||
this.handleOnClosePopover()
|
this.handleOnClosePopover()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +38,7 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
if (!this.props.isPro) {
|
if (!this.props.isPro) {
|
||||||
this.props.openProUpgradeModal()
|
this.props.openProUpgradeModal()
|
||||||
} else {
|
} else {
|
||||||
this.props.onPurge(this.props.chatConversationId)
|
this.props.onPurge()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleOnClosePopover()
|
this.handleOnClosePopover()
|
||||||
|
@ -44,6 +52,7 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
isXS,
|
isXS,
|
||||||
|
isMuted,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
|
@ -55,9 +64,9 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: 'Mute Conversation',
|
title: isMuted ? 'Unmute Conversation' : 'Mute Conversation',
|
||||||
subtitle: "Don't get notified of new messages",
|
subtitle: isMuted ? null : "Don't get notified of new messages",
|
||||||
onClick: () => this.handleOnHide(),
|
onClick: () => this.handleOnMute(),
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -86,23 +95,28 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
|
|
||||||
const mapStateToProps = (state, { chatConversationId }) => ({
|
const mapStateToProps = (state, { chatConversationId }) => ({
|
||||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||||
chatConversation: makeGetChatConversation()(state, { id: chatConversationId }),
|
isMuted: state.getIn(['chat_conversations', chatConversationId, 'is_muted']),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch, { chatConversationId }) => ({
|
||||||
openProUpgradeModal() {
|
openProUpgradeModal() {
|
||||||
dispatch(openModal(MODAL_PRO_UPGRADE))
|
dispatch(openModal(MODAL_PRO_UPGRADE))
|
||||||
},
|
},
|
||||||
onSetCommentSortingSetting(type) {
|
onPurge() {
|
||||||
dispatch(closePopover())
|
|
||||||
},
|
|
||||||
onPurge(chatConversationId) {
|
|
||||||
dispatch(purgeChatMessages(chatConversationId))
|
dispatch(purgeChatMessages(chatConversationId))
|
||||||
},
|
},
|
||||||
onHide(chatConversationId) {
|
onHide() {
|
||||||
dispatch(hideChatConversation(chatConversationId))
|
dispatch(hideChatConversation(chatConversationId))
|
||||||
},
|
},
|
||||||
onClosePopover: () => dispatch(closePopover()),
|
onMute() {
|
||||||
|
dispatch(muteChatConversation(chatConversationId))
|
||||||
|
},
|
||||||
|
onUnmute() {
|
||||||
|
dispatch(unmuteChatConversation(chatConversationId))
|
||||||
|
},
|
||||||
|
onClosePopover() {
|
||||||
|
dispatch(closePopover())
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
ChatConversationOptionsPopover.propTypes = {
|
ChatConversationOptionsPopover.propTypes = {
|
||||||
|
|
|
@ -4,11 +4,11 @@ import { connect } from 'react-redux'
|
||||||
import { closePopover } from '../../actions/popover'
|
import { closePopover } from '../../actions/popover'
|
||||||
import { deleteChatMessage } from '../../actions/chat_messages'
|
import { deleteChatMessage } from '../../actions/chat_messages'
|
||||||
import {
|
import {
|
||||||
|
fetchMessengerBlockingRelationships,
|
||||||
blockChatMessenger,
|
blockChatMessenger,
|
||||||
unblockChatMessenger,
|
unblockChatMessenger,
|
||||||
reportChatMessage,
|
// reportChatMessage,
|
||||||
} from '../../actions/chat_conversation_accounts'
|
} from '../../actions/chat_conversation_accounts'
|
||||||
import { fetchRelationships } from '../../actions/accounts'
|
|
||||||
import { makeGetChatMessage } from '../../selectors'
|
import { makeGetChatMessage } from '../../selectors'
|
||||||
import { me } from '../../initial_state'
|
import { me } from '../../initial_state'
|
||||||
import PopoverLayout from './popover_layout'
|
import PopoverLayout from './popover_layout'
|
||||||
|
@ -20,7 +20,7 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.isMine) {
|
if (!this.props.isMine) {
|
||||||
this.props.onFetchRelationships(this.props.fromAccountId)
|
this.props.onFetchMessengerBlockingRelationships(this.props.fromAccountId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnBlock = () => {
|
handleOnBlock = () => {
|
||||||
if (this.props.isBlocked) {
|
if (this.props.isChatBlocked) {
|
||||||
this.props.onUnblock(this.props.fromAccountId)
|
this.props.onUnblock(this.props.fromAccountId)
|
||||||
} else {
|
} else {
|
||||||
this.props.onBlock(this.props.fromAccountId)
|
this.props.onBlock(this.props.fromAccountId)
|
||||||
|
@ -48,7 +48,7 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
const {
|
const {
|
||||||
isXS,
|
isXS,
|
||||||
isMine,
|
isMine,
|
||||||
isBlocked,
|
isChatBlocked,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const items = isMine ? [
|
const items = isMine ? [
|
||||||
|
@ -66,8 +66,8 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: isBlocked ? 'Unblock Messenger' : 'Block Messenger',
|
title: isChatBlocked ? 'Unblock Messenger' : 'Block Messenger',
|
||||||
subtitle: isBlocked ? '' : 'The messenger will not be able to message you.',
|
subtitle: isChatBlocked ? null : 'The messenger will not be able to message you.',
|
||||||
onClick: () => this.handleOnBlock(),
|
onClick: () => this.handleOnBlock(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -90,7 +90,7 @@ const mapStateToProps = (state, { chatMessageId }) => {
|
||||||
return {
|
return {
|
||||||
fromAccountId,
|
fromAccountId,
|
||||||
isMine: fromAccountId === me,
|
isMine: fromAccountId === me,
|
||||||
isBlocked: state.getIn(['relationships', fromAccountId, 'chat_blocked_by'], false),
|
isChatBlocked: state.getIn(['relationships', fromAccountId, 'chat_blocking'], false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,15 +101,19 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
},
|
},
|
||||||
onBlock(accountId) {
|
onBlock(accountId) {
|
||||||
dispatch(blockChatMessenger(accountId))
|
dispatch(blockChatMessenger(accountId))
|
||||||
|
dispatch(closePopover())
|
||||||
},
|
},
|
||||||
onUnblock(accountId) {
|
onUnblock(accountId) {
|
||||||
dispatch(unblockChatMessenger(accountId))
|
dispatch(unblockChatMessenger(accountId))
|
||||||
|
dispatch(closePopover())
|
||||||
},
|
},
|
||||||
onReportChatMessage(chatMessageId) {
|
onReportChatMessage(chatMessageId) {
|
||||||
dispatch(reportChatMessage(chatMessageId))
|
// : todo :
|
||||||
|
// dispatch(reportChatMessage(chatMessageId))
|
||||||
|
dispatch(closePopover())
|
||||||
},
|
},
|
||||||
onFetchRelationships(accountId) {
|
onFetchMessengerBlockingRelationships(accountId) {
|
||||||
// dispatch(fetchRelationships(accountId))
|
dispatch(fetchMessengerBlockingRelationships(accountId))
|
||||||
},
|
},
|
||||||
onClosePopover() {
|
onClosePopover() {
|
||||||
dispatch(closePopover())
|
dispatch(closePopover())
|
||||||
|
@ -120,8 +124,9 @@ ChatMessageOptionsPopover.propTypes = {
|
||||||
isXS: PropTypes.bool,
|
isXS: PropTypes.bool,
|
||||||
isMine: PropTypes.bool,
|
isMine: PropTypes.bool,
|
||||||
chatMessageId: PropTypes.string.isRequired,
|
chatMessageId: PropTypes.string.isRequired,
|
||||||
isBlocked: PropTypes.bool.isRequired,
|
isChatBlocked: PropTypes.bool.isRequired,
|
||||||
onDeleteChatMessage: PropTypes.func.isRequired,
|
onDeleteChatMessage: PropTypes.func.isRequired,
|
||||||
|
onIsChatMessengerBlocked: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatMessageOptionsPopover)
|
export default connect(mapStateToProps, mapDispatchToProps)(ChatMessageOptionsPopover)
|
|
@ -6,9 +6,9 @@ import { closePopover } from '../../actions/popover'
|
||||||
import { changeExpiresAt } from '../../actions/compose'
|
import { changeExpiresAt } from '../../actions/compose'
|
||||||
import {
|
import {
|
||||||
EXPIRATION_OPTION_5_MINUTES,
|
EXPIRATION_OPTION_5_MINUTES,
|
||||||
EXPIRATION_OPTION_60_MINUTES,
|
EXPIRATION_OPTION_1_HOUR,
|
||||||
EXPIRATION_OPTION_6_HOURS,
|
EXPIRATION_OPTION_6_HOURS,
|
||||||
EXPIRATION_OPTION_24_HOURS,
|
EXPIRATION_OPTION_1_DAY,
|
||||||
EXPIRATION_OPTION_3_DAYS,
|
EXPIRATION_OPTION_3_DAYS,
|
||||||
EXPIRATION_OPTION_7_DAYS,
|
EXPIRATION_OPTION_7_DAYS,
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
|
@ -50,8 +50,8 @@ class StatusExpirationOptionsPopover extends React.PureComponent {
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.minutes, { number: 60 }),
|
title: intl.formatMessage(messages.minutes, { number: 60 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_60_MINUTES),
|
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_1_HOUR),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_60_MINUTES,
|
isActive: expiresAtValue === EXPIRATION_OPTION_1_HOUR,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
|
@ -63,8 +63,8 @@ class StatusExpirationOptionsPopover extends React.PureComponent {
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
title: intl.formatMessage(messages.hours, { number: 24 }),
|
title: intl.formatMessage(messages.hours, { number: 24 }),
|
||||||
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_24_HOURS),
|
onClick: () => this.handleOnSetStatusExpiration(EXPIRATION_OPTION_1_DAY),
|
||||||
isActive: expiresAtValue === EXPIRATION_OPTION_24_HOURS,
|
isActive: expiresAtValue === EXPIRATION_OPTION_1_DAY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
|
|
|
@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import punycode from 'punycode'
|
|
||||||
import {
|
import {
|
||||||
CX,
|
CX,
|
||||||
DEFAULT_REL,
|
DEFAULT_REL,
|
||||||
|
|
|
@ -134,9 +134,9 @@ export const GAB_COM_INTRODUCE_YOURSELF_GROUP_ID = '12'
|
||||||
export const MIN_ACCOUNT_CREATED_AT_ONBOARDING = 1594789200000 // 2020-07-15
|
export const MIN_ACCOUNT_CREATED_AT_ONBOARDING = 1594789200000 // 2020-07-15
|
||||||
|
|
||||||
export const EXPIRATION_OPTION_5_MINUTES = 'five_minutes'
|
export const EXPIRATION_OPTION_5_MINUTES = 'five_minutes'
|
||||||
export const EXPIRATION_OPTION_60_MINUTES = 'one_hour'
|
export const EXPIRATION_OPTION_1_HOUR = 'one_hour'
|
||||||
export const EXPIRATION_OPTION_6_HOURS = 'six_hours'
|
export const EXPIRATION_OPTION_6_HOURS = 'six_hours'
|
||||||
export const EXPIRATION_OPTION_24_HOURS = 'one_day'
|
export const EXPIRATION_OPTION_1_DAY = 'one_day'
|
||||||
export const EXPIRATION_OPTION_3_DAYS = 'three_days'
|
export const EXPIRATION_OPTION_3_DAYS = 'three_days'
|
||||||
export const EXPIRATION_OPTION_7_DAYS = 'one_week'
|
export const EXPIRATION_OPTION_7_DAYS = 'one_week'
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { makeGetChatConversation } from '../../../selectors'
|
||||||
import { setChatConversationSelected } from '../../../actions/chats'
|
import { setChatConversationSelected } from '../../../actions/chats'
|
||||||
import { CX } from '../../../constants'
|
import { CX } from '../../../constants'
|
||||||
import Input from '../../../components/input'
|
import Input from '../../../components/input'
|
||||||
|
import Icon from '../../../components/icon'
|
||||||
import DisplayNameGroup from '../../../components/display_name_group'
|
import DisplayNameGroup from '../../../components/display_name_group'
|
||||||
import DisplayName from '../../../components/display_name'
|
import DisplayName from '../../../components/display_name'
|
||||||
import AvatarGroup from '../../../components/avatar_group'
|
import AvatarGroup from '../../../components/avatar_group'
|
||||||
|
@ -35,8 +36,6 @@ class ChatConversationsListItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
if (!chatConversation) return <div/>
|
if (!chatConversation) return <div/>
|
||||||
|
|
||||||
console.log("chatConversation:", chatConversation)
|
|
||||||
|
|
||||||
const containerClasses = CX({
|
const containerClasses = CX({
|
||||||
d: 1,
|
d: 1,
|
||||||
w100PC: 1,
|
w100PC: 1,
|
||||||
|
@ -66,6 +65,8 @@ class ChatConversationsListItem extends ImmutablePureComponent {
|
||||||
lastMessageText = lastMessageText.length >= 28 ? `${lastMessageText.substring(0, 28).trim()}...` : lastMessageText
|
lastMessageText = lastMessageText.length >= 28 ? `${lastMessageText.substring(0, 28).trim()}...` : lastMessageText
|
||||||
const content = { __html: lastMessageText }
|
const content = { __html: lastMessageText }
|
||||||
const date = !!lastMessage ? lastMessage.get('created_at') : chatConversation.get('created_at')
|
const date = !!lastMessage ? lastMessage.get('created_at') : chatConversation.get('created_at')
|
||||||
|
const isUnread = chatConversation.get('is_unread')
|
||||||
|
const isMuted = chatConversation.get('is_muted')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
@ -73,7 +74,13 @@ class ChatConversationsListItem extends ImmutablePureComponent {
|
||||||
onClick={this.handleOnClick}
|
onClick={this.handleOnClick}
|
||||||
>
|
>
|
||||||
|
|
||||||
{ chatConversation.get('is_unread') && <div className={[_s.d, _s.posAbs, _s.left0, _s.top50PC, _s.ml10, _s.mtNeg5PX, _s.circle, _s.w10PX, _s.h10PX, _s.bgBrand].join(' ')} /> }
|
{ isUnread && !isMuted && <div className={[_s.d, _s.posAbs, _s.left0, _s.top50PC, _s.ml10, _s.mtNeg5PX, _s.circle, _s.w10PX, _s.h10PX, _s.bgBrand].join(' ')} /> }
|
||||||
|
{
|
||||||
|
isMuted &&
|
||||||
|
<div className={[_s.d, _s.posAbs, _s.left0, _s.top50PC, _s.ml10, _s.mtNeg5PX, _s.circle, _s.w10PX, _s.h10PX, _s.bgTransparent].join(' ')}>
|
||||||
|
<Icon id='audio-mute' className={_s.cError} size='12px' />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div className={innerContainerClasses}>
|
<div className={innerContainerClasses}>
|
||||||
<AvatarGroup accounts={otherAccounts} size={avatarSize} noHover />
|
<AvatarGroup accounts={otherAccounts} size={avatarSize} noHover />
|
||||||
|
|
|
@ -88,7 +88,11 @@ class ChatMessagesComposeForm extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isXS, chatConversationId } = this.props
|
const {
|
||||||
|
isXS,
|
||||||
|
expiresAtValue,
|
||||||
|
chatConversationId,
|
||||||
|
} = this.props
|
||||||
const { value } = this.state
|
const { value } = this.state
|
||||||
const disabled = false
|
const disabled = false
|
||||||
|
|
||||||
|
@ -108,6 +112,22 @@ class ChatMessagesComposeForm extends React.PureComponent {
|
||||||
py10: 1,
|
py10: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const expireBtnClasses = CX({
|
||||||
|
d: 1,
|
||||||
|
borderRight1PX: 1,
|
||||||
|
borderColorSecondary: 1,
|
||||||
|
w40PX: 1,
|
||||||
|
h100PC: 1,
|
||||||
|
aiCenter: 1,
|
||||||
|
jcCenter: 1,
|
||||||
|
cursorPointer: 1,
|
||||||
|
outlineNone: 1,
|
||||||
|
bgSubtle: !expiresAtValue,
|
||||||
|
bgBlack: !!expiresAtValue,
|
||||||
|
})
|
||||||
|
|
||||||
|
const expireBtnIconClassName = !!expiresAtValue ? _s.cWhite : _s.cBlack
|
||||||
|
|
||||||
const textarea = (
|
const textarea = (
|
||||||
<Textarea
|
<Textarea
|
||||||
id='chat-message-compose-input'
|
id='chat-message-compose-input'
|
||||||
|
@ -137,13 +157,15 @@ class ChatMessagesComposeForm extends React.PureComponent {
|
||||||
)
|
)
|
||||||
|
|
||||||
const expiresBtn = (
|
const expiresBtn = (
|
||||||
<button
|
<Button
|
||||||
ref={this.setExpiresBtn}
|
noClasses
|
||||||
className={[_s.d, _s.bgSubtle, _s.borderRight1PX, _s.borderColorSecondary, _s.w40PX, _s.h100PC, _s.aiCenter, _s.jcCenter, _s.cursorPointer, _s.outlineNone].join(' ')}
|
buttonRef={this.setExpiresBtn}
|
||||||
|
className={expireBtnClasses}
|
||||||
onClick={this.handleOnExpire}
|
onClick={this.handleOnExpire}
|
||||||
>
|
icon='stopwatch'
|
||||||
<Icon id='stopwatch' className={[_s.cPrimary, _s.ml2].join(' ')} size='15px' />
|
iconSize='15px'
|
||||||
</button>
|
iconClassName={expireBtnIconClassName}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isXS) {
|
if (isXS) {
|
||||||
|
@ -191,8 +213,9 @@ class ChatMessagesComposeForm extends React.PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state, { chatConversationId }) => ({
|
||||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||||
|
expiresAtValue: state.getIn(['chat_conversations', chatConversationId, 'chat_message_expiration_policy']),
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { chatConversationId }) => ({
|
const mapDispatchToProps = (dispatch, { chatConversationId }) => ({
|
||||||
|
|
|
@ -12,9 +12,11 @@ import {
|
||||||
} from '../../../constants'
|
} from '../../../constants'
|
||||||
import { me } from '../../../initial_state'
|
import { me } from '../../../initial_state'
|
||||||
import Input from '../../../components/input'
|
import Input from '../../../components/input'
|
||||||
|
import Icon from '../../../components/icon'
|
||||||
import Avatar from '../../../components/avatar'
|
import Avatar from '../../../components/avatar'
|
||||||
import Button from '../../../components/button'
|
import Button from '../../../components/button'
|
||||||
import Text from '../../../components/text'
|
import Text from '../../../components/text'
|
||||||
|
import DotTextSeperator from '../../../components/dot_text_seperator'
|
||||||
import { makeGetChatMessage } from '../../../selectors'
|
import { makeGetChatMessage } from '../../../selectors'
|
||||||
|
|
||||||
class ChatMessageItem extends ImmutablePureComponent {
|
class ChatMessageItem extends ImmutablePureComponent {
|
||||||
|
@ -30,9 +32,9 @@ class ChatMessageItem extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { lastChatMessageSameSender, lastChatMessageDate } = this.props
|
const { lastChatMessageSameSender, lastChatMessageDate, chatMessage } = this.props
|
||||||
if (lastChatMessageDate) {
|
if (lastChatMessageDate && chatMessage) {
|
||||||
const createdAt = this.props.chatMessage.get('created_at')
|
const createdAt = chatMessage.get('created_at')
|
||||||
const isNewDay = moment(createdAt).format('L') !== moment(lastChatMessageDate).format('L')
|
const isNewDay = moment(createdAt).format('L') !== moment(lastChatMessageDate).format('L')
|
||||||
const isCloseToMyLast = moment(lastChatMessageDate).diff(createdAt, 'minutes') < 60 && lastChatMessageSameSender && !isNewDay
|
const isCloseToMyLast = moment(lastChatMessageDate).diff(createdAt, 'minutes') < 60 && lastChatMessageSameSender && !isNewDay
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -125,6 +127,12 @@ class ChatMessageItem extends ImmutablePureComponent {
|
||||||
displayNone: !isHovering,
|
displayNone: !isHovering,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const expirationDate = chatMessage.get('expires_at')
|
||||||
|
let timeUntilExpiration
|
||||||
|
if (!!expirationDate) {
|
||||||
|
timeUntilExpiration = moment(expirationDate).fromNow()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={[_s.d, _s.w100PC, _s.pb10].join(' ')}
|
className={[_s.d, _s.w100PC, _s.pb10].join(' ')}
|
||||||
|
@ -161,6 +169,15 @@ class ChatMessageItem extends ImmutablePureComponent {
|
||||||
<div className={lowerContainerClasses}>
|
<div className={lowerContainerClasses}>
|
||||||
<Text size='extraSmall' color='tertiary' align={alt ? 'right' : 'left'}>
|
<Text size='extraSmall' color='tertiary' align={alt ? 'right' : 'left'}>
|
||||||
{moment(createdAt).format('lll')}
|
{moment(createdAt).format('lll')}
|
||||||
|
|
||||||
|
{
|
||||||
|
!!expirationDate &&
|
||||||
|
<React.Fragment>
|
||||||
|
<DotTextSeperator />
|
||||||
|
<Text size='extraSmall' color='tertiary' className={_s.ml5}>Expires in {timeUntilExpiration}</Text>
|
||||||
|
<Icon id='stopwatch' size='11px' className={[_s.d, _s.ml5, _s.displayInline, _s.cSecondary].join(' ')} />
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -47,15 +47,11 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
||||||
this.detachIntersectionObserver()
|
this.detachIntersectionObserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
|
||||||
const { chatConversationId } = nextProps
|
|
||||||
|
|
||||||
if (chatConversationId !== this.props.chatConversationId) {
|
|
||||||
this.props.onExpandChatMessages(chatConversationId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
|
if (prevProps.chatConversationId !== this.props.chatConversationId) {
|
||||||
|
this.props.onExpandChatMessages(this.props.chatConversationId)
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the scroll position when a new child comes in in order not to
|
// Reset the scroll position when a new child comes in in order not to
|
||||||
// jerk the scrollbar around if you're already scrolled down the page.
|
// jerk the scrollbar around if you're already scrolled down the page.
|
||||||
if (snapshot !== null && this.scrollContainerRef) {
|
if (snapshot !== null && this.scrollContainerRef) {
|
||||||
|
@ -69,6 +65,8 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
||||||
if (prevProps.chatMessageIds.size === 0 && this.props.chatMessageIds.size > 0 && this.scrollContainerRef) {
|
if (prevProps.chatMessageIds.size === 0 && this.props.chatMessageIds.size > 0 && this.scrollContainerRef) {
|
||||||
this.scrollContainerRef.scrollTop = this.scrollContainerRef.scrollHeight
|
this.scrollContainerRef.scrollTop = this.scrollContainerRef.scrollHeight
|
||||||
this.props.onReadChatConversation(this.props.chatConversationId)
|
this.props.onReadChatConversation(this.props.chatConversationId)
|
||||||
|
} else if (prevProps.chatMessageIds.size < this.props.chatMessageIds.size && this.scrollContainerRef) {
|
||||||
|
this.scrollContainerRef.scrollTop = this.scrollContainerRef.scrollHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +263,6 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
|
||||||
lastChatMessageId={lastChatMessageId}
|
lastChatMessageId={lastChatMessageId}
|
||||||
onMoveUp={this.handleMoveUp}
|
onMoveUp={this.handleMoveUp}
|
||||||
onMoveDown={this.handleMoveDown}
|
onMoveDown={this.handleMoveDown}
|
||||||
commentsLimited
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,13 @@ class ChatSettingsSidebar extends React.PureComponent {
|
||||||
to: '/messages/requests',
|
to: '/messages/requests',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Blocked Chats',
|
title: 'Blocked Chat Messengers',
|
||||||
to: '/messages/blocks',
|
to: '/messages/blocks',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Muted Conversations',
|
||||||
|
to: '/messages/muted_conversations',
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</ResponsiveClassesComponent>
|
</ResponsiveClassesComponent>
|
||||||
|
|
|
@ -221,6 +221,7 @@ class SwitchingArea extends React.PureComponent {
|
||||||
<WrappedRoute path='/messages/settings' exact page={MessagesPage} component={MessagesSettings} content={children} componentParams={{ isSettings: true }} />
|
<WrappedRoute path='/messages/settings' exact page={MessagesPage} component={MessagesSettings} content={children} componentParams={{ isSettings: true }} />
|
||||||
<WrappedRoute path='/messages/requests' exact page={MessagesPage} component={ChatConversationRequests} content={children} componentParams={{ isSettings: true, source: 'requested' }} />
|
<WrappedRoute path='/messages/requests' exact page={MessagesPage} component={ChatConversationRequests} content={children} componentParams={{ isSettings: true, source: 'requested' }} />
|
||||||
<WrappedRoute path='/messages/blocks' exact page={MessagesPage} component={ChatConversationBlockedAccounts} content={children} componentParams={{ isSettings: true }} />
|
<WrappedRoute path='/messages/blocks' exact page={MessagesPage} component={ChatConversationBlockedAccounts} content={children} componentParams={{ isSettings: true }} />
|
||||||
|
<WrappedRoute path='/messages/muted_conversations' exact page={MessagesPage} component={ChatConversationBlockedAccounts} content={children} componentParams={{ isSettings: true }} />
|
||||||
<WrappedRoute path='/messages/:chatConversationId' exact page={MessagesPage} component={Messages} content={children} componentParams={{ source: 'approved' }} />
|
<WrappedRoute path='/messages/:chatConversationId' exact page={MessagesPage} component={Messages} content={children} componentParams={{ source: 'approved' }} />
|
||||||
|
|
||||||
<WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Feed' }} />
|
<WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Feed' }} />
|
||||||
|
|
|
@ -7,6 +7,7 @@ import compareId from '../utils/compare_id'
|
||||||
import {
|
import {
|
||||||
CHAT_MESSAGES_SEND_SUCCESS,
|
CHAT_MESSAGES_SEND_SUCCESS,
|
||||||
CHAT_MESSAGES_DELETE_REQUEST,
|
CHAT_MESSAGES_DELETE_REQUEST,
|
||||||
|
CHAT_MESSAGES_PURGE_SUCCESS,
|
||||||
} from '../actions/chat_messages'
|
} from '../actions/chat_messages'
|
||||||
import {
|
import {
|
||||||
CHAT_CONVERSATION_MESSAGES_EXPAND_REQUEST,
|
CHAT_CONVERSATION_MESSAGES_EXPAND_REQUEST,
|
||||||
|
@ -101,6 +102,9 @@ export default function chat_conversation_messages(state = initialState, action)
|
||||||
case CHAT_MESSAGES_DELETE_REQUEST:
|
case CHAT_MESSAGES_DELETE_REQUEST:
|
||||||
// : todo :
|
// : todo :
|
||||||
return state
|
return state
|
||||||
|
case CHAT_MESSAGES_PURGE_SUCCESS:
|
||||||
|
// : todo :
|
||||||
|
return state
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
CHAT_CONVERSATIONS_REQUESTED_EXPAND_SUCCESS,
|
CHAT_CONVERSATIONS_REQUESTED_EXPAND_SUCCESS,
|
||||||
CHAT_CONVERSATION_REQUEST_APPROVE_SUCCESS,
|
CHAT_CONVERSATION_REQUEST_APPROVE_SUCCESS,
|
||||||
CHAT_CONVERSATION_MARK_READ_SUCCESS,
|
CHAT_CONVERSATION_MARK_READ_SUCCESS,
|
||||||
|
SET_CHAT_CONVERSATION_EXPIRATION_SUCCESS,
|
||||||
} from '../actions/chat_conversations'
|
} from '../actions/chat_conversations'
|
||||||
|
|
||||||
const initialState = ImmutableMap()
|
const initialState = ImmutableMap()
|
||||||
|
@ -41,6 +42,7 @@ const importChatConversations = (state, chatConversations) => {
|
||||||
export default function chat_conversations(state = initialState, action) {
|
export default function chat_conversations(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case CHAT_CONVERSATION_REQUEST_APPROVE_SUCCESS:
|
case CHAT_CONVERSATION_REQUEST_APPROVE_SUCCESS:
|
||||||
|
case SET_CHAT_CONVERSATION_EXPIRATION_SUCCESS:
|
||||||
return importChatConversation(state, action.chatConversation)
|
return importChatConversation(state, action.chatConversation)
|
||||||
case CHAT_CONVERSATIONS_APPROVED_FETCH_SUCCESS:
|
case CHAT_CONVERSATIONS_APPROVED_FETCH_SUCCESS:
|
||||||
case CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS:
|
case CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
RELATIONSHIPS_FETCH_SUCCESS,
|
RELATIONSHIPS_FETCH_SUCCESS,
|
||||||
} from '../actions/accounts'
|
} from '../actions/accounts'
|
||||||
import {
|
import {
|
||||||
|
FETCH_CHAT_MESSENGER_BLOCKING_RELATIONSHIPS_SUCCESS,
|
||||||
BLOCK_CHAT_MESSAGER_SUCCESS,
|
BLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
} from '../actions/chat_conversation_accounts'
|
} from '../actions/chat_conversation_accounts'
|
||||||
|
@ -39,14 +40,21 @@ export default function relationships(state = initialState, action) {
|
||||||
return state.setIn([action.id, 'following'], false)
|
return state.setIn([action.id, 'following'], false)
|
||||||
case ACCOUNT_UNFOLLOW_FAIL:
|
case ACCOUNT_UNFOLLOW_FAIL:
|
||||||
return state.setIn([action.id, 'following'], true)
|
return state.setIn([action.id, 'following'], true)
|
||||||
|
|
||||||
|
case BLOCK_CHAT_MESSAGER_SUCCESS:
|
||||||
|
case FETCH_CHAT_MESSENGER_BLOCKING_RELATIONSHIPS_SUCCESS:
|
||||||
|
case UNBLOCK_CHAT_MESSAGER_SUCCESS:
|
||||||
|
return state.withMutations((map) => {
|
||||||
|
if (action.data.chat_blocking !== undefined) map.setIn([data.target_id, 'chat_blocking'], action.data.chat_blocking)
|
||||||
|
if (action.data.chat_blocked_by !== undefined) map.setIn([data.target_id, 'chat_blocked_by'], action.data.chat_blocked_by)
|
||||||
|
})
|
||||||
|
|
||||||
case ACCOUNT_FOLLOW_SUCCESS:
|
case ACCOUNT_FOLLOW_SUCCESS:
|
||||||
case ACCOUNT_UNFOLLOW_SUCCESS:
|
case ACCOUNT_UNFOLLOW_SUCCESS:
|
||||||
case ACCOUNT_BLOCK_SUCCESS:
|
case ACCOUNT_BLOCK_SUCCESS:
|
||||||
case ACCOUNT_UNBLOCK_SUCCESS:
|
case ACCOUNT_UNBLOCK_SUCCESS:
|
||||||
case ACCOUNT_MUTE_SUCCESS:
|
case ACCOUNT_MUTE_SUCCESS:
|
||||||
case ACCOUNT_UNMUTE_SUCCESS:
|
case ACCOUNT_UNMUTE_SUCCESS:
|
||||||
case BLOCK_CHAT_MESSAGER_SUCCESS:
|
|
||||||
case UNBLOCK_CHAT_MESSAGER_SUCCESS:
|
|
||||||
return normalizeRelationship(state, action.relationship)
|
return normalizeRelationship(state, action.relationship)
|
||||||
case RELATIONSHIPS_FETCH_SUCCESS:
|
case RELATIONSHIPS_FETCH_SUCCESS:
|
||||||
return normalizeRelationships(state, action.relationships)
|
return normalizeRelationships(state, action.relationships)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import punycode from 'punycode'
|
||||||
const IDNA_PREFIX = 'xn--'
|
const IDNA_PREFIX = 'xn--'
|
||||||
|
|
||||||
export const decodeIDNA = (domain) => {
|
export const decodeIDNA = (domain) => {
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ChatConversationAccount < ApplicationRecord
|
||||||
EXPIRATION_POLICY_MAP = {
|
EXPIRATION_POLICY_MAP = {
|
||||||
none: nil,
|
none: nil,
|
||||||
five_minutes: '1',
|
five_minutes: '1',
|
||||||
sixty_minutes: '2',
|
one_hour: '2',
|
||||||
six_hours: '3',
|
six_hours: '3',
|
||||||
one_day: '4',
|
one_day: '4',
|
||||||
three_days: '5',
|
three_days: '5',
|
||||||
|
|
|
@ -23,6 +23,7 @@ class ChatMessage < ApplicationRecord
|
||||||
|
|
||||||
default_scope { recent }
|
default_scope { recent }
|
||||||
|
|
||||||
|
scope :expired, -> { where.not(expires_at: nil).where('expires_at < ?', Time.now.utc) }
|
||||||
scope :recent, -> { reorder(created_at: :desc) }
|
scope :recent, -> { reorder(created_at: :desc) }
|
||||||
|
|
||||||
def emojis
|
def emojis
|
||||||
|
|
|
@ -24,6 +24,14 @@ module AccountInteractions
|
||||||
follow_mapping(Block.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
|
follow_mapping(Block.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def chat_blocking_map(target_account_ids, account_id)
|
||||||
|
follow_mapping(ChatBlock.where(target_account_id: target_account_ids, account_id: account_id), :target_account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def chat_blocked_by_map(target_account_ids, account_id)
|
||||||
|
follow_mapping(ChatBlock.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
|
||||||
|
end
|
||||||
|
|
||||||
def muting_map(target_account_ids, account_id)
|
def muting_map(target_account_ids, account_id)
|
||||||
Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping|
|
Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping|
|
||||||
mapping[mute.target_account_id] = {
|
mapping[mute.target_account_id] = {
|
||||||
|
@ -97,6 +105,10 @@ module AccountInteractions
|
||||||
.find_or_create_by!(target_account: other_account)
|
.find_or_create_by!(target_account: other_account)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def chat_block!(other_account)
|
||||||
|
chat_block_relationships.find_or_create_by!(target_account: other_account)
|
||||||
|
end
|
||||||
|
|
||||||
def mute!(other_account, notifications: nil)
|
def mute!(other_account, notifications: nil)
|
||||||
notifications = true if notifications.nil?
|
notifications = true if notifications.nil?
|
||||||
mute = mute_relationships.create_with(hide_notifications: notifications).find_or_create_by!(target_account: other_account)
|
mute = mute_relationships.create_with(hide_notifications: notifications).find_or_create_by!(target_account: other_account)
|
||||||
|
@ -120,6 +132,11 @@ module AccountInteractions
|
||||||
block&.destroy
|
block&.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def chat_unblock!(other_account)
|
||||||
|
block = chat_block_relationships.find_by(target_account: other_account)
|
||||||
|
block&.destroy
|
||||||
|
end
|
||||||
|
|
||||||
def unmute!(other_account)
|
def unmute!(other_account)
|
||||||
mute = mute_relationships.find_by(target_account: other_account)
|
mute = mute_relationships.find_by(target_account: other_account)
|
||||||
mute&.destroy
|
mute&.destroy
|
||||||
|
@ -133,6 +150,14 @@ module AccountInteractions
|
||||||
block_relationships.where(target_account: other_account).exists?
|
block_relationships.where(target_account: other_account).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def chat_blocking?(other_account)
|
||||||
|
chat_block_relationships.where(target_account: other_account).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def chat_blocked_by(target_account_id, account_id)
|
||||||
|
ChatBlock.where(account_id: target_account_id, target_account_id: account_id).exists?
|
||||||
|
end
|
||||||
|
|
||||||
def muting?(other_account)
|
def muting?(other_account)
|
||||||
mute_relationships.where(target_account: other_account).exists?
|
mute_relationships.where(target_account: other_account).exists?
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,8 @@ class AccountRelationshipsPresenter
|
||||||
@followed_by = cached[:followed_by].merge(Account.followed_by_map(@uncached_account_ids, @current_account_id))
|
@followed_by = cached[:followed_by].merge(Account.followed_by_map(@uncached_account_ids, @current_account_id))
|
||||||
@blocking = cached[:blocking].merge(Account.blocking_map(@uncached_account_ids, @current_account_id))
|
@blocking = cached[:blocking].merge(Account.blocking_map(@uncached_account_ids, @current_account_id))
|
||||||
@blocked_by = cached[:blocked_by].merge(Account.blocked_by_map(@uncached_account_ids, @current_account_id))
|
@blocked_by = cached[:blocked_by].merge(Account.blocked_by_map(@uncached_account_ids, @current_account_id))
|
||||||
|
# @chat_blocking = cached[:chat_blocking].merge(Account.chat_blocking_map(@uncached_account_ids, @current_account_id))
|
||||||
|
# @chat_blocked_by = cached[:chat_blocked_by].merge(Account.chat_blocked_by_map(@uncached_account_ids, @current_account_id))
|
||||||
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
|
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
|
||||||
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
|
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
|
||||||
|
|
||||||
|
@ -21,15 +23,14 @@ class AccountRelationshipsPresenter
|
||||||
@followed_by.merge!(options[:followed_by_map] || {})
|
@followed_by.merge!(options[:followed_by_map] || {})
|
||||||
@blocking.merge!(options[:blocking_map] || {})
|
@blocking.merge!(options[:blocking_map] || {})
|
||||||
@blocked_by.merge!(options[:blocked_by_map] || {})
|
@blocked_by.merge!(options[:blocked_by_map] || {})
|
||||||
|
# @chat_blocking.merge!(options[:chat_blocking_map] || {})
|
||||||
|
# @chat_blocked_by.merge!(options[:chat_blocked_by_map] || {})
|
||||||
@muting.merge!(options[:muting_map] || {})
|
@muting.merge!(options[:muting_map] || {})
|
||||||
@requested.merge!(options[:requested_map] || {})
|
@requested.merge!(options[:requested_map] || {})
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# : todo :
|
|
||||||
# chat muting, chat blocking
|
|
||||||
|
|
||||||
def cached
|
def cached
|
||||||
return @cached if defined?(@cached)
|
return @cached if defined?(@cached)
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ class AccountRelationshipsPresenter
|
||||||
followed_by: {},
|
followed_by: {},
|
||||||
blocking: {},
|
blocking: {},
|
||||||
blocked_by: {},
|
blocked_by: {},
|
||||||
|
# chat_blocking: {},
|
||||||
|
# chat_blocked_by: {},
|
||||||
muting: {},
|
muting: {},
|
||||||
requested: {},
|
requested: {},
|
||||||
}
|
}
|
||||||
|
@ -64,6 +67,8 @@ class AccountRelationshipsPresenter
|
||||||
followed_by: { account_id => followed_by[account_id] },
|
followed_by: { account_id => followed_by[account_id] },
|
||||||
blocking: { account_id => blocking[account_id] },
|
blocking: { account_id => blocking[account_id] },
|
||||||
blocked_by: { account_id => blocked_by[account_id] },
|
blocked_by: { account_id => blocked_by[account_id] },
|
||||||
|
# chat_blocking: { account_id => chat_blocking[account_id] },
|
||||||
|
# chat_blocked_by: { account_id => chat_blocked_by[account_id] },
|
||||||
muting: { account_id => muting[account_id] },
|
muting: { account_id => muting[account_id] },
|
||||||
requested: { account_id => requested[account_id] },
|
requested: { account_id => requested[account_id] },
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,4 +24,23 @@ class REST::ChatConversationAccountSerializer < ActiveModel::Serializer
|
||||||
object.unread_count > 0
|
object.unread_count > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def chat_message_expiration_policy
|
||||||
|
case object.chat_message_expiration_policy
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:five_minutes]
|
||||||
|
return 'five_minutes'
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_hour]
|
||||||
|
return 'one_hour'
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:six_hours]
|
||||||
|
return 'six_hours'
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_day]
|
||||||
|
return 'one_day'
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:three_days]
|
||||||
|
return 'three_days'
|
||||||
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_week]
|
||||||
|
return 'one_week'
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::ChatMessengerBlockedSerializer < ActiveModel::Serializer
|
||||||
|
attributes :target_id, :chat_blocking, :chat_blocked_by
|
||||||
|
|
||||||
|
def target_id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def chat_blocking
|
||||||
|
instance_options[:chat_blocking] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def chat_blocked_by
|
||||||
|
instance_options[:chat_blocked_by] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,12 +1,23 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DeleteChatMessageService < BaseService
|
class DeleteChatMessageService < BaseService
|
||||||
def call(account, chatMessageId)
|
include Redisable
|
||||||
@chat = ChatMessage.where(from_account: account).find(chatMessageId)
|
|
||||||
|
|
||||||
# : todo :
|
def call(chat_message)
|
||||||
# make sure last_chat_message_id in chat_account_conversation gets set to last
|
return if chat_message.nil?
|
||||||
|
|
||||||
@chat.destroy!
|
@chat_message = chat_message
|
||||||
|
|
||||||
|
RedisLock.acquire(lock_options) do |lock|
|
||||||
|
if lock.acquired?
|
||||||
|
@chat_message.destroy!
|
||||||
|
else
|
||||||
|
raise GabSocial::RaceConditionError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def lock_options
|
||||||
|
{ redis: Redis.current, key: "distribute_chat_message:#{@chat_message.id}" }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,14 +49,13 @@ class PostChatMessageService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def postprocess_chat!
|
def postprocess_chat!
|
||||||
@chat_conversation_recipients_accounts = ChatConversationAccount.where(chat_conversation: @chat_conversation)
|
|
||||||
@chat_conversation_recipients_accounts.each do |recipient|
|
@chat_conversation_recipients_accounts.each do |recipient|
|
||||||
recipient.last_chat_message_id = @chat.id
|
recipient.last_chat_message_id = @chat.id
|
||||||
recipient.is_hidden = false # : todo : reset to show unless blocked
|
|
||||||
|
|
||||||
# Get not mine
|
# Get not mine
|
||||||
if @account_conversation.id != recipient.id
|
if @account_conversation.id != recipient.id
|
||||||
recipient.unread_count = recipient.unread_count + 1
|
recipient.unread_count = recipient.unread_count + 1
|
||||||
|
recipient.is_hidden = false
|
||||||
|
|
||||||
# check if muting
|
# check if muting
|
||||||
unless recipient.is_muted
|
unless recipient.is_muted
|
||||||
|
@ -72,11 +71,22 @@ class PostChatMessageService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_chat_conversation_recipients!
|
def set_chat_conversation_recipients!
|
||||||
# : todo :
|
|
||||||
# check if chat blocked
|
|
||||||
# check if normal blocked
|
|
||||||
|
|
||||||
@account_conversation = ChatConversationAccount.where(account: @account, chat_conversation: @chat_conversation).first
|
@account_conversation = ChatConversationAccount.where(account: @account, chat_conversation: @chat_conversation).first
|
||||||
|
@chat_conversation_recipients_accounts = ChatConversationAccount.where(chat_conversation: @chat_conversation)
|
||||||
|
|
||||||
|
# if 1-to-1 chat, check for blocking and dont allow message to send if blocking
|
||||||
|
# if 1-to-many let chat go through but keep is_hidden
|
||||||
|
@chat_conversation_recipients_accounts.each do |recipient|
|
||||||
|
# : todo :
|
||||||
|
# check if chat blocked
|
||||||
|
# check if normal blocked
|
||||||
|
|
||||||
|
if recipient.account.blocking?(@account) || recipient.account.chat_blocking?(@account)
|
||||||
|
raise GabSocial::NotPermittedError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
raise ActiveRecord::RecordInvalid
|
raise ActiveRecord::RecordInvalid
|
||||||
end
|
end
|
||||||
|
@ -84,21 +94,23 @@ class PostChatMessageService < BaseService
|
||||||
def set_message_expiration_date!
|
def set_message_expiration_date!
|
||||||
@expires_at = nil
|
@expires_at = nil
|
||||||
|
|
||||||
|
unless @account.is_pro
|
||||||
|
return @expires_at
|
||||||
|
end
|
||||||
|
|
||||||
case @account_conversation.chat_message_expiration_policy
|
case @account_conversation.chat_message_expiration_policy
|
||||||
when :five_minutes
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:five_minutes]
|
||||||
@expires_at = 5.minutes
|
@expires_at = Time.now + 5.minutes
|
||||||
when :sixty_minutes
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_hour]
|
||||||
@expires_at = 1.hour
|
@expires_at = Time.now + 1.hour
|
||||||
when :six_hours
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:six_hours]
|
||||||
@expires_at = 6.hours
|
@expires_at = Time.now + 6.hours
|
||||||
when :one_day
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_day]
|
||||||
@expires_at = 1.day
|
@expires_at = Time.now + 1.day
|
||||||
when :three_days
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:three_days]
|
||||||
@expires_at = 3.days
|
@expires_at = Time.now + 3.days
|
||||||
when :one_week
|
when ChatConversationAccount::EXPIRATION_POLICY_MAP[:one_week]
|
||||||
@expires_at = 1.week
|
@expires_at = Time.now + 1.week
|
||||||
else
|
|
||||||
@expires_at = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@expires_at
|
@expires_at
|
||||||
|
|
|
@ -59,7 +59,23 @@ class PostStatusService < BaseService
|
||||||
@visibility = @options[:visibility] || @account.user&.setting_default_privacy
|
@visibility = @options[:visibility] || @account.user&.setting_default_privacy
|
||||||
@visibility = :unlisted if @visibility == :public && @account.silenced?
|
@visibility = :unlisted if @visibility == :public && @account.silenced?
|
||||||
@visibility = :private_group if @isPrivateGroup
|
@visibility = :private_group if @isPrivateGroup
|
||||||
@expires_at = @options[:expires_at]&.to_datetime if @account.is_pro
|
@expires_at = nil
|
||||||
|
if @account.is_pro
|
||||||
|
case @options[:expires_at]
|
||||||
|
when 'five_minutes'
|
||||||
|
@expires_at = Time.now + 5.minutes
|
||||||
|
when 'one_hour'
|
||||||
|
@expires_at = Time.now + 1.hour
|
||||||
|
when 'six_hours'
|
||||||
|
@expires_at = Time.now + 6.hours
|
||||||
|
when 'one_day'
|
||||||
|
@expires_at = Time.now + 1.day
|
||||||
|
when 'three_days'
|
||||||
|
@expires_at = Time.now + 3.days
|
||||||
|
when 'one_week'
|
||||||
|
@expires_at = Time.now + 1.week
|
||||||
|
end
|
||||||
|
end
|
||||||
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
||||||
@scheduled_at = nil if scheduled_in_the_past?
|
@scheduled_at = nil if scheduled_in_the_past?
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DeleteChatMessageWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
sidekiq_options unique: :until_executed
|
||||||
|
|
||||||
|
def perform(chat_message_id)
|
||||||
|
return if chat_message_id.nil?
|
||||||
|
DeleteChatMessageService.new.call(ChatMessage.find(chat_message_id))
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Scheduler::ExpiringChatMessagesScheduler
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
def perform
|
||||||
|
expired_chat_messages.find_each do |chat_message|
|
||||||
|
DeleteChatMessageWorker.perform_async(chat_message.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def expired_chat_messages
|
||||||
|
ChatMessage.unscoped.expired
|
||||||
|
end
|
||||||
|
end
|
|
@ -226,17 +226,17 @@ Rails.application.routes.draw do
|
||||||
resource :explore, only: :show, controller: :explore
|
resource :explore, only: :show, controller: :explore
|
||||||
end
|
end
|
||||||
|
|
||||||
resource :chat_conversation_accounts, only: :show do
|
namespace :chat_conversation_accounts do
|
||||||
resource :blocked_chat_accounts, only: :show, controller: 'chat_conversation_accounts/blocked_chat_accounts'
|
resource :blocked_chat_accounts, only: :show, controller: 'chat_conversation_accounts/blocked_chat_accounts'
|
||||||
|
end
|
||||||
|
|
||||||
|
resources :chat_conversation_accounts, only: :show do
|
||||||
member do
|
member do
|
||||||
get :is_messenger_blocked
|
post :messenger_block_relationships
|
||||||
get :is_messenger_muted
|
|
||||||
post :block_messenger
|
post :block_messenger
|
||||||
post :unblock_messenger
|
post :unblock_messenger
|
||||||
post :mute_chat_conversation
|
post :mute_chat_conversation
|
||||||
post :unmute_chat_conversation
|
post :unmute_chat_conversation
|
||||||
post :set_expiration_policy
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ Rails.application.routes.draw do
|
||||||
post :mark_chat_conversation_approved
|
post :mark_chat_conversation_approved
|
||||||
post :mark_chat_conversation_read
|
post :mark_chat_conversation_read
|
||||||
post :mark_chat_conversation_hidden
|
post :mark_chat_conversation_hidden
|
||||||
|
post :set_expiration_policy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
scheduled_statuses_scheduler:
|
scheduled_statuses_scheduler:
|
||||||
every: '1m'
|
every: '1m'
|
||||||
class: Scheduler::ScheduledStatusesScheduler
|
class: Scheduler::ScheduledStatusesScheduler
|
||||||
|
expiring_chat_messages_scheduler:
|
||||||
|
every: '1m'
|
||||||
|
class: Scheduler::ExpiringChatMessagesScheduler
|
||||||
media_cleanup_scheduler:
|
media_cleanup_scheduler:
|
||||||
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
|
||||||
class: Scheduler::MediaCleanupScheduler
|
class: Scheduler::MediaCleanupScheduler
|
||||||
|
|
Loading…
Reference in New Issue