diff --git a/app/components-react/windows/source-showcase/SourceGrid.tsx b/app/components-react/windows/source-showcase/SourceGrid.tsx index 411e31546aa9..ade6befc1143 100644 --- a/app/components-react/windows/source-showcase/SourceGrid.tsx +++ b/app/components-react/windows/source-showcase/SourceGrid.tsx @@ -36,6 +36,14 @@ export default function SourceGrid(p: { activeTab: string }) { 'apps', ]); + const [widgetSections, setWidgetExpandedSections] = useState([ + 'essentialWidgets', + 'interactive', + 'goals', + 'flair', + 'charity', + ]); + const { isLoggedIn, linkedPlatforms, primaryPlatform } = useVuex(() => ({ isLoggedIn: UserService.views.isLoggedIn, linkedPlatforms: UserService.views.linkedPlatforms, @@ -103,6 +111,18 @@ export default function SourceGrid(p: { activeTab: string }) { }, []); const essentialSourcesOrder = ['game_capture', 'dshow_input', 'ffmpeg_source']; + // Stream Label is last, we don't have a widget type for it + const essentialWidgetsOrder = [ + WidgetType.AlertBox, + WidgetType.ChatBox, + WidgetType.EventList, + WidgetType.ViewerCount, + ]; + + function customOrder(orderArray: T[], getter: (a: U) => T) { + return (s1: U, s2: U): number => + orderArray.indexOf(getter(s1)) - orderArray.indexOf(getter(s2)); + } const essentialSources = useMemo(() => { const essentialDefaults = availableSources @@ -114,10 +134,7 @@ export default function SourceGrid(p: { activeTab: string }) { //byOS({ [OS.Windows]: 'screen_capture', [OS.Mac]: 'window_capture' }), ].includes(source.value), ) - .sort( - (s1, s2) => - essentialSourcesOrder.indexOf(s1.value) - essentialSourcesOrder.indexOf(s2.value), - ); + .sort(customOrder(essentialSourcesOrder, s => s.value)); const essentialWidgets = iterableWidgetTypes.filter(type => [WidgetType.AlertBox, WidgetType.ChatBox].includes(WidgetType[type]), @@ -152,6 +169,12 @@ export default function SourceGrid(p: { activeTab: string }) { ); + // TODO: restrict type + // Hide widget descriptions on non-general tab + const toWidgetEl = (widget: string) => ( + + ); + const essentialSourcesList = useMemo( () => ( <> @@ -178,6 +201,7 @@ export default function SourceGrid(p: { activeTab: string }) { ); const sourceDisplayData = useMemo(() => SourceDisplayData(), []); + const widgetDisplayData = useMemo(() => WidgetDisplayData(), []); const byGroup = (group: 'capture' | 'av' | 'media') => (source: IObsListOption) => { const displayData = sourceDisplayData[source.value]; @@ -188,6 +212,15 @@ export default function SourceGrid(p: { activeTab: string }) { return displayData.group === group; }; + const byWidgetGroup = (group: string) => (widget: string) => { + const displayData = widgetDisplayData[WidgetType[widget]]; + if (!displayData) { + return true; + } + + return displayData.group === group; + }; + const captureSourcesList = useMemo( () => availableSources.filter(byGroup('capture')).map(toSourceEl), [availableSources, excludeWrap], @@ -234,7 +267,12 @@ export default function SourceGrid(p: { activeTab: string }) { ) : ( <> {iterableWidgetTypes.filter(filterEssential).map(widgetType => ( - + ))} {p.activeTab !== 'all' && ( { + // TODO: restrict types + const widgetsInGroup = (group: string, sorter?: (s1: string, s2: string) => number) => { + const widgets = iterableWidgetTypes + .filter(byWidgetGroup(group)) + // Sort lexographically by default, if sorter is not provided + .sort(sorter); + + return widgets.map(toWidgetEl); + }; + + // Using essentials as a group for widgets since we wanna display more + const essentialWidgets = ( + <> + {widgetsInGroup( + 'essential', + customOrder(essentialWidgetsOrder, x => WidgetType[x]), + )} + + + ); + + const interactiveWidgets = widgetsInGroup('interactive'); + const goalWidgets = widgetsInGroup('goals'); + const flairWidgets = <>{widgetsInGroup('flair')}; + const charityWidgets = widgetsInGroup('charity'); + + return ( + <> + {!isLoggedIn ? ( + + + + ) : ( + setWidgetExpandedSections(xs as string[])} + > + +
+ {essentialWidgets} +
+
+ +
+ {interactiveWidgets} +
+
+ +
+ {goalWidgets} +
+
+ +
+ {flairWidgets} +
+
+ {/* TODO: we don't have any charity widgets on Desktop + +
+ {charityWidgets} +
+
+ */} +
+ )} + + ); + }, [isLoggedIn, iterableWidgetTypes, excludeWrap]); + const appsList = useMemo( () => ( <> @@ -308,10 +437,7 @@ export default function SourceGrid(p: { activeTab: string }) { } else if (showContent('widgets')) { return ( <> - - - - {widgetList} + {widgetGroupedList} ); } else if (showContent('apps')) { diff --git a/app/components-react/windows/source-showcase/SourceTag.tsx b/app/components-react/windows/source-showcase/SourceTag.tsx index f0d77df51178..2c99cf2dd863 100644 --- a/app/components-react/windows/source-showcase/SourceTag.tsx +++ b/app/components-react/windows/source-showcase/SourceTag.tsx @@ -15,6 +15,7 @@ export default function SourceTag(p: { appSourceId?: string; essential?: boolean; excludeWrap?: boolean; + hideShortDescription?: boolean; }) { const { inspectSource, selectInspectedSource, store } = useSourceShowcaseSettings(); @@ -54,7 +55,7 @@ export default function SourceTag(p: {
{displayData?.name || p.name}
- {displayData?.shortDesc && ( + {displayData?.shortDesc && !p.hideShortDescription && (