diff --git a/resources/icons/ui/end-call.png b/resources/icons/ui/end-call.png
new file mode 100644
index 0000000000000000000000000000000000000000..6cbb983e8d289503098a46f627d8b0cefcd03ea8
--- /dev/null
+++ b/resources/icons/ui/end-call.png
@@ -0,0 +1,5 @@
+‰PNG
+
+���
IHDR���@���@���ªiqÞ���	pHYs�����šœ��5IDATxœíØÍ‹Ma�ðß¹(㣐$ÅJ)ÑH²aa=ÅÚBÄÆÒìåcïÛ_@YÐÌÊRBÙ‰L$_#¢‘ŒÅyOÍæÎœ{ç½Ç<¿zsë>_çÜ;羄B!„B!„ÿKÑ`­±
++±"|Oñ
“øˆ?M4Õ«¬Á^ìÂÖC¨ùþx‰)á!¾dï4“E8€Kxª¼zÓ™ãOÊ})ÕZÔÈd³(”Wø2ÞË?ð\ñ>Õޥُ²%Á³CäŠg©§Å=œÛ�Nb¢n©Ç¥u‡ªsë8‚‹ØT7qòñ¯ðoÓë?RÀ²«±±;°k;¬ûgpW¹˜®mǘúW`
+÷pBùÍŸã³Y`3Žã~vÐÏXš¡c-œVÔÉ-8ÞM±wØÓTš¥U·Àz<è°H?/ ŠûX7Wò}øÜe~_À4>a¸]âcø5äaÓʏÎLX`tžIÒª8‡b1Φ?þ7£Ê»Á¤<]hwÀ4&[~Žî3E2&ü1W5ÎS> \—ç–:œ±¹veêõŠGó]ÂW寱¦Œ¤šY†¯t»„[j<aõÀ nvØkÛá+-\«™è9ö䞪»Õ?›˜uøJWçHt[ýó½&,Å
†¯´[ÂoœÒŸÿ:åÏðßæ9|¥¥<©’¼ÃþLÍöÒ°òÐ¥êû‚.†Ÿi*ÏòŠåÊ‹5ô¯	!„B!„B!„¾ò÷x³%Ú®����IEND®B`‚
\ No newline at end of file
diff --git a/resources/icons/ui/microphone-mute.png b/resources/icons/ui/microphone-mute.png
new file mode 100644
index 0000000000000000000000000000000000000000..0042fbe2babc3815f79c30098e687d321f0b3da6
--- /dev/null
+++ b/resources/icons/ui/microphone-mute.png
@@ -0,0 +1,8 @@
+‰PNG
+
+���
IHDR���@���@���ªiqÞ���sBIT|dˆ���	pHYs�����šœ��#IDATxœí›É‹I‡¿n—qéÅ}pZO"
+.ƒ6¸‹Ìa^æ0"2Œ0
+"êMýô ¢ øxP¦]Û
E<ˆ(*82.ÓJƒÚ®m·¶‡xe™U•YYå{öâPõ¢¢ò‹Z2+2«‰Àà,ðø|Ú€SÀV`LÁm*DÀ!¶'ź€}ÀˆRZêA󀧤ƒGí0»„öªªx‡;|`o……·ZIÓ€²Ãö˜\pÛs«p•üð]�ê
+%È©5èÁ¶ÚGCë}þôs‰…OpXàáüÖjDÿ꟥œ·	[/ÏfE&'-§\øpRJÖS>|8	óÕÈ,µ)¦1EÃvHÌR	Ђo¦ª‘Y*oN¡ÿ³–½ò$ êá!{j²% fàÁ=5n	8IÁƒ}jìP³ðž€ª‡¯~†Äüž”�_ðCIP4\ª4¢Xfð‰K€/øUÀëÊo­H2¼i[¤1ÿ|L	hÁßmÿ$â³Ùȵ"4:²=Ö☓H9ëm‚OphH‰µ¸Ù7*²í4±â«$Hd&IU> 
ïE¾Pðà'—)>w·××Ñ¿Û°¯?ð!´}%%Fø÷‘í>].]}Çç½ò#Û#
>/]º&à¡aŸmÍM㶿Ùždð‰&)Q®	¸eØ7Ýâ8
økÈ4{X³~wsœ#U€Nô‹6ö»!öñˆO708+œ­ZÐÛÛØM _$vòÂû]ÈEf©?ÐÛÛØ{`¦!þNƒïßÙ±ì5”âà?¿â7 =RØ·‹¯¿J‘ükâ×6øôã*-øâ—Ŭ3ø@Š4¥Êþ	°骢¿=�ö#«Êâ´ˆ/{¡ÀviøÊ><hL¨X\y-¬ÅÀCÜH÷\šlàÿ'û,mð_wy=È‹pJŽ¶ç–
|;²d.‹¦ÿÄÄíD‰ÒäòÂ;/û[Ä­G9AºÁ¸±Á
+
ˆ¬ßÓYÇö¯€sÈGÍàyeÿp¤¾8ø…ä/ÌvàW
+õ™¤ÕÕe±V`œÄxÙ–®7!‹µÀہ
ø/â&ʵn?ØÜI9&Éþ¶�?ú†KSž¹º:`°©&­\Dêÿs)ùŠÒž¨¬Öb¬áË×,íJCœ¥:MvSZÆ·“ÜÕ=EþН®ª¥%`/òÌšTõð>/ЊŒàŽ!oõ@qð}‘JmZbM“ªcI2îcžŸðªfd¦'陏ù3WÛnSÒ_ëæ#ã¾êà>°}ZP.Scç+§á9Ûâ¢"Ïe­EHiÊ÷ÕïDñ?�Ú‹Š¦"‰è£7P72sÏSü^õªWß™>ÖÐëݼ©C����IEND®B`‚
\ No newline at end of file
diff --git a/resources/icons/ui/microphone-unmute.png b/resources/icons/ui/microphone-unmute.png
new file mode 100644
index 0000000000000000000000000000000000000000..27999c70500ed3564c15e3131b3ed7157a79ab78
--- /dev/null
+++ b/resources/icons/ui/microphone-unmute.png
@@ -0,0 +1,5 @@
+‰PNG
+
+���
IHDR���@���@���ªiqÞ���sBIT|dˆ���	pHYs�����šœ��çIDATxœíšIkA€¿$j4F—ãQƒàÅ7Œõ`@^\Pô ŠGу?ÀƒDE/âÁC@‘Ä=ˆxAÜ—`$!·hÆ,㡦u¬©žéš®ê2¦?x‡êyýê½7ݯkƒh™œ�Z€.`0%]@3p˜±O‘P	\†€d©N<µÀJ “܁ËÒ,wà¯QÖ?ÐÞ“ïÀšÈ½6D
ð…üƒ÷ä07bßCSÜ'|ðž´‘F’í˜Þ“-‘F’{˜O@K”„¡óÁ'ŸÐɦ-4mXjÁ&ˆ°Ø´Q	¨²`Óc¦iƒ60΂MÓm$`X'Àµ®‰àÚ×Ä	pí€kâ¸vÀ5qò¸§�±BSjØ—0L�ªÉcÑD7eÀ]àbÑr½n‡Ø|�^wÉ°Æ1þž£¿SèÂÎz@دè¯CÒ9¬î0]jÛœúešÔž¡ss\];àš8l¸\¯Ý·n×FKíDž¾¡Oj+túuê&à³âš¼TÝ¡iS‡÷R{ŠBGå£/º	P'ïÛ=Ô´©ƒl»Z¡#')+º	xª¸¶Dj·4íáb›=e
+½gúþM™‡n(ôö`~¸KÑO“¤3�Œeä]ß™ïb1âŸ0üc2‹m¢à¥ëµé“ÏgðºÔì–®%€hVd@ƒÂÖ^`T߬P…8Ç“žù¨+r=ÁÎùÉ °Ma·qp"]·ŸÌy5®’éìyÝ­@¯B?—|6ùؼ¬Ð¿.$=jGv¢>‹~³BßOnó|l5(ôâàÍ…#}Àjý‚ÔoÀ[Žo€sˆSe~Ô"j‚|ïÉP‘äI	ðDáÌ×”£¹(f§$ÈòZêWé0VËsƒ,D¬z$÷af¢T�$ó“—DÂùúE"`Õ»ÜD8k€›>¶{Ò"aêw3‰(–—ïvqG!¢V\!ós›^k6˜pÜä\~-p
˜”E§hE¼·íü™¹•#Æ‹'C+³Øè6“Ǩ/
+fc爜'­X8'dš"à�bth*ðnÄÐwX-á•GQóƒÊkà01bߍR¬N#^lÃâ^ÄÎÓ)`ÃìJ!°ƒÌà·ã `z×{R¿EÊùˆé0â ¯¨˜°WMîĪ6U«Cßl¯PïO8gf×ýä	š;ÀQшýà=9kÊi“5 Ü ­©¯ÀÔâ?-6)	ÄÀʦwv QdØ®Ç�pxnÉ~LLÌã5!TGï™äÐ����IEND®B`‚
\ No newline at end of file
diff --git a/resources/icons/ui/place-call.png b/resources/icons/ui/place-call.png
new file mode 100644
index 0000000000000000000000000000000000000000..a820cf3fceafebf30ed5915c48c5f785a931734b
--- /dev/null
+++ b/resources/icons/ui/place-call.png
@@ -0,0 +1,5 @@
+‰PNG
+
+���
IHDR���@���@���ªiqÞ���	pHYs�����šœ��©IDATxœíš=kTA†Ÿ«ñ‚š¤qêEüDe;+í,$­ä/(ùÚè/AÐb!
+QKcaa¡‰ZDü*Äb±	lt-&4Îܝ;w7óÀévξçÝÙ»gÎ,D"‘H$‰˜™ºÀ0°ˆ0$b« ‹]ácFBlôq3྄آl±xMß1÷”㺠ØðÓ1wËq]Pª4 î�jðK`cÀÇÜÛ€]ŽkƒacÀ»ùO•X–Kä?]bm6½6ìí zˆÁ{&¾ánB'¼d{l¾àYÕB¤°1�Ü
x¼r\;R øÖ´%ÄVA,a_ü[`·ˆÒ
+¹Î&.`øM~ñKÀ)!XÀ\ü2
/à"úâ?{ucøÀÿ¬uå2ú]ð˜œÿ}ŸÐ›pAPWP®¢7à0)¨+[—èM¸%¨+(ô}Á/ଠ® ÜA¿zÀ1A]Á˜Þ£7a…†ò8êt&,;䤅cs‹üû¹CmI€»˜Mx�l/™ÿäzŒìŒ1Euƒ&q{&´Q“¥,OxÜ�Î1b7Pã¨BM&¬�Gäk£&KÃf}Ôàö5ðu5?ƒ1-òE÷€3yl‹Ï‹9O5¦…¹S þns˜0¬÷Q|f¶ãÀ¨s„óü»U}Ÿ…()ù¿YÌ£&Ͼ‹7�Ô§;‹¹YÊbø8ä5µ4 ã8êªÝwµ1�ÔÙá6çˍ5 £C~¿Ðx@®`¯5Þ€Œ¸„ùXÝx2ÆP÷ø}FÔ’iàÅ.du±Z¸o`?ê.âð•btmÞ N$¨Ýq8¼‡PÿGœø+Ràê!û]Di$‰D"‘‘ç9~]üÈ����IEND®B`‚
\ No newline at end of file
diff --git a/resources/res.qrc b/resources/res.qrc
index 3fd3fc9658a071e2c06c5633f9d75d0b4c908d1e..b245f48fabe9abffbc69a39675245c4bc558693d 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -70,6 +70,11 @@
     
         <file>icons/ui/mail-reply.png</file>
 
+        <file>icons/ui/place-call.png</file>
+        <file>icons/ui/end-call.png</file>
+        <file>icons/ui/microphone-mute.png</file>
+        <file>icons/ui/microphone-unmute.png</file>
+
         <file>icons/emoji-categories/people.png</file>
         <file>icons/emoji-categories/people@2x.png</file>
         <file>icons/emoji-categories/nature.png</file>
diff --git a/src/ActiveCallBar.cpp b/src/ActiveCallBar.cpp
index a5ef754df7bda2b66b9a64fc6d716952f4851379..5703c1edf117677d1d117f4f98dfb072536a306e 100644
--- a/src/ActiveCallBar.cpp
+++ b/src/ActiveCallBar.cpp
@@ -1,10 +1,17 @@
+#include <cstdio>
+
+#include <QDateTime>
 #include <QHBoxLayout>
 #include <QIcon>
 #include <QLabel>
 #include <QString>
+#include <QTimer>
 
 #include "ActiveCallBar.h"
+#include "ChatPage.h"
+#include "Utils.h"
 #include "WebRTCSession.h"
+#include "ui/Avatar.h"
 #include "ui/FlatButton.h"
 
 ActiveCallBar::ActiveCallBar(QWidget *parent)
@@ -12,7 +19,7 @@ ActiveCallBar::ActiveCallBar(QWidget *parent)
 {
         setAutoFillBackground(true);
         auto p = palette();
-        p.setColor(backgroundRole(), Qt::green);
+        p.setColor(backgroundRole(), QColorConstants::Svg::limegreen);
         setPalette(p);
 
         QFont f;
@@ -24,51 +31,126 @@ ActiveCallBar::ActiveCallBar(QWidget *parent)
 
         setFixedHeight(contentHeight + widgetMargin);
 
-        topLayout_ = new QHBoxLayout(this);
-        topLayout_->setSpacing(widgetMargin);
-        topLayout_->setContentsMargins(
+        layout_ = new QHBoxLayout(this);
+        layout_->setSpacing(widgetMargin);
+        layout_->setContentsMargins(
           2 * widgetMargin, widgetMargin, 2 * widgetMargin, widgetMargin);
-        topLayout_->setSizeConstraint(QLayout::SetMinimumSize);
 
         QFont labelFont;
-        labelFont.setPointSizeF(labelFont.pointSizeF() * 1.2);
+        labelFont.setPointSizeF(labelFont.pointSizeF() * 1.1);
         labelFont.setWeight(QFont::Medium);
 
+        avatar_ = new Avatar(this, QFontMetrics(f).height() * 2.5);
+
         callPartyLabel_ = new QLabel(this);
         callPartyLabel_->setFont(labelFont);
 
-        // TODO microphone mute/unmute icons
+        stateLabel_ = new QLabel(this);
+        stateLabel_->setFont(labelFont);
+
+        durationLabel_ = new QLabel(this);
+        durationLabel_->setFont(labelFont);
+        durationLabel_->hide();
+
         muteBtn_ = new FlatButton(this);
-        QIcon muteIcon;
-        muteIcon.addFile(":/icons/icons/ui/do-not-disturb-rounded-sign.png");
-        muteBtn_->setIcon(muteIcon);
-        muteBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));
-        muteBtn_->setToolTip(tr("Mute Mic"));
+        setMuteIcon(false);
         muteBtn_->setFixedSize(buttonSize_, buttonSize_);
         muteBtn_->setCornerRadius(buttonSize_ / 2);
-        connect(muteBtn_, &FlatButton::clicked, this, [this]() {
-                if (WebRTCSession::instance().toggleMuteAudioSrc(muted_)) {
-                        QIcon icon;
-                        if (muted_) {
-                                muteBtn_->setToolTip("Unmute Mic");
-                                icon.addFile(":/icons/icons/ui/round-remove-button.png");
-                        } else {
-                                muteBtn_->setToolTip("Mute Mic");
-                                icon.addFile(":/icons/icons/ui/do-not-disturb-rounded-sign.png");
-                        }
-                        muteBtn_->setIcon(icon);
-                }
+        connect(muteBtn_, &FlatButton::clicked, this, [this](){
+                if (WebRTCSession::instance().toggleMuteAudioSrc(muted_))
+                    setMuteIcon(muted_);
         });
 
-        topLayout_->addWidget(callPartyLabel_, 0, Qt::AlignLeft);
-        topLayout_->addWidget(muteBtn_, 0, Qt::AlignRight);
+        layout_->addWidget(avatar_, 0, Qt::AlignLeft);
+        layout_->addWidget(callPartyLabel_, 0, Qt::AlignLeft);
+        layout_->addWidget(stateLabel_, 0, Qt::AlignLeft);
+        layout_->addWidget(durationLabel_, 0, Qt::AlignLeft);
+        layout_->addStretch();
+        layout_->addWidget(muteBtn_, 0, Qt::AlignCenter);
+        layout_->addSpacing(18);
+
+        timer_ = new QTimer(this);
+        connect(timer_, &QTimer::timeout, this,
+            [this](){
+              auto seconds = QDateTime::currentSecsSinceEpoch() - callStartTime_;
+              int s = seconds % 60;
+              int m = (seconds / 60) % 60;
+              int h = seconds / 3600;
+              char buf[12];
+              if (h)
+                snprintf(buf, sizeof(buf), "%.2d:%.2d:%.2d", h, m, s);
+              else
+                snprintf(buf, sizeof(buf), "%.2d:%.2d", m, s);
+              durationLabel_->setText(buf);
+        });
+
+        connect(&WebRTCSession::instance(), &WebRTCSession::stateChanged, this, &ActiveCallBar::update);
+}
+
+void
+ActiveCallBar::setMuteIcon(bool muted)
+{
+        QIcon icon;
+        if (muted) {
+                muteBtn_->setToolTip("Unmute Mic");
+                icon.addFile(":/icons/icons/ui/microphone-unmute.png");
+        } else {
+                muteBtn_->setToolTip("Mute Mic");
+                icon.addFile(":/icons/icons/ui/microphone-mute.png");
+        }
+        muteBtn_->setIcon(icon);
+        muteBtn_->setIconSize(QSize(buttonSize_, buttonSize_));
 }
 
 void
-ActiveCallBar::setCallParty(const QString &userid, const QString &displayName)
+ActiveCallBar::setCallParty(
+    const QString &userid,
+    const QString &displayName,
+    const QString &roomName,
+    const QString &avatarUrl)
 {
-        if (!displayName.isEmpty() && displayName != userid)
-                callPartyLabel_->setText("Active Call: " + displayName + " (" + userid + ")");
+        callPartyLabel_->setText(
+            (displayName.isEmpty() ? userid : displayName) + " -");
+
+        if (!avatarUrl.isEmpty())
+          avatar_->setImage(avatarUrl);
         else
-                callPartyLabel_->setText("Active Call: " + userid);
+          avatar_->setLetter(utils::firstChar(roomName));
+}
+
+void
+ActiveCallBar::update(WebRTCSession::State state)
+{
+        switch (state) {
+          case WebRTCSession::State::INITIATING:
+            stateLabel_->setText("Initiating call...");
+            break;
+          case WebRTCSession::State::INITIATED:
+            stateLabel_->setText("Call initiated...");
+            break;
+          case WebRTCSession::State::OFFERSENT:
+            stateLabel_->setText("Calling...");
+            break;
+          case WebRTCSession::State::CONNECTING:
+            stateLabel_->setText("Connecting...");
+            break;
+          case WebRTCSession::State::CONNECTED:
+            callStartTime_ = QDateTime::currentSecsSinceEpoch();
+            timer_->start(1000);
+            stateLabel_->setText("Active call:");
+            durationLabel_->setText("00:00");
+            durationLabel_->show();
+            muteBtn_->show();
+            break;
+          case WebRTCSession::State::DISCONNECTED:
+            timer_->stop();
+            callPartyLabel_->setText(QString());
+            stateLabel_->setText(QString());
+            durationLabel_->setText(QString());
+            durationLabel_->hide();
+            setMuteIcon(false);
+            break;
+          default:
+            break;
+        }
 }
diff --git a/src/ActiveCallBar.h b/src/ActiveCallBar.h
index dd01e2ad749841a1fbc7e5f456eae78b26ca6bf6..8440d7f3e5817392835abb486d0730ecbf14c777 100644
--- a/src/ActiveCallBar.h
+++ b/src/ActiveCallBar.h
@@ -2,9 +2,12 @@
 
 #include <QWidget>
 
+#include "WebRTCSession.h"
+
 class QHBoxLayout;
 class QLabel;
-class QString;
+class QTimer;
+class Avatar;
 class FlatButton;
 
 class ActiveCallBar : public QWidget
@@ -15,12 +18,24 @@ public:
         ActiveCallBar(QWidget *parent = nullptr);
 
 public slots:
-        void setCallParty(const QString &userid, const QString &displayName);
+        void update(WebRTCSession::State);
+        void setCallParty(
+            const QString &userid,
+            const QString &displayName,
+            const QString &roomName,
+            const QString &avatarUrl);
 
 private:
-        QHBoxLayout *topLayout_ = nullptr;
+        QHBoxLayout *layout_    = nullptr;
+        Avatar *avatar_         = nullptr;
         QLabel *callPartyLabel_ = nullptr;
+        QLabel *stateLabel_     = nullptr;
+        QLabel *durationLabel_  = nullptr;
         FlatButton *muteBtn_    = nullptr;
-        int buttonSize_         = 32;
+        int buttonSize_         = 22;
         bool muted_             = false;
+        qint64 callStartTime_   = 0;
+        QTimer *timer_          = nullptr;
+
+        void setMuteIcon(bool muted);
 };
diff --git a/src/CallManager.cpp b/src/CallManager.cpp
index 92af3b2f8c85081cd80592edbd9fc549ccef9b63..b5c59e081847cad6385046175940db3c09c56f34 100644
--- a/src/CallManager.cpp
+++ b/src/CallManager.cpp
@@ -68,9 +68,9 @@ CallManager::CallManager(QSharedPointer<UserSettings> userSettings)
               turnServerTimer_.setInterval(res.ttl * 1000 * 0.9);
       });
 
-  connect(&session_, &WebRTCSession::pipelineChanged, this,
-      [this](bool started) {
-        if (!started)
+  connect(&session_, &WebRTCSession::stateChanged, this,
+      [this](WebRTCSession::State state) {
+        if (state == WebRTCSession::State::DISCONNECTED)
           playRingtone("qrc:/media/media/callend.ogg", false);
         });
 
@@ -87,9 +87,9 @@ CallManager::sendInvite(const QString &roomid)
     if (onActiveCall())
       return;
 
-    std::vector<RoomMember> members(cache::getMembers(roomid.toStdString()));
-    if (members.size() != 2) {
-      emit ChatPage::instance()->showNotification("Voice/Video calls are limited to 1:1 rooms");
+    auto roomInfo = cache::singleRoomInfo(roomid.toStdString());
+    if (roomInfo.member_count != 2) {
+      emit ChatPage::instance()->showNotification("Voice calls are limited to 1:1 rooms.");
       return;
     }
 
@@ -105,11 +105,13 @@ CallManager::sendInvite(const QString &roomid)
 
     // TODO Add invite timeout
     generateCallID();
+    std::vector<RoomMember> members(cache::getMembers(roomid.toStdString()));
     const RoomMember &callee = members.front().user_id == utils::localUser() ? members.back() : members.front();
-    emit newCallParty(callee.user_id, callee.display_name);
+    emit newCallParty(callee.user_id, callee.display_name,
+            QString::fromStdString(roomInfo.name), QString::fromStdString(roomInfo.avatar_url));
     playRingtone("qrc:/media/media/ringback.ogg", true);
     if (!session_.createOffer()) {
-      emit ChatPage::instance()->showNotification("Problem setting up call");
+      emit ChatPage::instance()->showNotification("Problem setting up call.");
       endCall();
     }
 }
@@ -127,7 +129,7 @@ CallManager::hangUp()
 bool
 CallManager::onActiveCall()
 {
-  return session_.isActive();
+  return session_.state() != WebRTCSession::State::DISCONNECTED;
 }
 
 void CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
@@ -156,8 +158,8 @@ CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent)
   if (callInviteEvent.content.call_id.empty())
     return;
 
-  std::vector<RoomMember> members(cache::getMembers(callInviteEvent.room_id));
-  if (onActiveCall() || members.size() != 2) {
+  auto roomInfo = cache::singleRoomInfo(callInviteEvent.room_id);
+  if (onActiveCall() || roomInfo.member_count != 2) {
     emit newMessage(QString::fromStdString(callInviteEvent.room_id),
         CallHangUp{callInviteEvent.content.call_id, 0, CallHangUp::Reason::InviteTimeOut});
     return;
@@ -168,10 +170,18 @@ CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent)
   callid_ = callInviteEvent.content.call_id;
   remoteICECandidates_.clear();
 
-  const RoomMember &caller = members.front().user_id == utils::localUser() ? members.back() : members.front();
-  emit newCallParty(caller.user_id, caller.display_name);
-
-  auto dialog = new dialogs::AcceptCall(caller.user_id, caller.display_name, MainWindow::instance());
+  std::vector<RoomMember> members(cache::getMembers(callInviteEvent.room_id));
+  const RoomMember &caller =
+    members.front().user_id == utils::localUser() ? members.back() : members.front();
+  emit newCallParty(caller.user_id, caller.display_name,
+          QString::fromStdString(roomInfo.name), QString::fromStdString(roomInfo.avatar_url));
+
+  auto dialog = new dialogs::AcceptCall(
+      caller.user_id,
+      caller.display_name,
+      QString::fromStdString(roomInfo.name),
+      QString::fromStdString(roomInfo.avatar_url),
+      MainWindow::instance());
   connect(dialog, &dialogs::AcceptCall::accept, this,
       [this, callInviteEvent](){
         MainWindow::instance()->hideOverlay();
@@ -198,7 +208,7 @@ CallManager::answerInvite(const CallInvite &invite)
   session_.setStunServer(settings_->useStunServer() ? STUN_SERVER : "");
 
   if (!session_.acceptOffer(invite.sdp)) {
-    emit ChatPage::instance()->showNotification("Problem setting up call");
+    emit ChatPage::instance()->showNotification("Problem setting up call.");
     hangUp();
     return;
   }
@@ -232,6 +242,7 @@ CallManager::handleEvent(const RoomEvent<CallAnswer> &callAnswerEvent)
 
   if (!onActiveCall() && callAnswerEvent.sender == utils::localUser().toStdString() &&
       callid_ == callAnswerEvent.content.call_id) {
+    emit ChatPage::instance()->showNotification("Call answered on another device.");
     stopRingtone();
     MainWindow::instance()->hideOverlay();
     return;
@@ -240,7 +251,7 @@ CallManager::handleEvent(const RoomEvent<CallAnswer> &callAnswerEvent)
   if (onActiveCall() && callid_ == callAnswerEvent.content.call_id) {
     stopRingtone();
     if (!session_.acceptAnswer(callAnswerEvent.content.sdp)) {
-      emit ChatPage::instance()->showNotification("Problem setting up call");
+      emit ChatPage::instance()->showNotification("Problem setting up call.");
       hangUp();
     }
   }
diff --git a/src/CallManager.h b/src/CallManager.h
index 8a93241fe49f84508614a9a42f6f77c62a507d03..df83a87a085dc4dfdd3ad3f1a843b2076034ebcf 100644
--- a/src/CallManager.h
+++ b/src/CallManager.h
@@ -36,7 +36,11 @@ signals:
         void newMessage(const QString &roomid, const mtx::events::msg::CallAnswer&);
         void newMessage(const QString &roomid, const mtx::events::msg::CallHangUp&);
         void turnServerRetrieved(const mtx::responses::TurnServer&);
-        void newCallParty(const QString &userid, const QString& displayName);
+        void newCallParty(
+            const QString &userid,
+            const QString &displayName,
+            const QString &roomName,
+            const QString &avatarUrl);
 
 private slots:
         void retrieveTurnServer();
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 15b7c545364c9ee7ef783b0c68b344213bcb70d7..5b8ea4752de79838b4d49d4bc098074f4d2f487f 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -138,13 +138,13 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
         connect(
           &callManager_, &CallManager::newCallParty, activeCallBar_, &ActiveCallBar::setCallParty);
         connect(&WebRTCSession::instance(),
-                &WebRTCSession::pipelineChanged,
+                &WebRTCSession::stateChanged,
                 this,
-                [this](bool callStarted) {
-                        if (callStarted)
-                                activeCallBar_->show();
-                        else
+                [this](WebRTCSession::State state) {
+                        if (state == WebRTCSession::State::DISCONNECTED)
                                 activeCallBar_->hide();
+                        else
+                                activeCallBar_->show();
                 });
 
         // Splitter
@@ -469,22 +469,28 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
                 if (callManager_.onActiveCall()) {
                         callManager_.hangUp();
                 } else {
-                        if (cache::singleRoomInfo(current_room_.toStdString()).member_count != 2) {
-                                showNotification("Voice/Video calls are limited to 1:1 rooms");
+                        if (auto roomInfo =
+                            cache::singleRoomInfo(current_room_.toStdString());
+                              roomInfo.member_count != 2) {
+                                showNotification("Voice calls are limited to 1:1 rooms.");
                         } else {
                                 std::vector<RoomMember> members(
                                   cache::getMembers(current_room_.toStdString()));
                                 const RoomMember &callee =
                                   members.front().user_id == utils::localUser() ? members.back()
                                                                                 : members.front();
-                                auto dialog =
-                                  new dialogs::PlaceCall(callee.user_id, callee.display_name, MainWindow::instance());
+                                auto dialog = new dialogs::PlaceCall(
+                                    callee.user_id,
+                                    callee.display_name,
+                                    QString::fromStdString(roomInfo.name),
+                                    QString::fromStdString(roomInfo.avatar_url),
+                                    MainWindow::instance());
                                 connect(dialog, &dialogs::PlaceCall::voice, this, [this]() {
                                         callManager_.sendInvite(current_room_);
                                 });
-                                connect(dialog, &dialogs::PlaceCall::video, this, [this]() {
-                                        showNotification("Video calls not yet implemented");
-                                });
+                                /*connect(dialog, &dialogs::PlaceCall::video, this, [this]() {
+                                        showNotification("Video calls not yet implemented.");
+                                });*/
                                 utils::centerWidget(dialog, MainWindow::instance());
                                 dialog->show();
                         }
diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp
index 2be0b404100f5f1f4b1fc99e7a677437be7ebb76..d49fc746cf43db7b785cfe586ad1e18d12164565 100644
--- a/src/TextInputWidget.cpp
+++ b/src/TextInputWidget.cpp
@@ -31,7 +31,6 @@
 #include "Logging.h"
 #include "TextInputWidget.h"
 #include "Utils.h"
-#include "WebRTCSession.h"
 #include "ui/FlatButton.h"
 #include "ui/LoadingIndicator.h"
 
@@ -455,9 +454,9 @@ TextInputWidget::TextInputWidget(QWidget *parent)
         topLayout_->setContentsMargins(13, 1, 13, 0);
 
         callBtn_ = new FlatButton(this);
-        changeCallButtonState(false);
+        changeCallButtonState(WebRTCSession::State::DISCONNECTED);
         connect(&WebRTCSession::instance(),
-                &WebRTCSession::pipelineChanged,
+                &WebRTCSession::stateChanged,
                 this,
                 &TextInputWidget::changeCallButtonState);
 
@@ -664,17 +663,16 @@ TextInputWidget::paintEvent(QPaintEvent *)
 }
 
 void
-TextInputWidget::changeCallButtonState(bool callStarted)
+TextInputWidget::changeCallButtonState(WebRTCSession::State state)
 {
-        // TODO Telephone and HangUp icons - co-opt the ones below for now
         QIcon icon;
-        if (callStarted) {
-                callBtn_->setToolTip(tr("Hang up"));
-                icon.addFile(":/icons/icons/ui/remove-symbol.png");
-        } else {
+        if (state == WebRTCSession::State::DISCONNECTED) {
                 callBtn_->setToolTip(tr("Place a call"));
-                icon.addFile(":/icons/icons/ui/speech-bubbles-comment-option.png");
+                icon.addFile(":/icons/icons/ui/place-call.png");
+        } else {
+                callBtn_->setToolTip(tr("Hang up"));
+                icon.addFile(":/icons/icons/ui/end-call.png");
         }
         callBtn_->setIcon(icon);
-        callBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight));
+        callBtn_->setIconSize(QSize(ButtonHeight * 1.1, ButtonHeight * 1.1));
 }
diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h
index ae58f4e3fa594a2c6a6101386b0e58a09f4435d5..27dff57f7d00a51f3474a63fc823751b72da0196 100644
--- a/src/TextInputWidget.h
+++ b/src/TextInputWidget.h
@@ -26,6 +26,7 @@
 #include <QTextEdit>
 #include <QWidget>
 
+#include "WebRTCSession.h"
 #include "dialogs/PreviewUploadOverlay.h"
 #include "emoji/PickButton.h"
 #include "popups/SuggestionsPopup.h"
@@ -149,7 +150,7 @@ public slots:
         void openFileSelection();
         void hideUploadSpinner();
         void focusLineEdit() { input_->setFocus(); }
-        void changeCallButtonState(bool callStarted);
+        void changeCallButtonState(WebRTCSession::State);
 
 private slots:
         void addSelectedEmoji(const QString &emoji);
diff --git a/src/WebRTCSession.cpp b/src/WebRTCSession.cpp
index 4ef7a818807997589f783c352a2bc6260fcf79e8..5baed72e8b09da375a0d2781a62fa2e600ecac1b 100644
--- a/src/WebRTCSession.cpp
+++ b/src/WebRTCSession.cpp
@@ -11,6 +11,8 @@ extern "C" {
 #include "gst/webrtc/webrtc.h"
 }
 
+Q_DECLARE_METATYPE(WebRTCSession::State)
+
 namespace {
 bool gisoffer;
 std::string glocalsdp;
@@ -29,6 +31,12 @@ std::string::const_iterator  findName(const std::string &sdp, const std::string
 int getPayloadType(const std::string &sdp, const std::string &name);
 }
 
+WebRTCSession::WebRTCSession() : QObject()
+{
+  qRegisterMetaType<WebRTCSession::State>();
+  connect(this, &WebRTCSession::stateChanged, this, &WebRTCSession::setState);
+}
+
 bool
 WebRTCSession::init(std::string *errorMessage)
 {
@@ -54,14 +62,14 @@ WebRTCSession::init(std::string *errorMessage)
   nhlog::ui()->info("Initialised " + gstVersion);
 
   // GStreamer Plugins:
-  // Base:            audioconvert, audioresample, opus, playback, videoconvert, volume
+  // Base:            audioconvert, audioresample, opus, playback, volume
   // Good:            autodetect, rtpmanager, vpx
   // Bad:             dtls, srtp, webrtc
   // libnice [GLib]:  nice
   initialised_ = true;
   std::string strError = gstVersion + ": Missing plugins: ";
   const gchar *needed[] = {"audioconvert", "audioresample", "autodetect", "dtls", "nice",
-    "opus", "playback", "rtpmanager", "srtp", "videoconvert", "vpx", "volume", "webrtc", nullptr};
+    "opus", "playback", "rtpmanager", "srtp", "vpx", "volume", "webrtc", nullptr};
   GstRegistry *registry = gst_registry_get();
   for (guint i = 0; i < g_strv_length((gchar**)needed); i++) {
     GstPlugin *plugin = gst_registry_find_plugin(registry, needed[i]);
@@ -91,17 +99,19 @@ WebRTCSession::createOffer()
 }
 
 bool
-WebRTCSession::acceptOffer(const std::string& sdp)
+WebRTCSession::acceptOffer(const std::string &sdp)
 {
   nhlog::ui()->debug("Received offer:\n{}", sdp);
+  if (state_ != State::DISCONNECTED)
+    return false;
+
   gisoffer = false;
   glocalsdp.clear();
   gcandidates.clear();
 
   int opusPayloadType = getPayloadType(sdp, "opus"); 
-  if (opusPayloadType == -1) {
+  if (opusPayloadType == -1)
     return false;
-  }
 
   GstWebRTCSessionDescription *offer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_OFFER);
   if (!offer)
@@ -120,9 +130,11 @@ WebRTCSession::acceptOffer(const std::string& sdp)
 bool
 WebRTCSession::startPipeline(int opusPayloadType)
 {
-  if (isActive())
+  if (state_ != State::DISCONNECTED)
     return false;
 
+  emit stateChanged(State::INITIATING);
+
   if (!createPipeline(opusPayloadType))
     return false;
 
@@ -132,7 +144,12 @@ WebRTCSession::startPipeline(int opusPayloadType)
     nhlog::ui()->info("WebRTC: Setting STUN server: {}", stunServer_);
     g_object_set(webrtc_, "stun-server", stunServer_.c_str(), nullptr);
   }
-  addTurnServers();
+
+  for (const auto &uri : turnServers_) {
+    nhlog::ui()->info("WebRTC: Setting TURN server: {}", uri);
+    gboolean udata;
+    g_signal_emit_by_name(webrtc_, "add-turn-server", uri.c_str(), (gpointer)(&udata));
+  }
 
   // generate the offer when the pipeline goes to PLAYING
   if (gisoffer)
@@ -152,16 +169,14 @@ WebRTCSession::startPipeline(int opusPayloadType)
   GstStateChangeReturn ret = gst_element_set_state(pipe_, GST_STATE_PLAYING);
   if (ret == GST_STATE_CHANGE_FAILURE) {
     nhlog::ui()->error("WebRTC: unable to start pipeline");
-    gst_object_unref(pipe_);
-    pipe_ = nullptr;
-    webrtc_ = nullptr;
+    end();
     return false;
   }
 
   GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
   gst_bus_add_watch(bus, newBusMessage, this);
   gst_object_unref(bus);
-  emit pipelineChanged(true);
+  emit stateChanged(State::INITIATED);
   return true;
 }
 
@@ -180,10 +195,7 @@ WebRTCSession::createPipeline(int opusPayloadType)
   if (error) {
     nhlog::ui()->error("WebRTC: Failed to parse pipeline: {}", error->message);
     g_error_free(error);
-    if (pipe_) {
-      gst_object_unref(pipe_);
-      pipe_ = nullptr;
-    }
+    end();
     return false;
   }
   return true;
@@ -193,7 +205,7 @@ bool
 WebRTCSession::acceptAnswer(const std::string &sdp)
 {
   nhlog::ui()->debug("WebRTC: Received sdp:\n{}", sdp);
-  if (!isActive())
+  if (state_ != State::OFFERSENT)
     return false;
 
   GstWebRTCSessionDescription *answer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_ANSWER);
@@ -206,18 +218,20 @@ WebRTCSession::acceptAnswer(const std::string &sdp)
 }
 
 void
-WebRTCSession::acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate>& candidates)
+WebRTCSession::acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate> &candidates)
 {
-  if (isActive()) {
-    for (const auto& c : candidates)
+  if (state_ >= State::INITIATED) {
+    for (const auto &c : candidates)
       g_signal_emit_by_name(webrtc_, "add-ice-candidate", c.sdpMLineIndex, c.candidate.c_str());
   }
+  if (state_ < State::CONNECTED)
+    emit stateChanged(State::CONNECTING);
 }
 
 bool
 WebRTCSession::toggleMuteAudioSrc(bool &isMuted)
 {
-  if (!isActive())
+  if (state_ < State::INITIATED)
     return false;
 
   GstElement *srclevel = gst_bin_get_by_name(GST_BIN(pipe_), "srclevel");
@@ -241,20 +255,7 @@ WebRTCSession::end()
     pipe_ = nullptr;
   }
   webrtc_ = nullptr;
-  emit pipelineChanged(false);
-}
-
-void
-WebRTCSession::addTurnServers()
-{
-  if (!webrtc_)
-    return;
-
-  for (const auto &uri : turnServers_) {
-    nhlog::ui()->info("WebRTC: Setting TURN server: {}", uri);
-    gboolean udata;
-    g_signal_emit_by_name(webrtc_, "add-turn-server", uri.c_str(), (gpointer)(&udata));
-  }
+  emit stateChanged(State::DISCONNECTED);
 }
 
 namespace {
@@ -373,8 +374,10 @@ gboolean
 onICEGatheringCompletion(gpointer timerid)
 {
   *(guint*)(timerid) = 0;
-  if (gisoffer)
+  if (gisoffer) {
     emit WebRTCSession::instance().offerCreated(glocalsdp, gcandidates);
+    emit WebRTCSession::instance().stateChanged(WebRTCSession::State::OFFERSENT);
+  }
   else
     emit WebRTCSession::instance().answerCreated(glocalsdp, gcandidates);
 
@@ -445,6 +448,9 @@ linkNewPad(GstElement *decodebin G_GNUC_UNUSED, GstPad *newpad, GstElement *pipe
   if (queuepad) {
     if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, queuepad)))
       nhlog::ui()->error("WebRTC: Unable to link new pad");
+    else {
+      emit WebRTCSession::instance().stateChanged(WebRTCSession::State::CONNECTED);
+    }
     gst_object_unref(queuepad);
   }
 }
diff --git a/src/WebRTCSession.h b/src/WebRTCSession.h
index fffefb254c993e189a8de3e0f03d23a439d31b96..42db204d00d788e88fea7fa8fb89323c9e3244a3 100644
--- a/src/WebRTCSession.h
+++ b/src/WebRTCSession.h
@@ -14,6 +14,15 @@ class WebRTCSession : public QObject
         Q_OBJECT
 
 public:
+        enum class State {
+          DISCONNECTED,
+          INITIATING,
+          INITIATED,
+          OFFERSENT,
+          CONNECTING,
+          CONNECTED
+        };
+
         static WebRTCSession& instance()
         {
           static WebRTCSession instance;
@@ -27,7 +36,7 @@ public:
         bool acceptAnswer(const std::string &sdp);
         void acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate>&);
 
-        bool isActive() { return pipe_ != nullptr; }
+        State state() const {return state_;} 
         bool toggleMuteAudioSrc(bool &isMuted);
         void end();
 
@@ -37,12 +46,16 @@ public:
 signals:
         void offerCreated(const std::string &sdp, const std::vector<mtx::events::msg::CallCandidates::Candidate>&);
         void answerCreated(const std::string &sdp, const std::vector<mtx::events::msg::CallCandidates::Candidate>&);
-        void pipelineChanged(bool started);
+        void stateChanged(WebRTCSession::State); // explicit qualifier necessary for Qt
+
+private slots:
+        void setState(State state) {state_ = state;}
 
 private:
-        WebRTCSession() : QObject() {}
+        WebRTCSession();
 
         bool initialised_ = false;
+        State state_ = State::DISCONNECTED;
         GstElement *pipe_ = nullptr;
         GstElement *webrtc_ = nullptr;
         std::string stunServer_;
@@ -50,7 +63,6 @@ private:
 
         bool startPipeline(int opusPayloadType);
         bool createPipeline(int opusPayloadType);
-        void addTurnServers();
 
 public:
         WebRTCSession(WebRTCSession const&) = delete;
diff --git a/src/dialogs/AcceptCall.cpp b/src/dialogs/AcceptCall.cpp
index f04a613a33d1e7e2a245225a5a81e71e00bc379e..6b5e2e60d81848eb4ebf043a85b3eb7ff5b2f875 100644
--- a/src/dialogs/AcceptCall.cpp
+++ b/src/dialogs/AcceptCall.cpp
@@ -1,43 +1,83 @@
 #include <QLabel>
 #include <QPushButton>
+#include <QString>
 #include <QVBoxLayout>
 
 #include "Config.h"
+#include "Utils.h"
 #include "dialogs/AcceptCall.h"
+#include "ui/Avatar.h"
 
 namespace dialogs {
 
-AcceptCall::AcceptCall(const QString &caller, const QString &displayName, QWidget *parent)
-  : QWidget(parent)
+AcceptCall::AcceptCall(
+    const QString &caller,
+    const QString &displayName,
+    const QString &roomName,
+    const QString &avatarUrl,
+    QWidget *parent) : QWidget(parent)
 {
         setAutoFillBackground(true);
         setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
         setWindowModality(Qt::WindowModal);
         setAttribute(Qt::WA_DeleteOnClose, true);
 
+        setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
+        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+
         auto layout = new QVBoxLayout(this);
         layout->setSpacing(conf::modals::WIDGET_SPACING);
         layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(15);
-        buttonLayout->setMargin(0);
+        QFont f;
+        f.setPointSizeF(f.pointSizeF());
+
+        QFont labelFont;
+        labelFont.setWeight(QFont::Medium);
+
+        QLabel *displayNameLabel = nullptr;
+        if (!displayName.isEmpty() && displayName != caller) {
+                displayNameLabel = new QLabel(displayName, this);
+                labelFont.setPointSizeF(f.pointSizeF() * 2);
+                displayNameLabel ->setFont(labelFont);
+                displayNameLabel ->setAlignment(Qt::AlignCenter);
+        }
 
+        QLabel *callerLabel = new QLabel(caller, this);
+        labelFont.setPointSizeF(f.pointSizeF() * 1.2);
+        callerLabel->setFont(labelFont);
+        callerLabel->setAlignment(Qt::AlignCenter);
+
+        QLabel *voiceCallLabel = new QLabel("Voice Call", this);
+        labelFont.setPointSizeF(f.pointSizeF() * 1.1);
+        voiceCallLabel->setFont(labelFont);
+        voiceCallLabel->setAlignment(Qt::AlignCenter);
+
+        auto avatar = new Avatar(this, QFontMetrics(f).height() * 6);
+        if (!avatarUrl.isEmpty())
+          avatar->setImage(avatarUrl);
+        else
+          avatar->setLetter(utils::firstChar(roomName));
+
+        const int iconSize = 24;
+        auto buttonLayout = new QHBoxLayout();
+        buttonLayout->setSpacing(20);
         acceptBtn_ = new QPushButton(tr("Accept"), this);
         acceptBtn_->setDefault(true);
-        rejectBtn_ = new QPushButton(tr("Reject"), this);
+        acceptBtn_->setIcon(QIcon(":/icons/icons/ui/place-call.png"));
+        acceptBtn_->setIconSize(QSize(iconSize, iconSize));
 
-        buttonLayout->addStretch(1);
+        rejectBtn_ = new QPushButton(tr("Reject"), this);
+        rejectBtn_->setIcon(QIcon(":/icons/icons/ui/end-call.png"));
+        rejectBtn_->setIconSize(QSize(iconSize, iconSize));
         buttonLayout->addWidget(acceptBtn_);
         buttonLayout->addWidget(rejectBtn_);
 
-        QLabel *label;
-        if (!displayName.isEmpty() && displayName != caller)
-                label = new QLabel("Accept call from " + displayName + " (" + caller + ")?", this);
-        else
-                label = new QLabel("Accept call from " + caller + "?", this);
-
-        layout->addWidget(label);
+        if (displayNameLabel)
+          layout->addWidget(displayNameLabel, 0, Qt::AlignCenter);
+        layout->addWidget(callerLabel, 0, Qt::AlignCenter);
+        layout->addWidget(voiceCallLabel, 0, Qt::AlignCenter);
+        layout->addWidget(avatar, 0, Qt::AlignCenter);
         layout->addLayout(buttonLayout);
 
         connect(acceptBtn_, &QPushButton::clicked, this, [this]() {
diff --git a/src/dialogs/AcceptCall.h b/src/dialogs/AcceptCall.h
index a410d6b79b7e31d4bb21f32390b3988d1fa606ab..8e3ed3b2b74dd9c6dbb0205b03f101151ce0cf0c 100644
--- a/src/dialogs/AcceptCall.h
+++ b/src/dialogs/AcceptCall.h
@@ -1,9 +1,9 @@
 #pragma once
 
-#include <QString>
 #include <QWidget>
 
 class QPushButton;
+class QString;
 
 namespace dialogs {
 
@@ -12,7 +12,12 @@ class AcceptCall : public QWidget
         Q_OBJECT
 
 public:
-        AcceptCall(const QString &caller, const QString &displayName, QWidget *parent = nullptr);
+        AcceptCall(
+            const QString &caller,
+            const QString &displayName,
+            const QString &roomName,
+            const QString &avatarUrl,
+            QWidget *parent = nullptr);
 
 signals:
         void accept();
diff --git a/src/dialogs/PlaceCall.cpp b/src/dialogs/PlaceCall.cpp
index 8b37ff6af923b2f134aa179288b6680cafbf1e6d..c5c78f94059ece043cf1ea87c080d290d9467471 100644
--- a/src/dialogs/PlaceCall.cpp
+++ b/src/dialogs/PlaceCall.cpp
@@ -4,12 +4,18 @@
 #include <QVBoxLayout>
 
 #include "Config.h"
+#include "Utils.h"
 #include "dialogs/PlaceCall.h"
+#include "ui/Avatar.h"
 
 namespace dialogs {
 
-PlaceCall::PlaceCall(const QString &callee, const QString &displayName, QWidget *parent)
-  : QWidget(parent)
+PlaceCall::PlaceCall(
+    const QString &callee,
+    const QString &displayName,
+    const QString &roomName,
+    const QString &avatarUrl,
+    QWidget *parent) : QWidget(parent)
 {
         setAutoFillBackground(true);
         setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
@@ -20,25 +26,31 @@ PlaceCall::PlaceCall(const QString &callee, const QString &displayName, QWidget
         layout->setSpacing(conf::modals::WIDGET_SPACING);
         layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
+        auto buttonLayout = new QHBoxLayout(this);
         buttonLayout->setSpacing(15);
         buttonLayout->setMargin(0);
 
+        QFont f;
+        f.setPointSizeF(f.pointSizeF());
+        auto avatar = new Avatar(this, QFontMetrics(f).height() * 3);
+        if (!avatarUrl.isEmpty())
+          avatar->setImage(avatarUrl);
+        else
+          avatar->setLetter(utils::firstChar(roomName));
+
         voiceBtn_ = new QPushButton(tr("Voice Call"), this);
         voiceBtn_->setDefault(true);
-        videoBtn_  = new QPushButton(tr("Video Call"), this);
+        //videoBtn_  = new QPushButton(tr("Video Call"), this);
         cancelBtn_ = new QPushButton(tr("Cancel"), this);
 
         buttonLayout->addStretch(1);
+        buttonLayout->addWidget(avatar);
         buttonLayout->addWidget(voiceBtn_);
-        buttonLayout->addWidget(videoBtn_);
+        //buttonLayout->addWidget(videoBtn_);
         buttonLayout->addWidget(cancelBtn_);
 
-        QLabel *label;
-        if (!displayName.isEmpty() && displayName != callee)
-                label = new QLabel("Place a call to " + displayName + " (" + callee + ")?", this);
-        else
-                label = new QLabel("Place a call to " + callee + "?", this);
+        QString name = displayName.isEmpty() ? callee : displayName;
+        QLabel *label = new QLabel("Place a call to " + name + "?", this);
 
         layout->addWidget(label);
         layout->addLayout(buttonLayout);
@@ -47,10 +59,10 @@ PlaceCall::PlaceCall(const QString &callee, const QString &displayName, QWidget
                 emit voice();
                 emit close();
         });
-        connect(videoBtn_, &QPushButton::clicked, this, [this]() {
+        /*connect(videoBtn_, &QPushButton::clicked, this, [this]() {
                 emit video();
                 emit close();
-        });
+        });*/
         connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
                 emit cancel();
                 emit close();
diff --git a/src/dialogs/PlaceCall.h b/src/dialogs/PlaceCall.h
index b4de1428c9ca18aab6c058e2e71bd475d15b67cd..1c157b7b4d13eb244e55252703164efc04b3b0ad 100644
--- a/src/dialogs/PlaceCall.h
+++ b/src/dialogs/PlaceCall.h
@@ -12,16 +12,21 @@ class PlaceCall : public QWidget
         Q_OBJECT
 
 public:
-        PlaceCall(const QString &callee, const QString &displayName, QWidget *parent = nullptr);
+        PlaceCall(
+            const QString &callee,
+            const QString &displayName,
+            const QString &roomName,
+            const QString &avatarUrl,
+            QWidget *parent = nullptr);
 
 signals:
         void voice();
-        void video();
+//        void video();
         void cancel();
 
 private:
         QPushButton *voiceBtn_;
-        QPushButton *videoBtn_;
+//        QPushButton *videoBtn_;
         QPushButton *cancelBtn_;
 };