diff --git a/images/icons/moderator.svg b/images/icons/moderator.svg
new file mode 100644
index 0000000000000000000000000000000000000000..60bc71b7e0bd58b909b7f769c319e7b341609b38
--- /dev/null
+++ b/images/icons/moderator.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>Moderateur</title>
+    <g id="Icones_Outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="Moderateur" fill-rule="nonzero" stroke="#000000" stroke-width="1.3">
+            <path d="M12.0856077,6.17414866 L15.2188905,10.399333 L21.4126996,6.23175137 L21.4126996,18.3907977 L2.73757526,18.3907977 L2.73757526,6.23175137 L8.92952352,10.3980809 L12.0856077,6.17414866 Z" id="Shape"></path>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/qml.qrc b/qml.qrc
index 7f2d12277203836d5f422d0cd0368bdb1da4b8b0..b06ef1cb9cd67a7b42af9923b99b4638bb818b7e 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -102,7 +102,6 @@
         <file>src/commoncomponents/GeneralMenuItem.qml</file>
         <file>src/mainview/components/ConversationSmartListContextMenu.qml</file>
         <file>src/mainview/components/CallViewContextMenu.qml</file>
-        <file>src/mainview/components/ParticipantContextMenu.qml</file>
         <file>src/commoncomponents/GeneralMenuSeparator.qml</file>
         <file>src/mainview/components/UserProfile.qml</file>
         <file>src/mainview/js/videodevicecontextmenuitemcreation.js</file>
@@ -137,5 +136,6 @@
         <file>src/commoncomponents/ResponsiveImage.qml</file>
         <file>src/commoncomponents/PresenceIndicator.qml</file>
         <file>src/commoncomponents/AvatarImage.qml</file>
+        <file>src/mainview/components/ParticipantOverlayMenu.qml</file>
     </qresource>
 </RCC>
diff --git a/resources.qrc b/resources.qrc
index efc77e06afa7ce8ae8c256f66c310563303498c9..6d7dbdab1720c8a24a509d3c22ae0c9118b96188 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -135,5 +135,6 @@
         <file>images/icons/settings_backup_restore-24px.svg</file>
         <file>images/logo-jami-standard-coul.svg</file>
         <file>images/logo-jami-standard-coul-white.svg</file>
+        <file>images/icons/moderator.svg</file>
     </qresource>
 </RCC>
diff --git a/src/calladapter.cpp b/src/calladapter.cpp
index 2797a82d2923ea9a8baa68bc3dbb560c66546a9b..d3e5f363edaeb004545bb7b7c3e9d08990c9bfa1 100644
--- a/src/calladapter.cpp
+++ b/src/calladapter.cpp
@@ -399,6 +399,7 @@ CallAdapter::connectCallModel(const QString& accountId)
             const auto convInfo = LRCInstance::getConversationFromCallId(callId);
             if (!convInfo.uid.isEmpty()) {
                 emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);
+                updateCallOverlay(convInfo);
             }
 
             switch (call.status) {
@@ -531,14 +532,13 @@ CallAdapter::hangupCall(const QString& uri)
                     }
                 }
             }
-
             callModel->hangUp(convInfo.callId);
         }
     }
 }
 
 void
-CallAdapter::maximizeParticipant(const QString& uri, bool isActive)
+CallAdapter::maximizeParticipant(const QString& uri)
 {
     auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
     auto* convModel = LRCInstance::getCurrentConversationModel();
@@ -547,48 +547,53 @@ CallAdapter::maximizeParticipant(const QString& uri, bool isActive)
     if (confId.isEmpty())
         confId = conversation.callId;
     try {
-        const auto call = callModel->getCall(confId);
-        switch (call.layout) {
-        case lrc::api::call::Layout::GRID:
-            callModel->setActiveParticipant(confId, uri);
-            callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
-            break;
-        case lrc::api::call::Layout::ONE_WITH_SMALL:
-            callModel->setActiveParticipant(confId, uri);
-            callModel->setConferenceLayout(confId,
-                                           isActive ? lrc::api::call::Layout::ONE
-                                                    : lrc::api::call::Layout::ONE_WITH_SMALL);
-            break;
-        case lrc::api::call::Layout::ONE:
-            callModel->setActiveParticipant(confId, uri);
-            callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
-            break;
-        };
+        auto call = callModel->getCall(confId);
+        if (call.participantsInfos.size() > 0) {
+            for (const auto& participant : call.participantsInfos) {
+                if (participant["uri"] == uri) {
+                    if (participant["active"] == "false") {
+                        callModel->setActiveParticipant(confId, uri);
+                        callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
+                    } else if (participant["y"].toInt() != 0) {
+                        callModel->setActiveParticipant(confId, uri);
+                        callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE);
+                    } else {
+                        callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
+                    }
+                    return;
+                }
+            }
+        }
     } catch (...) {
     }
 }
 
 void
-CallAdapter::minimizeParticipant()
+CallAdapter::minimizeParticipant(const QString& uri)
 {
     auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
     auto* convModel = LRCInstance::getCurrentConversationModel();
     const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
     auto confId = conversation.confId;
+
     if (confId.isEmpty())
         confId = conversation.callId;
     try {
         auto call = callModel->getCall(confId);
-        switch (call.layout) {
-        case lrc::api::call::Layout::GRID:
-            break;
-        case lrc::api::call::Layout::ONE_WITH_SMALL:
-            callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
-            break;
-        case lrc::api::call::Layout::ONE:
-            callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
-            break;
-        };
+        if (call.participantsInfos.size() > 0) {
+            for (const auto& participant : call.participantsInfos) {
+                if (participant["uri"] == uri) {
+                    if (participant["active"] == "true") {
+                        if (participant["y"].toInt() == 0) {
+                            callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
+                        } else {
+                            callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
+                        }
+                    }
+                    return;
+                }
+            }
+        }
     } catch (...) {
     }
 }
