@tellescope/video-chat 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/cjs/controls.d.ts +17 -2
  2. package/lib/cjs/controls.d.ts.map +1 -1
  3. package/lib/cjs/controls.js +41 -7
  4. package/lib/cjs/controls.js.map +1 -1
  5. package/lib/cjs/native/bridge.d.ts.map +1 -1
  6. package/lib/cjs/native/bridge.js +1 -0
  7. package/lib/cjs/native/bridge.js.map +1 -1
  8. package/lib/cjs/video.d.ts +3 -1
  9. package/lib/cjs/video.d.ts.map +1 -1
  10. package/lib/cjs/video.js +12 -8
  11. package/lib/cjs/video.js.map +1 -1
  12. package/lib/cjs/video.native.d.ts +3 -2
  13. package/lib/cjs/video.native.d.ts.map +1 -1
  14. package/lib/cjs/video.native.js +24 -16
  15. package/lib/cjs/video.native.js.map +1 -1
  16. package/lib/esm/controls.d.ts +17 -2
  17. package/lib/esm/controls.d.ts.map +1 -1
  18. package/lib/esm/controls.js +41 -10
  19. package/lib/esm/controls.js.map +1 -1
  20. package/lib/esm/native/bridge.d.ts.map +1 -1
  21. package/lib/esm/native/bridge.js +1 -0
  22. package/lib/esm/native/bridge.js.map +1 -1
  23. package/lib/esm/shared.d.ts +1 -0
  24. package/lib/esm/shared.d.ts.map +1 -0
  25. package/lib/esm/shared.js +2 -0
  26. package/lib/esm/shared.js.map +1 -0
  27. package/lib/esm/video.d.ts +3 -1
  28. package/lib/esm/video.d.ts.map +1 -1
  29. package/lib/esm/video.js +12 -8
  30. package/lib/esm/video.js.map +1 -1
  31. package/lib/esm/video.native.d.ts +3 -2
  32. package/lib/esm/video.native.d.ts.map +1 -1
  33. package/lib/esm/video.native.js +23 -15
  34. package/lib/esm/video.native.js.map +1 -1
  35. package/lib/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +9 -9
  37. package/src/controls.tsx +57 -4
  38. package/src/native/bridge.ts +1 -0
  39. package/src/video.native.tsx +12 -4
  40. package/src/video.tsx +8 -4
  41. package/lib/esm/components.d.ts +0 -1
  42. package/lib/esm/components.d.ts.map +0 -1
  43. package/lib/esm/components.js +0 -3
  44. package/lib/esm/components.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/video-chat",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -33,13 +33,13 @@
33
33
  "@fontsource/roboto": "^4.5.1",
34
34
  "@mui/icons-material": "^5.0.1",
35
35
  "@mui/material": "^5.0.2",
36
- "@tellescope/constants": "^0.0.16",
37
- "@tellescope/react-components": "^0.0.16",
38
- "@tellescope/sdk": "^0.0.16",
39
- "@tellescope/types-client": "^0.0.16",
40
- "@tellescope/types-models": "^0.0.16",
41
- "@tellescope/types-utilities": "^0.0.16",
42
- "@tellescope/utilities": "^0.0.16",
36
+ "@tellescope/constants": "^0.0.17",
37
+ "@tellescope/react-components": "^0.0.17",
38
+ "@tellescope/sdk": "^0.0.17",
39
+ "@tellescope/types-client": "^0.0.17",
40
+ "@tellescope/types-models": "^0.0.17",
41
+ "@tellescope/types-utilities": "^0.0.17",
42
+ "@tellescope/utilities": "^0.0.17",
43
43
  "@typescript-eslint/eslint-plugin": "^4.33.0",
44
44
  "@typescript-eslint/parser": "^4.33.0",
45
45
  "amazon-chime-sdk-component-library-react": "^2.12.0",
@@ -54,7 +54,7 @@
54
54
  "react": "^17.0.2",
55
55
  "react-dom": "^17.0.2"
56
56
  },
