Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Main Window to React #4853

Draft
wants to merge 45 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fcc690c
Port LiveDock Component
gettinToasty Dec 18, 2023
677b054
Fix import errors and tabs
gettinToasty Dec 18, 2023
d7ac74b
Add to ReactComponentList
gettinToasty Dec 18, 2023
e21b426
Fix strict nulls
gettinToasty Dec 18, 2023
967c98b
Fix import error
gettinToasty Dec 19, 2023
4be201a
Fix reactivity issues
gettinToasty Dec 19, 2023
24067d1
Fix positioning and styling
gettinToasty Dec 19, 2023
ce276db
Begin 1 to 1 port
gettinToasty Dec 19, 2023
4e7aaa1
Define variables and functions
gettinToasty Jan 8, 2024
5886f13
Add missing classNames
gettinToasty Jan 8, 2024
19a03fb
Fix non-modal redlines
gettinToasty Jan 8, 2024
019812a
Add modals to react
gettinToasty Jan 9, 2024
16f70db
Import components
gettinToasty Jan 9, 2024
8880d0a
Fix rendering bugs
gettinToasty Jan 9, 2024
36dc9db
Add misssing classes
gettinToasty Jan 10, 2024
79a5563
Change scope of windowWidth
gettinToasty Jan 10, 2024
c32edc2
Remove props from main window
gettinToasty Jan 19, 2024
a850c3c
Move to native react rendering
gettinToasty Jan 23, 2024
a5e7821
Revert to Vue wrapper component
gettinToasty Jan 24, 2024
8cd5bba
Merge branch 'master' into sb_port_livedock
gettinToasty Jan 30, 2024
edbf015
Merge branch 'sb_port_livedock' into sb_port_main_window
gettinToasty Jan 30, 2024
130b661
Fix stale style blockers
gettinToasty Feb 5, 2024
e6a836c
Merge branch 'master' into sb_port_main_window
gettinToasty Feb 9, 2024
fea5cc4
Add css aliases
gettinToasty Feb 9, 2024
c57626c
Merge branch 'master' into sb_port_main_window
gettinToasty Feb 15, 2024
64dc313
Begin livedock restructure
gettinToasty Feb 22, 2024
861f572
Fix rendering livedock
gettinToasty Feb 22, 2024
5be1d3d
Merge branch 'master' into sb_port_main_window
gettinToasty Mar 20, 2024
2be9d84
Merge branch 'master' into sb_port_main_window
gettinToasty Apr 5, 2024
95b343e
Use Realm
gettinToasty Apr 9, 2024
e601b61
Merge branch 'master' into sb_port_main_window
Jun 5, 2024
82cca15
Fix compilation error
Jun 5, 2024
20c9e84
Fix Livedock breaking render
Jun 5, 2024
1a95e10
Use realm props binding
Jun 5, 2024
9603e10
fix: pass theme to `Loader`
blackxored Jul 22, 2024
8fb450a
chore: uncoment main rendering
blackxored Jul 22, 2024
cd4baa7
fix(main): restore wrappers, should fix resizing behavior
blackxored Jul 24, 2024
3c95157
Merge branch 'master' into sb_port_main_window
gettinToasty Sep 11, 2024
050f4ae
Re-add ChatTabs
gettinToasty Sep 11, 2024
4edb751
Merge branch 'sb_port_main_window' of https://github.com/stream-labs/…
gettinToasty Sep 11, 2024
5999165
Merge branch 'master' into sb_port_main_window
gettinToasty Sep 25, 2024
ca1fe13
Fix index typing for customization service
gettinToasty Sep 25, 2024
e2c562d
Fix typing in Studio.tsx
gettinToasty Sep 25, 2024
60c5637
Merge branch 'master' into sb_port_main_window
gettinToasty Jan 14, 2025
42bee56
Fix resizing problem
gettinToasty Jan 16, 2025
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
35 changes: 24 additions & 11 deletions app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,20 @@ import { getResource } from 'services';
import * as obs from '../obs-api';
import path from 'path';
import util from 'util';
import uuid from 'uuid/v4';
import Main from 'components/windows/Main.vue';
import { Loader, Blank } from 'components/shared/ReactComponentList';
import Main from 'components/windows/Main';
import process from 'process';
import { MetricsService } from 'services/metrics';
import { UsageStatisticsService } from 'services/usage-statistics';
import * as remote from '@electron/remote';
import { RealmService } from 'app-services';

// // TODO: commented until we remove slap library
// // For React Windows
// import React from 'react';
// import ReactDOM from 'react-dom';
// import Main from 'components-react/windows/Main';

