Skip to content

Commit

Permalink
Improve type safety (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
gjmooney authored Jun 19, 2024
1 parent caded6e commit 8cb78aa
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 47 deletions.
21 changes: 13 additions & 8 deletions src/arCube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ISignal, Signal } from '@lumino/signaling';
import * as THREE from 'three';
import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry';
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { APP_DATA } from './constants';
import { hmsActions, hmsStore } from './hms';
import { IModelRegistryData } from './registry';

Expand Down Expand Up @@ -111,10 +112,12 @@ class ArCube {
this.scenesWithModel = {};
hmsStore.subscribe(
this.setupSource.bind(this),
selectAppData('videoDeviceId')
selectAppData(APP_DATA.videoDeviceId)
);

this.themeChangedSignal = hmsStore.getState(selectAppData('themeChanged'));
this.themeChangedSignal = hmsStore.getState(
selectAppData(APP_DATA.themeChanged)
);
this.themeChangedSignal.connect(this.handleThemeChange.bind(this));

this.setupThreeStuff();
Expand Down Expand Up @@ -197,12 +200,12 @@ class ArCube {
this.deltaTime = 0;
this.totalTime = 0;

hmsActions.setAppData('renderer', this.renderer);
hmsActions.setAppData(APP_DATA.renderer, this.renderer);
}

setupSource() {
console.log('setting up source');
const deviceId = hmsStore.getState(selectAppData('videoDeviceId'));
const deviceId = hmsStore.getState(selectAppData(APP_DATA.videoDeviceId));

this.arToolkitSource = new THREEx.ArToolkitSource({
sourceType: 'webcam',
Expand Down Expand Up @@ -388,7 +391,7 @@ class ArCube {

// load model
this.okToLoadModel = false;
hmsActions.setAppData('canLoadModel', false);
hmsActions.setAppData(APP_DATA.canLoadModel, false);

if ('url' in model) {
this.gltfLoader.load(
Expand Down Expand Up @@ -483,8 +486,8 @@ class ArCube {
this.modelInScene[sceneNumber] = modelName;

// update app data state
hmsActions.setAppData('loadedModels', updatedScenesWithModel);
hmsActions.setAppData('canLoadModel', true);
hmsActions.setAppData(APP_DATA.loadedModels, updatedScenesWithModel);
hmsActions.setAppData(APP_DATA.canLoadModel, true);

// Send scale value to right sidebar
this.scaleSignal.emit({ sceneNumber, scale: minRatio });
Expand Down Expand Up @@ -519,7 +522,9 @@ class ArCube {
}

findModelByName(name: string) {
const modelRegistry = hmsStore.getState(selectAppData('modelRegistry'));
const modelRegistry = hmsStore.getState(
selectAppData(APP_DATA.modelRegistry)
);
return modelRegistry.find(
(model: IModelRegistryData) => model.name === name
);
Expand Down
3 changes: 2 additions & 1 deletion src/arCubePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@100mslive/hms-video-store';
import * as THREE from 'three';
import ArCube from './arCube';
import { APP_DATA } from './constants';
import { hmsActions } from './hms';

class ArCubePlugin implements HMSVideoPlugin {
Expand Down Expand Up @@ -146,7 +147,7 @@ class ArCubePlugin implements HMSVideoPlugin {

async init() {
this.arCube = new ArCube();
hmsActions.setAppData('arCube', this.arCube);
hmsActions.setAppData(APP_DATA.arCube, this.arCube);

this.arCube.animate();
}
Expand Down
11 changes: 7 additions & 4 deletions src/components/ControlBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { faPersonThroughWindow } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect } from 'react';
import { SESSION_STORE } from '../constants';
import AudioToggleButton from './buttons/AudioToggleButton';
import PluginButton from './buttons/PluginButton';
import RaiseHandButton from './buttons/RaiseHandButton';
Expand All @@ -22,17 +23,19 @@ const ControlBar = () => {
const isHandRaised = useHMSStore(selectHasPeerHandRaised(localPeer!.id));
const { toggleAudio } = useAVToggle();

const presenterId = useHMSStore<HMSPeer>(selectSessionStore('presenterId'));
const presenterId = useHMSStore<HMSPeer>(
selectSessionStore(SESSION_STORE.presenterId)
);

useEffect(() => {
hmsActions.sessionStore.observe('presenterId');
hmsActions.sessionStore.observe(SESSION_STORE.presenterId);
}, [hmsActions]);

const handleLeave = async () => {
// Stop presentation if presenter leaves
if (localPeer?.id === presenterId?.id) {
await hmsActions.sessionStore.set('isPresenting', false);
await hmsActions.sessionStore.set('presenterId', '');
await hmsActions.sessionStore.set(SESSION_STORE.isPresenting, false);
await hmsActions.sessionStore.set(SESSION_STORE.presenterId, '');
}

hmsActions.leave();
Expand Down
13 changes: 8 additions & 5 deletions src/components/MainDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { IStateDB } from '@jupyterlab/statedb';
import React, { useEffect } from 'react';

import { APP_DATA, SESSION_STORE } from '../constants';
import GridView from '../layouts/GridView';
import JoinFormView from '../layouts/JoinFormView';
import PresenterView from '../layouts/PresenterView';
Expand All @@ -21,19 +22,21 @@ interface IMainDisplayProps {
export const MainDisplay = ({ state }: IMainDisplayProps) => {
const hmsActions = useHMSActions();
const isConnected = useHMSStore(selectIsConnectedToRoom);
const isConnecting = useHMSStore(selectAppData('isConnecting'));
const isPresenting = useHMSStore(selectSessionStore('isPresenting'));
const isConnecting = useHMSStore(selectAppData(APP_DATA.isConnecting));
const isPresenting = useHMSStore(
selectSessionStore(SESSION_STORE.isPresenting)
);

useEffect(() => {
if (isConnected) {
hmsActions.setAppData('isConnecting', false);
hmsActions.setAppData(APP_DATA.isConnecting, false);
}
}, [isConnected]);

useEffect(() => {
if (isConnected) {
hmsActions.sessionStore.observe('isPresenting');
hmsActions.sessionStore.observe('presenterId');
hmsActions.sessionStore.observe(SESSION_STORE.isPresenting);
hmsActions.sessionStore.observe(SESSION_STORE.presenterId);
}

window.onunload = () => {
Expand Down
21 changes: 13 additions & 8 deletions src/components/buttons/PluginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ import { faBan, faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useState } from 'react';
import ArCubePlugin from '../../arCubePlugin';
import { SESSION_STORE } from '../../constants';

const PluginButton = () => {
const hmsActions = useHMSActions();
const localPeer = useHMSStore(selectLocalPeer);
const isPresenting = useHMSStore<boolean>(selectSessionStore('isPresenting'));
const presenterId = useHMSStore<HMSPeer>(selectSessionStore('presenterId'));
const isPresenting = useHMSStore<boolean>(
selectSessionStore(SESSION_STORE.isPresenting)
);
const presenterId = useHMSStore<HMSPeer>(
selectSessionStore(SESSION_STORE.presenterId)
);
const role = useHMSStore(selectLocalPeerRole);

const arPlugin = new ArCubePlugin();
Expand All @@ -29,8 +34,8 @@ const PluginButton = () => {
const [prevRole, setPrevRole] = useState<HMSRole>();

useEffect(() => {
hmsActions.sessionStore.observe('isPresenting');
hmsActions.sessionStore.observe('presenterId');
hmsActions.sessionStore.observe(SESSION_STORE.isPresenting);
hmsActions.sessionStore.observe(SESSION_STORE.presenterId);

if (role) {
setPrevRole(role);
Expand All @@ -48,15 +53,15 @@ const PluginButton = () => {
if (!isPluginLoaded && !isPresenting) {
console.log('adding');
togglePresenterRole('presenter');
hmsActions.sessionStore.set('isPresenting', true);
hmsActions.sessionStore.set('presenterId', localPeer);
hmsActions.sessionStore.set(SESSION_STORE.isPresenting, true);
hmsActions.sessionStore.set(SESSION_STORE.presenterId, localPeer);

await hmsActions.addPluginToVideoTrack(arPlugin);
} else {
console.log('removing');
togglePresenterRole(prevRole?.name);
hmsActions.sessionStore.set('isPresenting', false);
hmsActions.sessionStore.set('presenterId', '');
hmsActions.sessionStore.set(SESSION_STORE.isPresenting, false);
hmsActions.sessionStore.set(SESSION_STORE.presenterId, '');

await hmsActions.removePluginFromVideoTrack(arPlugin);
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/modals/DeviceSettingModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DeviceType, useDevices } from '@100mslive/react-sdk';
import React, { ChangeEvent, useEffect, useRef } from 'react';

import { APP_DATA } from '../../constants';
import { hmsActions } from '../../hms';
import Modal from './Modal';

Expand All @@ -26,7 +27,7 @@ const DeviceSettingModal = ({ isOpen, onClose }: IAddNewModelModalProps) => {
const updateDeviceOnChange = (deviceId: string, deviceType: DeviceType) => {
updateDevice({ deviceId, deviceType });
if (deviceType === DeviceType.videoInput) {
hmsActions.setAppData('videoDeviceId', deviceId);
hmsActions.setAppData(APP_DATA.videoDeviceId, deviceId);
}
};

Expand Down
18 changes: 18 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,21 @@ export const ROLES = {
host: 'host',
presenter: 'presenter'
};

export const APP_DATA = {
arCube: 'arCube',
canLoadModel: 'canLoadModel',
config: 'config',
isConnecting: 'isConnecting',
loadedModels: 'loadedModels',
modelRegistry: 'modelRegistry',
selectedModel: 'selectedModel',
renderer: 'renderer',
themeChanged: 'themeChanged',
videoDeviceId: 'videoDeviceId'
};

export const SESSION_STORE = {
isPresenting: 'isPresenting',
presenterId: 'presenterId'
};
5 changes: 3 additions & 2 deletions src/layouts/JoinFormView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
colors,
uniqueNamesGenerator
} from 'unique-names-generator';
import { APP_DATA } from '../constants';

interface IJoinFormViewProps {
state: IStateDB;
Expand Down Expand Up @@ -58,7 +59,7 @@ const JoinFormView = ({ state }: IJoinFormViewProps) => {
e.preventDefault();

console.log('clicking join');
hmsActions.setAppData('isConnecting', true);
hmsActions.setAppData(APP_DATA.isConnecting, true);

const { userName = '', roomCode = '' } = inputValues;

Expand All @@ -77,7 +78,7 @@ const JoinFormView = ({ state }: IJoinFormViewProps) => {
},
metaData: ''
};
hmsActions.setAppData('config', config);
hmsActions.setAppData(APP_DATA.config, config);

try {
await hmsActions.preview({ ...config });
Expand Down
3 changes: 2 additions & 1 deletion src/layouts/PresenterView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, { useEffect } from 'react';
import Peer from '../components/Peer';
import PeerSidePane from '../components/PeerSidePane';
import {
SESSION_STORE,
SIDEPANE_PEER_LIST_MARGIN,
SIDEPANE_PEER_LIST_PADDING,
SIDEPANE_PEER_LIST_TILE,
Expand All @@ -17,7 +18,7 @@ import { useResizeObserver } from '../hooks/useResizeObserver';

const PresenterView = () => {
const peers = useHMSStore(selectPeers);
const presenter = useHMSStore(selectSessionStore('presenterId'));
const presenter = useHMSStore(selectSessionStore(SESSION_STORE.presenterId));
const rootDimensions = useResizeObserver();

const sidepaneWidth =
Expand Down
6 changes: 4 additions & 2 deletions src/layouts/PreviewView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import AudioToggleButton from '../components/buttons/AudioToggleButton';
import SettingsButton from '../components/buttons/SettingsButton';
import VideoToggleButton from '../components/buttons/VideoToggleButton';
import {
APP_DATA,
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
TILE_VIEW_GRID_VERTICAL_MARGIN
} from '../constants';
Expand All @@ -23,7 +24,7 @@ const PreviewView = () => {
const [isJoining, setIsJoining] = useState(false);

const localPeer = useHMSStore(selectLocalPeer);
const config = useHMSStore(selectAppData('config'));
const config = useHMSStore(selectAppData(APP_DATA.config));
const rootDimensions = useResizeObserver();

const handleClick = () => {
Expand All @@ -33,7 +34,8 @@ const PreviewView = () => {
};

const handleBack = () => {
hmsActions.setAppData('isConnecting', false);
hmsActions.setAppData(APP_DATA.isConnecting, false);
hmsActions.leave();
};

return (
Expand Down
30 changes: 19 additions & 11 deletions src/widgets/LeftSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { arIcon } from '../components/Icons';
import ModelListItem from '../components/ModelListItem';
import AddNewFileModal from '../components/modals/AddNewFileModal';
import AddNewUrlModal from '../components/modals/AddNewUrlModal';
import { APP_DATA } from '../constants';
import { hmsActions, hmsStore } from '../hms';
import { IModelRegistry, IModelRegistryData } from '../registry';
// https://github.khronos.org/glTF-Sample-Viewer-Release/assets/models/Models/Suzanne/glTF/Suzanne.gltf'
Expand All @@ -31,29 +32,34 @@ const LeftSidebarComponent = ({ modelList, modelRegistry }: IModelInfoList) => {
const [isAddModelFileOpen, setAddModelFileOpen] = useState(false);

useEffect(() => {
setArCube(hmsStore.getState(selectAppData('arCube')));
setArCube(hmsStore.getState(selectAppData(APP_DATA.arCube)));

hmsStore.subscribe(updateModelLoadingState, selectAppData('canLoadModel'));
hmsStore.subscribe(updateArCube, selectAppData('arCube'));
hmsStore.subscribe(
updateModelLoadingState,
selectAppData(APP_DATA.canLoadModel)
);
hmsStore.subscribe(updateArCube, selectAppData(APP_DATA.arCube));
}, []);

const updateArCube = () => {
setArCube(hmsStore.getState(selectAppData('arCube')));
setArCube(hmsStore.getState(selectAppData(APP_DATA.arCube)));
};

const updateModelLoadingState = () => {
const canLoadModel = hmsStore.getState(selectAppData('canLoadModel'));
const canLoadModel = hmsStore.getState(
selectAppData(APP_DATA.canLoadModel)
);
setIsDisabled(!canLoadModel);
};

const handleModelNameClick = (model: IModelRegistryData) => {
setSelected(model);
hmsActions.setAppData('selectedModel', model);
hmsActions.setAppData(APP_DATA.selectedModel, model);
};

const handleModelSelectClick = (sceneNumber: number) => {
if (!arCube) {
setArCube(hmsStore.getState(selectAppData('arCube')));
setArCube(hmsStore.getState(selectAppData(APP_DATA.arCube)));
}

if (!selected) {
Expand Down Expand Up @@ -206,7 +212,7 @@ export class LeftSidebarWidget extends SidePanel {

addModelToRegistryArray(model: IModelRegistryData) {
const registryFromStore: IModelRegistryData[] = [
...hmsStore.getState(selectAppData('modelRegistry'))
...hmsStore.getState(selectAppData(APP_DATA.modelRegistry))
];

const existingModels = registryFromStore.map(
Expand All @@ -225,14 +231,16 @@ export class LeftSidebarWidget extends SidePanel {
});
}

hmsActions.setAppData('modelRegistry', registryFromStore);
hmsActions.setAppData(APP_DATA.modelRegistry, registryFromStore);

return registryFromStore;
}

updateModel(modelName: string) {
const loadedModels = hmsStore.getState(selectAppData('loadedModels'));
const arCube: ArCube = hmsStore.getState(selectAppData('arCube'));
const loadedModels = hmsStore.getState(
selectAppData(APP_DATA.loadedModels)
);
const arCube: ArCube = hmsStore.getState(selectAppData(APP_DATA.arCube));

if (!arCube) {
return;
Expand Down
Loading

0 comments on commit 8cb78aa

Please sign in to comment.