Skip to content
Open
Show file tree
Hide file tree
Changes from all 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