forked from spencerwooo/onedrive-vercel-index
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Navbar.tsx
205 lines (180 loc) · 7.92 KB
/
Navbar.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { IconName } from '@fortawesome/fontawesome-svg-core'
import { Dialog, Transition } from '@headlessui/react'
import toast, { Toaster } from 'react-hot-toast'
import { useHotkeys } from 'react-hotkeys-hook'
import Link from 'next/link'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { Fragment, useEffect, useState } from 'react'
import { useTranslation } from 'next-i18next'
import siteConfig from '../config/site.config'
import SearchModal from './SearchModal'
import SwitchLang from './SwitchLang'
import useDeviceOS from '../utils/useDeviceOS'
const Navbar = () => {
const router = useRouter()
const os = useDeviceOS()
const [tokenPresent, setTokenPresent] = useState(false)
const [isOpen, setIsOpen] = useState(false)
const [searchOpen, setSearchOpen] = useState(false)
const openSearchBox = () => setSearchOpen(true)
useHotkeys(`${os === 'mac' ? 'cmd' : 'ctrl'}+k`, e => {
openSearchBox()
e.preventDefault()
})
useEffect(() => {
const storedToken = () => {
for (const r of siteConfig.protectedRoutes) {
if (localStorage.hasOwnProperty(r)) {
return true
}
}
return false
}
setTokenPresent(storedToken())
}, [])
const { t } = useTranslation()
const clearTokens = () => {
setIsOpen(false)
siteConfig.protectedRoutes.forEach(r => {
localStorage.removeItem(r)
})
toast.success(t('Cleared all tokens'))
setTimeout(() => {
router.reload()
}, 1000)
}
return (
<div className="sticky top-0 z-[100] border-b border-gray-900/10 bg-white bg-opacity-80 backdrop-blur-md dark:border-gray-500/30 dark:bg-gray-900">
<Toaster />
<SearchModal searchOpen={searchOpen} setSearchOpen={setSearchOpen} />
<div className="mx-auto flex w-full items-center justify-between space-x-4 px-4 py-1">
<Link href="/" passHref>
<a className="flex items-center space-x-2 py-2 hover:opacity-80 dark:text-white md:p-2">
<Image src={siteConfig.icon} alt="icon" width="25" height="25" priority />
<span className="hidden font-bold sm:block">{siteConfig.title}</span>
</a>
</Link>
<div className="flex flex-1 items-center space-x-4 text-gray-700 md:flex-initial">
<button
className="flex flex-1 items-center justify-between rounded-lg bg-gray-100 px-2.5 py-1.5 hover:opacity-80 dark:bg-gray-800 dark:text-white md:w-48"
onClick={openSearchBox}
>
<div className="flex items-center space-x-2">
<FontAwesomeIcon className="h-4 w-4" icon="search" />
<span className="truncate text-sm font-medium">{t('Search ...')}</span>
</div>
<div className="hidden items-center space-x-1 md:flex">
<div className="rounded-lg bg-gray-200 px-2 py-1 text-xs font-medium dark:bg-gray-700">
{os === 'mac' ? '⌘' : 'Ctrl'}
</div>
<div className="rounded-lg bg-gray-200 px-2 py-1 text-xs font-medium dark:bg-gray-700">K</div>
</div>
</button>
<SwitchLang />
{siteConfig.links.length !== 0 &&
siteConfig.links.map((l: { name: string; link: string }) => (
<a
key={l.name}
href={l.link}
target="_blank"
rel="noopener noreferrer"
className="flex items-center space-x-2 hover:opacity-80 dark:text-white"
>
<FontAwesomeIcon icon={['fab', l.name.toLowerCase() as IconName]} />
<span className="hidden text-sm font-medium md:inline-block">
{
// Append link name comments here to add translations
// t('Weibo')
t(l.name)
}
</span>
</a>
))}
{siteConfig.email && (
<a href={siteConfig.email} className="flex items-center space-x-2 hover:opacity-80 dark:text-white">
<FontAwesomeIcon icon={['far', 'envelope']} />
<span className="hidden text-sm font-medium md:inline-block">{t('Email')}</span>
</a>
)}
{tokenPresent && (
<button
className="flex items-center space-x-2 p-2 hover:opacity-80 dark:text-white"
onClick={() => setIsOpen(true)}
>
<span className="hidden text-sm font-medium md:inline-block">{t('Logout')}</span>
<FontAwesomeIcon icon="sign-out-alt" />
</button>
)}
</div>
</div>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="fixed inset-0 z-10 overflow-y-auto" open={isOpen} onClose={() => setIsOpen(false)}>
<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-50"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-gray-50 dark:bg-gray-800" />
</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-50"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<div className="my-8 inline-block w-full max-w-md transform overflow-hidden rounded-lg bg-white p-6 text-left align-middle transition-all dark:bg-gray-900">
<Dialog.Title className="text-lg font-bold text-gray-900 dark:text-gray-100">
{t('Clear all tokens?')}
</Dialog.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">
{t('These tokens are used to authenticate yourself into password protected folders, ') +
t('clearing them means that you will need to re-enter the passwords again.')}
</p>
</div>
<div className="mt-4 max-h-32 overflow-y-scroll font-mono text-sm dark:text-gray-100">
{siteConfig.protectedRoutes.map((r, i) => (
<div key={i} className="flex items-center space-x-1">
<FontAwesomeIcon icon="key" />
<span className="truncate">{r}</span>
</div>
))}
</div>
<div className="mt-8 flex items-center justify-end">
<button
className="mr-3 inline-flex items-center justify-center space-x-2 rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-400 focus:outline-none focus:ring focus:ring-blue-300"
onClick={() => setIsOpen(false)}
>
{t('Cancel')}
</button>
<button
className="inline-flex items-center justify-center space-x-2 rounded bg-red-500 px-4 py-2 text-white hover:bg-red-400 focus:outline-none focus:ring focus:ring-red-300"
onClick={() => clearTokens()}
>
<FontAwesomeIcon icon={['far', 'trash-alt']} />
<span>{t('Clear all')}</span>
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
</div>
)
}
export default Navbar