diff --git a/.eslintrc b/.eslintrc index 97a2bb8..913cdba 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,3 @@ { - "extends": ["next", "next/core-web-vitals"] + "extends": ["next", "next/core-web-vitals", "prettier"] } diff --git a/.gitignore b/.gitignore index b161a64..f383956 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,39 @@ yarn-error.log* # redis dump dump.rdb + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +.vscode/* + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..77ab421 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,9 @@ +module.exports = { + printWidth: 120, + arrowParens: "avoid", + singleQuote: true, + semi: false, + plugins: [ + require('prettier-plugin-tailwindcss') + ] +} diff --git a/components/FileListing.tsx b/components/FileListing.tsx index c2835b7..9ffff95 100644 --- a/components/FileListing.tsx +++ b/components/FileListing.tsx @@ -41,7 +41,9 @@ import type { OdFileObject, OdFolderObject } from '../types' // Disabling SSR for some previews (image gallery view, and PDF view) const ReactViewer = dynamic(() => import('react-viewer'), { ssr: false }) -const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { ssr: false }) +const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { + ssr: false, +}) /** * Convert url query into path string @@ -151,7 +153,9 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { const [selected, setSelected] = useState<{ [key: string]: boolean }>({}) const [totalSelected, setTotalSelected] = useState<0 | 1 | 2>(0) const [totalGenerating, setTotalGenerating] = useState(false) - const [folderGenerating, setFolderGenerating] = useState<{ [key: string]: boolean }>({}) + const [folderGenerating, setFolderGenerating] = useState<{ + [key: string]: boolean + }>({}) const router = useRouter() const clipboard = useClipboard() @@ -283,7 +287,9 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { downloadMultipleFiles({ toastId, router, files, folder }) .then(() => { setTotalGenerating(false) - toast.success('Finished downloading selected files.', { id: toastId }) + toast.success('Finished downloading selected files.', { + id: toastId, + }) }) .catch(() => { setTotalGenerating(false) @@ -312,7 +318,13 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { setFolderGenerating({ ...folderGenerating, [id]: true }) const toastId = toast.loading(DownloadingToast(router)) - downloadTreelikeMultipleFiles({ toastId, router, files, basePath: path, folder: name }) + downloadTreelikeMultipleFiles({ + toastId, + router, + files, + basePath: path, + folder: name, + }) .then(() => { setFolderGenerating({ ...folderGenerating, [id]: false }) toast.success('Finished downloading folder.', { id: toastId }) @@ -394,7 +406,9 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { render: , onClick: i => { clipboard.copy(i.alt ? `${getBaseUrl()}/api?path=${path + '/' + i.alt}&raw=true` : '') - toast('Copied image permanent link to clipboard.', { icon: 'πŸ‘Œ' }) + toast('Copied image permanent link to clipboard.', { + icon: 'πŸ‘Œ', + }) }, }, ]) @@ -544,7 +558,9 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => { const fileName = file.name const fileExtension = fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase() - const previewType = getPreviewType(fileExtension, { video: Boolean(file.video) }) + const previewType = getPreviewType(fileExtension, { + video: Boolean(file.video), + }) if (previewType) { switch (previewType) { case preview.image: diff --git a/components/FourOhFour.tsx b/components/FourOhFour.tsx index 927c56f..cffee5c 100644 --- a/components/FourOhFour.tsx +++ b/components/FourOhFour.tsx @@ -4,7 +4,7 @@ const FourOhFour: React.FC<{ errorMsg: string }> = ({ errorMsg }) => { return (
- 404 + 404
diff --git a/components/MultiFileDownloader.tsx b/components/MultiFileDownloader.tsx index b4f5b60..85115ca 100644 --- a/components/MultiFileDownloader.tsx +++ b/components/MultiFileDownloader.tsx @@ -81,7 +81,9 @@ export async function downloadMultipleFiles({ // Create zip file and download it const b = await zip.generateAsync({ type: 'blob' }, metadata => { - toast.loading(DownloadingToast(router, metadata.percent.toFixed(0)), { id: toastId }) + toast.loading(DownloadingToast(router, metadata.percent.toFixed(0)), { + id: toastId, + }) }) downloadBlob({ blob: b, name: folder ? folder + '.zip' : 'download.zip' }) } @@ -147,7 +149,9 @@ export async function downloadTreelikeMultipleFiles({ // Create zip file and download it const b = await zip.generateAsync({ type: 'blob' }, metadata => { - toast.loading(DownloadingToast(router, metadata.percent.toFixed(0)), { id: toastId }) + toast.loading(DownloadingToast(router, metadata.percent.toFixed(0)), { + id: toastId, + }) }) downloadBlob({ blob: b, name: folder ? folder + '.zip' : 'download.zip' }) } @@ -214,7 +218,7 @@ export async function* traverseFolder(path: string): AsyncGenerator< isFolder: boolean error?: { status: number; message: string } }[] - yield * items + yield* items folderPaths = items .filter(({ error }) => !error) .filter(i => i.isFolder) diff --git a/components/previews/AudioPreview.tsx b/components/previews/AudioPreview.tsx index 65bf3f6..e2eea60 100644 --- a/components/previews/AudioPreview.tsx +++ b/components/previews/AudioPreview.tsx @@ -21,10 +21,10 @@ const AudioPreview: FC<{ file: OdFileObject }> = ({ file }) => { return ( <> -
-
+
+
{playerStatus === PlayerState.Loading ? ( - + ) : ( = ({ file }) => { /> )}
-
+
{file.name}
Last modified:{' '} @@ -44,7 +44,7 @@ const AudioPreview: FC<{ file: OdFileObject }> = ({ file }) => {
setPlayerStatus(PlayerState.Ready)} diff --git a/components/previews/Containers.tsx b/components/previews/Containers.tsx index 277a945..556a736 100644 --- a/components/previews/Containers.tsx +++ b/components/previews/Containers.tsx @@ -1,10 +1,10 @@ export function PreviewContainer({ children }): JSX.Element { - return
{children}
+ return
{children}
} export function DownloadBtnContainer({ children }): JSX.Element { return ( -
+
{children}
) diff --git a/components/previews/DefaultPreview.tsx b/components/previews/DefaultPreview.tsx index 91ce1ed..8114c4e 100644 --- a/components/previews/DefaultPreview.tsx +++ b/components/previews/DefaultPreview.tsx @@ -13,53 +13,53 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => { return (
-
-
+
+
-
{file.name}
+
{file.name}
-
+
-
Last modified
+
Last modified
{formatModifiedDateTime(file.lastModifiedDateTime)}
-
File size
+
File size
{humanFileSize(file.size)}
-
MIME type
+
MIME type
{file.file.mimeType}
-
Hashes
- +
Hashes
+
- - + - - - + - - - + - diff --git a/components/previews/EPUBPreview.tsx b/components/previews/EPUBPreview.tsx index 2e2b56e..f16405f 100644 --- a/components/previews/EPUBPreview.tsx +++ b/components/previews/EPUBPreview.tsx @@ -36,11 +36,17 @@ const EPUBPreview: FC<{ file: OdFileObject }> = ({ file }) => { return (
-
-
+
+
fixEpub(rendition)} diff --git a/components/previews/MarkdownPreview.tsx b/components/previews/MarkdownPreview.tsx index 6a4209e..469b5c1 100644 --- a/components/previews/MarkdownPreview.tsx +++ b/components/previews/MarkdownPreview.tsx @@ -14,11 +14,11 @@ import DownloadButtonGroup from '../DownloadBtnGtoup' import useAxiosGet from '../../utils/fetchOnMount' import { DownloadBtnContainer, PreviewContainer } from './Containers' -const MarkdownPreview: FC<{ file: any; path: string; standalone?: boolean }> = ({ - file, - path, - standalone = true, -}) => { +const MarkdownPreview: FC<{ + file: any + path: string + standalone?: boolean +}> = ({ file, path, standalone = true }) => { const { response: content, error, validating } = useAxiosGet(file['@microsoft.graph.downloadUrl']) // The parent folder of the markdown file, which is also the relative image folder diff --git a/components/previews/PDFPreview.tsx b/components/previews/PDFPreview.tsx index 5e3ef24..dbf1f95 100644 --- a/components/previews/PDFPreview.tsx +++ b/components/previews/PDFPreview.tsx @@ -9,7 +9,7 @@ const PDFEmbedPreview: React.FC<{ file: any }> = ({ file }) => { return (
-
+
diff --git a/components/previews/TextPreview.tsx b/components/previews/TextPreview.tsx index 15226a9..68e825b 100644 --- a/components/previews/TextPreview.tsx +++ b/components/previews/TextPreview.tsx @@ -33,7 +33,7 @@ const TextPreview = ({ file }) => { return (
-
{content}
+
{content}
diff --git a/components/previews/URLPreview.tsx b/components/previews/URLPreview.tsx index 5bf459f..389b82d 100644 --- a/components/previews/URLPreview.tsx +++ b/components/previews/URLPreview.tsx @@ -40,7 +40,7 @@ const TextPreview = ({ file }) => { return (
-
{content}
+
{content}
diff --git a/components/previews/VideoPreview.tsx b/components/previews/VideoPreview.tsx index 2f5e20c..e5c0765 100644 --- a/components/previews/VideoPreview.tsx +++ b/components/previews/VideoPreview.tsx @@ -27,7 +27,10 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { options={{ volume: 1.0, lang: 'en', - video: { url: file['@microsoft.graph.downloadUrl'], pic: thumbnail }, + video: { + url: file['@microsoft.graph.downloadUrl'], + pic: thumbnail, + }, subtitle: { url: subtitle }, }} /> diff --git a/config/api.config.js b/config/api.config.js index b23df33..22c3345 100644 --- a/config/api.config.js +++ b/config/api.config.js @@ -10,22 +10,22 @@ module.exports = { // The clientId and clientSecret are used to authenticate the user with Microsoft Graph API using OAuth. You would // not need to change anything here if you can authenticate with your personal Microsoft account with OneDrive International. - clientId: "d87bcc39-1750-4ca0-ad54-f8d0efbb2735", - obfuscatedClientSecret: "U2FsdGVkX1830zo3/pFDqaBCVBb37iLw3WnBDWGF9GIB2f4apzv0roemp8Y+iIxI3Ih5ecyukqELQEGzZlYiWg==", + clientId: 'd87bcc39-1750-4ca0-ad54-f8d0efbb2735', + obfuscatedClientSecret: 'U2FsdGVkX1830zo3/pFDqaBCVBb37iLw3WnBDWGF9GIB2f4apzv0roemp8Y+iIxI3Ih5ecyukqELQEGzZlYiWg==', // The redirectUri is the URL that the user will be redirected to after they have authenticated with Microsoft Graph API. // Likewise, you would not need to change redirectUri if you are using your personal Microsoft account with OneDrive International. - redirectUri: "http://localhost", + redirectUri: 'http://localhost', // These are the URLs of the OneDrive API endpoints. You would not need to change anything here if you are using OneDrive International // or E5 Subscription OneDrive for Business. You may need to change these if you are using OneDrive δΈ–ηΊͺ互联. - authApi: "https://login.microsoftonline.com/common/oauth2/v2.0/token", - driveApi: "https://graph.microsoft.com/v1.0/me/drive", + authApi: 'https://login.microsoftonline.com/common/oauth2/v2.0/token', + driveApi: 'https://graph.microsoft.com/v1.0/me/drive', // The scope we require are listed here, in most cases you would not need to change this as well. - scope: "user.read files.read.all offline_access", + scope: 'user.read files.read.all offline_access', // The directLinkRegex is used to match the direct link of the file from the response of the API. We originally use this to prevent // unauthorised use of the proxied download feature - but that is disabled for now. So you can safely ignore this settings. - directLinkRegex: "public[.].*[.]files[.]1drv[.]com" + directLinkRegex: 'public[.].*[.]files[.]1drv[.]com', } diff --git a/config/site.config.js b/config/site.config.js index 8c20ad2..d4257ed 100644 --- a/config/site.config.js +++ b/config/site.config.js @@ -7,17 +7,17 @@ module.exports = { // Make sure this is exactly the same as the email address you use to sign into your Microsoft account. // You can also put this in your Vercel's environment variable 'NEXT_PUBLIC_USER_PRINCIPLE_NAME' if you worry about // your email being exposed in public. - userPrincipalName: process.env.NEXT_PUBLIC_USER_PRINCIPLE_NAME || "spencer@spwoo.onmicrosoft.com", + userPrincipalName: process.env.NEXT_PUBLIC_USER_PRINCIPLE_NAME || 'spencer@spwoo.onmicrosoft.com', // [OPTIONAL] This is the website icon to the left of the title inside the navigation bar. It should be placed under the // /public directory of your GitHub project (not your OneDrive folder!), and referenced here by its relative path to /public. - icon: "/icons/128.png", + icon: '/icons/128.png', // The name of your website. Present alongside your icon. title: "Spencer's OneDrive", // The folder that you are to share publicly with onedrive-vercel-index. Use '/' if you want to share your root folder. - baseDirectory: "/", + baseDirectory: '/', // [OPTIONAL] This represents the maximum number of items that one directory lists, pagination supported. // Do note that this is limited up to 200 items by the upstream OneDrive API. @@ -26,39 +26,35 @@ module.exports = { // [OPTIONAL] We use Google Fonts natively for font customisations. // You can check and generate the required links and names at https://fonts.google.com. // googleFontSans - the sans serif font used in onedrive-vercel-index. - googleFontSans: "Inter", + googleFontSans: 'Inter', // googleFontMono - the monospace font used in onedrive-vercel-index. - googleFontMono: "Fira Mono", + googleFontMono: 'Fira Mono', // googleFontLinks - an array of links for referencing the google font assets. - googleFontLinks: [ - "https://fonts.googleapis.com/css2?family=Fira+Mono&family=Inter:wght@400;500;700&display=swap" - ], + googleFontLinks: ['https://fonts.googleapis.com/css2?family=Fira+Mono&family=Inter:wght@400;500;700&display=swap'], // [OPTIONAL] The footer component of your website. You can write HTML here, but you need to escape double // quotes - changing " to \". You can write anything here, and if you like badges, generate some with https://shields.io - footer: "Powered by onedrive-vercel-index. Made with ❀ by SpencerWoo.", + footer: + 'Powered by onedrive-vercel-index. Made with ❀ by SpencerWoo.', // [OPTIONAL] This is where you specify the folders that are password protected. It is an array of paths pointing to all // the directories in which you have .password set. Check the documentation for details. - protectedRoutes: [ - "/🌞 Private folder/u-need-a-password", - "/πŸ₯Ÿ Some test files/Protected route" - ], + protectedRoutes: ['/🌞 Private folder/u-need-a-password', '/πŸ₯Ÿ Some test files/Protected route'], // [OPTIONAL] Use "" here if you want to remove this email address from the nav bar. - email: "mailto:spencer.wushangbo@gmail.com", + email: 'mailto:spencer.wushangbo@gmail.com', // [OPTIONAL] This is an array of names and links for setting your social information and links. // In the latest update, all brand icons inside font awesome is supported and the icon to render is based on the name // you provide. See the documentation for details. links: [ { - "name": "GitHub", - "link": "https://github.com/spencerwooo/onedrive-vercel-index" + name: 'GitHub', + link: 'https://github.com/spencerwooo/onedrive-vercel-index', }, { - "name": "Telegram", - "link": "https://t.me/realSpencerWoo" - } - ] + name: 'Telegram', + link: 'https://t.me/realSpencerWoo', + }, + ], } diff --git a/package.json b/package.json index 19546ae..cd22ac6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "format": "prettier components/**/*.tsx config/*.js pages/**/*.tsx {types,utils}/**/*.ts --write" }, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.35", @@ -58,7 +59,10 @@ "autoprefixer": "^10.4.0", "eslint": "8.8.0", "eslint-config-next": "12.0.10", + "eslint-config-prettier": "^8.3.0", "postcss": "^8.4.5", + "prettier": "^2.5.1", + "prettier-plugin-tailwindcss": "^0.1.4", "tailwindcss": "^3.0.18", "typescript": "4.5.5" } diff --git a/pages/onedrive-vercel-index-oauth/step-1.tsx b/pages/onedrive-vercel-index-oauth/step-1.tsx index 75a15a1..cf1272e 100644 --- a/pages/onedrive-vercel-index-oauth/step-1.tsx +++ b/pages/onedrive-vercel-index-oauth/step-1.tsx @@ -12,24 +12,24 @@ export default function OAuthStep1() { const router = useRouter() return ( -
+
{`OAuth Step 1 - ${siteConfig.title}`} -
+
-
-
+
+
-

Welcome to your new onedrive-vercel-index πŸŽ‰

+

Welcome to your new onedrive-vercel-index πŸŽ‰

-

Step 1/3: Preparations

+

Step 1/3: Preparations

-

+

If you have not specified a REDIS_URL inside your Vercel env variable, go initialise one at{' '} @@ -49,76 +49,76 @@ export default function OAuthStep1() {

Authorisation is required as no valid{' '} - access_token or{' '} - refresh_token is + access_token or{' '} + refresh_token is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.

-
-
+
Quick XOR + {file.file.hashes.quickXorHash}
+
SHA1 + {file.file.hashes.sha1Hash}
+
SHA256 + {file.file.hashes.sha256Hash}
+
+
- - + - - - + - - - + - - - + - - - + - - - + -
+
CLIENT_ID - {apiConfig.clientId} + + {apiConfig.clientId}
+
CLIENT_SECRET* - {apiConfig.obfuscatedClientSecret} + + {apiConfig.obfuscatedClientSecret}
+
REDIRECT_URI - {apiConfig.redirectUri} + + {apiConfig.redirectUri}
+
Auth API URL - {apiConfig.authApi} + + {apiConfig.authApi}
+
Drive API URL - {apiConfig.driveApi} + + {apiConfig.driveApi}
+
API Scope - {apiConfig.scope} + + {apiConfig.scope}
-

+

If you see anything - missing or incorrect, you need to reconfigure /config/api.json{' '} + missing or incorrect, you need to reconfigure /config/api.json{' '} and redeploy this instance.

-
+