const { ipcRenderer } = electron;
const slobsVersion = Utils.env.SLOBS_VERSION;
const isProduction = Utils.env.NODE_ENV === 'production';
Expand Down Expand Up @@ -335,8 +340,11 @@ document.addEventListener('DOMContentLoaded', async () => {
});
}

// create a root Vue component
const windowId = Utils.getCurrentUrlParams().windowId;

// // TODO: commented until we remove slap library
// if (windowId !== 'main') {
// create a root Vue component
const vm = new Vue({
i18n,
store,
Expand All @@ -360,18 +368,30 @@ document.addEventListener('DOMContentLoaded', async () => {
render(h) {
if (this.isRefreshing) return h(Blank);
if (windowId === 'worker') return h(Blank);
if (windowId === 'main') return h(Main);
if (windowId === 'child') {
if (store.state.bulkLoadFinished && store.state.i18nReady) {
return h(ChildWindow);
}

return h(Loader);
}
if (windowId === 'main') return h(Main);
return h(OneOffWindow);
},
});

// allow to refresh the window by pressing `F5` in the DevMode
if (Utils.isDevMode()) {
window.addEventListener('keyup', ev => {
if (ev.key === 'F5') vm.startWindowRefresh();
});
}
// // TODO: commented until we remove slap library
// } else {
// // create a roote React component
// ReactDOM.render(React.createElement(Main), document.getElementById('app'));
// }

let mainWindowShowTime = 0;
if (Utils.isMainWindow()) {
remote.getCurrentWindow().show();
Expand All @@ -398,13 +418,6 @@ document.addEventListener('DOMContentLoaded', async () => {
if (ctx) setSentryContext(ctx);
userService.sentryContext.subscribe(setSentryContext);
}

// allow to refresh the window by pressing `F5` in the DevMode
if (Utils.isDevMode()) {
window.addEventListener('keyup', ev => {
if (ev.key === 'F5') vm.startWindowRefresh();
});
}
});
});

Expand Down
5 changes: 2 additions & 3 deletions app/components-react/editor/elements/LegacyEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import styles from './RecentEvents.m.less';

const mins = { x: 360, y: 150 };

