File size: 8,829 Bytes
1b72d7e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState, useRef, useLayoutEffect } from 'react'
import { useGlobal } from '@/lib/global'
import { saveDarkModeToCookies, THEMES } from '@/themes/theme'
import useWindowSize from '@/hooks/useWindowSize'
import { siteConfig } from '@/lib/config'

/**
 * 自定义右键菜单
 * @param {*} props
 * @returns
 */
export default function CustomContextMenu(props) {
  const [position, setPosition] = useState({ x: '0px', y: '0px' })
  const [show, setShow] = useState(false)
  const { isDarkMode, updateDarkMode, locale } = useGlobal()
  const menuRef = useRef(null)
  const windowSize = useWindowSize()
  const [width, setWidth] = useState(0)
  const [height, setHeight] = useState(0)

  const { latestPosts } = props
  const router = useRouter()
  /**
   * 随机跳转文章
   */
  function handleJumpToRandomPost() {
    const randomIndex = Math.floor(Math.random() * latestPosts.length)
    const randomPost = latestPosts[randomIndex]
    router.push(`${siteConfig('SUB_PATH', '')}/${randomPost?.slug}`)
  }

  useLayoutEffect(() => {
    setWidth(menuRef.current.offsetWidth)
    setHeight(menuRef.current.offsetHeight)
  }, [])

  useEffect(() => {
    const handleContextMenu = (event) => {
      event.preventDefault()
      // 计算点击位置加菜单宽高是否超出屏幕,如果超出则贴边弹出
      const x = (event.clientX < windowSize.width - width) ? event.clientX : windowSize.width - width
      const y = (event.clientY < windowSize.height - height) ? event.clientY : windowSize.height - height
      setPosition({ y: `${y}px`, x: `${x}px` })
      setShow(true)
    }

    const handleClick = (event) => {
      if (menuRef.current && !menuRef.current.contains(event.target)) {
        setShow(false)
      }
    }

    window.addEventListener('contextmenu', handleContextMenu)
    window.addEventListener('click', handleClick)

    return () => {
      window.removeEventListener('contextmenu', handleContextMenu)
      window.removeEventListener('click', handleClick)
    }
  }, [windowSize])

  function handleBack() {
    window.history.back()
  }

  function handleForward() {
    window.history.forward()
  }

  function handleRefresh() {
    window.location.reload()
  }

  function handleScrollTop() {
    window.scrollTo({ top: 0, behavior: 'smooth' })
    setShow(false)
  }

  function handleCopyLink() {
    const url = window.location.href
    navigator.clipboard.writeText(url)
      .then(() => {
        console.log('页面地址已复制')
      })
      .catch((error) => {
        console.error('复制页面地址失败:', error)
      })
    setShow(false)
  }

  /**
  * 切换主题
  */
  function handleChangeTheme() {
    const randomTheme = THEMES[Math.floor(Math.random() * THEMES.length)] // 从THEMES数组中 随机取一个主题
    const query = router.query
    query.theme = randomTheme
    router.push({ pathname: router.pathname, query })
  }

  /**
   * 复制内容
   */
  function handleCopy() {
    const selectedText = document.getSelection().toString();
    if (selectedText) {
      const tempInput = document.createElement('input');
      tempInput.value = selectedText;
      document.body.appendChild(tempInput);
      tempInput.select();
      document.execCommand('copy');
      document.body.removeChild(tempInput);
      // alert("Text copied: " + selectedText);
    } else {
      // alert("Please select some text first.");
    }

    setShow(false)
  }

  function handleChangeDarkMode() {
    const newStatus = !isDarkMode
    saveDarkModeToCookies(newStatus)
    updateDarkMode(newStatus)
    const htmlElement = document.getElementsByTagName('html')[0]
    htmlElement.classList?.remove(newStatus ? 'light' : 'dark')
    htmlElement.classList?.add(newStatus ? 'dark' : 'light')
  }

  return (
        <div
            ref={menuRef}
            style={{ top: position.y, left: position.x }}
            className={`${show ? '' : 'invisible opacity-0'} select-none transition-opacity duration-200 fixed z-50`}
        >

            {/* 菜单内容 */}
            <div className='rounded-xl w-52 dark:hover:border-yellow-600 bg-white dark:bg-[#040404] dark:text-gray-200 dark:border-gray-600 p-3 border drop-shadow-lg flex-col duration-300 transition-colors'>
                {/* 顶部导航按钮 */}
                <div className='flex justify-between'>
                    <i onClick={handleBack} className="hover:bg-blue-600 hover:text-white px-2 py-2 text-center w-8 rounded cursor-pointer fa-solid fa-arrow-left"></i>
                    <i onClick={handleForward} className="hover:bg-blue-600 hover:text-white px-2 py-2 text-center w-8 rounded cursor-pointer fa-solid fa-arrow-right"></i>
                    <i onClick={handleRefresh} className="hover:bg-blue-600 hover:text-white px-2 py-2 text-center w-8 rounded cursor-pointer fa-solid fa-rotate-right"></i>
                    <i onClick={handleScrollTop} className="hover:bg-blue-600 hover:text-white px-2 py-2 text-center w-8 rounded cursor-pointer fa-solid fa-arrow-up"></i>
                </div>

                <hr className='my-2 border-dashed' />

                {/* 跳转导航按钮 */}
                <div className='w-full px-2'>

                    <div onClick={handleJumpToRandomPost} title={locale.MENU.WALK_AROUND} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        <i className="fa-solid fa-podcast mr-2" />
                        <div className='whitespace-nowrap'>{locale.MENU.WALK_AROUND}</div>
                    </div>

                    <Link href='/category' title={locale.MENU.CATEGORY} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        <i className="fa-solid fa-square-minus mr-2" />
                        <div className='whitespace-nowrap'>{locale.MENU.CATEGORY}</div>
                    </Link>

                    <Link href='/tag' title={locale.MENU.TAGS} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        <i className="fa-solid fa-tag mr-2" />
                        <div className='whitespace-nowrap'>{locale.MENU.TAGS}</div>
                    </Link>

                </div>

                <hr className='my-2 border-dashed' />

                {/* 功能按钮 */}
                <div className='w-full px-2'>

                    {siteConfig('CAN_COPY') && (
                         <div onClick={handleCopy} title={locale.MENU.COPY} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                         <i className="fa-solid fa-copy mr-2" />
                         <div className='whitespace-nowrap'>{locale.MENU.COPY}</div>
                     </div>
                    )}

                    <div onClick={handleCopyLink} title={locale.MENU.SHARE_URL} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        <i className="fa-solid fa-arrow-up-right-from-square mr-2" />
                        <div className='whitespace-nowrap'>{locale.MENU.SHARE_URL}</div>
                    </div>

                    <div onClick={handleChangeDarkMode} title={isDarkMode ? locale.MENU.LIGHT_MODE : locale.MENU.DARK_MODE} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        {isDarkMode ? <i className="fa-regular fa-sun mr-2" /> : <i className="fa-regular fa-moon mr-2" />}
                        <div className='whitespace-nowrap'> {isDarkMode ? locale.MENU.LIGHT_MODE : locale.MENU.DARK_MODE}</div>
                    </div>
                    {siteConfig('CUSTOM_RIGHT_CLICK_CONTEXT_MENU_THEME_SWITCH') && (
                    <div onClick={handleChangeTheme} title={locale.MENU.THEME_SWITCH} className='w-full px-2 h-10 flex justify-start items-center flex-nowrap cursor-pointer hover:bg-blue-600 hover:text-white rounded-lg duration-200 transition-all'>
                        <i className="fa-solid fa-palette mr-2" />
                        <div className='whitespace-nowrap'>{locale.MENU.THEME_SWITCH}</div>
                    </div>
                    )}

                </div>

            </div>
        </div >
  )
}