Merge pull request #371 from myl7/readable-path
This commit is contained in:
commit
bd8515401a
5 changed files with 63 additions and 8 deletions
|
@ -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"
|
||||
|
|
|
@ -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.')
|
||||
}}
|
||||
|
|
|
@ -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.')
|
||||
}}
|
||||
|
|
|
@ -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
43
utils/getReadablePath.ts
Normal 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
|
||||
}
|
Loading…
Reference in a new issue