Skip to content

Commit 85b0da3

Browse files
authored
Merge pull request #282 from nushea/Edit-file-body
feat: edit file description
2 parents d1ead29 + 55d92c6 commit 85b0da3

7 files changed

Lines changed: 353 additions & 165 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: minor
3+
---
4+
5+
Added the ability to edit the description of a file and streamlined the image and video ui

src/app/components/RenderMessageContent.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type RenderMessageContentProps = {
4747
htmlReactParserOptions: HTMLReactParserOptions;
4848
linkifyOpts: Opts;
4949
outlineAttachment?: boolean;
50+
hideCaption?: boolean;
5051
};
5152

5253
const getMediaType = (url: string) => {
@@ -71,6 +72,7 @@ function RenderMessageContentInternal({
7172
htmlReactParserOptions,
7273
linkifyOpts,
7374
outlineAttachment,
75+
hideCaption,
7476
}: RenderMessageContentProps) {
7577
const content = useMemo(() => getContent<any>(), [getContent]);
7678

@@ -121,7 +123,7 @@ function RenderMessageContentInternal({
121123

122124
const renderCaption = () => {
123125
const hasCaption = content.body && content.body.trim().length > 0;
124-
if (captionPosition === CaptionPosition.Hidden) return null;
126+
if (captionPosition === CaptionPosition.Hidden || hideCaption) return null;
125127
if (hasCaption && content.filename && content.filename !== content.body) {
126128
if (captionPosition !== CaptionPosition.Inline)
127129
return (

src/app/components/editor/Editor.css.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const Editor = style([
99
boxShadow: `inset 0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.ContainerLine}`,
1010
borderRadius: config.radii.R400,
1111
overflow: 'hidden',
12+
width: '100%',
1213
},
1314
]);
1415

src/app/components/message/content/ImageContent.tsx

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
Chip,
77
Icon,
88
Icons,
9+
Menu,
10+
MenuItem,
911
Modal,
1012
Overlay,
1113
OverlayBackdrop,
@@ -15,6 +17,7 @@ import {
1517
Tooltip,
1618
TooltipProvider,
1719
as,
20+
config,
1821
} from 'folds';
1922
import classNames from 'classnames';
2023
import { BlurhashCanvas } from 'react-blurhash';
@@ -84,6 +87,7 @@ export const ImageContent = as<'div', ImageContentProps>(
8487
const [error, setError] = useState(false);
8588
const [viewer, setViewer] = useState(false);
8689
const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
90+
const [isHovered, setIsHovered] = useState(false);
8791

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

121125
return (
122-
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
126+
<Box
127+
className={classNames(css.RelativeBase, className)}
128+
{...props}
129+
ref={ref}
130+
onPointerEnter={() => setIsHovered(true)}
131+
onPointerLeave={() => setIsHovered(false)}
132+
>
123133
{srcState.status === AsyncStatus.Success && (
124134
<Overlay open={viewer} backdrop={<OverlayBackdrop />}>
125135
<OverlayCenter>
@@ -156,7 +166,12 @@ export const ImageContent = as<'div', ImageContentProps>(
156166
/>
157167
)}
158168
{!autoPlay && !markedAsSpoiler && srcState.status === AsyncStatus.Idle && (
159-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
169+
<Box
170+
className={css.AbsoluteContainer}
171+
alignItems="Center"
172+
justifyContent="Center"
173+
onClick={loadSrc}
174+
>
160175
<Button
161176
variant="Secondary"
162177
fill="Solid"
@@ -183,36 +198,35 @@ export const ImageContent = as<'div', ImageContentProps>(
183198
</Box>
184199
)}
185200
{blurred && !error && srcState.status !== AsyncStatus.Error && (
186-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
187-
<TooltipProvider
188-
tooltip={
189-
typeof spoilerReason === 'string' && (
190-
<Tooltip variant="Secondary">
191-
<Text>{spoilerReason}</Text>
192-
</Tooltip>
193-
)
201+
<Box
202+
className={css.AbsoluteContainer}
203+
alignItems="Center"
204+
justifyContent="Center"
205+
onClick={() => {
206+
setBlurred(false);
207+
if (srcState.status === AsyncStatus.Idle) {
208+
loadSrc();
194209
}
195-
position="Top"
196-
align="Center"
210+
}}
211+
>
212+
<Chip
213+
variant="Secondary"
214+
radii="Pill"
215+
size="500"
216+
outlined
217+
onClick={() => {
218+
setBlurred(false);
219+
if (srcState.status === AsyncStatus.Idle) {
220+
loadSrc();
221+
}
222+
}}
197223
>
198-
{(triggerRef) => (
199-
<Chip
200-
ref={triggerRef}
201-
variant="Secondary"
202-
radii="Pill"
203-
size="500"
204-
outlined
205-
onClick={() => {
206-
setBlurred(false);
207-
if (srcState.status === AsyncStatus.Idle) {
208-
loadSrc();
209-
}
210-
}}
211-
>
212-
<Text size="B300">Spoiler</Text>
213-
</Chip>
214-
)}
215-
</TooltipProvider>
224+
<Text size="B300">
225+
{typeof spoilerReason === 'string' && spoilerReason.length > 0
226+
? `Spoiler reason: ${spoilerReason}`
227+
: `Spoilered`}
228+
</Text>
229+
</Chip>
216230
</Box>
217231
)}
218232
{(srcState.status === AsyncStatus.Loading || srcState.status === AsyncStatus.Success) &&
@@ -223,7 +237,12 @@ export const ImageContent = as<'div', ImageContentProps>(
223237
</Box>
224238
)}
225239
{(error || srcState.status === AsyncStatus.Error) && (
226-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
240+
<Box
241+
className={css.AbsoluteContainer}
242+
alignItems="Center"
243+
justifyContent="Center"
244+
onClick={handleRetry}
245+
>
227246
<TooltipProvider
228247
tooltip={
229248
<Tooltip variant="Critical">
@@ -250,6 +269,27 @@ export const ImageContent = as<'div', ImageContentProps>(
250269
</TooltipProvider>
251270
</Box>
252271
)}
272+
{isHovered && (
273+
<Box style={{ padding: config.space.S200, right: 0, position: 'absolute' }}>
274+
<Menu style={{ padding: config.space.S0 }}>
275+
<MenuItem
276+
size="300"
277+
after={<Icon size="200" src={blurred ? Icons.Eye : Icons.EyeBlind} />}
278+
radii="300"
279+
fill="Soft"
280+
variant="Secondary"
281+
title={blurred ? 'Reveal Image' : 'Hide Image'}
282+
onClick={(e) => {
283+
e.preventDefault();
284+
if (srcState.status === AsyncStatus.Idle) {
285+
loadSrc();
286+
setBlurred(false);
287+
} else setBlurred(!blurred);
288+
}}
289+
/>
290+
</Menu>
291+
</Box>
292+
)}
253293
{!load && typeof info?.size === 'number' && (
254294
<Box className={css.AbsoluteFooter} justifyContent="End" alignContent="Center" gap="200">
255295
<Badge variant="Secondary" fill="Soft">

src/app/components/message/content/VideoContent.tsx

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ import {
66
Chip,
77
Icon,
88
Icons,
9+
Menu,
10+
MenuItem,
911
Spinner,
1012
Text,
1113
Tooltip,
1214
TooltipProvider,
1315
as,
16+
config,
1417
} from 'folds';
1518
import classNames from 'classnames';
1619
import { BlurhashCanvas } from 'react-blurhash';
@@ -73,6 +76,7 @@ export const VideoContent = as<'div', VideoContentProps>(
7376
const [load, setLoad] = useState(false);
7477
const [error, setError] = useState(false);
7578
const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
79+
const [isHovered, setIsHovered] = useState(false);
7680

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

109113
return (
110-
<Box className={classNames(css.RelativeBase, className)} {...props} ref={ref}>
114+
<Box
115+
className={classNames(css.RelativeBase, className)}
116+
{...props}
117+
ref={ref}
118+
onPointerEnter={() => setIsHovered(true)}
119+
onPointerLeave={() => setIsHovered(false)}
120+
>
111121
{typeof blurHash === 'string' && !load && (
112122
<BlurhashCanvas
113123
style={{ width: '100%', height: '100%' }}
@@ -127,7 +137,12 @@ export const VideoContent = as<'div', VideoContentProps>(
127137
</Box>
128138
)}
129139
{!autoPlay && !blurred && srcState.status === AsyncStatus.Idle && (
130-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
140+
<Box
141+
className={css.AbsoluteContainer}
142+
alignItems="Center"
143+
justifyContent="Center"
144+
onClick={loadSrc}
145+
>
131146
<Button
132147
variant="Secondary"
133148
fill="Solid"
@@ -147,39 +162,41 @@ export const VideoContent = as<'div', VideoContentProps>(
147162
src: srcState.data,
148163
onLoadedMetadata: handleLoad,
149164
onError: handleError,
150-
autoPlay: true,
165+
autoPlay: false,
151166
controls: true,
152167
})}
153168
</Box>
154169
)}
155170
{blurred && !error && srcState.status !== AsyncStatus.Error && (
156-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
157-
<TooltipProvider
158-
tooltip={
159-
typeof spoilerReason === 'string' && (
160-
<Tooltip variant="Secondary">
161-
<Text>{spoilerReason}</Text>
162-
</Tooltip>
163-
)
171+
<Box
172+
className={css.AbsoluteContainer}
173+
alignItems="Center"
174+
justifyContent="Center"
175+
onClick={() => {
176+
setBlurred(false);
177+
if (srcState.status === AsyncStatus.Idle) {
178+
loadSrc();
164179
}
165-
position="Top"
166-
align="Center"
180+
}}
181+
>
182+
<Chip
183+
variant="Secondary"
184+
radii="Pill"
185+
size="500"
186+
outlined
187+
onClick={() => {
188+
setBlurred(false);
189+
if (srcState.status === AsyncStatus.Idle) {
190+
loadSrc();
191+
}
192+
}}
167193
>
168-
{(triggerRef) => (
169-
<Chip
170-
ref={triggerRef}
171-
variant="Secondary"
172-
radii="Pill"
173-
size="500"
174-
outlined
175-
onClick={() => {
176-
setBlurred(false);
177-
}}
178-
>
179-
<Text size="B300">Spoiler</Text>
180-
</Chip>
181-
)}
182-
</TooltipProvider>
194+
<Text size="B300">
195+
{typeof spoilerReason === 'string' && spoilerReason.length > 0
196+
? `Spoiler reason: ${spoilerReason}`
197+
: `Spoilered`}
198+
</Text>
199+
</Chip>
183200
</Box>
184201
)}
185202
{(srcState.status === AsyncStatus.Loading || srcState.status === AsyncStatus.Success) &&
@@ -190,7 +207,12 @@ export const VideoContent = as<'div', VideoContentProps>(
190207
</Box>
191208
)}
192209
{(error || srcState.status === AsyncStatus.Error) && (
193-
<Box className={css.AbsoluteContainer} alignItems="Center" justifyContent="Center">
210+
<Box
211+
className={css.AbsoluteContainer}
212+
alignItems="Center"
213+
justifyContent="Center"
214+
onClick={handleRetry}
215+
>
194216
<TooltipProvider
195217
tooltip={
196218
<Tooltip variant="Critical">
@@ -217,6 +239,27 @@ export const VideoContent = as<'div', VideoContentProps>(
217239
</TooltipProvider>
218240
</Box>
219241
)}
242+
{isHovered && (
243+
<Box style={{ padding: config.space.S200, right: 0, position: 'absolute' }}>
244+
<Menu style={{ padding: config.space.S0 }}>
245+
<MenuItem
246+
size="300"
247+
after={<Icon size="200" src={blurred ? Icons.Eye : Icons.EyeBlind} />}
248+
radii="300"
249+
fill="Soft"
250+
variant="Secondary"
251+
title={blurred ? 'Reveal Video' : 'Hide Video'}
252+
onClick={(e) => {
253+
e.preventDefault();
254+
if (srcState.status === AsyncStatus.Idle) {
255+
loadSrc();
256+
setBlurred(false);
257+
} else setBlurred(!blurred);
258+
}}
259+
/>
260+
</Menu>
261+
</Box>
262+
)}
220263
{!load && typeof info.size === 'number' && (
221264
<Box
222265
className={css.AbsoluteFooter}

0 commit comments

Comments
 (0)