Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(browser): add browser iframe mouse interaction #5815

Merged
merged 5 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/browser/src/client/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ function createIframe(container: HTMLDivElement, file: string) {

iframe.style.display = 'block'
iframe.style.border = 'none'
iframe.style.pointerEvents = 'none'
iframe.setAttribute('allowfullscreen', 'true')
iframe.setAttribute('allow', 'clipboard-write;')

iframes.set(file, iframe)
container.className = 'scrolls'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably move that to line 190

container.appendChild(iframe)
return iframe
}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/client/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,22 @@ declare global {
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const provideLocal: typeof import('@vueuse/core')['provideLocal']
const provideResizing: typeof import('./composables/browser')['provideResizing']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const recalculateDetailPanels: typeof import('./composables/navigation')['recalculateDetailPanels']
const recalculateDetailPanels: typeof import('./composables/browser')['recalculateDetailPanels']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const registerResizingListener: typeof import('./composables/browser')['registerResizingListener']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
Expand Down
29 changes: 22 additions & 7 deletions packages/ui/client/components/BrowserIframe.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
<script setup lang="ts">
const viewport = ref('custom')
import { recalculateDetailPanels } from '~/composables/navigation'
import { recalculateDetailPanels, registerResizingListener } from '~/composables/browser'

const sizes = {
type ViewportSize = 'small-mobile' | 'large-mobile' | 'tablet' | 'custom'

const sizes: Record<ViewportSize, [width: string, height: string]> = {
'small-mobile': ['320px', '568px'],
'large-mobile': ['414px', '896px'],
tablet: ['834px', '1112px'],
custom: ['100%', '100%'],
}

async function changeViewport(name: string) {
const testerRef = ref<HTMLDivElement>()
const viewport = ref<ViewportSize>('custom')

async function changeViewport(name: ViewportSize) {
if (viewport.value === name) {
viewport.value = 'custom'
} else {
viewport.value = name
}

const iframe = document.querySelector('#tester-ui iframe[data-vitest]')
const iframe = document.querySelector<HTMLIFrameElement>('#tester-ui iframe[data-vitest]')
if (!iframe) {
console.warn('Iframe not found')
return
Expand All @@ -31,6 +35,17 @@ async function changeViewport(name: string) {

recalculateDetailPanels()
}

function onResizing(isResizing: boolean) {
const tester = testerRef.value
if (!tester)
return

tester.style.pointerEvents = isResizing ? 'none' : ''
}
onMounted(() => {
registerResizingListener(onResizing)
})
</script>

<template>
Expand Down Expand Up @@ -84,8 +99,8 @@ async function changeViewport(name: string) {
@click="changeViewport('tablet')"
/>
</div>
<div flex-auto overflow-auto>
<div id="tester-ui" class="flex h-full justify-center items-center font-light op70" style="overflow: auto; width: 100%; height: 100%">
<div flex-auto class="scrolls">
<div id="tester-ui" ref="testerRef" class="flex h-full justify-center items-center font-light op70" style="overflow: auto; width: 100%; height: 100%">
Select a test to run
</div>
</div>
Expand Down
36 changes: 36 additions & 0 deletions packages/ui/client/composables/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { detailSizes } from '~/composables/navigation'

export type ResizingListener = (isResizing: boolean) => void

const resizingSymbol = Symbol.for('resizing')

export function recalculateDetailPanels() {
const iframe = document.querySelector('#tester-ui iframe[data-vitest]')!
const panel = document.querySelector('#details-splitpanes')!
const panelWidth = panel.clientWidth
const iframeWidth = iframe.clientWidth
const iframePercent = Math.min((iframeWidth / panelWidth) * 100, 95)
const detailsPercent = 100 - iframePercent
detailSizes.value = [iframePercent, detailsPercent]
}

export function registerResizingListener(listener: ResizingListener) {
inject<(listener: ResizingListener) => void>(resizingSymbol)?.(listener)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this just a ResizingListener?

Copy link
Member Author

@userquin userquin Jun 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to configure it globally (like navigation conposable), vitest ui is just a spa, dont need inject/provide

Copy link
Member Author

@userquin userquin Jun 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This listener is the callback called from the index.vue

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the type is repeated, you already defined it on the top

}

export function provideResizing() {
const listeners = new Set<ResizingListener>()

function addResizeListener(listener: ResizingListener) {
listeners.add(listener)
}

function notifyResizing(isResizing: boolean) {
for (const listener of listeners)
listener(isResizing)
}

provide(resizingSymbol, addResizeListener)

return { notifyResizing }
}
10 changes: 0 additions & 10 deletions packages/ui/client/composables/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@ export const detailSizes = useLocalStorage<[left: number, right: number]>('vites
initOnMounted: true,
})

export function recalculateDetailPanels() {
const iframe = document.querySelector('#tester-ui iframe[data-vitest]')!
const panel = document.querySelector('#details-splitpanes')!
const panelWidth = panel.clientWidth
const iframeWidth = iframe.clientWidth
const iframePercent = Math.min((iframeWidth / panelWidth) * 100, 95)
const detailsPercent = 100 - iframePercent
detailSizes.value = [iframePercent, detailsPercent]
}

// @ts-expect-error not typed global
window.__vitest_ui_api__ = {
get currentModule() {
Expand Down
8 changes: 6 additions & 2 deletions packages/ui/client/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// @ts-expect-error missing types
import { Pane, Splitpanes } from 'splitpanes'
import { browserState } from '~/composables/client';
import { coverageUrl, coverageVisible, initializeNavigation, detailSizes } from '../composables/navigation'
import { coverageUrl, coverageVisible, initializeNavigation, detailSizes } from '~/composables/navigation'
import { provideResizing } from '~/composables/browser'

const { notifyResizing } = provideResizing()
const dashboardVisible = initializeNavigation()

const mainSizes = useLocalStorage<[left: number, right: number]>('vitest-ui_splitpanes-mainSizes', [33, 67], {
initOnMounted: true,
})
Expand All @@ -18,6 +21,7 @@ const onModuleResized = useDebounceFn((event: { size: number }[]) => {
event.forEach((e, i) => {
detailSizes.value[i] = e.size
})
notifyResizing(false)
}, 0)

function resizeMain() {
Expand All @@ -41,7 +45,7 @@ function resizeMain() {
<Coverage v-else-if="coverageVisible" key="coverage" :src="coverageUrl" />
<FileDetails v-else />
</transition>
<Splitpanes v-else key="detail" id="details-splitpanes" @resized="onModuleResized">
<Splitpanes v-else key="detail" id="details-splitpanes" @resize="notifyResizing(true)" @resized="onModuleResized">
<Pane :size="detailSizes[0]">
<BrowserIframe v-once />
</Pane>
Expand Down
Loading