mirror of
https://github.com/filecoin-project/slate.git
synced 2024-11-26 13:45:30 +03:00
Merge pull request #1047 from filecoin-project/@aminejv/updates
Improvements and bug fixes
This commit is contained in:
commit
568d8bc4f5
@ -450,7 +450,8 @@ export const useImage = ({ src, maxWidth }) => {
|
|||||||
if (!src) setImgState({ error: true, loaded: true });
|
if (!src) setImgState({ error: true, loaded: true });
|
||||||
|
|
||||||
const img = new Image();
|
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 = () => {
|
img.onload = () => {
|
||||||
if (maxWidth && img.naturalWidth < maxWidth) {
|
if (maxWidth && img.naturalWidth < maxWidth) {
|
||||||
|
@ -15,8 +15,8 @@ import { css } from "@emotion/react";
|
|||||||
import { useFilterContext } from "~/components/core/Filter/Provider";
|
import { useFilterContext } from "~/components/core/Filter/Provider";
|
||||||
import { Link } from "~/components/core/Link";
|
import { Link } from "~/components/core/Link";
|
||||||
import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons";
|
import { ButtonPrimary, ButtonSecondary } from "~/components/system/components/Buttons";
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { FocusRing } from "../FocusRing";
|
import { FocusRing } from "../FocusRing";
|
||||||
|
import { Show } from "~/components/utility/Show";
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------------
|
||||||
* Shared components between filters
|
* Shared components between filters
|
||||||
@ -77,7 +77,7 @@ const FilterButton = React.forwardRef(({ children, Icon, image, isSelected, ...p
|
|||||||
</Link>
|
</Link>
|
||||||
));
|
));
|
||||||
|
|
||||||
const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => {
|
const FilterSection = React.forwardRef(({ title, children, emptyState, ...props }, ref) => {
|
||||||
const [isExpanded, setExpanded] = React.useState(true);
|
const [isExpanded, setExpanded] = React.useState(true);
|
||||||
const toggleExpandState = () => setExpanded((prev) => !prev);
|
const toggleExpandState = () => setExpanded((prev) => !prev);
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => {
|
|||||||
<Tooltip.Trigger aria-describedby={titleButtonId} aria-expanded={isExpanded}>
|
<Tooltip.Trigger aria-describedby={titleButtonId} aria-expanded={isExpanded}>
|
||||||
<FocusRing>
|
<FocusRing>
|
||||||
<Typography.H6
|
<Typography.H6
|
||||||
as={motion.button}
|
as="button"
|
||||||
layoutId={title + "title"}
|
layoutId={title + "title"}
|
||||||
css={STYLES_FILTER_TITLE_BUTTON}
|
css={STYLES_FILTER_TITLE_BUTTON}
|
||||||
style={{ paddingLeft: 8, marginBottom: 4 }}
|
style={{ paddingLeft: 8, marginBottom: 4 }}
|
||||||
@ -108,25 +108,26 @@ const FilterSection = React.forwardRef(({ title, children, ...props }, ref) => {
|
|||||||
</Tooltip.Root>
|
</Tooltip.Root>
|
||||||
)}
|
)}
|
||||||
{isExpanded ? (
|
{isExpanded ? (
|
||||||
<RovingTabIndex.Provider axis="vertical">
|
Array.isArray(children) && children?.length === 0 ? (
|
||||||
<RovingTabIndex.List>
|
<Show when={emptyState}>
|
||||||
<motion.ul
|
<System.P2 color="textGrayDark" style={{ paddingLeft: "8px" }}>
|
||||||
layoutId={title + "section"}
|
{emptyState}
|
||||||
initial={{ opacity: 0 }}
|
</System.P2>
|
||||||
animate={{ opacity: 1 }}
|
</Show>
|
||||||
css={STYLES_FILTERS_GROUP}
|
) : (
|
||||||
>
|
<RovingTabIndex.Provider axis="vertical">
|
||||||
{children}
|
<RovingTabIndex.List>
|
||||||
</motion.ul>
|
<ul css={STYLES_FILTERS_GROUP}>{children}</ul>
|
||||||
</RovingTabIndex.List>
|
</RovingTabIndex.List>
|
||||||
</RovingTabIndex.Provider>
|
</RovingTabIndex.Provider>
|
||||||
|
)
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------------
|
||||||
* InitialFilters
|
* Library
|
||||||
* -----------------------------------------------------------------------------------------------*/
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function Library({ page, onAction }) {
|
function Library({ page, onAction }) {
|
||||||
@ -151,11 +152,19 @@ function Library({ page, onAction }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------------------------------
|
||||||
|
* Tags
|
||||||
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function Tags({ viewer, data, onAction, ...props }) {
|
function Tags({ viewer, data, onAction, ...props }) {
|
||||||
const [, { hidePopup }] = useFilterContext();
|
const [, { hidePopup }] = useFilterContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterSection title="Tags" {...props}>
|
<FilterSection
|
||||||
|
title="Tags"
|
||||||
|
emptyState="when you tag a file, that tag will automatically show up here"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{viewer.slates.map((slate, index) => (
|
{viewer.slates.map((slate, index) => (
|
||||||
<li key={slate.id}>
|
<li key={slate.id}>
|
||||||
<RovingTabIndex.Item index={index}>
|
<RovingTabIndex.Item index={index}>
|
||||||
@ -175,35 +184,39 @@ function Tags({ viewer, data, onAction, ...props }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------------------------------
|
||||||
|
* Following
|
||||||
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function Following({ viewer, onAction, ...props }) {
|
function Following({ viewer, onAction, ...props }) {
|
||||||
const [, { hidePopup }] = useFilterContext();
|
const [, { hidePopup }] = useFilterContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RovingTabIndex.Provider axis="vertical">
|
<FilterSection title="Following" emptyState="follow users to see them here" {...props}>
|
||||||
<RovingTabIndex.List>
|
{viewer.following.map((user, index) => (
|
||||||
<FilterSection title="Following" {...props}>
|
<li key={user.id}>
|
||||||
{viewer.following.map((user, index) => (
|
<RovingTabIndex.Item index={index}>
|
||||||
<li key={user.id}>
|
<FilterButton
|
||||||
<RovingTabIndex.Item index={index}>
|
href={`/${user.username}`}
|
||||||
<FilterButton
|
isSelected={false}
|
||||||
href={`/${user.username}`}
|
onAction={onAction}
|
||||||
isSelected={false}
|
// Icon={SVG.ProfileUser}
|
||||||
onAction={onAction}
|
image={<ProfilePhoto user={user} style={{ borderRadius: "8px" }} size={20} />}
|
||||||
// Icon={SVG.ProfileUser}
|
onClick={hidePopup}
|
||||||
image={<ProfilePhoto user={user} style={{ borderRadius: "8px" }} size={20} />}
|
>
|
||||||
onClick={hidePopup}
|
{user.username}
|
||||||
>
|
</FilterButton>
|
||||||
{user.username}
|
</RovingTabIndex.Item>
|
||||||
</FilterButton>
|
</li>
|
||||||
</RovingTabIndex.Item>
|
))}
|
||||||
</li>
|
</FilterSection>
|
||||||
))}
|
|
||||||
</FilterSection>
|
|
||||||
</RovingTabIndex.List>
|
|
||||||
</RovingTabIndex.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------------------------------
|
||||||
|
* Profile
|
||||||
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function Profile({ viewer, data, page, ...props }) {
|
function Profile({ viewer, data, page, ...props }) {
|
||||||
if (page.id === "NAV_SLATE") {
|
if (page.id === "NAV_SLATE") {
|
||||||
data = data.owner;
|
data = data.owner;
|
||||||
@ -288,6 +301,10 @@ function Profile({ viewer, data, page, ...props }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------------------------------
|
||||||
|
* ProfileTags
|
||||||
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function ProfileTags({ data, page, onAction, ...props }) {
|
function ProfileTags({ data, page, onAction, ...props }) {
|
||||||
const [, { hidePopup }] = useFilterContext();
|
const [, { hidePopup }] = useFilterContext();
|
||||||
|
|
||||||
@ -297,27 +314,23 @@ function ProfileTags({ data, page, onAction, ...props }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RovingTabIndex.Provider axis="vertical">
|
<FilterSection {...props}>
|
||||||
<RovingTabIndex.List>
|
{user?.slates?.map((slate, index) => (
|
||||||
<FilterSection {...props}>
|
<li key={slate.id}>
|
||||||
{user?.slates?.map((slate, index) => (
|
<RovingTabIndex.Item index={index}>
|
||||||
<li key={slate.id}>
|
<FilterButton
|
||||||
<RovingTabIndex.Item index={index}>
|
href={`/$/slate/${slate.id}`}
|
||||||
<FilterButton
|
isSelected={slate.id === data?.id}
|
||||||
href={`/$/slate/${slate.id}`}
|
onAction={onAction}
|
||||||
isSelected={slate.id === data?.id}
|
Icon={slate.isPublic ? SVG.Hash : SVG.SecurityLock}
|
||||||
onAction={onAction}
|
onClick={hidePopup}
|
||||||
Icon={slate.isPublic ? SVG.Hash : SVG.SecurityLock}
|
>
|
||||||
onClick={hidePopup}
|
{slate.slatename}
|
||||||
>
|
</FilterButton>
|
||||||
{slate.slatename}
|
</RovingTabIndex.Item>
|
||||||
</FilterButton>
|
</li>
|
||||||
</RovingTabIndex.Item>
|
))}
|
||||||
</li>
|
</FilterSection>
|
||||||
))}
|
|
||||||
</FilterSection>
|
|
||||||
</RovingTabIndex.List>
|
|
||||||
</RovingTabIndex.Provider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import { Show } from "~/components/utility/Show";
|
|||||||
import { useHover } from "~/common/hooks";
|
import { useHover } from "~/common/hooks";
|
||||||
import { clamp } from "lodash";
|
import { clamp } from "lodash";
|
||||||
import { useUploadStore } from "~/components/core/Upload/store";
|
import { useUploadStore } from "~/components/core/Upload/store";
|
||||||
|
import { LoaderSpinner } from "~/components/system/components/Loaders";
|
||||||
|
|
||||||
import DataMeter from "~/components/core/DataMeter";
|
import DataMeter from "~/components/core/DataMeter";
|
||||||
import BlobObjectPreview from "~/components/core/BlobObjectPreview";
|
import BlobObjectPreview from "~/components/core/BlobObjectPreview";
|
||||||
@ -27,7 +28,6 @@ const STYLES_POPUP_WRAPPER = (theme) => css`
|
|||||||
bottom: 24px;
|
bottom: 24px;
|
||||||
right: 24px;
|
right: 24px;
|
||||||
z-index: ${theme.zindex.tooltip};
|
z-index: ${theme.zindex.tooltip};
|
||||||
box-shadow: ${theme.shadow.lightLarge};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const STYLES_DISMISS_BUTTON = (theme) => css`
|
const STYLES_DISMISS_BUTTON = (theme) => css`
|
||||||
@ -391,11 +391,15 @@ function Summary({ uploadSummary }) {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Match when={file.status === "uploading"}>
|
<Match when={file.status === "uploading"}>
|
||||||
<DataMeter
|
{file.isLink ? (
|
||||||
bytes={file.loaded}
|
<LoaderSpinner style={{ height: 12, width: 12 }} />
|
||||||
maximumBytes={file.total}
|
) : (
|
||||||
style={{ maxWidth: 84, marginTop: 2 }}
|
<DataMeter
|
||||||
/>
|
bytes={file.loaded}
|
||||||
|
maximumBytes={file.total}
|
||||||
|
style={{ maxWidth: 84, marginTop: 2 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={file.status === "failed"}>
|
<Match when={file.status === "failed"}>
|
||||||
<System.P3 color="red">failed</System.P3>
|
<System.P3 color="red">failed</System.P3>
|
||||||
|
@ -161,7 +161,9 @@ export const useUploadStore = create((setUploadState) => {
|
|||||||
onError: handleError,
|
onError: handleError,
|
||||||
});
|
});
|
||||||
|
|
||||||
const resetUploadState = () => (uploadProvider.clearUploadCache(), setUploadState(DEFAULT_STATE));
|
const resetUploadState = () => (
|
||||||
|
uploadProvider.clearUploadCache(), setUploadState((prev) => ({ ...prev, state: DEFAULT_STATE }))
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state: DEFAULT_STATE,
|
state: DEFAULT_STATE,
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
useDetectTextOverflow,
|
useDetectTextOverflow,
|
||||||
useEscapeKey,
|
useEscapeKey,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
useIsomorphicLayoutEffect,
|
|
||||||
useLockScroll,
|
useLockScroll,
|
||||||
} from "~/common/hooks";
|
} from "~/common/hooks";
|
||||||
import { Show } from "~/components/utility/Show";
|
import { Show } from "~/components/utility/Show";
|
||||||
@ -50,7 +49,7 @@ const VisitLinkButton = ({ file }) => {
|
|||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
type="link"
|
type="link"
|
||||||
>
|
>
|
||||||
<LinkIcon file={file} width={16} height={16} style={{ marginRight: 4 }} />
|
<LinkIcon file={file} width={16} height={16} style={{ marginRight: 4 }} key={file.id} />
|
||||||
<span style={{ whiteSpace: "nowrap" }}>Visit site</span>
|
<span style={{ whiteSpace: "nowrap" }}>Visit site</span>
|
||||||
</System.ButtonTertiary>
|
</System.ButtonTertiary>
|
||||||
);
|
);
|
||||||
@ -142,7 +141,6 @@ const useCarouselJumperControls = () => {
|
|||||||
|
|
||||||
const STYLES_HEADER_WRAPPER = (theme) => css`
|
const STYLES_HEADER_WRAPPER = (theme) => css`
|
||||||
${Styles.HORIZONTAL_CONTAINER_CENTERED};
|
${Styles.HORIZONTAL_CONTAINER_CENTERED};
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
padding: 13px 24px 10px;
|
padding: 13px 24px 10px;
|
||||||
@ -243,42 +241,6 @@ function CarouselHeader({
|
|||||||
};
|
};
|
||||||
useEventListener({ type: "keyup", handler: handleKeyDown });
|
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();
|
const headerRef = React.useRef();
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (headerRef.current) headerRef.current.focus();
|
if (headerRef.current) headerRef.current.focus();
|
||||||
@ -320,18 +282,7 @@ function CarouselHeader({
|
|||||||
/>
|
/>
|
||||||
</ModalPortal>
|
</ModalPortal>
|
||||||
|
|
||||||
<motion.nav
|
<nav css={STYLES_HEADER_WRAPPER} {...props}>
|
||||||
css={STYLES_HEADER_WRAPPER}
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: isHeaderVisible ? 1 : 0 }}
|
|
||||||
transition={{ ease: "easeInOut", duration: 0.25 }}
|
|
||||||
onMouseEnter={showHeader}
|
|
||||||
onMouseOver={showHeader}
|
|
||||||
onMouseLeave={hideHeader}
|
|
||||||
onFocus={showHeader}
|
|
||||||
onBlur={hideHeader}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<div css={Styles.HORIZONTAL_CONTAINER}>
|
<div css={Styles.HORIZONTAL_CONTAINER}>
|
||||||
<System.H5
|
<System.H5
|
||||||
@ -483,20 +434,14 @@ function CarouselHeader({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</motion.nav>
|
</nav>
|
||||||
|
|
||||||
<CarouselControls
|
<CarouselControls
|
||||||
enableNextSlide={enableNextSlide}
|
enableNextSlide={enableNextSlide}
|
||||||
enablePreviousSlide={enablePreviousSlide}
|
enablePreviousSlide={enablePreviousSlide}
|
||||||
onNextSlide={onNextSlide}
|
onNextSlide={onNextSlide}
|
||||||
onPreviousSlide={onPreviousSlide}
|
onPreviousSlide={onPreviousSlide}
|
||||||
showControls={isHeaderVisible}
|
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onMouseEnter={showHeader}
|
|
||||||
onMouseOver={showHeader}
|
|
||||||
onMouseLeave={hideHeader}
|
|
||||||
onFocus={showHeader}
|
|
||||||
onBlur={hideHeader}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -783,10 +728,7 @@ function CarouselControls({
|
|||||||
enablePreviousSlide,
|
enablePreviousSlide,
|
||||||
onNextSlide,
|
onNextSlide,
|
||||||
onPreviousSlide,
|
onPreviousSlide,
|
||||||
showControls,
|
|
||||||
onClose,
|
onClose,
|
||||||
|
|
||||||
...props
|
|
||||||
}) {
|
}) {
|
||||||
useCarouselKeyCommands({
|
useCarouselKeyCommands({
|
||||||
handleNext: onNextSlide,
|
handleNext: onNextSlide,
|
||||||
@ -794,19 +736,41 @@ function CarouselControls({
|
|||||||
handleClose: onClose,
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
css={STYLES_CONTROLS_WRAPPER}
|
css={STYLES_CONTROLS_WRAPPER}
|
||||||
style={{ left: 0, justifyContent: "flex-start" }}
|
style={{ left: 0, justifyContent: "flex-start" }}
|
||||||
{...props}
|
onMouseEnter={showControls}
|
||||||
|
onMouseLeave={hideControls}
|
||||||
|
onFocus={showControls}
|
||||||
|
onBlur={hideControls}
|
||||||
>
|
>
|
||||||
{enablePreviousSlide ? (
|
{enablePreviousSlide ? (
|
||||||
<System.ButtonPrimitive
|
<System.ButtonPrimitive
|
||||||
as={motion.button}
|
as={motion.button}
|
||||||
onClick={onPreviousSlide}
|
onClick={onPreviousSlide}
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: showControls ? 1 : 0 }}
|
animate={{ opacity: areControlsVisible ? 1 : 0 }}
|
||||||
transition={{ ease: "easeInOut", duration: 0.25 }}
|
transition={{ ease: "easeInOut", duration: 0.25 }}
|
||||||
css={STYLES_CONTROLS_BUTTON}
|
css={STYLES_CONTROLS_BUTTON}
|
||||||
aria-label="previous slide"
|
aria-label="previous slide"
|
||||||
@ -818,14 +782,17 @@ function CarouselControls({
|
|||||||
<div
|
<div
|
||||||
css={STYLES_CONTROLS_WRAPPER}
|
css={STYLES_CONTROLS_WRAPPER}
|
||||||
style={{ right: 0, justifyContent: "flex-end" }}
|
style={{ right: 0, justifyContent: "flex-end" }}
|
||||||
{...props}
|
onMouseEnter={showControls}
|
||||||
|
onMouseLeave={hideControls}
|
||||||
|
onFocus={showControls}
|
||||||
|
onBlur={hideControls}
|
||||||
>
|
>
|
||||||
{enableNextSlide ? (
|
{enableNextSlide ? (
|
||||||
<System.ButtonPrimitive
|
<System.ButtonPrimitive
|
||||||
as={motion.button}
|
as={motion.button}
|
||||||
onClick={onNextSlide}
|
onClick={onNextSlide}
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: showControls ? 1 : 0 }}
|
animate={{ opacity: areControlsVisible ? 1 : 0 }}
|
||||||
css={STYLES_CONTROLS_BUTTON}
|
css={STYLES_CONTROLS_BUTTON}
|
||||||
aria-label="next slide"
|
aria-label="next slide"
|
||||||
>
|
>
|
||||||
|
@ -76,7 +76,7 @@ function ChannelKeyboardShortcut({ searchResults, searchQuery, onAddFileToChanne
|
|||||||
});
|
});
|
||||||
|
|
||||||
// NOTE(amine): don't show the 'select channel ⏎' hint when the channel is created optimistically
|
// 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 (
|
return (
|
||||||
<div css={Styles.HORIZONTAL_CONTAINER_CENTERED}>
|
<div css={Styles.HORIZONTAL_CONTAINER_CENTERED}>
|
||||||
@ -113,7 +113,15 @@ const STYLES_SEARCH_TAGS_INPUT_WRAPPER = (theme) => css`
|
|||||||
|
|
||||||
function ChannelInput({ value, searchResults, onChange, onAddFileToChannel, ...props }) {
|
function ChannelInput({ value, searchResults, onChange, onAddFileToChannel, ...props }) {
|
||||||
const { publicChannels, privateChannels } = searchResults;
|
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 (
|
return (
|
||||||
<div css={[STYLES_SEARCH_TAGS_INPUT_WRAPPER, Styles.CONTAINER_CENTERED]}>
|
<div css={[STYLES_SEARCH_TAGS_INPUT_WRAPPER, Styles.CONTAINER_CENTERED]}>
|
||||||
@ -129,7 +137,7 @@ function ChannelInput({ value, searchResults, onChange, onAddFileToChannel, ...p
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
<div style={{ position: "absolute", top: "50%", transform: "translateY(-50%)", right: 20 }}>
|
<div style={{ position: "absolute", top: "50%", transform: "translateY(-50%)", right: 20 }}>
|
||||||
{showShortcut ? (
|
{isShortcutVisible ? (
|
||||||
<ChannelKeyboardShortcut
|
<ChannelKeyboardShortcut
|
||||||
searchQuery={value}
|
searchQuery={value}
|
||||||
searchResults={searchResults}
|
searchResults={searchResults}
|
||||||
@ -425,7 +433,7 @@ export function EditChannels({ file, viewer, isOpen, onClose, ...props }) {
|
|||||||
channels={isSearching ? searchResults.privateChannels : privateChannels}
|
channels={isSearching ? searchResults.privateChannels : privateChannels}
|
||||||
searchQuery={searchQuery}
|
searchQuery={searchQuery}
|
||||||
onAddFileToChannel={handleAddFileToChannel}
|
onAddFileToChannel={handleAddFileToChannel}
|
||||||
onCreateChannel={handleCreateChannel(false)}
|
onCreateChannel={(query) => (handleCreateChannel(false)(query), clearQuery())}
|
||||||
file={file}
|
file={file}
|
||||||
viewer={viewer}
|
viewer={viewer}
|
||||||
/>
|
/>
|
||||||
@ -437,7 +445,7 @@ export function EditChannels({ file, viewer, isOpen, onClose, ...props }) {
|
|||||||
isCreatingChannel={isSearching && !channelAlreadyExists}
|
isCreatingChannel={isSearching && !channelAlreadyExists}
|
||||||
channels={isSearching ? searchResults.publicChannels : publicChannels}
|
channels={isSearching ? searchResults.publicChannels : publicChannels}
|
||||||
onAddFileToChannel={handleAddFileToChannel}
|
onAddFileToChannel={handleAddFileToChannel}
|
||||||
onCreateChannel={handleCreateChannel(true)}
|
onCreateChannel={(query) => (handleCreateChannel(true)(query), clearQuery())}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Jumper.Item>
|
</Jumper.Item>
|
||||||
@ -493,7 +501,7 @@ export function EditChannelsMobile({ file, viewer, isOpen, onClose }) {
|
|||||||
channels={isSearching ? searchResults.privateChannels : privateChannels}
|
channels={isSearching ? searchResults.privateChannels : privateChannels}
|
||||||
searchQuery={searchQuery}
|
searchQuery={searchQuery}
|
||||||
onAddFileToChannel={handleAddFileToChannel}
|
onAddFileToChannel={handleAddFileToChannel}
|
||||||
onCreateChannel={handleCreateChannel(false)}
|
onCreateChannel={(query) => (handleCreateChannel(false)(query), clearQuery())}
|
||||||
/>
|
/>
|
||||||
<div style={{ marginTop: 20 }}>
|
<div style={{ marginTop: 20 }}>
|
||||||
<Channels
|
<Channels
|
||||||
@ -503,7 +511,7 @@ export function EditChannelsMobile({ file, viewer, isOpen, onClose }) {
|
|||||||
isCreatingChannel={isSearching && !channelAlreadyExists}
|
isCreatingChannel={isSearching && !channelAlreadyExists}
|
||||||
channels={isSearching ? searchResults.publicChannels : publicChannels}
|
channels={isSearching ? searchResults.publicChannels : publicChannels}
|
||||||
onAddFileToChannel={handleAddFileToChannel}
|
onAddFileToChannel={handleAddFileToChannel}
|
||||||
onCreateChannel={handleCreateChannel(true)}
|
onCreateChannel={(query) => (handleCreateChannel(true)(query), clearQuery())}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</MobileJumper.Content>
|
</MobileJumper.Content>
|
||||||
|
Loading…
Reference in New Issue
Block a user