From a2f95a916ea78ed6c5c630d927850789fa89b1d5 Mon Sep 17 00:00:00 2001 From: Apoorv Mishra Date: Fri, 2 Aug 2024 23:00:07 +0530 Subject: [PATCH 1/5] fix: make share dialog scrollable --- .../Collection/CollectionMemberList.tsx | 81 +++++- .../Sharing/Collection/SharePopover.tsx | 39 +-- .../Sharing/Document/DocumentMemberList.tsx | 24 +- .../Sharing/Document/OtherAccess.tsx | 248 ++++++++++++------ .../Sharing/Document/SharePopover.tsx | 31 +-- .../Sharing/components/Suggestions.tsx | 2 +- app/hooks/useMaxHeight.ts | 8 +- shared/i18n/locales/en_US/translation.json | 4 +- 8 files changed, 263 insertions(+), 174 deletions(-) diff --git a/app/components/Sharing/Collection/CollectionMemberList.tsx b/app/components/Sharing/Collection/CollectionMemberList.tsx index 27cf834cbd25..79f6300d4552 100644 --- a/app/components/Sharing/Collection/CollectionMemberList.tsx +++ b/app/components/Sharing/Collection/CollectionMemberList.tsx @@ -1,13 +1,15 @@ -import { observer } from "mobx-react"; -import { GroupIcon } from "outline-icons"; +import { GroupIcon, UserIcon } from "outline-icons"; import * as React from "react"; import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components"; +import styled, { useTheme } from "styled-components"; import Squircle from "@shared/components/Squircle"; import { CollectionPermission } from "@shared/types"; import Collection from "~/models/Collection"; import Avatar, { AvatarSize } from "~/components/Avatar/Avatar"; import InputMemberPermissionSelect from "~/components/InputMemberPermissionSelect"; +import InputSelectPermission from "~/components/InputSelectPermission"; +import Scrollable from "~/components/Scrollable"; +import useMaxHeight from "~/hooks/useMaxHeight"; import usePolicy from "~/hooks/usePolicy"; import useRequest from "~/hooks/useRequest"; import useStores from "~/hooks/useStores"; @@ -23,32 +25,45 @@ type Props = { invitedInSession: string[]; }; -function CollectionMemberList({ collection, invitedInSession }: Props) { +export function CollectionMemberList({ collection, invitedInSession }: Props) { const { memberships, groupMemberships } = useStores(); const can = usePolicy(collection); const { t } = useTranslation(); const theme = useTheme(); const collectionId = collection.id; - const { request: fetchMemberships } = useRequest( + const { request: fetchMemberships, data: membershipData } = useRequest( React.useCallback( () => memberships.fetchAll({ id: collectionId }), [memberships, collectionId] ) ); - const { request: fetchGroupMemberships } = useRequest( - React.useCallback( - () => groupMemberships.fetchAll({ id: collectionId }), - [groupMemberships, collectionId] - ) - ); + const { request: fetchGroupMemberships, data: grpMembershipData } = + useRequest( + React.useCallback( + () => groupMemberships.fetchAll({ id: collectionId }), + [groupMemberships, collectionId] + ) + ); React.useEffect(() => { void fetchMemberships(); void fetchGroupMemberships(); }, [fetchMemberships, fetchGroupMemberships]); + const containerRef = React.useRef(null); + const { maxHeight, calcMaxHeight } = useMaxHeight({ + elementRef: containerRef, + maxViewportPercentage: 70, + }); + + React.useEffect(() => { + if (!!membershipData && !!grpMembershipData) { + calcMaxHeight(); + } + }, [membershipData, grpMembershipData, calcMaxHeight]); + const permissions = React.useMemo( () => [ @@ -73,8 +88,43 @@ function CollectionMemberList({ collection, invitedInSession }: Props) { [t] ); + if (!membershipData || !grpMembershipData) { + return null; + } + return ( - <> + + + + + } + title={t("All members")} + subtitle={t("Everyone in the workspace")} + actions={ +
+ { + void collection.save({ + permission: value === EmptySelectValue ? null : value, + }); + }} + disabled={!can.update} + value={collection?.permission} + labelHidden + nude + /> +
+ } + /> {groupMemberships .inCollection(collection.id) .sort((a, b) => @@ -173,8 +223,11 @@ function CollectionMemberList({ collection, invitedInSession }: Props) { } /> ))} - +
); } -export default observer(CollectionMemberList); +const ScrollableContainer = styled(Scrollable)` + padding: 12px 24px; + margin: -12px -24px; +`; diff --git a/app/components/Sharing/Collection/SharePopover.tsx b/app/components/Sharing/Collection/SharePopover.tsx index f3c0ccca01a0..34dad45def7e 100644 --- a/app/components/Sharing/Collection/SharePopover.tsx +++ b/app/components/Sharing/Collection/SharePopover.tsx @@ -1,18 +1,15 @@ import { isEmail } from "class-validator"; import { m } from "framer-motion"; import { observer } from "mobx-react"; -import { BackIcon, UserIcon } from "outline-icons"; +import { BackIcon } from "outline-icons"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; -import { useTheme } from "styled-components"; -import Squircle from "@shared/components/Squircle"; import { CollectionPermission } from "@shared/types"; import Collection from "~/models/Collection"; import Group from "~/models/Group"; import User from "~/models/User"; import Avatar, { AvatarSize } from "~/components/Avatar/Avatar"; -import InputSelectPermission from "~/components/InputSelectPermission"; import NudeButton from "~/components/NudeButton"; import { createAction } from "~/actions"; import { UserSection } from "~/actions/sections"; @@ -22,15 +19,14 @@ import useKeyDown from "~/hooks/useKeyDown"; import usePolicy from "~/hooks/usePolicy"; import usePrevious from "~/hooks/usePrevious"; import useStores from "~/hooks/useStores"; -import { EmptySelectValue, Permission } from "~/types"; +import { Permission } from "~/types"; import { collectionPath, urlify } from "~/utils/routeHelpers"; import { Wrapper, presence } from "../components"; import { CopyLinkButton } from "../components/CopyLinkButton"; -import { ListItem } from "../components/ListItem"; import { PermissionAction } from "../components/PermissionAction"; import { SearchInput } from "../components/SearchInput"; import { Suggestions } from "../components/Suggestions"; -import CollectionMemberList from "./CollectionMemberList"; +import { CollectionMemberList } from "./CollectionMemberList"; type Props = { /** The collection to share. */ @@ -42,7 +38,6 @@ type Props = { }; function SharePopover({ collection, visible, onRequestClose }: Props) { - const theme = useTheme(); const team = useCurrentTeam(); const { groupMemberships, users, groups, memberships } = useStores(); const { t } = useTranslation(); @@ -367,34 +362,6 @@ function SharePopover({ collection, visible, onRequestClose }: Props) { )}
- - - - } - title={t("All members")} - subtitle={t("Everyone in the workspace")} - actions={ -
- { - void collection.save({ - permission: value === EmptySelectValue ? null : value, - }); - }} - disabled={!can.update} - value={collection?.permission} - labelHidden - nude - /> -
- } - /> - - userMemberships.fetchDocumentMemberships({ - id: document.id, - limit: Pagination.defaultLimit, - }), - [userMemberships, document.id] - ) - ); - - React.useEffect(() => { - void fetchDocumentMembers(); - }, [fetchDocumentMembers]); - const handleRemoveUser = React.useCallback( async (item) => { try { @@ -105,10 +87,6 @@ function DocumentMembersList({ document, invitedInSession }: Props) { [document.members, invitedInSession] ); - if (loadingDocumentMembers) { - return ; - } - return ( <> {members.map((item) => ( diff --git a/app/components/Sharing/Document/OtherAccess.tsx b/app/components/Sharing/Document/OtherAccess.tsx index 4170e9dcec46..c32dd9732dcb 100644 --- a/app/components/Sharing/Document/OtherAccess.tsx +++ b/app/components/Sharing/Document/OtherAccess.tsx @@ -2,111 +2,206 @@ import { observer } from "mobx-react"; import { MoreIcon, QuestionMarkIcon, UserIcon } from "outline-icons"; import * as React from "react"; import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components"; +import styled, { useTheme } from "styled-components"; import Squircle from "@shared/components/Squircle"; +import { Pagination } from "@shared/constants"; import { CollectionPermission, IconType } from "@shared/types"; import { determineIconType } from "@shared/utils/icon"; import type Collection from "~/models/Collection"; import type Document from "~/models/Document"; +import Share from "~/models/Share"; import Flex from "~/components/Flex"; +import LoadingIndicator from "~/components/LoadingIndicator"; +import Scrollable from "~/components/Scrollable"; import Text from "~/components/Text"; +import useCurrentTeam from "~/hooks/useCurrentTeam"; import useCurrentUser from "~/hooks/useCurrentUser"; +import useMaxHeight from "~/hooks/useMaxHeight"; +import usePolicy from "~/hooks/usePolicy"; import useRequest from "~/hooks/useRequest"; import useStores from "~/hooks/useStores"; import Avatar from "../../Avatar"; import { AvatarSize } from "../../Avatar/Avatar"; import CollectionIcon from "../../Icons/CollectionIcon"; import Tooltip from "../../Tooltip"; +import { Separator } from "../components"; import { ListItem } from "../components/ListItem"; +import DocumentMemberList from "./DocumentMemberList"; +import PublicAccess from "./PublicAccess"; type Props = { /** The document being shared. */ document: Document; - children: React.ReactNode; + /** List of users that have been invited during the current editing session */ + invitedInSession: string[]; + /** The existing share model, if any. */ + share: Share | null | undefined; + /** The existing share parent model, if any. */ + sharedParent: Share | null | undefined; + /** Callback fired when the popover requests to be closed. */ + onRequestClose: () => void; + /** Whether the popover is visible. */ + visible: boolean; }; -export const OtherAccess = observer(({ document, children }: Props) => { - const { t } = useTranslation(); - const theme = useTheme(); - const collection = document.collection; - const usersInCollection = useUsersInCollection(collection); - const user = useCurrentUser(); +export const OtherAccess = observer( + ({ + document, + invitedInSession, + share, + sharedParent, + onRequestClose, + visible, + }: Props) => { + const { t } = useTranslation(); + const theme = useTheme(); + const collection = document.collection; + const usersInCollection = useUsersInCollection(collection); + const user = useCurrentUser(); + const { userMemberships } = useStores(); + const collectionSharingDisabled = document.collection?.sharing === false; + const team = useCurrentTeam(); + const can = usePolicy(document); - return ( - <> - {collection ? ( - <> - {collection.permission ? ( + const containerRef = React.useRef(null); + const { maxHeight, calcMaxHeight } = useMaxHeight({ + elementRef: containerRef, + maxViewportPercentage: 70, + }); + + const { + loading: loadingDocumentMembers, + request: fetchDocumentMembers, + data, + } = useRequest( + React.useCallback( + () => + userMemberships.fetchDocumentMemberships({ + id: document.id, + limit: Pagination.defaultLimit, + }), + [userMemberships, document.id] + ) + ); + + React.useEffect(() => { + void fetchDocumentMembers(); + }, [fetchDocumentMembers]); + + React.useEffect(() => { + if (data) { + calcMaxHeight(); + } + }, [data, calcMaxHeight]); + + if (loadingDocumentMembers) { + return ; + } + + if (!data) { + return null; + } + + return ( + + {collection ? ( + <> + {collection.permission ? ( + + + + } + title={t("All members")} + subtitle={t("Everyone in the workspace")} + actions={ + + {collection?.permission === CollectionPermission.ReadWrite + ? t("Can edit") + : t("Can view")} + + } + /> + ) : usersInCollection ? ( + } + title={collection.name} + subtitle={t("Everyone in the collection")} + actions={{t("Can view")}} + /> + ) : ( + } + title={user.name} + subtitle={t("You have full access")} + actions={{t("Can edit")}} + /> + )} + + + ) : document.isDraft ? ( + <> + } + title={document.createdBy?.name} + actions={ + + {t("Can edit")} + + } + /> + + + ) : ( + <> + - + } - title={t("All members")} - subtitle={t("Everyone in the workspace")} + title={t("Other people")} + subtitle={t("Other workspace members may have access")} actions={ - - {collection?.permission === CollectionPermission.ReadWrite - ? t("Can edit") - : t("Can view")} - + } /> - ) : usersInCollection ? ( - } - title={collection.name} - subtitle={t("Everyone in the collection")} - actions={{t("Can view")}} - /> - ) : ( - } - title={user.name} - subtitle={t("You have full access")} - actions={{t("Can edit")}} + + )} + {team.sharing && can.share && !collectionSharingDisabled && visible && ( + <> + {document.members.length ? : null} + - )} - {children} - - ) : document.isDraft ? ( - <> - } - title={document.createdBy?.name} - actions={ - - {t("Can edit")} - - } - /> - {children} - - ) : ( - <> - {children} - - - - } - title={t("Other people")} - subtitle={t("Other workspace members may have access")} - actions={ - - } - /> - - )} - - ); -}); + + )} + + ); + } +); const AccessTooltip = ({ children, @@ -165,3 +260,8 @@ function useUsersInCollection(collection?: Collection) { : users.inCollection(collection.id).length > 1 : false; } + +const ScrollableContainer = styled(Scrollable)` + padding: 12px 24px; + margin: -12px -24px; +`; diff --git a/app/components/Sharing/Document/SharePopover.tsx b/app/components/Sharing/Document/SharePopover.tsx index d1c2d841689f..3a05cc15690a 100644 --- a/app/components/Sharing/Document/SharePopover.tsx +++ b/app/components/Sharing/Document/SharePopover.tsx @@ -22,14 +22,12 @@ import usePrevious from "~/hooks/usePrevious"; import useStores from "~/hooks/useStores"; import { Permission } from "~/types"; import { documentPath, urlify } from "~/utils/routeHelpers"; -import { Separator, Wrapper, presence } from "../components"; +import { Wrapper, presence } from "../components"; import { CopyLinkButton } from "../components/CopyLinkButton"; import { PermissionAction } from "../components/PermissionAction"; import { SearchInput } from "../components/SearchInput"; import { Suggestions } from "../components/Suggestions"; -import DocumentMembersList from "./DocumentMemberList"; import { OtherAccess } from "./OtherAccess"; -import PublicAccess from "./PublicAccess"; type Props = { /** The document to share. */ @@ -60,7 +58,6 @@ function SharePopover({ const [picker, showPicker, hidePicker] = useBoolean(); const [invitedInSession, setInvitedInSession] = React.useState([]); const [pendingIds, setPendingIds] = React.useState([]); - const collectionSharingDisabled = document.collection?.sharing === false; const [permission, setPermission] = React.useState( DocumentPermission.Read ); @@ -341,24 +338,14 @@ function SharePopover({ )}
- - - - - {team.sharing && can.share && !collectionSharingDisabled && visible && ( - <> - {document.members.length ? : null} - - - )} +
); diff --git a/app/components/Sharing/components/Suggestions.tsx b/app/components/Sharing/components/Suggestions.tsx index 0731c0ba2d69..27ff06471b11 100644 --- a/app/components/Sharing/components/Suggestions.tsx +++ b/app/components/Sharing/components/Suggestions.tsx @@ -68,7 +68,7 @@ export const Suggestions = observer( const user = useCurrentUser(); const theme = useTheme(); const containerRef = React.useRef(null); - const maxHeight = useMaxHeight({ + const { maxHeight } = useMaxHeight({ elementRef: containerRef, maxViewportPercentage: 70, }); diff --git a/app/hooks/useMaxHeight.ts b/app/hooks/useMaxHeight.ts index 9fa0c8692827..27600cce39fe 100644 --- a/app/hooks/useMaxHeight.ts +++ b/app/hooks/useMaxHeight.ts @@ -18,7 +18,7 @@ const useMaxHeight = ({ const isMobile = useMobile(); const { height: windowHeight } = useWindowSize(); - React.useLayoutEffect(() => { + const calcMaxHeight = React.useCallback(() => { if (!isMobile && elementRef?.current) { const mxHeight = (windowHeight / 100) * maxViewportPercentage; @@ -37,7 +37,11 @@ const useMaxHeight = ({ } }, [elementRef, windowHeight, margin, isMobile, maxViewportPercentage]); - return maxHeight; + React.useLayoutEffect(() => { + calcMaxHeight(); + }, [calcMaxHeight]); + + return { maxHeight, calcMaxHeight }; }; export default useMaxHeight; diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 142ac1cb51b7..ee24acbccdd0 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -284,14 +284,14 @@ "Results": "Results", "No results for {{query}}": "No results for {{query}}", "Manage": "Manage", + "All members": "All members", + "Everyone in the workspace": "Everyone in the workspace", "Invite": "Invite", "{{ userName }} was added to the collection": "{{ userName }} was added to the collection", "{{ count }} people added to the collection": "{{ count }} people added to the collection", "{{ count }} people added to the collection_plural": "{{ count }} people added to the collection", "{{ count }} people and {{ count2 }} groups added to the collection": "{{ count }} people and {{ count2 }} groups added to the collection", "{{ count }} people and {{ count2 }} groups added to the collection_plural": "{{ count }} people and {{ count2 }} groups added to the collection", - "All members": "All members", - "Everyone in the workspace": "Everyone in the workspace", "Add": "Add", "Add or invite": "Add or invite", "Viewer": "Viewer", From fb7e5694cc763d3cf9dbecb25907204654939e3f Mon Sep 17 00:00:00 2001 From: Apoorv Mishra Date: Fri, 2 Aug 2024 23:15:34 +0530 Subject: [PATCH 2/5] fix: rename --- ...ctionMemberList.tsx => AccessControlList.tsx} | 8 +++----- .../Sharing/Collection/SharePopover.tsx | 4 ++-- .../{OtherAccess.tsx => AccessControlList.tsx} | 8 +++----- app/components/Sharing/Document/SharePopover.tsx | 4 ++-- shared/i18n/locales/en_US/translation.json | 16 ++++++++-------- 5 files changed, 18 insertions(+), 22 deletions(-) rename app/components/Sharing/Collection/{CollectionMemberList.tsx => AccessControlList.tsx} (97%) rename app/components/Sharing/Document/{OtherAccess.tsx => AccessControlList.tsx} (98%) diff --git a/app/components/Sharing/Collection/CollectionMemberList.tsx b/app/components/Sharing/Collection/AccessControlList.tsx similarity index 97% rename from app/components/Sharing/Collection/CollectionMemberList.tsx rename to app/components/Sharing/Collection/AccessControlList.tsx index 79f6300d4552..0efe47c49044 100644 --- a/app/components/Sharing/Collection/CollectionMemberList.tsx +++ b/app/components/Sharing/Collection/AccessControlList.tsx @@ -25,7 +25,7 @@ type Props = { invitedInSession: string[]; }; -export function CollectionMemberList({ collection, invitedInSession }: Props) { +export function AccessControlList({ collection, invitedInSession }: Props) { const { memberships, groupMemberships } = useStores(); const can = usePolicy(collection); const { t } = useTranslation(); @@ -59,10 +59,8 @@ export function CollectionMemberList({ collection, invitedInSession }: Props) { }); React.useEffect(() => { - if (!!membershipData && !!grpMembershipData) { - calcMaxHeight(); - } - }, [membershipData, grpMembershipData, calcMaxHeight]); + calcMaxHeight(); + }); const permissions = React.useMemo( () => diff --git a/app/components/Sharing/Collection/SharePopover.tsx b/app/components/Sharing/Collection/SharePopover.tsx index 34dad45def7e..f86cba796052 100644 --- a/app/components/Sharing/Collection/SharePopover.tsx +++ b/app/components/Sharing/Collection/SharePopover.tsx @@ -26,7 +26,7 @@ import { CopyLinkButton } from "../components/CopyLinkButton"; import { PermissionAction } from "../components/PermissionAction"; import { SearchInput } from "../components/SearchInput"; import { Suggestions } from "../components/Suggestions"; -import { CollectionMemberList } from "./CollectionMemberList"; +import { AccessControlList } from "./AccessControlList"; type Props = { /** The collection to share. */ @@ -362,7 +362,7 @@ function SharePopover({ collection, visible, onRequestClose }: Props) { )}
- diff --git a/app/components/Sharing/Document/OtherAccess.tsx b/app/components/Sharing/Document/AccessControlList.tsx similarity index 98% rename from app/components/Sharing/Document/OtherAccess.tsx rename to app/components/Sharing/Document/AccessControlList.tsx index c32dd9732dcb..f73bcc0c49d4 100644 --- a/app/components/Sharing/Document/OtherAccess.tsx +++ b/app/components/Sharing/Document/AccessControlList.tsx @@ -44,7 +44,7 @@ type Props = { visible: boolean; }; -export const OtherAccess = observer( +export const AccessControlList = observer( ({ document, invitedInSession, @@ -89,10 +89,8 @@ export const OtherAccess = observer( }, [fetchDocumentMembers]); React.useEffect(() => { - if (data) { - calcMaxHeight(); - } - }, [data, calcMaxHeight]); + calcMaxHeight(); + }); if (loadingDocumentMembers) { return ; diff --git a/app/components/Sharing/Document/SharePopover.tsx b/app/components/Sharing/Document/SharePopover.tsx index 3a05cc15690a..a87bdbf2fb2f 100644 --- a/app/components/Sharing/Document/SharePopover.tsx +++ b/app/components/Sharing/Document/SharePopover.tsx @@ -27,7 +27,7 @@ import { CopyLinkButton } from "../components/CopyLinkButton"; import { PermissionAction } from "../components/PermissionAction"; import { SearchInput } from "../components/SearchInput"; import { Suggestions } from "../components/Suggestions"; -import { OtherAccess } from "./OtherAccess"; +import { AccessControlList } from "./AccessControlList"; type Props = { /** The document to share. */ @@ -338,7 +338,7 @@ function SharePopover({ )}
- parent": "Has access through <2>parent", - "Suspended": "Suspended", - "Invited": "Invited", - "Leave": "Leave", "Can view": "Can view", "Everyone in the collection": "Everyone in the collection", "You have full access": "You have full access", @@ -314,6 +306,14 @@ "Other workspace members may have access": "Other workspace members may have access", "This document may be shared with more workspace members through a parent document or collection you do not have access to": "This document may be shared with more workspace members through a parent document or collection you do not have access to", "Access inherited from collection": "Access inherited from collection", + "{{ userName }} was removed from the document": "{{ userName }} was removed from the document", + "Could not remove user": "Could not remove user", + "Permissions for {{ userName }} updated": "Permissions for {{ userName }} updated", + "Could not update user": "Could not update user", + "Has access through <2>parent": "Has access through <2>parent", + "Suspended": "Suspended", + "Invited": "Invited", + "Leave": "Leave", "Only lowercase letters, digits and dashes allowed": "Only lowercase letters, digits and dashes allowed", "Sorry, this link has already been used": "Sorry, this link has already been used", "Public link copied to clipboard": "Public link copied to clipboard", From be5dd33f9a136e6322205eb2c289ca0a5e8644b8 Mon Sep 17 00:00:00 2001 From: Apoorv Mishra Date: Sat, 3 Aug 2024 11:56:20 +0530 Subject: [PATCH 3/5] fix: mobile --- app/hooks/useMaxHeight.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/hooks/useMaxHeight.ts b/app/hooks/useMaxHeight.ts index 27600cce39fe..c7ff9f15d555 100644 --- a/app/hooks/useMaxHeight.ts +++ b/app/hooks/useMaxHeight.ts @@ -1,5 +1,4 @@ import * as React from "react"; -import useMobile from "./useMobile"; import useWindowSize from "./useWindowSize"; const useMaxHeight = ({ @@ -15,11 +14,10 @@ const useMaxHeight = ({ margin?: number; }) => { const [maxHeight, setMaxHeight] = React.useState(10); - const isMobile = useMobile(); const { height: windowHeight } = useWindowSize(); const calcMaxHeight = React.useCallback(() => { - if (!isMobile && elementRef?.current) { + if (elementRef?.current) { const mxHeight = (windowHeight / 100) * maxViewportPercentage; setMaxHeight( @@ -35,7 +33,7 @@ const useMaxHeight = ({ } else { setMaxHeight(0); } - }, [elementRef, windowHeight, margin, isMobile, maxViewportPercentage]); + }, [elementRef, windowHeight, margin, maxViewportPercentage]); React.useLayoutEffect(() => { calcMaxHeight(); From a1b9175a2206ee31bfc8e5ac0abfd2794c835c74 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 4 Aug 2024 16:40:33 +0100 Subject: [PATCH 4/5] fix: useMaxHeight margin calculation --- app/components/Sharing/Document/AccessControlList.tsx | 1 + app/hooks/useMaxHeight.ts | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/components/Sharing/Document/AccessControlList.tsx b/app/components/Sharing/Document/AccessControlList.tsx index f73bcc0c49d4..20004025b371 100644 --- a/app/components/Sharing/Document/AccessControlList.tsx +++ b/app/components/Sharing/Document/AccessControlList.tsx @@ -67,6 +67,7 @@ export const AccessControlList = observer( const { maxHeight, calcMaxHeight } = useMaxHeight({ elementRef: containerRef, maxViewportPercentage: 70, + margin: 24, }); const { diff --git a/app/hooks/useMaxHeight.ts b/app/hooks/useMaxHeight.ts index c7ff9f15d555..c3f5e0a922bd 100644 --- a/app/hooks/useMaxHeight.ts +++ b/app/hooks/useMaxHeight.ts @@ -18,7 +18,7 @@ const useMaxHeight = ({ const calcMaxHeight = React.useCallback(() => { if (elementRef?.current) { - const mxHeight = (windowHeight / 100) * maxViewportPercentage; + const mxHeight = (windowHeight / 100) * maxViewportPercentage - margin; setMaxHeight( Math.min( @@ -35,9 +35,7 @@ const useMaxHeight = ({ } }, [elementRef, windowHeight, margin, maxViewportPercentage]); - React.useLayoutEffect(() => { - calcMaxHeight(); - }, [calcMaxHeight]); + React.useLayoutEffect(calcMaxHeight, [calcMaxHeight]); return { maxHeight, calcMaxHeight }; }; From 153e61f0df7d1d3d78af9c3e13f574ec9884c9ea Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 4 Aug 2024 16:44:43 +0100 Subject: [PATCH 5/5] cleanup --- app/components/Sharing/Collection/AccessControlList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/Sharing/Collection/AccessControlList.tsx b/app/components/Sharing/Collection/AccessControlList.tsx index 0efe47c49044..c3411c978fd1 100644 --- a/app/components/Sharing/Collection/AccessControlList.tsx +++ b/app/components/Sharing/Collection/AccessControlList.tsx @@ -39,7 +39,7 @@ export function AccessControlList({ collection, invitedInSession }: Props) { ) ); - const { request: fetchGroupMemberships, data: grpMembershipData } = + const { request: fetchGroupMemberships, data: groupMembershipData } = useRequest( React.useCallback( () => groupMemberships.fetchAll({ id: collectionId }), @@ -86,7 +86,7 @@ export function AccessControlList({ collection, invitedInSession }: Props) { [t] ); - if (!membershipData || !grpMembershipData) { + if (!membershipData || !groupMembershipData) { return null; }