diff --git a/css/_premeeting-screens.scss b/css/_premeeting-screens.scss
index c892100d6..f2164b00b 100644
--- a/css/_premeeting-screens.scss
+++ b/css/_premeeting-screens.scss
@@ -197,16 +197,9 @@
text-align: center;
}
- .preview-avatar-container {
- width: 100%;
- height: 80%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
.avatar {
background: #A4B8D1;
+ margin: 0 auto;
}
video {
diff --git a/react/features/base/premeeting/components/web/Avatar.js b/react/features/base/premeeting/components/web/Avatar.js
new file mode 100644
index 000000000..03531f9cc
--- /dev/null
+++ b/react/features/base/premeeting/components/web/Avatar.js
@@ -0,0 +1,61 @@
+// @flow
+
+import React from 'react';
+
+import { Avatar } from '../../../avatar';
+import { connect } from '../../../redux';
+import { calculateAvatarDimensions } from '../../functions';
+
+type Props = {
+
+ /**
+ * The height of the window.
+ */
+ height: number,
+
+ /**
+ * The name of the participant (if any).
+ */
+ name: string
+}
+
+/**
+ * Component displaying the avatar for the premeeting screen.
+ *
+ * @param {Props} props - The props of the component.
+ * @returns {ReactElement}
+ */
+function PremeetingAvatar({ height, name }: Props) {
+ const { marginTop, size } = calculateAvatarDimensions(height);
+
+ if (size <= 5) {
+ return null;
+ }
+
+
+ return (
+
+ );
+}
+
+/**
+ * Maps (parts of) the redux state to the React {@code Component} props.
+ *
+ * @param {Object} state - The redux state.
+ * @returns {{
+ * height: number
+ * }}
+ */
+function mapStateToProps(state) {
+ return {
+ height: state['features/base/responsive-ui'].clientHeight
+ };
+}
+
+export default connect(mapStateToProps)(PremeetingAvatar);
diff --git a/react/features/base/premeeting/components/web/Preview.js b/react/features/base/premeeting/components/web/Preview.js
index 7dae4675e..c3330fe7c 100644
--- a/react/features/base/premeeting/components/web/Preview.js
+++ b/react/features/base/premeeting/components/web/Preview.js
@@ -2,11 +2,12 @@
import React from 'react';
-import { Avatar } from '../../../avatar';
import { Video } from '../../../media';
import { connect } from '../../../redux';
import { getLocalVideoTrack } from '../../../tracks';
+import PreviewAvatar from './Avatar';
+
export type Props = {
/**
@@ -54,13 +55,7 @@ function Preview(props: Props) {
);
}
diff --git a/react/features/base/premeeting/functions.js b/react/features/base/premeeting/functions.js
index ff088abe0..43b7b9cc8 100644
--- a/react/features/base/premeeting/functions.js
+++ b/react/features/base/premeeting/functions.js
@@ -1,3 +1,5 @@
+// @flow
+
import { findIndex } from 'lodash';
import { CONNECTION_TYPE } from './constants';
@@ -8,6 +10,75 @@ const LOSS_VIDEO_THRESHOLDS = [ 0.33, 0.1, 0.05 ];
const THROUGHPUT_AUDIO_THRESHOLDS = [ 8, 20 ];
const THROUGHPUT_VIDEO_THRESHOLDS = [ 60, 750 ];
+/**
+ * The avatar size to container size ration.
+ */
+const ratio = 1 / 3;
+
+/**
+ * The max avatar size.
+ */
+const maxSize = 190;
+
+/**
+ * The window limit hight over which the avatar should have the default dimension.
+ */
+const upperHeightLimit = 760;
+
+/**
+ * The window limit hight under which the avatar should not be resized anymore.
+ */
+const lowerHeightLimit = 460;
+
+/**
+ * The default top margin of the avatar.
+ */
+const defaultMarginTop = '10%';
+
+/**
+ * The top margin of the avatar when its dimension is small.
+ */
+const smallMarginTop = '5%';
+
+/**
+ * Calculates avatar dimensions based on window height and position.
+ *
+ * @param {number} height - The window height.
+ * @returns {{
+ * marginTop: string,
+ * size: number
+ * }}
+ */
+export function calculateAvatarDimensions(height: number) {
+ if (height > upperHeightLimit) {
+ return {
+ size: maxSize,
+ marginTop: defaultMarginTop
+ };
+ }
+
+ if (height > lowerHeightLimit) {
+ const diff = height - lowerHeightLimit;
+ const percent = diff * ratio;
+ const size = Math.floor(maxSize * percent / 100);
+ let marginTop = defaultMarginTop;
+
+ if (height < 600) {
+ marginTop = smallMarginTop;
+ }
+
+ return {
+ size,
+ marginTop
+ };
+ }
+
+ return {
+ size: 0,
+ marginTop: '0'
+ };
+}
+
/**
* Returns the level based on a list of thresholds.
*
@@ -121,7 +192,7 @@ function _getConnectionDataFromTestResults({ fractionalLoss: l, throughput: t })
* connectionDetails: string[]
* }}
*/
-export function getConnectionData(state) {
+export function getConnectionData(state: Object) {
const { precallTestResults } = state['features/prejoin'];
if (precallTestResults) {