Skip to content

Commit

Permalink
Minimize Deviations with Upstream (#71)
Browse files Browse the repository at this point in the history
* Add isMobile isReactNative flag to isMobile

* Remove use of global.RNBridgeless

* Restore workflow files

* Restore unchanged files

* Restore stylelint

* Remove diff from Physics and useRendererEntity

* Revert server changes

* Clean up MediaWindows deviations

* Add license

* Split out native files for major deviations

* Add flags for API.ts
  • Loading branch information
hmallen99 authored Feb 13, 2025
1 parent d5917e9 commit 5f27a02
Show file tree
Hide file tree
Showing 45 changed files with 1,309 additions and 440 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"at-rule-no-unknown": null,
"no-descending-specificity": null,
"indentation": 2,
"no-unexpected-multiline": 0,
"number-leading-zero": null,
"property-no-vendor-prefix": null,
"font-family-no-missing-generic-family-keyword": null,
Expand Down
31 changes: 23 additions & 8 deletions packages/client-core/src/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { API as CommonAPI } from '@ir-engine/common'
import type { ServiceTypes } from '@ir-engine/common/declarations'
import config from '@ir-engine/common/src/config'

import { HyperFlux } from '@ir-engine/hyperflux'
import { isReactNative } from '@ir-engine/spatial/src/common/functions/isMobile'
import primusClient from './util/primus-client'

declare module '@feathersjs/client' {
Expand All @@ -48,19 +50,32 @@ export class API {
static instance: API
client: FeathersApplication<ServiceTypes>

static createAPI = (pathName: string = window?.location?.pathname || 'default') => {
static createAPI = () => {
const feathersClient = feathers()

const primus = new Primus(`${config.client.serverUrl}?pathName=${window.location.pathname}`, {
const query = {
pathName: window.location.pathname,
peerID: HyperFlux.store.peerID
}

const queryString = new URLSearchParams(query).toString()

const uri = isReactNative
? `${config.client.serverUrl}?pathName=${window.location.pathname}`
: `${config.client.serverUrl}?${queryString}`

const primus = new Primus(uri, {
withCredentials: true,
pingTimeout: config.websocket.pingTimeout,
pingInterval: config.websocket.pingInterval,
transport: {
headers: {
Origin: config.client.clientUrl,
Host: process.env.VITE_SERVER_HOST
}
}
transport: isReactNative
? {
headers: {
Origin: config.client.clientUrl,
Host: process.env.VITE_SERVER_HOST
}
}
: undefined
})
feathersClient.configure(primusClient(primus, { timeout: 10000 }))

Expand Down
4 changes: 2 additions & 2 deletions packages/client-core/src/common/services/RouterService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ import { API } from '@ir-engine/common'
import { routePath, RouteType } from '@ir-engine/common/src/schema.type.module'
import { defineState, getMutableState, NO_PROXY, startReactor, useHookstate } from '@ir-engine/hyperflux'
import { loadRoute } from '@ir-engine/projects/loadRoute'
import { isReactNative } from '@ir-engine/spatial/src/common/functions/isMobile'

type SearchParamsType = { [key: string]: string }

export let history: BrowserHistory

// TODO: Better detection for React Native
if (!global.RN$Bridgeless) {
if (!isReactNative) {
history = createBrowserHistory()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,104 +23,8 @@ All portions of the code written by the Infinite Reality Engine team are Copyrig
Infinite Reality Engine. All Rights Reserved.
*/

import { UserID } from '@ir-engine/common/src/schema.type.module'
import { Engine } from '@ir-engine/ecs/src/Engine'
import { NO_PROXY, PeerID, useMutableState } from '@ir-engine/hyperflux'
import { NetworkState } from '@ir-engine/network'

import { EngineState } from '@ir-engine/ecs'
import { NetworkPeerState } from '@ir-engine/network/src/NetworkPeerState'
import { useEffect } from 'react'
import { useMediaNetwork } from '../../common/services/MediaInstanceConnectionService'
import { PeerMediaChannelState, PeerMediaStreamInterface } from '../../media/PeerMediaChannelState'
import { AuthState } from '../../user/services/AuthService'
import { FilteredUsersState } from '../../world/FilteredUsersSystem'
// import { UserMediaWindow, UserMediaWindowWidget } from '../UserMediaWindow'

type WindowType = { peerID: PeerID; type: 'cam' | 'screen' }

const sortScreensBeforeCameras = (a: WindowType, b: WindowType) => {
if (a.type === 'screen' && b.type === 'cam') return -1
if (a.type === 'cam' && b.type === 'screen') return 1
return 0
}

export const useMediaWindows = () => {
const peerMediaChannelState = useMutableState(PeerMediaChannelState)
const mediaNetworkInstanceState = useMediaNetwork()
const mediaNetwork = NetworkState.mediaNetwork
const networkPeerState = useMutableState(NetworkPeerState).value
const mediaNetworkUsers = mediaNetwork ? networkPeerState?.[mediaNetwork.id]?.users : undefined
const selfUser = useMutableState(AuthState).user
const mediaNetworkConnected = mediaNetwork && mediaNetworkInstanceState?.ready?.value

const consumers = Object.entries(peerMediaChannelState.get(NO_PROXY)) as [
PeerID,
{ cam: PeerMediaStreamInterface; screen: PeerMediaStreamInterface }
][]

const selfPeerID = Engine.instance.store.peerID
const selfUserID = useMutableState(EngineState).userID.value

const camActive = (cam: PeerMediaStreamInterface) => cam.videoMediaStream || cam.audioMediaStream

const userPeers: Array<[UserID, PeerID[]]> =
mediaNetworkConnected && mediaNetworkUsers
? (Object.entries(mediaNetworkUsers) as Array<[UserID, PeerID[]]>)
: [[selfUserID, [selfPeerID]]]

// reduce all userPeers to an array 'windows' of { peerID, type } objects, displaying screens first, then cams. if a user has no cameras, only include one peerID for that user
const windows = userPeers
.reduce((acc, [userID, peerIDs]) => {
const isSelfWindows = userID === selfUser.id.value
const userCams = consumers
.filter(([peerID, { cam, screen }]) => peerIDs.includes(peerID) && cam && camActive(cam))
.map(([peerID]) => {
return { peerID, type: 'cam' as const }
})

const userScreens = consumers
.filter(([peerID, { cam, screen }]) => peerIDs.includes(peerID) && screen?.videoMediaStream)
.map(([peerID]) => {
return { peerID, type: 'screen' as const }
})

const userWindows = [...userScreens, ...userCams]
if (userWindows.length) {
if (isSelfWindows) acc.unshift(...userWindows)
else acc.push(...userWindows)
} else {
if (isSelfWindows) acc.unshift({ peerID: peerIDs[0], type: 'cam' })
else acc.push({ peerID: peerIDs[0], type: 'cam' })
}
return acc
}, [] as WindowType[])
.sort(sortScreensBeforeCameras)
.filter(({ peerID }) => peerMediaChannelState[peerID].value)

// if window doesnt exist for self, add it
if (
mediaNetworkConnected &&
mediaNetwork.users &&
!windows.find(({ peerID }) => mediaNetwork.users[selfUserID]?.includes(peerID))
) {
windows.unshift({ peerID: selfPeerID, type: 'cam' })
}

const filteredUsersState = useMutableState(FilteredUsersState)

const nearbyPeers = mediaNetwork
? filteredUsersState.nearbyLayerUsers.value.map((userID) => mediaNetwork.users[userID]).flat()
: []

return windows.filter(
({ peerID }) =>
(peerID === Engine.instance.store.peerID ||
mediaNetwork?.peers[peerID].userId === selfUserID ||
nearbyPeers.includes(peerID)) &&
peerMediaChannelState.value[peerID]
)
}
export * from './useMediaWindows'

export const UserMediaWindows = () => {
useEffect(() => {
Expand Down
100 changes: 6 additions & 94 deletions packages/client-core/src/components/UserMediaWindows/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Version 1.0. (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://github.com/ir-engine/ir-engine/blob/dev/LICENSE.
The License is based on the Mozilla Public License Version 1.1, but Sections 14
and 15 have been added to cover use of software over a computer network and
provide for limited attribution for the Original Developer. In addition,
and 15 have been added to cover use of software over a computer network and
provide for limited attribution for the Original Developer. In addition,
Exhibit A has been modified to be consistent with Exhibit B.
Software distributed under the License is distributed on an "AS IS" basis,
Expand All @@ -19,111 +19,23 @@ The Original Code is Infinite Reality Engine.
The Original Developer is the Initial Developer. The Initial Developer of the
Original Code is the Infinite Reality Engine team.
All portions of the code written by the Infinite Reality Engine team are Copyright © 2021-2023
All portions of the code written by the Infinite Reality Engine team are Copyright © 2021-2023
Infinite Reality Engine. All Rights Reserved.
*/

import React from 'react'

import { UserID } from '@ir-engine/common/src/schema.type.module'
import { Engine } from '@ir-engine/ecs/src/Engine'
import { NO_PROXY, PeerID, useMutableState } from '@ir-engine/hyperflux'
import { PeerID, useMutableState } from '@ir-engine/hyperflux'
import { NetworkState } from '@ir-engine/network'

import { EngineState } from '@ir-engine/ecs'
import { NetworkPeerState } from '@ir-engine/network/src/NetworkPeerState'
import { useMediaNetwork } from '../../common/services/MediaInstanceConnectionService'
import { PeerMediaChannelState, PeerMediaStreamInterface } from '../../media/PeerMediaChannelState'
import { AuthState } from '../../user/services/AuthService'
import { FilteredUsersState } from '../../world/FilteredUsersSystem'
import { useShelfStyles } from '../Shelves/useShelfStyles'
import { UserMediaWindow, UserMediaWindowWidget } from '../UserMediaWindow'
import styles from './index.module.scss'

type WindowType = { peerID: PeerID; type: 'cam' | 'screen' }

const sortScreensBeforeCameras = (a: WindowType, b: WindowType) => {
if (a.type === 'screen' && b.type === 'cam') return -1
if (a.type === 'cam' && b.type === 'screen') return 1
return 0
}

export const useMediaWindows = () => {
const peerMediaChannelState = useMutableState(PeerMediaChannelState)
const mediaNetworkInstanceState = useMediaNetwork()
const mediaNetwork = NetworkState.mediaNetwork
const networkPeerState = useMutableState(NetworkPeerState).value
const mediaNetworkUsers = mediaNetwork ? networkPeerState?.[mediaNetwork.id]?.users : undefined
const selfUser = useMutableState(AuthState).user
const mediaNetworkConnected = mediaNetwork && mediaNetworkInstanceState?.ready?.value

const consumers = Object.entries(peerMediaChannelState.get(NO_PROXY)) as [
PeerID,
{ cam: PeerMediaStreamInterface; screen: PeerMediaStreamInterface }
][]

const selfPeerID = Engine.instance.store.peerID
const selfUserID = useMutableState(EngineState).userID.value

const camActive = (cam: PeerMediaStreamInterface) => cam.videoMediaStream || cam.audioMediaStream

const userPeers: Array<[UserID, PeerID[]]> =
mediaNetworkConnected && mediaNetworkUsers
? (Object.entries(mediaNetworkUsers) as Array<[UserID, PeerID[]]>)
: [[selfUserID, [selfPeerID]]]

// reduce all userPeers to an array 'windows' of { peerID, type } objects, displaying screens first, then cams. if a user has no cameras, only include one peerID for that user
const windows = userPeers
.reduce((acc, [userID, peerIDs]) => {
const isSelfWindows = userID === selfUser.id.value
const userCams = consumers
.filter(([peerID, { cam, screen }]) => peerIDs.includes(peerID) && cam && camActive(cam))
.map(([peerID]) => {
return { peerID, type: 'cam' as const }
})

const userScreens = consumers
.filter(([peerID, { cam, screen }]) => peerIDs.includes(peerID) && screen?.videoMediaStream)
.map(([peerID]) => {
return { peerID, type: 'screen' as const }
})

const userWindows = [...userScreens, ...userCams]
if (userWindows.length) {
if (isSelfWindows) acc.unshift(...userWindows)
else acc.push(...userWindows)
} else {
if (isSelfWindows) acc.unshift({ peerID: peerIDs[0], type: 'cam' })
else acc.push({ peerID: peerIDs[0], type: 'cam' })
}
return acc
}, [] as WindowType[])
.sort(sortScreensBeforeCameras)
.filter(({ peerID }) => peerMediaChannelState[peerID].value)

// if window doesnt exist for self, add it
if (
mediaNetworkConnected &&
mediaNetwork.users &&
!windows.find(({ peerID }) => mediaNetwork.users[selfUserID]?.includes(peerID))
) {
windows.unshift({ peerID: selfPeerID, type: 'cam' })
}

const filteredUsersState = useMutableState(FilteredUsersState)

const nearbyPeers = mediaNetwork
? filteredUsersState.nearbyLayerUsers.value.map((userID) => mediaNetwork.users[userID]).flat()
: []

return windows.filter(
({ peerID }) =>
(peerID === Engine.instance.store.peerID ||
mediaNetwork?.peers[peerID].userId === selfUserID ||
nearbyPeers.includes(peerID)) &&
peerMediaChannelState.value[peerID]
)
}
import { useMediaWindows } from './useMediaWindows'
export * from './useMediaWindows'

export const UserMediaWindows = () => {
const { topShelfStyle } = useShelfStyles()
Expand Down
Loading

0 comments on commit 5f27a02

Please sign in to comment.