57
- "gitHead": "06e581f4d3a6c5b57fd0cfcc22103b94125f9da4",
57
+ "gitHead": "4f6785b4e580de4f3fceb9bc3d455cc7191cd094",
58
58
  "publishConfig": {
59
59
  "access": "public"
60
60
  }
package/src/controls.tsx CHANGED
@@ -6,28 +6,81 @@ import {
6
6
  VideoOffIcon,
7
7
  MicrophoneIcon,
8
8
  MicrophoneOffIcon,
9
+ CallEndIcon,
10
+
11
+ Paper,
12
+
13
+ Styled,
9
14
  } from "@tellescope/react-components/lib/esm/mui"
10
15
  import { LabeledIconButton } from "@tellescope/react-components/lib/esm/controls"
16
+ import { Flex } from "@tellescope/react-components/lib/esm/layout"
11
17
  import {
12
18
  CurrentCallContext,
19
+ useStartVideoCall,
13
20
  } from "./video"
14
21
 
15
- export const VideoToggle = () => {
22
+ const DEFAULT_BUTTON_SIZE = 30
23
+ interface ButtonProps {
24
+ size?: number,
25
+ }
26
+ export const VideoToggle = ({ size=DEFAULT_BUTTON_SIZE } : ButtonProps) => {
16
27
  const { toggleVideo, videoIsEnabled } = React.useContext(CurrentCallContext)
17
28
 
18
29
  return (
19
- <LabeledIconButton Icon={videoIsEnabled ? VideoIcon : VideoOffIcon} onClick={toggleVideo}
30
+ <LabeledIconButton size={size} Icon={videoIsEnabled ? VideoIcon : VideoOffIcon} onClick={toggleVideo}
20
31
  label={videoIsEnabled ? "Turn Camera Off" : "Turn Camera On"}
21
32
  />
22
33
  )
23
34
  }
24
35
 
25
- export const MicrophoneToggle = () => {
36
+ export const MicrophoneToggle = ({ size=DEFAULT_BUTTON_SIZE }: ButtonProps) => {
26
37
  const { microphoneIsEnabled, toggleMicrophone } = React.useContext(CurrentCallContext)
27
38
 
28
39
  return (
29
- <LabeledIconButton Icon={microphoneIsEnabled ? MicrophoneIcon : MicrophoneOffIcon} onClick={toggleMicrophone}
40
+ <LabeledIconButton size={size} Icon={microphoneIsEnabled ? MicrophoneIcon : MicrophoneOffIcon} onClick={toggleMicrophone}
30
41
  label={microphoneIsEnabled ? "Turn Microphone Off" : "Turn Microphone On"}
31
42
  />
32
43
  )
44
+ }
45
+
46
+ // ends meeting if host, otherwise leaves meeting
47
+ export const EndMeeting = ({ size=DEFAULT_BUTTON_SIZE }: ButtonProps) => {
48
+ const { endMeeting } = useStartVideoCall()
49
+
50
+ return (
51
+ <LabeledIconButton size={size} Icon={CallEndIcon} onClick={endMeeting} label="End Meeting"/>
52
+ )
53
+ }
54
+
55
+ interface LeaveMeetingProps {
56
+ onLeave?: () => void,
57
+ }
58
+ export const LeaveMeeting = ({ onLeave, size=DEFAULT_BUTTON_SIZE } : LeaveMeetingProps & ButtonProps) => (
59
+ <LabeledIconButton size={size} Icon={CallEndIcon} onClick={onLeave} label="Leave Meeting"/>
60
+ )
61
+
62
+ interface ControlbarProps {
63
+ spacing?: number,
64
+ size?: number,
65
+
66
+ }
67
+ export const ControlBar = ({ onLeave, style, spacing=15, size } : ControlbarProps & LeaveMeetingProps & Styled) => {
68
+ const { isHost } = React.useContext(CurrentCallContext)
69
+ const itemStyle = { marginLeft: spacing, marginRight: spacing }
70
+
71
+ return (
72
+ <Flex flex={1} alignItems="center" justifyContent="center" style={style}>
73
+ <Paper elevation={5} style={{ display: 'flex', flexDirection: 'row', padding: spacing }}>
74
+ <Flex style={itemStyle}>
75
+ <VideoToggle size={size}/>
76
+ </Flex>
77
+ <Flex style={itemStyle}>
78
+ <MicrophoneToggle size={size}/>
79
+ </Flex>
80
+ <Flex style={itemStyle}>
81
+ {isHost ? <EndMeeting size={size}/> : <LeaveMeeting size={size} onLeave={onLeave}/>}
82
+ </Flex>
83
+ </Paper>
84
+ </Flex>
85
+ )
33
86
  }
@@ -17,6 +17,7 @@ import { NativeModules, NativeEventEmitter } from 'react-native';
17
17
  * NativeEventEmitter.onRemoveVideoTile(tileState)
18
18
  * NativeEventEmitter.onError(errorMessage)
19
19
  */
20
+ console.log(NativeModules)
20
21
  const _eventEmitter = new NativeEventEmitter(NativeModules.NativeMobileSDKBridge);
21
22
 
22
23
  export const MobileSDKEvent = {
@@ -44,6 +44,8 @@ import {
44
44
  } from "./native/bridge"
45
45
  import { RNVideoView } from "./native/RNVideoRenderView"
46
46
 
47
+ export { CurrentCallContext }
48
+
47
49
  interface TileState {
48
50
  isLocal: boolean,
49
51
  isScreenShare: boolean,
@@ -52,6 +54,7 @@ interface TileState {
52
54
 
53
55
  export const WithVideo = ({ children } : VideoProps) => {
54
56
  const [meeting, setMeeting] = useState(undefined as MeetingInfo | undefined)
57
+ const [isHost, setIsHost] = useState(false)
55
58
 
56
59
  const [inMeeting, setInMeeting] = useState(false)
57
60
  const [isLoading, setIsLoading] = useState(false)
@@ -64,6 +67,9 @@ export const WithVideo = ({ children } : VideoProps) => {
64
67
 
65
68
  const toggleVideo = async () => {
66
69
  NativeFunction.setCameraOn(!videoIsEnabled)
70
+ if (videoIsEnabled) {
71
+ setLocalTileId(null)
72
+ }
67
73
  setVideoIsEnabled(v => !v)
68
74
  }
69
75
  const toggleMic = async () => {
@@ -145,6 +151,7 @@ export const WithVideo = ({ children } : VideoProps) => {
145
151
 
146
152
  return (
147
153
  <CurrentCallContext.Provider value={{
154
+ isHost, setIsHost,
148
155
  attendees,
149
156
  localTileId,
150
157
  videoTiles,
@@ -162,18 +169,18 @@ export const WithVideo = ({ children } : VideoProps) => {
162
169
  }
163
170
 
164
171
 
165
- export const useRemoteViews = ({ style } : { style: React.CSSProperties }) => {
172
+ export const useRemoteViews = (props={} as { style: React.CSSProperties }) => {
166
173
  const { localTileId, videoTiles } = React.useContext(CurrentCallContext)
167
174
  const nonLocal = videoTiles.filter(v => v !== localTileId)
168
175
 
169
176
  return nonLocal.map(tileId =>
170
- <RNVideoView style={convert_CSS_to_RNStyles(style) ?? styles.video} tileId={tileId} />
177
+ <RNVideoView key={tileId} style={convert_CSS_to_RNStyles(props.style) ?? styles.video} tileId={tileId} />
171
178
  )
172
179
  }
173
180
 
174
181
  export const SelfView = ({ style } : VideoViewProps) => {
175
182
  const { localTileId } = React.useContext(CurrentCallContext)
176
- if (!localTileId) return null
183
+ if (localTileId === null) return null // localTileId may be zero, don't return null on simple falsey check
177
184
 
178
185
  return (
179
186
  <RNVideoView style={convert_CSS_to_RNStyles(style) ?? styles.video} tileId={localTileId}/>
@@ -182,7 +189,7 @@ export const SelfView = ({ style } : VideoViewProps) => {
182
189
 
183
190
  export const useStartVideoCall = (): StartVideoCallReturnType => {
184
191
  const session = useSession()
185
- const { meeting, setMeeting, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
192
+ const { meeting, setMeeting, setIsHost, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
186
193
 
187
194
  const [starting, setStarting] = useState(false)
188
195
  const [ending, setEnding] = useState(false)
@@ -198,6 +205,7 @@ export const useStartVideoCall = (): StartVideoCallReturnType => {
198
205
  NativeFunction.startMeeting(meeting.Meeting, host.Attendee)
199
206
 
200
207
  setMeeting(meeting.Meeting)
208
+ setIsHost(true)
201
209
  } catch(err) {
202
210
  console.error(err)
203
211
  }
package/src/video.tsx CHANGED
@@ -45,6 +45,7 @@ export const CurrentCallContext = React.createContext({} as {
45
45
  microphoneIsEnabled: boolean, toggleMicrophone: () => Promise<void>,
46
46
  attendees: AttendeeDisplayInfo[], shareScreenId: number | null,
47
47
  localTileId: number | null,
48
+ isHost: boolean, setIsHost: (b: boolean) => void;
48
49
  videoTiles: (number)[],
49
50
  })
50
51
  export interface VideoProps {
@@ -53,6 +54,7 @@ export interface VideoProps {
53
54
  }
54
55
  const WithContext = ({ children } : { children: React.ReactNode }) => {
55
56
  const [meeting, setMeeting] = useState(undefined as MeetingInfo | undefined)
57
+ const [isHost, setIsHost] = useState(false)
56
58
  const { toggleVideo, isVideoEnabled: videoIsEnabled, tileId: localTileId } = useLocalVideo();
57
59
  const { roster } = useRosterState()
58
60
  const { tileId } = useContentShareState()
@@ -67,6 +69,7 @@ const WithContext = ({ children } : { children: React.ReactNode }) => {
67
69
 
68
70
  return (
69
71
  <CurrentCallContext.Provider value={{
72
+ isHost, setIsHost,
70
73
  attendees,
71
74
  localTileId,
72
75
  videoTiles: tiles,
@@ -95,9 +98,9 @@ export const WithVideo = ({ children, theme=darkTheme }: VideoProps) => (
95
98
  export const useStartVideoCall = () => {
96
99
  const [starting, setStarting] = useState(false)
97
100
  const [ending, setEnding] = useState(false)
98
- const { meeting, setMeeting, toggleVideo, videoIsEnabled } = React.useContext(CurrentCallContext)
101
+ const { meeting, setMeeting, toggleVideo, videoIsEnabled, setIsHost } = React.useContext(CurrentCallContext)
99
102
 
100
- const session = useSession()
103
+ const session = useSession() // meetings can only be started by users, not endusers (for now)
101
104
  const meetingManager = useMeetingManager();
102
105
 
103
106
  const createAndStartMeeting = async (initialAttendees?: UserIdentity[]) => {
@@ -114,6 +117,7 @@ export const useStartVideoCall = () => {
114
117
  }
115
118
 
116
119
  setMeeting(meeting.Meeting)
120
+ setIsHost(true)
117
121
  } catch(err) {
118
122
  console.error(err)
119
123
  }
@@ -162,12 +166,12 @@ export interface VideoViewProps {
162
166
  }
163
167
  export const SelfView = ({ style }: VideoViewProps) => <div style={style}><LocalVideo/></div>
164
168
 
165
- export const useRemoteViews = ({ style } : VideoViewProps) => {
169
+ export const useRemoteViews = (props={} as VideoViewProps) => {
166
170
  const { localTileId, videoTiles } = React.useContext(CurrentCallContext)
167
171
  const nonLocal = videoTiles.filter(v => v !== localTileId)
168
172
 
169
173
  return nonLocal.map(tileId =>
170
- <RemoteVideo style={style} tileId={tileId} />
174
+ <RemoteVideo key={tileId} style={props.style} tileId={tileId} />
171
175
  )
172
176
  }
173
177
 
@@ -1 +0,0 @@
1
- //# sourceMappingURL=components.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/components.tsx"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- // components that work with web or native
3
- //# sourceMappingURL=components.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/components.tsx"],"names":[],"mappings":";AAAA,0CAA0C"}