Progress
This commit is contained in:
parent
d1ff39bb81
commit
8f94ffad9c
|
@ -1,60 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::ChatConversationAccounts::MutedChatAccountsController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :follow, :'read:mutes' }
|
|
||||||
before_action :require_user!
|
|
||||||
after_action :insert_pagination_headers
|
|
||||||
|
|
||||||
def show
|
|
||||||
@accounts = load_accounts
|
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def load_accounts
|
|
||||||
paginated_mutes.map(&:target_account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def paginated_mutes
|
|
||||||
@paginated_mutes ||= ChatMute.eager_load(target_account: :account_stat)
|
|
||||||
.where(account: current_account)
|
|
||||||
.paginate_by_max_id(
|
|
||||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
|
||||||
params[:max_id],
|
|
||||||
params[:since_id]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def insert_pagination_headers
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
if records_continue?
|
|
||||||
api_v1_chat_conversation_accounts_muted_chat_accounts_url pagination_params(max_id: pagination_max_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
unless paginated_mutes.empty?
|
|
||||||
api_v1_chat_conversation_accounts_muted_chat_accounts_url pagination_params(since_id: pagination_since_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_max_id
|
|
||||||
paginated_mutes.last.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_since_id
|
|
||||||
paginated_mutes.first.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def records_continue?
|
|
||||||
paginated_mutes.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.slice(:limit).permit(:limit).merge(core_params)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -7,37 +7,31 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def is_messenger_blocked
|
|
||||||
#
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_messenger_muted
|
|
||||||
#
|
|
||||||
end
|
|
||||||
|
|
||||||
def block_messenger
|
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_messenger
|
|
||||||
MuteMessengerService.new.call(current_user.account, @account)
|
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
|
||||||
end
|
|
||||||
|
|
||||||
def unblock_messenger
|
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_messenger
|
def mute_chat_conversation
|
||||||
UnmuteMessegerService.new.call(current_user.account, @account)
|
@chat_conversation_account.is_muted = true
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
@chat_conversation_account.save!
|
||||||
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def unmute_chat_conversation
|
||||||
|
@chat_conversation_account.is_muted = false
|
||||||
|
@chat_conversation_account.save!
|
||||||
|
render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_expiration_policy
|
def set_expiration_policy
|
||||||
if current_user.account.is_pro
|
if current_user.account.is_pro
|
||||||
#
|
# : todo :
|
||||||
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
|
||||||
|
@ -50,6 +44,14 @@ class Api::V1::ChatConversationAccountsController < Api::BaseController
|
||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_chat_conversation
|
||||||
|
@chat_conversation = ChatConversation.find(params[:id])
|
||||||
|
@chat_conversation_account = ChatConversationAccount.where(
|
||||||
|
account: current_account,
|
||||||
|
chat_conversation: @chat_conversation
|
||||||
|
).first
|
||||||
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
gone if @account.suspended?
|
gone if @account.suspended?
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,8 @@ class Api::Web::SettingsController < Api::Web::BaseController
|
||||||
setting.data = params[:data]
|
setting.data = params[:data]
|
||||||
setting.save!
|
setting.save!
|
||||||
|
|
||||||
|
# todo validate all data objects
|
||||||
|
|
||||||
render_empty_success
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
before_action :set_cache_headers, only: [:edit, :update]
|
before_action :set_cache_headers, only: [:edit, :update]
|
||||||
|
|
||||||
def new
|
def new
|
||||||
super(&:build_invite_request)
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
|
@ -24,79 +24,92 @@ export const BOOKMARK_COLLECTIONS_REMOVE_REQUEST = 'BOOKMARK_COLLECTIONS_REMOVE_
|
||||||
export const BOOKMARK_COLLECTIONS_REMOVE_SUCCESS = 'BOOKMARK_COLLECTIONS_REMOVE_SUCCESS'
|
export const BOOKMARK_COLLECTIONS_REMOVE_SUCCESS = 'BOOKMARK_COLLECTIONS_REMOVE_SUCCESS'
|
||||||
export const BOOKMARK_COLLECTIONS_REMOVE_FAIL = 'BOOKMARK_COLLECTIONS_REMOVE_FAIL'
|
export const BOOKMARK_COLLECTIONS_REMOVE_FAIL = 'BOOKMARK_COLLECTIONS_REMOVE_FAIL'
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_FAIL = 'UPDATE_BOOKMARK_COLLECTION_FAIL'
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_REQUEST = 'UPDATE_BOOKMARK_COLLECTION_REQUEST'
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_SUCCESS = 'UPDATE_BOOKMARK_COLLECTION_SUCCESS'
|
||||||
|
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_STATUS_FAIL = 'UPDATE_BOOKMARK_COLLECTION_STATUS_FAIL'
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_STATUS_REQUEST = 'UPDATE_BOOKMARK_COLLECTION_STATUS_REQUEST'
|
||||||
|
export const UPDATE_BOOKMARK_COLLECTION_STATUS_SUCCESS = 'UPDATE_BOOKMARK_COLLECTION_STATUS_SUCCESS'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const fetchBookmarkedStatuses = () => (dispatch, getState) => {
|
export const fetchBookmarkedStatuses = (bookmarkCollectionId) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me) return
|
||||||
|
|
||||||
if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
|
if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(fetchBookmarkedStatusesRequest())
|
dispatch(fetchBookmarkedStatusesRequest(bookmarkCollectionId))
|
||||||
|
|
||||||
api(getState).get('/api/v1/bookmarks').then((response) => {
|
api(getState).get('/api/v1/bookmarks').then((response) => {
|
||||||
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||||
dispatch(importFetchedStatuses(response.data))
|
dispatch(importFetchedStatuses(response.data))
|
||||||
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
|
dispatch(fetchBookmarkedStatusesSuccess(response.data, bookmarkCollectionId, next ? next.uri : null))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(fetchBookmarkedStatusesFail(error))
|
dispatch(fetchBookmarkedStatusesFail(bookmarkCollectionId, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchBookmarkedStatusesRequest = () => ({
|
const fetchBookmarkedStatusesRequest = (bookmarkCollectionId) => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
|
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
|
const fetchBookmarkedStatusesSuccess = (statuses, bookmarkCollectionId, next) => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
|
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
|
||||||
|
bookmarkCollectionId,
|
||||||
statuses,
|
statuses,
|
||||||
next,
|
next,
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchBookmarkedStatusesFail = (error) => ({
|
const fetchBookmarkedStatusesFail = (bookmarkCollectionId, error) => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_FAIL,
|
type: BOOKMARKED_STATUSES_FETCH_FAIL,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
|
bookmarkCollectionId,
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const expandBookmarkedStatuses = () => (dispatch, getState) => {
|
export const expandBookmarkedStatuses = (bookmarkCollectionId) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me) return
|
||||||
|
|
||||||
const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null)
|
const url = getState().getIn(['status_lists', 'bookmarks', bookmarkCollectionId, 'next'], null)
|
||||||
|
|
||||||
if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
|
if (url === null || getState().getIn(['status_lists', 'bookmarks', bookmarkCollectionId, 'isLoading'])) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(expandBookmarkedStatusesRequest())
|
dispatch(expandBookmarkedStatusesRequest(bookmarkCollectionId))
|
||||||
|
|
||||||
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')
|
||||||
dispatch(importFetchedStatuses(response.data))
|
dispatch(importFetchedStatuses(response.data))
|
||||||
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
|
dispatch(expandBookmarkedStatusesSuccess(response.data, bookmarkCollectionId, next ? next.uri : null))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(expandBookmarkedStatusesFail(error))
|
dispatch(expandBookmarkedStatusesFail(bookmarkCollectionId, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandBookmarkedStatusesRequest = () => ({
|
const expandBookmarkedStatusesRequest = (bookmarkCollectionId) => ({
|
||||||
type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
|
type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
|
||||||
})
|
})
|
||||||
|
|
||||||
const expandBookmarkedStatusesSuccess = (statuses, next) => ({
|
const expandBookmarkedStatusesSuccess = (statuses, bookmarkCollectionId, next) => ({
|
||||||
type: BOOKMARKED_STATUSES_EXPAND_SUCCESS,
|
type: BOOKMARKED_STATUSES_EXPAND_SUCCESS,
|
||||||
statuses,
|
statuses,
|
||||||
next,
|
next,
|
||||||
})
|
})
|
||||||
|
|
||||||
const expandBookmarkedStatusesFail = (error) => ({
|
const expandBookmarkedStatusesFail = (bookmarkCollectionId, error) => ({
|
||||||
type: BOOKMARKED_STATUSES_EXPAND_FAIL,
|
type: BOOKMARKED_STATUSES_EXPAND_FAIL,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
|
bookmarkCollectionId,
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -191,3 +204,63 @@ const removeBookmarkCollectionFail = (error) => ({
|
||||||
showToast: true,
|
showToast: true,
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const updateBookmarkCollection = (bookmarkCollectionId, title) => (dispatch, getState) => {
|
||||||
|
if (!me || !statusId) return
|
||||||
|
|
||||||
|
dispatch(updateBookmarkCollectionRequest())
|
||||||
|
|
||||||
|
api(getState).post('/api/v1/bookmark_collections', { title }).then((response) => {
|
||||||
|
dispatch(updateBookmarkCollectionSuccess(response.data))
|
||||||
|
}).catch((error) => {
|
||||||
|
dispatch(updateBookmarkCollectionFail(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateBookmarkCollectionRequest = () => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_REQUEST,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateBookmarkCollectionSuccess = (bookmarkCollection) => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_SUCCESS,
|
||||||
|
bookmarkCollection,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateBookmarkCollectionFail = (error) => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_FAIL,
|
||||||
|
showToast: true,
|
||||||
|
error,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const updateBookmarkCollectionStatus = (statusId, bookmarkCollectionId) => (dispatch, getState) => {
|
||||||
|
if (!me || !statusId) return
|
||||||
|
|
||||||
|
dispatch(updateBookmarkCollectionStatusRequest())
|
||||||
|
|
||||||
|
api(getState).post('/api/v1/bookmark_collections', { title }).then((response) => {
|
||||||
|
dispatch(updateBookmarkCollectionStatusSuccess(response.data))
|
||||||
|
}).catch((error) => {
|
||||||
|
dispatch(updateBookmarkCollectionStatusFail(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateBookmarkCollectionStatusRequest = () => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_STATUS_REQUEST,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateBookmarkCollectionStatusSuccess = (bookmarkCollection) => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_STATUS_SUCCESS,
|
||||||
|
bookmarkCollection,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateBookmarkCollectionStatusFail = (error) => ({
|
||||||
|
type: UPDATE_BOOKMARK_COLLECTION_STATUS_FAIL,
|
||||||
|
showToast: true,
|
||||||
|
error,
|
||||||
|
})
|
||||||
|
|
|
@ -24,23 +24,13 @@ export const IS_CHAT_MESSENGER_BLOCKED_SUCCESS = 'IS_CHAT_MESSENGER_BLOCKED_SUCC
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
export const CHAT_MESSENGER_MUTES_FETCH_REQUEST = 'CHAT_MESSENGER_MUTES_FETCH_REQUEST'
|
export const MUTE_CHAT_CONVERSATION_REQUEST = 'MUTE_CHAT_CONVERSATION_REQUEST'
|
||||||
export const CHAT_MESSENGER_MUTES_FETCH_SUCCESS = 'CHAT_MESSENGER_MUTES_FETCH_SUCCESS'
|
export const MUTE_CHAT_CONVERSATION_SUCCESS = 'MUTE_CHAT_CONVERSATION_SUCCESS'
|
||||||
export const CHAT_MESSENGER_MUTES_FETCH_FAIL = 'CHAT_MESSENGER_MUTES_FETCH_FAIL'
|
export const MUTE_CHAT_CONVERSATION_FAIL = 'MUTE_CHAT_CONVERSATION_FAIL'
|
||||||
|
|
||||||
export const CHAT_MESSENGER_MUTES_EXPAND_REQUEST = 'CHAT_MESSENGER_MUTES_EXPAND_REQUEST'
|
export const UNMUTE_CHAT_CONVERSATION_REQUEST = 'UNMUTE_CHAT_CONVERSATION_REQUEST'
|
||||||
export const CHAT_MESSENGER_MUTES_EXPAND_SUCCESS = 'CHAT_MESSENGER_MUTES_EXPAND_SUCCESS'
|
export const UNMUTE_CHAT_CONVERSATION_SUCCESS = 'UNMUTE_CHAT_CONVERSATION_SUCCESS'
|
||||||
export const CHAT_MESSENGER_MUTES_EXPAND_FAIL = 'CHAT_MESSENGER_MUTES_EXPAND_FAIL'
|
export const UNMUTE_CHAT_CONVERSATION_FAIL = 'UNMUTE_CHAT_CONVERSATION_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'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -96,12 +86,12 @@ const unblockChatMessengerRequest = (accountId) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
const unblockChatMessengerSuccess = () => ({
|
const unblockChatMessengerSuccess = () => ({
|
||||||
type: UNBLOCK_CHAT_MESSAGER_REQUEST,
|
type: UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const unblockChatMessengerFail = (accountId, error) => ({
|
const unblockChatMessengerFail = (accountId, error) => ({
|
||||||
type: UNBLOCK_CHAT_MESSAGER_REQUEST,
|
type: UNBLOCK_CHAT_MESSAGER_FAIL,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
accountId,
|
accountId,
|
||||||
error,
|
error,
|
||||||
|
@ -195,147 +185,64 @@ export const expandChatMessengerBlocksFail = (error) => ({
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const muteChatMessenger = (accountId) => (dispatch, getState) => {
|
export const muteChatConversation = (chatConversationId) => (dispatch, getState) => {
|
||||||
if (!me || !accountId) return
|
if (!me || !chatConversationId) return
|
||||||
|
|
||||||
dispatch(muteChatMessengerRequest(accountId))
|
dispatch(muteChatConversationRequest(chatConversationId))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/mute_messenger`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/${chatConversationId}/mute_chat_conversation`).then((response) => {
|
||||||
dispatch(muteChatMessengerSuccess())
|
dispatch(muteChatConversationSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(muteChatMessengerFail(accountId, error))
|
dispatch(muteChatMessengerFail(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const muteChatMessengerRequest = (accountId) => ({
|
const muteChatConversationRequest = (accountId) => ({
|
||||||
type: MUTE_CHAT_MESSAGER_REQUEST,
|
type: MUTE_CHAT_CONVERSATION_REQUEST,
|
||||||
accountId,
|
accountId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const muteChatMessengerSuccess = () => ({
|
const muteChatConversationSuccess = (chatConversation) => ({
|
||||||
type: MUTE_CHAT_MESSAGER_SUCCESS,
|
type: MUTE_CHAT_CONVERSATION_SUCCESS,
|
||||||
|
chatConversation,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const muteChatMessengerFail = (accountId, error) => ({
|
const muteChatConversationFail = (error) => ({
|
||||||
type: MUTE_CHAT_MESSAGER_FAIL,
|
type: MUTE_CHAT_CONVERSATION_FAIL,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
accountId,
|
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const unmuteChatMessenger = (accountId) => (dispatch, getState) => {
|
export const unmuteChatConversation = (chatConversationId) => (dispatch, getState) => {
|
||||||
if (!me || !accountId) return
|
if (!me || !chatConversationId) return
|
||||||
|
|
||||||
dispatch(unmuteChatMessengerRequest(accountId))
|
dispatch(unmuteChatConversationRequest(chatConversationId))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/chat_conversation_accounts/${accountId}/unmute_messenger`).then((response) => {
|
api(getState).post(`/api/v1/chat_conversation_accounts/${chatConversationId}/unmute_chat_conversation`).then((response) => {
|
||||||
dispatch(unmuteChatMessengerSuccess())
|
dispatch(unmuteChatConversationSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unmuteChatMessengerFail(accountId, error))
|
dispatch(unmuteChatConversationFail(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const unmuteChatMessengerRequest = (accountId) => ({
|
const unmuteChatConversationRequest = (accountId) => ({
|
||||||
type: UNMUTE_CHAT_MESSAGER_REQUEST,
|
type: UNMUTE_CHAT_CONVERSATION_REQUEST,
|
||||||
accountId,
|
accountId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const unmuteChatMessengerSuccess = () => ({
|
const unmuteChatConversationSuccess = (chatConversation) => ({
|
||||||
type: UNMUTE_CHAT_MESSAGER_REQUEST,
|
type: UNMUTE_CHAT_CONVERSATION_SUCCESS,
|
||||||
|
chatConversation,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const unmuteChatMessengerFail = (accountId, error) => ({
|
const unmuteChatConversationFail = (accountId, error) => ({
|
||||||
type: UNMUTE_CHAT_MESSAGER_REQUEST,
|
type: UNMUTE_CHAT_CONVERSATION_FAIL,
|
||||||
showToast: true,
|
showToast: true,
|
||||||
accountId,
|
accountId,
|
||||||
error,
|
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ export const SET_CHAT_CONVERSATION_SELECTED = 'SET_CHAT_CONVERSATION_SELECTED'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const fetchChatConversationAccountSuggestions = (query) => throttle((dispatch, getState) => {
|
export const fetchChatConversationAccountSuggestions = (query) => throttle((dispatch, getState) => {
|
||||||
|
if (!query) return
|
||||||
|
|
||||||
api(getState).get('/api/v1/accounts/search', {
|
api(getState).get('/api/v1/accounts/search', {
|
||||||
params: {
|
params: {
|
||||||
q: query,
|
q: query,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { CX } from '../constants'
|
||||||
|
import Button from './button'
|
||||||
|
import Icon from './icon'
|
||||||
|
import Image from './image'
|
||||||
|
import Text from './text'
|
||||||
|
|
||||||
|
class Album extends React.PureComponent {
|
||||||
|
|
||||||
|
handleOnClick = (e) => {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { album } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
to={to}
|
||||||
|
href={href}
|
||||||
|
onClick={this.handleOnClick}
|
||||||
|
noClasses
|
||||||
|
>
|
||||||
|
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Album.propTypes = {
|
||||||
|
album: ImmutablePropTypes.map,
|
||||||
|
isAddable: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Album
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
import BookmarkCollectionCreate from '../../features/bookmark_collection_create'
|
||||||
|
|
||||||
|
class BookmarkCollectionCreateModal extends React.PureComponent {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { onClose } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalLayout
|
||||||
|
title='Create Bookmark Collection'
|
||||||
|
width={500}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<BookmarkCollectionCreate isModal />
|
||||||
|
</ModalLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BookmarkCollectionCreateModal.propTypes = {
|
||||||
|
onClose: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BookmarkCollectionCreateModal
|
|
@ -1,88 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
||||||
import { changeSetting, saveSettings } from '../../actions/settings'
|
|
||||||
import ModalLayout from './modal_layout'
|
|
||||||
import Button from '../button'
|
|
||||||
import SettingSwitch from '../setting_switch'
|
|
||||||
import Text from '../text'
|
|
||||||
|
|
||||||
class CommunityTimelineSettingsModal extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
handleSaveAndClose = () => {
|
|
||||||
this.props.onSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
intl,
|
|
||||||
settings,
|
|
||||||
onChange,
|
|
||||||
onClose,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalLayout
|
|
||||||
onClose={onClose}
|
|
||||||
width={320}
|
|
||||||
title={intl.formatMessage(messages.title)}
|
|
||||||
>
|
|
||||||
|
|
||||||
<div className={[_s.d, _s.pb10].join(' ')}>
|
|
||||||
<SettingSwitch
|
|
||||||
prefix='community_timeline'
|
|
||||||
settings={settings}
|
|
||||||
settingPath={['shows', 'onlyMedia']}
|
|
||||||
onChange={onChange}
|
|
||||||
label={intl.formatMessage(messages.onlyMedia)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
backgroundColor='brand'
|
|
||||||
color='white'
|
|
||||||
className={_s.jcCenter}
|
|
||||||
onClick={this.handleSaveAndClose}
|
|
||||||
>
|
|
||||||
<Text color='inherit' weight='bold' align='center'>
|
|
||||||
{intl.formatMessage(messages.saveAndClose)}
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
</ModalLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
title: { id: 'community_timeline_settings', defaultMessage: 'Community Feed Settings' },
|
|
||||||
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
|
|
||||||
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
settings: state.getIn(['settings', 'community']),
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { onClose }) => ({
|
|
||||||
onChange(key, checked) {
|
|
||||||
dispatch(changeSetting(['community', ...key], checked))
|
|
||||||
},
|
|
||||||
onSave() {
|
|
||||||
dispatch(saveSettings())
|
|
||||||
onClose()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
CommunityTimelineSettingsModal.propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
settings: ImmutablePropTypes.map.isRequired,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
onSave: PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(CommunityTimelineSettingsModal))
|
|
|
@ -1,36 +1,138 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { openModal } from '../../actions/modal'
|
import { openModal } from '../../actions/modal'
|
||||||
|
import { setDeckColumnAtIndex } from '../../actions/deck'
|
||||||
|
import { getOrderedLists, getListOfGroups } from '../../selectors'
|
||||||
|
import { fetchLists } from '../../actions/lists'
|
||||||
|
import { fetchGroupsByTab } from '../../actions/groups'
|
||||||
import { MODAL_DECK_COLUMN_ADD } from '../../constants'
|
import { MODAL_DECK_COLUMN_ADD } from '../../constants'
|
||||||
import Heading from '../heading'
|
import Heading from '../heading'
|
||||||
import Button from '../button'
|
import Button from '../button'
|
||||||
import Block from '../block'
|
import Block from '../block'
|
||||||
|
import Input from '../input'
|
||||||
|
import List from '../list'
|
||||||
|
|
||||||
class DeckColumnAddOptionsModal extends React.PureComponent {
|
class DeckColumnAddOptionsModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
selectedItem: null,
|
hashtagValue: '',
|
||||||
|
usernameValue: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
switch (this.props.column) {
|
||||||
|
case 'list':
|
||||||
|
this.props.onFetchLists()
|
||||||
|
break
|
||||||
|
case 'group':
|
||||||
|
this.props.onFetchMemberGroups()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickClose = () => {
|
onClickClose = () => {
|
||||||
this.props.onClose()
|
this.props.onClose()
|
||||||
this.props.dispatch(openModal(MODAL_DECK_COLUMN_ADD))
|
this.props.onOpenDeckColumnAddModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAdd = (id) => {
|
||||||
|
this.props.onSetDeckColumn(id)
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddHashtag = () => {
|
||||||
|
this.handleAdd(`hashtag.${this.state.hashtagValue}`)
|
||||||
|
this.setState({ hashtagValue: '' })
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeHashtagValue = (hashtagValue) => {
|
||||||
|
this.setState({ hashtagValue })
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeUsernameValue = (usernameValue) => {
|
||||||
|
this.setState({ usernameValue })
|
||||||
|
}
|
||||||
|
|
||||||
|
getContentForColumn = () => {
|
||||||
|
const { column, lists, groups, accounts } = this.props
|
||||||
|
const { hashtagValue } = this.state
|
||||||
|
|
||||||
|
if (column === 'hashtag') {
|
||||||
|
return (
|
||||||
|
<div className={[_s.d, _s.px15, _s.py10].join(' ')}>
|
||||||
|
<Input
|
||||||
|
type='text'
|
||||||
|
value={hashtagValue}
|
||||||
|
placeholder='gabfam'
|
||||||
|
id='hashtag-deck'
|
||||||
|
title='Enter hashtag'
|
||||||
|
onChange={this.onChangeHashtagValue}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else if (column === 'list') {
|
||||||
|
const listItems = lists.map((list) => ({
|
||||||
|
onClick: () => this.handleAdd(`list.${list.get('id')}`),
|
||||||
|
title: list.get('title'),
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.d, _s.maxH340PX, _s.overflowYScroll].join(' ')}>
|
||||||
|
<List
|
||||||
|
scrollKey='lists-deck-add'
|
||||||
|
showLoading={lists.size === 0}
|
||||||
|
emptyMessage="You don't have any lists yet."
|
||||||
|
items={listItems}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else if (column === 'group') {
|
||||||
|
const listItems = groups.map((group) => ({
|
||||||
|
onClick: () => this.handleAdd(`group.${group.get('id')}`),
|
||||||
|
title: group.get('title'),
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.d, _s.maxH340PX, _s.overflowYScroll].join(' ')}>
|
||||||
|
<List
|
||||||
|
scrollKey='groups-deck-add'
|
||||||
|
showLoading={groups.size === 0}
|
||||||
|
emptyMessage="You are not a member of any groups yet."
|
||||||
|
items={listItems}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else if (column === 'group') {
|
||||||
|
return (
|
||||||
|
<div className={[_s.d, _s.px15, _s.py10].join(' ')}>
|
||||||
|
<Input
|
||||||
|
type='text'
|
||||||
|
value={usernameValue}
|
||||||
|
placeholder=''
|
||||||
|
id='user-deck'
|
||||||
|
title='Enter username'
|
||||||
|
onChange={this.onChangeUsernameValue}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAdd = () => {
|
|
||||||
//
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { column } = this.props
|
const { column } = this.props
|
||||||
const { selectedItem } = this.state
|
const { hashtagValue } = this.state
|
||||||
|
|
||||||
// user, hashtag, list, groups
|
|
||||||
|
|
||||||
if (!column) return <div />
|
if (!column) return <div />
|
||||||
const title = `Select a ${column}`
|
const title = `Select a ${column}`
|
||||||
|
|
||||||
|
const content = this.getContentForColumn()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{width: '520px'}} className={[_s.d, _s.modal].join(' ')}>
|
<div style={{width: '520px'}} className={[_s.d, _s.modal].join(' ')}>
|
||||||
<Block>
|
<Block>
|
||||||
|
@ -49,16 +151,19 @@ class DeckColumnAddOptionsModal extends React.PureComponent {
|
||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className={[_s.d, _s.w115PX, _s.aiEnd, _s.jcCenter, _s.mlAuto].join(' ')}>
|
<div className={[_s.d, _s.w115PX, _s.aiEnd, _s.jcCenter, _s.mlAuto].join(' ')}>
|
||||||
|
{
|
||||||
|
column === 'hashtag' &&
|
||||||
<Button
|
<Button
|
||||||
isDisabled={!selectedItem}
|
isDisabled={!hashtagValue}
|
||||||
onClick={this.handleAdd}
|
onClick={this.handleAddHashtag}
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.d].join(' ')}>
|
<div className={[_s.d].join(' ')}>
|
||||||
test
|
{content}
|
||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,9 +172,33 @@ class DeckColumnAddOptionsModal extends React.PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
lists: getOrderedLists(state),
|
||||||
|
groups: getListOfGroups(state, { type: 'member' }),
|
||||||
|
accounts: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onFetchLists() {
|
||||||
|
dispatch(fetchLists())
|
||||||
|
},
|
||||||
|
onFetchMemberGroups() {
|
||||||
|
dispatch(fetchGroupsByTab('member'))
|
||||||
|
},
|
||||||
|
onSetDeckColumn(id) {
|
||||||
|
dispatch(setDeckColumnAtIndex(id))
|
||||||
|
},
|
||||||
|
onOpenDeckColumnAddModal() {
|
||||||
|
dispatch(openModal(MODAL_DECK_COLUMN_ADD))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
DeckColumnAddOptionsModal.propTypes = {
|
DeckColumnAddOptionsModal.propTypes = {
|
||||||
|
groupIds: ImmutablePropTypes.list,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
|
onFetchLists: PropTypes.func.isRequired,
|
||||||
|
onSetDeckColumn: PropTypes.func.isRequired,
|
||||||
column: PropTypes.string.isRequired,
|
column: PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect()(DeckColumnAddOptionsModal)
|
export default connect(mapStateToProps, mapDispatchToProps)(DeckColumnAddOptionsModal)
|
|
@ -1,88 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
||||||
import { changeSetting, saveSettings } from '../../actions/settings'
|
|
||||||
import ModalLayout from './modal_layout'
|
|
||||||
import Button from '../button'
|
|
||||||
import SettingSwitch from '../setting_switch'
|
|
||||||
import Text from '../text'
|
|
||||||
|
|
||||||
class HashtagTimelineSettingsModal extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
handleSaveAndClose = () => {
|
|
||||||
this.props.onSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { intl, settings, onChange, onClose } = this.props
|
|
||||||
|
|
||||||
// : todo :
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalLayout
|
|
||||||
width={320}
|
|
||||||
title={intl.formatMessage(messages.title)}
|
|
||||||
onClose={onClose}
|
|
||||||
>
|
|
||||||
|
|
||||||
<div className={[_s.d, _s.pb10].join(' ')}>
|
|
||||||
<SettingSwitch
|
|
||||||
prefix='community_timeline'
|
|
||||||
settings={settings}
|
|
||||||
settingPath={['shows', 'inSidebar']}
|
|
||||||
onChange={onChange}
|
|
||||||
label={intl.formatMessage(messages.showInSidebar)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
backgroundColor='brand'
|
|
||||||
color='white'
|
|
||||||
className={_s.jcCenter}
|
|
||||||
onClick={this.handleSaveAndClose}
|
|
||||||
>
|
|
||||||
<Text color='inherit' weight='bold' align='center'>
|
|
||||||
{intl.formatMessage(messages.saveAndClose)}
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
</ModalLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
title: { id: 'hashtag_timeline_settings', defaultMessage: 'Hashtag Timeline Settings' },
|
|
||||||
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
|
|
||||||
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
|
|
||||||
showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' },
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
settings: state.getIn(['settings', 'community']),
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { onClose }) => {
|
|
||||||
return {
|
|
||||||
onChange(key, checked) {
|
|
||||||
dispatch(changeSetting(['community', ...key], checked))
|
|
||||||
},
|
|
||||||
onSave() {
|
|
||||||
dispatch(saveSettings())
|
|
||||||
onClose()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HasttagTimelineSettingsModal.propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
settings: ImmutablePropTypes.map.isRequired,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
onSave: PropTypes.func.isRequired,
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(HashtagTimelineSettingsModal))
|
|
|
@ -8,11 +8,12 @@ import ModalBase from './modal_base'
|
||||||
import BundleErrorModal from './bundle_error_modal'
|
import BundleErrorModal from './bundle_error_modal'
|
||||||
import LoadingModal from './loading_modal'
|
import LoadingModal from './loading_modal'
|
||||||
import {
|
import {
|
||||||
|
MODAL_ALBUM_CREATE,
|
||||||
MODAL_BLOCK_ACCOUNT,
|
MODAL_BLOCK_ACCOUNT,
|
||||||
|
MODAL_BOOKMARK_COLLECTION_CREATE,
|
||||||
MODAL_BOOST,
|
MODAL_BOOST,
|
||||||
MODAL_CHAT_CONVERSATION_CREATE,
|
MODAL_CHAT_CONVERSATION_CREATE,
|
||||||
MODAL_CHAT_CONVERSATION_DELETE,
|
MODAL_CHAT_CONVERSATION_DELETE,
|
||||||
MODAL_COMMUNITY_TIMELINE_SETTINGS,
|
|
||||||
MODAL_COMPOSE,
|
MODAL_COMPOSE,
|
||||||
MODAL_CONFIRM,
|
MODAL_CONFIRM,
|
||||||
MODAL_DECK_COLUMN_ADD,
|
MODAL_DECK_COLUMN_ADD,
|
||||||
|
@ -24,7 +25,6 @@ import {
|
||||||
MODAL_GROUP_CREATE,
|
MODAL_GROUP_CREATE,
|
||||||
MODAL_GROUP_DELETE,
|
MODAL_GROUP_DELETE,
|
||||||
MODAL_GROUP_PASSWORD,
|
MODAL_GROUP_PASSWORD,
|
||||||
MODAL_HASHTAG_TIMELINE_SETTINGS,
|
|
||||||
MODAL_HOME_TIMELINE_SETTINGS,
|
MODAL_HOME_TIMELINE_SETTINGS,
|
||||||
MODAL_HOTKEYS,
|
MODAL_HOTKEYS,
|
||||||
MODAL_LIST_ADD_USER,
|
MODAL_LIST_ADD_USER,
|
||||||
|
@ -44,11 +44,12 @@ import {
|
||||||
MODAL_VIDEO,
|
MODAL_VIDEO,
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
import {
|
import {
|
||||||
|
AlbumCreateModal,
|
||||||
BlockAccountModal,
|
BlockAccountModal,
|
||||||
|
BookmarkCollectionCreateModal,
|
||||||
BoostModal,
|
BoostModal,
|
||||||
ChatConversationCreateModal,
|
ChatConversationCreateModal,
|
||||||
ChatConversationDeleteModal,
|
ChatConversationDeleteModal,
|
||||||
CommunityTimelineSettingsModal,
|
|
||||||
ComposeModal,
|
ComposeModal,
|
||||||
ConfirmationModal,
|
ConfirmationModal,
|
||||||
DeckColumnAddModal,
|
DeckColumnAddModal,
|
||||||
|
@ -62,7 +63,6 @@ import {
|
||||||
GroupMembersModal,
|
GroupMembersModal,
|
||||||
GroupPasswordModal,
|
GroupPasswordModal,
|
||||||
GroupRemovedAccountsModal,
|
GroupRemovedAccountsModal,
|
||||||
HashtagTimelineSettingsModal,
|
|
||||||
HomeTimelineSettingsModal,
|
HomeTimelineSettingsModal,
|
||||||
HotkeysModal,
|
HotkeysModal,
|
||||||
ListAddUserModal,
|
ListAddUserModal,
|
||||||
|
@ -83,11 +83,12 @@ import {
|
||||||
} from '../../features/ui/util/async_components'
|
} from '../../features/ui/util/async_components'
|
||||||
|
|
||||||
const MODAL_COMPONENTS = {
|
const MODAL_COMPONENTS = {
|
||||||
|
[MODAL_ALBUM_CREATE]: AlbumCreateModal,
|
||||||
[MODAL_BLOCK_ACCOUNT]: BlockAccountModal,
|
[MODAL_BLOCK_ACCOUNT]: BlockAccountModal,
|
||||||
|
[MODAL_BOOKMARK_COLLECTION_CREATE]: BookmarkCollectionCreateModal,
|
||||||
[MODAL_BOOST]: BoostModal,
|
[MODAL_BOOST]: BoostModal,
|
||||||
[MODAL_CHAT_CONVERSATION_CREATE]: ChatConversationCreateModal,
|
[MODAL_CHAT_CONVERSATION_CREATE]: ChatConversationCreateModal,
|
||||||
[MODAL_CHAT_CONVERSATION_DELETE]: ChatConversationDeleteModal,
|
[MODAL_CHAT_CONVERSATION_DELETE]: ChatConversationDeleteModal,
|
||||||
[MODAL_COMMUNITY_TIMELINE_SETTINGS]: CommunityTimelineSettingsModal,
|
|
||||||
[MODAL_COMPOSE]: ComposeModal,
|
[MODAL_COMPOSE]: ComposeModal,
|
||||||
[MODAL_CONFIRM]: ConfirmationModal,
|
[MODAL_CONFIRM]: ConfirmationModal,
|
||||||
[MODAL_DECK_COLUMN_ADD]: DeckColumnAddModal,
|
[MODAL_DECK_COLUMN_ADD]: DeckColumnAddModal,
|
||||||
|
@ -99,7 +100,6 @@ const MODAL_COMPONENTS = {
|
||||||
[MODAL_GROUP_CREATE]: GroupCreateModal,
|
[MODAL_GROUP_CREATE]: GroupCreateModal,
|
||||||
[MODAL_GROUP_DELETE]: GroupDeleteModal,
|
[MODAL_GROUP_DELETE]: GroupDeleteModal,
|
||||||
[MODAL_GROUP_PASSWORD]: GroupPasswordModal,
|
[MODAL_GROUP_PASSWORD]: GroupPasswordModal,
|
||||||
[MODAL_HASHTAG_TIMELINE_SETTINGS]: HashtagTimelineSettingsModal,
|
|
||||||
[MODAL_HOME_TIMELINE_SETTINGS]: HomeTimelineSettingsModal,
|
[MODAL_HOME_TIMELINE_SETTINGS]: HomeTimelineSettingsModal,
|
||||||
[MODAL_HOTKEYS]: HotkeysModal,
|
[MODAL_HOTKEYS]: HotkeysModal,
|
||||||
[MODAL_LIST_ADD_USER]: ListAddUserModal,
|
[MODAL_LIST_ADD_USER]: ListAddUserModal,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import BackButton from '../back_button'
|
import BackButton from '../back_button'
|
||||||
|
import Button from '../button'
|
||||||
import Heading from '../heading'
|
import Heading from '../heading'
|
||||||
|
|
||||||
class ProfileNavigationBar extends React.PureComponent {
|
class ProfileNavigationBar extends React.PureComponent {
|
||||||
|
@ -28,6 +29,19 @@ class ProfileNavigationBar extends React.PureComponent {
|
||||||
</Heading>
|
</Heading>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={[_s.d, _s.minH53PX, _s.jcCenter, _s.mr15].join(' ')}>
|
||||||
|
<Button
|
||||||
|
icon='ellipsis'
|
||||||
|
iconSize='26px'
|
||||||
|
iconClassName={_s.inheritFill}
|
||||||
|
color='brand'
|
||||||
|
backgroundColor='none'
|
||||||
|
className={[_s.jcCenter, _s.aiCenter, _s.ml10, _s.px10].join(' ')}
|
||||||
|
onClick={this.handleOpenMore}
|
||||||
|
buttonRef={this.setOpenMoreNodeRef}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -61,7 +61,7 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
||||||
noPadding
|
noPadding
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
headerButtonTitle={!!account ? intl.formatMessage(messages.show_all) : undefined}
|
headerButtonTitle={!!account ? intl.formatMessage(messages.show_all) : undefined}
|
||||||
headerButtonTo={!!account ? `/${account.get('acct')}/photos` : undefined}
|
headerButtonTo={!!account ? `/${account.get('acct')}/albums` : undefined}
|
||||||
>
|
>
|
||||||
<div className={[_s.d, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
<div className={[_s.d, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,35 +32,27 @@ class ProfileStatsPanel extends ImmutablePureComponent {
|
||||||
!!account &&
|
!!account &&
|
||||||
<ResponsiveClassesComponent
|
<ResponsiveClassesComponent
|
||||||
classNames={[_s.d, _s.flexRow].join(' ')}
|
classNames={[_s.d, _s.flexRow].join(' ')}
|
||||||
classNamesXS={[_s.d, _s.flexRow, _s.mt15, _s.pt10].join(' ')}
|
classNamesXS={[_s.d, _s.flexRow, _s.mt15, _s.flexWrap].join(' ')}
|
||||||
>
|
>
|
||||||
<UserStat
|
<UserStat
|
||||||
title={intl.formatMessage(messages.gabs)}
|
title={intl.formatMessage(messages.gabs)}
|
||||||
value={shortNumberFormat(account.get('statuses_count'))}
|
value={shortNumberFormat(account.get('statuses_count'))}
|
||||||
to={`/${account.get('acct')}`}
|
to={`/${account.get('acct')}`}
|
||||||
isCentered={noPanel}
|
isInline={noPanel}
|
||||||
/>
|
/>
|
||||||
<UserStat
|
<UserStat
|
||||||
title={intl.formatMessage(messages.followers)}
|
title={intl.formatMessage(messages.followers)}
|
||||||
value={shortNumberFormat(account.get('followers_count'))}
|
value={shortNumberFormat(account.get('followers_count'))}
|
||||||
to={`/${account.get('acct')}/followers`}
|
to={`/${account.get('acct')}/followers`}
|
||||||
isCentered={noPanel}
|
isInline={noPanel}
|
||||||
/>
|
/>
|
||||||
<UserStat
|
<UserStat
|
||||||
|
isLast
|
||||||
title={intl.formatMessage(messages.follows)}
|
title={intl.formatMessage(messages.follows)}
|
||||||
value={shortNumberFormat(account.get('following_count'))}
|
value={shortNumberFormat(account.get('following_count'))}
|
||||||
to={`/${account.get('acct')}/following`}
|
to={`/${account.get('acct')}/following`}
|
||||||
isCentered={noPanel}
|
isInline={noPanel}
|
||||||
/>
|
/>
|
||||||
{
|
|
||||||
account.get('id') === me &&
|
|
||||||
<UserStat
|
|
||||||
title={intl.formatMessage(messages.likes)}
|
|
||||||
value={shortNumberFormat(0)}
|
|
||||||
to={`/${account.get('acct')}/likes`}
|
|
||||||
isCentered={noPanel}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</ResponsiveClassesComponent>
|
</ResponsiveClassesComponent>
|
||||||
}
|
}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
|
|
@ -53,6 +53,12 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
|
||||||
subtitle: 'Hide until next message',
|
subtitle: 'Hide until next message',
|
||||||
onClick: () => this.handleOnHide(),
|
onClick: () => this.handleOnHide(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
hideArrow: true,
|
||||||
|
title: 'Mute Conversation',
|
||||||
|
subtitle: "Don't get notified of new messages",
|
||||||
|
onClick: () => this.handleOnHide(),
|
||||||
|
},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
hideArrow: true,
|
hideArrow: true,
|
||||||
|
|
|
@ -4,14 +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 {
|
||||||
isChatMessengerBlocked,
|
|
||||||
isChatMessengerMuted,
|
|
||||||
blockChatMessenger,
|
blockChatMessenger,
|
||||||
unblockChatMessenger,
|
unblockChatMessenger,
|
||||||
muteChatMessenger,
|
|
||||||
unmuteChatMessenger,
|
|
||||||
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'
|
||||||
|
@ -21,6 +18,12 @@ import Text from '../text'
|
||||||
|
|
||||||
class ChatMessageOptionsPopover extends React.PureComponent {
|
class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (!this.props.isMine) {
|
||||||
|
this.props.onFetchRelationships(this.props.fromAccountId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleOnDelete = () => {
|
handleOnDelete = () => {
|
||||||
this.props.onDeleteChatMessage(this.props.chatMessageId)
|
this.props.onDeleteChatMessage(this.props.chatMessageId)
|
||||||
}
|
}
|
||||||
|
@ -31,17 +34,9 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
|
|
||||||
handleOnBlock = () => {
|
handleOnBlock = () => {
|
||||||
if (this.props.isBlocked) {
|
if (this.props.isBlocked) {
|
||||||
this.props.unblockChatMessenger(this.props.fromAccountId)
|
this.props.onUnblock(this.props.fromAccountId)
|
||||||
} else {
|
} else {
|
||||||
this.props.blockChatMessenger(this.props.fromAccountId)
|
this.props.onBlock(this.props.fromAccountId)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnMute = () => {
|
|
||||||
if (this.props.isMuted) {
|
|
||||||
this.props.unmuteChatMessenger(this.props.fromAccountId)
|
|
||||||
} else {
|
|
||||||
this.props.muteChatMessenger(this.props.fromAccountId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +48,6 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
const {
|
const {
|
||||||
isXS,
|
isXS,
|
||||||
isMine,
|
isMine,
|
||||||
isMuted,
|
|
||||||
isBlocked,
|
isBlocked,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
@ -76,12 +70,6 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
subtitle: isBlocked ? '' : 'The messenger will not be able to message you.',
|
subtitle: isBlocked ? '' : 'The messenger will not be able to message you.',
|
||||||
onClick: () => this.handleOnBlock(),
|
onClick: () => this.handleOnBlock(),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
hideArrow: true,
|
|
||||||
title: isMuted ? 'Unmute Messenger' : 'Mute Messenger',
|
|
||||||
subtitle: isMuted ? '' : 'You will not be notified of new messsages',
|
|
||||||
onClick: () => this.handleOnMute(),
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -96,12 +84,15 @@ class ChatMessageOptionsPopover extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state, { chatMessageId }) => ({
|
const mapStateToProps = (state, { chatMessageId }) => {
|
||||||
isMine: state.getIn(['chat_messages', chatMessageId, 'from_account_id']) === me,
|
const fromAccountId = state.getIn(['chat_messages', chatMessageId, 'from_account_id'])
|
||||||
fromAccountId: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
|
|
||||||
isBlocked: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
|
return {
|
||||||
isMuted: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
|
fromAccountId,
|
||||||
})
|
isMine: fromAccountId === me,
|
||||||
|
isBlocked: state.getIn(['relationships', fromAccountId, 'chat_blocked_by'], false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onDeleteChatMessage(chatMessageId) {
|
onDeleteChatMessage(chatMessageId) {
|
||||||
|
@ -114,15 +105,12 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onUnblock(accountId) {
|
onUnblock(accountId) {
|
||||||
dispatch(unblockChatMessenger(accountId))
|
dispatch(unblockChatMessenger(accountId))
|
||||||
},
|
},
|
||||||
onMute(accountId) {
|
|
||||||
dispatch(muteChatMessenger(accountId))
|
|
||||||
},
|
|
||||||
onUnmute(accountId) {
|
|
||||||
dispatch(unmuteChatMessenger(accountId))
|
|
||||||
},
|
|
||||||
onReportChatMessage(chatMessageId) {
|
onReportChatMessage(chatMessageId) {
|
||||||
dispatch(reportChatMessage(chatMessageId))
|
dispatch(reportChatMessage(chatMessageId))
|
||||||
},
|
},
|
||||||
|
onFetchRelationships(accountId) {
|
||||||
|
// dispatch(fetchRelationships(accountId))
|
||||||
|
},
|
||||||
onClosePopover() {
|
onClosePopover() {
|
||||||
dispatch(closePopover())
|
dispatch(closePopover())
|
||||||
},
|
},
|
||||||
|
@ -130,9 +118,9 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
||||||
ChatMessageOptionsPopover.propTypes = {
|
ChatMessageOptionsPopover.propTypes = {
|
||||||
isXS: PropTypes.bool,
|
isXS: PropTypes.bool,
|
||||||
|
isMine: PropTypes.bool,
|
||||||
chatMessageId: PropTypes.string.isRequired,
|
chatMessageId: PropTypes.string.isRequired,
|
||||||
isBlocked: PropTypes.bool.isRequired,
|
isBlocked: PropTypes.bool.isRequired,
|
||||||
isMuted: PropTypes.bool.isRequired,
|
|
||||||
onDeleteChatMessage: PropTypes.func.isRequired,
|
onDeleteChatMessage: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { connect } from 'react-redux'
|
||||||
import { closePopover } from '../../actions/popover'
|
import { closePopover } from '../../actions/popover'
|
||||||
import PopoverLayout from './popover_layout'
|
import PopoverLayout from './popover_layout'
|
||||||
import List from '../list'
|
import List from '../list'
|
||||||
|
import Button from '../button'
|
||||||
import Text from '../text'
|
import Text from '../text'
|
||||||
|
|
||||||
class ComposePostDesinationPopover extends React.PureComponent {
|
class ComposePostDesinationPopover extends React.PureComponent {
|
||||||
|
@ -38,8 +39,20 @@ class ComposePostDesinationPopover extends React.PureComponent {
|
||||||
isXS={isXS}
|
isXS={isXS}
|
||||||
onClose={this.handleOnClosePopover}
|
onClose={this.handleOnClosePopover}
|
||||||
>
|
>
|
||||||
|
<div className={[_s.d]}>
|
||||||
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>Post to:</Text>
|
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>Post to:</Text>
|
||||||
<List items={items} />
|
<List items={items} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>
|
||||||
|
<Button
|
||||||
|
isText
|
||||||
|
icon='back'
|
||||||
|
/>
|
||||||
|
Select group:
|
||||||
|
</Text>
|
||||||
|
<List items={items} />
|
||||||
|
</div>
|
||||||
</PopoverLayout>
|
</PopoverLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||||
handleGroupRemoveAccount = () => {
|
handleGroupRemoveAccount = () => {
|
||||||
const { status } = this.props
|
const { status } = this.props
|
||||||
|
|
||||||
|
// : todo : check
|
||||||
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']))
|
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
title: intl.formatMessage(messages.comments),
|
title: intl.formatMessage(messages.comments),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: `/${account.get('acct')}/photos`,
|
to: `/${account.get('acct')}/albums`,
|
||||||
title: intl.formatMessage(messages.photos),
|
title: intl.formatMessage(messages.photos),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -119,7 +119,11 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
const isMyProfile = !account ? false : account.get('id') === me
|
const isMyProfile = !account ? false : account.get('id') === me
|
||||||
if (isMyProfile) {
|
if (isMyProfile) {
|
||||||
tabs.push({
|
tabs.push({
|
||||||
to: `/${account.get('acct')}/bookmarks`,
|
to: `/${account.get('acct')}/likes`,
|
||||||
|
title: 'Likes',
|
||||||
|
})
|
||||||
|
tabs.push({
|
||||||
|
to: `/${account.get('acct')}/bookmark_collections`,
|
||||||
title: intl.formatMessage(messages.bookmarks),
|
title: intl.formatMessage(messages.bookmarks),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -149,21 +153,12 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
displayNone: stickied,
|
displayNone: stickied,
|
||||||
})
|
})
|
||||||
|
|
||||||
const mobileAvatarContainerClasses = CX({
|
|
||||||
d: 1,
|
|
||||||
circle: 1,
|
|
||||||
boxShadowProfileAvatar: 1,
|
|
||||||
mtNeg50PX: !headerMissing,
|
|
||||||
})
|
|
||||||
|
|
||||||
const mobileDescriptionContainerClasses = CX({
|
const mobileDescriptionContainerClasses = CX({
|
||||||
d: 1,
|
d: 1,
|
||||||
w100PC: 1,
|
w100PC: 1,
|
||||||
px15: 1,
|
px15: 1,
|
||||||
mt5: !!me,
|
|
||||||
mb10: 1,
|
mb10: 1,
|
||||||
pt15: !!me,
|
pt15: !!me,
|
||||||
pb10: 1,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -174,10 +169,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||||
{
|
{
|
||||||
!headerMissing &&
|
!headerMissing &&
|
||||||
<div className={[_s.d, _s.h200PX, _s.px10, _s.w100PC, _s.mt10, _s.overflowHidden].join(' ')}>
|
<div className={[_s.d, _s.h172PX, _s.w100PC, _s.overflowHidden].join(' ')}>
|
||||||
<Image
|
<Image
|
||||||
alt={intl.formatMessage(messages.headerPhoto)}
|
alt={intl.formatMessage(messages.headerPhoto)}
|
||||||
className={[_s.topRightRadiusSmall, _s.topLeftRadiusSmall, _s.h100PC].join(' ')}
|
className={_s.h100PC}
|
||||||
src={headerSrc}
|
src={headerSrc}
|
||||||
expandOnClick
|
expandOnClick
|
||||||
/>
|
/>
|
||||||
|
@ -185,37 +180,24 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
headerMissing &&
|
headerMissing &&
|
||||||
<div className={[_s.d, _s.h20PX, _s.w100PC].join(' ')} />
|
<div className={[_s.d, _s.h122PX, _s.w100PC, _s.bgSecondary].join(' ')} />
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||||
|
|
||||||
<div className={[_s.d, _s.aiCenter, _s.px15, _s.mb5].join(' ')}>
|
<div className={[_s.d, _s.px15].join(' ')}>
|
||||||
<div className={mobileAvatarContainerClasses}>
|
<div class={[_s.d, _s.flexRow].join(' ')}>
|
||||||
<Avatar size={100} account={account} noHover expandOnClick />
|
<div className={[_s.d, _s.circle, _s.boxShadowProfileAvatar, _s.mtNeg32PX].join(' ')}>
|
||||||
|
<Avatar size={88} account={account} noHover expandOnClick />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[_s.d, _s.flexRow, _s.flexNormal, _s.py10].join(' ')}>
|
|
||||||
<DisplayName
|
|
||||||
account={account}
|
|
||||||
isMultiline
|
|
||||||
isLarge
|
|
||||||
isCentered
|
|
||||||
noHover
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div className={[_s.d, _s.bgPrimary, _s.aiCenter].join(' ')}>
|
|
||||||
{
|
{
|
||||||
account && account.get('id') === me &&
|
account && account.get('id') === me &&
|
||||||
<div className={[_s.d,_s.py5].join(' ')}>
|
<div className={[_s.d, _s.flexRow, _s.pt10, _s.flexGrow1, _s.h40PX, _s.jcEnd].join(' ')}>
|
||||||
<Button
|
<Button
|
||||||
isOutline
|
isOutline
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
color='brand'
|
color='brand'
|
||||||
className={[_s.jcCenter, _s.aiCenter].join(' ')}
|
className={[_s.jcCenter, _s.aiCenter, _s.h40PX].join(' ')}
|
||||||
onClick={this.handleOnEditProfile}
|
onClick={this.handleOnEditProfile}
|
||||||
>
|
>
|
||||||
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
|
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
|
||||||
|
@ -227,43 +209,51 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||||
|
|
||||||
{
|
{
|
||||||
account && account.get('id') !== me && !!me &&
|
account && account.get('id') !== me && !!me &&
|
||||||
<div className={[_s.d, _s.flexRow, _s.py5].join(' ')}>
|
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.pt15, _s.flexGrow1, _s.h40PX, _s.jcEnd].join(' ')}>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
icon={isShortcut ? 'star' : 'star-outline'}
|
icon={isShortcut ? 'star' : 'star-outline'}
|
||||||
iconSize='18px'
|
iconSize='18px'
|
||||||
color='brand'
|
color='brand'
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
className={[_s.jcCenter, _s.aiCenter, _s.px10, _s.mr15].join(' ')}
|
className={[_s.jcCenter, _s.aiCenter, _s.px10, _s.mr10].join(' ')}
|
||||||
onClick={this.handleToggleShortcut}
|
onClick={this.handleToggleShortcut}
|
||||||
/>
|
/>
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.h40PX].join(' ')}>
|
||||||
<div className={[_s.d, _s.flexRow, _s.mr15].join(' ')}>
|
|
||||||
<AccountActionButton account={account} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Button
|
<Button
|
||||||
isOutline
|
isOutline
|
||||||
icon='ellipsis'
|
icon='chat'
|
||||||
iconSize='18px'
|
iconSize='18px'
|
||||||
iconClassName={_s.inheritFill}
|
iconClassName={_s.inheritFill}
|
||||||
color='brand'
|
color='brand'
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
className={[_s.jcCenter, _s.aiCenter, _s.ml10, _s.px10].join(' ')}
|
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10].join(' ')}
|
||||||
onClick={this.handleOpenMore}
|
onClick={this.handleOpenMore}
|
||||||
buttonRef={this.setOpenMoreNodeRef}
|
buttonRef={this.setOpenMoreNodeRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.h40PX].join(' ')}>
|
||||||
|
<AccountActionButton account={account} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.flexNormal, _s.pt10].join(' ')}>
|
||||||
|
<DisplayName
|
||||||
|
account={account}
|
||||||
|
isMultiline
|
||||||
|
isLarge
|
||||||
|
noHover
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[_s.d, _s.bgPrimary, _s.aiCenter].join(' ')}>
|
||||||
<div className={mobileDescriptionContainerClasses}>
|
<div className={mobileDescriptionContainerClasses}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[_s.d, _s.mt10, _s.mb10, _s.pt5, _s.w100PC, _s.pr10].join(' ')}>
|
<div className={[_s.d, _s.mt10, _s.mb10, _s.pt5, _s.w100PC].join(' ')}>
|
||||||
<Pills pills={tabs} />
|
<Pills pills={tabs} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -89,17 +89,11 @@ class DeckSidebar extends ImmutablePureComponent {
|
||||||
|
|
||||||
<div className={[_s.d, _s.aiCenter, _s.jcCenter].join(' ')}>
|
<div className={[_s.d, _s.aiCenter, _s.jcCenter].join(' ')}>
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
!!gabDeckOrder && gabDeckOrder.map((item, i) => (
|
!!gabDeckOrder && gabDeckOrder.map((item, i) => (
|
||||||
<Button
|
|
||||||
isText
|
|
||||||
key={`gab-deck-sidebar-dot-${i}`}
|
|
||||||
onClick={this.scrollToItem}
|
|
||||||
backgroundColor='secondary'
|
|
||||||
className={[_s.mt5, _s.mb5, _s.px10, _s.py10, _s.circle].join(' ')}
|
|
||||||
icon='notifications'
|
|
||||||
iconClassName={_s.cPrimary}
|
|
||||||
/>
|
|
||||||
))
|
))
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { CX } from '../constants'
|
import { CX } from '../constants'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
|
import DotTextSeperator from './dot_text_seperator'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a user stat component
|
* Renders a user stat component
|
||||||
|
@ -30,17 +31,29 @@ class UserStat extends React.PureComponent {
|
||||||
title,
|
title,
|
||||||
value,
|
value,
|
||||||
isCentered,
|
isCentered,
|
||||||
|
isInline,
|
||||||
|
isLast,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { hovering } = this.state
|
const { hovering } = this.state
|
||||||
|
|
||||||
const align = isCentered ? 'center' : 'left'
|
const align = isCentered ? 'center' : 'left'
|
||||||
|
const titleSize = isInline ? 'normal' : 'extraLarge'
|
||||||
|
const subtitleSize = isInline ? 'normal' : 'small'
|
||||||
|
|
||||||
const containerClasses = CX({
|
const containerClasses = CX({
|
||||||
d: 1,
|
d: 1,
|
||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
noUnderline: 1,
|
noUnderline: 1,
|
||||||
flexNormal: isCentered,
|
flexNormal: isCentered,
|
||||||
flexGrow1: !isCentered,
|
flexGrow1: !isCentered && !isInline,
|
||||||
pr15: !isCentered,
|
flexRow: isInline,
|
||||||
|
aiCenter: isInline,
|
||||||
|
pr15: !isCentered && !isInline,
|
||||||
|
pr10: !isCentered && isInline,
|
||||||
|
})
|
||||||
|
const subtitleClasses = CX({
|
||||||
|
pr5: isInline,
|
||||||
|
pl5: isInline,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -51,12 +64,13 @@ class UserStat extends React.PureComponent {
|
||||||
onMouseEnter={this.handleOnMouseEnter}
|
onMouseEnter={this.handleOnMouseEnter}
|
||||||
onMouseLeave={this.handleOnMouseLeave}
|
onMouseLeave={this.handleOnMouseLeave}
|
||||||
>
|
>
|
||||||
<Text size='extraLarge' weight='bold' color='brand' align={align}>
|
<Text size={titleSize} weight='bold' color='brand' align={align}>
|
||||||
{value}
|
{value}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size='small' weight='medium' color='secondary' hasUnderline={hovering} align={align}>
|
<Text size={subtitleSize} weight='medium' color='secondary' hasUnderline={hovering} align={align} className={subtitleClasses}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
|
{ !isLast && isInline && <DotTextSeperator /> }
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -72,6 +86,8 @@ UserStat.propTypes = {
|
||||||
PropTypes.object,
|
PropTypes.object,
|
||||||
]).isRequired,
|
]).isRequired,
|
||||||
isCentered: PropTypes.bool,
|
isCentered: PropTypes.bool,
|
||||||
|
isInline: PropTypes.bool,
|
||||||
|
isLast: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserStat
|
export default UserStat
|
|
@ -46,11 +46,12 @@ export const POPOVER_TIMELINE_INJECTION_OPTIONS = 'TIMELINE_INJECTION_OPTIONS'
|
||||||
export const POPOVER_USER_INFO = 'USER_INFO'
|
export const POPOVER_USER_INFO = 'USER_INFO'
|
||||||
export const POPOVER_VIDEO_STATS = 'VIDEO_STATS'
|
export const POPOVER_VIDEO_STATS = 'VIDEO_STATS'
|
||||||
|
|
||||||
|
export const MODAL_ALBUM_CREATE = 'ALBUM_CREATE'
|
||||||
export const MODAL_BLOCK_ACCOUNT = 'BLOCK_ACCOUNT'
|
export const MODAL_BLOCK_ACCOUNT = 'BLOCK_ACCOUNT'
|
||||||
|
export const MODAL_BOOKMARK_COLLECTION_CREATE = 'BOOKMARK_COLLECTION_CREATE'
|
||||||
export const MODAL_BOOST = 'BOOST'
|
export const MODAL_BOOST = 'BOOST'
|
||||||
export const MODAL_CHAT_CONVERSATION_CREATE = 'CHAT_CONVERSATION_CREATE'
|
export const MODAL_CHAT_CONVERSATION_CREATE = 'CHAT_CONVERSATION_CREATE'
|
||||||
export const MODAL_CHAT_CONVERSATION_DELETE = 'CHAT_CONVERSATION_DELETE'
|
export const MODAL_CHAT_CONVERSATION_DELETE = 'CHAT_CONVERSATION_DELETE'
|
||||||
export const MODAL_COMMUNITY_TIMELINE_SETTINGS = 'COMMUNITY_TIMELINE_SETTINGS'
|
|
||||||
export const MODAL_COMPOSE = 'COMPOSE'
|
export const MODAL_COMPOSE = 'COMPOSE'
|
||||||
export const MODAL_CONFIRM = 'CONFIRM'
|
export const MODAL_CONFIRM = 'CONFIRM'
|
||||||
export const MODAL_DECK_COLUMN_ADD = 'DECK_COLUMN_ADD'
|
export const MODAL_DECK_COLUMN_ADD = 'DECK_COLUMN_ADD'
|
||||||
|
@ -62,7 +63,6 @@ export const MODAL_EMAIL_CONFIRMATION_REMINDER = 'EMAIL_CONFIRMATION_REMINDER'
|
||||||
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
|
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
|
||||||
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
|
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
|
||||||
export const MODAL_GROUP_PASSWORD = 'GROUP_PASSWORD'
|
export const MODAL_GROUP_PASSWORD = 'GROUP_PASSWORD'
|
||||||
export const MODAL_HASHTAG_TIMELINE_SETTINGS = 'HASHTAG_TIMELINE_SETTINGS'
|
|
||||||
export const MODAL_HOME_TIMELINE_SETTINGS = 'HOME_TIMELINE_SETTINGS'
|
export const MODAL_HOME_TIMELINE_SETTINGS = 'HOME_TIMELINE_SETTINGS'
|
||||||
export const MODAL_HOTKEYS = 'HOTKEYS'
|
export const MODAL_HOTKEYS = 'HOTKEYS'
|
||||||
export const MODAL_LIST_ADD_USER = 'LIST_ADD_USER'
|
export const MODAL_LIST_ADD_USER = 'LIST_ADD_USER'
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { expandAccountMediaTimeline } from '../actions/timelines'
|
||||||
|
import { getAccountGallery } from '../selectors'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
import MediaItem from '../components/media_item'
|
||||||
|
import LoadMore from '../components/load_more'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import MediaGalleryPlaceholder from '../components/placeholder/media_gallery_placeholder'
|
||||||
|
|
||||||
|
class AccountAlbums extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { accountId, mediaType } = this.props
|
||||||
|
|
||||||
|
if (accountId && accountId !== -1) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (
|
||||||
|
(nextProps.accountId && nextProps.accountId !== this.props.accountId) ||
|
||||||
|
(nextProps.accountId && nextProps.mediaType !== this.props.mediaType)
|
||||||
|
) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {
|
||||||
|
mediaType: nextProps.mediaType,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleScrollToBottom = () => {
|
||||||
|
if (this.props.hasMore) {
|
||||||
|
this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleScroll = (e) => {
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||||
|
const offset = scrollHeight - scrollTop - clientHeight
|
||||||
|
|
||||||
|
if (150 > offset && !this.props.isLoading) {
|
||||||
|
this.handleScrollToBottom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadMore = (maxId) => {
|
||||||
|
if (this.props.accountId && this.props.accountId !== -1) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, {
|
||||||
|
maxId,
|
||||||
|
mediaType: this.props.mediaType,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoadOlder = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.handleScrollToBottom()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
attachments,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
intl,
|
||||||
|
account,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div
|
||||||
|
role='feed'
|
||||||
|
onScroll={this.handleScroll}
|
||||||
|
className={[_s.d, _s.flexRow, _s.flexWrap, _s.py5, _s.px5].join(' ')}
|
||||||
|
>
|
||||||
|
|
||||||
|
{
|
||||||
|
attachments.map((attachment, i) => (
|
||||||
|
<MediaItem
|
||||||
|
key={attachment.get('id')}
|
||||||
|
attachment={attachment}
|
||||||
|
account={account}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
isLoading && attachments.size === 0 &&
|
||||||
|
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||||
|
<MediaGalleryPlaceholder />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!isLoading && attachments.size === 0 &&
|
||||||
|
<ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
hasMore && !(isLoading && attachments.size === 0) &&
|
||||||
|
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
||||||
|
}
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
none: { id: 'account_gallery.none', defaultMessage: 'No media to show.' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { account, mediaType }) => {
|
||||||
|
const accountId = !!account ? account.get('id') : -1
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId,
|
||||||
|
attachments: getAccountGallery(state, accountId, mediaType),
|
||||||
|
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
|
||||||
|
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
AccountAlbums.propTypes = {
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
|
accountId: PropTypes.string,
|
||||||
|
attachments: ImmutablePropTypes.list.isRequired,
|
||||||
|
isLoading: PropTypes.bool,
|
||||||
|
hasMore: PropTypes.bool,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
mediaType: PropTypes.oneOf([
|
||||||
|
'photo',
|
||||||
|
'video',
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(AccountAlbums))
|
|
@ -0,0 +1,73 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import { changeListEditorTitle, submitListEditor } from '../actions/lists'
|
||||||
|
import { closeModal } from '../actions/modal'
|
||||||
|
import { MODAL_LIST_CREATE } from '../constants'
|
||||||
|
import Button from '../components/button'
|
||||||
|
import Input from '../components/input'
|
||||||
|
import Form from '../components/form'
|
||||||
|
import Text from '../components/text'
|
||||||
|
|
||||||
|
class BookmarkCollectionCreate extends React.PureComponent {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
value: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange = (value) => {
|
||||||
|
this.setState({ value })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnSubmit = () => {
|
||||||
|
this.props.onSubmit()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { disabled, isModal } = this.props
|
||||||
|
const { value } = this.state
|
||||||
|
|
||||||
|
const isDisabled = !value || disabled
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form>
|
||||||
|
<Input
|
||||||
|
title='Title'
|
||||||
|
placeholder='Bookmark collection title'
|
||||||
|
value={value}
|
||||||
|
onChange={this.onChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
onClick={this.handleOnSubmit}
|
||||||
|
className={[_s.mt10].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='inherit' align='center'>
|
||||||
|
Create
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
disabled: state.getIn(['listEditor', 'isSubmitting']),
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, { isModal }) => ({
|
||||||
|
onSubmit() {
|
||||||
|
if (isModal) dispatch(closeModal(MODAL_LIST_CREATE))
|
||||||
|
dispatch(submitListEditor(true))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
BookmarkCollectionCreate.propTypes = {
|
||||||
|
onSubmit: PropTypes.func.isRequired,
|
||||||
|
isModal: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(BookmarkCollectionCreate)
|
|
@ -3,8 +3,18 @@ import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import {
|
||||||
|
MODAL_BOOKMARK_COLLECTION_CREATE,
|
||||||
|
} from '../constants'
|
||||||
|
import {
|
||||||
|
meUsername,
|
||||||
|
} from '../initial_state'
|
||||||
import { fetchBookmarkCollections } from '../actions/bookmarks'
|
import { fetchBookmarkCollections } from '../actions/bookmarks'
|
||||||
|
import { openModal } from '../actions/modal'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import Button from '../components/button'
|
||||||
|
import Text from '../components/text'
|
||||||
import List from '../components/list'
|
import List from '../components/list'
|
||||||
|
|
||||||
class BookmarkCollections extends ImmutablePureComponent {
|
class BookmarkCollections extends ImmutablePureComponent {
|
||||||
|
@ -13,6 +23,10 @@ class BookmarkCollections extends ImmutablePureComponent {
|
||||||
this.props.onFetchBookmarkCollections()
|
this.props.onFetchBookmarkCollections()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleOpenModal = () => {
|
||||||
|
this.props.onOpenModal()
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
isLoading,
|
isLoading,
|
||||||
|
@ -24,19 +38,32 @@ class BookmarkCollections extends ImmutablePureComponent {
|
||||||
return <ColumnIndicator type='error' message='Error fetching bookmark collections' />
|
return <ColumnIndicator type='error' message='Error fetching bookmark collections' />
|
||||||
}
|
}
|
||||||
|
|
||||||
const listItems = shortcuts.map((s) => ({
|
const listItems = [{ to: `/${meUsername}/bookmark_collections/bookmarks`, title: 'Bookmarks' }].concat(!!bookmarkCollections ? bookmarkCollections.map((s) => ({
|
||||||
to: s.get('to'),
|
to: s.get('to'),
|
||||||
title: s.get('title'),
|
title: s.get('title'),
|
||||||
image: s.get('image'),
|
})) : [])
|
||||||
}))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Block>
|
||||||
|
<div className={[_s.d, _s.px15, _s.py10].join(' ')}>
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.aiCenter].join(' ')}>
|
||||||
|
<Text size='extraLarge' weight='bold'>Bookmark Collections</Text>
|
||||||
|
<Button
|
||||||
|
className={[_s.px10, _s.mlAuto].join(' ')}
|
||||||
|
onClick={this.handleOpenModal}
|
||||||
|
backgroundColor='tertiary'
|
||||||
|
color='tertiary'
|
||||||
|
icon='add'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<List
|
<List
|
||||||
scrollKey='bookmark-collections'
|
scrollKey='bookmark-collections'
|
||||||
emptyMessage='You have no bookmark collections'
|
emptyMessage='You have no bookmark collections'
|
||||||
items={listItems}
|
items={listItems}
|
||||||
showLoading={isLoading}
|
showLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
</Block>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +76,9 @@ const mapStateToProps = (state) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onOpenModal() {
|
||||||
|
dispatch(openModal(MODAL_BOOKMARK_COLLECTION_CREATE))
|
||||||
|
},
|
||||||
onFetchBookmarkCollections() {
|
onFetchBookmarkCollections() {
|
||||||
dispatch(fetchBookmarkCollections())
|
dispatch(fetchBookmarkCollections())
|
||||||
},
|
},
|
||||||
|
@ -58,6 +88,7 @@ BookmarkCollections.propTypes = {
|
||||||
isLoading: PropTypes.bool.isRequired,
|
isLoading: PropTypes.bool.isRequired,
|
||||||
isError: PropTypes.bool.isRequired,
|
isError: PropTypes.bool.isRequired,
|
||||||
onFetchBookmarkCollections: PropTypes.func.isRequired,
|
onFetchBookmarkCollections: PropTypes.func.isRequired,
|
||||||
|
onOpenModal: PropTypes.func.isRequired,
|
||||||
bookmarkCollections: ImmutablePropTypes.list,
|
bookmarkCollections: ImmutablePropTypes.list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ import ColumnIndicator from '../components/column_indicator'
|
||||||
class BookmarkedStatuses extends ImmutablePureComponent {
|
class BookmarkedStatuses extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.dispatch(fetchBookmarkedStatuses())
|
this.props.dispatch(fetchBookmarkedStatuses(this.props.bookmarkCollectionId))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadMore = debounce(() => {
|
handleLoadMore = debounce(() => {
|
||||||
this.props.dispatch(expandBookmarkedStatuses())
|
this.props.dispatch(expandBookmarkedStatuses(this.props.bookmarkCollectionId))
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -46,14 +46,13 @@ class BookmarkedStatuses extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username } }) => {
|
const mapStateToProps = (state, { params: { username, bookmarkCollectionId } }) => ({
|
||||||
return {
|
bookmarkCollectionId,
|
||||||
isMyAccount: (username.toLowerCase() === meUsername.toLowerCase()),
|
isMyAccount: (username.toLowerCase() === meUsername.toLowerCase()),
|
||||||
statusIds: state.getIn(['status_lists', 'bookmarks', 'items']),
|
statusIds: state.getIn(['status_lists', 'bookmarks', 'items']),
|
||||||
isLoading: state.getIn(['status_lists', 'bookmarks', 'isLoading'], true),
|
isLoading: state.getIn(['status_lists', 'bookmarks', 'isLoading'], true),
|
||||||
hasMore: !!state.getIn(['status_lists', 'bookmarks', 'next']),
|
hasMore: !!state.getIn(['status_lists', 'bookmarks', 'next']),
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
BookmarkedStatuses.propTypes = {
|
BookmarkedStatuses.propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -21,7 +21,6 @@ class ChatConversationCreate extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnCreateChatConversation = (accountId) => {
|
handleOnCreateChatConversation = (accountId) => {
|
||||||
console.log("handleOnCreateChatConversation:", accountId)
|
|
||||||
this.props.onCreateChatConversation(accountId)
|
this.props.onCreateChatConversation(accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +68,6 @@ const mapStateToProps = (state) => ({
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onChange: (value) => {
|
onChange: (value) => {
|
||||||
console.log("value", value)
|
|
||||||
dispatch(fetchChatConversationAccountSuggestions(value))
|
dispatch(fetchChatConversationAccountSuggestions(value))
|
||||||
},
|
},
|
||||||
onCreateChatConversation: (accountId) => {
|
onCreateChatConversation: (accountId) => {
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { injectIntl, FormattedMessage } from 'react-intl'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
||||||
import debounce from 'lodash.debounce'
|
|
||||||
import { me } from '../initial_state'
|
|
||||||
import {
|
|
||||||
fetchChatMessengerMutes,
|
|
||||||
expandChatMessengerMutes,
|
|
||||||
unmuteChatMessenger,
|
|
||||||
} from '../actions/chat_conversation_accounts'
|
|
||||||
import Account from '../components/account'
|
|
||||||
import Block from '../components/block'
|
|
||||||
import BlockHeading from '../components/block_heading'
|
|
||||||
import ScrollableList from '../components/scrollable_list'
|
|
||||||
|
|
||||||
class ChatConversationMutedAccounts extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
this.props.onFetchMutes()
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLoadMore = debounce(() => {
|
|
||||||
this.props.onExpandMutes()
|
|
||||||
}, 300, { leading: true })
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
accountIds,
|
|
||||||
hasMore,
|
|
||||||
isLoading,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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(' ')}>
|
|
||||||
<BlockHeading title={<FormattedMessage id='navigation_bar.chat_mutes' defaultMessage='Muted chat users' />} />
|
|
||||||
</div>
|
|
||||||
<ScrollableList
|
|
||||||
scrollKey='chat_muted_accounts'
|
|
||||||
onLoadMore={this.handleLoadMore}
|
|
||||||
hasMore={hasMore}
|
|
||||||
isLoading={isLoading}
|
|
||||||
emptyMessage={<FormattedMessage id='empty_column.chat_mutes' defaultMessage="You haven't muted any chat users yet." />}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
accountIds && accountIds.map((id) =>
|
|
||||||
<Account
|
|
||||||
key={`mutes-${id}`}
|
|
||||||
id={id}
|
|
||||||
compact
|
|
||||||
actionIcon='subtract'
|
|
||||||
onActionClick={() => this.props.onRemove(id)}
|
|
||||||
actionTitle='Remove'
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</ScrollableList>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
accountIds: state.getIn(['user_lists', 'chat_mutes', me, 'items']),
|
|
||||||
hasMore: !!state.getIn(['user_lists', 'chat_mutes', me, 'next']),
|
|
||||||
isLoading: state.getIn(['user_lists', 'chat_mutes', me, 'isLoading']),
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
onFetchMutes: () => dispatch(fetchChatMessengerMutes()),
|
|
||||||
onExpandMutes: () => dispatch(expandChatMessengerMutes()),
|
|
||||||
onRemove: (accountId) => dispatch(unmuteChatMessenger(accountId)),
|
|
||||||
})
|
|
||||||
|
|
||||||
ChatConversationMutedAccounts.propTypes = {
|
|
||||||
accountIds: ImmutablePropTypes.list,
|
|
||||||
hasMore: PropTypes.bool,
|
|
||||||
isLoading: PropTypes.bool,
|
|
||||||
onExpandMutes: PropTypes.func.isRequired,
|
|
||||||
onFetchMutes: PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ChatConversationMutedAccounts))
|
|
|
@ -30,14 +30,17 @@ class ComposeDestinationHeader extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, isModal } = this.props
|
const { account, isModal, formLocation } = this.props
|
||||||
|
|
||||||
|
const isIntroduction = formLocation === 'introduction'
|
||||||
const title = 'Post to timeline'
|
const title = 'Post to timeline'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.bgPrimary, _s.w100PC, _s.h40PX, _s.pr15].join(' ')}>
|
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.bgPrimary, _s.w100PC, _s.h40PX, _s.pr15].join(' ')}>
|
||||||
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.pl15, _s.flexGrow1, _s.mrAuto, _s.h40PX].join(' ')}>
|
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.pl15, _s.flexGrow1, _s.mrAuto, _s.h40PX].join(' ')}>
|
||||||
<Avatar account={account} size={28} />
|
<Avatar account={account} size={28} />
|
||||||
|
{
|
||||||
|
!isIntroduction &&
|
||||||
<div className={[_s.ml15].join(' ')}>
|
<div className={[_s.ml15].join(' ')}>
|
||||||
<Button
|
<Button
|
||||||
isNarrow
|
isNarrow
|
||||||
|
@ -55,9 +58,10 @@ class ComposeDestinationHeader extends ImmutablePureComponent {
|
||||||
</Text>
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
!isModal &&
|
!isModal && !isIntroduction &&
|
||||||
<Button
|
<Button
|
||||||
isText
|
isText
|
||||||
isNarrow
|
isNarrow
|
||||||
|
@ -89,6 +93,7 @@ ComposeDestinationHeader.propTypes = {
|
||||||
isModal: PropTypes.bool,
|
isModal: PropTypes.bool,
|
||||||
onOpenModal: PropTypes.func.isRequired,
|
onOpenModal: PropTypes.func.isRequired,
|
||||||
onOpenPopover: PropTypes.func.isRequired,
|
onOpenPopover: PropTypes.func.isRequired,
|
||||||
|
formLocation: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(ComposeDestinationHeader)
|
export default connect(null, mapDispatchToProps)(ComposeDestinationHeader)
|
|
@ -57,6 +57,7 @@ class ComposeExtraButtonList extends React.PureComponent {
|
||||||
const isXS = width <= BREAKPOINT_EXTRA_SMALL
|
const isXS = width <= BREAKPOINT_EXTRA_SMALL
|
||||||
const isStandalone = formLocation === 'standalone'
|
const isStandalone = formLocation === 'standalone'
|
||||||
const isTimeline = formLocation === 'timeline'
|
const isTimeline = formLocation === 'timeline'
|
||||||
|
const isIntroduction = formLocation === 'introduction'
|
||||||
const small = (!isModal && isXS && !isStandalone) || isTimeline
|
const small = (!isModal && isXS && !isStandalone) || isTimeline
|
||||||
|
|
||||||
console.log("small, formLocation:", small, formLocation)
|
console.log("small, formLocation:", small, formLocation)
|
||||||
|
@ -84,8 +85,8 @@ class ComposeExtraButtonList extends React.PureComponent {
|
||||||
<UploadButton small={small} />
|
<UploadButton small={small} />
|
||||||
<EmojiPickerButton isMatch={isMatch} small={small} />
|
<EmojiPickerButton isMatch={isMatch} small={small} />
|
||||||
{ !edit && <PollButton small={small} /> }
|
{ !edit && <PollButton small={small} /> }
|
||||||
<StatusVisibilityButton small={small} />
|
{ !isIntroduction && <StatusVisibilityButton small={small} /> }
|
||||||
<SpoilerButton small={small} />
|
{ !isIntroduction && <SpoilerButton small={small} /> }
|
||||||
{ !hidePro && !edit && <SchedulePostButton small={small} /> }
|
{ !hidePro && !edit && <SchedulePostButton small={small} /> }
|
||||||
{ !hidePro && !edit && <ExpiresPostButton small={small} /> }
|
{ !hidePro && !edit && <ExpiresPostButton small={small} /> }
|
||||||
{ !hidePro && !isXS && <RichTextEditorButton small={small} /> }
|
{ !hidePro && !isXS && <RichTextEditorButton small={small} /> }
|
||||||
|
|
|
@ -273,7 +273,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
<div className={[_s.d, _s.calcMaxH410PX, _s.overflowYScroll].join(' ')}>
|
<div className={[_s.d, _s.calcMaxH410PX, _s.overflowYScroll].join(' ')}>
|
||||||
|
|
||||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||||
<ComposeDestinationHeader account={account} isModal={isModalOpen} />
|
<ComposeDestinationHeader formLocation={formLocation} account={account} isModal={isModalOpen} />
|
||||||
</Responsive>
|
</Responsive>
|
||||||
|
|
||||||
<div className={containerClasses} ref={this.setForm} onClick={this.handleClick}>
|
<div className={containerClasses} ref={this.setForm} onClick={this.handleClick}>
|
||||||
|
|
|
@ -25,7 +25,9 @@ import Text from '../components/text'
|
||||||
import {
|
import {
|
||||||
AccountTimeline,
|
AccountTimeline,
|
||||||
Compose,
|
Compose,
|
||||||
|
GroupTimeline,
|
||||||
LikedStatuses,
|
LikedStatuses,
|
||||||
|
ListTimeline,
|
||||||
HomeTimeline,
|
HomeTimeline,
|
||||||
Notifications,
|
Notifications,
|
||||||
HashtagTimeline,
|
HashtagTimeline,
|
||||||
|
@ -73,7 +75,7 @@ class Deck extends React.PureComponent {
|
||||||
|
|
||||||
let Component = null
|
let Component = null
|
||||||
let componentParams = {}
|
let componentParams = {}
|
||||||
let title, icon = ''
|
let title, subtitle, icon = ''
|
||||||
|
|
||||||
switch (deckColumn) {
|
switch (deckColumn) {
|
||||||
case 'notifications':
|
case 'notifications':
|
||||||
|
@ -123,18 +125,32 @@ class Deck extends React.PureComponent {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// : todo :
|
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
if (deckColumn.indexOf('user.') > -1) {
|
if (deckColumn.indexOf('user.') > -1) {
|
||||||
|
|
||||||
} else if (deckColumn.indexOf('list.') > -1) {
|
} else if (deckColumn.indexOf('list.') > -1) {
|
||||||
|
const listId = deckColumn.replace('list.', '')
|
||||||
|
title = 'List'
|
||||||
|
subtitle = listId
|
||||||
|
icon = 'list'
|
||||||
|
Component = ListTimeline
|
||||||
|
componentParams = { params: { id: listId }}
|
||||||
} else if (deckColumn.indexOf('group.') > -1) {
|
} else if (deckColumn.indexOf('group.') > -1) {
|
||||||
|
const groupId = deckColumn.replace('group.', '')
|
||||||
|
title = 'Group'
|
||||||
|
subtitle = groupId
|
||||||
|
icon = 'group'
|
||||||
|
Component = GroupTimeline
|
||||||
|
componentParams = { params: { id: groupId }}
|
||||||
} else if (deckColumn.indexOf('news.') > -1) {
|
} else if (deckColumn.indexOf('news.') > -1) {
|
||||||
|
// : todo :
|
||||||
} else if (deckColumn.indexOf('hashtag.') > -1) {
|
} else if (deckColumn.indexOf('hashtag.') > -1) {
|
||||||
|
const hashtag = deckColumn.replace('hashtag.', '')
|
||||||
|
title = 'Hashtag'
|
||||||
|
subtitle = hashtag
|
||||||
|
icon = 'apps'
|
||||||
|
Component = HashtagTimeline
|
||||||
|
componentParams = { params: { id: hashtag }}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +162,7 @@ class Deck extends React.PureComponent {
|
||||||
index={index}
|
index={index}
|
||||||
sortIndex={index}
|
sortIndex={index}
|
||||||
>
|
>
|
||||||
<DeckColumn title={title} icon={icon} index={index}>
|
<DeckColumn title={title} subtitle={subtitle} icon={icon} index={index}>
|
||||||
<WrappedBundle component={Component} componentParams={componentParams} />
|
<WrappedBundle component={Component} componentParams={componentParams} />
|
||||||
</DeckColumn>
|
</DeckColumn>
|
||||||
</SortableItem>
|
</SortableItem>
|
||||||
|
@ -158,6 +174,8 @@ class Deck extends React.PureComponent {
|
||||||
|
|
||||||
const isEmpty = gabDeckOrder.size === 0
|
const isEmpty = gabDeckOrder.size === 0
|
||||||
|
|
||||||
|
console.log("gabDeckOrder:", gabDeckOrder)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableContainer
|
<SortableContainer
|
||||||
axis='x'
|
axis='x'
|
||||||
|
|
|
@ -22,10 +22,6 @@ class ListTimeline extends ImmutablePureComponent {
|
||||||
this.handleConnect(this.props.params.id)
|
this.handleConnect(this.props.params.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.handleDisconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.params.id !== this.props.params.id) {
|
if (nextProps.params.id !== this.props.params.id) {
|
||||||
this.handleConnect(nextProps.params.id)
|
this.handleConnect(nextProps.params.id)
|
||||||
|
|
|
@ -193,4 +193,4 @@ ChatMessagesComposeForm.propTypes = {
|
||||||
onSendMessage: PropTypes.func.isRequired,
|
onSendMessage: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapDispatchToProps)(ChatMessagesComposeForm)
|
export default connect(null, mapDispatchToProps)(ChatMessagesComposeForm)
|
|
@ -30,10 +30,6 @@ class ChatSettingsSidebar extends React.PureComponent {
|
||||||
title: 'Blocked Chats',
|
title: 'Blocked Chats',
|
||||||
to: '/messages/blocks',
|
to: '/messages/blocks',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'Muted Chats',
|
|
||||||
to: '/messages/mutes',
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</ResponsiveClassesComponent>
|
</ResponsiveClassesComponent>
|
||||||
|
|
|
@ -56,16 +56,17 @@ import {
|
||||||
AccountGallery,
|
AccountGallery,
|
||||||
AccountTimeline,
|
AccountTimeline,
|
||||||
AccountCommentsTimeline,
|
AccountCommentsTimeline,
|
||||||
|
AlbumCreate,
|
||||||
Assets,
|
Assets,
|
||||||
BlockedAccounts,
|
BlockedAccounts,
|
||||||
BookmarkCollections,
|
BookmarkCollections,
|
||||||
|
BookmarkCollectionCreate,
|
||||||
BookmarkedStatuses,
|
BookmarkedStatuses,
|
||||||
CaliforniaConsumerProtection,
|
CaliforniaConsumerProtection,
|
||||||
CaliforniaConsumerProtectionContact,
|
CaliforniaConsumerProtectionContact,
|
||||||
ChatConversationCreate,
|
ChatConversationCreate,
|
||||||
ChatConversationRequests,
|
ChatConversationRequests,
|
||||||
ChatConversationBlockedAccounts,
|
ChatConversationBlockedAccounts,
|
||||||
ChatConversationMutedAccounts,
|
|
||||||
CommunityTimeline,
|
CommunityTimeline,
|
||||||
Compose,
|
Compose,
|
||||||
Deck,
|
Deck,
|
||||||
|
@ -219,7 +220,6 @@ 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/mutes' exact page={MessagesPage} component={ChatConversationMutedAccounts} 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' }} />
|
||||||
|
@ -278,9 +278,13 @@ class SwitchingArea extends React.PureComponent {
|
||||||
<WrappedRoute path='/:username/videos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ noSidebar: true, mediaType: 'video' }} />
|
<WrappedRoute path='/:username/videos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ noSidebar: true, mediaType: 'video' }} />
|
||||||
<WrappedRoute path='/:username/albums' page={ProfilePage} component={AccountAlbums} content={children} componentParams={{ noSidebar: true, mediaType: 'photo' }} />
|
<WrappedRoute path='/:username/albums' page={ProfilePage} component={AccountAlbums} content={children} componentParams={{ noSidebar: true, mediaType: 'photo' }} />
|
||||||
|
|
||||||
|
<WrappedRoute path='/:username/album_create' page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Create Album', page: 'create-album' }} />
|
||||||
|
<WrappedRoute path='/:username/album_edit/:albumId' page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Create Album', page: 'edit-album' }} />
|
||||||
|
|
||||||
<WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} />
|
<WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} />
|
||||||
<WrappedRoute path='/:username/bookmarks' page={ProfilePage} component={BookmarkCollections} content={children} />
|
<WrappedRoute path='/:username/bookmark_collections' page={ProfilePage} component={BookmarkCollections} content={children} />
|
||||||
<WrappedRoute path='/:username/:bookmarkCollectionId/bookmarks' page={ProfilePage} component={BookmarkedStatuses} content={children} />
|
<WrappedRoute path='/:username/bookmark_collections/create' page={ModalPage} component={BookmarkCollectionCreate} content={children} componentParams={{ title: 'Create Bookmark Collection', page: 'create-bookmark-collection' }} />
|
||||||
|
<WrappedRoute path='/:username/bookmark_collections/:bookmarkCollectionId' page={ProfilePage} component={BookmarkedStatuses} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={StatusFeature} content={children} componentParams={{ title: 'Status', page: 'status' }} />
|
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={StatusFeature} content={children} componentParams={{ title: 'Status', page: 'status' }} />
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,14 @@ export function AboutSidebar() { return import(/* webpackChunkName: "components/
|
||||||
export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') }
|
export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') }
|
||||||
export function AccountCommentsTimeline() { return import(/* webpackChunkName: "features/account_comments_timeline" */'../../account_comments_timeline') }
|
export function AccountCommentsTimeline() { return import(/* webpackChunkName: "features/account_comments_timeline" */'../../account_comments_timeline') }
|
||||||
export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') }
|
export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') }
|
||||||
|
export function AlbumCreate() { return import(/* webpackChunkName: "features/album_create" */'../../album_create') }
|
||||||
|
export function AlbumCreateModal() { return import(/* webpackChunkName: "components/album_create_modal" */'../../../components/modal/album_create_modal') }
|
||||||
export function Assets() { return import(/* webpackChunkName: "features/about/assets" */'../../about/assets') }
|
export function Assets() { return import(/* webpackChunkName: "features/about/assets" */'../../about/assets') }
|
||||||
export function BlockAccountModal() { return import(/* webpackChunkName: "components/block_account_modal" */'../../../components/modal/block_account_modal') }
|
export function BlockAccountModal() { return import(/* webpackChunkName: "components/block_account_modal" */'../../../components/modal/block_account_modal') }
|
||||||
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
||||||
export function BookmarkCollections() { return import(/* webpackChunkName: "features/bookmark_collections" */'../../bookmark_collections') }
|
export function BookmarkCollections() { return import(/* webpackChunkName: "features/bookmark_collections" */'../../bookmark_collections') }
|
||||||
|
export function BookmarkCollectionCreate() { return import(/* webpackChunkName: "features/bookmark_collection_create" */'../../bookmark_collection_create') }
|
||||||
|
export function BookmarkCollectionCreateModal() { return import(/* webpackChunkName: "components/bookmark_collection_create_modal" */'../../../components/modal/bookmark_collection_create_modal') }
|
||||||
export function BookmarkedStatuses() { return import(/* webpackChunkName: "features/bookmarked_statuses" */'../../bookmarked_statuses') }
|
export function BookmarkedStatuses() { return import(/* webpackChunkName: "features/bookmarked_statuses" */'../../bookmarked_statuses') }
|
||||||
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
||||||
export function CaliforniaConsumerProtection() { return import(/* webpackChunkName: "features/california_consumer_protection" */'../../about/california_consumer_protection') }
|
export function CaliforniaConsumerProtection() { return import(/* webpackChunkName: "features/california_consumer_protection" */'../../about/california_consumer_protection') }
|
||||||
|
@ -15,13 +19,11 @@ export function ChatConversationBlockedAccounts() { return import(/* webpackChun
|
||||||
export function ChatConversationCreate() { return import(/* webpackChunkName: "features/chat_conversation_create" */'../../chat_conversation_create') }
|
export function ChatConversationCreate() { return import(/* webpackChunkName: "features/chat_conversation_create" */'../../chat_conversation_create') }
|
||||||
export function ChatConversationCreateModal() { return import(/* webpackChunkName: "components/chat_conversation_create_modal" */'../../../components/modal/chat_conversation_create_modal') }
|
export function ChatConversationCreateModal() { return import(/* webpackChunkName: "components/chat_conversation_create_modal" */'../../../components/modal/chat_conversation_create_modal') }
|
||||||
export function ChatConversationDeleteModal() { return import(/* webpackChunkName: "components/chat_conversation_delete_modal" */'../../../components/modal/chat_conversation_delete_modal') }
|
export function ChatConversationDeleteModal() { return import(/* webpackChunkName: "components/chat_conversation_delete_modal" */'../../../components/modal/chat_conversation_delete_modal') }
|
||||||
export function ChatConversationMutedAccounts() { return import(/* webpackChunkName: "features/chat_conversation_muted_accounts" */'../../chat_conversation_muted_accounts') }
|
|
||||||
export function ChatConversationOptionsPopover() { return import(/* webpackChunkName: "components/chat_conversation_options_popover" */'../../../components/popover/chat_conversation_options_popover') }
|
export function ChatConversationOptionsPopover() { return import(/* webpackChunkName: "components/chat_conversation_options_popover" */'../../../components/popover/chat_conversation_options_popover') }
|
||||||
export function ChatConversationRequests() { return import(/* webpackChunkName: "features/chat_conversation_requests" */'../../chat_conversation_requests') }
|
export function ChatConversationRequests() { return import(/* webpackChunkName: "features/chat_conversation_requests" */'../../chat_conversation_requests') }
|
||||||
export function ChatMessageOptionsPopover() { return import(/* webpackChunkName: "components/chat_message_options_popover" */'../../../components/popover/chat_message_options_popover') }
|
export function ChatMessageOptionsPopover() { return import(/* webpackChunkName: "components/chat_message_options_popover" */'../../../components/popover/chat_message_options_popover') }
|
||||||
export function CommentSortingOptionsPopover() { return import(/* webpackChunkName: "components/comment_sorting_options_popover" */'../../../components/popover/comment_sorting_options_popover') }
|
export function CommentSortingOptionsPopover() { return import(/* webpackChunkName: "components/comment_sorting_options_popover" */'../../../components/popover/comment_sorting_options_popover') }
|
||||||
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
||||||
export function CommunityTimelineSettingsModal() { return import(/* webpackChunkName: "components/community_timeline_settings_modal" */'../../../components/modal/community_timeline_settings_modal') }
|
|
||||||
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
||||||
export function ComposeForm() { return import(/* webpackChunkName: "components/compose_form" */'../../compose/components/compose_form') }
|
export function ComposeForm() { return import(/* webpackChunkName: "components/compose_form" */'../../compose/components/compose_form') }
|
||||||
export function ComposeModal() { return import(/* webpackChunkName: "components/compose_modal" */'../../../components/modal/compose_modal') }
|
export function ComposeModal() { return import(/* webpackChunkName: "components/compose_modal" */'../../../components/modal/compose_modal') }
|
||||||
|
@ -70,7 +72,6 @@ export function GroupsCategories() { return import(/* webpackChunkName: "feature
|
||||||
export function GroupCategory() { return import(/* webpackChunkName: "features/group_category" */'../../group_category') }
|
export function GroupCategory() { return import(/* webpackChunkName: "features/group_category" */'../../group_category') }
|
||||||
export function GroupTag() { return import(/* webpackChunkName: "features/group_tag" */'../../group_tag') }
|
export function GroupTag() { return import(/* webpackChunkName: "features/group_tag" */'../../group_tag') }
|
||||||
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
||||||
export function HashtagTimelineSettingsModal() { return import(/* webpackChunkName: "components/hashtag_timeline_settings_modal" */'../../../components/modal/hashtag_timeline_settings_modal') }
|
|
||||||
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
||||||
export function HomeTimelineSettingsModal() { return import(/* webpackChunkName: "components/home_timeline_settings_modal" */'../../../components/modal/home_timeline_settings_modal') }
|
export function HomeTimelineSettingsModal() { return import(/* webpackChunkName: "components/home_timeline_settings_modal" */'../../../components/modal/home_timeline_settings_modal') }
|
||||||
export function HotkeysModal() { return import(/* webpackChunkName: "components/hotkeys_modal" */'../../../components/modal/hotkeys_modal') }
|
export function HotkeysModal() { return import(/* webpackChunkName: "components/hotkeys_modal" */'../../../components/modal/hotkeys_modal') }
|
||||||
|
|
|
@ -41,7 +41,7 @@ class DeckLayout extends React.PureComponent {
|
||||||
|
|
||||||
if (isXS) {
|
if (isXS) {
|
||||||
return (
|
return (
|
||||||
<div className={[_s.d, _s.aiCenter, _s.jcCenter, _s.w100PC, _s.h100VH, _s.bgTertiary].join(' ')}>
|
<div className={[_s.d, _s.aiCenter, _s.jcCenter, _s.w100PC, _s.h100VH, _s.bgTertiary, _s.px15, _s.py15].join(' ')}>
|
||||||
<Text className={_s.mb10}>Gab Deck is not available on mobile or tablet devices. Please only access using a desktop computer.</Text>
|
<Text className={_s.mb10}>Gab Deck is not available on mobile or tablet devices. Please only access using a desktop computer.</Text>
|
||||||
<Button to='/home'>Return home</Button>
|
<Button to='/home'>Return home</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -110,7 +110,7 @@ class ProfileLayout extends ImmutablePureComponent {
|
||||||
|
|
||||||
<div className={[_s.d, _s.w100PC, , _s.flexRow, _s.jcEnd, _s.py15].join(' ')}>
|
<div className={[_s.d, _s.w100PC, , _s.flexRow, _s.jcEnd, _s.py15].join(' ')}>
|
||||||
<div className={[_s.d, _s.w100PC, _s.z1].join(' ')}>
|
<div className={[_s.d, _s.w100PC, _s.z1].join(' ')}>
|
||||||
<div className={_s.d}>
|
<div className={[_s.d, _s.boxShadowNone].join(' ')}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { openModal } from '../actions/modal'
|
|
||||||
import PageTitle from '../features/ui/util/page_title'
|
import PageTitle from '../features/ui/util/page_title'
|
||||||
import DefaultLayout from '../layouts/default_layout'
|
import DefaultLayout from '../layouts/default_layout'
|
||||||
import { MODAL_COMMUNITY_TIMELINE_SETTINGS } from '../constants'
|
|
||||||
import {
|
import {
|
||||||
LinkFooter,
|
LinkFooter,
|
||||||
GroupsPanel,
|
GroupsPanel,
|
||||||
|
@ -16,10 +13,6 @@ import {
|
||||||
|
|
||||||
class CommunityPage extends React.PureComponent {
|
class CommunityPage extends React.PureComponent {
|
||||||
|
|
||||||
onOpenCommunityPageSettingsModal = () => {
|
|
||||||
this.props.dispatch(openModal(MODAL_COMMUNITY_TIMELINE_SETTINGS))
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, intl } = this.props
|
const { children, intl } = this.props
|
||||||
|
|
||||||
|
@ -29,12 +22,6 @@ class CommunityPage extends React.PureComponent {
|
||||||
<DefaultLayout
|
<DefaultLayout
|
||||||
title={title}
|
title={title}
|
||||||
page='community'
|
page='community'
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
icon: 'ellipsis',
|
|
||||||
onClick: this.onOpenCommunityPageSettingsModal,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
layout={[
|
layout={[
|
||||||
ProgressPanel,
|
ProgressPanel,
|
||||||
TrendsBreakingPanel,
|
TrendsBreakingPanel,
|
||||||
|
@ -60,4 +47,4 @@ CommunityPage.propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(connect()(CommunityPage))
|
export default injectIntl(CommunityPage)
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { openModal } from '../actions/modal'
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import isObject from 'lodash.isobject'
|
import isObject from 'lodash.isobject'
|
||||||
import PageTitle from '../features/ui/util/page_title'
|
import PageTitle from '../features/ui/util/page_title'
|
||||||
import DefaultLayout from '../layouts/default_layout'
|
import DefaultLayout from '../layouts/default_layout'
|
||||||
import { MODAL_HASHTAG_TIMELINE_SETTINGS } from '../constants'
|
|
||||||
import {
|
import {
|
||||||
LinkFooter,
|
LinkFooter,
|
||||||
ProgressPanel,
|
ProgressPanel,
|
||||||
|
@ -16,17 +13,6 @@ import {
|
||||||
|
|
||||||
class HashtagPage extends React.PureComponent {
|
class HashtagPage extends React.PureComponent {
|
||||||
|
|
||||||
onOpenHashtagPageSettingsModal = () => {
|
|
||||||
const { params } = this.props
|
|
||||||
|
|
||||||
const hashtag = isObject(params) ? params.id : ''
|
|
||||||
if (!hashtag) return
|
|
||||||
|
|
||||||
this.props.dispatch(openModal(MODAL_HASHTAG_TIMELINE_SETTINGS, {
|
|
||||||
hashtag,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
children,
|
children,
|
||||||
|
@ -41,12 +27,6 @@ class HashtagPage extends React.PureComponent {
|
||||||
showBackBtn
|
showBackBtn
|
||||||
title={intl.formatMessage(messages.hashtagTimeline)}
|
title={intl.formatMessage(messages.hashtagTimeline)}
|
||||||
page={`hashtag.${hashtag}`}
|
page={`hashtag.${hashtag}`}
|
||||||
actions={[
|
|
||||||
{
|
|
||||||
icon: 'ellipsis',
|
|
||||||
onClick: this.onOpenHashtagPageSettingsModal,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
layout={[
|
layout={[
|
||||||
ProgressPanel,
|
ProgressPanel,
|
||||||
TrendsBreakingPanel,
|
TrendsBreakingPanel,
|
||||||
|
@ -73,4 +53,4 @@ HashtagPage.propTypes = {
|
||||||
params: PropTypes.object.isRequired,
|
params: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(connect()(HashtagPage))
|
export default injectIntl(HashtagPage)
|
|
@ -10,41 +10,47 @@ import {
|
||||||
ACCOUNT_MUTE_SUCCESS,
|
ACCOUNT_MUTE_SUCCESS,
|
||||||
ACCOUNT_UNMUTE_SUCCESS,
|
ACCOUNT_UNMUTE_SUCCESS,
|
||||||
RELATIONSHIPS_FETCH_SUCCESS,
|
RELATIONSHIPS_FETCH_SUCCESS,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts'
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import {
|
||||||
|
BLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
|
UNBLOCK_CHAT_MESSAGER_SUCCESS,
|
||||||
|
} from '../actions/chat_conversation_accounts'
|
||||||
|
import { Map as ImmutableMap, fromJS } from 'immutable'
|
||||||
|
|
||||||
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
|
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship))
|
||||||
|
|
||||||
const normalizeRelationships = (state, relationships) => {
|
const normalizeRelationships = (state, relationships) => {
|
||||||
relationships.forEach(relationship => {
|
relationships.forEach(relationship => {
|
||||||
state = normalizeRelationship(state, relationship);
|
state = normalizeRelationship(state, relationship)
|
||||||
});
|
})
|
||||||
|
|
||||||
return state;
|
return state
|
||||||
};
|
}
|
||||||
|
|
||||||
const initialState = ImmutableMap();
|
const initialState = ImmutableMap()
|
||||||
|
|
||||||
export default function relationships(state = initialState, action) {
|
export default function relationships(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case ACCOUNT_FOLLOW_REQUEST:
|
case ACCOUNT_FOLLOW_REQUEST:
|
||||||
return state.setIn([action.id, action.locked ? 'requested' : 'following'], true);
|
return state.setIn([action.id, action.locked ? 'requested' : 'following'], true)
|
||||||
case ACCOUNT_FOLLOW_FAIL:
|
case ACCOUNT_FOLLOW_FAIL:
|
||||||
return state.setIn([action.id, action.locked ? 'requested' : 'following'], false);
|
return state.setIn([action.id, action.locked ? 'requested' : 'following'], false)
|
||||||
case ACCOUNT_UNFOLLOW_REQUEST:
|
case ACCOUNT_UNFOLLOW_REQUEST:
|
||||||
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 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:
|
||||||
return normalizeRelationship(state, action.relationship);
|
case BLOCK_CHAT_MESSAGER_SUCCESS:
|
||||||
|
case UNBLOCK_CHAT_MESSAGER_SUCCESS:
|
||||||
|
return normalizeRelationship(state, action.relationship)
|
||||||
case RELATIONSHIPS_FETCH_SUCCESS:
|
case RELATIONSHIPS_FETCH_SUCCESS:
|
||||||
return normalizeRelationships(state, action.relationships);
|
return normalizeRelationships(state, action.relationships)
|
||||||
default:
|
default:
|
||||||
return state;
|
return state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -50,18 +50,12 @@ const initialState = ImmutableMap({
|
||||||
theme: 'white',
|
theme: 'white',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
home: ImmutableMap({
|
// home: ImmutableMap({
|
||||||
shows: ImmutableMap({
|
// shows: ImmutableMap({
|
||||||
reply: true,
|
// reply: true,
|
||||||
repost: true,
|
// repost: true,
|
||||||
}),
|
// }),
|
||||||
}),
|
// }),
|
||||||
|
|
||||||
community: ImmutableMap({
|
|
||||||
shows: ImmutableMap({
|
|
||||||
onlyMedia: false,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultColumns = fromJS([
|
const defaultColumns = fromJS([
|
||||||
|
|
|
@ -5,14 +5,19 @@ import {
|
||||||
} from '../actions/toasts'
|
} from '../actions/toasts'
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'
|
||||||
|
|
||||||
|
const makeMessageFromData = (data) => {
|
||||||
|
return `${data.type}`.split('_').join(' ').toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
const initialState = ImmutableList([])
|
const initialState = ImmutableList([])
|
||||||
|
|
||||||
export default function toasts(state = initialState, action) {
|
export default function toasts(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case TOAST_SHOW:
|
case TOAST_SHOW:
|
||||||
|
console.log("action:", action)
|
||||||
return state.set(state.size, ImmutableMap({
|
return state.set(state.size, ImmutableMap({
|
||||||
key: state.size > 0 ? state.last().get('key') + 1 : 0,
|
key: state.size > 0 ? state.last().get('key') + 1 : 0,
|
||||||
message: 'action.message',
|
message: makeMessageFromData(action.toastData),
|
||||||
type: action.toastType,
|
type: action.toastType,
|
||||||
}))
|
}))
|
||||||
case TOAST_DISMISS:
|
case TOAST_DISMISS:
|
||||||
|
|
|
@ -62,13 +62,6 @@ import {
|
||||||
CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST,
|
CHAT_MESSENGER_BLOCKS_EXPAND_REQUEST,
|
||||||
CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS,
|
CHAT_MESSENGER_BLOCKS_EXPAND_SUCCESS,
|
||||||
CHAT_MESSENGER_BLOCKS_EXPAND_FAIL,
|
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'
|
} from '../actions/chat_conversation_accounts'
|
||||||
import {
|
import {
|
||||||
GROUP_MEMBERS_FETCH_SUCCESS,
|
GROUP_MEMBERS_FETCH_SUCCESS,
|
||||||
|
@ -243,17 +236,6 @@ export default function userLists(state = initialState, action) {
|
||||||
case CHAT_MESSENGER_BLOCKS_EXPAND_FAIL:
|
case CHAT_MESSENGER_BLOCKS_EXPAND_FAIL:
|
||||||
return setListFailed(state, 'chat_blocks', me)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ export const getToasts = createSelector([
|
||||||
|
|
||||||
let arr = []
|
let arr = []
|
||||||
|
|
||||||
base.forEach(item => {
|
base.forEach((item) => {
|
||||||
arr.push({
|
arr.push({
|
||||||
message: item.get('message'),
|
message: item.get('message'),
|
||||||
type: item.get('type'),
|
type: item.get('type'),
|
||||||
|
@ -242,3 +242,19 @@ export const getToasts = createSelector([
|
||||||
|
|
||||||
return arr
|
return arr
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const getListOfGroups = createSelector([
|
||||||
|
(state) => state.get('groups'),
|
||||||
|
(state, { type }) => state.getIn(['group_lists', type, 'items']),
|
||||||
|
], (groups, groupIds) => {
|
||||||
|
console.log("groupIds:", groupIds)
|
||||||
|
let list = ImmutableList()
|
||||||
|
groupIds.forEach((id, i) => {
|
||||||
|
const group = groups.get(`${id}`)
|
||||||
|
console.log("groupIds:", id, i, group)
|
||||||
|
list = list.set(i, group)
|
||||||
|
})
|
||||||
|
console.log("list:", list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
})
|
|
@ -576,6 +576,7 @@ pre {
|
||||||
.h220PX { height: 220px; }
|
.h220PX { height: 220px; }
|
||||||
.h215PX { height: 215px; }
|
.h215PX { height: 215px; }
|
||||||
.h200PX { height: 200px; }
|
.h200PX { height: 200px; }
|
||||||
|
.h172PX { height: 172px; }
|
||||||
.h158PX { height: 158px; }
|
.h158PX { height: 158px; }
|
||||||
.h122PX { height: 122px; }
|
.h122PX { height: 122px; }
|
||||||
.h60PX { height: 60px; }
|
.h60PX { height: 60px; }
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# unread_count :bigint(8) default(0), not null
|
# unread_count :bigint(8) default(0), not null
|
||||||
# chat_message_expiration_policy :string
|
# chat_message_expiration_policy :string
|
||||||
|
# is_muted :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
# : todo : expires
|
# : todo : expires
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
# == Schema Information
|
|
||||||
#
|
|
||||||
# Table name: chat_mutes
|
|
||||||
#
|
|
||||||
# id :bigint(8) not null, primary key
|
|
||||||
# account_id :integer not null
|
|
||||||
# target_account_id :integer not null
|
|
||||||
# created_at :datetime not null
|
|
||||||
# updated_at :datetime not null
|
|
||||||
#
|
|
||||||
|
|
||||||
class ChatMute < ApplicationRecord
|
|
||||||
include Paginable
|
|
||||||
include RelationshipCacheable
|
|
||||||
|
|
||||||
belongs_to :account
|
|
||||||
belongs_to :target_account, class_name: 'Account'
|
|
||||||
|
|
||||||
validates :account_id, uniqueness: { scope: :target_account_id }
|
|
||||||
|
|
||||||
after_commit :remove_blocking_cache
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def remove_blocking_cache
|
|
||||||
Rails.cache.delete("exclude_chat_account_ids_for:#{account_id}")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -22,6 +22,9 @@ class LinkBlock < ApplicationRecord
|
||||||
Addressable::URI.parse(array[0]).normalize
|
Addressable::URI.parse(array[0]).normalize
|
||||||
}
|
}
|
||||||
url = urls.first
|
url = urls.first
|
||||||
|
|
||||||
|
return false if url.nil?
|
||||||
|
|
||||||
link_for_fetch = TagManager.instance.normalize_link(url)
|
link_for_fetch = TagManager.instance.normalize_link(url)
|
||||||
link_for_fetch = link_for_fetch.chomp("/")
|
link_for_fetch = link_for_fetch.chomp("/")
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ class AccountRelationshipsPresenter
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# : todo :
|
||||||
|
# chat muting, chat blocking
|
||||||
|
|
||||||
def cached
|
def cached
|
||||||
return @cached if defined?(@cached)
|
return @cached if defined?(@cached)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class REST::ChatConversationAccountSerializer < ActiveModel::Serializer
|
class REST::ChatConversationAccountSerializer < ActiveModel::Serializer
|
||||||
attributes :id, :is_hidden, :is_approved, :unread_count,
|
attributes :id, :is_hidden, :is_approved, :unread_count,
|
||||||
:is_unread, :chat_conversation_id, :created_at,
|
:is_unread, :chat_conversation_id, :created_at,
|
||||||
:is_blocked, :is_muted, :chat_message_expiration_policy
|
:is_muted, :chat_message_expiration_policy
|
||||||
|
|
||||||
has_many :participant_accounts, key: :other_accounts, serializer: REST::AccountSerializer
|
has_many :participant_accounts, key: :other_accounts, serializer: REST::AccountSerializer
|
||||||
has_one :last_chat_message, serializer: REST::ChatMessageSerializer, unless: :last_chat_message_id?
|
has_one :last_chat_message, serializer: REST::ChatMessageSerializer, unless: :last_chat_message_id?
|
||||||
|
@ -24,12 +24,4 @@ class REST::ChatConversationAccountSerializer < ActiveModel::Serializer
|
||||||
object.unread_count > 0
|
object.unread_count > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_blocked
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_muted
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# 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
|
|
|
@ -52,16 +52,17 @@ class PostChatMessageService < BaseService
|
||||||
@chat_conversation_recipients_accounts = ChatConversationAccount.where(chat_conversation: @chat_conversation)
|
@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 # reset to show unless blocked
|
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
|
||||||
|
|
||||||
# : todo :
|
# check if muting
|
||||||
# check if muting, redis
|
unless recipient.is_muted
|
||||||
payload = InlineRenderer.render(@chat, recipient.account, :chat_message)
|
payload = InlineRenderer.render(@chat, recipient.account, :chat_message)
|
||||||
Redis.current.publish("chat_messages:#{recipient.account.id}", Oj.dump(event: :notification, payload: payload))
|
Redis.current.publish("chat_messages:#{recipient.account.id}", Oj.dump(event: :notification, payload: payload))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
recipient.unread_count = 0
|
recipient.unread_count = 0
|
||||||
end
|
end
|
||||||
|
@ -80,8 +81,10 @@ class PostChatMessageService < BaseService
|
||||||
raise ActiveRecord::RecordInvalid
|
raise ActiveRecord::RecordInvalid
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_message_expiration_date
|
def set_message_expiration_date!
|
||||||
case @account_conversation.expiration_policy
|
@expires_at = nil
|
||||||
|
|
||||||
|
case @account_conversation.chat_message_expiration_policy
|
||||||
when :five_minutes
|
when :five_minutes
|
||||||
@expires_at = 5.minutes
|
@expires_at = 5.minutes
|
||||||
when :sixty_minutes
|
when :sixty_minutes
|
||||||
|
|
|
@ -111,6 +111,8 @@ class PostStatusService < BaseService
|
||||||
return if group_id.blank?
|
return if group_id.blank?
|
||||||
return if @autoJoinGroup
|
return if @autoJoinGroup
|
||||||
|
|
||||||
|
# : todo : check removedaccounts if exist dont allow
|
||||||
|
|
||||||
raise GabSocial::ValidationError, I18n.t('statuses.not_a_member_of_group') if not GroupAccount.where(account: @account, group_id: group_id).exists?
|
raise GabSocial::ValidationError, I18n.t('statuses.not_a_member_of_group') if not GroupAccount.where(account: @account, group_id: group_id).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# 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
|
|
|
@ -228,15 +228,14 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resource :chat_conversation_accounts, only: :show do
|
resource :chat_conversation_accounts, only: :show 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'
|
||||||
resource :muted_chat_accounts, only: :show, controller: 'chat_conversation_accounts/muted_chat_accounts'
|
|
||||||
|
|
||||||
member do
|
member do
|
||||||
get :is_messenger_blocked
|
get :is_messenger_blocked
|
||||||
get :is_messenger_muted
|
get :is_messenger_muted
|
||||||
post :block_messenger
|
post :block_messenger
|
||||||
post :unblock_messenger
|
post :unblock_messenger
|
||||||
post :mute_messenger
|
post :mute_chat_conversation
|
||||||
post :unmute_messenger
|
post :unmute_chat_conversation
|
||||||
post :set_expiration_policy
|
post :set_expiration_policy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -392,6 +391,13 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
get '/', to: 'react#react', as: :homepage
|
get '/', to: 'react#react', as: :homepage
|
||||||
|
|
||||||
|
get '/about', to: 'react#react'
|
||||||
|
get '/about/tos', to: 'react#react'
|
||||||
|
get '/about/privacy', to: 'react#react'
|
||||||
|
get '/about/investors', to: 'react#react'
|
||||||
|
get '/about/dmca', to: 'react#react'
|
||||||
|
get '/about/sales', to: 'react#react'
|
||||||
|
|
||||||
match '*unmatched_route',
|
match '*unmatched_route',
|
||||||
via: :all,
|
via: :all,
|
||||||
to: 'application#raise_not_found',
|
to: 'application#raise_not_found',
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddIsMutedToChatConversationAccounts < ActiveRecord::Migration[5.2]
|
||||||
|
def up
|
||||||
|
safety_assured { add_column :chat_conversation_accounts, :is_muted, :bool, default: false, null: false }
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :chat_conversation_accounts, :is_muted
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
class RemoveChatMutes < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
drop_table :chat_mutes
|
||||||
|
end
|
||||||
|
end
|
11
db/schema.rb
11
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2020_12_15_203113) do
|
ActiveRecord::Schema.define(version: 2020_12_16_051551) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_stat_statements"
|
enable_extension "pg_stat_statements"
|
||||||
|
@ -214,6 +214,7 @@ ActiveRecord::Schema.define(version: 2020_12_15_203113) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.bigint "unread_count", default: 0, null: false
|
t.bigint "unread_count", default: 0, null: false
|
||||||
t.string "chat_message_expiration_policy"
|
t.string "chat_message_expiration_policy"
|
||||||
|
t.boolean "is_muted", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_chat_conversation_accounts_on_account_id"
|
t.index ["account_id"], name: "index_chat_conversation_accounts_on_account_id"
|
||||||
t.index ["chat_conversation_id"], name: "index_chat_conversation_accounts_on_chat_conversation_id"
|
t.index ["chat_conversation_id"], name: "index_chat_conversation_accounts_on_chat_conversation_id"
|
||||||
end
|
end
|
||||||
|
@ -234,14 +235,6 @@ ActiveRecord::Schema.define(version: 2020_12_15_203113) do
|
||||||
t.index ["from_account_id", "chat_conversation_id"], name: "index_chat_messages_on_from_account_id_and_chat_conversation_id"
|
t.index ["from_account_id", "chat_conversation_id"], name: "index_chat_messages_on_from_account_id_and_chat_conversation_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "chat_mutes", force: :cascade do |t|
|
|
||||||
t.integer "account_id", null: false
|
|
||||||
t.integer "target_account_id", null: false
|
|
||||||
t.datetime "created_at", null: false
|
|
||||||
t.datetime "updated_at", null: false
|
|
||||||
t.index ["account_id", "target_account_id"], name: "index_chat_mutes_on_account_id_and_target_account_id", unique: true
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "conversations", force: :cascade do |t|
|
create_table "conversations", force: :cascade do |t|
|
||||||
t.string "uri"
|
t.string "uri"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
|
|
Loading…
Reference in New Issue