export function LegacyEvents(p: { onPopout: () => void }) {
export function LegacyEvents() {
const { UserService, RecentEventsService, MagicLinkService } = Services;

const containerRef = useRef<HTMLDivElement>(null);
const magicLinkDisabled = useRef(false);

function popoutRecentEvents() {
p.onPopout();
return RecentEventsService.openRecentEventsWindow();
return RecentEventsService.actions.openRecentEventsWindow();
}

function handleBrowserViewReady(view: Electron.BrowserView) {
Expand Down
6 changes: 3 additions & 3 deletions app/components-react/editor/elements/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export { MiniFeed } from './Minifeed';
export { MiniFeed as Minifeed } from './Minifeed';
export { LegacyEvents } from './LegacyEvents';
export { SceneSelectorElement } from './SceneSelector';
export { SourceSelectorElement } from './SourceSelector';
export { SceneSelectorElement as Scenes } from './SceneSelector';
export { SourceSelectorElement as Sources } from './SourceSelector';
export { Mixer } from './Mixer';
export { RecordingPreview } from './RecordingPreview';
export { StreamPreview } from './StreamPreview';
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/Classic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function Classic(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={styles.rows} ref={componentRef}>
<div className={cx(styles.rows, p.className)} ref={componentRef}>
<div className={styles.cell} style={{ height: `${100 - resizes.bar1 * 100}%` }}>
{p.children?.['1'] || <></>}
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/Default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function Default(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={styles.rows} ref={componentRef}>
<div className={cx(styles.rows, p.className)} ref={componentRef}>
<div
className={styles.cell}
style={{ height: `${100 - (resizes.bar1 + resizes.bar2!) * 100}%` }}
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/FourByFour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function FourByFour(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={styles.rows} ref={componentRef}>
<div className={cx(styles.rows, p.className)} ref={componentRef}>
<div
className={styles.cell}
style={{ height: `${100 - (resizes.bar1 + resizes.bar2) * 100}%` }}
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/OnePane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function OnePane(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={cx(styles.columns, styles.sidePadded)} ref={componentRef}>
<div className={cx(styles.columns, styles.sidePadded, p.className)} ref={componentRef}>
<ResizeBar
position="left"
value={bars.bar1}
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/OnePaneR.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function OnePaneR(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={cx(styles.columns, styles.sidePadded)} ref={componentRef}>
<div className={cx(styles.columns, styles.sidePadded, p.className)} ref={componentRef}>
<div
className={styles.rows}
style={{ width: `${100 - resizes.bar1 * 100}%`, paddingTop: '16px' }}
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/Pyramid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function Pyramid(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={styles.rows} ref={componentRef}>
<div className={cx(styles.rows, p.className)} ref={componentRef}>
<div className={styles.cell} style={{ height: `${100 - resizes.bar1 * 100}%` }}>
{p.children?.['1'] || <></>}
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/Triplets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function Triplets(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={cx(styles.columns, styles.sidePadded)} ref={componentRef}>
<div className={cx(styles.columns, styles.sidePadded, p.className)} ref={componentRef}>
<ResizeBar
position="left"
value={bars.bar1}
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/editor/layouts/TwoPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function TwoPane(p: React.PropsWithChildren<LayoutProps>) {
);

return (
<div className={cx(styles.columns, styles.sidePadded)} ref={componentRef}>
<div className={cx(styles.columns, styles.sidePadded, p.className)} ref={componentRef}>
<ResizeBar
position="left"
value={bars.bar1}
Expand Down
1 change: 1 addition & 0 deletions app/components-react/editor/layouts/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Services } from 'components-react/service-provider';
export class LayoutProps {
onTotalWidth: (slots: IVec2Array, isColumns: boolean) => void = () => {};
childrenMins: Dictionary<IVec2>;
className?: string;
}

export interface IResizeMins {
Expand Down
48 changes: 7 additions & 41 deletions app/components-react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,16 @@ import ScreenCaptureProperties from './windows/ScreenCaptureProperties';
import GuestCamProperties from './windows/GuestCamProperties';
import News from './windows/notifications/News';
import PerformanceMetrics from './shared/PerformanceMetrics';
import PatchNotes from './pages/PatchNotes';
import Display from './shared/Display';
import TitleBar from './shared/TitleBar';
import Chat from './root/Chat';
import Highlighter from './pages/Highlighter';
import Grow from './pages/grow/Grow';
import Loader from './pages/Loader';
import PlatformLogo from './shared/PlatformLogo';
import Onboarding from './pages/onboarding/Onboarding';
import AdvancedStatistics from './windows/AdvancedStatistics';
import StudioFooter from './root/StudioFooter';
import StreamScheduler from './pages/stream-scheduler/StreamScheduler';
import { createRoot } from './root/ReactRoot';
import StartStreamingButton from './root/StartStreamingButton';
import SourceProperties from './windows/SourceProperties';
import TestWidgets from './root/TestWidgets';
import RenameSource from './windows/RenameSource';
import NotificationsArea from './root/NotificationsArea';
import StudioEditor from './root/StudioEditor';
import SharedComponentsLibrary from './windows/sharedComponentsLibrary/SharedComponentsLibrary';
import { ObsSettings } from './windows/settings/ObsSettings';
import ManageSceneCollections from './windows/ManageSceneCollections';
import ThemeAudit from './pages/ThemeAudit';
import { WidgetWindow } from './widgets/common/WidgetWindow';
import SafeMode from './windows/SafeMode';
import AdvancedAudio from './windows/advanced-audio';
Expand All @@ -39,7 +26,6 @@ import SourceFilters from './windows/SourceFilters';
import RecentEvents from './editor/elements/RecentEvents';
import BrowserView from './shared/BrowserView';
import MediaGallery from './windows/MediaGallery';
import LayoutEditor from './pages/layout-editor/LayoutEditor';
import Projector from './windows/Projector';
import AddSource from './windows/AddSource';
import SideNav from './sidebar/SideNav';
Expand All @@ -48,27 +34,21 @@ import Notifications from './windows/notifications/Notifications';
import NotificationsAndNews from './windows/notifications';
import MultistreamChatInfo from './windows/MultistreamChatInfo';
import Blank from './windows/Blank';
import PlatformMerge from './pages/PlatformMerge';
import AlertboxLibrary from './pages/AlertboxLibrary';
import PlatformAppStore from './pages/PlatformAppStore';
import BrowseOverlays from './pages/BrowseOverlays';
import PlatformAppMainPage from './pages/PlatformAppMainPage';
import PlatformAppPageView from './shared/PlatformAppPageView';
import PlatformAppPopOut from './windows/PlatformAppPopOut';
import RecentEventsWindow from './windows/RecentEvents';
import NewBadge from './shared/NewBadge';
import RecordingHistory from './pages/RecordingHistory';
import UltraIcon from './shared/UltraIcon';
import EditTransform from './windows/EditTransform';
import InstalledApps from './windows/settings/InstalledApps';
import Hotkeys from './windows/settings/Hotkeys';
import Studio from './pages/Studio';
import LiveDock from './root/LiveDock';
import Main from './windows/Main';
import Loader from './pages/Loader';
import StartStreamingButton from './root/StartStreamingButton';
import { PlatformMerge, PlatformAppStore, PlatformAppMainPage } from './pages';

// list of React components to be used inside Vue components
export const components = {
AlertboxLibrary,
BrowseOverlays,
NameFolder,
NameScene,
BrowserView,
Expand All @@ -80,28 +60,15 @@ export const components = {
News,
PerformanceMetrics,
ManageSceneCollections,
PatchNotes,
Display,
TitleBar,
Chat,
Highlighter: createRoot(Highlighter),
Grow,
Loader,
PlatformLogo,
Onboarding: createRoot(Onboarding),
Projector,
StreamScheduler: createRoot(StreamScheduler),
AdvancedStatistics,
SourceProperties: createRoot(SourceProperties),
SharedComponentsLibrary: createRoot(SharedComponentsLibrary),
TestWidgets,
RenameSource,
StudioFooter: createRoot(StudioFooter),
StartStreamingButton,
NotificationsArea,
ObsSettings: createRoot(ObsSettings),
ThemeAudit,
StudioEditor,
WidgetWindow: createRoot(WidgetWindow),
CustomCodeWindow: createRoot(CustomCodeWindow),
SafeMode,
Expand All @@ -110,9 +77,7 @@ export const components = {
SourceFilters,
RecentEvents,
MediaGallery,
LayoutEditor: createRoot(LayoutEditor),
AddSource,
RecordingHistory: createRoot(RecordingHistory),
RecentEventsWindow,
SideNav,
WelcomeToPrime,
Expand All @@ -130,6 +95,7 @@ export const components = {
InstalledApps,
Blank,
Hotkeys,
LiveDock: createRoot(LiveDock),
Studio: createRoot(Studio),
Main: createRoot(Main),
Loader,
StartStreamingButton,
};
3 changes: 2 additions & 1 deletion app/components-react/pages/AlertboxLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { GuestApiHandler } from 'util/guest-api-handler';
import { IDownloadProgress } from 'util/requests';
import { Services } from 'components-react/service-provider';

export default function AlertboxLibrary(p: { params: { id?: string } }) {
export default function AlertboxLibrary(p: { params: { id?: string }; className?: string }) {
const {
NotificationsService,
JsonrpcService,
Expand Down Expand Up @@ -85,6 +85,7 @@ export default function AlertboxLibrary(p: { params: { id?: string } }) {
if (!libraryUrl) return <></>;
return (
<BrowserView
className={p.className}
style={{ position: 'absolute', top: '0', left: '0', right: '0', bottom: '0' }}
src={libraryUrl}
enableGuestApi
Expand Down
2 changes: 2 additions & 0 deletions app/components-react/pages/BrowseOverlays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Services } from 'components-react/service-provider';

export default function BrowseOverlays(p: {
params: { type?: 'overlay' | 'widget-themes' | 'site-themes'; id?: string; install?: string };
className?: string;
}) {
const {
UserService,
Expand Down Expand Up @@ -282,6 +283,7 @@ export default function BrowseOverlays(p: {
if (!overlaysUrl) return <></>;
return (
<BrowserView
className={p.className}
onReady={onBrowserViewReady}
src={overlaysUrl}
style={{ position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 }}
Expand Down
5 changes: 3 additions & 2 deletions app/components-react/pages/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
import cx from 'classnames';
import SvgContainer from 'components-react/shared/SvgContainer';
import { $t } from 'services/i18n';

Expand Down Expand Up @@ -35,7 +36,7 @@ const loadingStrings = () => [
'You can customize the design of your tip page from the Theme Library.',
];

export default function Loader() {
export default function Loader(p: { className?: string }) {
const [loaderText, setLoaderText] = useState('');
useEffect(lifecycle, []);

Expand All @@ -57,7 +58,7 @@ export default function Loader() {
}

return (
<div className="s-loader">
<div className={cx('s-loader', p.className)}>
<div className="s-loader__bg">
<div className="s-loader__inner">
<Spinner />
Expand Down
9 changes: 5 additions & 4 deletions app/components-react/pages/PatchNotes.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { $t } from '../../services/i18n';
import React from 'react';
import { Services } from '../service-provider';
import cx from 'classnames';
import { $t } from '../../services/i18n';
import { Services } from '../service-provider';

import styles from './PatchNotes.m.less';

export default function PatchNotes() {
export default function PatchNotes(p: { className?: string }) {
const { PatchNotesService, NavigationService } = Services;

const notes = PatchNotesService.notes;
Expand All @@ -14,7 +15,7 @@ export default function PatchNotes() {
}

return (
<div className={styles.patchNotesPage}>
<div className={cx(styles.patchNotesPage, p.className)}>
<div className={styles.patchNotesContainer}>
<div className={styles.patchNotesContent}>
<div className={styles.patchNotesHeader}>
Expand Down
Loading
Loading