From 67eb9d58902bb1567ffe62ced5e3355e3fbcf540 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Sun, 20 Dec 2020 12:27:24 -0500 Subject: [PATCH] Progress Report modal style fix, chat updates, statusserializer revert, display name truncation --- .../api/v1/accounts/statuses_controller.rb | 1 - .../api/v1/chat_conversation_controller.rb | 2 +- .../api/v1/timelines/group_controller.rb | 2 +- .../v1/timelines/preview_card_controller.rb | 2 +- .../api/web/chat_settings_controller.rb | 20 +++++++ app/javascript/gabsocial/actions/accounts.js | 1 - .../gabsocial/actions/chat_conversations.js | 1 - .../gabsocial/actions/chat_messages.js | 2 - .../gabsocial/actions/chat_settings.js | 35 ++++++++++++ app/javascript/gabsocial/actions/timelines.js | 1 - .../gabsocial/components/display_name.js | 14 ++--- .../components/modal/report_modal.js | 11 ++-- .../navigation_bar/chat_navigation_bar_xs.js | 25 ++++++--- .../navigation_bar/profile_navigation_bar.js | 20 ++++--- ...conversation_expiration_options_popover.js | 1 - .../chat_conversation_options_popover.js | 2 + .../popover/chat_settings_popover.js | 54 +++++++++++++++++++ .../components/popover/date_picker_popover.js | 2 +- .../components/popover/popover_root.js | 5 +- app/javascript/gabsocial/components/status.js | 7 ++- .../gabsocial/components/status_check_box.js | 18 +++++-- .../gabsocial/components/status_header.js | 13 +++-- .../user_suggestions_injection.js | 2 +- app/javascript/gabsocial/constants.js | 1 + .../features/chat_conversation_create.js | 50 ++++++++--------- .../features/chat_conversation_mutes.js | 21 ++++++++ .../gabsocial/features/group_members.js | 31 +++++------ .../features/group_removed_accounts.js | 14 +++++ .../components/chat_message_compose_form.js | 11 ++-- .../components/chat_message_scrolling_list.js | 17 ++++-- .../gabsocial/features/messages_settings.js | 2 +- app/javascript/gabsocial/features/status.js | 1 + app/javascript/gabsocial/features/ui/ui.js | 3 +- .../features/ui/util/async_components.js | 2 + .../features/ui/util/wrapped_route.js | 9 ---- .../gabsocial/layouts/messages_layout.js | 29 ++++++++-- app/javascript/gabsocial/pages/modal_page.js | 1 + .../gabsocial/reducers/chat_settings.js | 26 +++++++++ app/javascript/gabsocial/reducers/index.js | 2 + app/javascript/gabsocial/reducers/toasts.js | 1 - app/javascript/gabsocial/selectors/index.js | 6 --- app/javascript/gabsocial/utils/scroll_to.js | 2 +- app/javascript/styles/global.css | 10 ++++ app/models/chat_conversation_account.rb | 8 +++ app/models/home_feed.rb | 1 - app/serializers/rest/status_serializer.rb | 34 ++---------- app/views/admin/accounts/_account.html.haml | 2 + config/navigation.rb | 1 + config/routes.rb | 1 + 49 files changed, 369 insertions(+), 158 deletions(-) create mode 100644 app/controllers/api/web/chat_settings_controller.rb create mode 100644 app/javascript/gabsocial/actions/chat_settings.js create mode 100644 app/javascript/gabsocial/components/popover/chat_settings_popover.js create mode 100644 app/javascript/gabsocial/features/chat_conversation_mutes.js create mode 100644 app/javascript/gabsocial/reducers/chat_settings.js diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index b4563d28..68703ed3 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -9,7 +9,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, - account_id: params[:account_id], relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) end diff --git a/app/controllers/api/v1/chat_conversation_controller.rb b/app/controllers/api/v1/chat_conversation_controller.rb index 8a146645..db796456 100644 --- a/app/controllers/api/v1/chat_conversation_controller.rb +++ b/app/controllers/api/v1/chat_conversation_controller.rb @@ -25,6 +25,7 @@ class Api::V1::ChatConversationController < Api::BaseController # check if chat blocked # check if allow anyone to message then create with approved:true # unique account id, participants + chat_conversation_account = find_or_create_conversation render json: chat_conversation_account, each_serializer: REST::ChatConversationAccountSerializer end @@ -67,7 +68,6 @@ class Api::V1::ChatConversationController < Api::BaseController else @expires_at = nil end - puts "tilly @expires_at: " + @expires_at.inspect @chat_conversation_account.chat_message_expiration_policy = @expires_at @chat_conversation_account.save! render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer diff --git a/app/controllers/api/v1/timelines/group_controller.rb b/app/controllers/api/v1/timelines/group_controller.rb index 01e0a31b..489ddae3 100644 --- a/app/controllers/api/v1/timelines/group_controller.rb +++ b/app/controllers/api/v1/timelines/group_controller.rb @@ -13,7 +13,7 @@ class Api::V1::Timelines::GroupController < Api::BaseController if current_user render json: @statuses, each_serializer: REST::StatusSerializer, - group_id: params[:id], + group_id: params[:id], # : todo : relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id, group_id: @group.id) else render json: @statuses, each_serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/timelines/preview_card_controller.rb b/app/controllers/api/v1/timelines/preview_card_controller.rb index 4734ea2a..4b7fcf00 100644 --- a/app/controllers/api/v1/timelines/preview_card_controller.rb +++ b/app/controllers/api/v1/timelines/preview_card_controller.rb @@ -10,7 +10,7 @@ class Api::V1::Timelines::PreviewCardController < Api::BaseController def show render json: @statuses, each_serializer: REST::StatusSerializer, - preview_card_id: params[:id], + preview_card_id: params[:id], # : todo : relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id) end diff --git a/app/controllers/api/web/chat_settings_controller.rb b/app/controllers/api/web/chat_settings_controller.rb new file mode 100644 index 00000000..32fee0ba --- /dev/null +++ b/app/controllers/api/web/chat_settings_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Api::Web::ChatSettingsController < Api::Web::BaseController + before_action :require_user! + + def update + setting.data = params[:data] + setting.save! + + # todo validate all data objects + + render_empty_success + end + + private + + def setting + @_setting ||= ::Web::Setting.where(user: current_user).first_or_initialize(user: current_user) + end +end diff --git a/app/javascript/gabsocial/actions/accounts.js b/app/javascript/gabsocial/actions/accounts.js index 7677afd9..702cc345 100644 --- a/app/javascript/gabsocial/actions/accounts.js +++ b/app/javascript/gabsocial/actions/accounts.js @@ -162,7 +162,6 @@ export const followAccount = (id, reblogs = true) => (dispatch, getState) => { dispatch(followAccountRequest(id, locked)) api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then((response) => { - console.log("response:", response) dispatch(followAccountSuccess(response.data, alreadyFollowing)) }).catch((error) => { dispatch(followAccountFail(error, locked)) diff --git a/app/javascript/gabsocial/actions/chat_conversations.js b/app/javascript/gabsocial/actions/chat_conversations.js index 3386009d..777a099c 100644 --- a/app/javascript/gabsocial/actions/chat_conversations.js +++ b/app/javascript/gabsocial/actions/chat_conversations.js @@ -258,7 +258,6 @@ export const deleteChatConversation = (chatConversationId) => (dispatch, getStat dispatch(deleteChatConversationRequest(conversationId)) api(getState).delete(`/api/v1/chat_conversation/${chatConversationId}`).then((response) => { - console.log("chat_conversations delete response: ", response) dispatch(deleteChatConversationSuccess()) }).catch((error) => { dispatch(deleteChatConversationFail(error)) diff --git a/app/javascript/gabsocial/actions/chat_messages.js b/app/javascript/gabsocial/actions/chat_messages.js index 43e85700..41844f15 100644 --- a/app/javascript/gabsocial/actions/chat_messages.js +++ b/app/javascript/gabsocial/actions/chat_messages.js @@ -62,11 +62,9 @@ const sendChatMessageFail = (error) => ({ export const manageIncomingChatMessage = (chatMessage) => (dispatch, getState) => { if (!chatMessage) return - console.log("chatMessage:", chatMessage) dispatch(sendChatMessageSuccess(chatMessage)) const isOnline = getState().getIn(['chat_conversation_messages', chatMessage.chat_conversation_id, 'online']) - console.log("isOnline: ", isOnline) // : todo : // Check if is online for conversation, if not increase total/convo unread count diff --git a/app/javascript/gabsocial/actions/chat_settings.js b/app/javascript/gabsocial/actions/chat_settings.js new file mode 100644 index 00000000..7eab5433 --- /dev/null +++ b/app/javascript/gabsocial/actions/chat_settings.js @@ -0,0 +1,35 @@ +import api from '../api' +import debounce from 'lodash.debounce' +import { me } from '../initial_state' + +export const CHAT_SETTING_CHANGE = 'CHAT_SETTING_CHANGE' +export const CHAT_SETTING_SAVE = 'CHAT_SETTING_SAVE' + +export const changeChatSetting = (path, value) => (dispatch) => { + dispatch({ + type: CHAT_SETTING_CHANGE, + path, + value, + }) + + dispatch(saveChatSettings()) +} + +/** + * + */ +export const saveChatSettings = () => (dispatch, getState) => { + debouncedChatSettingsSave(dispatch, getState) +} + +const debouncedChatSettingsSave = debounce((dispatch, getState) => { + if (!me) return + + if (getState().getIn(['chat_settings', 'saved'])) return + + const data = getState().get('chat_settings').filter((_, path) => path !== 'saved').toJS() + + api().put('/api/web/chat_settings', { data }) + .then(() => dispatch({ type: CHAT_SETTING_SAVE })) + .catch(() => { /* */ }) +}, 350, { trailing: true }) diff --git a/app/javascript/gabsocial/actions/timelines.js b/app/javascript/gabsocial/actions/timelines.js index 2429c6d6..08a91207 100644 --- a/app/javascript/gabsocial/actions/timelines.js +++ b/app/javascript/gabsocial/actions/timelines.js @@ -151,7 +151,6 @@ export const expandTimeline = (timelineId, path, params = {}, done = noop) => (d dispatch(expandTimelineRequest(timelineId, isLoadingMore)) api(getState).get(path, { params }).then((response) => { - console.log("response:", response) const next = getLinks(response).refs.find(link => link.rel === 'next') dispatch(importFetchedStatuses(response.data)) dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingRecent, isLoadingMore)) diff --git a/app/javascript/gabsocial/components/display_name.js b/app/javascript/gabsocial/components/display_name.js index 3c3bd16f..16926bea 100644 --- a/app/javascript/gabsocial/components/display_name.js +++ b/app/javascript/gabsocial/components/display_name.js @@ -106,8 +106,7 @@ class DisplayName extends ImmutablePureComponent { const usernameClasses = CX({ text: 1, displayFlex: 1, - flexNormal: 1, - flexShrink1: 1, + flexShrink0: 1, overflowWrapBreakWord: 1, textOverflowEllipsis: 1, cSecondary: 1, @@ -131,17 +130,10 @@ class DisplayName extends ImmutablePureComponent { const isFollowedBy = (me !== accountId && account.getIn(['relationship', 'followed_by'])) if (isFollowedBy) { - relationshipLabel = 'Follows you'//intl.formatMessage(messages.accountFollowsYou) + relationshipLabel = 'Follows you' } } - // { - // /* : todo : audio-mute, bot - // account.getIn(['relationship', 'muting']) - // */ - // } - // bot: { id: 'account.badges.bot', defaultMessage: 'Bot' }, - return (
- + @@ -95,13 +96,13 @@ class ReportModal extends ImmutablePureComponent { -
+
{ - statusIds.map(statusId => ( - + statusIds.map((statusId) => ( + )) }
diff --git a/app/javascript/gabsocial/components/navigation_bar/chat_navigation_bar_xs.js b/app/javascript/gabsocial/components/navigation_bar/chat_navigation_bar_xs.js index 3b15a3d0..a1df6f7d 100644 --- a/app/javascript/gabsocial/components/navigation_bar/chat_navigation_bar_xs.js +++ b/app/javascript/gabsocial/components/navigation_bar/chat_navigation_bar_xs.js @@ -33,6 +33,9 @@ class ChatNavigationBar extends React.PureComponent { const otherAccounts = chatConversation ? chatConversation.get('other_accounts') : null const nameHTML = !!otherAccounts ? otherAccounts.get(0).get('display_name_html') : '' + // : todo : + // fix padding on mobile device + return (
@@ -46,23 +49,29 @@ class ChatNavigationBar extends React.PureComponent { iconClassName={[_s.mr5, _s.fillNavigation].join(' ')} /> -
- - -
- +
+
+ +
+ +
+
+
diff --git a/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js b/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js index 7a34635e..5c744774 100644 --- a/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js +++ b/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js @@ -24,6 +24,9 @@ class ProfileNavigationBar extends React.PureComponent { render() { const { titleHTML } = this.props + // : todo : + // fix padding on mobile device + return (
@@ -36,12 +39,17 @@ class ProfileNavigationBar extends React.PureComponent { iconClassName={[_s.mr5, _s.fillNavigation].join(' ')} /> -
- - -
- - +
+
+ +
+ +
+
+
diff --git a/app/javascript/gabsocial/components/popover/chat_conversation_expiration_options_popover.js b/app/javascript/gabsocial/components/popover/chat_conversation_expiration_options_popover.js index 7ed1409b..7aa64c08 100644 --- a/app/javascript/gabsocial/components/popover/chat_conversation_expiration_options_popover.js +++ b/app/javascript/gabsocial/components/popover/chat_conversation_expiration_options_popover.js @@ -35,7 +35,6 @@ class ChatConversationExpirationOptionsPopover extends React.PureComponent { isXS, } = this.props - console.log("expiresAtValue:", expiresAtValue) if (!chatConversationId) return
const listItems = [ diff --git a/app/javascript/gabsocial/components/popover/chat_conversation_options_popover.js b/app/javascript/gabsocial/components/popover/chat_conversation_options_popover.js index 4e1c1ddf..93393c8b 100644 --- a/app/javascript/gabsocial/components/popover/chat_conversation_options_popover.js +++ b/app/javascript/gabsocial/components/popover/chat_conversation_options_popover.js @@ -6,6 +6,7 @@ import { connect } from 'react-redux' import { closePopover } from '../../actions/popover' import { openModal } from '../../actions/modal' import { hideChatConversation } from '../../actions/chat_conversations' +import { setChatConversationSelected } from '../../actions/chats' import { muteChatConversation, unmuteChatConversation, @@ -107,6 +108,7 @@ const mapDispatchToProps = (dispatch, { chatConversationId }) => ({ }, onHide() { dispatch(hideChatConversation(chatConversationId)) + dispatch(setChatConversationSelected(null)) }, onMute() { dispatch(muteChatConversation(chatConversationId)) diff --git a/app/javascript/gabsocial/components/popover/chat_settings_popover.js b/app/javascript/gabsocial/components/popover/chat_settings_popover.js new file mode 100644 index 00000000..e3c92bca --- /dev/null +++ b/app/javascript/gabsocial/components/popover/chat_settings_popover.js @@ -0,0 +1,54 @@ +import React from 'react' +import PropTypes from 'prop-types' +import PopoverLayout from './popover_layout' +import List from '../list' + +class ChatSettingsPopover extends React.PureComponent { + + handleOnClosePopover = () => { + this.props.onClose() + } + + render() { + const { intl, isXS } = this.props + + return ( + + this.handleOnClosePopover(), + }, + { + title: 'Message Requests', + to: '/messages/requests', + onClick: () => this.handleOnClosePopover(), + }, + { + title: 'Blocked Chat Messengers', + to: '/messages/blocks', + onClick: () => this.handleOnClosePopover(), + }, + { + title: 'Muted Conversations', + to: '/messages/muted_conversations', + onClick: () => this.handleOnClosePopover(), + }, + ]} + /> + + ) + } +} + + +ChatSettingsPopover.propTypes = { + onClose: PropTypes.func.isRequired, + isXS: PropTypes.bool, +} + +export default ChatSettingsPopover diff --git a/app/javascript/gabsocial/components/popover/date_picker_popover.js b/app/javascript/gabsocial/components/popover/date_picker_popover.js index eff857ea..4fadb79e 100644 --- a/app/javascript/gabsocial/components/popover/date_picker_popover.js +++ b/app/javascript/gabsocial/components/popover/date_picker_popover.js @@ -70,7 +70,7 @@ class DatePickerPopover extends React.PureComponent {
diff --git a/app/javascript/gabsocial/components/popover/popover_root.js b/app/javascript/gabsocial/components/popover/popover_root.js index a4b31a27..be254907 100644 --- a/app/javascript/gabsocial/components/popover/popover_root.js +++ b/app/javascript/gabsocial/components/popover/popover_root.js @@ -3,6 +3,7 @@ import { POPOVER_CHAT_CONVERSATION_EXPIRATION_OPTIONS, POPOVER_CHAT_CONVERSATION_OPTIONS, POPOVER_CHAT_MESSAGE_OPTIONS, + POPOVER_CHAT_SETTINGS, POPOVER_COMMENT_SORTING_OPTIONS, POPOVER_COMPOSE_POST_DESTINATION, POPOVER_DATE_PICKER, @@ -27,6 +28,7 @@ import { ChatConversationExpirationOptionsPopover, ChatConversationOptionsPopover, ChatMessageOptionsPopover, + ChatSettingsPopover, CommentSortingOptionsPopover, ComposePostDesinationPopover, DatePickerPopover, @@ -65,6 +67,7 @@ const POPOVER_COMPONENTS = { [POPOVER_CHAT_CONVERSATION_EXPIRATION_OPTIONS]: ChatConversationExpirationOptionsPopover, [POPOVER_CHAT_CONVERSATION_OPTIONS]: ChatConversationOptionsPopover, [POPOVER_CHAT_MESSAGE_OPTIONS]: ChatMessageOptionsPopover, + [POPOVER_CHAT_SETTINGS]: ChatSettingsPopover, [POPOVER_COMMENT_SORTING_OPTIONS]: CommentSortingOptionsPopover, [POPOVER_COMPOSE_POST_DESTINATION]: ComposePostDesinationPopover, [POPOVER_DATE_PICKER]: DatePickerPopover, @@ -161,7 +164,7 @@ class PopoverRoot extends React.PureComponent { renderDelay={150} > { - (Component) => + (Component) => } } diff --git a/app/javascript/gabsocial/components/status.js b/app/javascript/gabsocial/components/status.js index 834f4038..74bdc0f0 100644 --- a/app/javascript/gabsocial/components/status.js +++ b/app/javascript/gabsocial/components/status.js @@ -310,12 +310,15 @@ class Status extends ImmutablePureComponent { commentSortingType, onOpenProModal, isDeckConnected, + statusId, } = this.props // const { height } = this.state let { status } = this.props - if (!status) return null + if (!status) { + return null + } if (isComment && !ancestorStatus && !isChild) { // Wait to load... @@ -331,7 +334,7 @@ class Status extends ImmutablePureComponent { if (ancestorStatus) { status = ancestorStatus } else { - if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') { + if (status.get('reblog', null) !== null) { rebloggedByText = intl.formatMessage( { id: 'status.reposted_by', defaultMessage: '{name} reposted' }, { name: status.getIn(['account', 'acct']) } diff --git a/app/javascript/gabsocial/components/status_check_box.js b/app/javascript/gabsocial/components/status_check_box.js index 64407820..ff54926a 100644 --- a/app/javascript/gabsocial/components/status_check_box.js +++ b/app/javascript/gabsocial/components/status_check_box.js @@ -46,17 +46,27 @@ class StatusCheckBox extends ImmutablePureComponent { } else { media = ( - {Component => } + {Component => ( + + )} ); } } return ( -
-
+
+
- {media} +
+ {media} +
diff --git a/app/javascript/gabsocial/components/status_header.js b/app/javascript/gabsocial/components/status_header.js index 86f2a427..af17d102 100644 --- a/app/javascript/gabsocial/components/status_header.js +++ b/app/javascript/gabsocial/components/status_header.js @@ -79,7 +79,8 @@ class StatusHeader extends ImmutablePureComponent { const textContainerClasses = CX({ d: 1, aiStart: 1, - flexGrow1 :1, + flex1: 1, + overflowHidden: 1, mt5: !isCompact, }) @@ -100,13 +101,15 @@ class StatusHeader extends ImmutablePureComponent {
-
+
- +
+ +
{ @@ -118,7 +121,7 @@ class StatusHeader extends ImmutablePureComponent { icon='ellipsis' iconSize='20px' iconClassName={_s.cSecondary} - className={_s.mlAuto} + className={[_s.mlAuto].join(' ')} onClick={this.handleOpenStatusOptionsPopover} buttonRef={this.setStatusOptionsButton} /> diff --git a/app/javascript/gabsocial/components/timeline_injections/user_suggestions_injection.js b/app/javascript/gabsocial/components/timeline_injections/user_suggestions_injection.js index 75bcc9a4..a35615cf 100644 --- a/app/javascript/gabsocial/components/timeline_injections/user_suggestions_injection.js +++ b/app/javascript/gabsocial/components/timeline_injections/user_suggestions_injection.js @@ -44,7 +44,7 @@ class UserSuggestionsInjection extends ImmutablePureComponent { id={injectionId} title={title} buttonLink='/suggestions' - buttonTitle='See more reccomendations' + buttonTitle='See more recommendations' isXS={isXS} > { diff --git a/app/javascript/gabsocial/constants.js b/app/javascript/gabsocial/constants.js index 52cbcf49..008b3f7a 100644 --- a/app/javascript/gabsocial/constants.js +++ b/app/javascript/gabsocial/constants.js @@ -27,6 +27,7 @@ export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png' export const POPOVER_CHAT_CONVERSATION_OPTIONS = 'CHAT_CONVERSATION_OPTIONS' export const POPOVER_CHAT_MESSAGE_OPTIONS = 'CHAT_MESSAGE_OPTIONS' export const POPOVER_CHAT_CONVERSATION_EXPIRATION_OPTIONS = 'CHAT_CONVERSATION_EXPIRATION_OPTIONS' +export const POPOVER_CHAT_SETTINGS = 'CHAT_SETTINGS' export const POPOVER_COMMENT_SORTING_OPTIONS = 'COMMENT_SORTING_OPTIONS' export const POPOVER_COMPOSE_POST_DESTINATION = 'COMPOSE_POST_DESTINATION' export const POPOVER_DATE_PICKER = 'DATE_PICKER' diff --git a/app/javascript/gabsocial/features/chat_conversation_create.js b/app/javascript/gabsocial/features/chat_conversation_create.js index d1a53cc7..1d986b5f 100644 --- a/app/javascript/gabsocial/features/chat_conversation_create.js +++ b/app/javascript/gabsocial/features/chat_conversation_create.js @@ -37,31 +37,33 @@ class ChatConversationCreate extends React.PureComponent { return (
-
- -
+
+
+ +
-
-
- - Search results ({suggestionsIds.size}) - - { - suggestionsIds && - suggestionsIds.map((accountId) => ( - this.handleOnCreateChatConversation(accountId)} - actionIcon='add' - /> - )) - } +
+
+ + Search results ({suggestionsIds.size}) + + { + suggestionsIds && + suggestionsIds.map((accountId) => ( + this.handleOnCreateChatConversation(accountId)} + actionIcon='add' + /> + )) + } +
diff --git a/app/javascript/gabsocial/features/chat_conversation_mutes.js b/app/javascript/gabsocial/features/chat_conversation_mutes.js new file mode 100644 index 00000000..97d4d858 --- /dev/null +++ b/app/javascript/gabsocial/features/chat_conversation_mutes.js @@ -0,0 +1,21 @@ +import React from 'react' +import PropTypes from 'prop-types' +import BlockHeading from '../components/block_heading' +import ChatConversationsList from './messages/components/chat_conversations_list' + +class ChatConversationMutes extends React.PureComponent { + + render() { + return ( +
+
+ +
+ +
+ ) + } + +} + +export default ChatConversationMutes \ No newline at end of file diff --git a/app/javascript/gabsocial/features/group_members.js b/app/javascript/gabsocial/features/group_members.js index a6a4abcf..605c7335 100644 --- a/app/javascript/gabsocial/features/group_members.js +++ b/app/javascript/gabsocial/features/group_members.js @@ -62,23 +62,20 @@ class GroupMembers extends ImmutablePureComponent { - { - /* : todo : -
- -
- */ - } +
+ +
+
+
+ +
{ this.props.onSendChatMessage(this.state.value, this.props.chatConversationId) + document.querySelector('#gabsocial').focus() + this.onBlur() this.setState({ value: '' }) } @@ -93,7 +95,7 @@ class ChatMessagesComposeForm extends React.PureComponent { expiresAtValue, chatConversationId, } = this.props - const { value } = this.state + const { focused, value } = this.state const disabled = false const textareaClasses = CX({ @@ -141,6 +143,7 @@ class ChatMessagesComposeForm extends React.PureComponent { onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.onKeyDown} + focused={focused} aria-autocomplete='list' maxLength={1600} /> @@ -170,11 +173,11 @@ class ChatMessagesComposeForm extends React.PureComponent { if (isXS) { return ( -
+
-
+
{expiresBtn}
@@ -182,7 +185,7 @@ class ChatMessagesComposeForm extends React.PureComponent { {textarea}
-
+
{button}
diff --git a/app/javascript/gabsocial/features/messages/components/chat_message_scrolling_list.js b/app/javascript/gabsocial/features/messages/components/chat_message_scrolling_list.js index 3a1ba183..1918a01e 100644 --- a/app/javascript/gabsocial/features/messages/components/chat_message_scrolling_list.js +++ b/app/javascript/gabsocial/features/messages/components/chat_message_scrolling_list.js @@ -39,6 +39,7 @@ class ChatMessageScrollingList extends ImmutablePureComponent { componentDidMount () { const { chatConversationId } = this.props this.props.onExpandChatMessages(chatConversationId) + this.scrollToBottom() } componentWillUnmount() { @@ -63,10 +64,10 @@ class ChatMessageScrollingList extends ImmutablePureComponent { } if (prevProps.chatMessageIds.size === 0 && this.props.chatMessageIds.size > 0 && this.scrollContainerRef) { - this.scrollContainerRef.scrollTop = this.scrollContainerRef.scrollHeight + this.scrollToBottom() this.props.onReadChatConversation(this.props.chatConversationId) } else if (prevProps.chatMessageIds.size < this.props.chatMessageIds.size && this.scrollContainerRef) { - this.scrollContainerRef.scrollTop = this.scrollContainerRef.scrollHeight + // this.setScrollTop(this.scrollContainerRef.scrollHeight) } } @@ -114,10 +115,15 @@ class ChatMessageScrollingList extends ImmutablePureComponent { if (!this.scrollContainerRef) return if (this.scrollContainerRef.scrollTop !== newScrollTop) { this.lastScrollWasSynthetic = true + console.log("newScrollTop:", newScrollTop) this.scrollContainerRef.scrollTop = newScrollTop } } + scrollToBottom = () => { + this.messagesEnd.scrollIntoView({ behavior: 'smooth' }); + } + _selectChild(index, align_top) { const container = this.node.node const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`) @@ -163,6 +169,7 @@ class ChatMessageScrollingList extends ImmutablePureComponent { handleWheel = throttle(() => { this.scrollToTopOnMouseIdle = false + this.handleScroll() }, 150, { trailing: true, }) @@ -190,7 +197,7 @@ class ChatMessageScrollingList extends ImmutablePureComponent { handleMouseIdle = () => { if (this.scrollToTopOnMouseIdle) { - this.setScrollTop(0) + this.setScrollTop(this.scrollContainerRef.scrollHeight) } this.mouseMovedRecently = false @@ -320,6 +327,10 @@ class ChatMessageScrollingList extends ImmutablePureComponent { )) } +
{ this.messagesEnd = el }} + />
diff --git a/app/javascript/gabsocial/features/messages_settings.js b/app/javascript/gabsocial/features/messages_settings.js index f00e2755..50820c5d 100644 --- a/app/javascript/gabsocial/features/messages_settings.js +++ b/app/javascript/gabsocial/features/messages_settings.js @@ -38,7 +38,7 @@ class MessagesSettings extends ImmutablePureComponent {
-
+
{ const statusId = props.id || props.params.statusId return { + statusId, status: state.getIn(['statuses', statusId]), } } diff --git a/app/javascript/gabsocial/features/ui/ui.js b/app/javascript/gabsocial/features/ui/ui.js index 879c906c..491a4376 100644 --- a/app/javascript/gabsocial/features/ui/ui.js +++ b/app/javascript/gabsocial/features/ui/ui.js @@ -68,6 +68,7 @@ import { ChatConversationCreate, ChatConversationRequests, ChatConversationBlockedAccounts, + ChatConversationMutes, CommunityTimeline, Compose, Deck, @@ -221,7 +222,7 @@ class SwitchingArea extends React.PureComponent { - + diff --git a/app/javascript/gabsocial/features/ui/util/async_components.js b/app/javascript/gabsocial/features/ui/util/async_components.js index 45017655..3bb8d0f0 100644 --- a/app/javascript/gabsocial/features/ui/util/async_components.js +++ b/app/javascript/gabsocial/features/ui/util/async_components.js @@ -25,7 +25,9 @@ export function ChatConversationDeleteModal() { return import(/* webpackChunkNam 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 ChatConversationExpirationOptionsPopover() { return import(/* webpackChunkName: "components/chat_conversation_expiration_options_popover" */'../../../components/popover/chat_conversation_expiration_options_popover') } +export function ChatConversationMutes() { return import(/* webpackChunkName: "features/chat_conversation_mutes" */'../../chat_conversation_mutes') } export function ChatMessageOptionsPopover() { return import(/* webpackChunkName: "components/chat_message_options_popover" */'../../../components/popover/chat_message_options_popover') } +export function ChatSettingsPopover() { return import(/* webpackChunkName: "components/chat_settings_popover" */'../../../components/popover/chat_settings_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 Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') } diff --git a/app/javascript/gabsocial/features/ui/util/wrapped_route.js b/app/javascript/gabsocial/features/ui/util/wrapped_route.js index 36c27196..f03a2350 100644 --- a/app/javascript/gabsocial/features/ui/util/wrapped_route.js +++ b/app/javascript/gabsocial/features/ui/util/wrapped_route.js @@ -43,15 +43,6 @@ class WrappedRoute extends React.PureComponent { ...rest } = this.props - // : todo : - // api().get('/api/v1/accounts/verify_credentials') - // .then((res) => { - // console.log("res:", res) - // }) - // .catch((err) => { - // console.log("err:", err) - // }) - if (!publicRoute && !me) { const actualUrl = encodeURIComponent(this.props.computedMatch.url) return { diff --git a/app/javascript/gabsocial/layouts/messages_layout.js b/app/javascript/gabsocial/layouts/messages_layout.js index f4342423..87614998 100644 --- a/app/javascript/gabsocial/layouts/messages_layout.js +++ b/app/javascript/gabsocial/layouts/messages_layout.js @@ -3,9 +3,11 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import { me } from '../initial_state' import { openModal } from '../actions/modal' +import { openPopover } from '../actions/popover' import { CX, BREAKPOINT_EXTRA_SMALL, + POPOVER_CHAT_SETTINGS, MODAL_CHAT_CONVERSATION_CREATE, } from '../constants' import { getWindowDimension } from '../utils/is_mobile' @@ -43,6 +45,10 @@ class MessagesLayout extends React.PureComponent { this.setState({ width }) } + handleOpenSettingsOptionsPopover = () => { + this.props.onOpenSettingsOptionsPopover() + } + onClickAdd = () => { this.props.onOpenChatConversationCreateModal() } @@ -74,12 +80,12 @@ class MessagesLayout extends React.PureComponent { }, { icon: 'cog', - to: '/messages/settings', + onClick: this.handleOpenSettingsOptionsPopover, } ]} title={title} /> -
+
{ (isSettings || currentConversationIsRequest) && @@ -98,7 +104,7 @@ class MessagesLayout extends React.PureComponent { return (
-
+
{ currentConversationIsRequest && } @@ -106,7 +112,17 @@ class MessagesLayout extends React.PureComponent {
) } else { - //settings + return ( +
+ +
+
+ {children} +
+ +
+
+ ) } } @@ -174,7 +190,10 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch) => ({ onOpenChatConversationCreateModal() { dispatch(openModal(MODAL_CHAT_CONVERSATION_CREATE)) - } + }, + onOpenSettingsOptionsPopover() { + dispatch(openPopover(POPOVER_CHAT_SETTINGS)) + }, }) MessagesLayout.propTypes = { diff --git a/app/javascript/gabsocial/pages/modal_page.js b/app/javascript/gabsocial/pages/modal_page.js index 33d8a70a..16cbb374 100644 --- a/app/javascript/gabsocial/pages/modal_page.js +++ b/app/javascript/gabsocial/pages/modal_page.js @@ -19,6 +19,7 @@ class ModalPage extends React.PureComponent { return ( 0 ? state.last().get('key') + 1 : 0, message: makeMessageFromData(action.toastData), diff --git a/app/javascript/gabsocial/selectors/index.js b/app/javascript/gabsocial/selectors/index.js index e9838f5c..13de36ed 100644 --- a/app/javascript/gabsocial/selectors/index.js +++ b/app/javascript/gabsocial/selectors/index.js @@ -166,9 +166,6 @@ export const makeGetStatus = () => { quotedStatus = quotedStatus.set('account', accountQuoted); } - - // console.log("group:", group) - //Find ancestor status const regex = (accountRepost || accountBase).get('id') !== me && regexFromFilters(filters); @@ -247,14 +244,11 @@ 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 }) \ No newline at end of file diff --git a/app/javascript/gabsocial/utils/scroll_to.js b/app/javascript/gabsocial/utils/scroll_to.js index 6b7f40ef..1f84d51f 100644 --- a/app/javascript/gabsocial/utils/scroll_to.js +++ b/app/javascript/gabsocial/utils/scroll_to.js @@ -1,5 +1,5 @@ // https://gist.github.com/andjosh/6764939 -export const scrollTo = (element, to, duration) => { +export const scrollTo = (element, to, duration = 0) => { var start = element.scrollTop, change = to - start, currentTime = 0, diff --git a/app/javascript/styles/global.css b/app/javascript/styles/global.css index 1cf7070c..7a80521c 100644 --- a/app/javascript/styles/global.css +++ b/app/javascript/styles/global.css @@ -314,6 +314,7 @@ pre { .flex1 { flex: 1; } .flexGrow1 { flex-grow: 1; } +.flexShrink0 { flex-shrink: 0; } .flexShrink1 { flex-shrink: 1; } .flexRow { flex-direction: row; } @@ -597,6 +598,8 @@ pre { .maxW100PC130PX { max-width: calc(100% - 130px); } .maxW100PC86PX { max-width: calc(100% - 86px); } .maxW100PC42PX { max-width: calc(100% - 42px); } +.maxW100PC30PX { max-width: calc(100% - 30px); } +.maxW320PX { max-width: 320px; } .maxW212PX { max-width: 212px; } .minW330PX { min-width: 330px; } @@ -1314,6 +1317,13 @@ pre { width: 100px !important; } +:global(.react-datepicker__day--disabled), +:global(.react-datepicker__month-text--disabled), +:global(.react-datepicker__quarter-text--disabled) { + cursor: not-allowed; + opacity: 0.2 !important; +} + @media (max-width: 500px) { :global(.react-datepicker) { flex-direction: column !important; diff --git a/app/models/chat_conversation_account.rb b/app/models/chat_conversation_account.rb index 63d0cae9..304ece96 100644 --- a/app/models/chat_conversation_account.rb +++ b/app/models/chat_conversation_account.rb @@ -38,6 +38,8 @@ class ChatConversationAccount < ApplicationRecord belongs_to :chat_conversation belongs_to :last_chat_message, class_name: 'ChatMessage', optional: true + validate :validate_total_limit + def participant_accounts if participant_account_ids.empty? [account] @@ -47,4 +49,10 @@ class ChatConversationAccount < ApplicationRecord end end + private + + def validate_total_limit + # errors.add(:base, I18n.t('scheduled_statuses.over_total_limit', limit: PER_ACCOUNT_APPROVED_LIMIT)) if account.scheduled_statuses.count >= PER_ACCOUNT_APPROVED_LIMIT + end + end diff --git a/app/models/home_feed.rb b/app/models/home_feed.rb index 845bd1c8..1e956b31 100644 --- a/app/models/home_feed.rb +++ b/app/models/home_feed.rb @@ -18,7 +18,6 @@ class HomeFeed < Feed private def from_database(limit, max_id, since_id, min_id) - puts "tilly from_database" Status.as_home_timeline(@account) .paginate_by_id(limit, max_id: max_id, since_id: since_id, min_id: min_id) .reject { |status| FeedManager.instance.filter?(:home, status, @account.id) } diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 0bdddd05..29e19622 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -9,10 +9,6 @@ class REST::StatusSerializer < ActiveModel::Serializer attribute :favourited, if: :current_user? attribute :reblogged, if: :current_user? - attribute :account_id, if: :account_id? - attribute :group_id, if: :group_id? - attribute :preview_card_id, if: :preview_card_id? - attribute :content, unless: :source_requested? attribute :rich_content, unless: :source_requested? attribute :plain_markdown, unless: :source_requested? @@ -20,15 +16,15 @@ class REST::StatusSerializer < ActiveModel::Serializer belongs_to :reblog, serializer: REST::StatusSerializer belongs_to :quote, serializer: REST::StatusSerializer - belongs_to :account, serializer: REST::AccountSerializer, unless: :account_id? - belongs_to :group, serializer: REST::GroupSerializer, unless: :group_id? + belongs_to :account, serializer: REST::AccountSerializer + belongs_to :group, serializer: REST::GroupSerializer has_many :media_attachments, serializer: REST::MediaAttachmentSerializer has_many :ordered_mentions, key: :mentions has_many :tags has_many :emojis, serializer: REST::CustomEmojiSerializer - has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer, unless: :preview_card_id? + has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer def id @@ -51,30 +47,6 @@ class REST::StatusSerializer < ActiveModel::Serializer !current_user.nil? end - def account_id - instance_options[:account_id] - end - - def account_id? - !instance_options[:account_id].nil? - end - - def group_id - instance_options[:group_id] - end - - def group_id? - !instance_options[:group_id].nil? - end - - def preview_card_id - instance_options[:preview_card_id] - end - - def preview_card_id? - !instance_options[:preview_card_id].nil? - end - def visibility # This visibility is masked behind "private" # to avoid API changes because there are no diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml index 6e26a141..ab55bdf5 100644 --- a/app/views/admin/accounts/_account.html.haml +++ b/app/views/admin/accounts/_account.html.haml @@ -1,6 +1,8 @@ %tr %td = admin_account_link_to(account) + - if account.is_flagged_as_spam + %span SPAM %td - if account.user_current_sign_in_ip %samp.ellipsized-ip{ title: account.user_current_sign_in_ip }= account.user_current_sign_in_ip diff --git a/config/navigation.rb b/config/navigation.rb index f2ed39f5..b8da8ba5 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -28,6 +28,7 @@ SimpleNavigation::Configuration.run do |navigation| n.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url, if: -> { current_user.staff? } n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |s| + s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts|/admin/pending_accounts} s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports} s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? } diff --git a/config/routes.rb b/config/routes.rb index d2612157..3e55a800 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -382,6 +382,7 @@ Rails.application.routes.draw do namespace :web do resource :settings, only: [:update] + resource :chat_settings, only: [:update] resource :embed, only: [:create] resources :push_subscriptions, only: [:create] do member do