1- import { MouseEvent , useEffect , useState } from "react" ;
1+ import { MouseEvent , useEffect , useRef , useState } from "react" ;
22import { useDispatch } from "react-redux" ;
33import clsx from "clsx" ;
4-
4+ import { motion } from "framer-motion" ;
55import { switchServer , updateAddModalVisible } from "@/app/slices/data" ;
66import { useAppSelector } from "@/app/store" ;
77import { ReactComponent as IconAdd } from "@/assets/icons/add.svg" ;
8+ // import { ReactComponent as IconDrag } from "@/assets/icons/drag.svg";
9+ import { ReactComponent as IconRefresh } from "@/assets/icons/refresh.svg" ;
10+ import { ReactComponent as IconLeft } from "@/assets/icons/arrow.left.svg" ;
11+ import { ReactComponent as IconRight } from "@/assets/icons/arrow.right.svg" ;
812// import { isDarkMode } from "@/utils";
913import ServerTip from "./server-tip" ;
1014import AddServerModal from "./modal-add-server" ;
@@ -15,17 +19,21 @@ import { hideAll } from "tippy.js";
1519import ContextMenu , { MenuItem } from "./context-menu" ;
1620
1721const Layout = ( ) => {
22+ const webviewContainerRef = useRef ( null ) ;
1823 const [ removeServer , setRemoveServer ] = useState < undefined | string > ( ) ;
1924 const [ reloadVisible , setReloadVisible ] = useState ( false ) ;
2025 const [ menuVisibleMap , setMenuVisibleMap ] = useState < Record < string , boolean > > ( { } ) ;
2126 const { servers, active, addModalVisible } = useAppSelector ( ( store ) => store . data ) ;
2227 const dispatch = useDispatch ( ) ;
28+ // const dragControls = useDragControls();
2329 useEffect ( ( ) => {
2430 if ( servers . length == 0 ) {
2531 handleAddServer ( ) ;
2632 }
2733 } , [ servers ] ) ;
28-
34+ // const startDrag = (event: any) => {
35+ // dragControls.start(event, { snapToCursor: true });
36+ // };
2937 const handleSwitch = ( evt : MouseEvent < HTMLLIElement > ) => {
3038 console . log ( "switch" ) ;
3139 const { url } = evt . currentTarget . dataset ;
@@ -34,6 +42,25 @@ const Layout = () => {
3442 dispatch ( switchServer ( url ) ) ;
3543 }
3644 } ;
45+ const handleWebviewNav = ( cmd : "back" | "forward" | "refresh" ) => {
46+ const wv = document . querySelector ( "webview[data-visible='true']" ) as WebviewTag ;
47+ if ( wv ) {
48+ switch ( cmd ) {
49+ case "back" :
50+ wv . goBack ( ) ;
51+ break ;
52+ case "forward" :
53+ wv . goForward ( ) ;
54+ break ;
55+ case "refresh" :
56+ wv . reload ( ) ;
57+ break ;
58+
59+ default :
60+ break ;
61+ }
62+ }
63+ } ;
3764 const handleAddServer = ( ) => {
3865 dispatch ( updateAddModalVisible ( true ) ) ;
3966 } ;
@@ -106,6 +133,7 @@ const Layout = () => {
106133 }
107134 return (
108135 < Tippy
136+ key = { web_url }
109137 appendTo = { document . body }
110138 offset = { [ - 20 , 34 ] }
111139 onClickOutside = { hideContextMenu . bind ( null , web_url ) }
@@ -164,7 +192,10 @@ const Layout = () => {
164192 </ div >
165193 </ ServerTip >
166194 </ aside >
167- < main className = "relative flex h-full flex-1 items-center justify-center" >
195+ < motion . main
196+ ref = { webviewContainerRef }
197+ className = "relative flex h-full flex-1 items-center justify-center"
198+ >
168199 { servers . map ( ( server ) => {
169200 const { web_url } = server ;
170201
@@ -176,18 +207,51 @@ const Layout = () => {
176207 //@ts -ignore
177208 //eslint-disable-next-line react/no-unknown-property
178209 disablewebsecurity = "true"
179- useragent = { ` ${ navigator . userAgent } ${ process . platform } ` }
210+ key = { web_url }
180211 className = { clsx (
181212 "absolute left-0 top-0 h-full w-full" ,
182213 active == web_url ? "visible" : "invisible"
183214 ) }
215+ useragent = { `${ navigator . userAgent } ${ process . platform } ` }
184216 data-visible = { active == web_url }
185- key = { web_url }
186217 src = { web_url }
187218 > </ webview >
188219 ) ;
189220 } ) }
190- </ main >
221+ < motion . div
222+ drag
223+ // dragControls={dragControls}
224+ dragListener = { false }
225+ dragConstraints = { webviewContainerRef }
226+ dragElastic = { false }
227+ dragMomentum = { false }
228+ className = "group absolute bottom-1 left-1/2 flex -translate-x-1/2 flex-col items-center opacity-50 hover:opacity-100"
229+ >
230+ { /* <button onPointerDown={startDrag} className="invisible cursor-move group-hover:visible">
231+ <IconDrag className="h-4 w-4 dark:stroke-gray-200" />
232+ </button> */ }
233+ < div className = "flex overflow-hidden rounded-lg border border-gray-500" >
234+ < button
235+ onClick = { handleWebviewNav . bind ( null , "back" ) }
236+ className = " px-2 py-1 hover:bg-gray-500"
237+ >
238+ < IconLeft className = "dark:stroke-gray-200" />
239+ </ button >
240+ < button
241+ onClick = { handleWebviewNav . bind ( null , "refresh" ) }
242+ className = " px-2 py-1 hover:bg-gray-500"
243+ >
244+ < IconRefresh className = "dark:stroke-gray-200" />
245+ </ button >
246+ < button
247+ onClick = { handleWebviewNav . bind ( null , "forward" ) }
248+ className = " px-2 py-1 hover:bg-gray-500"
249+ >
250+ < IconRight className = "dark:stroke-gray-200" />
251+ </ button >
252+ </ div >
253+ </ motion . div >
254+ </ motion . main >
191255
192256 { contextMenuVisible ? (
193257 < div className = "menu-mask fixed left-0 top-0 z-10 h-full w-full" > </ div >
0 commit comments