Skip to content

Commit

Permalink
feat: split screen support (#327)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
arashsheyda and antfu committed Jul 18, 2023
1 parent 4d2f842 commit f2eee67
Show file tree
Hide file tree
Showing 25 changed files with 314 additions and 114 deletions.
2 changes: 2 additions & 0 deletions packages/devtools-kit/src/_types/custom-tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,5 @@ export interface ModuleBuiltinTab {
}

export type ModuleTabInfo = ModuleCustomTab | ModuleBuiltinTab

export type CategorizedTabs = [TabCategory, (ModuleCustomTab | ModuleBuiltinTab)[]][]
25 changes: 24 additions & 1 deletion packages/devtools/client/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'splitpanes/dist/splitpanes.css'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import './styles/global.css'
import { setupClientRPC } from './setup/client-rpc'
import { splitScreenAvailable } from '~/composables/storage'
if (process.client)
import('./setup/unocss-runtime')
Expand Down Expand Up @@ -62,6 +63,21 @@ onMounted(() => {
document.body.style.fontSize = `${scale.value * 15}px`
})
})
registerCommands(() =>
splitScreenAvailable.value
? [
{
id: 'action:split-screen',
title: `${splitScreenEnabled.value ? 'Close' : 'Open'} Split Screen`,
icon: 'i-carbon-split-screen',
action: () => {
splitScreenEnabled.value = !splitScreenEnabled.value
},
},
]
: [],
)
</script>

