Skip to content

Commit

Permalink
feat: support lock in pipWindow
Browse files Browse the repository at this point in the history
  • Loading branch information
magicdawn committed May 10, 2024
1 parent 7f1a12b commit ab5b039
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 95 deletions.
183 changes: 183 additions & 0 deletions src/components/VideoCard/use/_pip-window.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { APP_NAME_ROOT_CLASSNAME } from '$common'
import { AntdApp } from '$components/AntdApp'
import { colorPrimaryValue } from '$components/ModalSettings/theme.shared'
import createEmotion from '@emotion/css/create-instance'
import { Global } from '@emotion/react'
import { useHover } from 'ahooks'
import { App } from 'antd'
import { once } from 'lodash'
import RadixIconsLockClosed from '~icons/radix-icons/lock-closed'
import RadixIconsLockOpen1 from '~icons/radix-icons/lock-open-1'
import RadixIconsOpenInNewWindow from '~icons/radix-icons/open-in-new-window'
import { VideoCardActionButton } from '../child-components/VideoCardActions'
import { PLAYER_SCREEN_MODE } from '../index.shared'

export function openPipWindow(newHref: string, pipWindow: Window) {
const cssInsertContainer = pipWindow.document.head
const { cache } = createEmotion({
key: 'pip-window',
container: cssInsertContainer,
})

const container = document.createElement('div')
container.classList.add(APP_NAME_ROOT_CLASSNAME)
pipWindow.document.body.appendChild(container)

const root = createRoot(container)
root.render(
<AntdApp
emotionCache={cache}
styleProviderProps={{ container: cssInsertContainer }}
injectGlobalStyle
>
<App component={false} message={{ getContainer: () => pipWindow.document.body }}>
<PipWindowContent newHref={newHref} pipWindow={pipWindow} />
</App>
</AntdApp>,
)
}

export function PipWindowContent({ newHref, pipWindow }: { pipWindow: Window; newHref: string }) {
const focusOnce = useMemo(() => {
return once(() => {
window.focus()
})
}, [])
useKeyPress(
['leftarrow', 'rightarrow', 'uparrow', 'downawrrow', 'esc', 'tab'],
(e) => {
focusOnce()
},
{
exactMatch: true,
target: pipWindow.document.documentElement,
},
)

const hovering = useHover(pipWindow.document.documentElement)
const [locked, setLocked] = useState(true)

return (
<>
<Global
styles={[
css`
* {
box-sizing: border-box;
}
body,
iframe {
margin: 0;
padding: 0;
}
`,
]}
/>

<iframe
src={newHref}
css={css`
width: 100%;
height: 100%;
border: none;
`}
/>

<LockOverlay locked={locked} />

<div
css={css`
position: fixed;
z-index: 9999;
right: 10px;
top: 10px;
display: ${hovering ? 'flex' : 'none'};
column-gap: 8px;
flex-direction: row-reverse;
`}
>
<CloseButton pipWindow={pipWindow} newHref={newHref} />
<LockButton locked={locked} setLocked={setLocked} />
</div>
</>
)
}

const S = {
button: css`
border: 1px solid ${colorPrimaryValue};
svg {
width: 14px;
height: 14px;
}
`,
}

function LockOverlay({ locked }: { locked: boolean }) {
const [clickedTimes, setClickedTimes] = useState(0)
const [targetTimes, setTargetTimes] = useState(3)
const { message } = App.useApp()

return (
locked && (
<div
className='locked-overlay'
css={css`
position: fixed;
inset: 0;
z-index: 9999;
background-color: transparent;
user-select: none;
`}
onClick={() => {
const val = clickedTimes + 1
setClickedTimes(val)
if (val === targetTimes) {
setClickedTimes(0)
setTargetTimes((x) => x + 1)
message.info('请先点击右上角 🔓解锁按钮 解锁')
}
}}
/>
)
)
}

function CloseButton({ newHref, pipWindow }: { pipWindow: Window; newHref: string }) {
const onClick = () => {
pipWindow.close()
const u = new URL(newHref)
u.searchParams.delete(PLAYER_SCREEN_MODE)
GM.openInTab(u.href)
}

return (
<VideoCardActionButton
inlinePosition={'right'}
icon={<RadixIconsOpenInNewWindow />}
tooltip={'新窗口打开'}
onClick={onClick}
css={S.button}
/>
)
}

function LockButton({
locked,
setLocked,
}: {
locked: boolean
setLocked: React.Dispatch<React.SetStateAction<boolean>>
}) {
return (
<VideoCardActionButton
inlinePosition={'right'}
icon={locked ? <RadixIconsLockClosed /> : <RadixIconsLockOpen1 />}
tooltip={locked ? '解锁' : '锁定'}
css={S.button}
onClick={(e) => {
setLocked((x) => !x)
}}
/>
)
}
94 changes: 2 additions & 92 deletions src/components/VideoCard/use/useOpenRelated.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { APP_NAME_ROOT_CLASSNAME, baseDebug } from '$common'
import { AntdApp } from '$components/AntdApp'
import { baseDebug } from '$common'
import type { RecItemType } from '$define'
import { EApiType } from '$define/index.shared'
import { settings, useSettingsSnapshot } from '$modules/settings'
import createEmotion from '@emotion/css/create-instance'
import { useHover } from 'ahooks'
import { Button } from 'antd'
import { once } from 'lodash'
import type { MouseEventHandler } from 'react'
import RadixIconsOpenInNewWindow from '~icons/radix-icons/open-in-new-window'
import { VideoCardActionButton } from '../child-components/VideoCardActions'
import {
VideoLinkOpenMode as Mode,
Expand All @@ -18,6 +12,7 @@ import {
VideoLinkOpenMode,
VideoLinkOpenModeKey,
} from '../index.shared'
import { openPipWindow } from './_pip-window'

const debug = baseDebug.extend('VideoCard:useOpenRelated')

Expand Down Expand Up @@ -122,44 +117,6 @@ export function useOpenRelated({
}
}

function openPipWindow(newHref: string, pipWindow: Window) {
const cssInsertContainer = pipWindow.document.head
const { css, cache } = createEmotion({
key: 'pip-window',
container: cssInsertContainer,
})

const iframe = document.createElement('iframe')
iframe.src = newHref
pipWindow.document.body.append(iframe)

const resetCls = css`
margin: 0;
padding: 0;
width: 100%;
height: 100%;
border: none;
`
pipWindow.document.body.classList.add(resetCls)
iframe.classList.add(resetCls)

const container = document.createElement('div')
container.classList.add(APP_NAME_ROOT_CLASSNAME)
pipWindow.document.body.appendChild(container)

const root = createRoot(container)
root.render(
<AntdApp emotionCache={cache} styleProviderProps={{ container: cssInsertContainer }}>
<CloseButton newHref={newHref} pipWindow={pipWindow} />
</AntdApp>,
)

setTimeout(() => {
// focus original window
window.focus()
}, 500)
}

function openPopupWindow(newHref: string, popupWidth: number, popupHeight: number) {
// 将 left 减去 50px,你可以根据需要调整这个值
const left = (window.innerWidth - popupWidth) / 2
Expand Down Expand Up @@ -250,50 +207,3 @@ export function useOpenRelated({
onOpenInPopup,
}
}

function CloseButton({ newHref, pipWindow }: { pipWindow: Window; newHref: string }) {
const hovering = useHover(pipWindow.document.documentElement)

const focusOnce = useMemo(() => {
return once(() => {
window.focus()
})
}, [])
useKeyPress(
['leftarrow', 'rightarrow', 'uparrow', 'downawrrow', 'esc', 'tab'],
(e) => {
focusOnce()
},
{
exactMatch: true,
target: pipWindow.document.documentElement,
},
)

return (
<Button
onClick={(e) => {
pipWindow.close()
const u = new URL(newHref)
u.searchParams.delete(PLAYER_SCREEN_MODE)
GM.openInTab(u.href)
}}
css={css`
position: fixed;
right: 10px;
top: 10px;
display: ${hovering ? 'flex' : 'none'};
align-items: center;
text-align: center;
justify-content: center;
`}
>
<RadixIconsOpenInNewWindow
css={css`
margin-right: 5px;
`}
/>
打开
</Button>
)
}
2 changes: 1 addition & 1 deletion src/components/VideoCard/use/useWatchlaterRelated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function useWatchlaterRelated({

// <use href={watchLaterAdded ? '#widget-watch-save' : '#widget-watch-later'} />

const size = 20
const size = 16
const icon = watchLaterAdded ? (
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width={size} height={size}>
<motion.path
Expand Down
4 changes: 2 additions & 2 deletions src/utility/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const singleLine = styled.generateClassName`
text-align: center;
`

export function toast(msg: string, duration = 2000) {
export function toast(msg: string, duration = 2000, container = document.body) {
const div = document.createElement('div')
div.classList.add(toastContainer, APP_NAME_ROOT_CLASSNAME)
div.innerText = msg
Expand All @@ -36,7 +36,7 @@ export function toast(msg: string, duration = 2000) {
div.classList.add(singleLine)
}

document.body.appendChild(div)
container.appendChild(div)
setTimeout(() => div.remove(), duration)
}

Expand Down

0 comments on commit ab5b039

Please sign in to comment.