@@ -626,7 +631,10 @@ CallAdapter::isCurrentHost() const
     if (!convInfo.uid.isEmpty()) {
         auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
         try {
-            auto call = callModel->getCall(convInfo.callId);
+            auto confId = convInfo.confId;
+            if (confId.isEmpty())
+                confId = convInfo.callId;
+            auto call = callModel->getCall(confId);
             if (call.participantsInfos.size() == 0) {
                 return true;
             } else {
@@ -647,13 +655,12 @@ CallAdapter::participantIsHost(const QString& uri) const
         auto& accInfo = LRCInstance::getAccountInfo(accountId_);
         auto* callModel = accInfo.callModel.get();
         try {
-            auto call = callModel->getCall(convInfo.callId);
-            if (call.participantsInfos.size() == 0) {
-                return (uri.isEmpty() || uri == accInfo.profileInfo.uri);
+            if (isCurrentHost()) {
+                return uri == accInfo.profileInfo.uri;
             } else {
-                return !convInfo.confId.isEmpty()
-                        && callModel->hasCall(convInfo.confId)
-                        && (uri.isEmpty() || uri == accInfo.profileInfo.uri);
+                auto call = callModel->getCall(convInfo.callId);
+                auto peer = call.peerUri.remove("ring:");
+                return (uri == peer);
             }
         } catch (...) {
         }
@@ -778,22 +785,6 @@ CallAdapter::isCurrentMuted() const
     return true;
 }
 
-int
-CallAdapter::getCurrentLayoutType() const
-{
-    auto* convModel = LRCInstance::getCurrentConversationModel();
-    const auto convInfo = convModel->getConversationForUID(convUid_);
-    if (!convInfo.uid.isEmpty()) {
-        auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
-        try {
-            auto call = callModel->getCall(convInfo.confId);
-            return static_cast<int>(call.layout);
-        } catch (...) {
-        }
-    }
-    return -1;
-}
-
 void
 CallAdapter::holdThisCallToggle()
 {
diff --git a/src/calladapter.h b/src/calladapter.h
index af6a3a25526f92eeb0edda6e35b0370040483174..f33e6679b8924f026a81260ed38a9b4a53f77bad 100644
--- a/src/calladapter.h
+++ b/src/calladapter.h
@@ -53,15 +53,14 @@ public:
      * For Call Overlay
      */
     Q_INVOKABLE void hangupCall(const QString& uri);
-    Q_INVOKABLE void maximizeParticipant(const QString& uri, bool isActive);
-    Q_INVOKABLE void minimizeParticipant();
+    Q_INVOKABLE void maximizeParticipant(const QString& uri);
+    Q_INVOKABLE void minimizeParticipant(const QString& uri);
     Q_INVOKABLE void hangUpThisCall();
-    Q_INVOKABLE void setModerator(const QString& uri, const bool state);
     Q_INVOKABLE bool isCurrentHost() const;
-    Q_INVOKABLE bool participantIsHost(const QString& uri = {}) const;
+    Q_INVOKABLE bool participantIsHost(const QString& uri) const;
+    Q_INVOKABLE void setModerator(const QString& uri, const bool state);
     Q_INVOKABLE bool isModerator(const QString& uri = {}) const;
     Q_INVOKABLE bool isCurrentModerator() const;
-    Q_INVOKABLE int getCurrentLayoutType() const;
     Q_INVOKABLE void holdThisCallToggle();
     Q_INVOKABLE void muteThisCallToggle();
     Q_INVOKABLE void recordThisCallToggle();
diff --git a/src/commoncomponents/ResponsiveImage.qml b/src/commoncomponents/ResponsiveImage.qml
index 08d1eb7289a9dbe95b625c728bba1659053b2476..6fe7da23b9ffc448b6154d0b551a05cfd2aedac1 100644
--- a/src/commoncomponents/ResponsiveImage.qml
+++ b/src/commoncomponents/ResponsiveImage.qml
@@ -62,8 +62,8 @@ Image {
 
     function setSourceSize() {
         if (isSvg) {
-            sourceSize.width = Math.max(24, width)
-            sourceSize.height = Math.max(24, height)
+            sourceSize.width = width
+            sourceSize.height = height
         } else
             sourceSize = undefined
     }
diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml
index 97c17cb06b192348c3575942267286c90e1482fd..517fa28b94654de0b4b8cd3766dd1dbc145dfd77 100644
--- a/src/constant/JamiStrings.qml
+++ b/src/constant/JamiStrings.qml
@@ -397,4 +397,14 @@ Item {
     // Generic dialog options
     property string optionOk: qsTr("Ok")
     property string optionCancel: qsTr("Cancel")
+
+    // Conference moderation
+    property string setModerator: qsTr("Set moderator")
+    property string unsetModerator: qsTr("Unset moderator")
+    property string muteParticipant: qsTr("Mute")
+    property string unmuteParticipant: qsTr("Unmute")
+    property string maximizeParticipant: qsTr("Maximize")
+    property string minimizeParticipant: qsTr("Minimize")
+    property string hangupParticipant: qsTr("Hangup")
 }
+
diff --git a/src/constant/JamiTheme.qml b/src/constant/JamiTheme.qml
index 70ce90aa013906d05442d34275c5756b76a4567d..ae2061e93b5bc37e880c0f94c36ba3840bac8ef0 100644
--- a/src/constant/JamiTheme.qml
+++ b/src/constant/JamiTheme.qml
@@ -30,6 +30,8 @@ Item {
     // General
     property color blackColor: "#000000"
     property color whiteColor: "#ffffff"
+    property color darkGreyColor: "#272727"
+    property color darkGreyColorOpacity: "#4D272727" // 77%
     property color transparentColor: "transparent"
     property color primaryForegroundColor: darkTheme? whiteColor : blackColor
     property color primaryBackgroundColor: darkTheme? bgDarkMode_ : whiteColor
@@ -91,6 +93,10 @@ Item {
     property color sipInputButtonHoverColor: "#4477aa"
     property color sipInputButtonPressColor: "#5588bb"
 
+    property string buttonConference: "#110000"
+    property string buttonConferenceHovered: "#66cfff"
+    property string buttonConferencePressed: "#66cfff"
+
     // Wizard / account manager
     property color accountCreationOtherStepColor: "grey"
     property color accountCreationCurrentStepColor: "#28b1ed"
@@ -151,6 +157,7 @@ Item {
     property int textFontSize: 9
     property int settingsFontSize: 9
     property int buttonFontSize: 9
+    property int participantFontSize: 10
     property int menuFontSize: 12
     property int headerFontSize: 13
     property int titleFontSize: 16
diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml
index d2c8bae009a25880a2b4c6e819db46e3c364e428..621d0f28331a1e32bb287ea61117c999a2cd1087 100644
--- a/src/mainview/components/CallOverlay.qml
+++ b/src/mainview/components/CallOverlay.qml
@@ -47,7 +47,8 @@ Rectangle {
         recordingRect.visible = isRecording
     }
 
-    function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
+    function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted,
+                                isRecording, isSIP, isConferenceCall) {
         callViewContextMenu.isSIP = isSIP
         callViewContextMenu.isPaused = isPaused
         callViewContextMenu.isAudioOnly = isAudioOnly
@@ -75,46 +76,116 @@ Rectangle {
         MediaHandlerPickerCreation.closeMediaHandlerPicker()
     }
 
+    // returns true if participant is not fully maximized
+    function showMaximize(pX, pY, pW, pH) {
+        // Hack: -1 offset added to avoid problems with odd sizes
+        return (pX - distantRenderer.getXOffset() !== 0
+                || pY - distantRenderer.getYOffset() !== 0
+                || pW < (distantRenderer.width - distantRenderer.getXOffset() * 2 - 1)
+                || pH < (distantRenderer.height - distantRenderer.getYOffset() * 2 - 1))
+    }
+
+    // returns true if participant takes renderer's width
+    function showMinimize(pX, pW) {
+        return (pX - distantRenderer.getXOffset() === 0
+                && pW >= distantRenderer.width - distantRenderer.getXOffset() * 2 - 1)
+    }
+
+
     function handleParticipantsInfo(infos) {
+        // TODO: in the future the conference layout should be entirely managed by the client
         videoCallOverlay.updateMenu()
-        var isModerator = CallAdapter.isCurrentModerator()
-        var isHost = CallAdapter.isCurrentHost()
+        var showMax = false
+        var showMin = false
+
+        var deletedUris = []
+        var currentUris = []
         for (var p in participantOverlays) {
-            if (participantOverlays[p])
-                participantOverlays[p].destroy()
+            if (participantOverlays[p]) {
+                var participant = infos.find(e => e.uri === participantOverlays[p].uri);
+                if (participant) {
+                    // Update participant's information
+                    var newX = distantRenderer.getXOffset()
+                            + participant.x * distantRenderer.getScaledWidth()
+                    var newY = distantRenderer.getYOffset()
+                            + participant.y * distantRenderer.getScaledHeight()
+                    var newWidth = participant.w * distantRenderer.getScaledWidth()
+                    var newHeight = participant.h * distantRenderer.getScaledHeight()
+                    var newVisible = participant.w !== 0 && participant.h !== 0
+
+                    if (participantOverlays[p].x !== newX)
+                        participantOverlays[p].x = newX
+                    if (participantOverlays[p].y !== newY)
+                        participantOverlays[p].y = newY
+                    if (participantOverlays[p].width !== newWidth)
+                        participantOverlays[p].width = newWidth
+                    if (participantOverlays[p].height !== newHeight)
+                        participantOverlays[p].height = newHeight
+                    if (participantOverlays[p].visible !== newVisible)
+                        participantOverlays[p].visible = newVisible
+
+                    showMax = showMaximize(participantOverlays[p].x,
+                                           participantOverlays[p].y,
+                                           participantOverlays[p].width,
+                                           participantOverlays[p].height)
+                    showMin = showMinimize(participantOverlays[p].x,
+                                           participantOverlays[p].width)
+
+                    participantOverlays[p].setMenu(participant.uri, participant.bestName,
+                                                   participant.isLocal, showMax, showMin)
+                    if (participant.videoMuted)
+                        participantOverlays[p].setAvatar(participant.avatar)
+                    else
+                        participantOverlays[p].setAvatar("")
+                    currentUris.push(participantOverlays[p].uri)
+                } else {
+                    // Participant is no longer in conference
+                    deletedUris.push(participantOverlays[p].uri)
+                    participantOverlays[p].destroy()
+                }
+            }
         }
-        participantOverlays = []
-        if (infos.length == 0) {
+        participantOverlays = participantOverlays.filter(part => !deletedUris.includes(part.uri))
+
+        if (infos.length === 0) { // Return to normal call
             previewRenderer.visible = true
+            for (var part in participantOverlays) {
+                if (participantOverlays[part]) {
+                        participantOverlays[part].destroy()
+                }
+            }
+            participantOverlays = []
         } else {
             previewRenderer.visible = false
             for (var infoVariant in infos) {
-                var hover = participantComponent.createObject(callOverlayRectMouseArea, {
-                    x: distantRenderer.getXOffset() + infos[infoVariant].x * distantRenderer.getScaledWidth(),
-                    y: distantRenderer.getYOffset() + infos[infoVariant].y * distantRenderer.getScaledHeight(),
-                    width: infos[infoVariant].w * distantRenderer.getScaledWidth(),
-                    height: infos[infoVariant].h * distantRenderer.getScaledHeight(),
-                    visible: infos[infoVariant].w != 0 && infos[infoVariant].h != 0
-                })
-                if (!hover) {
-                    console.log("Error when creating the hover")
-                    return
-                }
+                // Only create overlay for new participants
+                if (!currentUris.includes(infos[infoVariant].uri)) {
+                    var hover = participantComponent.createObject(callOverlayRectMouseArea, {
+                        x: distantRenderer.getXOffset() + infos[infoVariant].x * distantRenderer.getScaledWidth(),
+                        y: distantRenderer.getYOffset() + infos[infoVariant].y * distantRenderer.getScaledHeight(),
+                        width: infos[infoVariant].w * distantRenderer.getScaledWidth(),
+                        height: infos[infoVariant].h * distantRenderer.getScaledHeight(),
+                        visible: infos[infoVariant].w !== 0 && infos[infoVariant].h !== 0
+                    })
+                    if (!hover) {
+                        console.log("Error when creating the hover")
+                        return
+                    }
+
+                    showMax = showMaximize(hover.x, hover.y, hover.width, hover.height)
+                    showMin = showMinimize(hover.x, hover.width)
 
-                hover.setParticipantName(infos[infoVariant].bestName)
-                hover.active = infos[infoVariant].active;
-                hover.isLocal = infos[infoVariant].isLocal;
-                hover.setMenuVisible(isModerator)
-                hover.setEndCallVisible(isHost)
-                hover.uri = infos[infoVariant].uri
-                if (infos[infoVariant].videoMuted)
-                    hover.setAvatar(infos[infoVariant].avatar)
-                else
-                    hover.setAvatar("")
-                hover.injectedContextMenu = participantContextMenu
-                participantOverlays.push(hover)
+                    hover.setMenu(infos[infoVariant].uri, infos[infoVariant].bestName,
+                                  infos[infoVariant].isLocal, showMax, showMin)
+                    if (infos[infoVariant].videoMuted)
+                        hover.setAvatar(infos[infoVariant].avatar)
+                    else
+                        hover.setAvatar("")
+                    participantOverlays.push(hover)
+                }
             }
         }
+
     }
 
     // x, y position does not need to be translated
@@ -477,8 +548,4 @@ Rectangle {
             MediaHandlerPickerCreation.openMediaHandlerPicker()
         }
     }
-
-    ParticipantContextMenu {
-        id: participantContextMenu
-    }
 }
diff --git a/src/mainview/components/CallOverlayButtonGroup.qml b/src/mainview/components/CallOverlayButtonGroup.qml
index f8bfc0e8559fb61579ba9b8208c87869ca37065b..84295ba03c7682530398d3be06ab3e4b368844f9 100644
--- a/src/mainview/components/CallOverlayButtonGroup.qml
+++ b/src/mainview/components/CallOverlayButtonGroup.qml
@@ -33,22 +33,23 @@ Rectangle {
     // ButtonCounts here is to make sure that flow layout margin is calculated correctly,
     // since no other methods can make buttons at the layout center.
     property int buttonPreferredSize: 48
-    property var isHost: true
+    property var isModerator: true
     property var isSip: false
 
     signal chatButtonClicked
     signal addToConferenceButtonClicked
 
     function updateMenu() {
-        root.isHost = CallAdapter.isCurrentHost()
-        addToConferenceButton.visible = !root.isSip && root.isHost
+        root.isModerator = CallAdapter.isCurrentModerator()
+        addToConferenceButton.visible = !root.isSip && root.isModerator
     }
 
-    function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) {
-        root.isHost = CallAdapter.isCurrentModerator()
+    function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted,
+                             isRecording, isSIP, isConferenceCall) {
+        root.isModerator = CallAdapter.isCurrentModerator()
         root.isSip = isSIP
         noVideoButton.visible = !isAudioOnly
-        addToConferenceButton.visible = !isSIP && isHost
+        addToConferenceButton.visible = !root.isSIP && root.isModerator
 
         noMicButton.checked = isAudioMuted
         noVideoButton.checked = isVideoMuted
@@ -150,7 +151,7 @@ Rectangle {
 
             Layout.preferredWidth: buttonPreferredSize
             Layout.preferredHeight: buttonPreferredSize
-            visible: !isHost
+            visible: !isModerator
 
             pressedColor: JamiTheme.invertedPressedButtonColor
             hoveredColor: JamiTheme.invertedHoveredButtonColor
diff --git a/src/mainview/components/ParticipantContextMenu.qml b/src/mainview/components/ParticipantContextMenu.qml
deleted file mode 100644
index 5c9f4985ac3dcc0e0cbcbac55b04b22cda9094b4..0000000000000000000000000000000000000000
--- a/src/mainview/components/ParticipantContextMenu.qml
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2020 by Savoir-faire Linux
- * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
- * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.14
-import QtQuick.Controls 2.14
-import QtGraphicalEffects 1.14
-import net.jami.Models 1.0
-import net.jami.Constants 1.0
-
-import "../../commoncomponents"
-import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
-
-Item {
-    id: root
-
-    property var uri: ""
-    property var maximized: true
-    property var active: true
-    property var showHangup: false
-    property var showMaximize: false
-    property var showMinimize: false
-    property var showSetModerator: false
-    property var showUnsetModerator: false
-    property var showMute: false
-    property var showUnmute: false
-
-    function openMenu(){
-        ContextMenuGenerator.initMenu()
-        if (showHangup)
-            ContextMenuGenerator.addMenuItem(JamiStrings.hangup,
-                                             "qrc:/images/icons/ic_call_end_white_24px.svg",
-                                             function (){
-                                                 CallAdapter.hangupCall(uri)
-                                             })
-
-        if (showMaximize)
-            ContextMenuGenerator.addMenuItem(qsTr("Maximize participant"),
-                                             "qrc:/images/icons/open_in_full-24px.svg",
-                                             function (){
-                                                  CallAdapter.maximizeParticipant(uri, active)
-                                             })
-        if (showMinimize)
-            ContextMenuGenerator.addMenuItem(qsTr("Minimize participant"),
-                                             "qrc:/images/icons/close_fullscreen-24px.svg",
-                                             function (){
-                                                  CallAdapter.minimizeParticipant()
-                                             })
-
-        if (showSetModerator)
-            ContextMenuGenerator.addMenuItem(qsTr("Set moderator"),
-                                             "qrc:/images/icons/person_add-24px.svg",
-                                             function (){
-                                                  CallAdapter.setModerator(uri, true)
-                                             })
-
-        if (showUnsetModerator)
-            ContextMenuGenerator.addMenuItem(qsTr("Unset moderator"),
-                                             "qrc:/images/icons/round-close-24px.svg",
-                                             function (){
-                                                  CallAdapter.setModerator(uri, false)
-                                             })
-
-        if (showMute)
-            ContextMenuGenerator.addMenuItem(qsTr("Mute participant"),
-                                             "qrc:/images/icons/mic_off-24px.svg",
-                                             function (){
-                                                  CallAdapter.muteParticipant(uri, true)
-                                             })
-
-        if (showUnmute)
-            ContextMenuGenerator.addMenuItem(qsTr("Unmute participant"),
-                                             "qrc:/images/icons/mic-24px.svg",
-                                             function (){
-                                                  CallAdapter.muteParticipant(uri, false)
-                                             })
-
-
-        root.height = ContextMenuGenerator.getMenu().height
-        root.width = ContextMenuGenerator.getMenu().width
-        ContextMenuGenerator.getMenu().open()
-    }
-
-    Component.onCompleted: {
-        ContextMenuGenerator.createBaseContextMenuObjects(root)
-    }
-}
-
diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml
index 38e19e753d8abefad534418cf49fc701a1d3f07d..a28f630d197c34182af44c6a10cbaf39c8b18ff4 100644
--- a/src/mainview/components/ParticipantOverlay.qml
+++ b/src/mainview/components/ParticipantOverlay.qml
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2020 by Savoir-faire Linux
  * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ * Author: Albert Babí <albert.babi@savoirfairelinux.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +20,7 @@
 import QtQuick 2.14
 import QtQuick.Controls 2.14
 import QtQuick.Layouts 1.14
+import QtQuick.Shapes 1.14
 import QtQuick.Controls.Universal 2.14
 import QtGraphicalEffects 1.14
 import net.jami.Models 1.0
@@ -29,190 +31,215 @@ import "../../commoncomponents"
 Rectangle {
     id: root
 
-    property int buttonPreferredSize: 12
-    property var uri: ""
-    property var active: true
-    property var isLocal: true
-    property var showEndCall: true
-    property var injectedContextMenu: null
+    // svg path for the background participant shape (width is offset dependant)
+    property int offset: indicatorsRowLayout.width
+    property int shapeHeight: 16
+    property string pathShape: "M 0.0,%8
+    C 0.0,%8 %1,%8 %1,%8 %2,%8 %3,%9 %4,10.0 %5,5.0 %5,0.0 %6,0.0 %7,0.0 %4,0.0
+      0.0,0.0 0.0,0.0 0.0,%8 0.0,%8 Z".arg(offset).arg(4.0+offset).arg(7+offset)
+    .arg(9+offset).arg(11+offset).arg(15+offset).arg(18+offset).arg(shapeHeight)
+    .arg(shapeHeight-2)
 
-    function setParticipantName(name) {
-        participantName.text = name
-    }
+    // TODO: properties should be
+    property string uri: overlayMenu.uri
+    property bool participantIsModerator: false
+    property bool participantIsMuted: false
 
     // TODO: try to use AvatarImage as well
     function setAvatar(avatar) {
         if (avatar === "") {
-            opacity = 0
             contactImage.source = ""
         } else {
-            opacity = 1
             contactImage.source = "data:image/png;base64," + avatar
         }
     }
 
-    function setMenuVisible(isVisible) {
-        optionsButton.visible = isVisible
-    }
+    function setMenu(newUri, bestName, isLocal, showMax, showMin) {
+
+        overlayMenu.uri = newUri
+        overlayMenu.bestName = bestName
 
-    function setEndCallVisible(isVisible) {
-        showEndCall = isVisible
+        var isHost = CallAdapter.isCurrentHost()
+        var isModerator = CallAdapter.isCurrentModerator()
+        var participantIsHost = CallAdapter.participantIsHost(overlayMenu.uri)
+        participantIsModerator = CallAdapter.isModerator(overlayMenu.uri)
+        overlayMenu.showSetModerator = isHost && !isLocal && !participantIsModerator
+        overlayMenu.showUnsetModerator = isHost && !isLocal && participantIsModerator
+
+        participantIsMuted = CallAdapter.isMuted(overlayMenu.uri)
+        overlayMenu.showMute = isModerator && !participantIsMuted
+        overlayMenu.showUnmute = isModerator && participantIsMuted && isLocal
+        overlayMenu.showMaximize = isModerator && showMax
+        overlayMenu.showMinimize = isModerator && showMin
+        overlayMenu.showHangup = isModerator && !isLocal && !participantIsHost
     }
 
-    border.width: 1
-    opacity: 0
     color: "transparent"
     z: 1
 
-    MouseArea {
-        id: mouseAreaHover
-        anchors.fill: parent
-        hoverEnabled: true
-        propagateComposedEvents: true
-        acceptedButtons: Qt.LeftButton
-
-        Image {
-            id: contactImage
-
-            anchors.centerIn: parent
-
-            height:  Math.min(parent.width / 2, parent.height / 2)
-            width:  Math.min(parent.width / 2, parent.height / 2)
-
-            fillMode: Image.PreserveAspectFit
-            source: ""
-            asynchronous: true
-
-            layer.enabled: true
-            layer.effect: OpacityMask {
-                maskSource: Rectangle{
-                    width: contactImage.width
-                    height: contactImage.height
-                    radius: {
-                        var size = ((contactImage.width <= contactImage.height)? contactImage.width:contactImage.height)
-                        return size /2
-                    }
-                }
+    // Participant header with moderator / mute indicators
+    Rectangle {
+        id: participantIndicators
+        width: indicatorsRowLayout.width
+        height: shapeHeight
+        visible: participantIsModerator || participantIsMuted
+        color: "transparent"
+
+        Shape {
+            id: myShape
+            ShapePath {
+                id: backgroundShape
+                strokeColor: "transparent"
+                fillColor: JamiTheme.darkGreyColorOpacity
+                capStyle: ShapePath.RoundCap
+                PathSvg { path: pathShape }
             }
         }
 
         RowLayout {
-            id: bottomLabel
-
-            height: 24
-            width: parent.width
-            anchors.bottom: parent.bottom
-
-            Rectangle {
-                color: "black"
-                opacity: 0.8
-                height: parent.height
-                width: parent.width
-                Layout.fillWidth: true
-                Layout.preferredHeight: parent.height
-
-                Text {
-                    id: participantName
-                    anchors.fill: parent
-                    leftPadding: 8.0
-
-                    TextMetrics {
-                        id: participantMetrics
-                        elide: Text.ElideRight
-                        elideWidth: bottomLabel.width - 8
-                    }
-
-                    text: participantMetrics.elidedText
-
-                    color: "white"
-                    font.pointSize: JamiTheme.textFontSize
-                    horizontalAlignment: Text.AlignLeft
-                    verticalAlignment: Text.AlignVCenter
+            id: indicatorsRowLayout
+            height: parent.height
+            anchors.verticalCenter: parent.verticalCenter
+
+            ResponsiveImage {
+                id: isModeratorIndicator
+
+                visible: participantIsModerator
+
+                Layout.alignment: Qt.AlignVCenter
+                Layout.leftMargin: 6
+                containerHeight: 12
+                containerWidth: 12
+
+                source: "qrc:/images/icons/moderator.svg"
+                layer {
+                    enabled: true
+                    effect: ColorOverlay { color: JamiTheme.whiteColor }
+                    mipmap: false
+                    smooth: true
                 }
+            }
 
-                Button {
-                    id: optionsButton
+            ResponsiveImage {
+                id: isMutedIndicator
+
+                visible: participantIsMuted
+                Layout.alignment: Qt.AlignVCenter
+                Layout.leftMargin: 6
+                containerHeight: 12
+                containerWidth: 12
+
+                source: "qrc:/images/icons/mic_off-24px.svg"
+                layer {
+                    enabled: true
+                    effect: ColorOverlay { color: JamiTheme.whiteColor }
+                    mipmap: false
+                    smooth: true
+                }
+            }
+        }
+    }
 
-                    anchors.right: parent.right
-                    anchors.verticalCenter: parent.verticalCenter
+    // Participant background, mousearea, hover and buttons for moderation
+    Rectangle {
+        id: participantRect
 
-                    background: Rectangle {
-                        color: "transparent"
+        anchors.fill: parent
+        opacity: 0
+        color: JamiTheme.darkGreyColorOpacity
+        z: 1
+
+        MouseArea {
+            id: mouseAreaHover
+
+            anchors.fill: parent
+            hoverEnabled: true
+            propagateComposedEvents: false
+            acceptedButtons: Qt.LeftButton
+
+            Image {
+                id: contactImage
+
+                anchors.centerIn: parent
+                height:  Math.min(parent.width / 2, parent.height / 2)
+                width:  Math.min(parent.width / 2, parent.height / 2)
+
+                fillMode: Image.PreserveAspectFit
+                source: ""
+                asynchronous: true
+
+                layer.enabled: true
+                layer.effect: OpacityMask {
+                    maskSource: Rectangle{
+                        width: contactImage.width
+                        height: contactImage.height
+                        radius: {
+                            var size = ((contactImage.width <= contactImage.height)?
+                                            contactImage.width : contactImage.height)
+                            return size / 2
+                        }
                     }
+                }
+                layer.mipmap: false
+                layer.smooth: true
+            }
 
+            ParticipantOverlayMenu {
+                id: overlayMenu
+                visible: participantRect.opacity !== 0
+                anchors.centerIn: parent
+                hasMinimumSize: root.width > minimumWidth && root.height > minimumHeight
 
-                    icon.color: "white"
-                    icon.height: buttonPreferredSize
-                    icon.width: buttonPreferredSize
-                    icon.source: "qrc:/images/icons/more_vert-24px.svg"
-
-                    onClicked: {
-                        if (!injectedContextMenu) {
-                            console.log("Participant's overlay don't have any injected context menu")
-                            return
-                        }
-                        var mousePos = mapToItem(videoCallPageRect, parent.x, parent.y)
-                        var layout = CallAdapter.getCurrentLayoutType()
-                        var showMaximized = layout !== 2
-                        var showMinimized = !(layout === 0 || (layout === 1 && !active))
-                        var isModerator = CallAdapter.isModerator(uri)
-                        var isHost = CallAdapter.isCurrentHost()
-                        var participantIsHost = CallAdapter.participantIsHost(uri)
-                        var isMuted = CallAdapter.isMuted(uri)
-                        injectedContextMenu.showHangup = !root.isLocal && showEndCall
-                        injectedContextMenu.showMaximize = showMaximized
-                        injectedContextMenu.showMinimize = showMinimized
-                        injectedContextMenu.uri = uri
-                        injectedContextMenu.active = active
-                        injectedContextMenu.x = mousePos.x
-                        injectedContextMenu.y = mousePos.y - injectedContextMenu.height
-                        injectedContextMenu.showSetModerator = (isHost && !participantIsHost && !isModerator)
-                        injectedContextMenu.showUnsetModerator = (isHost && !participantIsHost && isModerator)
-                        injectedContextMenu.showMute = !isMuted
-                        injectedContextMenu.showUnmute = isMuted && root.isLocal
-                        injectedContextMenu.openMenu()
+                onMouseAreaExited: {
+                    if (contactImage.status === Image.Null) {
+                        root.z = 1
+                        participantRect.state = "exited"
                     }
                 }
             }
-        }
 
-        onClicked: {
-            CallAdapter.maximizeParticipant(uri, active)
-        }
+            onClicked: {
+                CallAdapter.maximizeParticipant(uri)
+            }
 
-        onEntered: {
-            if (contactImage.status === Image.Null)
-                root.state = "entered"
-        }
+            onEntered: {
+                if (contactImage.status === Image.Null) {
+                    root.z = 2
+                    participantRect.state = "entered"
+                }
+            }
 
-        onExited: {
-            if (contactImage.status === Image.Null)
-                root.state = "exited"
+            onExited: {
+                if (contactImage.status === Image.Null) {
+                    root.z = 1
+                    participantRect.state = "exited"
+                }
+            }
         }
-    }
 
-    states: [
-        State {
-            name: "entered"
-            PropertyChanges {
-                target: root
-                opacity: 1
-            }
-        },
-        State {
-            name: "exited"
-            PropertyChanges {
-                target: root
-                opacity: 0
+        states: [
+            State {
+                name: "entered"
+                PropertyChanges {
+                    target: participantRect
+                    opacity: 1
+                }
+            },
+            State {
+                name: "exited"
+                PropertyChanges {
+                    target: participantRect
+                    opacity: 0
+                }
             }
-        }
-    ]
+        ]
 
-    transitions: Transition {
-        PropertyAnimation {
-            target: root
-            property: "opacity"
-            duration: 500
+        transitions: Transition {
+            PropertyAnimation {
+                target: participantRect
+                property: "opacity"
+                duration: 500
+            }
         }
     }
 }
diff --git a/src/mainview/components/ParticipantOverlayMenu.qml b/src/mainview/components/ParticipantOverlayMenu.qml
new file mode 100644
index 0000000000000000000000000000000000000000..3383abb384e0f22c19f113f9d9155e53cd5a61ba
--- /dev/null
+++ b/src/mainview/components/ParticipantOverlayMenu.qml
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Albert Babí <albert.babi@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtGraphicalEffects 1.14
+import QtQuick.Layouts 1.14
+import net.jami.Models 1.0
+import net.jami.Constants 1.0
+
+import "../../commoncomponents"
+
+// Overlay menu for conference moderation
+Rectangle {
+    id: root
+
+    property bool hasMinimumSize: true
+    property int buttonPreferredSize: 30
+    property int minimumWidth: Math.max(114, visibleButtons * 37 + 21 * 2)
+    property int minimumHeight: 114
+    property int visibleButtons: toggleModerator.visible
+                                 + toggleMute.visible
+                                 + maximizeParticipant.visible
+                                 + minimizeParticipant.visible
+                                 + hangupParticipant.visible
+
+    property string uri: ""
+    property string bestName: ""
+    property bool showSetModerator: false
+    property bool showUnsetModerator: false
+    property bool showMute: false
+    property bool showUnmute: false
+    property bool showMaximize: false
+    property bool showMinimize: false
+    property bool showHangup: false
+
+    signal mouseAreaExited
+
+    // values taken from sketch
+    width: hasMinimumSize? parent.width : minimumWidth
+    height: hasMinimumSize? parent.height: minimumHeight
+
+    color: hasMinimumSize? "transparent" : JamiTheme.darkGreyColorOpacity
+    radius: 10
+
+    MouseArea {
+        id: mouseAreaHover
+
+        anchors.fill: parent
+        hoverEnabled: true
+        propagateComposedEvents: true
+        acceptedButtons: Qt.LeftButton
+
+        onExited: mouseAreaExited()
+
+        ColumnLayout {
+            id: layout
+            anchors.horizontalCenter: parent.horizontalCenter
+            anchors.verticalCenter: parent.verticalCenter
+            spacing: 8
+
+            Text {
+                id: participantName
+
+                TextMetrics {
+                    id: participantMetrics
+                    text: bestName
+                    elide: Text.ElideRight
+                    elideWidth: root.width - JamiTheme.preferredMarginSize * 2
+                }
+
+                text: participantMetrics.elidedText
+                color: JamiTheme.whiteColor
+                font.pointSize: JamiTheme.participantFontSize
+                Layout.alignment: Qt.AlignCenter
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+
+            RowLayout {
+                id: rowLayoutButtons
+
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
+                Layout.fillWidth: true
+                spacing: 7
+
+                PushButton {
+                    id: toggleModerator
+
+                    visible: (showSetModerator || showUnsetModerator)
+                    Layout.preferredWidth: buttonPreferredSize
+                    Layout.preferredHeight: buttonPreferredSize
+                    preferredSize: 16
+                    normalColor: JamiTheme.buttonConference
+                    hoveredColor: JamiTheme.buttonConferenceHovered
+                    pressedColor: JamiTheme.buttonConferencePressed
+
+                    source: "qrc:/images/icons/moderator.svg"
+                    imageColor: hovered? JamiTheme.darkGreyColor
+                                       : JamiTheme.whiteColor
+
+                    onClicked: CallAdapter.setModerator(uri, showSetModerator)
+                    onHoveredChanged: toggleModeratorToolTip.visible = hovered
+
+                    Text {
+                        id: toggleModeratorToolTip
+
+                        visible: false
+                        width: parent.width
+                        text: showSetModerator? JamiStrings.setModerator
+                                              : JamiStrings.unsetModerator
+                        horizontalAlignment: Text.AlignHCenter
+                        anchors.top: parent.bottom
+                        anchors.topMargin: 6
+                        color: JamiTheme.whiteColor
+                        font.pointSize: JamiTheme.tinyFontSize
+                    }
+                }
+
+                PushButton {
+                    id: toggleMute
+
+                    visible: showMute || showUnmute
+                    Layout.preferredWidth: buttonPreferredSize
+                    Layout.preferredHeight: buttonPreferredSize
+                    preferredSize: 16
+
+                    normalColor: JamiTheme.buttonConference
+                    hoveredColor: JamiTheme.buttonConferenceHovered
+                    pressedColor: JamiTheme.buttonConferencePressed
+
+                    source: showMute? "qrc:/images/icons/mic-24px.svg"
+                                    : "qrc:/images/icons/mic_off-24px.svg"
+                    imageColor: hovered? JamiTheme.darkGreyColor
+                                       : JamiTheme.whiteColor
+
+                    onClicked: CallAdapter.muteParticipant(uri, showMute)
+                    onHoveredChanged: toggleParticipantToolTip.visible = hovered
+
+                    Text {
+                        id: toggleParticipantToolTip
+
+                        visible: false
+                        width: parent.width
+                        text: showMute? JamiStrings.muteParticipant
+                                      : JamiStrings.unmuteParticipant
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignTop
+
+                        anchors.top: parent.bottom
+                        anchors.topMargin: 6
+                        color: JamiTheme.whiteColor
+                        font.pointSize: JamiTheme.tinyFontSize
+                    }
+                }
+
+                PushButton {
+                    id: maximizeParticipant
+
+                    visible: showMaximize
+                    Layout.preferredWidth: buttonPreferredSize
+                    Layout.preferredHeight: buttonPreferredSize
+                    preferredSize: 16
+
+                    normalColor: JamiTheme.buttonConference
+                    hoveredColor: JamiTheme.buttonConferenceHovered
+                    pressedColor: JamiTheme.buttonConferencePressed
+
+                    source: "qrc:/images/icons/open_in_full-24px.svg"
+                    imageColor: hovered? JamiTheme.darkGreyColor
+                                       : JamiTheme.whiteColor
+
+                    onClicked: CallAdapter.maximizeParticipant(uri)
+                    onHoveredChanged: maximizeParticipantToolTip.visible = hovered
+
+                    Text {
+                        id: maximizeParticipantToolTip
+
+                        visible: false
+                        width: parent.width
+                        text: JamiStrings.maximizeParticipant
+                        horizontalAlignment: Text.AlignHCenter
+                        anchors.top: parent.bottom
+                        anchors.topMargin: 6
+                        color: JamiTheme.whiteColor
+                        font.pointSize: JamiTheme.tinyFontSize
+                    }
+                }
+
+                PushButton {
+                    id: minimizeParticipant
+
+                    visible: showMinimize
+                    Layout.preferredWidth: buttonPreferredSize
+                    Layout.preferredHeight: buttonPreferredSize
+                    preferredSize: 16
+
+                    normalColor: JamiTheme.buttonConference
+                    hoveredColor: JamiTheme.buttonConferenceHovered
+                    pressedColor: JamiTheme.buttonConferencePressed
+
+                    source: "qrc:/images/icons/close_fullscreen-24px.svg"
+                    imageColor: hovered? JamiTheme.darkGreyColor
+                                       : JamiTheme.whiteColor
+                    onClicked: CallAdapter.minimizeParticipant(uri)
+                    onHoveredChanged: minimizeParticipantToolTip.visible = hovered
+
+                    Text {
+                        id: minimizeParticipantToolTip
+
+                        visible: false
+                        width: parent.width
+                        text: JamiStrings.minimizeParticipant
+                        horizontalAlignment: Text.AlignHCenter
+                        anchors.top: parent.bottom
+                        anchors.topMargin: 6
+                        color: JamiTheme.whiteColor
+                        font.pointSize: JamiTheme.tinyFontSize
+                    }
+                }
+
+                PushButton {
+                    id: hangupParticipant
+
+                    visible: showHangup
+                    Layout.preferredWidth: buttonPreferredSize
+                    Layout.preferredHeight: buttonPreferredSize
+                    preferredSize: 16
+
+                    normalColor: JamiTheme.buttonConference
+                    hoveredColor: JamiTheme.buttonConferenceHovered
+                    pressedColor: JamiTheme.buttonConferencePressed
+
+                    source: "qrc:/images/icons/ic_block_24px.svg"
+                    imageColor: hovered? JamiTheme.darkGreyColor
+                                       : JamiTheme.whiteColor
+                    onClicked: CallAdapter.hangupCall(uri)
+                    onHoveredChanged: hangupParticipantToolTip.visible = hovered
+
+                    Text {
+                        id: hangupParticipantToolTip
+
+                        visible: false
+                        width: parent.width
+                        text: JamiStrings.hangupParticipant
+                        horizontalAlignment: Text.AlignHCenter
+                        anchors.top: parent.bottom
+                        anchors.topMargin: 6
+                        color: JamiTheme.whiteColor
+                        font.pointSize: JamiTheme.tinyFontSize
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/mainview/components/VideoCallPage.qml b/src/mainview/components/VideoCallPage.qml
index 4befacc2fb058f14269cb16a8f5fc88fc53257c4..45ad4d5bc9039b179762eb88c6272d3bf2a23572 100644
--- a/src/mainview/components/VideoCallPage.qml
+++ b/src/mainview/components/VideoCallPage.qml
@@ -191,6 +191,7 @@ Rectangle {
                                                                 isRecording, isSIP,
                                                                 isConferenceCall)
                             videoCallPageRect.bestName = bestName
+                            videoCallOverlay.handleParticipantsInfo(CallAdapter.getConferencesInfos())
                         }
 
                         function onShowOnHoldLabel(isPaused) {