From 0e273d9ab13b814e9d89a6933881fd225ebe9e9a Mon Sep 17 00:00:00 2001 From: Arturo Manzoli Date: Mon, 17 Feb 2025 14:04:53 -0300 Subject: [PATCH] Composables: Add dialog queue composable Signed-off-by: Arturo Manzoli --- src/App.vue | 34 +++++++----- src/composables/dialogQueue.ts | 96 ++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 src/composables/dialogQueue.ts diff --git a/src/App.vue b/src/App.vue index d74fab760..7f2e7fed3 100644 --- a/src/App.vue +++ b/src/App.vue @@ -310,10 +310,11 @@ - - - + +
+ +
@@ -336,6 +337,7 @@ import Tutorial from '@/components/Tutorial.vue' import UpdateNotification from '@/components/UpdateNotification.vue' import VehicleDiscoveryDialog from '@/components/VehicleDiscoveryDialog.vue' import VideoLibraryModal from '@/components/VideoLibraryModal.vue' +import { useComponentQueue } from '@/composables/dialogQueue' import { useInteractionDialog } from '@/composables/interactionDialog' import { availableCockpitActions, @@ -366,6 +368,8 @@ import ConfigurationUIView from './views/ConfigurationUIView.vue' import ConfigurationVideoView from './views/ConfigurationVideoView.vue' import ToolsDataLakeView from './views/ToolsDataLakeView.vue' import ToolsMAVLinkView from './views/ToolsMAVLinkView.vue' + +const { enqueueDialog, WrappedDialog } = useComponentQueue() const { showDialog, closeDialog } = useInteractionDialog() const { openSnackbar } = useSnackbar() @@ -760,23 +764,27 @@ onBeforeUnmount(() => { const currentTopBarHeightPixels = computed(() => `${widgetStore.currentTopBarHeightPixels}px`) const currentBottomBarHeightPixels = computed(() => `${widgetStore.currentBottomBarHeightPixels}px`) -const showDiscoveryDialog = ref(false) const preventAutoSearch = useStorage('cockpit-prevent-auto-vehicle-discovery-dialog', false) onMounted(() => { - if (isElectron() && !preventAutoSearch.value) { + if (!interfaceStore.userHasSeenTutorial) { + enqueueDialog({ + component: Tutorial, + }) + } + if (isElectron()) { + enqueueDialog({ + component: UpdateNotification, + }) // Wait 5 seconds to check if we're connected to a vehicle setTimeout(() => { - if (vehicleStore.isVehicleOnline) return - showDiscoveryDialog.value = true + if (vehicleStore.isVehicleOnline || preventAutoSearch.value) return + enqueueDialog({ + component: VehicleDiscoveryDialog, + props: { showAutoSearchOption: true }, + }) }, 5000) } - - if (!interfaceStore.userHasSeenTutorial) { - setTimeout(() => { - interfaceStore.isTutorialVisible = true - }, 6000) - } }) diff --git a/src/composables/dialogQueue.ts b/src/composables/dialogQueue.ts new file mode 100644 index 000000000..5db044a07 --- /dev/null +++ b/src/composables/dialogQueue.ts @@ -0,0 +1,96 @@ +import { Component, computed, defineComponent, h, Ref, ref } from 'vue' + +/** + * Queued component to be displayed. Usually a dialog. + */ +export interface QueuedComponent { + /** + * The component reference (e.g. Tutorial or VehicleDiscoveryDialog) + */ + component: Component + /** + * Optional props to pass into the component + */ + props?: Record +} + +/** + * Component queue to manage the order of components to be displayed. + */ +export interface ComponentQueue { + /** + * Enqueue a dialog to be displayed. + */ + enqueueDialog: (item: QueuedComponent) => void + /** + * Clear the queue. + */ + clear: () => void + /** + * The queue itself. + */ + queue: Ref + /** + * The current dialog to be displayed. + */ + currentDialog: Ref + /** + * Whether the dialog is visible or not. + */ + isDialogVisible: Ref + /** + * The wrapped dialog component. + */ + WrappedDialog: Ref +} + +export const useComponentQueue = (): ComponentQueue => { + const queue: Ref = ref([]) + const isDialogVisible: Ref = ref(true) + + const enqueueDialog = (item: QueuedComponent): void => { + queue.value.push(item) + } + + const clear = (): void => { + queue.value = [] + } + + const currentDialog = computed(() => queue.value[0] || null) + + const closeCurrentDialog = (): void => { + queue.value.shift() + isDialogVisible.value = true + } + + const WrappedDialog = computed(() => { + if (!currentDialog.value) return null + + return defineComponent({ + name: 'WrappedDialog', + setup() { + const handleUpdate = (value: boolean): void => { + if (!value) { + closeCurrentDialog() + } + } + + return () => + h(currentDialog.value!.component, { + ...currentDialog.value!.props, + 'modelValue': isDialogVisible.value, + 'onUpdate:modelValue': handleUpdate, + }) + }, + }) + }) + + return { + enqueueDialog, + clear, + queue, + currentDialog, + isDialogVisible, + WrappedDialog, + } +}