extract and cleanup some functions

This commit is contained in:
spencerwooo
2022-02-05 21:16:57 +08:00
parent b42036afb7
commit 53470ff61e
4 changed files with 52 additions and 60 deletions
+26 -14
View File
@@ -1,23 +1,17 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import toast, { Toaster } from 'react-hot-toast' import toast, { Toaster } from 'react-hot-toast'
import emojiRegex from 'emoji-regex' import emojiRegex from 'emoji-regex'
import { useClipboard } from 'use-clipboard-copy'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import { FC, MouseEventHandler, SetStateAction, useEffect, useRef, useState } from 'react' import { FC, MouseEventHandler, SetStateAction, useEffect, useRef, useState } from 'react'
import Link from 'next/link'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { layouts } from './SwitchLayout'
import useLocalStorage from '../utils/useLocalStorage' import useLocalStorage from '../utils/useLocalStorage'
import { humanFileSize, formatModifiedDateTime } from '../utils/fileDetails'
import { getFileIcon } from '../utils/getFileIcon'
import { getPreviewType, preview } from '../utils/getPreviewType' import { getPreviewType, preview } from '../utils/getPreviewType'
import { useProtectedSWRInfinite } from '../utils/fetchWithSWR' import { useProtectedSWRInfinite } from '../utils/fetchWithSWR'
import { getBaseUrl } from '../utils/getBaseUrl' import { getFileIcon } from '../utils/getFileIcon'
import { import {
DownloadingToast, DownloadingToast,
downloadMultipleFiles, downloadMultipleFiles,
@@ -25,6 +19,7 @@ import {
traverseFolder, traverseFolder,
} from './MultiFileDownloader' } from './MultiFileDownloader'
import { layouts } from './SwitchLayout'
import Loading, { LoadingIcon } from './Loading' import Loading, { LoadingIcon } from './Loading'
import FourOhFour from './FourOhFour' import FourOhFour from './FourOhFour'
import Auth from './Auth' import Auth from './Auth'
@@ -36,14 +31,13 @@ import AudioPreview from './previews/AudioPreview'
import VideoPreview from './previews/VideoPreview' import VideoPreview from './previews/VideoPreview'
import PDFPreview from './previews/PDFPreview' import PDFPreview from './previews/PDFPreview'
import URLPreview from './previews/URLPreview' import URLPreview from './previews/URLPreview'
import DefaultPreview from './previews/DefaultPreview'
import { DownloadBtnContainer, PreviewContainer } from './previews/Containers'
import DownloadButtonGroup from './DownloadBtnGtoup'
import FolderListLayout from './FolderListLayout'
import type { OdFileObject, OdFolderObject } from '../types'
import FolderGridLayout from './FolderGridLayout'
import ImagePreview from './previews/ImagePreview' import ImagePreview from './previews/ImagePreview'
import DefaultPreview from './previews/DefaultPreview'
import { PreviewContainer } from './previews/Containers'
import type { OdFileObject, OdFolderChildren, OdFolderObject } from '../types'
import FolderListLayout from './FolderListLayout'
import FolderGridLayout from './FolderGridLayout'
// Disabling SSR for some previews // Disabling SSR for some previews
const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), {
@@ -66,6 +60,24 @@ const queryToPath = (query?: ParsedUrlQuery) => {
return '/' return '/'
} }
// Render the icon of a folder child (may be a file or a folder), use emoji if the name of the child contains emoji
const renderEmoji = (name: string) => {
const emoji = emojiRegex().exec(name)
return { render: emoji && !emoji.index, emoji }
}
export const formatChildName = (name: string) => {
const { render, emoji } = renderEmoji(name)
return render ? name.replace(emoji ? emoji[0] : '', '').trim() : name
}
export const ChildIcon: FC<{ child: OdFolderChildren }> = ({ child }) => {
const { render, emoji } = renderEmoji(child.name)
return render ? (
<span>{emoji ? emoji[0] : '📁'}</span>
) : (
<FontAwesomeIcon icon={child.file ? getFileIcon(child.name, { video: Boolean(child.video) }) : ['far', 'folder']} />
)
}
export const Checkbox: FC<{ export const Checkbox: FC<{
checked: 0 | 1 | 2 checked: 0 | 1 | 2
onChange: () => void onChange: () => void
+16 -25
View File
@@ -1,29 +1,15 @@
import type { OdFolderObject } from '../types' import type { OdFolderChildren } from '../types'
import { useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import emojiRegex from 'emoji-regex' import { useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useClipboard } from 'use-clipboard-copy' import { useClipboard } from 'use-clipboard-copy'
import { getFileIcon } from '../utils/getFileIcon'
import { getBaseUrl } from '../utils/getBaseUrl' import { getBaseUrl } from '../utils/getBaseUrl'
import { formatModifiedDateTime } from '../utils/fileDetails' import { formatModifiedDateTime } from '../utils/fileDetails'
import { Checkbox, Downloading } from './FileListing' import { Checkbox, ChildIcon, Downloading, formatChildName } from './FileListing'
type OdFolderChildren = OdFolderObject['value'][number]
const GridItem = ({ c }: { c: OdFolderChildren }) => { const GridItem = ({ c }: { c: OdFolderChildren }) => {
const emojiIcon = emojiRegex().exec(c.name)
const renderEmoji = emojiIcon && !emojiIcon.index
const ChildIcon = () =>
renderEmoji ? (
<span>{emojiIcon ? emojiIcon[0] : '📁'}</span>
) : (
<FontAwesomeIcon icon={c.file ? getFileIcon(c.name, { video: Boolean(c.video) }) : ['far', 'folder']} />
)
// We use the generated medium thumbnail for rendering preview images // We use the generated medium thumbnail for rendering preview images
const thumbnail = c.thumbnails && c.thumbnails.length > 0 ? c.thumbnails[0].medium : null const thumbnail = c.thumbnails && c.thumbnails.length > 0 ? c.thumbnails[0].medium : null
@@ -43,7 +29,7 @@ const GridItem = ({ c }: { c: OdFolderChildren }) => {
/> />
) : ( ) : (
<div className="relative flex h-full w-full items-center justify-center rounded-lg"> <div className="relative flex h-full w-full items-center justify-center rounded-lg">
<ChildIcon /> <ChildIcon child={c} />
<span className="absolute bottom-0 right-0 m-1 font-medium text-gray-700 dark:text-gray-500"> <span className="absolute bottom-0 right-0 m-1 font-medium text-gray-700 dark:text-gray-500">
{c.folder?.childCount} {c.folder?.childCount}
</span> </span>
@@ -53,11 +39,9 @@ const GridItem = ({ c }: { c: OdFolderChildren }) => {
<div className="flex items-start justify-center space-x-2"> <div className="flex items-start justify-center space-x-2">
<span className="w-5 flex-shrink-0 text-center"> <span className="w-5 flex-shrink-0 text-center">
<ChildIcon /> <ChildIcon child={c} />
</span>
<span className="overflow-hidden truncate">
{renderEmoji ? c.name.replace(emojiIcon ? emojiIcon[0] : '', '').trim() : c.name}
</span> </span>
<span className="overflow-hidden truncate">{formatChildName(c.name)}</span>
</div> </div>
<div className="truncate text-center font-mono text-xs text-gray-700 dark:text-gray-500"> <div className="truncate text-center font-mono text-xs text-gray-700 dark:text-gray-500">
{formatModifiedDateTime(c.lastModifiedDateTime)} {formatModifiedDateTime(c.lastModifiedDateTime)}
@@ -109,8 +93,11 @@ const FolderGridLayout = ({
<div className="grid grid-cols-2 gap-3 p-3 md:grid-cols-4"> <div className="grid grid-cols-2 gap-3 p-3 md:grid-cols-4">
{folderChildren.map((c: OdFolderChildren) => ( {folderChildren.map((c: OdFolderChildren) => (
<div key={c.id} className="group relative overflow-hidden rounded hover:bg-gray-100 dark:hover:bg-gray-850"> <div
<div className="absolute top-0 right-0 z-10 m-1 rounded bg-white/50 py-0.5 dark:bg-gray-900/50"> key={c.id}
className="group relative overflow-hidden rounded transition-all duration-100 hover:bg-gray-100 dark:hover:bg-gray-850"
>
<div className="absolute top-0 right-0 z-10 m-1 rounded bg-white/50 py-0.5 opacity-0 transition-all duration-100 group-hover:opacity-100 dark:bg-gray-900/50">
{c.folder ? ( {c.folder ? (
<div> <div>
<span <span
@@ -163,7 +150,11 @@ const FolderGridLayout = ({
)} )}
</div> </div>
<div className="absolute top-0 left-0 z-10 m-1 rounded bg-white/50 py-0.5 dark:bg-gray-900/50"> <div
className={`${
selected[c.id] ? 'opacity-100' : 'opacity-0'
} absolute top-0 left-0 z-10 m-1 rounded bg-white/50 py-0.5 group-hover:opacity-100 dark:bg-gray-900/50`}
>
{!c.folder && !(c.name === '.password') && ( {!c.folder && !(c.name === '.password') && (
<Checkbox <Checkbox
checked={selected[c.id] ? 2 : 0} checked={selected[c.id] ? 2 : 0}
+9 -21
View File
@@ -1,38 +1,23 @@
import type { OdFolderObject } from '../types' import type { OdFolderChildren } from '../types'
import Link from 'next/link'
import { FC } from 'react' import { FC } from 'react'
import emojiRegex from 'emoji-regex'
import { useClipboard } from 'use-clipboard-copy' import { useClipboard } from 'use-clipboard-copy'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import { getBaseUrl } from '../utils/getBaseUrl' import { getBaseUrl } from '../utils/getBaseUrl'
import { getFileIcon } from '../utils/getFileIcon'
import { humanFileSize, formatModifiedDateTime } from '../utils/fileDetails' import { humanFileSize, formatModifiedDateTime } from '../utils/fileDetails'
import { Downloading, Checkbox } from './FileListing' import { Downloading, Checkbox, formatChildName, ChildIcon } from './FileListing'
type OdFolderChildren = OdFolderObject['value'][number]
const FileListItem: FC<{ fileContent: OdFolderChildren }> = ({ fileContent: c }) => { const FileListItem: FC<{ fileContent: OdFolderChildren }> = ({ fileContent: c }) => {
const emojiIcon = emojiRegex().exec(c.name)
const renderEmoji = emojiIcon && !emojiIcon.index
return ( return (
<div className="grid cursor-pointer grid-cols-10 items-center space-x-2 px-3 py-2.5"> <div className="grid cursor-pointer grid-cols-10 items-center space-x-2 px-3 py-2.5">
<div className="col-span-10 flex items-center space-x-2 truncate md:col-span-6" title={c.name}> <div className="col-span-10 flex items-center space-x-2 truncate md:col-span-6" title={c.name}>
{/* <div>{c.file ? c.file.mimeType : 'folder'}</div> */}
<div className="w-5 flex-shrink-0 text-center"> <div className="w-5 flex-shrink-0 text-center">
{renderEmoji ? ( <ChildIcon child={c} />
<span>{emojiIcon ? emojiIcon[0] : '📁'}</span>
) : (
<FontAwesomeIcon icon={c.file ? getFileIcon(c.name, { video: Boolean(c.video) }) : ['far', 'folder']} />
)}
</div>
<div className="truncate">
{renderEmoji ? c.name.replace(emojiIcon ? emojiIcon[0] : '', '').trim() : c.name}
</div> </div>
<div className="truncate">{formatChildName(c.name)}</div>
</div> </div>
<div className="col-span-3 hidden flex-shrink-0 font-mono text-sm text-gray-700 dark:text-gray-500 md:block"> <div className="col-span-3 hidden flex-shrink-0 font-mono text-sm text-gray-700 dark:text-gray-500 md:block">
{formatModifiedDateTime(c.lastModifiedDateTime)} {formatModifiedDateTime(c.lastModifiedDateTime)}
@@ -99,7 +84,10 @@ const FolderListLayout = ({
</div> </div>
{folderChildren.map((c: OdFolderChildren) => ( {folderChildren.map((c: OdFolderChildren) => (
<div className="grid grid-cols-12 hover:bg-gray-100 dark:hover:bg-gray-850" key={c.id}> <div
className="grid grid-cols-12 transition-all duration-100 hover:bg-gray-100 dark:hover:bg-gray-850"
key={c.id}
>
<Link href={`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`} passHref> <Link href={`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`} passHref>
<a className="col-span-10"> <a className="col-span-10">
<FileListItem fileContent={c} /> <FileListItem fileContent={c} />
+1
View File
@@ -21,6 +21,7 @@ export type OdFolderObject = {
thumbnails?: Array<OdThumbnail> thumbnails?: Array<OdThumbnail>
}> }>
} }
export type OdFolderChildren = OdFolderObject['value'][number]
// A file object returned from the OneDrive API. This object may contain 'video' if the file is a video. // A file object returned from the OneDrive API. This object may contain 'video' if the file is a video.
export type OdFileObject = { export type OdFileObject = {
'@microsoft.graph.downloadUrl': string '@microsoft.graph.downloadUrl': string