From b75e397043037ea4d383eaa62c6abca1f806a3bc Mon Sep 17 00:00:00 2001 From: "depfu[bot]" Date: Thu, 2 May 2019 06:05:47 +0000 Subject: [PATCH 01/10] Update react-helmet to version 5.2.1 --- api/yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/api/yarn.lock b/api/yarn.lock index 43c73ed5b6..dd1abf5ac7 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -3309,11 +3309,6 @@ decorate-component-with-props@^1.0.2: resolved "https://registry.yarnpkg.com/decorate-component-with-props/-/decorate-component-with-props-1.1.0.tgz#b496c814c6a2aba0cf2ad26e44cbedb8ead42f15" integrity sha512-tTYQojixN64yK3/WBODMfvss/zbmyUx9HQXhzSxZiSiofeekVeRyyuToy9BCiTMrVEIKWxTcla2t3y5qdaUF7Q== -deep-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= - deep-extend@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -8021,14 +8016,19 @@ react-dom@^15.4.1: object-assign "^4.1.0" prop-types "^15.5.10" +react-fast-compare@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-helmet@5.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.0.tgz#a81811df21313a6d55c5f058c4aeba5d6f3d97a7" - integrity sha1-qBgR3yExOm1VxfBYxK66XW89l6c= + version "5.2.1" + resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.1.tgz#16a7192fdd09951f8e0fe22ffccbf9bb3e591ffa" + integrity sha512-CnwD822LU8NDBnjCpZ4ySh8L6HYyngViTZLfBBb3NjtrpN8m49clH8hidHouq20I51Y6TpCTISCBbqiY5GamwA== dependencies: - deep-equal "^1.0.1" object-assign "^4.1.1" prop-types "^15.5.4" + react-fast-compare "^2.0.2" react-side-effect "^1.1.0" react-infinite-scroller-with-scroll-element@^1.0.4: From b5e16b1b2ff061e93b4544e9132c1d5ed4498ed1 Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 07:51:23 -0400 Subject: [PATCH 02/10] Link to channel posts tab by default --- src/components/entities/listItems/channel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/entities/listItems/channel.js b/src/components/entities/listItems/channel.js index 90cbf140af..9539e20e8f 100644 --- a/src/components/entities/listItems/channel.js +++ b/src/components/entities/listItems/channel.js @@ -145,7 +145,7 @@ const Channel = (props: Props) => { return ( - + {name && ( From 34ad981e4bb528236c44e92fb391335108845632 Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 07:54:33 -0400 Subject: [PATCH 03/10] Prevent message actions being taken on an optimistic message --- src/components/message/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/message/index.js b/src/components/message/index.js index 2a386ac7c5..70e8f96298 100644 --- a/src/components/message/index.js +++ b/src/components/message/index.js @@ -191,7 +191,7 @@ class Message extends React.Component { const searchObj = queryString.parse(location.search); const { m = null } = searchObj; const isSelected = m && m === selectedMessageId; - + const isOptimistic = message && message.id < 0; return ( { /> )} - {!isEditing && ( + {!isEditing && !isOptimistic && ( {canEditMessage && ( From 3fd4e72cc4d511ab5cfb7163ce8e3c20b8b894bc Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 08:06:01 -0400 Subject: [PATCH 04/10] Prevent long thread titles from overflowing content area --- src/views/thread/style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/thread/style.js b/src/views/thread/style.js index bbc14564cc..a3d23a047c 100644 --- a/src/views/thread/style.js +++ b/src/views/thread/style.js @@ -475,7 +475,7 @@ export const StickyHeaderContent = styled.div` display: flex; padding: 12px 16px; cursor: pointer; - max-width: 70%; + max-width: 560px; @media (max-width: 728px) { padding: 16px; From 37c2054dea5e2b5dc33accec5021dfb38117b415 Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 08:27:54 -0400 Subject: [PATCH 05/10] Fix composer allowing scrolling in the background --- src/components/composer/style.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/composer/style.js b/src/components/composer/style.js index eb85825e4c..cffc0f9e74 100644 --- a/src/components/composer/style.js +++ b/src/components/composer/style.js @@ -3,7 +3,15 @@ import styled, { css } from 'styled-components'; import theme from 'shared/theme'; import Icon from 'src/components/icon'; import { hexa, FlexRow, FlexCol, zIndex } from '../globals'; -import { MAX_WIDTH, MEDIA_BREAK, TITLEBAR_HEIGHT } from 'src/components/layout'; +import { + COL_GAP, + MAX_WIDTH, + MEDIA_BREAK, + TITLEBAR_HEIGHT, + NAVBAR_EXPANDED_WIDTH, + NAVBAR_WIDTH, + MIN_WIDTH_TO_EXPAND_NAVIGATION, +} from 'src/components/layout'; export const DropzoneWrapper = styled.div` position: sticky; @@ -30,13 +38,26 @@ export const DropImageOverlay = (props: { }; export const Wrapper = styled.div` - grid-area: main; display: flex; justify-content: center; z-index: 9995; + position: fixed; + max-width: ${MAX_WIDTH}px; + left: ${NAVBAR_WIDTH + COL_GAP}px; + width: 100%; + max-width: calc(100% - ${NAVBAR_WIDTH * 2}px); @media (max-width: ${MEDIA_BREAK}px) { height: calc(100vh - ${TITLEBAR_HEIGHT}px); + left: 0; + right: 0; + bottom: 0; + max-width: 100%; + } + + @media (min-width: ${MIN_WIDTH_TO_EXPAND_NAVIGATION}px) { + left: ${NAVBAR_EXPANDED_WIDTH + COL_GAP}px; + max-width: calc(100% - ${NAVBAR_EXPANDED_WIDTH * 2}px); } `; From da478d539f520147d2e2c88b593c599c3781df32 Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 08:36:46 -0400 Subject: [PATCH 06/10] Fix flow --- src/components/message/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/message/index.js b/src/components/message/index.js index 70e8f96298..7b5e6920c4 100644 --- a/src/components/message/index.js +++ b/src/components/message/index.js @@ -191,7 +191,8 @@ class Message extends React.Component { const searchObj = queryString.parse(location.search); const { m = null } = searchObj; const isSelected = m && m === selectedMessageId; - const isOptimistic = message && message.id < 0; + const isOptimistic = + message && typeof message.id === 'number' && message.id < 0; return ( Date: Thu, 2 May 2019 14:55:03 +0200 Subject: [PATCH 07/10] Fallback to thread link in attachment --- src/components/message/threadAttachment/attachment.js | 5 ++--- src/components/message/threadAttachment/index.js | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/message/threadAttachment/attachment.js b/src/components/message/threadAttachment/attachment.js index 39a0a39722..042b17561b 100644 --- a/src/components/message/threadAttachment/attachment.js +++ b/src/components/message/threadAttachment/attachment.js @@ -12,7 +12,7 @@ import getThreadLink from 'src/helpers/get-thread-link'; class Attachment extends React.Component { render() { - const { data, currentUser } = this.props; + const { data, currentUser, id } = this.props; const { thread, loading, error } = data; if (loading) @@ -23,9 +23,8 @@ class Attachment extends React.Component { ); - if (error) return null; - if (!thread) return null; + if (error || !thread) return `https://spectrum.chat/thread/${id}`; return (
diff --git a/src/components/message/threadAttachment/index.js b/src/components/message/threadAttachment/index.js index aa3eb07456..7cce761c1f 100644 --- a/src/components/message/threadAttachment/index.js +++ b/src/components/message/threadAttachment/index.js @@ -12,6 +12,7 @@ import Attachment from './attachment'; export type Props = { currentUser: UserInfoType, message: MessageInfoType, + id: string, data: { thread: GetThreadType, loading: boolean, @@ -19,8 +20,8 @@ export type Props = { }, }; -const Query = ({ data, message, ...rest }: Props) => ( - +const Query = ({ data, message, id, ...rest }: Props) => ( + ); const ThreadAttachment = compose(getThreadById)(Query); From 4dc9caac6ed2783ddbac97ac717e536b638fab6c Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 09:00:20 -0400 Subject: [PATCH 08/10] Remove pinned thread if thread is moved to a private channel --- api/mutations/thread/moveThread.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/api/mutations/thread/moveThread.js b/api/mutations/thread/moveThread.js index d28bb9aa9f..740a34288d 100644 --- a/api/mutations/thread/moveThread.js +++ b/api/mutations/thread/moveThread.js @@ -3,7 +3,8 @@ import type { GraphQLContext } from '../../'; import UserError from '../../utils/UserError'; import { getThread, moveThread } from '../../models/thread'; import { getUserPermissionsInCommunity } from '../../models/usersCommunities'; -import { getChannels } from '../../models/channel'; +import { getChannelById } from '../../models/channel'; +import { getCommunityById } from '../../models/community'; import { isAuthedResolver as requireAuth } from '../../utils/permissions'; import { events } from 'shared/analytics'; import { trackQueue } from 'shared/bull/queues'; @@ -18,6 +19,8 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { const { threadId, channelId } = args; const thread = await getThread(threadId); + const { communityId } = thread; + if (!thread) { trackQueue.add({ userId: user.id, @@ -65,7 +68,11 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { ); } - const [newChannel] = await getChannels([channelId]); + const [newChannel, community] = await Promise.all([ + getChannelById(channelId), + getCommunityById(thread.communityid), + ]); + if (newChannel.communityId !== thread.communityId) { trackQueue.add({ userId: user.id, @@ -81,6 +88,16 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { ); } + // if the thread is being moved into a private channel, make sure it is not pinned + // in the community + if ( + newChannel.isPrivate && + community.pinnedThreadId && + thread.id === community.pinnedThreadId + ) { + await setPinnedThreadInCommunity(communityId, null, user.id); + } + return moveThread(threadId, channelId, user.id).then(res => { if (res) return res; From d0ec6394e9c1bde29e1218fa4ac5499b4daa41ea Mon Sep 17 00:00:00 2001 From: Max Stoiber Date: Thu, 2 May 2019 15:04:07 +0200 Subject: [PATCH 09/10] Link fallback thread links --- src/components/message/threadAttachment/attachment.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/message/threadAttachment/attachment.js b/src/components/message/threadAttachment/attachment.js index 042b17561b..8dae27ab57 100644 --- a/src/components/message/threadAttachment/attachment.js +++ b/src/components/message/threadAttachment/attachment.js @@ -1,5 +1,6 @@ // @flow import React from 'react'; +import { Link } from 'react-router-dom'; import type { Props } from './'; import compose from 'recompose/compose'; import { Loading } from 'src/components/loading'; @@ -24,7 +25,10 @@ class Attachment extends React.Component {
); - if (error || !thread) return `https://spectrum.chat/thread/${id}`; + if (error || !thread) + return ( + https://spectrum.chat/thread/{id} + ); return (
From 021f733d55825d7a06647ba34ae40a8cc678c7de Mon Sep 17 00:00:00 2001 From: Brian Lovin Date: Thu, 2 May 2019 09:08:06 -0400 Subject: [PATCH 10/10] Fix flow --- api/models/community.js | 2 +- api/mutations/thread/moveThread.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/api/models/community.js b/api/models/community.js index 6598526a90..42b4a5b114 100644 --- a/api/models/community.js +++ b/api/models/community.js @@ -543,7 +543,7 @@ export const deleteCommunity = (communityId: string, userId: string): Promise => { +export const setPinnedThreadInCommunity = (communityId: string, value: ?string, userId: string): Promise => { return db .table('communities') .get(communityId) diff --git a/api/mutations/thread/moveThread.js b/api/mutations/thread/moveThread.js index 740a34288d..f6d21120bf 100644 --- a/api/mutations/thread/moveThread.js +++ b/api/mutations/thread/moveThread.js @@ -4,7 +4,10 @@ import UserError from '../../utils/UserError'; import { getThread, moveThread } from '../../models/thread'; import { getUserPermissionsInCommunity } from '../../models/usersCommunities'; import { getChannelById } from '../../models/channel'; -import { getCommunityById } from '../../models/community'; +import { + getCommunityById, + setPinnedThreadInCommunity, +} from '../../models/community'; import { isAuthedResolver as requireAuth } from '../../utils/permissions'; import { events } from 'shared/analytics'; import { trackQueue } from 'shared/bull/queues'; @@ -19,7 +22,6 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { const { threadId, channelId } = args; const thread = await getThread(threadId); - const { communityId } = thread; if (!thread) { trackQueue.add({ @@ -70,7 +72,7 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { const [newChannel, community] = await Promise.all([ getChannelById(channelId), - getCommunityById(thread.communityid), + getCommunityById(thread.communityId), ]); if (newChannel.communityId !== thread.communityId) { @@ -95,7 +97,7 @@ export default requireAuth(async (_: any, args: Input, ctx: GraphQLContext) => { community.pinnedThreadId && thread.id === community.pinnedThreadId ) { - await setPinnedThreadInCommunity(communityId, null, user.id); + await setPinnedThreadInCommunity(thread.communityId, null, user.id); } return moveThread(threadId, channelId, user.id).then(res => {