mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-01 23:58:58 -04:00
refactor(media): store filenames, use pre-signed s3/azure URLs, UUIDs
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
4132833b5d
commit
157a0fe278
47 changed files with 869 additions and 389 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -60,8 +60,8 @@ export const useHandleUpload = (): handleUploadSignature => {
|
|||
return replaceSelection(cursorSelection ?? currentSelection, uploadPlaceholder, false)
|
||||
})
|
||||
uploadFile(noteId, file)
|
||||
.then(({ id }) => {
|
||||
const fullUrl = `${baseUrl}api/private/media/${id}`
|
||||
.then(({ uuid }) => {
|
||||
const fullUrl = `${baseUrl}media/${uuid}`
|
||||
const replacement = ``
|
||||
changeContent(({ markdownContent }) => [
|
||||
replaceInContent(markdownContent, uploadPlaceholder, replacement),
|
||||
|
|
|
@ -49,7 +49,7 @@ export const MediaBrowserSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
|
|||
if (loading || error || !value) {
|
||||
return []
|
||||
}
|
||||
return value.map((entry) => <MediaEntry entry={entry} key={entry.id} onDelete={setMediaEntryForDeletion} />)
|
||||
return value.map((entry) => <MediaEntry entry={entry} key={entry.uuid} onDelete={setMediaEntryForDeletion} />)
|
||||
}, [value, loading, error, setMediaEntryForDeletion])
|
||||
|
||||
const cancelDeletion = useCallback(() => {
|
||||
|
|
|
@ -25,7 +25,7 @@ export const MediaEntryDeletionModal: React.FC<MediaEntryDeletionModalProps> = (
|
|||
const { showErrorNotification, dispatchUiNotification } = useUiNotifications()
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
deleteUploadedMedia(entry.id)
|
||||
deleteUploadedMedia(entry.uuid)
|
||||
.then(() => {
|
||||
dispatchUiNotification('common.success', 'editor.mediaBrowser.mediaDeleted', {})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
.preview {
|
||||
max-width: 100%;
|
||||
max-height: 150px;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
|
@ -11,13 +11,15 @@ import {
|
|||
Trash as IconTrash,
|
||||
FileRichtextFill as IconFileRichtextFill,
|
||||
Person as IconPerson,
|
||||
Clock as IconClock
|
||||
Clock as IconClock,
|
||||
FileText as IconFileText
|
||||
} from 'react-bootstrap-icons'
|
||||
import { useIsOwner } from '../../../../../hooks/common/use-is-owner'
|
||||
import { useApplicationState } from '../../../../../hooks/common/use-application-state'
|
||||
import { UserAvatarForUsername } from '../../../../common/user-avatar/user-avatar-for-username'
|
||||
import { useChangeEditorContentCallback } from '../../../change-content-context/use-change-editor-content-callback'
|
||||
import { replaceSelection } from '../../../editor-pane/tool-bar/formatters/replace-selection'
|
||||
import styles from './media-entry.module.css'
|
||||
|
||||
export interface MediaEntryProps {
|
||||
entry: MediaUpload
|
||||
|
@ -37,7 +39,7 @@ export const MediaEntry: React.FC<MediaEntryProps> = ({ entry, onDelete }) => {
|
|||
const isOwner = useIsOwner()
|
||||
|
||||
const imageUrl = useMemo(() => {
|
||||
return `${baseUrl}api/private/media/${entry.id}`
|
||||
return `${baseUrl}media/${entry.uuid}`
|
||||
}, [entry, baseUrl])
|
||||
const textCreatedTime = useMemo(() => {
|
||||
return new Date(entry.createdAt).toLocaleString()
|
||||
|
@ -47,7 +49,7 @@ export const MediaEntry: React.FC<MediaEntryProps> = ({ entry, onDelete }) => {
|
|||
changeEditorContent?.(({ currentSelection }) => {
|
||||
return replaceSelection(
|
||||
{ from: currentSelection.to ?? currentSelection.from },
|
||||
``,
|
||||
``,
|
||||
true
|
||||
)
|
||||
})
|
||||
|
@ -61,10 +63,15 @@ export const MediaEntry: React.FC<MediaEntryProps> = ({ entry, onDelete }) => {
|
|||
<div className={'p-2 border-bottom border-opacity-50'}>
|
||||
<a href={imageUrl} target={'_blank'} rel={'noreferrer'} className={'text-center d-block mb-2'}>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={imageUrl} alt={`Upload ${entry.id}`} height={100} className={'mw-100'} />
|
||||
<img src={imageUrl} alt={`Upload ${entry.fileName}`} className={styles.preview} />
|
||||
</a>
|
||||
<div className={'w-100 d-flex flex-row align-items-center justify-content-between'}>
|
||||
<div>
|
||||
<small>
|
||||
<IconFileText className={'me-1'} />
|
||||
{entry.fileName}
|
||||
</small>
|
||||
<br />
|
||||
<small className={'d-inline-flex flex-row align-items-center'}>
|
||||
<IconPerson className={'me-1'} />
|
||||
<UserAvatarForUsername username={entry.username} size={'sm'} />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue