a0b85dfbca
file name clicked
158 lines
3.9 KiB
TypeScript
158 lines
3.9 KiB
TypeScript
import React from 'react';
|
|
//import logo from './logo.svg';
|
|
import './App.css';
|
|
import { useState, useEffect } from 'react';
|
|
|
|
function App() {
|
|
const [data, setData] = useState('');
|
|
const [category, setCategory] = useState('');
|
|
|
|
useEffect(() => {
|
|
post(category, (json: string) => {
|
|
setData(json);
|
|
});
|
|
});
|
|
|
|
return (
|
|
<div className="App">
|
|
<div className="Header">
|
|
{getContents(data, true, category, setCategory)}
|
|
</div>
|
|
<div className="Contents">
|
|
{getContents(data, false, category, setCategory)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface galleryItemInfo {
|
|
is_dir: boolean;
|
|
url: string;
|
|
thumbnail_url: string;
|
|
}
|
|
|
|
function getContents(
|
|
data: string,
|
|
getDir: boolean,
|
|
category: string,
|
|
setCategory: (category: string) => void
|
|
) {
|
|
if (data === '') return;
|
|
|
|
let obj = null;
|
|
try {
|
|
obj = JSON.parse(data);
|
|
} catch (error: unknown) {
|
|
if (!(error instanceof SyntaxError)) {
|
|
throw new Error(error as unknown as undefined);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
return obj
|
|
.sort((a: galleryItemInfo, b: galleryItemInfo) => {
|
|
if (a.is_dir && b.is_dir) return 0;
|
|
if (a.is_dir && !b.is_dir) return -1;
|
|
if (!a.is_dir && b.is_dir) return 1;
|
|
if (!a.is_dir && !b.is_dir) return 0;
|
|
})
|
|
.filter((item: galleryItemInfo) => {
|
|
return getDir == item.is_dir;
|
|
})
|
|
.map((item: galleryItemInfo, index: number) => {
|
|
const url = item.thumbnail_url === null ? item.url : item.thumbnail_url;
|
|
let onClick = () => {};
|
|
if (item.is_dir) {
|
|
onClick = () => {
|
|
const subCategory = getFileName(url);
|
|
|
|
if (category !== '') category = `${category}/${subCategory}`;
|
|
else category = subCategory;
|
|
if (subCategory === '..')
|
|
category = category.split('/').slice(0, -2).join('/');
|
|
|
|
setCategory(category);
|
|
};
|
|
return <DirectoryItem key={index} url={url} onClick={onClick} />;
|
|
}
|
|
if (url.endsWith('.mp4')) {
|
|
return <VideoItem key={index} url={url} onClick={onClick} />;
|
|
}
|
|
return <ImageItem key={index} url={url} onClick={onClick} />;
|
|
});
|
|
}
|
|
|
|
interface galleryItem {
|
|
url: string;
|
|
onClick: () => void;
|
|
}
|
|
|
|
function ImageItem({ url }: galleryItem) {
|
|
return (
|
|
<div className="GalleryItem">
|
|
<a href={url} target="_blank">
|
|
{getFileName(url)}
|
|
</a>
|
|
<img src={url} loading="lazy" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function VideoItem({ url }: galleryItem) {
|
|
return (
|
|
<div className="GalleryItem">
|
|
<a href={url} target="_blank">
|
|
{getFileName(url)}
|
|
</a>
|
|
<video controls>
|
|
<source src={url} type="video/mp4" />
|
|
</video>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function DirectoryItem({ url, onClick }: galleryItem) {
|
|
let buttonText = getFileName(url);
|
|
const isBackButton = buttonText === '..';
|
|
buttonText = isBackButton ? 'Back' : `Category: ${buttonText}`;
|
|
const backButtonClass = isBackButton ? 'ParentDirectoryItem' : '';
|
|
return (
|
|
<div className={`DirectoryItem ${backButtonClass}`}>
|
|
<button className="DirectoryItem" onClick={onClick}>
|
|
{buttonText}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function getFileName(string: string): string {
|
|
return string.split('/').at(-1) as unknown as string;
|
|
}
|
|
|
|
function post(category: string, callback: (text: string) => void) {
|
|
fetch('http://localhost/photo-viewer-backend/php/get.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
category: category,
|
|
}),
|
|
})
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return response;
|
|
})
|
|
.then((response) => response.text())
|
|
.then((data) => {
|
|
callback(data as unknown as string);
|
|
})
|
|
.catch((error) => {
|
|
console.error('There was a problem with the fetch operation:', error);
|
|
});
|
|
}
|
|
|
|
export default App;
|