Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
34 changes: 34 additions & 0 deletions src/renderer/src/components/docks/IrlControl.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<AppGoldenLayoutContainer>
<template v-if="false">

</template>
<AppEmptyState
v-else
:icon="{ name: 'server' }"
:actions="actions"
title="No IRL Control"
description="Not connected to a server"
/>
</AppGoldenLayoutContainer>
</template>

<script setup lang="ts">
import { useAppStore } from '../../store/app'
import AppEmptyState from '../atoms/AppEmptyState.vue'
import { ButtonVariant } from '../atoms/AppButton.vue'
import AppGoldenLayoutContainer from '../atoms/AppGoldenLayoutContainer.vue'
import { usePopupStore } from '../../store/popup'

const { openPopup } = usePopupStore()
const store = useAppStore()

const actions = [
{
label: 'Add Server',
variant: 'outline' as ButtonVariant,
onClick: () => {
}
}
]
</script>
40 changes: 5 additions & 35 deletions src/renderer/src/components/molecules/AppGoldenLayout.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,21 @@
<template>
<Glayout
ref="GLayoutRoot"
:component-types="componentTypes"
:component-types="docks.componentTypes"
class="h-full w-full"
/>
</template>

<script setup lang="ts">
import Glayout from '../atoms/AppGoldenLayout.vue'
import SceneItemList from '../docks/SceneItemList.vue'
import SceneList from '../docks/SceneList.vue'
import StudioView from '../docks/StudioView.vue'
import AudioMixer from '../docks/AudioMixer.vue'
import { markRaw, onMounted, ref } from 'vue'
import { useWaitForRef } from '../../composables/useWaitForComponent'
import { defaultLayoutConfig } from '../../predefined-layouts'
import { LayoutConfig } from 'golden-layout'
import { onMounted, ref } from 'vue'
import { useDocksStore } from '../../store/dock'

const GLayoutRoot = ref<null | typeof Glayout>(null)

const componentTypes = {
Sources: markRaw(SceneItemList),
Scenes: markRaw(SceneList),
Main: markRaw(StudioView),
AudioMixer: markRaw(AudioMixer)
}
const docks = useDocksStore()

onMounted(async () => {
await onLoadLayout()
await docks.onLoadLayout(GLayoutRoot)
})

const onLoadLayout = async () => {
const layout = await useWaitForRef<typeof Glayout>(GLayoutRoot)

const str = localStorage.getItem('gl_config')
if (!str) {
layout.loadGLLayout(defaultLayoutConfig)
return
}

const config = JSON.parse(str as string) as LayoutConfig
config.header = {
...config.header,
maximise: false,
popout: false
}
console.log(config)
layout.loadGLLayout(config)
}
</script>
111 changes: 74 additions & 37 deletions src/renderer/src/components/organisms/AppTitlebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class="flex justify-center items-center hover:bg-white/10 w-8 h-8 rounded"
@click="showSecondLevelMenu = !showSecondLevelMenu"
>
<i class="fas fa-fw fa-bars"/>
<i class="fas fa-fw fa-bars" />
</button>

<div
Expand Down Expand Up @@ -92,35 +92,37 @@
</OnClickOutside>

<div class="flex items-center gap-6 -mr-6">
<AppControls v-if="store.connected"/>
<AppElectronControls/>
<AppControls v-if="store.connected" />
<AppElectronControls />
</div>
</div>
</div>
</template>

