mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-06 17:02:54 +02:00
Media dashboard fixes + improvements
This commit is contained in:
+4
-1
@@ -11,11 +11,14 @@
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
- [#316](https://github.com/estruyf/vscode-front-matter/issues/316): Surpress file parsing errors when closing the dashboard
|
||||
- [#316](https://github.com/estruyf/vscode-front-matter/issues/316): Suppress file parsing errors when closing the dashboard
|
||||
|
||||
### 🐞 Fixes
|
||||
|
||||
- Hide the view mode action from the Front Matter panel if no custom modes are defined
|
||||
- Fix in decode base64 uploaded video files
|
||||
- Fix for a lightbox on other types of documents (pdf, etc.)
|
||||
- Fix for hiding the image preview on slide-over for none image documents
|
||||
|
||||
## [7.1.2] - 2022-04-11
|
||||
|
||||
|
||||
Generated
+8552
-24
File diff suppressed because it is too large
Load Diff
@@ -18,12 +18,13 @@ export interface IDetailsSlideOverProps {
|
||||
folder: string;
|
||||
media: MediaInfo;
|
||||
showForm: boolean;
|
||||
isImageFile: boolean;
|
||||
onEdit: () => void;
|
||||
onEditClose: () => void;
|
||||
onDismiss: () => void;
|
||||
}
|
||||
|
||||
export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> = ({ imgSrc, size, dimensions, media, folder, showForm, onEdit, onEditClose, onDismiss }: React.PropsWithChildren<IDetailsSlideOverProps>) => {
|
||||
export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> = ({ imgSrc, size, dimensions, media, folder, showForm, onEdit, onEditClose, onDismiss, isImageFile }: React.PropsWithChildren<IDetailsSlideOverProps>) => {
|
||||
const [ filename, setFilename ] = React.useState<string>(media.filename);
|
||||
const [ caption, setCaption ] = React.useState<string | undefined>(media.caption);
|
||||
const [ alt, setAlt ] = React.useState(media.alt);
|
||||
@@ -93,9 +94,13 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
|
||||
<div className="relative mt-6 flex-1 px-4 sm:px-6">
|
||||
<div className="absolute inset-0 px-4 sm:px-6 space-y-8">
|
||||
<div>
|
||||
<div className="block w-full aspect-w-10 aspect-h-7 overflow-hidden border-gray-200 dark:border-vulcan-200 border">
|
||||
<img src={imgSrc} alt={media.filename} className="object-cover" />
|
||||
</div>
|
||||
{
|
||||
isImageFile && (
|
||||
<div className="block w-full aspect-w-10 aspect-h-7 overflow-hidden border-gray-200 dark:border-vulcan-200 border">
|
||||
<img src={imgSrc} alt={media.filename} className="object-cover" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className="mt-4 flex items-start justify-between">
|
||||
<div>
|
||||
<h2 className="text-lg font-medium text-vulcan-300 dark:text-whisper-500"><span className="sr-only">Details for </span>{media.filename}</h2>
|
||||
|
||||
@@ -181,7 +181,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
|
||||
};
|
||||
|
||||
const openLightbox = useCallback(() => {
|
||||
if (!isVideoFile() && !isAudioFile()) {
|
||||
if (isImageFile) {
|
||||
setLightbox(media.vsPath || "");
|
||||
}
|
||||
}, [media.vsPath]);
|
||||
@@ -200,21 +200,21 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
|
||||
))
|
||||
}
|
||||
|
||||
const isVideoFile = useCallback(() => {
|
||||
const isVideoFile = useMemo(() => {
|
||||
if (media.mimeType?.startsWith("video/")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, [media]);
|
||||
|
||||
const isAudioFile = useCallback(() => {
|
||||
const isAudioFile = useMemo(() => {
|
||||
if (media.mimeType?.startsWith("audio/")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, [media]);
|
||||
|
||||
const isImageFile = useCallback(() => {
|
||||
const isImageFile = useMemo(() => {
|
||||
if (media.mimeType?.startsWith("image/")) {
|
||||
return true;
|
||||
}
|
||||
@@ -222,27 +222,37 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
|
||||
}, [media]);
|
||||
|
||||
const renderMediaIcon = useMemo(() => {
|
||||
if (isVideoFile()) {
|
||||
return <VideoCameraIcon className={`h-1/2 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}
|
||||
|
||||
if (isAudioFile()) {
|
||||
return <MusicNoteIcon className={`h-1/2 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}
|
||||
const path = media.fsPath;
|
||||
const extension = path.split('.').pop();
|
||||
|
||||
if (isImageFile()) {
|
||||
if (isImageFile) {
|
||||
return <PhotographIcon className={`h-1/2 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}
|
||||
|
||||
return <DocumentIcon className={`h-1/2 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}, [media]);
|
||||
let icon = <DocumentIcon className={`h-4/6 text-gray-300 dark:text-vulcan-200`} />;
|
||||
|
||||
if (isVideoFile) {
|
||||
icon = <VideoCameraIcon className={`h-4/6 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}
|
||||
|
||||
if (isAudioFile) {
|
||||
icon = <MusicNoteIcon className={`h-4/6 text-gray-300 dark:text-vulcan-200`} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='w-full h-full flex justify-center items-center'>
|
||||
{icon}
|
||||
<span className='text-2xl font-bold absolute top-0 right-0 bottom-0 left-0 flex justify-center items-center'>{extension}</span>
|
||||
</div>
|
||||
);
|
||||
}, [media, isImageFile, isVideoFile, isAudioFile]);
|
||||
|
||||
const renderMedia = useMemo(() => {
|
||||
if (isVideoFile() || isAudioFile()) {
|
||||
if (isVideoFile || isAudioFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isImageFile()) {
|
||||
if (isImageFile) {
|
||||
return <img src={media.vsPath} alt={basename(media.fsPath)} className="mx-auto object-cover" />;
|
||||
}
|
||||
|
||||
@@ -271,7 +281,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
|
||||
return (
|
||||
<>
|
||||
<li className="group relative bg-gray-50 dark:bg-vulcan-200 shadow-md hover:shadow-xl dark:shadow-none dark:hover:bg-vulcan-100 border border-gray-200 dark:border-vulcan-50">
|
||||
<button className="relative bg-gray-200 dark:bg-vulcan-300 block w-full aspect-w-10 aspect-h-7 overflow-hidden cursor-pointer h-48" onClick={openLightbox}>
|
||||
<button className={`relative bg-gray-200 dark:bg-vulcan-300 block w-full aspect-w-10 aspect-h-7 overflow-hidden h-48 ${isImageFile ? "cursor-pointer" : "cursor-default"}`} onClick={openLightbox}>
|
||||
<div className={`absolute top-0 right-0 bottom-0 left-0 flex items-center justify-center`}>
|
||||
{
|
||||
renderMediaIcon
|
||||
@@ -424,6 +434,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
|
||||
folder={getFolder()}
|
||||
media={media}
|
||||
showForm={showForm}
|
||||
isImageFile={isImageFile}
|
||||
onEdit={() => setShowForm(true)}
|
||||
onEditClose={() => setShowForm(false)}
|
||||
onDismiss={() => { setShowDetails(false); setShowForm(false); }} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { decodeBase64Image, Extension, MediaLibrary, Notifications, parseWinPath, Settings, Sorting } from ".";
|
||||
import { decodeBase64, Extension, MediaLibrary, Notifications, parseWinPath, Settings, Sorting } from ".";
|
||||
import { Dashboard } from "../commands/Dashboard";
|
||||
import { Folders } from "../commands/Folders";
|
||||
import { DEFAULT_CONTENT_TYPE, ExtensionState, HOME_PAGE_NAVIGATION_ID, SETTING_CONTENT_STATIC_FOLDER, SETTING_MEDIA_SUPPORTED_MIMETYPES } from "../constants";
|
||||
@@ -228,7 +228,7 @@ export class MediaHelpers {
|
||||
}
|
||||
|
||||
const staticPath = join(absFolderPath, fileName);
|
||||
const imgData = decodeBase64Image(contents);
|
||||
const imgData = decodeBase64(contents);
|
||||
|
||||
if (imgData) {
|
||||
writeFileSync(staticPath, imgData.data);
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
export const decodeBase64Image = (dataString: string) => {
|
||||
const matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
|
||||
let response: any = {};
|
||||
export const decodeBase64 = (dataString: string) => {
|
||||
const dataParts = dataString.split(';base64,');
|
||||
|
||||
if (matches?.length !== 3) {
|
||||
if (dataParts?.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
response.type = matches[1];
|
||||
response.data = Buffer.from(matches[2], 'base64');
|
||||
const typePart = dataParts[0].split(':').pop() as string;
|
||||
const dataPart = dataParts.pop() as string;
|
||||
|
||||
let response: any = {};
|
||||
|
||||
response.type = typePart;
|
||||
response.data = Buffer.from(dataPart, 'base64');
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user