Skip to content

Commit

Permalink
Make preferences a modal on Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
grantjbutler committed Feb 6, 2022
1 parent 96c044b commit 3fdb346
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 115 deletions.
15 changes: 12 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
<template>
<div class="flex flex-col h-screen text-sm text-system-text">
<nav-bar v-if="isMacOS" class="flex-none"></nav-bar>
<command-bar v-if="isWindows" class="flex-none"></command-bar>
<command-bar v-if="isWindows" class="flex-none" @open-settings="openSettings"></command-bar>
<div class="flex flex-row items-stretch flex-1">
<sidebar class="flex-none border-r border-system-divider"></sidebar>
<preview></preview>
<controls class="flex-none border-l border-system-divider"></controls>
</div>
<preferences-modal :open="isSettingsOpen" @close="closeSettings"></preferences-modal>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, ref } from 'vue';
import Preview from './components/Preview.vue';
import Sidebar from './components/Sidebar.vue';
import Controls from './components/Controls.vue';
import NavBar from './components/NavBar.vue';
import CommandBar from './components/CommandBar.vue';
import PreferencesModal from './components/Preferences/Modal.vue';
import { useIsMacOS, useIsWindows } from './integration/platform';
export default defineComponent({
Expand All @@ -27,11 +29,18 @@ export default defineComponent({
Controls,
NavBar,
CommandBar,
PreferencesModal,
},
setup() {
const isSettingsOpen = ref(false);
return {
isMacOS: useIsMacOS(),
isWindows: useIsWindows()
isWindows: useIsWindows(),
isSettingsOpen,
openSettings: () => isSettingsOpen.value = true,
closeSettings: () => isSettingsOpen.value = false
}
}
});
Expand Down
97 changes: 4 additions & 93 deletions src/Preferences.vue
Original file line number Diff line number Diff line change
@@ -1,103 +1,14 @@
<template>
<div class="h-screen p-2 space-y-2 text-sm macos:bg-system-background-under-page macos:text-system-text">
<Controls label="OBS Connection">
<Control label="Host" type="text" v-model="connection.host"></Control>
<Control label="Port" type="text" v-model="connection.port"></Control>
<Control label="Password" type="password" v-model="connection.password"></Control>

<div class="flex justify-end macos:col-start-2 macos:col-end-9">
<button v-if="isConnectButtonVisible" class="px-3 py-1 bg-green-500 rounded" @click="connect">Connect</button>
<button v-if="isAbortButtonVisible" class="px-3 py-1 bg-yellow-500 rounded">Abort</button>
<button v-if="isDisconnectButtonVisible" class="px-3 py-1 bg-red-500 rounded" @click="disconnect">Disconnect</button>
</div>
</Controls>

<Controls label="Filters">
<Control label="Source Filter" type="text" v-model="sourceFilter"></Control>
<Control label="Scene Filter" type="text" v-model="sceneFilter"></Control>
</Controls>
</div>
<Content></Content>
</template>

<script lang="ts">
import { ipcRenderer } from 'electron';
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import debounce from 'lodash/debounce';
import { isOBSConnectionOptions } from './obs/connection';
import { useObsConnectionState } from './integration/obs';
import { OBSConnectionState } from './obs/connection-state';
import Controls from '@/components/Preferences/Controls.vue';
import Control from '@/components/Preferences/Control.vue';
import { defineComponent } from 'vue'
import Content from '@/components/Preferences/Content.vue';
export default defineComponent({
components: {
Controls,
Control
},
setup() {
const connectionState = useObsConnectionState();
const connection = ref({
host: 'localhost',
port: 4444,
password: null
});
const sourceFilter = ref('');
const sceneFilter = ref('');
const isConnectButtonVisible = computed(() => connectionState.value == OBSConnectionState.Disconnected || connectionState.value == OBSConnectionState.Error)
const isAbortButtonVisible = computed(() => connectionState.value == OBSConnectionState.Connecting);
const isDisconnectButtonVisible = computed(() => connectionState.value == OBSConnectionState.Connected);
const connect = () => {
if (isOBSConnectionOptions(connection.value)) {
ipcRenderer.send('connect-to-obs', JSON.parse(JSON.stringify(connection.value)));
}
}
const disconnect = () => {
ipcRenderer.send('disconnect-from-obs');
}
onMounted(() => {
ipcRenderer.invoke('load-obs-connection')
.then(connection => {
if (connection) {
connection.value = connection
}
});
ipcRenderer.invoke('load-source-filter')
.then(filter => {
sourceFilter.value = filter;
})
ipcRenderer.invoke('load-scene-filter')
.then(filter => {
sceneFilter.value = filter;
});
});
watch(sourceFilter, debounce((newFilter: string) => {
ipcRenderer.send('set-source-filter', newFilter);
}));
watch(sceneFilter, debounce((newFilter: string) => {
ipcRenderer.send('set-scene-filter', newFilter);
}));
return {
connection,
connectionState,
connect,
disconnect,
isConnectButtonVisible,
isAbortButtonVisible,
isDisconnectButtonVisible,
sourceFilter,
sceneFilter
}
Content
}
})
</script>
Expand Down
10 changes: 3 additions & 7 deletions src/components/CommandBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { defineComponent } from 'vue'
import { CloudUploadIcon, CogIcon } from '@heroicons/vue/outline';
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue'
import ConnectionState from './ConnectionState.vue';
import { ipcRenderer } from 'electron';
import SyncPopover from './SyncPopover.vue';
export default defineComponent({
Expand All @@ -46,14 +45,11 @@ export default defineComponent({
PopoverButton,
PopoverPanel
},
setup() {
const openSettings = () => {
ipcRenderer.send('open-settings');
}
setup(_, { emit }) {
return {
openSettings
openSettings: () => emit('openSettings')
}
},
emits: ['openSettings']
})
</script>
111 changes: 111 additions & 0 deletions src/components/Preferences/Content.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<template>
<div class="text-sm macos:bg-system-background-under-page macos:text-system-text">
<div class="macos:space-y-2 windows:flex windows:flex-col windows:gap-8 windows:w-1/2">
<Controls label="OBS Connection">
<Control label="Host" type="text" v-model="connection.host"></Control>
<Control label="Port" type="text" v-model="connection.port"></Control>
<Control label="Password" type="password" v-model="connection.password"></Control>

<div class="flex justify-end macos:col-start-2 macos:col-end-9 windows:w-2/3">
<button v-if="isConnectButtonVisible" class="px-3 py-1 bg-green-500 rounded" @click="connect">Connect</button>
<button v-if="isAbortButtonVisible" class="px-3 py-1 bg-yellow-500 rounded">Abort</button>
<button v-if="isDisconnectButtonVisible" class="px-3 py-1 bg-red-500 rounded" @click="disconnect">Disconnect</button>
</div>
</Controls>

<Controls label="Filters">
<div v-if="isWindows" class="mb-2">Filters allow you to limit which scenes and sources show up.</div>
<Control label="Source Filter" type="text" v-model="sourceFilter"></Control>
<Control label="Scene Filter" type="text" v-model="sceneFilter"></Control>
</Controls>
</div>
</div>
</template>

<script lang="ts">
import { ipcRenderer } from 'electron';
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import debounce from 'lodash/debounce';
import { isOBSConnectionOptions } from '@/obs/connection';
import { useObsConnectionState } from '@/integration/obs';
import { OBSConnectionState } from '@/obs/connection-state';
import Controls from '@/components/Preferences/Controls.vue';
import Control from '@/components/Preferences/Control.vue';
import { useIsWindows } from '@/integration/platform';
export default defineComponent({
components: {
Controls,
Control
},
setup() {
const connectionState = useObsConnectionState();
const connection = ref({
host: 'localhost',
port: 4444,
password: null
});
const sourceFilter = ref('');
const sceneFilter = ref('');
const isConnectButtonVisible = computed(() => connectionState.value == OBSConnectionState.Disconnected || connectionState.value == OBSConnectionState.Error)
const isAbortButtonVisible = computed(() => connectionState.value == OBSConnectionState.Connecting);
const isDisconnectButtonVisible = computed(() => connectionState.value == OBSConnectionState.Connected);
const connect = () => {
if (isOBSConnectionOptions(connection.value)) {
ipcRenderer.send('connect-to-obs', JSON.parse(JSON.stringify(connection.value)));
}
}
const disconnect = () => {
ipcRenderer.send('disconnect-from-obs');
}
onMounted(() => {
ipcRenderer.invoke('load-obs-connection')
.then(connection => {
if (connection) {
connection.value = connection
}
});
ipcRenderer.invoke('load-source-filter')
.then(filter => {
sourceFilter.value = filter;
})
ipcRenderer.invoke('load-scene-filter')
.then(filter => {
sceneFilter.value = filter;
});
});
watch(sourceFilter, debounce((newFilter: string) => {
ipcRenderer.send('set-source-filter', newFilter);
}));
watch(sceneFilter, debounce((newFilter: string) => {
ipcRenderer.send('set-scene-filter', newFilter);
}));
const isWindows = useIsWindows();
return {
connection,
connectionState,
connect,
disconnect,
isConnectButtonVisible,
isAbortButtonVisible,
isDisconnectButtonVisible,
sourceFilter,
sceneFilter,
isWindows
}
}
})
</script>
7 changes: 2 additions & 5 deletions src/components/Preferences/Control.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<template>
<label class="macos:col-span-2 macos:col-start-2 macos:text-right">{{ label }}</label>
<input class="macos:col-span-5 macos:col-end-9 macos:px-2 macos:py-1 macos:rounded macos:text-system-text-control macos:bg-system-background-control" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" v-bind="$attrs">
<input class="macos:col-span-5 macos:col-end-9 macos:px-2 macos:py-1 macos:rounded macos:text-system-text-control macos:bg-system-background-control windows:mb-2 windows:w-2/3 windows:text-sm windows:border-gray-300" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" v-bind="$attrs">
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
type Value = string | number
import { defineComponent } from 'vue'
export default defineComponent({
name: 'Control',
Expand All @@ -16,7 +14,6 @@ export default defineComponent({
required: true
},
modelValue: {
type: Object as PropType<Value>,
required: true
}
},
Expand Down
6 changes: 3 additions & 3 deletions src/components/Preferences/Controls.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<fieldset>
<legend class="macos:ml-2">{{ label }}</legend>
<legend class="macos:ml-2 windows:text-2xl windows:mb-4">{{ label }}</legend>

<div class="p-2 space-y-2 macos:border macos:rounded macos:border-system-separator macos:bg-system-background-window">
<div class="macos:grid macos:items-baseline macos:grid-cols-9 macos:gap-2">
<div class="macos:p-2 macos:border macos:rounded macos:border-system-separator macos:bg-system-background-window">
<div class="macos:grid macos:items-baseline macos:grid-cols-9 macos:gap-2 windows:flex windows:flex-col">
<slot></slot>
</div>
</div>
Expand Down
45 changes: 45 additions & 0 deletions src/components/Preferences/Modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<Dialog :open="open" @close="close" class="fixed inset-x-0 bottom-0 z-10 bg-white flex flex-col" style="top: env(titlebar-area-height, 40px);">
<DialogTitle class="text-4xl font-light flex space-x-2 mb-4">
<button class="hover:bg-gray-200 px-2 py-2" title="Back" @click.prevent="close">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
</button>

<span>Settings</span>
</DialogTitle>

<Content class="p-6 pt-4 overflow-y-auto"></Content>
</Dialog>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import {
Dialog,
DialogTitle,
} from "@headlessui/vue";
import Content from './Content.vue';
export default defineComponent({
components: {
Dialog,
DialogTitle,
Content
},
props: {
open: {
type: Boolean,
required: true
}
},
emits: ['close'],
setup(_, { emit }) {
return {
close: () => emit('close')
};
}
})
</script>
4 changes: 0 additions & 4 deletions src/electron/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,4 @@ export function install(options: InstallationOptions): void {
ipcMain.handle('sync-layout-to-scene', (_, nodes: Node[], sceneName: string) => {
return options.obsSocket.syncLayout(nodes, sceneName);
})

ipcMain.on('open-settings', () => {
emitter.emit('open-preferences');
})
}
1 change: 1 addition & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module.exports = {
borderWidth: ['responsive', 'macos', 'windows'],
boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus', 'macos', 'windows', 'window-blur'],
display: ['responsive', 'macos', 'windows'],
flexDirection: ['responsive', 'macos', 'windows'],
flexGrow: ['responsive', 'macos', 'windows'],
flexShrink: ['responsive', 'macos', 'windows'],
fontSize: ['responsive', 'macos', 'windows'],
Expand Down

0 comments on commit 3fdb346

Please sign in to comment.