<script setup lang="ts">
import {OnClickOutside} from '@vueuse/components'
import AppTitlebarDropdown, {MenuItem} from '../atoms/AppTitlebarDropdown.vue'
import {computed, Ref, ref} from 'vue'
import {Connection, useAppStore} from '../../store/app'
import {useObs} from '../../composables/useObs'
import {useNotificationStore} from '../../store/notification'
import { OnClickOutside } from '@vueuse/components'
import AppTitlebarDropdown, { MenuItem } from '../atoms/AppTitlebarDropdown.vue'
import { computed, Ref, ref } from 'vue'
import { Connection, useAppStore } from '../../store/app'
import { useObs } from '../../composables/useObs'
import { useNotificationStore } from '../../store/notification'
import AppControls from '../atoms/AppControls.vue'
import {usePopupStore} from '../../store/popup'
import {colorPalette} from '../../color-palette'
import { usePopupStore } from '../../store/popup'
import { useDocksStore } from '../../store/dock'
import { colorPalette } from '../../color-palette'
import AppElectronControls from '../molecules/AppElectronControls.vue'
import {useUserStore} from '../../store/user'
import {storeToRefs} from 'pinia'
import LoginPopup from "../popups/LoginPopup.vue";
import ConnectPopup from "../popups/ConnectPopup.vue";
import { useUserStore } from '../../store/user'
import { storeToRefs } from 'pinia'
import LoginPopup from '../popups/LoginPopup.vue'
import ConnectPopup from '../popups/ConnectPopup.vue'

const store = useAppStore()
const {error} = useNotificationStore()
const {openPopup} = usePopupStore()
const {obs} = useObs()
const docks = useDocksStore()
const { error } = useNotificationStore()
const { openPopup } = usePopupStore()
const { obs } = useObs()
const userStore = useUserStore()
const {user} = storeToRefs(userStore);
const { user } = storeToRefs(userStore)

const showSecondLevelMenu = ref(false)

