From 7149b283efc95d3ac440f40d1f74df467499beea Mon Sep 17 00:00:00 2001 From: Martin Schoeler Date: Mon, 30 Nov 2020 15:53:24 -0300 Subject: [PATCH] [NEW] Custom scroll (#19701) Co-authored-by: Guilherme Gazzo Co-authored-by: Guilherme Gazzo --- .../client/lib/ReactionListContent.js | 7 +- .../channel/Discussions/ContextualBar/List.js | 2 + client/channel/Threads/ContextualBar/List.js | 2 + client/components/GenericTable/index.js | 11 +-- client/components/basic/Page.tsx | 10 +-- .../basic/ScrollableContentWrapper.tsx | 21 ++++++ client/components/basic/Sidebar.js | 8 ++- client/hooks/useDir.js | 27 +++++++ client/sidebar/RoomList.js | 2 + client/sidebar/search/SearchList.js | 2 + client/views/setupWizard/SetupWizardPage.js | 7 +- client/views/setupWizard/SideBar.js | 7 +- package-lock.json | 71 ++++++++++++------- package.json | 5 +- 14 files changed, 131 insertions(+), 51 deletions(-) create mode 100644 client/components/basic/ScrollableContentWrapper.tsx create mode 100644 client/hooks/useDir.js diff --git a/app/ui-utils/client/lib/ReactionListContent.js b/app/ui-utils/client/lib/ReactionListContent.js index 17c132ce8a9..b25269de7c2 100644 --- a/app/ui-utils/client/lib/ReactionListContent.js +++ b/app/ui-utils/client/lib/ReactionListContent.js @@ -1,18 +1,19 @@ import React from 'react'; -import { Box, Tag, Modal, ButtonGroup, Button, Scrollable } from '@rocket.chat/fuselage'; +import { Box, Tag, Modal, ButtonGroup, Button } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '../../../../client/contexts/TranslationContext'; import { useSetting } from '../../../../client/contexts/SettingsContext'; import { useSession } from '../../../../client/contexts/SessionContext'; import Emoji from '../../../../client/components/basic/Emoji'; +import ScrollableContentWrapper from '../../../../client/components/basic/ScrollableContentWrapper'; import { openUserCard } from '../../../ui/client/lib/UserCard'; import { openProfileTabOrOpenDM } from '../../../ui/client/views/app/room'; export function Reactions({ reactions, roomInstance, onClose }) { const useRealName = useSetting('UI_Use_Real_Name'); - return + return {Object.entries(reactions).map(([reaction, { names = [], usernames }]) => @@ -29,7 +30,7 @@ export function Reactions({ reactions, roomInstance, onClose }) { )} - ; + ; } export function Username({ username, displayName, roomInstance, onClose }) { diff --git a/client/channel/Discussions/ContextualBar/List.js b/client/channel/Discussions/ContextualBar/List.js index 7616466ae6c..93feb793b7f 100644 --- a/client/channel/Discussions/ContextualBar/List.js +++ b/client/channel/Discussions/ContextualBar/List.js @@ -21,6 +21,7 @@ import { useUserRoom } from '../../hooks/useUserRoom'; import { useSetting } from '../../../contexts/SettingsContext'; import DiscussionListMessage from './components/Message'; import { clickableItem } from '../../helpers/clickableItem'; +import ScrollableContentWrapper from '../../../components/basic/ScrollableContentWrapper'; function mapProps(WrappedComponent) { return ({ msg, username, tcount, ts, ...props }) => ; @@ -219,6 +220,7 @@ export function DiscussionList({ total = 10, discussions = [], loadMoreItems, lo loadMoreItems={ loading ? () => {} : loadMoreItems} > {({ onItemsRendered, ref }) => ( ; @@ -261,6 +262,7 @@ export function ThreadList({ total = 10, threads = [], room, unread = [], unread loadMoreItems={ loading ? () => {} : loadMoreItems} > {({ onItemsRendered, ref }) => ( : <> - - + + {header && @@ -66,8 +67,8 @@ const GenericTable = ({ {children && (results ? results.map(children) : )}
-
-
+ + = ({ onScrollContent, ...props }) => - - - ; +const PageScrollableContent: FC = React.forwardRef(({ onScrollContent, ...props }, ref) => + +); const PageScrollableContentWithShadow: FC = ({ onScrollContent, ...props }) => { const [, setBorder] = useContext(PageContext); diff --git a/client/components/basic/ScrollableContentWrapper.tsx b/client/components/basic/ScrollableContentWrapper.tsx new file mode 100644 index 00000000000..c14c8cca4b4 --- /dev/null +++ b/client/components/basic/ScrollableContentWrapper.tsx @@ -0,0 +1,21 @@ +import React, { FC } from 'react'; +import SimpleBar from 'simplebar-react'; +import 'simplebar/src/simplebar.css'; + +import { useDir } from '../../hooks/useDir'; + +const style = { + maxHeight: '100%', flexGrow: 1, +}; + +type CustomScrollbarsProps = { + onScroll?: Function; + ref: React.Ref; +} + +const ScrollableContentWrapper: FC = React.memo(React.forwardRef(({ onScroll, children }, ref) => { + const dir = useDir(); + return ; +})); + +export default ScrollableContentWrapper; diff --git a/client/components/basic/Sidebar.js b/client/components/basic/Sidebar.js index ae98a84ab59..65f37a93ea7 100644 --- a/client/components/basic/Sidebar.js +++ b/client/components/basic/Sidebar.js @@ -1,19 +1,21 @@ import React, { useMemo } from 'react'; import { css } from '@rocket.chat/css-in-js'; -import { Box, Scrollable, Icon, ActionButton } from '@rocket.chat/fuselage'; +import { Box, Icon, ActionButton } from '@rocket.chat/fuselage'; import { useTranslation } from '../../contexts/TranslationContext'; import { useRoutePath } from '../../contexts/RouterContext'; +import ScrollableContentWrapper from './ScrollableContentWrapper'; + const Sidebar = ({ children, ...props }) => {children} ; -const Content = ({ children, ...props }) => +const Content = ({ children, ...props }) => {children} -; +; const Header = ({ title, onClose, children = undefined, ...props }) => {(title || onClose) && diff --git a/client/hooks/useDir.js b/client/hooks/useDir.js new file mode 100644 index 00000000000..fe28f0021dc --- /dev/null +++ b/client/hooks/useDir.js @@ -0,0 +1,27 @@ +import { useEffect, useState } from 'react'; +import { Emitter } from '@rocket.chat/emitter'; + +const ee = new Emitter(); + +const getDir = () => document.documentElement.getAttribute('dir') || 'ltr'; + +const config = { attributes: true, childList: false, subtree: false }; +const callback = function(mutationsList) { + for (const mutation of mutationsList) { + if (mutation.type === 'attributes' && mutation.attributeName === 'dir') { + ee.emit('change', getDir()); + } + } +}; + +const observer = new MutationObserver(callback); +observer.observe(document.documentElement, config); + +export const useDir = () => { + const [dir, setDir] = useState(getDir); + useEffect(() => { + ee.on('change', setDir); + return () => ee.off('change', setDir); + }, []); + return dir; +}; diff --git a/client/sidebar/RoomList.js b/client/sidebar/RoomList.js index e123eda3075..7fa68440cd1 100644 --- a/client/sidebar/RoomList.js +++ b/client/sidebar/RoomList.js @@ -19,6 +19,7 @@ import { useShortcutOpenMenu } from './hooks/useShortcutOpenMenu'; import { useAvatarTemplate } from './hooks/useAvatarTemplate'; import { useRoomList } from './hooks/useRoomList'; import { useSidebarPaletteColor } from './hooks/useSidebarPaletteColor'; +import ScrollableContentWrapper from '../components/basic/ScrollableContentWrapper'; const sections = { Omnichannel, @@ -130,6 +131,7 @@ export default () => { return (typeof roomsList[index] === 'string' ? (sections[roomsList[index]] && sections[roomsList[index]].size) || 40 : itemSize)} diff --git a/client/sidebar/search/SearchList.js b/client/sidebar/search/SearchList.js index 7b229a31d49..cd7ae64e063 100644 --- a/client/sidebar/search/SearchList.js +++ b/client/sidebar/search/SearchList.js @@ -16,6 +16,7 @@ import { useUserPreference, useUserSubscriptions } from '../../contexts/UserCont import { itemSizeMap, SideBarItemTemplateWithData } from '../RoomList'; import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; import { useAvatarTemplate } from '../hooks/useAvatarTemplate'; +import ScrollableContentWrapper from '../../components/basic/ScrollableContentWrapper'; const createItemData = memoize((items, t, SideBarItemTemplate, AvatarTemplate, useRealName, extended) => ({ items, @@ -274,6 +275,7 @@ const SearchList = React.forwardRef(function SearchList({ onClose }, ref) { - + @@ -68,7 +69,7 @@ function SetupWizardPage({ currentStep = 1 }) { - + } diff --git a/client/views/setupWizard/SideBar.js b/client/views/setupWizard/SideBar.js index 7c5e7b88f9b..fc084020768 100644 --- a/client/views/setupWizard/SideBar.js +++ b/client/views/setupWizard/SideBar.js @@ -1,10 +1,11 @@ -import { Box, Margins, Scrollable } from '@rocket.chat/fuselage'; +import { Box, Margins } from '@rocket.chat/fuselage'; import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import React from 'react'; import { useTranslation } from '../../contexts/TranslationContext'; import Logo from '../../components/basic/Logo'; import './SideBar.css'; +import ScrollableContentWrapper from '../../components/basic/ScrollableContentWrapper'; function SideBar({ logoSrc = 'images/logo/logo.svg', @@ -60,7 +61,7 @@ function SideBar({ - {!small && + {!small && - } + } ; } diff --git a/package-lock.json b/package-lock.json index 4d869c4f4b6..8c2008c7662 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5064,9 +5064,9 @@ } }, "@rocket.chat/fuselage": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.19.0.tgz", - "integrity": "sha512-zZaXeylSLuinH7Cutc7UleRZDTHsTp6bYYNmwamloHt8Z6KlHIUL2wgmZntkRsJgJE6BSpdQowxDzEVEK20GHw==", + "version": "0.6.3-dev.141", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.6.3-dev.141.tgz", + "integrity": "sha512-OQB7SFtjYvWx+HbuTYSyJxMbtxYDoRlXhRbtSY5csrprh1MXv0ErbBiezgBwNYm64Ch2G3zKRCPHsRrfApCokg==", "requires": { "@rocket.chat/css-in-js": "^0.19.0", "@rocket.chat/fuselage-tokens": "^0.19.0", @@ -5101,9 +5101,9 @@ "integrity": "sha512-y/201Fdagj01++tnFhiwY7vueBERSoD9MrY2/1rDu/qqqstRFE28wxuEeBlp53p4oHi/a7ZpKhOPfGv1R5Kpnw==" }, "@rocket.chat/fuselage-ui-kit": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.19.0.tgz", - "integrity": "sha512-SX1rns6XWnI8vC5G4NPqcED5GFpyOxDSHEfKY2QUKzN5H8232QI1UXc1NJ74FXVXU1RTV+OqcNXarM6DydHcZw==", + "version": "0.6.3-dev.141", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.3-dev.141.tgz", + "integrity": "sha512-sZBahrIwkK57OlsW+5muhEHXm1+pYdd1ELXUGtlBrvXU5icOkBwCbMy0Xb55bxoKe7rLSO9oBwRNmTpTo3SiCw==", "requires": { "@rocket.chat/fuselage-polyfills": "^0.19.0" } @@ -5625,6 +5625,30 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true + }, + "simplebar": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/simplebar/-/simplebar-4.2.3.tgz", + "integrity": "sha512-9no0pK7/1y+8/oTF3sy/+kx0PjQ3uk4cYwld5F1CJGk2gx+prRyUq8GRfvcVLq5niYWSozZdX73a2wIr1o9l/g==", + "dev": true, + "requires": { + "can-use-dom": "^0.1.0", + "core-js": "^3.0.1", + "lodash.debounce": "^4.0.8", + "lodash.memoize": "^4.1.2", + "lodash.throttle": "^4.1.1", + "resize-observer-polyfill": "^1.5.1" + } + }, + "simplebar-react": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-1.2.3.tgz", + "integrity": "sha512-1EOWJzFC7eqHUp1igD1/tb8GBv5aPQA5ZMvpeDnVkpNJ3jAuvmrL2kir3HuijlxhG7njvw9ssxjjBa89E5DrJg==", + "dev": true, + "requires": { + "prop-types": "^15.6.1", + "simplebar": "^4.2.3" + } } } }, @@ -12850,8 +12874,7 @@ "can-use-dom": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz", - "integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=", - "dev": true + "integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=" }, "caniuse-lite": { "version": "1.0.30000989", @@ -22898,8 +22921,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.defaults": { "version": "4.2.0", @@ -22979,8 +23001,7 @@ "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, "lodash.merge": { "version": "4.6.2", @@ -23031,8 +23052,7 @@ "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", - "dev": true + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" }, "lodash.trim": { "version": "4.5.1", @@ -30785,10 +30805,9 @@ } }, "simplebar": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/simplebar/-/simplebar-4.2.3.tgz", - "integrity": "sha512-9no0pK7/1y+8/oTF3sy/+kx0PjQ3uk4cYwld5F1CJGk2gx+prRyUq8GRfvcVLq5niYWSozZdX73a2wIr1o9l/g==", - "dev": true, + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/simplebar/-/simplebar-5.3.0.tgz", + "integrity": "sha512-LgrGdIWpwHLLlI9HqfnGql62H/iZlF0KDZ7w3ZNbd2ZLwh9NKsODLHPzQgUlqQ8aZe7Y6/1xJMXK1PU5e810+w==", "requires": { "can-use-dom": "^0.1.0", "core-js": "^3.0.1", @@ -30799,21 +30818,19 @@ }, "dependencies": { "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz", + "integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA==" } } }, "simplebar-react": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-1.2.3.tgz", - "integrity": "sha512-1EOWJzFC7eqHUp1igD1/tb8GBv5aPQA5ZMvpeDnVkpNJ3jAuvmrL2kir3HuijlxhG7njvw9ssxjjBa89E5DrJg==", - "dev": true, + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-2.3.0.tgz", + "integrity": "sha512-ZhWEe4UkshSJ9xPG1F/W58UMJdA3fzgtXGrYsya3hxdMbIYoKUKEhdBsqdMoeaLGyn/5dbMPqDLinkLeg0W0cQ==", "requires": { "prop-types": "^15.6.1", - "simplebar": "^4.2.3" + "simplebar": "^5.3.0" } }, "slash": { diff --git a/package.json b/package.json index a22488ae310..b125866a10e 100644 --- a/package.json +++ b/package.json @@ -139,10 +139,10 @@ "@rocket.chat/apps-engine": "1.20.0", "@rocket.chat/css-in-js": "^0.19.0", "@rocket.chat/emitter": "^0.19.0", - "@rocket.chat/fuselage": "^0.19.0", + "@rocket.chat/fuselage": "^0.6.3-dev.141", "@rocket.chat/fuselage-hooks": "^0.19.0", "@rocket.chat/fuselage-polyfills": "^0.19.0", - "@rocket.chat/fuselage-ui-kit": "^0.19.0", + "@rocket.chat/fuselage-ui-kit": "^0.6.3-dev.141", "@rocket.chat/icons": "^0.19.0", "@rocket.chat/mp3-encoder": "^0.19.0", "@rocket.chat/ui-kit": "^0.19.0", @@ -244,6 +244,7 @@ "redis": "^2.8.0", "semver": "^5.7.1", "sharp": "^0.22.1", + "simplebar-react": "^2.3.0", "speakeasy": "^2.0.0", "stream-buffers": "^3.0.2", "string-strip-html": "^4.5.1",