Merge branch 'main' of github.com:spencerwooo/onedrive-vercel-index into stale-while-revalidate-59
This commit is contained in:
commit
aea8a4d029
10 changed files with 241 additions and 40 deletions
109
components/CustomEmbedLinkMenu.tsx
Normal file
109
components/CustomEmbedLinkMenu.tsx
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
import { Dispatch, Fragment, SetStateAction, useState } from 'react'
|
||||||
|
import toast from 'react-hot-toast'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
import { Dialog, Transition } from '@headlessui/react'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { useClipboard } from 'use-clipboard-copy'
|
||||||
|
|
||||||
|
import { getBaseUrl } from '../utils/getBaseUrl'
|
||||||
|
|
||||||
|
export default function CustomEmbedLinkMenu({
|
||||||
|
path,
|
||||||
|
menuOpen,
|
||||||
|
setMenuOpen,
|
||||||
|
}: {
|
||||||
|
path: string
|
||||||
|
menuOpen: boolean
|
||||||
|
setMenuOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const clipboard = useClipboard()
|
||||||
|
const closeMenu = () => setMenuOpen(false)
|
||||||
|
|
||||||
|
const filename = path.substring(path.lastIndexOf('/') + 1)
|
||||||
|
const [name, setName] = useState(filename)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition appear show={menuOpen} as={Fragment}>
|
||||||
|
<Dialog as="div" className="fixed inset-0 z-10 overflow-y-auto" onClose={closeMenu}>
|
||||||
|
<div className="min-h-screen px-4 text-center">
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-100"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-100"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<Dialog.Overlay className="fixed inset-0 bg-white/60 dark:bg-gray-800/60" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
{/* This element is to trick the browser into centering the modal contents. */}
|
||||||
|
<span className="inline-block h-screen align-middle" aria-hidden="true">
|
||||||
|
​
|
||||||
|
</span>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-100"
|
||||||
|
enterFrom="opacity-0 scale-95"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="ease-in duration-100"
|
||||||
|
leaveFrom="opacity-100 scale-100"
|
||||||
|
leaveTo="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<div className="inline-block max-h-[80vh] w-full max-w-3xl transform overflow-hidden overflow-y-scroll rounded border border-gray-400/30 bg-white p-4 text-left align-middle text-sm shadow-xl transition-all dark:bg-gray-900 dark:text-white">
|
||||||
|
<Dialog.Title as="h3" className="py-2 text-xl font-bold">
|
||||||
|
{t('Customise direct link')}
|
||||||
|
</Dialog.Title>
|
||||||
|
<Dialog.Description as="p" className="py-2 opacity-80">
|
||||||
|
{t('Change the raw file direct link to a URL ending with the extension of the file.')}{' '}
|
||||||
|
<a
|
||||||
|
href="https://onedrive-vercel-index.spencerwoo.com/docs/features/customise-direct-link"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-blue-400 underline"
|
||||||
|
>
|
||||||
|
{t('What is this?')}
|
||||||
|
</a>
|
||||||
|
</Dialog.Description>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<h4 className="py-2 text-xs font-medium uppercase tracking-wider">{t('Filename')}</h4>
|
||||||
|
<input
|
||||||
|
className="mb-2 w-full rounded border border-gray-600/10 p-1 font-mono focus:outline-none focus:ring focus:ring-blue-300 dark:bg-gray-600 dark:text-white dark:focus:ring-blue-700"
|
||||||
|
value={name}
|
||||||
|
onChange={e => setName(e.target.value)}
|
||||||
|
/>
|
||||||
|
<h4 className="py-2 text-xs font-medium uppercase tracking-wider">{t('Default')}</h4>
|
||||||
|
<div className="mb-2 rounded border border-gray-400/20 bg-gray-50 p-1 font-mono dark:bg-gray-800">
|
||||||
|
{`${getBaseUrl()}/api?path=${path}&raw=true`}
|
||||||
|
</div>
|
||||||
|
<h4 className="py-2 text-xs font-medium uppercase tracking-wider">{t('Customised')}</h4>
|
||||||
|
<div className="mb-2 rounded border border-gray-400/20 bg-gray-50 p-1 font-mono dark:bg-gray-800">
|
||||||
|
<span>{`${getBaseUrl()}/api/name/`}</span>
|
||||||
|
<span className="underline decoration-blue-400 decoration-wavy">{name}</span>
|
||||||
|
<span>{`?path=${path}&raw=true`}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-2 mt-6 text-right">
|
||||||
|
<button
|
||||||
|
className="rounded-lg bg-gradient-to-r from-cyan-500 to-blue-500 px-4 py-2 text-center text-sm font-medium text-white hover:bg-gradient-to-bl focus:ring-4 focus:ring-cyan-300 dark:focus:ring-cyan-800"
|
||||||
|
onClick={() => {
|
||||||
|
clipboard.copy(`${getBaseUrl()}/api/name/${name}?path=${path}&raw=true`)
|
||||||
|
toast.success(t('Copied customised link to clipboard.'))
|
||||||
|
closeMenu()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon="copy" />
|
||||||
|
<span className="ml-2">{t('Copy custom link to clipboard')}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { MouseEventHandler } from 'react'
|
import { MouseEventHandler, useState } from 'react'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { IconProp } from '@fortawesome/fontawesome-svg-core'
|
import { IconProp } from '@fortawesome/fontawesome-svg-core'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
|
@ -10,6 +10,7 @@ import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import { getBaseUrl } from '../utils/getBaseUrl'
|
import { getBaseUrl } from '../utils/getBaseUrl'
|
||||||
import { getReadablePath } from '../utils/getReadablePath'
|
import { getReadablePath } from '../utils/getReadablePath'
|
||||||
|
import CustomEmbedLinkMenu from './CustomEmbedLinkMenu'
|
||||||
|
|
||||||
const btnStyleMap = (btnColor?: string) => {
|
const btnStyleMap = (btnColor?: string) => {
|
||||||
const colorMap = {
|
const colorMap = {
|
||||||
|
@ -64,36 +65,46 @@ export const DownloadButton = ({
|
||||||
const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl }) => {
|
const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl }) => {
|
||||||
const { asPath } = useRouter()
|
const { asPath } = useRouter()
|
||||||
const clipboard = useClipboard()
|
const clipboard = useClipboard()
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false)
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap justify-center gap-2">
|
<>
|
||||||
<DownloadButton
|
<CustomEmbedLinkMenu menuOpen={menuOpen} setMenuOpen={setMenuOpen} path={asPath} />
|
||||||
onClickCallback={() => window.open(downloadUrl)}
|
<div className="flex flex-wrap justify-center gap-2">
|
||||||
btnColor="blue"
|
<DownloadButton
|
||||||
btnText={t('Download')}
|
onClickCallback={() => window.open(downloadUrl)}
|
||||||
btnIcon="file-download"
|
btnColor="blue"
|
||||||
btnTitle={t('Download the file directly through OneDrive')}
|
btnText={t('Download')}
|
||||||
/>
|
btnIcon="file-download"
|
||||||
{/* <DownloadButton
|
btnTitle={t('Download the file directly through OneDrive')}
|
||||||
|
/>
|
||||||
|
{/* <DownloadButton
|
||||||
onClickCallback={() => window.open(`/api/proxy?url=${encodeURIComponent(downloadUrl)}`)}
|
onClickCallback={() => window.open(`/api/proxy?url=${encodeURIComponent(downloadUrl)}`)}
|
||||||
btnColor="teal"
|
btnColor="teal"
|
||||||
btnText={t('Proxy download')}
|
btnText={t('Proxy download')}
|
||||||
btnIcon="download"
|
btnIcon="download"
|
||||||
btnTitle={t('Download the file with the stream proxied through Vercel Serverless')}
|
btnTitle={t('Download the file with the stream proxied through Vercel Serverless')}
|
||||||
/> */}
|
/> */}
|
||||||
<DownloadButton
|
<DownloadButton
|
||||||
onClickCallback={() => {
|
onClickCallback={() => {
|
||||||
clipboard.copy(`${getBaseUrl()}/api?path=${getReadablePath(asPath)}&raw=true`)
|
clipboard.copy(`${getBaseUrl()}/api?path=${getReadablePath(asPath)}&raw=true`)
|
||||||
toast.success(t('Copied direct link to clipboard.'))
|
toast.success(t('Copied direct link to clipboard.'))
|
||||||
}}
|
}}
|
||||||
btnColor="pink"
|
btnColor="pink"
|
||||||
btnText={t('Copy direct link')}
|
btnText={t('Copy direct link')}
|
||||||
btnIcon="copy"
|
btnIcon="copy"
|
||||||
btnTitle={t('Copy the permalink to the file to the clipboard')}
|
btnTitle={t('Copy the permalink to the file to the clipboard')}
|
||||||
/>
|
/>
|
||||||
</div>
|
<DownloadButton
|
||||||
|
onClickCallback={() => setMenuOpen(true)}
|
||||||
|
btnColor="teal"
|
||||||
|
btnText={t('Customise link')}
|
||||||
|
btnIcon="pen"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Menu, Transition } from '@headlessui/react'
|
||||||
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { useCookies, withCookies } from 'react-cookie'
|
||||||
|
|
||||||
// https://headlessui.dev/react/menu#integrating-with-next-js
|
// https://headlessui.dev/react/menu#integrating-with-next-js
|
||||||
const CustomLink = ({ href, children, as, locale, ...props }): JSX.Element => {
|
const CustomLink = ({ href, children, as, locale, ...props }): JSX.Element => {
|
||||||
|
@ -28,6 +29,8 @@ const localeText = (locale: string): string => {
|
||||||
const SwitchLang = () => {
|
const SwitchLang = () => {
|
||||||
const { locales, pathname, query, asPath } = useRouter()
|
const { locales, pathname, query, asPath } = useRouter()
|
||||||
|
|
||||||
|
const [_, setCookie] = useCookies(['NEXT_LOCALE'])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Menu>
|
<Menu>
|
||||||
|
@ -48,7 +51,13 @@ const SwitchLang = () => {
|
||||||
<Menu.Items className="absolute top-0 right-0 z-20 mt-8 w-28 divide-y divide-gray-900 overflow-auto rounded border border-gray-900/10 bg-white py-1 shadow-lg focus:outline-none dark:border-gray-500/30 dark:bg-gray-900 dark:text-white">
|
<Menu.Items className="absolute top-0 right-0 z-20 mt-8 w-28 divide-y divide-gray-900 overflow-auto rounded border border-gray-900/10 bg-white py-1 shadow-lg focus:outline-none dark:border-gray-500/30 dark:bg-gray-900 dark:text-white">
|
||||||
{locales!.map(locale => (
|
{locales!.map(locale => (
|
||||||
<Menu.Item key={locale}>
|
<Menu.Item key={locale}>
|
||||||
<CustomLink key={locale} href={{ pathname, query }} as={asPath} locale={locale}>
|
<CustomLink
|
||||||
|
key={locale}
|
||||||
|
href={{ pathname, query }}
|
||||||
|
as={asPath}
|
||||||
|
locale={locale}
|
||||||
|
onClick={() => setCookie('NEXT_LOCALE', locale, { path: '/' })}
|
||||||
|
>
|
||||||
<div className="m-1 cursor-pointer rounded px-2 py-1 text-left text-sm font-medium hover:bg-blue-50 hover:text-blue-700 dark:hover:bg-blue-600/10 dark:hover:text-blue-400">
|
<div className="m-1 cursor-pointer rounded px-2 py-1 text-left text-sm font-medium hover:bg-blue-50 hover:text-blue-700 dark:hover:bg-blue-600/10 dark:hover:text-blue-400">
|
||||||
{localeText(locale)}
|
{localeText(locale)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,4 +71,4 @@ const SwitchLang = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SwitchLang
|
export default withCookies(SwitchLang)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { OdFileObject } from '../../types'
|
import type { OdFileObject } from '../../types'
|
||||||
|
import { useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useClipboard } from 'use-clipboard-copy'
|
import { useClipboard } from 'use-clipboard-copy'
|
||||||
import DPlayer from 'react-dplayer'
|
import DPlayer from 'react-dplayer'
|
||||||
|
@ -13,11 +14,13 @@ import { DownloadButton } from '../DownloadBtnGtoup'
|
||||||
import { DownloadBtnContainer, PreviewContainer } from './Containers'
|
import { DownloadBtnContainer, PreviewContainer } from './Containers'
|
||||||
import FourOhFour from '../FourOhFour'
|
import FourOhFour from '../FourOhFour'
|
||||||
import Loading from '../Loading'
|
import Loading from '../Loading'
|
||||||
|
import CustomEmbedLinkMenu from '../CustomEmbedLinkMenu'
|
||||||
|
|
||||||
const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
|
const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
|
||||||
const { asPath } = useRouter()
|
const { asPath } = useRouter()
|
||||||
const clipboard = useClipboard()
|
const clipboard = useClipboard()
|
||||||
|
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false)
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
// OneDrive generates thumbnails for its video files, we pick the thumbnail with the highest resolution
|
// OneDrive generates thumbnails for its video files, we pick the thumbnail with the highest resolution
|
||||||
|
@ -30,15 +33,16 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
result: flvjs,
|
result: mpegts,
|
||||||
} = useAsync(async () => {
|
} = useAsync(async () => {
|
||||||
if (isFlv) {
|
if (isFlv) {
|
||||||
return (await import('flv.js')).default
|
return (await import('mpegts.js')).default
|
||||||
}
|
}
|
||||||
}, [isFlv])
|
}, [isFlv])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<CustomEmbedLinkMenu path={getReadablePath(asPath)} menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
|
||||||
<PreviewContainer>
|
<PreviewContainer>
|
||||||
{error ? (
|
{error ? (
|
||||||
<FourOhFour errorMsg={error.message} />
|
<FourOhFour errorMsg={error.message} />
|
||||||
|
@ -56,7 +60,7 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
|
||||||
type: isFlv ? 'customFlv' : 'auto',
|
type: isFlv ? 'customFlv' : 'auto',
|
||||||
customType: {
|
customType: {
|
||||||
customFlv: (video: HTMLVideoElement) => {
|
customFlv: (video: HTMLVideoElement) => {
|
||||||
const flvPlayer = flvjs!.createPlayer({
|
const flvPlayer = mpegts!.createPlayer({
|
||||||
type: 'flv',
|
type: 'flv',
|
||||||
url: video.src,
|
url: video.src,
|
||||||
})
|
})
|
||||||
|
@ -96,6 +100,12 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
|
||||||
btnText={t('Copy direct link')}
|
btnText={t('Copy direct link')}
|
||||||
btnIcon="copy"
|
btnIcon="copy"
|
||||||
/>
|
/>
|
||||||
|
<DownloadButton
|
||||||
|
onClickCallback={() => setMenuOpen(true)}
|
||||||
|
btnColor="teal"
|
||||||
|
btnText={t('Customise link')}
|
||||||
|
btnIcon="pen"
|
||||||
|
/>
|
||||||
|
|
||||||
<DownloadButton
|
<DownloadButton
|
||||||
onClickCallback={() => window.open(`iina://weblink?url=${file['@microsoft.graph.downloadUrl']}`)}
|
onClickCallback={() => window.open(`iina://weblink?url=${file['@microsoft.graph.downloadUrl']}`)}
|
||||||
|
|
|
@ -22,11 +22,12 @@
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
"csstype": "^2.6.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"emoji-regex": "^10.0.0",
|
"emoji-regex": "^10.0.0",
|
||||||
"flv.js": "^1.6.2",
|
|
||||||
"ioredis": "^4.28.2",
|
"ioredis": "^4.28.2",
|
||||||
"jszip": "^3.7.1",
|
"jszip": "^3.7.1",
|
||||||
|
"mpegts.js": "^1.6.10",
|
||||||
"next": "^12.0.10",
|
"next": "^12.0.10",
|
||||||
"next-i18next": "^10.2.0",
|
"next-i18next": "^10.2.0",
|
||||||
"nextjs-progressbar": "^0.0.13",
|
"nextjs-progressbar": "^0.0.13",
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-async-hook": "^4.0.0",
|
"react-async-hook": "^4.0.0",
|
||||||
"react-audio-player": "^0.17.0",
|
"react-audio-player": "^0.17.0",
|
||||||
|
"react-cookie": "^4.1.1",
|
||||||
"react-copy-to-clipboard": "^5.0.3",
|
"react-copy-to-clipboard": "^5.0.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-dplayer": "^0.4.2",
|
"react-dplayer": "^0.4.2",
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
} from '@fortawesome/free-regular-svg-icons'
|
} from '@fortawesome/free-regular-svg-icons'
|
||||||
import {
|
import {
|
||||||
faSearch,
|
faSearch,
|
||||||
|
faPen,
|
||||||
faCheck,
|
faCheck,
|
||||||
faPlus,
|
faPlus,
|
||||||
faMinus,
|
faMinus,
|
||||||
|
@ -109,6 +110,7 @@ library.add(
|
||||||
faThLarge,
|
faThLarge,
|
||||||
faThList,
|
faThList,
|
||||||
faLanguage,
|
faLanguage,
|
||||||
|
faPen,
|
||||||
...iconList
|
...iconList
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
|
|
||||||
// Fetch password from remote file content
|
// Fetch password from remote file content
|
||||||
if (authTokenPath !== '') {
|
if (authTokenPath !== '') {
|
||||||
|
// Don't server cached response for password protected folders
|
||||||
|
res.setHeader('Cache-Control', 'no-cache')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const token = await axios.get(`${apiConfig.driveApi}/root${encodePath(authTokenPath)}`, {
|
const token = await axios.get(`${apiConfig.driveApi}/root${encodePath(authTokenPath)}`, {
|
||||||
headers: { Authorization: `Bearer ${accessToken}` },
|
headers: { Authorization: `Bearer ${accessToken}` },
|
||||||
|
|
|
@ -22,15 +22,16 @@ specifiers:
|
||||||
axios: ^0.25.0
|
axios: ^0.25.0
|
||||||
cors: ^2.8.5
|
cors: ^2.8.5
|
||||||
crypto-js: ^4.1.1
|
crypto-js: ^4.1.1
|
||||||
|
csstype: ^2.6.2
|
||||||
dayjs: ^1.10.7
|
dayjs: ^1.10.7
|
||||||
emoji-regex: ^10.0.0
|
emoji-regex: ^10.0.0
|
||||||
eslint: 8.8.0
|
eslint: 8.8.0
|
||||||
eslint-config-next: 12.0.10
|
eslint-config-next: 12.0.10
|
||||||
eslint-config-prettier: ^8.3.0
|
eslint-config-prettier: ^8.3.0
|
||||||
flv.js: ^1.6.2
|
|
||||||
i18next-parser: ^5.4.0
|
i18next-parser: ^5.4.0
|
||||||
ioredis: ^4.28.2
|
ioredis: ^4.28.2
|
||||||
jszip: ^3.7.1
|
jszip: ^3.7.1
|
||||||
|
mpegts.js: ^1.6.10
|
||||||
next: ^12.0.10
|
next: ^12.0.10
|
||||||
next-i18next: ^10.2.0
|
next-i18next: ^10.2.0
|
||||||
nextjs-progressbar: ^0.0.13
|
nextjs-progressbar: ^0.0.13
|
||||||
|
@ -41,6 +42,7 @@ specifiers:
|
||||||
react: ^17.0.2
|
react: ^17.0.2
|
||||||
react-async-hook: ^4.0.0
|
react-async-hook: ^4.0.0
|
||||||
react-audio-player: ^0.17.0
|
react-audio-player: ^0.17.0
|
||||||
|
react-cookie: ^4.1.1
|
||||||
react-copy-to-clipboard: ^5.0.3
|
react-copy-to-clipboard: ^5.0.3
|
||||||
react-dom: ^17.0.2
|
react-dom: ^17.0.2
|
||||||
react-dplayer: ^0.4.2
|
react-dplayer: ^0.4.2
|
||||||
|
@ -72,11 +74,12 @@ dependencies:
|
||||||
axios: 0.25.0
|
axios: 0.25.0
|
||||||
cors: 2.8.5
|
cors: 2.8.5
|
||||||
crypto-js: 4.1.1
|
crypto-js: 4.1.1
|
||||||
|
csstype: 2.6.19
|
||||||
dayjs: 1.10.7
|
dayjs: 1.10.7
|
||||||
emoji-regex: 10.0.0
|
emoji-regex: 10.0.0
|
||||||
flv.js: 1.6.2
|
|
||||||
ioredis: 4.28.3
|
ioredis: 4.28.3
|
||||||
jszip: 3.7.1
|
jszip: 3.7.1
|
||||||
|
mpegts.js: 1.6.10
|
||||||
next: 12.0.10_react-dom@17.0.2+react@17.0.2
|
next: 12.0.10_react-dom@17.0.2+react@17.0.2
|
||||||
next-i18next: 10.2.0_61390be992b634a688f7c2555547b55b
|
next-i18next: 10.2.0_61390be992b634a688f7c2555547b55b
|
||||||
nextjs-progressbar: 0.0.13_next@12.0.10+react@17.0.2
|
nextjs-progressbar: 0.0.13_next@12.0.10+react@17.0.2
|
||||||
|
@ -84,10 +87,11 @@ dependencies:
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-async-hook: 4.0.0_react@17.0.2
|
react-async-hook: 4.0.0_react@17.0.2
|
||||||
react-audio-player: 0.17.0_react-dom@17.0.2+react@17.0.2
|
react-audio-player: 0.17.0_react-dom@17.0.2+react@17.0.2
|
||||||
|
react-cookie: 4.1.1_react@17.0.2
|
||||||
react-copy-to-clipboard: 5.0.4_react@17.0.2
|
react-copy-to-clipboard: 5.0.4_react@17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
react-dplayer: 0.4.2_react@17.0.2
|
react-dplayer: 0.4.2_react@17.0.2
|
||||||
react-hot-toast: 2.2.0_react-dom@17.0.2+react@17.0.2
|
react-hot-toast: 2.2.0_6bba596ee6fb84e656d75c53902ecf01
|
||||||
react-hotkeys-hook: 3.4.4_react-dom@17.0.2+react@17.0.2
|
react-hotkeys-hook: 3.4.4_react-dom@17.0.2+react@17.0.2
|
||||||
react-markdown: 8.0.0_b08e3c15324cbe90a6ff8fcd416c932c
|
react-markdown: 8.0.0_b08e3c15324cbe90a6ff8fcd416c932c
|
||||||
react-reader: 0.20.5_react@17.0.2
|
react-reader: 0.20.5_react@17.0.2
|
||||||
|
@ -393,6 +397,10 @@ packages:
|
||||||
tailwindcss: 3.0.18_833e1018ad0d7954aa80c53675939269
|
tailwindcss: 3.0.18_833e1018ad0d7954aa80c53675939269
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/cookie/0.3.3:
|
||||||
|
resolution: {integrity: sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/cors/2.8.12:
|
/@types/cors/2.8.12:
|
||||||
resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==}
|
resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1066,6 +1074,11 @@ packages:
|
||||||
safe-buffer: 5.1.2
|
safe-buffer: 5.1.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/cookie/0.4.2:
|
||||||
|
resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/copy-to-clipboard/3.3.1:
|
/copy-to-clipboard/3.3.1:
|
||||||
resolution: {integrity: sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==}
|
resolution: {integrity: sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1138,6 +1151,10 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/csstype/2.6.19:
|
||||||
|
resolution: {integrity: sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/csstype/3.0.10:
|
/csstype/3.0.10:
|
||||||
resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==}
|
resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==}
|
||||||
|
|
||||||
|
@ -1783,13 +1800,6 @@ packages:
|
||||||
readable-stream: 2.3.7
|
readable-stream: 2.3.7
|
||||||
dev: true
|
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:
|
/follow-redirects/1.14.7:
|
||||||
resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==}
|
resolution: {integrity: sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
@ -1977,10 +1987,12 @@ packages:
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/goober/2.1.7:
|
/goober/2.1.7_csstype@2.6.19:
|
||||||
resolution: {integrity: sha512-aCR8u3A/tTgSrZAHfJObhYC0xgdKoYm4GvE/UFmxmzgvj3TSF+3oFYWtmJ459WBewjOIoEsoOG81sDs1rn+W5w==}
|
resolution: {integrity: sha512-aCR8u3A/tTgSrZAHfJObhYC0xgdKoYm4GvE/UFmxmzgvj3TSF+3oFYWtmJ459WBewjOIoEsoOG81sDs1rn+W5w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
csstype: ^2.6.2
|
csstype: ^2.6.2
|
||||||
|
dependencies:
|
||||||
|
csstype: 2.6.19
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/graceful-fs/4.2.9:
|
/graceful-fs/4.2.9:
|
||||||
|
@ -3102,6 +3114,13 @@ packages:
|
||||||
engines: {node: '>0.9'}
|
engines: {node: '>0.9'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mpegts.js/1.6.10:
|
||||||
|
resolution: {integrity: sha512-ZgX4b93cWk+EazOFRV4lekLqmc4rV7P+WMisG8N0F2M4/EiluPMNNWjuaurQfitak++AIc/ZVQ3IgM3cBcH7WA==}
|
||||||
|
dependencies:
|
||||||
|
es6-promise: 4.2.8
|
||||||
|
webworkify-webpack: 2.1.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mri/1.2.0:
|
/mri/1.2.0:
|
||||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
@ -3637,6 +3656,17 @@ packages:
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-cookie/4.1.1_react@17.0.2:
|
||||||
|
resolution: {integrity: sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>= 16.3.0'
|
||||||
|
dependencies:
|
||||||
|
'@types/hoist-non-react-statics': 3.3.1
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
react: 17.0.2
|
||||||
|
universal-cookie: 4.0.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-copy-to-clipboard/5.0.4_react@17.0.2:
|
/react-copy-to-clipboard/5.0.4_react@17.0.2:
|
||||||
resolution: {integrity: sha512-IeVAiNVKjSPeGax/Gmkqfa/+PuMTBhutEvFUaMQLwE2tS0EXrAdgOpWDX26bWTXF3HrioorR7lr08NqeYUWQCQ==}
|
resolution: {integrity: sha512-IeVAiNVKjSPeGax/Gmkqfa/+PuMTBhutEvFUaMQLwE2tS0EXrAdgOpWDX26bWTXF3HrioorR7lr08NqeYUWQCQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -3670,14 +3700,14 @@ packages:
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/react-hot-toast/2.2.0_react-dom@17.0.2+react@17.0.2:
|
/react-hot-toast/2.2.0_6bba596ee6fb84e656d75c53902ecf01:
|
||||||
resolution: {integrity: sha512-248rXw13uhf/6TNDVzagX+y7R8J183rp7MwUMNkcrBRyHj/jWOggfXTGlM8zAOuh701WyVW+eUaWG2LeSufX9g==}
|
resolution: {integrity: sha512-248rXw13uhf/6TNDVzagX+y7R8J183rp7MwUMNkcrBRyHj/jWOggfXTGlM8zAOuh701WyVW+eUaWG2LeSufX9g==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16'
|
react: '>=16'
|
||||||
react-dom: '>=16'
|
react-dom: '>=16'
|
||||||
dependencies:
|
dependencies:
|
||||||
goober: 2.1.7
|
goober: 2.1.7_csstype@2.6.19
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -4465,6 +4495,13 @@ packages:
|
||||||
unist-util-visit-parents: 5.1.0
|
unist-util-visit-parents: 5.1.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/universal-cookie/4.0.4:
|
||||||
|
resolution: {integrity: sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==}
|
||||||
|
dependencies:
|
||||||
|
'@types/cookie': 0.3.3
|
||||||
|
cookie: 0.4.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/universalify/0.1.2:
|
/universalify/0.1.2:
|
||||||
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
|
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
|
||||||
engines: {node: '>= 4.0.0'}
|
engines: {node: '>= 4.0.0'}
|
||||||
|
|
|
@ -14,18 +14,25 @@
|
||||||
"Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.": "Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.",
|
"Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.": "Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
"Cannot preview {{path}}": "Cannot preview {{path}}",
|
"Cannot preview {{path}}": "Cannot preview {{path}}",
|
||||||
|
"Change the raw file direct link to a URL ending with the extension of the file.": "Change the raw file direct link to a URL ending with the extension of the file.",
|
||||||
"Check out <2>Microsoft's official explanation</2> on the error message.": "Check out <2>Microsoft's official explanation</2> on the error message.",
|
"Check out <2>Microsoft's official explanation</2> on the error message.": "Check out <2>Microsoft's official explanation</2> on the error message.",
|
||||||
"Clear all": "Clear all",
|
"Clear all": "Clear all",
|
||||||
"Clear all tokens?": "Clear all tokens?",
|
"Clear all tokens?": "Clear all tokens?",
|
||||||
"Cleared all tokens": "Cleared all tokens",
|
"Cleared all tokens": "Cleared all tokens",
|
||||||
"clearing them means that you will need to re-enter the passwords again.": "clearing them means that you will need to re-enter the passwords again.",
|
"clearing them means that you will need to re-enter the passwords again.": "clearing them means that you will need to re-enter the passwords again.",
|
||||||
|
"Copied customised link to clipboard.": "Copied customised link to clipboard.",
|
||||||
"Copied direct link to clipboard.": "Copied direct link to clipboard.",
|
"Copied direct link to clipboard.": "Copied direct link to clipboard.",
|
||||||
"Copied folder permalink.": "Copied folder permalink.",
|
"Copied folder permalink.": "Copied folder permalink.",
|
||||||
"Copied raw file permalink.": "Copied raw file permalink.",
|
"Copied raw file permalink.": "Copied raw file permalink.",
|
||||||
|
"Copy custom link to clipboard": "Copy custom link to clipboard",
|
||||||
"Copy direct link": "Copy direct link",
|
"Copy direct link": "Copy direct link",
|
||||||
"Copy folder permalink": "Copy folder permalink",
|
"Copy folder permalink": "Copy folder permalink",
|
||||||
"Copy raw file permalink": "Copy raw file permalink",
|
"Copy raw file permalink": "Copy raw file permalink",
|
||||||
"Copy the permalink to the file to the clipboard": "Copy the permalink to the file to the clipboard",
|
"Copy the permalink to the file to the clipboard": "Copy the permalink to the file to the clipboard",
|
||||||
|
"Customise direct link": "Customise direct link",
|
||||||
|
"Customise link": "Customise link",
|
||||||
|
"Customised": "Customised",
|
||||||
|
"Default": "Default",
|
||||||
"Do not pretend to be the site owner": "Do not pretend to be the site owner",
|
"Do not pretend to be the site owner": "Do not pretend to be the site owner",
|
||||||
"Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.": "Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.",
|
"Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.": "Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.",
|
||||||
"Download": "Download",
|
"Download": "Download",
|
||||||
|
@ -47,6 +54,7 @@
|
||||||
"Failed to download selected files.": "Failed to download selected files.",
|
"Failed to download selected files.": "Failed to download selected files.",
|
||||||
"File is empty.": "File is empty.",
|
"File is empty.": "File is empty.",
|
||||||
"File size": "File size",
|
"File size": "File size",
|
||||||
|
"Filename": "Filename",
|
||||||
"Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ": "Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ",
|
"Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ": "Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ",
|
||||||
"Finished downloading folder.": "Finished downloading folder.",
|
"Finished downloading folder.": "Finished downloading folder.",
|
||||||
"Finished downloading selected files.": "Finished downloading selected files.",
|
"Finished downloading selected files.": "Finished downloading selected files.",
|
||||||
|
@ -106,6 +114,7 @@
|
||||||
"Waiting for code...": "Waiting for code...",
|
"Waiting for code...": "Waiting for code...",
|
||||||
"Weibo": "Weibo",
|
"Weibo": "Weibo",
|
||||||
"Welcome to your new onedrive-vercel-index 🎉": "Welcome to your new onedrive-vercel-index 🎉",
|
"Welcome to your new onedrive-vercel-index 🎉": "Welcome to your new onedrive-vercel-index 🎉",
|
||||||
|
"What is this?": "What is this?",
|
||||||
"Where is the auth code? Did you follow step 2 you silly donut?": "Where is the auth code? Did you follow step 2 you silly donut?",
|
"Where is the auth code? Did you follow step 2 you silly donut?": "Where is the auth code? Did you follow step 2 you silly donut?",
|
||||||
"Whoops, looks like we got a problem: {{error}}.": "Whoops, looks like we got a problem: {{error}}."
|
"Whoops, looks like we got a problem: {{error}}.": "Whoops, looks like we got a problem: {{error}}."
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,18 +12,25 @@
|
||||||
"Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.": "本项目还没有设置有效的 <2>access_token</2> 和 <5>refresh_token</5>,需要进行授权。在继续对 onedrive-vercel-index 授权你的 Microsoft 帐号前,请检查一下下方的配置信息。",
|
"Authorisation is required as no valid <2>access_token</2> or <5>refresh_token</5> is present on this deployed instance. Check the following configurations before proceeding with authorising onedrive-vercel-index with your own Microsoft account.": "本项目还没有设置有效的 <2>access_token</2> 和 <5>refresh_token</5>,需要进行授权。在继续对 onedrive-vercel-index 授权你的 Microsoft 帐号前,请检查一下下方的配置信息。",
|
||||||
"Cancel": "取消",
|
"Cancel": "取消",
|
||||||
"Cannot preview {{path}}": "无法预览 {{path}}",
|
"Cannot preview {{path}}": "无法预览 {{path}}",
|
||||||
|
"Change the raw file direct link to a URL ending with the extension of the file.": "将文件直链接更改为以文件扩展名结尾的 URL。",
|
||||||
"Check out <2>Microsoft's official explanation</2> on the error message.": "请查阅 <2>Microsoft 官方解释</2> 以获取详细的错误信息。",
|
"Check out <2>Microsoft's official explanation</2> on the error message.": "请查阅 <2>Microsoft 官方解释</2> 以获取详细的错误信息。",
|
||||||
"Clear all": "清除所有密钥",
|
"Clear all": "清除所有密钥",
|
||||||
"Clear all tokens?": "清除所有密钥?",
|
"Clear all tokens?": "清除所有密钥?",
|
||||||
"Cleared all tokens": "已清除所有密钥",
|
"Cleared all tokens": "已清除所有密钥",
|
||||||
"clearing them means that you will need to re-enter the passwords again.": "清除它们意味着下次访问时你需要重新输入密钥。",
|
"clearing them means that you will need to re-enter the passwords again.": "清除它们意味着下次访问时你需要重新输入密钥。",
|
||||||
|
"Copied customised link to clipboard.": "已复制自定义直链到剪贴板。",
|
||||||
"Copied direct link to clipboard.": "已复制直链到剪贴板。",
|
"Copied direct link to clipboard.": "已复制直链到剪贴板。",
|
||||||
"Copied folder permalink.": "已复制文件夹永久链接。",
|
"Copied folder permalink.": "已复制文件夹永久链接。",
|
||||||
"Copied raw file permalink.": "已复制文件永久链接。",
|
"Copied raw file permalink.": "已复制文件永久链接。",
|
||||||
|
"Copy custom link to clipboard": "复制自定义链接",
|
||||||
"Copy direct link": "复制文件直链",
|
"Copy direct link": "复制文件直链",
|
||||||
"Copy folder permalink": "复制文件夹永久链接",
|
"Copy folder permalink": "复制文件夹永久链接",
|
||||||
"Copy raw file permalink": "复制文件永久链接",
|
"Copy raw file permalink": "复制文件永久链接",
|
||||||
"Copy the permalink to the file to the clipboard": "复制文件永久链接到剪贴板",
|
"Copy the permalink to the file to the clipboard": "复制文件永久链接到剪贴板",
|
||||||
|
"Customise direct link": "自定义文件直链",
|
||||||
|
"Customise link": "自定义直链",
|
||||||
|
"Customised": "自定义链接",
|
||||||
|
"Default": "默认",
|
||||||
"Do not pretend to be the site owner": "你不是网站所有者",
|
"Do not pretend to be the site owner": "你不是网站所有者",
|
||||||
"Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.": "别担心,存储它们之后,onedrive-vercel-index 会在帮助你定时更新 token",
|
"Don't worry, after storing them, onedrive-vercel-index will take care of token refreshes and updates after your site goes live.": "别担心,存储它们之后,onedrive-vercel-index 会在帮助你定时更新 token",
|
||||||
"Download": "下载",
|
"Download": "下载",
|
||||||
|
@ -45,6 +52,7 @@
|
||||||
"Failed to download selected files.": "下载选定文件失败。",
|
"Failed to download selected files.": "下载选定文件失败。",
|
||||||
"File is empty.": "文件为空。",
|
"File is empty.": "文件为空。",
|
||||||
"File size": "文件大小",
|
"File size": "文件大小",
|
||||||
|
"Filename": "文件名",
|
||||||
"Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ": "最后一步,在这些 tokens 于 {{minutes}} 分钟 {{seconds}} 秒后失效前,点击下方按钮以永久存储这些 tokens",
|
"Final step, click the button below to store these tokens persistently before they expire after {{minutes}} minutes {{seconds}} seconds. ": "最后一步,在这些 tokens 于 {{minutes}} 分钟 {{seconds}} 秒后失效前,点击下方按钮以永久存储这些 tokens",
|
||||||
"Finished downloading folder.": "下载文件夹成功。",
|
"Finished downloading folder.": "下载文件夹成功。",
|
||||||
"Finished downloading selected files.": "下载选定文件成功。",
|
"Finished downloading selected files.": "下载选定文件成功。",
|
||||||
|
@ -102,6 +110,7 @@
|
||||||
"Waiting for code...": "等待授权码…",
|
"Waiting for code...": "等待授权码…",
|
||||||
"Weibo": "微博",
|
"Weibo": "微博",
|
||||||
"Welcome to your new onedrive-vercel-index 🎉": "欢迎来到你崭新的 onedrive-vercel-index 🎉",
|
"Welcome to your new onedrive-vercel-index 🎉": "欢迎来到你崭新的 onedrive-vercel-index 🎉",
|
||||||
|
"What is this?": "这是什么?",
|
||||||
"Where is the auth code? Did you follow step 2 you silly donut?": "授权码呢?你遵守了第 2 步吗?你这个傻瓜甜甜圈!o( ̄ヘ ̄o#)",
|
"Where is the auth code? Did you follow step 2 you silly donut?": "授权码呢?你遵守了第 2 步吗?你这个傻瓜甜甜圈!o( ̄ヘ ̄o#)",
|
||||||
"Whoops, looks like we got a problem: {{error}}.": "Whoops,看来我们遇到了一个问题:{{error}}"
|
"Whoops, looks like we got a problem: {{error}}.": "Whoops,看来我们遇到了一个问题:{{error}}"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue