diff --git a/app/components-react/root/StudioEditor.tsx b/app/components-react/root/StudioEditor.tsx index 6344c8d0597e..90d651092257 100644 --- a/app/components-react/root/StudioEditor.tsx +++ b/app/components-react/root/StudioEditor.tsx @@ -40,9 +40,13 @@ export default function StudioEditor() { const [studioModeStacked, setStudioModeStacked] = useState(false); const [verticalPlaceholder, setVerticalPlaceholder] = useState(false); const [messageActive, setMessageActive] = useState(false); - const studioModeTransitionName = useMemo(() => TransitionsService.getStudioTransitionName(), [ - v.studioMode, - ]); + + const [studioModeTransitionName, setStudioModeTransitionName] = useState(); + useEffect(() => { + if (!studioModeTransitionName) { + TransitionsService.actions.return.getStudioTransitionName().then(setStudioModeTransitionName); + } + }, [v.studioMode]); const sourceId = useMemo(() => { const dualOutputMode = v.showHorizontalDisplay && v.showVerticalDisplay; diff --git a/app/components-react/windows/AddSource.tsx b/app/components-react/windows/AddSource.tsx index e9e8c31af6f6..2fe862d74a41 100644 --- a/app/components-react/windows/AddSource.tsx +++ b/app/components-react/windows/AddSource.tsx @@ -13,6 +13,7 @@ import styles from './AddSource.m.less'; import { TextInput, SwitchInput } from 'components-react/shared/inputs'; import Form, { useForm } from 'components-react/shared/inputs/Form'; import Scrollable from 'components-react/shared/Scrollable'; +import { IObsListOption } from '../../components/obs/inputs/ObsInput'; export default function AddSource() { const { @@ -57,6 +58,15 @@ export default function AddSource() { const existingSources = sources.map(source => ({ name: source.name, value: source.sourceId })); + // TODO: maybe refactor into a `useSourceTypes` hook + const [sourceTypes, setSourceTypes] = useState[]>([]); + + useEffect(() => { + if (!sourceTypes.length) { + SourcesService.actions.return.getAvailableSourcesTypesList().then(setSourceTypes); + } + }, []); + useEffect(() => { const suggestName = (name: string) => SourcesService.views.suggestName(name); let name; @@ -80,14 +90,12 @@ export default function AddSource() { } else { const sourceDescription = sourceType && - SourcesService.getAvailableSourcesTypesList().find( - sourceTypeDef => sourceTypeDef.value === sourceType, - )?.description; + sourceTypes.find(sourceTypeDef => sourceTypeDef.value === sourceType)?.description; name = suggestName(sourceDescription || ''); } setName(name); - }, []); + }, [sourceTypes]); function close() { WindowsService.actions.closeChildWindow(); diff --git a/app/components-react/windows/source-showcase/SourceGrid.tsx b/app/components-react/windows/source-showcase/SourceGrid.tsx index bec94f3b9ca0..7e86cfc9bb38 100644 --- a/app/components-react/windows/source-showcase/SourceGrid.tsx +++ b/app/components-react/windows/source-showcase/SourceGrid.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Empty, Row, Col, PageHeader, Button } from 'antd'; import Scrollable from 'components-react/shared/Scrollable'; import { Services } from 'components-react/service-provider'; @@ -16,6 +16,8 @@ import { EAvailableFeatures } from 'services/incremental-rollout'; import { useRealmObject } from 'components-react/hooks/realm'; export default function SourceGrid(p: { activeTab: string }) { + const [sourceTypes, setSourceTypes] = useState[]>([]); + const { SourcesService, UserService, @@ -71,13 +73,19 @@ export default function SourceGrid(p: { activeTab: string }) { [], ); + useEffect(() => { + if (!sourceTypes.length) { + SourcesService.actions.return.getAvailableSourcesTypesList().then(setSourceTypes); + } + }, []); + const availableSources = useMemo(() => { const guestCamAvailable = (IncrementalRolloutService.views.featureIsEnabled(EAvailableFeatures.guestCamBeta) || IncrementalRolloutService.views.featureIsEnabled(EAvailableFeatures.guestCaProduction)) && UserService.views.isLoggedIn; - return SourcesService.getAvailableSourcesTypesList().filter(type => { + return sourceTypes.filter(type => { // Freetype on windows is hidden if (type.value === 'text_ft2_source' && byOS({ [OS.Windows]: true, [OS.Mac]: false })) { return; @@ -89,7 +97,7 @@ export default function SourceGrid(p: { activeTab: string }) { return !(type.value === 'scene' && ScenesService.views.scenes.length <= 1); }); - }, []); + }, [sourceTypes]); const essentialSources = useMemo(() => { const essentialDefaults = availableSources.filter(source => diff --git a/app/components-react/windows/source-showcase/useSourceShowcase.tsx b/app/components-react/windows/source-showcase/useSourceShowcase.tsx index 5bad82efec03..bb4a27d1fbd3 100644 --- a/app/components-react/windows/source-showcase/useSourceShowcase.tsx +++ b/app/components-react/windows/source-showcase/useSourceShowcase.tsx @@ -6,6 +6,7 @@ import { WidgetType } from 'services/widgets'; import { byOS, OS } from 'util/operating-systems'; import { IAppSource } from 'services/platform-apps'; import { initStore, useController } from 'components-react/hooks/zustand'; +import { IObsListOption } from '../../../components/obs/inputs/ObsInput'; interface ISelectSourceOptions { propertiesManager?: TPropertiesManager; @@ -26,8 +27,15 @@ export class SourceShowcaseController { : 'ffmpeg_source') as TInspectableSource, inspectedAppId: '', inspectedAppSourceId: '', + availableSourceTypes: [] as TSourceType[], }); + init() { + this.sourcesService.actions.return.getAvailableSourcesTypes().then(sourceTypes => { + this.store.setState({ availableSourceTypes: sourceTypes }); + }); + } + private get sourcesService() { return Services.SourcesService; } @@ -70,9 +78,7 @@ export class SourceShowcaseController { this.selectSource('image_source', { propertiesManager: 'iconLibrary' }); } else if (inspectedSource === 'app_source') { this.selectAppSource(this.store.inspectedAppId, this.store.inspectedAppSourceId); - } else if ( - this.sourcesService.getAvailableSourcesTypes().includes(inspectedSource as TSourceType) - ) { + } else if (this.store.availableSourceTypes.includes(inspectedSource as TSourceType)) { this.selectSource(inspectedSource as TSourceType); } } @@ -81,7 +87,7 @@ export class SourceShowcaseController { const managerType = options.propertiesManager || 'default'; const propertiesManagerSettings: Dictionary = { ...omit(options, 'propertiesManager') }; - this.sourcesService.showAddSource(sourceType, { + this.sourcesService.actions.showAddSource(sourceType, { propertiesManagerSettings, propertiesManager: managerType, }); diff --git a/app/util/menus/EditMenu.ts b/app/util/menus/EditMenu.ts index 40d8135485f2..057a8469b7d2 100644 --- a/app/util/menus/EditMenu.ts +++ b/app/util/menus/EditMenu.ts @@ -71,7 +71,7 @@ export class EditMenu extends Menu { this.appendEditMenuItems(); } - private appendEditMenuItems() { + private async appendEditMenuItems() { if (this.scene) { this.append({ label: $t('Paste (Reference)'), @@ -356,7 +356,9 @@ export class EditMenu extends Menu { }, }); - const filtersCount = this.sourceFiltersService.getFilters(this.source.sourceId).length; + const filtersCount = ( + await this.sourceFiltersService.actions.return.getFilters(this.source.sourceId) + ).length; this.append({ label: $t('Filters') + (filtersCount > 0 ? ` (${filtersCount})` : ''), diff --git a/test/helpers/webdriver/index.ts b/test/helpers/webdriver/index.ts index 9b583b02635a..6cb4ec7976e5 100644 --- a/test/helpers/webdriver/index.ts +++ b/test/helpers/webdriver/index.ts @@ -273,7 +273,7 @@ export function useWebdriver(options: ITestRunnerOptions = {}) { await focusMain(); // await t.context.app.webContents.executeJavaScript(disableTransitionsCode); - app.client.execute(disableTransitionsCode); + await app.client.execute(disableTransitionsCode); await focusMain(); // Wait up to N seconds before giving up looking for an element. @@ -296,7 +296,7 @@ export function useWebdriver(options: ITestRunnerOptions = {}) { await focusChild(); // await t.context.app.webContents.executeJavaScript(disableTransitionsCode); - app.client.execute(disableTransitionsCode); + await app.client.execute(disableTransitionsCode); await focusMain(); appIsRunning = true; @@ -332,7 +332,7 @@ export function useWebdriver(options: ITestRunnerOptions = {}) { */ async function checkErrorsInLogFile(t: TExecutionContext) { await sleep(1000); // electron-log needs some time to write down logs - const logs: string = await readLogs(); + const logs: string = readLogs(); lastLogs = logs; let ignoringErrors = false; const errors = logs @@ -428,7 +428,7 @@ export function useWebdriver(options: ITestRunnerOptions = {}) { } } } catch (e: unknown) { - fail('Test finalization failed'); + fail('Test finalization failed ' + (e as Error)?.message); console.error(e); } @@ -451,7 +451,7 @@ export function useWebdriver(options: ITestRunnerOptions = {}) { test.after.always(async t => { if (appIsRunning) await stopAppFn(t); if (!testPassed) saveFailedTestsToFile([testName]); - await saveTestStatsToFile(testStats); + saveTestStatsToFile(testStats); }); /**