From e6381c2dec190588e31197b80c13e2f4186ede18 Mon Sep 17 00:00:00 2001 From: Aminejv Date: Tue, 4 Jan 2022 18:14:14 +0100 Subject: [PATCH 1/7] feat(Upload/Popup): display loader spinner when saving a link --- components/core/Upload/Popup.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/components/core/Upload/Popup.js b/components/core/Upload/Popup.js index f3163f0d..1bea098a 100644 --- a/components/core/Upload/Popup.js +++ b/components/core/Upload/Popup.js @@ -12,6 +12,7 @@ import { Show } from "~/components/utility/Show"; import { useHover } from "~/common/hooks"; import { clamp } from "lodash"; import { useUploadStore } from "~/components/core/Upload/store"; +import { LoaderSpinner } from "~/components/system/components/Loaders"; import DataMeter from "~/components/core/DataMeter"; import BlobObjectPreview from "~/components/core/BlobObjectPreview"; @@ -27,7 +28,6 @@ const STYLES_POPUP_WRAPPER = (theme) => css` bottom: 24px; right: 24px; z-index: ${theme.zindex.tooltip}; - box-shadow: ${theme.shadow.lightLarge}; `; const STYLES_DISMISS_BUTTON = (theme) => css` @@ -391,11 +391,15 @@ function Summary({ uploadSummary }) { } > - + {file.isLink ? ( + + ) : ( + + )} failed From 55b562254dfb95dfca923bf54318cc2646c876aa Mon Sep 17 00:00:00 2001 From: Aminejv Date: Tue, 4 Jan 2022 18:15:35 +0100 Subject: [PATCH 2/7] feat(GlobalCarousel): toolbar persists in the global carousel --- .../system/components/GlobalCarousel/index.js | 97 ++++++------------- 1 file changed, 32 insertions(+), 65 deletions(-) diff --git a/components/system/components/GlobalCarousel/index.js b/components/system/components/GlobalCarousel/index.js index 0000052e..7e4c0a98 100644 --- a/components/system/components/GlobalCarousel/index.js +++ b/components/system/components/GlobalCarousel/index.js @@ -17,7 +17,6 @@ import { useDetectTextOverflow, useEscapeKey, useEventListener, - useIsomorphicLayoutEffect, useLockScroll, } from "~/common/hooks"; import { Show } from "~/components/utility/Show"; @@ -50,7 +49,7 @@ const VisitLinkButton = ({ file }) => { rel="noreferrer" type="link" > - + Visit site ); @@ -142,7 +141,6 @@ const useCarouselJumperControls = () => { const STYLES_HEADER_WRAPPER = (theme) => css` ${Styles.HORIZONTAL_CONTAINER_CENTERED}; - position: absolute; width: 100%; min-height: 64px; padding: 13px 24px 10px; @@ -243,42 +241,6 @@ function CarouselHeader({ }; useEventListener({ type: "keyup", handler: handleKeyDown }); - const isJumperOpen = - isFileDescriptionVisible || - isMoreInfoVisible || - isEditInfoVisible || - isShareFileVisible || - isEditChannelsVisible; - - const [isHeaderVisible, setHeaderVisibility] = React.useState(true); - const timeoutRef = React.useRef(); - - const showHeader = () => { - clearTimeout(timeoutRef.current); - setHeaderVisibility(true); - }; - - const hideHeader = (ms = 1000) => { - timeoutRef.current = setTimeout(() => { - if (isJumperOpen) return; - setHeaderVisibility(false); - }, ms); - }; - - React.useEffect(() => { - hideHeader(3000); - return () => clearTimeout(timeoutRef.current); - }, []); - - useIsomorphicLayoutEffect(() => { - if (isJumperOpen) { - showHeader(); - return; - } - - hideHeader(); - }, [isJumperOpen]); - const headerRef = React.useRef(); React.useEffect(() => { if (headerRef.current) headerRef.current.focus(); @@ -320,18 +282,7 @@ function CarouselHeader({ /> - + ); @@ -783,10 +728,7 @@ function CarouselControls({ enablePreviousSlide, onNextSlide, onPreviousSlide, - showControls, onClose, - - ...props }) { useCarouselKeyCommands({ handleNext: onNextSlide, @@ -794,19 +736,41 @@ function CarouselControls({ handleClose: onClose, }); + const [areControlsVisible, setCarouselVisibility] = React.useState(true); + const timeoutRef = React.useRef(); + + const showControls = () => { + clearTimeout(timeoutRef.current); + setCarouselVisibility(true); + }; + + const hideControls = (ms = 1000) => { + timeoutRef.current = setTimeout(() => { + setCarouselVisibility(false); + }, ms); + }; + + React.useEffect(() => { + hideControls(3000); + return () => clearTimeout(timeoutRef.current); + }, []); + return ( <>
{enablePreviousSlide ? ( {enableNextSlide ? ( From 1e3596c801ae333f199c85eee79cf58267111316 Mon Sep 17 00:00:00 2001 From: Aminejv Date: Tue, 4 Jan 2022 18:16:44 +0100 Subject: [PATCH 3/7] fix(hooks/useImage): setting new Image().src to null redirect the app to /_/null --- common/hooks/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/hooks/index.js b/common/hooks/index.js index 33e235b2..99feb2c4 100644 --- a/common/hooks/index.js +++ b/common/hooks/index.js @@ -450,7 +450,8 @@ export const useImage = ({ src, maxWidth }) => { if (!src) setImgState({ error: true, loaded: true }); const img = new Image(); - img.src = src; + // NOTE(amine): setting img.src to null will redirect the app to /_/null + img.src = src || ""; img.onload = () => { if (maxWidth && img.naturalWidth < maxWidth) { From aa9efe2b993f19ee453ea9196eafd0ecf4d55130 Mon Sep 17 00:00:00 2001 From: Aminejv Date: Tue, 4 Jan 2022 18:17:55 +0100 Subject: [PATCH 4/7] fix(Upload/store): correctly reset upload state when upload finishes --- components/core/Upload/store.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/core/Upload/store.js b/components/core/Upload/store.js index 8c8c68de..c2df965a 100644 --- a/components/core/Upload/store.js +++ b/components/core/Upload/store.js @@ -161,7 +161,9 @@ export const useUploadStore = create((setUploadState) => { onError: handleError, }); - const resetUploadState = () => (uploadProvider.clearUploadCache(), setUploadState(DEFAULT_STATE)); + const resetUploadState = () => ( + uploadProvider.clearUploadCache(), setUploadState((prev) => ({ ...prev, state: DEFAULT_STATE })) + ); return { state: DEFAULT_STATE, From 383b095db97adff96b305a8f588f386894e147fb Mon Sep 17 00:00:00 2001 From: Aminejv Date: Tue, 4 Jan 2022 18:18:56 +0100 Subject: [PATCH 5/7] fix(EditChannels/ChannelInput): don't display the keyboard shortcut when a tag is created --- .../GlobalCarousel/jumpers/EditChannels.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/system/components/GlobalCarousel/jumpers/EditChannels.js b/components/system/components/GlobalCarousel/jumpers/EditChannels.js index 6d9b2a40..1062cf50 100644 --- a/components/system/components/GlobalCarousel/jumpers/EditChannels.js +++ b/components/system/components/GlobalCarousel/jumpers/EditChannels.js @@ -113,7 +113,15 @@ const STYLES_SEARCH_TAGS_INPUT_WRAPPER = (theme) => css` function ChannelInput({ value, searchResults, onChange, onAddFileToChannel, ...props }) { const { publicChannels, privateChannels } = searchResults; - const showShortcut = publicChannels.length + privateChannels.length === 1; + const [isShortcutVisible, setShortcutVisibility] = React.useState(); + + React.useEffect(() => { + if (value && publicChannels.length + privateChannels.length === 1) { + setShortcutVisibility(true); + } else { + setShortcutVisibility(false); + } + }, [value]); return (
@@ -129,7 +137,7 @@ function ChannelInput({ value, searchResults, onChange, onAddFileToChannel, ...p {...props} />
- {showShortcut ? ( + {isShortcutVisible ? ( Date: Wed, 5 Jan 2022 20:26:36 +0100 Subject: [PATCH 6/7] fix(GlobalCarousel/EditChannels): clear input when creating a tag --- .../components/GlobalCarousel/jumpers/EditChannels.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/system/components/GlobalCarousel/jumpers/EditChannels.js b/components/system/components/GlobalCarousel/jumpers/EditChannels.js index 1062cf50..ec0201e1 100644 --- a/components/system/components/GlobalCarousel/jumpers/EditChannels.js +++ b/components/system/components/GlobalCarousel/jumpers/EditChannels.js @@ -76,7 +76,7 @@ function ChannelKeyboardShortcut({ searchResults, searchQuery, onAddFileToChanne }); // NOTE(amine): don't show the 'select channel ⏎' hint when the channel is created optimistically - if (isFileAdded || !selectedChannel.ownerId) return null; + if (isFileAdded || !selectedChannel?.ownerId) return null; return (
@@ -433,7 +433,7 @@ export function EditChannels({ file, viewer, isOpen, onClose, ...props }) { channels={isSearching ? searchResults.privateChannels : privateChannels} searchQuery={searchQuery} onAddFileToChannel={handleAddFileToChannel} - onCreateChannel={handleCreateChannel(false)} + onCreateChannel={(query) => (handleCreateChannel(false)(query), clearQuery())} file={file} viewer={viewer} /> @@ -445,7 +445,7 @@ export function EditChannels({ file, viewer, isOpen, onClose, ...props }) { isCreatingChannel={isSearching && !channelAlreadyExists} channels={isSearching ? searchResults.publicChannels : publicChannels} onAddFileToChannel={handleAddFileToChannel} - onCreateChannel={handleCreateChannel(true)} + onCreateChannel={(query) => (handleCreateChannel(true)(query), clearQuery())} />
@@ -501,7 +501,7 @@ export function EditChannelsMobile({ file, viewer, isOpen, onClose }) { channels={isSearching ? searchResults.privateChannels : privateChannels} searchQuery={searchQuery} onAddFileToChannel={handleAddFileToChannel} - onCreateChannel={handleCreateChannel(false)} + onCreateChannel={(query) => (handleCreateChannel(false)(query), clearQuery())} />
(handleCreateChannel(true)(query), clearQuery())} />
From b5b67b94ffb0af80cbcf267df282065a115c07a5 Mon Sep 17 00:00:00 2001 From: Aminejv Date: Thu, 6 Jan 2022 18:17:13 +0100 Subject: [PATCH 7/7] feat(Filter/Filters): add emptystate --- components/core/Filter/Filters.js | 133 ++++++++++++++++-------------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/components/core/Filter/Filters.js b/components/core/Filter/Filters.js index 2bf10d27..ac010eb6 100644 --- a/components/core/Filter/Filters.js +++ b/components/core/Filter/Filters.js @@ -15,8 +15,8 @@ import { css } from "@emotion/react"; import { useFilterContext } from "~/components/core/Filter/Provider"; import { Link } from "~/components/core/Link"; import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons"; -import { motion } from "framer-motion"; import { FocusRing } from "../FocusRing"; +import { Show } from "~/components/utility/Show"; /* ------------------------------------------------------------------------------------------------- * Shared components between filters @@ -77,7 +77,7 @@ const FilterButton = React.forwardRef(({ children, Icon, image, isSelected, ...p )); -const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => { +const FilterSection = React.forwardRef(({ title, children, emptyState, ...props }, ref) => { const [isExpanded, setExpanded] = React.useState(true); const toggleExpandState = () => setExpanded((prev) => !prev); @@ -89,7 +89,7 @@ const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => { { )} {isExpanded ? ( - - - - {children} - - - + Array.isArray(children) && children?.length === 0 ? ( + + + {emptyState} + + + ) : ( + + +
    {children}
+
+
+ ) ) : null}
); }); /* ------------------------------------------------------------------------------------------------- - * InitialFilters + * Library * -----------------------------------------------------------------------------------------------*/ function Library({ page, onAction }) { @@ -151,11 +152,19 @@ function Library({ page, onAction }) { ); } +/* ------------------------------------------------------------------------------------------------- + * Tags + * -----------------------------------------------------------------------------------------------*/ + function Tags({ viewer, data, onAction, ...props }) { const [, { hidePopup }] = useFilterContext(); return ( - + {viewer.slates.map((slate, index) => (
  • @@ -175,35 +184,39 @@ function Tags({ viewer, data, onAction, ...props }) { ); } +/* ------------------------------------------------------------------------------------------------- + * Following + * -----------------------------------------------------------------------------------------------*/ + function Following({ viewer, onAction, ...props }) { const [, { hidePopup }] = useFilterContext(); return ( - - - - {viewer.following.map((user, index) => ( -
  • - - } - onClick={hidePopup} - > - {user.username} - - -
  • - ))} -
    - - + + {viewer.following.map((user, index) => ( +
  • + + } + onClick={hidePopup} + > + {user.username} + + +
  • + ))} +
    ); } +/* ------------------------------------------------------------------------------------------------- + * Profile + * -----------------------------------------------------------------------------------------------*/ + function Profile({ viewer, data, page, ...props }) { if (page.id === "NAV_SLATE") { data = data.owner; @@ -288,6 +301,10 @@ function Profile({ viewer, data, page, ...props }) { ); } +/* ------------------------------------------------------------------------------------------------- + * ProfileTags + * -----------------------------------------------------------------------------------------------*/ + function ProfileTags({ data, page, onAction, ...props }) { const [, { hidePopup }] = useFilterContext(); @@ -297,27 +314,23 @@ function ProfileTags({ data, page, onAction, ...props }) { } return ( - - - - {user?.slates?.map((slate, index) => ( -
  • - - - {slate.slatename} - - -
  • - ))} -
    -
    -
    + + {user?.slates?.map((slate, index) => ( +
  • + + + {slate.slatename} + + +
  • + ))} +
    ); }