Merge pull request #371 from myl7/readable-path

This commit is contained in:
Spencer Woo 2022-02-08 16:32:27 +08:00 committed by GitHub
commit bd8515401a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 8 deletions

View file

@ -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 = {
@ -46,7 +47,7 @@ export const DownloadButton = ({
}) => {
return (
<button
className={`flex items-center space-x-2 py-2 px-4 text-sm font-medium text-gray-900 bg-white rounded-lg border hover:bg-gray-100/10 focus:z-10 focus:ring-2 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-900 ${btnStyleMap(
className={`flex items-center space-x-2 rounded-lg border bg-white py-2 px-4 text-sm font-medium text-gray-900 hover:bg-gray-100/10 focus:z-10 focus:ring-2 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-900 ${btnStyleMap(
btnColor
)}`}
title={btnTitle}
@ -81,7 +82,7 @@ const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl })
/> */}
<DownloadButton
onClickCallback={() => {
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"

View file

@ -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.')
}}

View file

@ -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.')
}}

View file

@ -6,9 +6,10 @@ import toast from 'react-hot-toast'
import { useAsync } from 'react-async-hook'
import { getBaseUrl } from '../../utils/getBaseUrl'
import { getExtension } from '../../utils/getFileIcon'
import { getReadablePath } from '../../utils/getReadablePath'
import { DownloadButton } from '../DownloadBtnGtoup'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
import { getExtension } from '../../utils/getFileIcon'
import FourOhFour from '../FourOhFour'
import Loading from '../Loading'
@ -85,7 +86,7 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
/> */}
<DownloadButton
onClickCallback={() => {
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"

43
utils/getReadablePath.ts Normal file
View file

@ -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
}