Expand All @@ -132,13 +134,13 @@ const secondLevelMenus = computed(() => {
{
id: 0,
label: 'Sign in',
icon: {name: 'sign-in'},
icon: { name: 'sign-in' },
click: () => openPopup(LoginPopup)
},
{
id: 1,
label: 'Sign out',
icon: {name: 'sign-out'},
icon: { name: 'sign-out' },
click: () => userStore.logout()
}
]
Expand All @@ -149,56 +151,91 @@ const secondLevelMenus = computed(() => {
{
id: 0,
label: 'Studio Mode',
icon: store.studioMode ? {name: 'check'} : {name: 'empty'},
icon: store.studioMode ? { name: 'check' } : { name: 'empty' },
click: () => store.toggleStudioMode()
},
{
id: 10,
label: 'Image Quality: Low Bandwidth',
icon: store.screenshot.imageCompressionQuality === 10 ? {name: 'check'} : {name: 'empty'},
icon: store.screenshot.imageCompressionQuality === 10 ? { name: 'check' } : { name: 'empty' },
click: () => store.setImageCompressionQuality(10)
},
{
id: 40,
label: 'Image Quality: Medium Bandwidth',
icon: store.screenshot.imageCompressionQuality === 40 ? {name: 'check'} : {name: 'empty'},
icon: store.screenshot.imageCompressionQuality === 40 ? { name: 'check' } : { name: 'empty' },
click: () => store.setImageCompressionQuality(40)
},
{
id: 80,
label: 'Image Quality: High Bandwidth',
icon: store.screenshot.imageCompressionQuality === 80 ? {name: 'check'} : {name: 'empty'},
icon: store.screenshot.imageCompressionQuality === 80 ? { name: 'check' } : { name: 'empty' },
click: () => store.setImageCompressionQuality(80)
}
]
},
{
label: 'Docks',
menuItems: [
{
id: 0,
label: 'Scenes',
icon: docks.loadedComponentTypes.includes('Sources') ? { name: 'check' } : { name: 'empty' },
click: async () => await docks.addComponent('Sources', 'Sources')
},
{
id: 10,
label: 'Sources',
icon: docks.loadedComponentTypes.includes('Scenes') ? { name: 'check' } : { name: 'empty' },
click: async () => await docks.addComponent('Scenes', 'Scenes')
},
{
id: 40,
label: 'Studio View',
icon: docks.loadedComponentTypes.includes('StudioView') ? { name: 'check' } : { name: 'empty' },
click: async () => await docks.addComponent('StudioView', 'Studio View')
},
{
id: 80,
label: 'Audio Mixer',
icon: docks.loadedComponentTypes.includes('AudioMixer') ? { name: 'check' } : { name: 'empty' },
click: async () => await docks.addComponent('AudioMixer', 'Audio Mixer')
},
{
id: 80,
label: 'IRL Control',
icon: docks.loadedComponentTypes.includes('IrlControl') ? { name: 'check' } : { name: 'empty' },
click: async () => await docks.addComponent('IrlControl', 'IRL Control')
}
]
},
{
label: 'Help',
menuItems: [
{
id: 0,
label: 'About',
icon: {name: 'info-circle'}
icon: { name: 'info-circle' }
},
{
id: 1,
label: 'Check for updates',
icon: {name: 'download'}
icon: { name: 'download' }
},
{
id: 2,
label: 'Report a bug',
icon: {name: 'bug'}
icon: { name: 'bug' }
},
{
id: 3,
label: 'Join the Discord',
icon: {name: 'discord'}
icon: { name: 'discord' }
},
{
id: 4,
label: 'Open the Wiki',
icon: {name: 'book'}
icon: { name: 'book' }
}
]
}
Expand All @@ -210,16 +247,16 @@ const menuItems: Ref<MenuItem[]> = computed(() => {
{
id: 0,
label: 'Connect to a new server',
icon: {name: 'plus'}
icon: { name: 'plus' }
}
];
]

user.value?.connections?.forEach((connection) => {
items.push({
id: connection.id,
label: connection.name,
subtitle: `ws://${connection.ip}:${connection.port}`,
letter: {text: connection.name[0], color: connection.color},
letter: { text: connection.name[0], color: connection.color },
data: {
ip: connection.ip,
port: connection.port,
Expand All @@ -232,7 +269,7 @@ const menuItems: Ref<MenuItem[]> = computed(() => {
})

const calculateViaGradient = computed(() => {
const {r, g, b} = colorPalette[activeConnection.value.letter?.color ?? 'red']
const { r, g, b } = colorPalette[activeConnection.value.letter?.color ?? 'red']
return {
'background': `linear-gradient(90deg, #18181B 0px, rgba(${r}, ${g}, ${b}, .4) 95px, #18181B 300px)`,
'-webkit-app-region': 'drag'
Expand All @@ -243,15 +280,15 @@ const profileMenuItems = computed(() => {
return store.profileList.profiles.map((profile) => ({
id: profile,
label: profile,
icon: {name: 'user'}
icon: { name: 'user' }
}))
})

const sceneCollectionMenuItems = computed(() => {
return store.sceneCollectionList.sceneCollections.map((sceneCollection) => ({
id: sceneCollection,
label: sceneCollection,
icon: {name: 'rectangle-history'}
icon: { name: 'rectangle-history' }
}))
})

Expand All @@ -265,7 +302,7 @@ const activeConnection = computed(() => {
}) ?? {
label: store.connection.ip,
subtitle: `ws://${store.connection.ip}:${store.connection.port}`,
letter: {text: store.connection.ip[0], color: 'rose'},
letter: { text: store.connection.ip[0], color: 'rose' }
}
})

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/composables/useWaitForComponent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Ref } from 'vue'

export async function useWaitForRef<T>(ref: Ref) {
export async function useWaitForRef<T>(ref: Ref): Promise<T> {
return new Promise<T>((resolve) => {
const interval = setInterval(() => {
if (ref.value) {
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/predefined-layouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ export const defaultLayoutConfig: LayoutConfig = {
maximised: false,
isClosable: true,
reorderEnabled: true,
title: 'Main',
componentType: 'Main',
title: 'Studio View',
componentType: 'StudioView',
componentState: {
refId: 2
}
Expand Down
Loading