Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/file_description_editing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

Added the ability to edit the description of a file and streamlined the image and video ui
4 changes: 3 additions & 1 deletion src/app/components/RenderMessageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type RenderMessageContentProps = {
htmlReactParserOptions: HTMLReactParserOptions;
linkifyOpts: Opts;
outlineAttachment?: boolean;
hideCaption?: boolean;
};

const getMediaType = (url: string) => {
Expand All @@ -71,6 +72,7 @@ function RenderMessageContentInternal({
htmlReactParserOptions,
linkifyOpts,
outlineAttachment,
hideCaption,
}: RenderMessageContentProps) {
const content = useMemo(() => getContent<any>(), [getContent]);

Expand Down Expand Up @@ -121,7 +123,7 @@ function RenderMessageContentInternal({

const renderCaption = () => {
const hasCaption = content.body && content.body.trim().length > 0;
if (captionPosition === CaptionPosition.Hidden) return null;
if (captionPosition === CaptionPosition.Hidden || hideCaption) return null;
if (hasCaption && content.filename && content.filename !== content.body) {
if (captionPosition !== CaptionPosition.Inline)
return (
Expand Down
116 changes: 84 additions & 32 deletions src/app/components/message/content/ImageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
Chip,
Icon,
Icons,
Menu,
MenuItem,
Modal,
Overlay,
OverlayBackdrop,
Expand All @@ -15,6 +17,7 @@ import {
Tooltip,
TooltipProvider,
as,
config,
} from 'folds';
import classNames from 'classnames';
import { BlurhashCanvas } from 'react-blurhash';
Expand Down Expand Up @@ -84,6 +87,7 @@ export const ImageContent = as<'div', ImageContentProps>(
const [error, setError] = useState(false);
const [viewer, setViewer] = useState(false);
const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
const [isHovered, setIsHovered] = useState(false);

const [srcState, loadSrc] = useAsyncCallback(
useCallback(async () => {
Expand Down Expand Up @@ -119,7 +123,13 @@ export const ImageContent = as<'div', ImageContentProps>(
}, [autoPlay, loadSrc]);

return (
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
<Box
className={classNames(css.RelativeBase, className)}
{...props}
ref={ref}
onPointerEnter={() => setIsHovered(true)}
onPointerLeave={() => setIsHovered(false)}
>
{srcState.status === AsyncStatus.Success && (
<Overlay open={viewer} backdrop={<OverlayBackdrop />}>
<OverlayCenter>
Expand Down Expand Up @@ -156,7 +166,12 @@ export const ImageContent = as<'div', ImageContentProps>(
/>
)}
{!autoPlay && !markedAsSpoiler && srcState.status === AsyncStatus.Idle && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={loadSrc}
>
<Button
variant="Secondary"
fill="Solid"
Expand All @@ -183,36 +198,48 @@ export const ImageContent = as<'div', ImageContentProps>(
</Box>
)}
{blurred && !error && srcState.status !== AsyncStatus.Error && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<TooltipProvider
tooltip={
typeof spoilerReason === 'string' && (
<Tooltip variant="Secondary">
<Text>{spoilerReason}</Text>
</Tooltip>
)
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
position="Top"
align="Center"
>
{(triggerRef) => (
<Chip
ref={triggerRef}
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
}}
>
<Text size="B300">Spoiler</Text>
</Chip>
)}
</TooltipProvider>
}}
>
{typeof spoilerReason === 'string' && spoilerReason.length > 0 ? (
<Chip
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
}}
>
<Text size="B300">Spoiler reason: {spoilerReason}</Text>
</Chip>
) : (
<Chip
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
}}
>
<Text size="B300">Spoilered</Text>
</Chip>
)}
</Box>
)}
{(srcState.status === AsyncStatus.Loading || srcState.status === AsyncStatus.Success) &&
Expand All @@ -223,7 +250,12 @@ export const ImageContent = as<'div', ImageContentProps>(
</Box>
)}
{(error || srcState.status === AsyncStatus.Error) && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={handleRetry}
>
<TooltipProvider
tooltip={
<Tooltip variant="Critical">
Expand All @@ -250,6 +282,26 @@ export const ImageContent = as<'div', ImageContentProps>(
</TooltipProvider>
</Box>
)}
{isHovered && (
<Box style={{ padding: config.space.S200, right: 0, position: 'absolute' }}>
<Menu style={{ padding: config.space.S0 }}>
<MenuItem
size="300"
after={<Icon size="200" src={blurred ? Icons.Eye : Icons.EyeBlind} />}
radii="300"
fill="Soft"
variant="Secondary"
onClick={(e) => {
e.preventDefault();
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
setBlurred(false);
} else setBlurred(!blurred);
}}
/>
</Menu>
</Box>
)}
{!load && typeof info?.size === 'number' && (
<Box className={css.AbsoluteFooter} justifyContent="End" alignContent="Center" gap="200">
<Badge variant="Secondary" fill="Soft">
Expand Down
115 changes: 85 additions & 30 deletions src/app/components/message/content/VideoContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import {
Chip,
Icon,
Icons,
Menu,
MenuItem,
Spinner,
Text,
Tooltip,
TooltipProvider,
as,
config,
} from 'folds';
import classNames from 'classnames';
import { BlurhashCanvas } from 'react-blurhash';
Expand Down Expand Up @@ -73,6 +76,7 @@ export const VideoContent = as<'div', VideoContentProps>(
const [load, setLoad] = useState(false);
const [error, setError] = useState(false);
const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
const [isHovered, setIsHovered] = useState(false);

const [srcState, loadSrc] = useAsyncCallback(
useCallback(async () => {
Expand Down Expand Up @@ -107,7 +111,13 @@ export const VideoContent = as<'div', VideoContentProps>(
}, [autoPlay, loadSrc]);

return (
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
<Box
className={classNames(css.RelativeBase, className)}
{...props}
ref={ref}
onPointerEnter={() => setIsHovered(true)}
onPointerLeave={() => setIsHovered(false)}
>
{typeof blurHash === 'string' && !load && (
<BlurhashCanvas
style={{ width: '100%', height: '100%' }}
Expand All @@ -127,7 +137,12 @@ export const VideoContent = as<'div', VideoContentProps>(
</Box>
)}
{!autoPlay && !blurred && srcState.status === AsyncStatus.Idle && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={loadSrc}
>
<Button
variant="Secondary"
fill="Solid"
Expand All @@ -147,39 +162,54 @@ export const VideoContent = as<'div', VideoContentProps>(
src: srcState.data,
onLoadedMetadata: handleLoad,
onError: handleError,
autoPlay: true,
autoPlay: false,
controls: true,
})}
</Box>
)}
{blurred && !error && srcState.status !== AsyncStatus.Error && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<TooltipProvider
tooltip={
typeof spoilerReason === 'string' && (
<Tooltip variant="Secondary">
<Text>{spoilerReason}</Text>
</Tooltip>
)
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
position="Top"
align="Center"
>
{(triggerRef) => (
<Chip
ref={triggerRef}
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
}}
>
<Text size="B300">Spoiler</Text>
</Chip>
)}
</TooltipProvider>
}}
>
{typeof spoilerReason === 'string' && spoilerReason.length > 0 ? (
<Chip
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
}}
>
<Text size="B300">Spoiler reason: {spoilerReason}</Text>
</Chip>
) : (
<Chip
variant="Secondary"
radii="Pill"
size="500"
outlined
onClick={() => {
setBlurred(false);
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
}
}}
>
<Text size="B300">Spoilered</Text>
</Chip>
)}
</Box>
)}
{(srcState.status === AsyncStatus.Loading || srcState.status === AsyncStatus.Success) &&
Expand All @@ -190,7 +220,12 @@ export const VideoContent = as<'div', VideoContentProps>(
</Box>
)}
{(error || srcState.status === AsyncStatus.Error) && (
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
<Box
className={css.AbsoluteContainer}
alignItems="Center"
justifyContent="Center"
onClick={handleRetry}
>
<TooltipProvider
tooltip={
<Tooltip variant="Critical">
Expand All @@ -217,6 +252,26 @@ export const VideoContent = as<'div', VideoContentProps>(
</TooltipProvider>
</Box>
)}
{isHovered && (
<Box style={{ padding: config.space.S200, right: 0, position: 'absolute' }}>
<Menu style={{ padding: config.space.S0 }}>
<MenuItem
size="300"
after={<Icon size="200" src={blurred ? Icons.Eye : Icons.EyeBlind} />}
radii="300"
fill="Soft"
variant="Secondary"
onClick={(e) => {
e.preventDefault();
if (srcState.status === AsyncStatus.Idle) {
loadSrc();
setBlurred(false);
} else setBlurred(!blurred);
}}
/>
</Menu>
</Box>
)}
{!load && typeof info.size === 'number' && (
<Box
className={css.AbsoluteFooter}
Expand Down
Loading
Loading