Compare commits
	
		
			2 Commits
		
	
	
		
			098777bb02
			...
			8a1b52749b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8a1b52749b | |||
| d959c004dd | 
| @ -8,8 +8,7 @@ body { | |||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: row; |   flex-direction: row; | ||||||
| 
 | 
 | ||||||
|   margin: 1em; |   padding: 1em; | ||||||
|   padding: 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .Contents { | .Contents { | ||||||
| @ -40,6 +39,7 @@ body { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .GalleryItem > img, video { | .GalleryItem > img, video { | ||||||
|  |   object-fit: contain; | ||||||
|   max-height: 80vh; |   max-height: 80vh; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										177
									
								
								src/App.tsx
									
									
									
									
									
								
							
							
						
						
									
										177
									
								
								src/App.tsx
									
									
									
									
									
								
							| @ -1,185 +1,14 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| //import logo from './logo.svg';
 |  | ||||||
| import './App.css'; | import './App.css'; | ||||||
| import { useState, useEffect } from 'react'; | 
 | ||||||
|  | import Gallery from './Gallery/index'; | ||||||
| 
 | 
 | ||||||
| function App() { | function App() { | ||||||
|   const [data, setData] = useState(''); |  | ||||||
|   const [category, setCategory] = useState(''); |  | ||||||
| 
 |  | ||||||
|   useEffect(() => { |  | ||||||
|     post(category, (json: string) => { |  | ||||||
|       setData(json); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   return ( |   return ( | ||||||
|     <div className="App"> |     <div className="App"> | ||||||
|       <div className="Header"> |       <Gallery /> | ||||||
|         {getContents(data, true, category, setCategory)} |  | ||||||
|       </div> |  | ||||||
|       <div className="Contents"> |  | ||||||
|         {getContents(data, false, category, setCategory)} |  | ||||||
|       </div> |  | ||||||
|     </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.url; |  | ||||||
|       const thumbnail_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} |  | ||||||
|             thumbnail_url={thumbnail_url} |  | ||||||
|             url={url} |  | ||||||
|             onClick={onClick} |  | ||||||
|           /> |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|       if (url.endsWith('.mp4')) { |  | ||||||
|         return ( |  | ||||||
|           <VideoItem |  | ||||||
|             key={index} |  | ||||||
|             thumbnail_url={thumbnail_url} |  | ||||||
|             url={url} |  | ||||||
|             onClick={onClick} |  | ||||||
|           /> |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|       return ( |  | ||||||
|         <ImageItem |  | ||||||
|           key={index} |  | ||||||
|           thumbnail_url={thumbnail_url} |  | ||||||
|           url={url} |  | ||||||
|           onClick={onClick} |  | ||||||
|         /> |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| interface galleryItem { |  | ||||||
|   url: string; |  | ||||||
|   thumbnail_url: string; |  | ||||||
|   onClick: () => void; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function ImageItem({ thumbnail_url, url }: galleryItem) { |  | ||||||
|   return ( |  | ||||||
|     <div className="GalleryItem"> |  | ||||||
|       <a href={url} target="_blank"> |  | ||||||
|         {getFileName(url)} |  | ||||||
|       </a> |  | ||||||
|       <img src={thumbnail_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',
 |  | ||||||
|     'https://dundun.ddns.net/photo-viewer/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; | export default App; | ||||||
|  | |||||||
							
								
								
									
										167
									
								
								src/Gallery/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/Gallery/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,167 @@ | |||||||
|  | import React from 'react'; | ||||||
|  | import '../App.css'; | ||||||
|  | import { useState, useEffect } from 'react'; | ||||||
|  | 
 | ||||||
|  | function Gallery() { | ||||||
|  |   const [data, setData] = useState(''); | ||||||
|  |   const [category, setCategory] = useState(''); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     post(category, (json: string) => { | ||||||
|  |       setData(json); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className="Gallery"> | ||||||
|  |       <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 itemProps = { | ||||||
|  |         key: index, | ||||||
|  |         url: item.url, | ||||||
|  |         thumbnail_url: | ||||||
|  |           item.thumbnail_url === null ? item.url : item.thumbnail_url, | ||||||
|  |         onClick: () => {}, | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       if (item.is_dir) { | ||||||
|  |         itemProps.onClick = () => { | ||||||
|  |           const subCategory = getFileName(itemProps.url); | ||||||
|  | 
 | ||||||
|  |           if (category !== '') category = `${category}/${subCategory}`; | ||||||
|  |           else category = subCategory; | ||||||
|  |           if (subCategory === '..') | ||||||
|  |             category = category.split('/').slice(0, -2).join('/'); | ||||||
|  | 
 | ||||||
|  |           setCategory(category); | ||||||
|  |         }; | ||||||
|  |         return <DirectoryItem {...itemProps} />; | ||||||
|  |       } | ||||||
|  |       if (itemProps.url.endsWith('.mp4')) { | ||||||
|  |         return <VideoItem {...itemProps} />; | ||||||
|  |       } | ||||||
|  |       return <ImageItem {...itemProps} />; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface galleryItem { | ||||||
|  |   url: string; | ||||||
|  |   thumbnail_url: string; | ||||||
|  |   onClick: () => void; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function ImageItem({ thumbnail_url, url }: galleryItem) { | ||||||
|  |   return ( | ||||||
|  |     <div className="GalleryItem"> | ||||||
|  |       <a href={url} target="_blank"> | ||||||
|  |         {getFileName(url)} | ||||||
|  |       </a> | ||||||
|  |       <img src={thumbnail_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', | ||||||
|  |     //'https://dundun.ddns.net/photo-viewer/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 Gallery; | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user