From 20990fcf08d0c9e796adbc7c9b5a28d991e7a108 Mon Sep 17 00:00:00 2001 From: Ovler <86chengyujin@gmail.com> Date: Sat, 5 Feb 2022 23:07:08 +0800 Subject: [PATCH 1/8] Try to fix CJK search --- pages/api/search.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/api/search.ts b/pages/api/search.ts index d140f6c..0edae83 100644 --- a/pages/api/search.ts +++ b/pages/api/search.ts @@ -12,7 +12,10 @@ import siteConfig from '../../config/site.config' * @returns Sanitised query string which replaces non-alphanumeric characters with ' ' */ function sanitiseQuery(query: string): string { - const sanitisedQuery = query.replace(/[^a-zA-Z0-9]/g, ' ') +/** const sanitisedQuery = query.replace(/[^a-zA-Z0-9]/g, ' ') + * Actually this will cause problems with CJK only query words as it will remove every character. + * After removing it, CJK search will be much improved. + */ return encodeURIComponent(sanitisedQuery) } From 234d826d3a95415490c3c534a5c460ad3e2c7f86 Mon Sep 17 00:00:00 2001 From: Ovler <86chengyujin@gmail.com> Date: Sat, 5 Feb 2022 23:36:49 +0800 Subject: [PATCH 2/8] fix typo --- pages/api/search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/api/search.ts b/pages/api/search.ts index 0edae83..f7c07f9 100644 --- a/pages/api/search.ts +++ b/pages/api/search.ts @@ -12,8 +12,8 @@ import siteConfig from '../../config/site.config' * @returns Sanitised query string which replaces non-alphanumeric characters with ' ' */ function sanitiseQuery(query: string): string { -/** const sanitisedQuery = query.replace(/[^a-zA-Z0-9]/g, ' ') - * Actually this will cause problems with CJK only query words as it will remove every character. + const sanitisedQuery = query +/** Actually this will cause problems with CJK only query words as it will remove every character. * After removing it, CJK search will be much improved. */ return encodeURIComponent(sanitisedQuery) From d4998466debc198ad1e8e882ada5895dbab90eb0 Mon Sep 17 00:00:00 2001 From: Ovler <86chengyujin@gmail.com> Date: Sun, 6 Feb 2022 15:27:06 +0800 Subject: [PATCH 3/8] Update search.ts --- pages/api/search.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pages/api/search.ts b/pages/api/search.ts index f7c07f9..ece3ccd 100644 --- a/pages/api/search.ts +++ b/pages/api/search.ts @@ -9,13 +9,10 @@ import siteConfig from '../../config/site.config' * Sanitize the search query * * @param query User search query, which may contain special characters - * @returns Sanitised query string which replaces non-alphanumeric characters with ' ' + * @returns Sanitised query string which encodes the '<' and '>' characters, replaces '?' and '/' characters with ' ', and replaces ''' with '''' accroading to https://stackoverflow.com/questions/41491222/single-quote-escaping-in-microsoft-graph. */ function sanitiseQuery(query: string): string { - const sanitisedQuery = query -/** Actually this will cause problems with CJK only query words as it will remove every character. - * After removing it, CJK search will be much improved. - */ + const sanitisedQuery = query.replace(/'/g, "''").replace('<', ' < ').replace('>', ' > ').replace('?', ' ').replace('/', ' ') return encodeURIComponent(sanitisedQuery) } From 96b3c92df941218e39cfadb9c890133a04cd9182 Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Sun, 6 Feb 2022 16:01:21 +0800 Subject: [PATCH 4/8] some housekeeping --- pages/api/search.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pages/api/search.ts b/pages/api/search.ts index ece3ccd..1762264 100644 --- a/pages/api/search.ts +++ b/pages/api/search.ts @@ -9,10 +9,19 @@ import siteConfig from '../../config/site.config' * Sanitize the search query * * @param query User search query, which may contain special characters - * @returns Sanitised query string which encodes the '<' and '>' characters, replaces '?' and '/' characters with ' ', and replaces ''' with '''' accroading to https://stackoverflow.com/questions/41491222/single-quote-escaping-in-microsoft-graph. + * @returns Sanitised query string, which: + * - encodes the '<' and '>' characters, + * - replaces '?' and '/' characters with ' ', + * - replaces ''' with '''' + * Reference: https://stackoverflow.com/questions/41491222/single-quote-escaping-in-microsoft-graph. */ function sanitiseQuery(query: string): string { - const sanitisedQuery = query.replace(/'/g, "''").replace('<', ' < ').replace('>', ' > ').replace('?', ' ').replace('/', ' ') + const sanitisedQuery = query + .replace(/'/g, "''") + .replace('<', ' < ') + .replace('>', ' > ') + .replace('?', ' ') + .replace('/', ' ') return encodeURIComponent(sanitisedQuery) } From 9faa2849ebbdb2ffa1d4730c39e0ab17b38aee1d Mon Sep 17 00:00:00 2001 From: myl7 Date: Mon, 7 Feb 2022 01:51:28 +0800 Subject: [PATCH 5/8] add flv video support with flv.js which is dynamicly imported --- components/previews/VideoPreview.tsx | 51 +++++++++++++++++++++------- package.json | 1 + pnpm-lock.yaml | 17 ++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/components/previews/VideoPreview.tsx b/components/previews/VideoPreview.tsx index e5c0765..5c3142f 100644 --- a/components/previews/VideoPreview.tsx +++ b/components/previews/VideoPreview.tsx @@ -3,11 +3,14 @@ import { useRouter } from 'next/router' import { useClipboard } from 'use-clipboard-copy' import DPlayer from 'react-dplayer' import toast from 'react-hot-toast' +import { useAsync } from 'react-async-hook' import { getBaseUrl } from '../../utils/getBaseUrl' import { DownloadButton } from '../DownloadBtnGtoup' import { DownloadBtnContainer, PreviewContainer } from './Containers' import { getExtension } from '../../utils/getFileIcon' +import FourOhFour from '../FourOhFour' +import Loading from '../Loading' const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { const { asPath } = useRouter() @@ -19,21 +22,45 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { // We assume subtitle files are beside the video with the same name, only webvtt '.vtt' files are supported const subtitle = `/api?path=${asPath.replace(getExtension(file.name), 'vtt')}&raw=true` + const isFlv = getExtension(file.name) === 'flv' + const { loading, error, result: flvjs } = useAsync(async () => { + if (isFlv) { + return (await import('flv.js')).default + } + }, [isFlv]) + return ( <> - + {error ? ( + + ) : loading && isFlv ? ( + + ) : ( + { + const flvPlayer = flvjs!.createPlayer({ + type: 'flv', + url: video.src + }) + flvPlayer.attachMediaElement(video) + flvPlayer.load() + } + } + }, + subtitle: { url: subtitle } + }} + /> + )} diff --git a/package.json b/package.json index d433360..36a1669 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "cors": "^2.8.5", "crypto-js": "^4.1.1", "emoji-regex": "^10.0.0", + "flv.js": "^1.6.2", "ioredis": "^4.28.2", "jszip": "^3.7.1", "next": "^12.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 514d019..f87579b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,7 @@ specifiers: eslint: 8.8.0 eslint-config-next: 12.0.10 eslint-config-prettier: ^8.3.0 + flv.js: ^1.6.2 ioredis: ^4.28.2 jszip: ^3.7.1 next: ^12.0.10 @@ -68,6 +69,7 @@ dependencies: cors: 2.8.5 crypto-js: 4.1.1 emoji-regex: 10.0.0 + flv.js: 1.6.2 ioredis: 4.28.3 jszip: 3.7.1 next: 12.0.10_react-dom@17.0.2+react@17.0.2 @@ -1185,6 +1187,10 @@ packages: es6-symbol: 3.1.3 dev: false + /es6-promise/4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + dev: false + /es6-symbol/3.1.3: resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} dependencies: @@ -1539,6 +1545,13 @@ packages: resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} dev: true + /flv.js/1.6.2: + resolution: {integrity: sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==} + dependencies: + es6-promise: 4.2.8 + webworkify-webpack: 2.1.5 + dev: false + /follow-redirects/1.14.7: resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==} engines: {node: '>=4.0'} @@ -3696,6 +3709,10 @@ packages: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} dev: false + /webworkify-webpack/2.1.5: + resolution: {integrity: sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==} + dev: false + /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: From 73651e4f50a725c95320dce6cfbf33ea20cb1fa4 Mon Sep 17 00:00:00 2001 From: myl7 Date: Tue, 8 Feb 2022 02:54:48 +0800 Subject: [PATCH 6/8] add getReadablePath util to make copied url readable --- components/DownloadBtnGtoup.tsx | 3 +- components/FolderGridLayout.tsx | 9 ++++-- components/FolderListLayout.tsx | 9 ++++-- components/previews/VideoPreview.tsx | 3 +- utils/getReadablePath.ts | 43 ++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 utils/getReadablePath.ts diff --git a/components/DownloadBtnGtoup.tsx b/components/DownloadBtnGtoup.tsx index 7f0eabc..de4d379 100644 --- a/components/DownloadBtnGtoup.tsx +++ b/components/DownloadBtnGtoup.tsx @@ -8,6 +8,7 @@ import Image from 'next/image' import { useRouter } from 'next/router' import { getBaseUrl } from '../utils/getBaseUrl' +import { getReadablePath } from '../utils/getReadablePath' const btnStyleMap = (btnColor?: string) => { const colorMap = { @@ -81,7 +82,7 @@ const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl }) /> */} { - clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`) + clipboard.copy(`${getBaseUrl()}/api?path=${getReadablePath(asPath)}&raw=true`) toast.success('Copied direct link to clipboard.') }} btnColor="pink" diff --git a/components/FolderGridLayout.tsx b/components/FolderGridLayout.tsx index 7f32807..567793b 100644 --- a/components/FolderGridLayout.tsx +++ b/components/FolderGridLayout.tsx @@ -7,6 +7,7 @@ import { useClipboard } from 'use-clipboard-copy' import { getBaseUrl } from '../utils/getBaseUrl' import { formatModifiedDateTime } from '../utils/fileDetails' +import { getReadablePath } from '../utils/getReadablePath' import { Checkbox, ChildIcon, Downloading, formatChildName } from './FileListing' const GridItem = ({ c }: { c: OdFolderChildren }) => { @@ -104,7 +105,9 @@ const FolderGridLayout = ({ title="Copy folder permalink" className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600" onClick={() => { - clipboard.copy(`${getBaseUrl()}${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`) + clipboard.copy( + `${getBaseUrl()}${getReadablePath(`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)}` + ) toast('Copied folder permalink.', { icon: '👌' }) }} > @@ -132,7 +135,9 @@ const FolderGridLayout = ({ className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600" onClick={() => { clipboard.copy( - `${getBaseUrl()}/api?path=${path === '/' ? '' : path}/${encodeURIComponent(c.name)}&raw=true` + `${getBaseUrl()}/api?path=${getReadablePath( + `${path === '/' ? '' : path}/${encodeURIComponent(c.name)}` + )}&raw=true` ) toast.success('Copied raw file permalink.') }} diff --git a/components/FolderListLayout.tsx b/components/FolderListLayout.tsx index 897cd70..2537e3f 100644 --- a/components/FolderListLayout.tsx +++ b/components/FolderListLayout.tsx @@ -7,6 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { getBaseUrl } from '../utils/getBaseUrl' import { humanFileSize, formatModifiedDateTime } from '../utils/fileDetails' +import { getReadablePath } from '../utils/getReadablePath' import { Downloading, Checkbox, formatChildName, ChildIcon } from './FileListing' @@ -100,7 +101,9 @@ const FolderListLayout = ({ title="Copy folder permalink" className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600" onClick={() => { - clipboard.copy(`${getBaseUrl()}${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`) + clipboard.copy( + `${getBaseUrl()}${getReadablePath(`${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)}` + ) toast('Copied folder permalink.', { icon: '👌' }) }} > @@ -128,7 +131,9 @@ const FolderListLayout = ({ className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600" onClick={() => { clipboard.copy( - `${getBaseUrl()}/api?path=${path === '/' ? '' : path}/${encodeURIComponent(c.name)}&raw=true` + `${getBaseUrl()}/api?path=${getReadablePath( + `${path === '/' ? '' : path}/${encodeURIComponent(c.name)}` + )}&raw=true` ) toast.success('Copied raw file permalink.') }} diff --git a/components/previews/VideoPreview.tsx b/components/previews/VideoPreview.tsx index e5c0765..875825d 100644 --- a/components/previews/VideoPreview.tsx +++ b/components/previews/VideoPreview.tsx @@ -8,6 +8,7 @@ import { getBaseUrl } from '../../utils/getBaseUrl' import { DownloadButton } from '../DownloadBtnGtoup' import { DownloadBtnContainer, PreviewContainer } from './Containers' import { getExtension } from '../../utils/getFileIcon' +import { getReadablePath } from '../../utils/getReadablePath' const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { const { asPath } = useRouter() @@ -54,7 +55,7 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { /> */} { - clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`) + clipboard.copy(`${getBaseUrl()}/api?path=${getReadablePath(asPath)}&raw=true`) toast.success('Copied direct link to clipboard.') }} btnColor="pink" diff --git a/utils/getReadablePath.ts b/utils/getReadablePath.ts new file mode 100644 index 0000000..9081feb --- /dev/null +++ b/utils/getReadablePath.ts @@ -0,0 +1,43 @@ +/** + * Make path readable but still valid in URL (means the whole URL is still recognized as a URL) + * @param path Path. May be used as URL path or query value. + * @returns Readable but still valid path + */ +export function getReadablePath(path: string) { + path = path + .split('/') + .map(s => decodeURIComponent(s)) + .map(s => + Array.from(s) + .map(c => (isSafeChar(c) ? c : encodeURIComponent(c))) + .join('') + ) + .join('/') + // Handle trailing char for autolink + // Ref: https://github.github.com/gfm/#autolinks-extension- + if (/^[!,:*]$/.test(path[path.length - 1])) { + path = path.substring(0, path.length - 1) + encodeURIComponent(path[path.length - 1]) + } + return path +} + +// Check if the character is safe (means no need of percent-encoding) +function isSafeChar(c: string) { + if (c.charCodeAt(0) < 0x80) { + // ASCII + if (/^[a-zA-Z0-9\-._~]$/.test(c)) { + // RFC3986 unreserved chars + return true + } else if (/^[*:+@,!]$/.test(c)) { + // Some extra pretty safe chars for URL path or query + // Ref: https://stackoverflow.com/a/42287988/11691878 + return true + } + } else { + if (!/\s|\u180e/.test(c)) { + // Non-whitespace char. \u180e is missed in \s. + return true + } + } + return false +} From 331ee20fd6e01fa7491e242e12419067d9861723 Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Tue, 8 Feb 2022 16:13:54 +0800 Subject: [PATCH 7/8] styles and some housekeeping --- components/previews/VideoPreview.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/components/previews/VideoPreview.tsx b/components/previews/VideoPreview.tsx index 5c3142f..3254c08 100644 --- a/components/previews/VideoPreview.tsx +++ b/components/previews/VideoPreview.tsx @@ -23,7 +23,11 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { const subtitle = `/api?path=${asPath.replace(getExtension(file.name), 'vtt')}&raw=true` const isFlv = getExtension(file.name) === 'flv' - const { loading, error, result: flvjs } = useAsync(async () => { + const { + loading, + error, + result: flvjs, + } = useAsync(async () => { if (isFlv) { return (await import('flv.js')).default } @@ -50,14 +54,14 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => { customFlv: (video: HTMLVideoElement) => { const flvPlayer = flvjs!.createPlayer({ type: 'flv', - url: video.src + url: video.src, }) flvPlayer.attachMediaElement(video) flvPlayer.load() - } - } + }, + }, }, - subtitle: { url: subtitle } + subtitle: { url: subtitle }, }} /> )} From 070394a66160fb3b6f09253aa9a7307e234a1d13 Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Tue, 8 Feb 2022 16:31:56 +0800 Subject: [PATCH 8/8] some housekeeping --- components/DownloadBtnGtoup.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/DownloadBtnGtoup.tsx b/components/DownloadBtnGtoup.tsx index de4d379..22e5fd6 100644 --- a/components/DownloadBtnGtoup.tsx +++ b/components/DownloadBtnGtoup.tsx @@ -47,7 +47,7 @@ export const DownloadButton = ({ }) => { return (