<template>
Expand All @@ -77,7 +93,14 @@ onMounted(() => {
>
<SideNav v-show="!isUtilityView" of-x-hidden of-y-auto />
<NuxtLayout>
<NuxtPage />
<PanelLeftRight storage-key="devtools:split-screen-mode" :min-size="20">
<template #left>
<NuxtPage />
</template>
<template v-if="splitScreenEnabled && splitScreenAvailable" #right>
<SplitScreen />
</template>
</PanelLeftRight>
</NuxtLayout>
<CommandPalette />
<AuthConfirmDialog />
Expand Down
32 changes: 17 additions & 15 deletions packages/devtools/client/components/ComponentsGraph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,23 @@ function setFilter() {
<template>
<Navbar ref="navbar" absolute left-0 right-0 top-0>
<template #search>
<NCheckbox v-model="showPages" n="primary sm">
<span op75>Show pages</span>
</NCheckbox>
<NCheckbox v-model="showLayouts" n="primary sm">
<span op75>Show layouts</span>
</NCheckbox>
<NCheckbox v-model="showWorkspace" n="primary sm">
<span op75>Show workspace</span>
</NCheckbox>
<NCheckbox v-model="showNodeModules" n="primary sm">
<span op75>Show node_modules</span>
</NCheckbox>
<NCheckbox v-model="showGlobalComponents" n="primary sm">
<span op75>Show global components</span>
</NCheckbox>
<div flex="~ gap-4 wrap" w-full>
<NCheckbox v-model="showPages" n="primary sm">
<span op75>Show pages</span>
</NCheckbox>
<NCheckbox v-model="showLayouts" n="primary sm">
<span op75>Show layouts</span>
</NCheckbox>
<NCheckbox v-model="showWorkspace" n="primary sm">
<span op75>Show workspace</span>
</NCheckbox>
<NCheckbox v-model="showNodeModules" n="primary sm">
<span op75>Show node_modules</span>
</NCheckbox>
<NCheckbox v-model="showGlobalComponents" n="primary sm">
<span op75>Show global components</span>
</NCheckbox>
</div>
<button v-if="selectedFilter" flex="~ gap-1" items-center rounded-full bg-gray:20 py1 pl3 pr2 text-xs op50 hover:op100 @click="selectedFilter = undefined">
Clear filter <div i-carbon-close />
</button>
Expand Down
10 changes: 10 additions & 0 deletions packages/devtools/client/components/DockingPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ function refreshData() {
function refreshPage() {
location.reload()
}
function toggleSplitScreen() {
splitScreenEnabled.value = !splitScreenEnabled.value
}
</script>

<template>
Expand All @@ -23,6 +27,12 @@ function refreshPage() {
<NButton n="sm primary" to="/settings">
<div i-carbon-settings-adjust /> Settings
</NButton>
</div>
<div px3 py2 border="b base" flex="~ gap-2">
<NButton v-if="splitScreenAvailable" n="sm primary" @click="toggleSplitScreen">
<div i-carbon-split-screen />
{{ splitScreenEnabled ? 'Close Split Screen' : 'Split Screen' }}
</NButton>
<PictureInPictureButton />
</div>
<div px3 py2 flex="~ gap2">
Expand Down
4 changes: 3 additions & 1 deletion packages/devtools/client/components/ModuleItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const data = computed(() => ({
...props.mod,
...staticInfo.value,
}))
const terminalId = useCurrentTerminalId()
</script>

<template>
Expand All @@ -27,7 +28,8 @@ const data = computed(() => ({
<NuxtLink
v-if="state === 'running'" flex="~ gap-2"
animate-pulse items-center
:to="id ? `/modules/terminals?id=${encodeURIComponent(id)}` : undefined"
:to="id ? '/modules/terminals' : undefined"
@click="id ? terminalId = id : undefined"
>
<span i-carbon-circle-dash animate-spin text-lg op50 />
<code text-sm op50>Upgrading...</code>
Expand Down
7 changes: 5 additions & 2 deletions packages/devtools/client/components/NpmVersionCheck.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const shouldRestartServer = ref(true)
const restartDialogs = useRestartDialogs()
const PromiseConfirm = createTemplatePromise<boolean, [string]>()
const terminalId = useCurrentTerminalId()
async function updateWithConfirm() {
const processId = await update(async (command) => {
Expand All @@ -37,8 +38,10 @@ async function updateWithConfirm() {
message: `${props.packageName} has been updated. Do you want to restart the Nuxt server now?`,
})
}
if (processId && shouldGotoTerminal.value)
router.push(`/modules/terminals?id=${encodeURIComponent(processId)}`)
if (processId && shouldGotoTerminal.value) {
terminalId.value = processId
router.push('/modules/terminals')
}
}
</script>

Expand Down
6 changes: 3 additions & 3 deletions packages/devtools/client/components/PanelLeftRight.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const props = defineProps<{
* The key to use for storing the pane sizes in localStorage.
*/
storageKey?: string
leftSize?: number
minSize?: number
}>()
const DEFAULT = 30
Expand All @@ -24,10 +24,10 @@ const size = key

<template>
<Splitpanes h-full of-hidden @resize="size = $event[0].size">
<Pane border="r base" h-full class="of-auto!" :size="size" min-size="10">
<Pane border="r base" h-full class="of-auto!" :size="size" :min-size="$slots.right ? (minSize || 10) : 100">
<slot name="left" />
</Pane>
<Pane relative h-full class="of-auto!" min-size="10">
<Pane v-if="$slots.right" relative h-full class="of-auto!" :min-size="minSize || 10">
<slot name="right" />
</Pane>
</Splitpanes>
Expand Down
5 changes: 2 additions & 3 deletions packages/devtools/client/components/ServerRouteDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const props = defineProps<{
route: ServerRouteInfo
}>()
const currentRoute = useRoute()
const config = useServerConfig()
const response = reactive({
Expand Down Expand Up @@ -67,7 +66,7 @@ const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD']
const bodyPayloadMethods = ['PATCH', 'POST', 'PUT', 'DELETE']
const hasBody = computed(() => bodyPayloadMethods.includes(routeMethod.value.toUpperCase()))
const activeTab = ref(currentRoute.query.tab ? currentRoute.query.tab : paramNames.value.length ? 'params' : 'query')
const activeTab = ref(paramNames.value.length ? 'params' : 'query')
const tabInputs = ['input', 'json']
const selectedTabInput = ref(tabInputs[0])
Expand Down Expand Up @@ -303,7 +302,7 @@ watch(currentParams, (value) => {
</div>
</div>

<div flex="~ gap2" w-full items-center px4 pb2 text-center text-sm border="b base">
<div flex="~ gap2 wrap" w-full items-center px4 pb2 text-center text-sm border="b base">
<NButton
v-for="tab of tabs"
:key="tab.slug"
Expand Down
16 changes: 7 additions & 9 deletions packages/devtools/client/components/ServerRouteListItem.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script setup lang="ts">
import { NuxtLink } from '#components'
import type { ServerRouteInfo } from '~/../src/types'
withDefaults(defineProps<{
Expand All @@ -10,17 +9,16 @@ withDefaults(defineProps<{
})
const open = ref(true)
const currentServerRoute = useCurrentServeRoute()
</script>

<template>
<div>
<component
:is="item.routes ? 'button' : NuxtLink"
flex="~ gap-2" w-full items-center hover-bg-active px2 py1
:class="[{ 'bg-active': $route.query.path === item.route && $route.query.method === item.method }]"
<button
flex="~ gap-2" w-full items-start items-center hover-bg-active px2 py1
:class="[{ 'bg-active': currentServerRoute === item.filepath }]"
:style="{ paddingLeft: `calc(0.5rem + ${index * 1.5}em)` }"
:to="{ query: { path: item.route, method: item.method } }"
@click="open = !open"
@click="open = !open;currentServerRoute = item.filepath"
>
<div :class="{ 'w-12': !item.routes }" flex-none text-left>
<NIcon v-if="item.type === 'collection'" icon="carbon:chevron-right" mb0.5 :transform-rotate="open ? 90 : 0" transition />
Expand All @@ -30,7 +28,7 @@ const open = ref(true)
v-text="(item.method || '*').toUpperCase()"
/>
</div>
<span :class="{ 'flex items-center': item.routes }" flex-auto text-sm font-mono>
<span :class="{ 'flex items-center': item.routes }" text-sm font-mono>
<NIcon v-if="item.type === 'collection'" :title="`${item.routes?.length} routes`" icon="carbon:folder" mr1 />
{{ item.route }}
</span>
Expand All @@ -40,7 +38,7 @@ const open = ref(true)
<NIconButton icon="carbon-overflow-menu-vertical" @click.stop.prevent="click()" />
</template>
</NDropdown> -->
</component>
</button>
<div x-divider />
<slot v-if="open">
<ServerRouteListItem
Expand Down
17 changes: 3 additions & 14 deletions packages/devtools/client/components/SideNav.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import TabsGrid from './TabsGrid.vue'
const client = useClient()
const allTabs = useEnabledTabs()
Expand Down Expand Up @@ -118,20 +120,7 @@ onClickOutside(
</div>
</button>
<template #popper>
<div flex="~ col gap-1" max-w-80 py1>
<template v-for="[name, tabs], idx of categorizedOverflowTabs" :key="name">
<template v-if="tabs.length">
<div v-if="idx" h-1px border="b base" />
<div flex="~ wrap" px1>
<SideNavItem
v-for="tab of tabs"
:key="tab.name"
:tab="tab"
/>
</div>
</template>
</template>
</div>
<TabsGrid :categories="categorizedOverflowTabs" max-w-80 target="main" />
</template>
</VDropdown>
<NuxtLink
Expand Down
27 changes: 21 additions & 6 deletions packages/devtools/client/components/SideNavItem.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
<script setup lang="ts">
import { NuxtLink } from '#components'
import type { ModuleBuiltinTab, ModuleCustomTab } from '~/../src/types'
const props = defineProps<{
tab: ModuleCustomTab | ModuleBuiltinTab
}>()
const props = withDefaults(
defineProps<{
tab: ModuleCustomTab | ModuleBuiltinTab
target?: 'main' | 'side'
}>(),
{
target: 'main',
},
)
const route = useRoute()
const badge = computed(() => 'badge' in props.tab && props.tab.badge?.())
const tabPath = computed(() => 'path' in props.tab ? props.tab.path! : `/modules/custom-${props.tab.name}`)
const isActive = computed(() => route.path.startsWith(tabPath.value))
function onClick() {
if ('onClick' in props.tab && props.tab.onClick)
props.tab.onClick()
else if (props.target === 'side')
splitScreenView.value = props.tab.name
}
</script>

<template>
<VTooltip placement="right">
<NuxtLink
<component
:is="target === 'main' ? NuxtLink : 'button'"
:to="tabPath"
flex="~"
hover="bg-active" relative
h-10 w-10 select-none items-center justify-center rounded-xl p1 text-secondary
exact-active-class="!text-primary bg-active"
@click="'onClick' in tab && tab.onClick?.()"
@click="onClick"
>
<TabIcon
text-xl
Expand All @@ -33,7 +48,7 @@ const isActive = computed(() => route.path.startsWith(tabPath.value))
>
<span translate-y-0.5px>{{ toValue(badge) }}</span>
</div>
</NuxtLink>
</component>
<template #popper>
<div>
{{ tab.title }}
Expand Down

0 comments on commit f2eee67

Please sign in to comment.