From f631742bf9ab3fc5ebc11715c0f26f8a6737f099 Mon Sep 17 00:00:00 2001
From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Thu, 27 Sep 2018 17:08:20 -0400
Subject: [PATCH] call: implement leave message view

Change-Id: Ie4ab6134d39907d108e6a5bf39a863cb56ede684
Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
---
 CMakeLists.txt                   |   7 +
 data/dark/ic_audio_file.png      | Bin 0 -> 756 bytes
 data/dark/ic_exit.png            | Bin 0 -> 399 bytes
 data/dark/ic_stoprecord.png      | Bin 0 -> 1162 bytes
 src/AppDelegate.mm               |   2 +-
 src/ConversationVC.h             |  18 ++-
 src/ConversationVC.mm            |  34 +++-
 src/LeaveMessageVC.h             |  45 ++++++
 src/LeaveMessageVC.mm            | 203 ++++++++++++++++++++++++
 src/LrcModelsProtocol.h          |   3 +
 src/MessagesVC.mm                |  76 +++++----
 src/RingWindowController.mm      |  34 ++--
 ui/Base.lproj/LeaveMessageVC.xib | 257 +++++++++++++++++++++++++++++++
 13 files changed, 630 insertions(+), 49 deletions(-)
 create mode 100644 data/dark/ic_audio_file.png
 create mode 100644 data/dark/ic_exit.png
 create mode 100644 data/dark/ic_stoprecord.png
 create mode 100644 src/LeaveMessageVC.h
 create mode 100644 src/LeaveMessageVC.mm
 create mode 100644 ui/Base.lproj/LeaveMessageVC.xib

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9360a1bb..8cfc8850 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -167,6 +167,8 @@ SET(ringclient_CONTROLLERS
    src/AddSIPAccountVC.h
    src/AccountSettingsVC.mm
    src/AccountSettingsVC.h
+   src/LeaveMessageVC.mm
+   src/LeaveMessageVC.h
 )
 
 SET(ringclient_BACKENDS
@@ -261,6 +263,7 @@ SET(ringclient_XIBS
    MessageCells
    AddSIPAccountVC
    AccountSettings
+   LeaveMessageVC
 )
 
 # Icons
@@ -269,6 +272,10 @@ SET(myApp_ICON ${CMAKE_CURRENT_SOURCE_DIR}/data/appicon.icns)
 SET_SOURCE_FILES_PROPERTIES(${myApp_ICON} PROPERTIES
        MACOSX_PACKAGE_LOCATION Resources)
 SET(ring_ICONS
+${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_audio_file.png
+${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_exit.png
+${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_stoprecord.png
+${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_audio.png
 ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_audio.png
 ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_folder.png
 ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_block.png
diff --git a/data/dark/ic_audio_file.png b/data/dark/ic_audio_file.png
new file mode 100644
index 0000000000000000000000000000000000000000..6130da1025bad9198cfcf4a3109349a611d8bbbd
GIT binary patch
literal 756
zcmeAS@N?(olHy`uVBq!ia0y~yVDJWE4mJh`1`EHcR}2gcY)RhkE)4%caKYZ?lNlJ8
zR(iTPhE&XXd)vN;*HPxc$MdqCbDaM4yD6zeaS1ssUbHy;ZmZX#3llUZXk5^8;jk3y
zbqW!>su{q^+3Doy)Y#PLQP5R8ea`7t^Y{1um8IwJJE@ZY{cqW`?f1{TIk)Go`@(<|
z9h+z5Iqqz{Smj?@CzV;!*z<T7ThaMIF<wsTEgOp^IQ5D-#iwPTpQRWQv2Ih|nO`=2
z*-YnD!z0}bQm=h$X^@+?dQGOx=j|JAwWqAxl;IF@ZWD*twB0&Pt)-4)j)!(Bbu%Q!
zPI5haXqQ^IRBLIVm?`J$RXSM$*HR;SA|tM+8oDHUx6cSsQD?V!W^0#Rn_nHH`bnei
zd$8lWO?o^l=W*^i@U*T;{IJ0v`Rrf3XI7@i$|S{BZ&d%fU{1<hsifF+UWL^>hgrJT
zfY7aqvr+BL5{JWU4tigeSs8ds<F#Gc`J3jwnsbg_e$kSa@z~&w&G~(TZw@D4H9p+C
zQ1WZW;x+Y#i=vk8Ib7_M6dm$7SElW+LD$>8n_Nv#@?@Hnhq;?xVU0}O5_!$v=5X|%
zEDP~1(bvM?1l*Mke_$}rWM;tZ)U(f|->nea|NA4u{p$O^uBsCs-~EudUguy`O;?u1
z^m(T8`&qh_@*^LLL~@Ema&8F>%g(pToxIiS!6((JW+$Z%R(}5PxIon8;?wXXakCXw
zm!xtI`Q_v)%-`2JWoyXSH}55;v2L?AQA(9P-r4eF-#z;dl~1!uH4Ohb>qhD{ctj?5
zeq5h*GKtaURMmWm`pwgH#2l8axy`w8az#kEQnQfe>v^wKx5)qR__?+!{8fgBTc^wU
z&3X^T_*T`i#&$nlwfyY*Lh<~j;#afP)RxK@ZVlhG$oKTzYr!e10l1ODi(4Oj*6V0_
jo%dRBLQ90p@*{g)Sa${wcYz!O0|SGntDnm{r-UW|+rCbF

literal 0
HcmV?d00001

diff --git a/data/dark/ic_exit.png b/data/dark/ic_exit.png
new file mode 100644
index 0000000000000000000000000000000000000000..4139f44e2b97c0d21fd7ccd02d502a3be43c73fe
GIT binary patch
literal 399
zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hE<t`_ZS!$*pj^6T^Rm@;DWu&Co?cG
zx_G)chE&XXJImYeuz`pxe+Or@<DamDe3H}dDlQS5VZ_7y#H%-Ip~|-RoA239O82~X
zcH-kBeFr6yed5-M$yl3uZ|qaOsb3WPSV=jV@fAZ>p4pt}r;;%alMOX$`8P0>GMI`j
z;9GEv=?Y`mr?nbZXJ@VYCs!eKg<tUj^A6!Fc5DG$77X8;cDY|+n#XGDAHY51v&VBs
zn@J7g57;XfFK*FbI(2rs%v}{1fdcM5^G|MC+}y&!^dR5hkIm%emHr({3@$=SoD7XE
z8B7Z{w`^s4_WWy>wbuIRKD7j<xS#HaR$NZxT>Q1cpx?o}O@bwQ;xE$~znnF`F5jT;
ztTLZZJV?Jo<dSZuEl1Y81!5EGB5Ra>_D>8l|GIwTrF~hkC8ymyzp82GPg&E*x`KJd
zMv!M-vgX{>mPvHlGV_b=0j4XAJ%-05WcLfmsL$S%UG|iLfq}u()z4*}Q$iB};s2c7

literal 0
HcmV?d00001

diff --git a/data/dark/ic_stoprecord.png b/data/dark/ic_stoprecord.png
new file mode 100644
index 0000000000000000000000000000000000000000..085d7e14ffd4ee8f590aa617c97a95a49f09a405
GIT binary patch
literal 1162
zcmeAS@N?(olHy`uVBq!ia0y~yV2A=?4mJh`28$JrObiSRY)RhkE)4%caKYZ?lNlIT
z>^)r^Ln`LHo$H$)>MC)(e%h<t%Zp6!I%Fp;j3_%=;@!DKWZR=fvsT>Y)X91joh2Mz
z$8u>&JcAtrr;duip(fUrD;cTEI#*i1_U>ae{c>#Ijv3A-*W*6VF+P80j&XV2N&9l+
z?|1(HDSl_0{>;W$T&UAUX`+XUP^ZhHB{t%>4(PpMbZba_U|_%^!?LSk`sVNk`^Kwp
zzOp~C`@j&vu#a)uo?YuW)-%X6hc~z%=v#WN;q(D_hyBOvrcCln5Zcja`8(%u?lRv8
zQXlLtJY1Ttx=^}!neHRKJ88d|e+X5aELC^@WMjaq^Vt4@n=bSG)Om{@Nfh*dU^IVK
zop2{{|K5v?XBcm{@Nb>Dtub=JGY#hFJPhR=@=HSEncHJn9!@GO$-7*W%_~tnp<VbM
z(>x)&EsIt$zhAL@(V56Q_k@365-V`Cls5HCW@BIIe2M3G?$s6%31%}6`Mzzh4rm^o
zv!<dqEAGdVC}y^+m$W>1i=#!Xc&^V<|4{qwj^47Qt80SNc3Qgabg#K}i|t;3ryl#;
z8JyoP%>BN$x?*0(tg;K8t6m7V{&6W`_Lj2>3DZrLe6mRQy>x@-g6#)>CoL4Wc>c@T
zs`35>OXF7uo;%FXzI-$NOv?O~5C4kG*o(~$G1}Gqaz}oe&L6W^w$t6#YfIgIe<?%w
zTjY=2E8**WzAd)S6yehSAN@ol^+d7ZoC6};Rd{k|>?|)#)>Qvg-6{8VxnZ@z)9|SH
z-4b<HWd<`l_C391T*dN2a9gfwRl{{v-ldN6n(tJr+Eja&IPynIbjk*rU0T2&4P~%*
z{qC5@Jjw0Sg2n6hZE=~>Yw}{Rm|K!Nh;irhdfk?+3!L6d9M@Zy2IkK5kn(I6lU?H)
z$op$z>%<#^smi>+mOrvv^xWN3IrGAI-JT<T8nZ>V*sgM{Pft`S3)$=`{C}R>zwHgt
zhqkRf;@i^w`*ROZzQ|`GQ$M4Z%2TEPM9-dKC8!<~Z1QTc$eM|D-1~b^g*r?w4|?fz
z?%V(4OCD`>s(I#mH2H74--Gaya~)R8#MX7W_H|d>_`P^)_l5Z{gI|lVmN4=&m#ov#
z3h9VjGVPuInL{%#>6CmqBVHjByoLF`(7!jIbl-QkGPrr3zQ4y%+d!iGoOWthhg90n
zycYs7uk}7O1*Nr09?|jPmu=HttF*@L)4{@3dtdt)Uu~RRW%%-g+Q-};qlL33D5ZBK
zub%Jwfca_86-(c(^=@Vw55?@yN-Ulwej@bD*JVL_xbCRcR0N$3Zqlvo3OdY_b;_pc
z&M_Xhru*vI240rtL6Ho7R&UA$ZW+$*nv&S{RWXhKb=h)TJ|FRAlkFedKe%rwUAq6p
zuF0v3m^X_a4!y%yVrIx6bbsm5ZS(H;{yorsKsAB&cR~23WZ#DyR22AA|5i^>p0RYl
z^Gv>keeZ1le3r<REnfdmBG~FTLvX>437UUxJ)jv_X`+Y64{5fRd7J+&E>mY<U|{fc
L^>bP0l+XkKl~xvM

literal 0
HcmV?d00001

diff --git a/src/AppDelegate.mm b/src/AppDelegate.mm
index cee31395..134a457c 100644
--- a/src/AppDelegate.mm
+++ b/src/AppDelegate.mm
@@ -319,7 +319,7 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet
 - (void) showMainWindow
 {
     if(self.ringWindowController == nil) {
-        self.ringWindowController = [[RingWindowController alloc] initWithWindowNibName:@"RingWindow" bundle: nil accountModel:&lrc->getAccountModel() dataTransferModel:&lrc->getDataTransferModel() behaviourController:&lrc->getBehaviorController()];
+        self.ringWindowController = [[RingWindowController alloc] initWithWindowNibName:@"RingWindow" bundle: nil accountModel:&lrc->getAccountModel() dataTransferModel:&lrc->getDataTransferModel() behaviourController:&lrc->getBehaviorController() avModel: &lrc->getAVModel()];
     }
     [[NSApplication sharedApplication] removeWindowsItem:self.wizard.window];
     [self.ringWindowController.window makeKeyAndOrderFront:self];
diff --git a/src/ConversationVC.h b/src/ConversationVC.h
index c56b1009..c6e5860e 100644
--- a/src/ConversationVC.h
+++ b/src/ConversationVC.h
@@ -18,12 +18,19 @@
  */
 
 #import <Cocoa/Cocoa.h>
-#import <api/conversation.h>
-#import <api/conversationmodel.h>
+#import <string>
 
+namespace lrc {
+    namespace api {
+        class AVModel;
+        class ConversationModel;
+    }
+}
 @class RingWindowController;
+@class LeaveMessageVC;
+@protocol LeaveMessageDelegate;
 
-@interface ConversationVC : NSViewController
+@interface ConversationVC : NSViewController <LeaveMessageDelegate>
 
 -(void) initFrame;
 -(void) showWithAnimation:(BOOL)animate;
@@ -31,6 +38,9 @@
 
 - (void) setConversationUid:(const std::string)convUid model:(lrc::api::ConversationModel*)model;
 
-- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(RingWindowController*) mainWindow;
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(RingWindowController*) mainWindow aVModel:(lrc::api::AVModel*) avModel;
+- (void) presentLeaveMessageView;
+
+-(NSViewController*) getMessagesView;
 
 @end
diff --git a/src/ConversationVC.mm b/src/ConversationVC.mm
index 9d2fe89c..f787e15c 100644
--- a/src/ConversationVC.mm
+++ b/src/ConversationVC.mm
@@ -36,8 +36,12 @@
 #import "utils.h"
 #import "RingWindowController.h"
 #import "NSString+Extensions.h"
+#import "LeaveMessageVC.h"
+#import <QuickLook/QuickLook.h>
+#import <Quartz/Quartz.h>
+#import "LeaveMessageVC.h"
 
-@interface ConversationVC () {
+@interface ConversationVC () <QLPreviewPanelDataSource, QLPreviewPanelDelegate>{
 
     __unsafe_unretained IBOutlet NSTextField* conversationTitle;
     __unsafe_unretained IBOutlet NSTextField *conversationID;
@@ -46,6 +50,7 @@
 
     __unsafe_unretained IBOutlet NSButton* sentContactRequestButton;
     IBOutlet MessagesVC* messagesViewVC;
+    LeaveMessageVC* leaveMessageVC;
 
     IBOutlet NSLayoutConstraint *titleCenteredConstraint;
     IBOutlet NSLayoutConstraint* titleTopConstraint;
@@ -55,6 +60,7 @@
     lrc::api::ConversationModel* convModel_;
 
     RingWindowController* delegate;
+    NSMutableArray* leaveMessageConversations;
 
     // All those connections are needed to invalidate cached conversation as pointer
     // may not be referencing the same conversation anymore
@@ -69,15 +75,26 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
 
 @implementation ConversationVC
 
-- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(RingWindowController*) mainWindow
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(RingWindowController*) mainWindow aVModel:(lrc::api::AVModel*) avModel
 {
     if (self = [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
     {
         delegate = mainWindow;
+        leaveMessageVC = [[LeaveMessageVC alloc] initWithNibName:@"LeaveMessageVC" bundle:nil];
+        [[leaveMessageVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+        [self.view addSubview:[leaveMessageVC view] positioned:NSWindowAbove relativeTo:nil];
+        [leaveMessageVC initFrame];
+        [leaveMessageVC setAVModel: avModel];
+        leaveMessageConversations = [[NSMutableArray alloc] init];
+        leaveMessageVC.delegate = self;
     }
     return self;
 }
 
+-(NSViewController*) getMessagesView {
+    return messagesViewVC;
+}
+
 -(void) clearData {
     cachedConv_ = nil;
     convUid_ = "";
@@ -120,6 +137,11 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
 
     if (convUid_.empty() || convModel_ == nil)
         return;
+    if([leaveMessageConversations containsObject:@(convUid_.c_str())]) {
+        [leaveMessageVC setConversationUID: convUid_ conversationModel: convModel_];
+    } else {
+        [leaveMessageVC hide];
+    }
 
     // Signals tracking changes in conversation list, we need them as cached conversation can be invalid
     // after a reordering.
@@ -247,5 +269,13 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
     [CATransaction commit];
 }
 
+- (void) presentLeaveMessageView {
+    [leaveMessageVC setConversationUID: convUid_ conversationModel: convModel_];
+    [leaveMessageConversations addObject:@(convUid_.c_str())];
+}
+
+-(void) messageCompleted {
+    [leaveMessageConversations removeObject:@(convUid_.c_str())];
+}
 
 @end
diff --git a/src/LeaveMessageVC.h b/src/LeaveMessageVC.h
new file mode 100644
index 00000000..3ef6561d
--- /dev/null
+++ b/src/LeaveMessageVC.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (C) 2018 Savoir-faire Linux Inc.
+ *  Author: Kateryna Kostiuk <kateryna.kostiuk@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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+#import <Cocoa/Cocoa.h>
+#import <string>
+
+namespace lrc {
+    namespace api {
+        class AVModel;
+        class ConversationModel;
+    }
+}
+
+@protocol LeaveMessageDelegate
+
+-(void) messageCompleted;
+
+@end
+
+@interface LeaveMessageVC : NSViewController
+
+@property (retain, nonatomic) id <LeaveMessageDelegate> delegate;
+
+-(void)setConversationUID:(const std::string) convUid conversationModel:(lrc::api::ConversationModel*) convModel;
+-(void) hide;
+-(void) initFrame;
+-(void) setAVModel: (const lrc::api::AVModel*) avmodel;
+
+@end
+
diff --git a/src/LeaveMessageVC.mm b/src/LeaveMessageVC.mm
new file mode 100644
index 00000000..c35fcfcf
--- /dev/null
+++ b/src/LeaveMessageVC.mm
@@ -0,0 +1,203 @@
+/*
+ *  Copyright (C) 2018 Savoir-faire Linux Inc.
+ *  Author: Kateryna Kostiuk <kateryna.kostiuk@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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#import "LeaveMessageVC.h"
+#import "views/NSColor+RingTheme.h"
+#import "utils.h"
+
+//lrc
+#import <api/avmodel.h>
+#import <api/conversationmodel.h>
+
+#import <QuartzCore/QuartzCore.h>
+#import "delegates/ImageManipulationDelegate.h"
+
+//Qt
+#import <QtMacExtras/qmacfunctions.h>
+#import <QPixmap>
+#import <globalinstances.h>
+
+@interface LeaveMessageVC () {
+    __unsafe_unretained IBOutlet NSImageView* personPhoto;
+    __unsafe_unretained IBOutlet NSTextField* infoLabel;
+    __unsafe_unretained IBOutlet NSBox* timerBox;
+    __unsafe_unretained IBOutlet NSTextField* timerLabel;
+    __unsafe_unretained IBOutlet NSBox* sendBox;
+    __unsafe_unretained IBOutlet NSTextField* sendFilename;
+    __unsafe_unretained IBOutlet NSButton* recordButton;
+}
+
+@end
+
+@implementation LeaveMessageVC
+
+bool isRecording = false;
+int recordingTime = 0;
+NSTimer* refreshDurationTimer;
+lrc::api::AVModel* avModel;
+std::string fileName;
+NSMutableDictionary *filesToSend;
+std::string conversationUid;
+lrc::api::ConversationModel* conversationModel;
+
+- (void)loadView {
+    [super loadView];
+    [personPhoto setWantsLayer:YES];
+    personPhoto.layer.masksToBounds =true;
+    personPhoto.layer.cornerRadius = personPhoto.frame.size.width * 0.5;
+    filesToSend = [[NSMutableDictionary alloc] init];
+}
+
+-(void) setAVModel: (lrc::api::AVModel*) avmodel {
+    avModel = avmodel;
+}
+
+-(void) initFrame {
+    [self.view setFrame:self.view.superview.bounds];
+    [self.view setHidden:YES];
+    self.view.layer.position = self.view.frame.origin;
+}
+
+- (IBAction)cancel:(id)sender {
+    [self exit];
+}
+
+- (IBAction)recordMessage:(NSButton *)sender {
+    if (!isRecording) {
+        [self clearData];
+        std::string file_name = avModel->startLocalRecorder(true);
+        if (file_name.empty()) {
+            return;
+        }
+        filesToSend[@(conversationUid.c_str())] = @(file_name.c_str());
+        isRecording = true;
+        recordButton.image = [NSImage imageNamed:@"ic_stoprecord.png"];
+        [timerBox setHidden:NO];
+        if (refreshDurationTimer == nil)
+            refreshDurationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
+                                                                    target:self
+                                                                  selector:@selector(updateDurationLabel)
+                                                                  userInfo:nil
+                                                                   repeats:YES];
+    } else {
+        avModel->stopLocalRecorder([filesToSend[@(conversationUid.c_str())] UTF8String]);
+        isRecording = false;
+        recordButton.image = [NSImage imageNamed:@"ic_action_audio.png"];
+        [refreshDurationTimer invalidate];
+        refreshDurationTimer = nil;
+        [timerBox setHidden:YES];
+        [sendBox setHidden: NO];
+        [sendFilename setStringValue:[self timeFormatted: recordingTime]];
+    }
+}
+
+- (IBAction)sendMessage:(NSButton *)sender {
+    NSArray* pathURL = [filesToSend[@(conversationUid.c_str())] componentsSeparatedByString: @"/"];
+    if([pathURL count] < 1) {
+        return;
+    }
+    NSString* name = [pathURL objectAtIndex: [pathURL count] - 1];
+    conversationModel->sendFile(conversationUid, [filesToSend[@(conversationUid.c_str())] UTF8String], [name UTF8String]);
+    [filesToSend removeObjectForKey: @(conversationUid.c_str())];
+    [self exit];
+}
+
+- (void) exit {
+    [self clearData];
+    [self hide];
+    [self.delegate messageCompleted];
+}
+
+- (void)clearData {
+    recordButton.image = [NSImage imageNamed:@"ic_action_audio.png"];
+    recordingTime = 0;
+    [timerLabel setStringValue: [self timeFormatted: recordingTime]];
+    isRecording = false;
+    [timerBox setHidden:YES];
+    [sendBox setHidden: YES];
+    [refreshDurationTimer invalidate];
+    refreshDurationTimer = nil;
+    [sendFilename setStringValue:@""];
+    [filesToSend removeObjectForKey: @(conversationUid.c_str())];
+}
+
+- (void)viewWillHide {
+    recordButton.image = [NSImage imageNamed:@"ic_action_audio.png"];
+    if(filesToSend[@(conversationUid.c_str())]) {
+        [sendFilename setStringValue:[self timeFormatted: recordingTime]];
+        [sendBox setHidden: NO];
+    } else {
+        [sendFilename setStringValue:@""];
+        [sendBox setHidden: YES];
+    }
+    recordingTime = 0;
+    [timerLabel setStringValue: [self timeFormatted: recordingTime]];
+    isRecording = false;
+    [timerBox setHidden:YES];
+    [refreshDurationTimer invalidate];
+    refreshDurationTimer = nil;
+}
+
+-(void) hide {
+    if(self.view.frame.origin.x < 0) {
+        return;
+    }
+    [self viewWillHide];
+    [self.view setHidden:YES];
+}
+
+-(void) show {
+    if(self.view.frame.origin.x < 0) {
+        return;
+    }
+    [self.view setHidden:NO];
+}
+
+-(void)setConversationUID:(std::string) convUid conversationModel:(lrc::api::ConversationModel*) convModel {
+    conversationUid = convUid;
+    conversationModel = convModel;
+    [self updateView];
+}
+
+-(void) updateView {
+    auto it = getConversationFromUid(conversationUid, *conversationModel);
+    if (it != conversationModel->allFilteredConversations().end()) {
+        auto& imgManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
+        QVariant photo = imgManip.conversationPhoto(*it, conversationModel->owner, QSize(120, 120), NO);
+        [personPhoto setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
+        NSString *name = bestNameForConversation(*it, *conversationModel);
+        [infoLabel setStringValue:name];
+    }
+    [self show];
+}
+
+-(void) updateDurationLabel
+{
+    recordingTime++;
+    [timerLabel setStringValue: [self timeFormatted: recordingTime]];
+}
+
+- (NSString *)timeFormatted:(int)totalSeconds
+{
+    int seconds = totalSeconds % 60;
+    int minutes = (totalSeconds / 60) % 60;
+    return [NSString stringWithFormat:@"%02d:%02d",minutes, seconds];
+}
+
+@end
diff --git a/src/LrcModelsProtocol.h b/src/LrcModelsProtocol.h
index f75848e3..662f134c 100644
--- a/src/LrcModelsProtocol.h
+++ b/src/LrcModelsProtocol.h
@@ -22,6 +22,7 @@ namespace lrc {
         class DataTransferModel;
         class NewAccountModel;
         class BehaviorController;
+        class AVModel;
     }
 }
 
@@ -30,9 +31,11 @@ namespace lrc {
 -(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil dataTransferModel:(const lrc::api::DataTransferModel*) dataTransferModel;
 -(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(const lrc::api::NewAccountModel*) accountModel;
 -(id) initWithWindowNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountModel:(const lrc::api::NewAccountModel*)accountModel dataTransferModel:(const lrc::api::DataTransferModel*)dataTransferModel behaviourController:(const lrc::api::BehaviorController*) behaviorController;
+-(id) initWithWindowNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountModel:(const lrc::api::NewAccountModel*)accountModel dataTransferModel:(const lrc::api::DataTransferModel*)dataTransferModel behaviourController:(const lrc::api::BehaviorController*) behaviorController avModel: (const lrc::api::AVModel*)avModel;
 
 @property lrc::api::DataTransferModel* dataTransferModel;
 @property lrc::api::NewAccountModel* accountModel;
 @property lrc::api::BehaviorController* behaviorController;
+@property lrc::api::AVModel* avModel;
 
 @end
diff --git a/src/MessagesVC.mm b/src/MessagesVC.mm
index 90360b57..79ebee9d 100644
--- a/src/MessagesVC.mm
+++ b/src/MessagesVC.mm
@@ -50,7 +50,6 @@
     std::string convUid_;
     lrc::api::ConversationModel* convModel_;
     const lrc::api::conversation::Info* cachedConv_;
-
     QMetaObject::Connection newInteractionSignal_;
 
     // Both are needed to invalidate cached conversation as pointer
@@ -790,6 +789,24 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
     return [dateFormatter stringFromDate:msgTime];
 }
 
+- (void) updateSendMessageHeight {
+    NSAttributedString *msgAttString = messageField.attributedStringValue;
+    NSRect frame = NSMakeRect(0, 0, messageField.frame.size.width, msgAttString.size.height);
+    NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
+    [[tv textStorage] setAttributedString:msgAttString];
+    [tv sizeToFit];
+    CGFloat height = tv.frame.size.height + MEESAGE_MARGIN * 2;
+    CGFloat newHeight = MIN(SEND_PANEL_MAX_HEIGHT, MAX(SEND_PANEL_DEFAULT_HEIGHT, height));
+    if(messagesBottomMargin.constant == newHeight) {
+        return;
+    }
+    messagesBottomMargin.constant = newHeight;
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+        [self scrollToBottom];
+        sendPanelHeight.constant = newHeight;
+    });
+}
+
 #pragma mark - NSTableViewDataSource
 
 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
@@ -877,39 +894,12 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
     if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) {
         [[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
     } else {
-        [[QLPreviewPanel sharedPreviewPanel] updateController];
-        [QLPreviewPanel sharedPreviewPanel].dataSource = self;
-        [[QLPreviewPanel sharedPreviewPanel] setAnimationBehavior:NSWindowAnimationBehaviorDocumentWindow];
-        [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:self];
+        });
     }
 }
 
-- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
-    return 1;
-}
-
-- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
-    return [NSURL fileURLWithPath:previewImage];
-}
-
-- (void) updateSendMessageHeight {
-    NSAttributedString *msgAttString = messageField.attributedStringValue;
-    NSRect frame = NSMakeRect(0, 0, messageField.frame.size.width, msgAttString.size.height);
-    NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
-    [[tv textStorage] setAttributedString:msgAttString];
-    [tv sizeToFit];
-    CGFloat height = tv.frame.size.height + MEESAGE_MARGIN * 2;
-    CGFloat newHeight = MIN(SEND_PANEL_MAX_HEIGHT, MAX(SEND_PANEL_DEFAULT_HEIGHT, height));
-    if(messagesBottomMargin.constant == newHeight) {
-        return;
-    }
-    messagesBottomMargin.constant = newHeight;
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
-        [self scrollToBottom];
-        sendPanelHeight.constant = newHeight;
-    });
-}
-
 - (IBAction)sendMessage:(id)sender {
     NSString* text = self.message;
     if (text && text.length > 0) {
@@ -971,4 +961,28 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
     [self updateSendMessageHeight];
 }
 
+#pragma mark - QLPreviewPanelDataSource
+
+-(void)beginPreviewPanelControl:(QLPreviewPanel *)panel
+{
+    panel.dataSource = self;
+}
+
+- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
+    panel.dataSource = nil;
+}
+
+-(BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel
+{
+    return YES;
+}
+
+- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
+    return 1;
+}
+
+- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
+    return [NSURL fileURLWithPath:previewImage];
+}
+
 @end
diff --git a/src/RingWindowController.mm b/src/RingWindowController.mm
index 971622e4..dbfd0972 100644
--- a/src/RingWindowController.mm
+++ b/src/RingWindowController.mm
@@ -59,6 +59,7 @@ typedef NS_ENUM(NSInteger, ViewState) {
     SHOW_CONVERSATION_SCREEN,
     SHOW_CALL_SCREEN,
     SHOW_SETTINGS_SCREEN,
+    LEAVE_MESSAGE,
 };
 
 @interface RingWindowController () <MigrateRingAccountsDelegate>
@@ -87,24 +88,20 @@ typedef NS_ENUM(NSInteger, ViewState) {
     ConversationVC* conversationVC;
     AccountSettingsVC* settingsVC;
 
-    // toolbar menu items
     IBOutlet ChooseAccountVC* chooseAccountVC;
 }
 
-static NSString* const kPreferencesIdentifier        = @"PreferencesIdentifier";
-NSString* const kChangeAccountToolBarItemIdentifier  = @"ChangeAccountToolBarItemIdentifier";
-NSString* const kOpenAccountToolBarItemIdentifier    = @"OpenAccountToolBarItemIdentifier";
-
-@synthesize dataTransferModel, accountModel, behaviorController;
+@synthesize dataTransferModel, accountModel, behaviorController, avModel;
 @synthesize wizard;
 
--(id) initWithWindowNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountModel:( lrc::api::NewAccountModel*)accountModel dataTransferModel:( lrc::api::DataTransferModel*)dataTransferModel behaviourController:( lrc::api::BehaviorController*) behaviorController
+-(id) initWithWindowNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountModel:( lrc::api::NewAccountModel*)accountModel dataTransferModel:( lrc::api::DataTransferModel*)dataTransferModel behaviourController:( lrc::api::BehaviorController*) behaviorController avModel: (lrc::api::AVModel*)avModel
 {
     if (self =  [self initWithWindowNibName:nibNameOrNil])
     {
         self.accountModel = accountModel;
         self.dataTransferModel = dataTransferModel;
         self.behaviorController = behaviorController;
+        self.avModel = avModel;
     }
     return self;
 }
@@ -165,6 +162,10 @@ NSString* const kOpenAccountToolBarItemIdentifier    = @"OpenAccountToolBarItemI
             [smartViewVC.view setHidden: YES];
             [settingsVC show];
             break;
+        case LEAVE_MESSAGE:
+            [conversationVC showWithAnimation: false];
+            [currentCallVC hideWithAnimation: false];
+            [conversationVC presentLeaveMessageView];
         default:
             break;
     }
@@ -178,12 +179,9 @@ NSString* const kOpenAccountToolBarItemIdentifier    = @"OpenAccountToolBarItemI
 
     currentCallVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil];
     currentCallVC.delegate = self;
-    conversationVC = [[ConversationVC alloc] initWithNibName:@"Conversation" bundle:nil delegate:self];
-    // toolbar items
-    //chooseAccountVC = [[ChooseAccountVC alloc] initWithNibName:@"ChooseAccount" bundle:nil model:self.accountModel delegate:self];
+    conversationVC = [[ConversationVC alloc] initWithNibName:@"Conversation" bundle:nil delegate:self aVModel:self.avModel];
     [chooseAccountVC updateWithDelegate: self andModel:self.accountModel];
     settingsVC = [[AccountSettingsVC alloc] initWithNibName:@"AccountSettings" bundle:nil accountmodel:self.accountModel];
-    //[self.window.contentView addSubview:[chooseAccountVC view]];
     [callView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
     [[currentCallVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
     [[conversationVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
@@ -219,6 +217,11 @@ NSString* const kOpenAccountToolBarItemIdentifier    = @"OpenAccountToolBarItemI
     }
     NSToolbar *tb = [[self window] toolbar];
     [tb setAllowsUserCustomization:NO];
+
+    //add messages view controller to responders chain
+    NSResponder * viewNextResponder = [self nextResponder];
+    [self setNextResponder: [conversationVC getMessagesView]];
+    [[conversationVC getMessagesView] setNextResponder: viewNextResponder];
 }
 
 - (void) connect
@@ -266,6 +269,15 @@ NSString* const kOpenAccountToolBarItemIdentifier    = @"OpenAccountToolBarItemI
                          [smartViewVC selectConversation: convInfo model:accInfo.conversationModel.get()];
                          [self changeViewTo:SHOW_CONVERSATION_SCREEN];
                      });
+    QObject::connect(self.behaviorController,
+                     &lrc::api::BehaviorController::showLeaveMessageView,
+                     [self](const std::string& accountId,
+                            const lrc::api::conversation::Info& convInfo){
+                         auto& accInfo = self.accountModel->getAccountInfo(accountId);
+                         [conversationVC setConversationUid:convInfo.uid model:accInfo.conversationModel.get()];
+                         [smartViewVC selectConversation: convInfo model:accInfo.conversationModel.get()];
+                         [self changeViewTo:LEAVE_MESSAGE];
+                     });
 }
 
 /**
diff --git a/ui/Base.lproj/LeaveMessageVC.xib b/ui/Base.lproj/LeaveMessageVC.xib
new file mode 100644
index 00000000..783ba042
--- /dev/null
+++ b/ui/Base.lproj/LeaveMessageVC.xib
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
+        <capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="LeaveMessageVC">
+            <connections>
+                <outlet property="infoLabel" destination="oeJ-VI-uhE" id="9bG-8v-9PT"/>
+                <outlet property="personPhoto" destination="gFu-2j-j1g" id="NOO-yO-d5d"/>
+                <outlet property="recordButton" destination="cOl-pS-cP5" id="YsL-fB-biO"/>
+                <outlet property="sendBox" destination="MxH-aj-EXO" id="715-t9-z7D"/>
+                <outlet property="sendFilename" destination="Zj8-Dk-VI5" id="y15-gg-zgb"/>
+                <outlet property="timerBox" destination="WtB-WH-CJz" id="WyV-9R-KT0"/>
+                <outlet property="timerLabel" destination="1k9-gR-Qgh" id="Rch-wt-Q7U"/>
+                <outlet property="view" destination="Hz6-mo-xeY" id="0ae-8W-gNO"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="Hz6-mo-xeY">
+            <rect key="frame" x="0.0" y="0.0" width="798" height="658"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <box boxType="custom" borderType="none" cornerRadius="4" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="TwL-yO-BXI">
+                    <rect key="frame" x="0.0" y="0.0" width="798" height="658"/>
+                    <view key="contentView" id="RNM-sD-Phj">
+                        <rect key="frame" x="0.0" y="0.0" width="798" height="658"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </view>
+                    <color key="borderColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    <color key="fillColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
+                </box>
+                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cOl-pS-cP5" customClass="HoverButton">
+                    <rect key="frame" x="350" y="222" width="40" height="40"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="40" id="hiL-Mx-vuA"/>
+                        <constraint firstAttribute="height" constant="40" id="qPN-3f-Ko7"/>
+                    </constraints>
+                    <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_audio" imagePosition="only" alignment="center" transparent="YES" imageScaling="proportionallyUpOrDown" inset="2" id="hiW-Yq-71M">
+                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                        <font key="font" metaFont="system"/>
+                    </buttonCell>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="imageInsets">
+                            <integer key="value" value="6"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="hoverColor">
+                            <color key="value" name="unemphasizedSelectedContentBackgroundColor" catalog="System" colorSpace="catalog"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="imageColor">
+                            <color key="value" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="recordMessage:" target="-2" id="AcE-mM-mr5"/>
+                    </connections>
+                </button>
+                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0v7-mC-auu" customClass="HoverButton">
+                    <rect key="frame" x="400" y="222" width="40" height="40"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="40" id="Ubr-IA-SO6"/>
+                        <constraint firstAttribute="width" constant="40" id="hhA-GJ-SQo"/>
+                    </constraints>
+                    <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_exit" imagePosition="only" alignment="center" transparent="YES" imageScaling="proportionallyUpOrDown" inset="2" id="121-P0-aCH">
+                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                        <font key="font" metaFont="system"/>
+                    </buttonCell>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="imageInsets">
+                            <integer key="value" value="6"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="hoverColor">
+                            <color key="value" name="unemphasizedSelectedContentBackgroundColor" catalog="System" colorSpace="catalog"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="imageColor">
+                            <color key="value" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="cancel:" target="-2" id="dVf-0K-pdq"/>
+                    </connections>
+                </button>
+                <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="gFu-2j-j1g">
+                    <rect key="frame" x="339" y="398" width="120" height="120"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="120" id="KMx-gW-5Jr"/>
+                        <constraint firstAttribute="width" constant="120" id="kGL-D8-QE0"/>
+                    </constraints>
+                    <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSUser" id="boQ-fa-nNO"/>
+                </imageView>
+                <box titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="WtB-WH-CJz">
+                    <rect key="frame" x="306" y="118" width="187" height="86"/>
+                    <view key="contentView" id="tbn-BB-CbR">
+                        <rect key="frame" x="3" y="3" width="181" height="80"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CvL-tU-YNA">
+                                <rect key="frame" x="57" y="53" width="66" height="17"/>
+                                <textFieldCell key="cell" lineBreakMode="clipping" title="Recording" id="kIq-PG-Ymw">
+                                    <font key="font" usesAppearanceFont="YES"/>
+                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                </textFieldCell>
+                            </textField>
+                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1k9-gR-Qgh">
+                                <rect key="frame" x="48" y="8" width="84" height="35"/>
+                                <textFieldCell key="cell" lineBreakMode="clipping" title="00:00" id="78U-cA-2f2">
+                                    <font key="font" metaFont="system" size="29"/>
+                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                </textFieldCell>
+                            </textField>
+                        </subviews>
+                        <constraints>
+                            <constraint firstItem="1k9-gR-Qgh" firstAttribute="centerX" secondItem="tbn-BB-CbR" secondAttribute="centerX" id="ALD-VB-KGO"/>
+                            <constraint firstItem="CvL-tU-YNA" firstAttribute="top" secondItem="tbn-BB-CbR" secondAttribute="top" constant="10" id="Xxf-0h-14a"/>
+                            <constraint firstItem="CvL-tU-YNA" firstAttribute="centerX" secondItem="tbn-BB-CbR" secondAttribute="centerX" id="Ylf-xL-G77"/>
+                            <constraint firstItem="1k9-gR-Qgh" firstAttribute="top" secondItem="CvL-tU-YNA" secondAttribute="bottom" constant="10" id="gnT-ir-ivn"/>
+                        </constraints>
+                    </view>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="181" id="Wgv-cO-Eg5"/>
+                        <constraint firstAttribute="height" constant="80" id="dEB-5M-hAm"/>
+                    </constraints>
+                    <font key="titleFont" metaFont="cellTitle"/>
+                </box>
+                <box title="Box" titlePosition="noTitle" transparent="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MxH-aj-EXO">
+                    <rect key="frame" x="306" y="118" width="187" height="86"/>
+                    <view key="contentView" id="U9z-Rg-Zs3">
+                        <rect key="frame" x="3" y="3" width="181" height="80"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <box boxType="custom" borderType="bezel" cornerRadius="20" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Zlv-nH-Y9y">
+                                <rect key="frame" x="20" y="40" width="100" height="40"/>
+                                <view key="contentView" id="bxd-ht-hMm">
+                                    <rect key="frame" x="1" y="1" width="98" height="38"/>
+                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    <subviews>
+                                        <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kSA-Cr-Pp3">
+                                            <rect key="frame" x="10" y="10" width="20" height="18"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="20" id="YUW-eF-aaS"/>
+                                            </constraints>
+                                            <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ic_audio_file" id="8ee-Km-Vp6"/>
+                                        </imageView>
+                                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Zj8-Dk-VI5">
+                                            <rect key="frame" x="38" y="11" width="62" height="17"/>
+                                            <textFieldCell key="cell" lineBreakMode="clipping" id="Lml-tH-Au6">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="Zj8-Dk-VI5" firstAttribute="centerY" secondItem="bxd-ht-hMm" secondAttribute="centerY" id="Hpd-t9-NNA"/>
+                                        <constraint firstItem="kSA-Cr-Pp3" firstAttribute="centerY" secondItem="bxd-ht-hMm" secondAttribute="centerY" id="c4e-NF-hy4"/>
+                                        <constraint firstAttribute="trailing" secondItem="Zj8-Dk-VI5" secondAttribute="trailing" id="iWD-1w-N3k"/>
+                                        <constraint firstItem="kSA-Cr-Pp3" firstAttribute="leading" secondItem="bxd-ht-hMm" secondAttribute="leading" constant="10" id="ofV-eC-JpI"/>
+                                        <constraint firstItem="kSA-Cr-Pp3" firstAttribute="top" secondItem="bxd-ht-hMm" secondAttribute="top" constant="10" id="x9O-tw-81d"/>
+                                        <constraint firstItem="Zj8-Dk-VI5" firstAttribute="leading" secondItem="kSA-Cr-Pp3" secondAttribute="trailing" constant="10" id="zu8-7j-OP5"/>
+                                    </constraints>
+                                </view>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="40" id="Iyu-Nl-TpG"/>
+                                    <constraint firstAttribute="width" constant="100" id="cw3-NU-2Lj"/>
+                                </constraints>
+                                <color key="borderColor" name="unemphasizedSelectedContentBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                <color key="fillColor" name="unemphasizedSelectedContentBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </box>
+                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XN4-Vb-UWd" customClass="HoverButton">
+                                <rect key="frame" x="131" y="40" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="40" id="LNf-7D-co7"/>
+                                    <constraint firstAttribute="width" constant="40" id="ouZ-f5-Vfs"/>
+                                </constraints>
+                                <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_send" imagePosition="only" alignment="center" transparent="YES" imageScaling="proportionallyDown" inset="2" id="9LO-UF-tss">
+                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                    <font key="font" metaFont="system"/>
+                                </buttonCell>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="imageInsets">
+                                        <integer key="value" value="6"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="color" keyPath="imageColor">
+                                        <color key="value" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="color" keyPath="hoverColor">
+                                        <color key="value" name="unemphasizedSelectedContentBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <action selector="sendMessage:" target="-2" id="4WL-7f-xpJ"/>
+                                </connections>
+                            </button>
+                        </subviews>
+                        <constraints>
+                            <constraint firstItem="XN4-Vb-UWd" firstAttribute="top" secondItem="U9z-Rg-Zs3" secondAttribute="top" id="073-sZ-trD"/>
+                            <constraint firstItem="Zlv-nH-Y9y" firstAttribute="leading" secondItem="U9z-Rg-Zs3" secondAttribute="leading" constant="20" id="Xh6-x6-TnF"/>
+                            <constraint firstItem="Zlv-nH-Y9y" firstAttribute="top" secondItem="U9z-Rg-Zs3" secondAttribute="top" id="aot-Tv-9mi"/>
+                            <constraint firstAttribute="trailing" secondItem="XN4-Vb-UWd" secondAttribute="trailing" constant="10" id="hUi-OE-cZU"/>
+                            <constraint firstItem="XN4-Vb-UWd" firstAttribute="leading" secondItem="Zlv-nH-Y9y" secondAttribute="trailing" constant="11" id="j7u-cW-AWB"/>
+                        </constraints>
+                    </view>
+                </box>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="oeJ-VI-uhE">
+                    <rect key="frame" x="378" y="320" width="42" height="18"/>
+                    <textFieldCell key="cell" lineBreakMode="clipping" title="Name" id="uol-7p-Y2J">
+                        <font key="font" metaFont="system" size="14"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dbY-HE-70Z">
+                    <rect key="frame" x="247" y="282" width="304" height="18"/>
+                    <textFieldCell key="cell" lineBreakMode="clipping" title="Contact appears to be busy. Leave a message?" id="hnr-x5-xnb">
+                        <font key="font" metaFont="systemLight" size="14"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+            </subviews>
+            <constraints>
+                <constraint firstItem="cOl-pS-cP5" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" constant="-29" id="3kZ-xx-zfF"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" id="4ia-YI-y5O"/>
+                <constraint firstItem="dbY-HE-70Z" firstAttribute="top" secondItem="oeJ-VI-uhE" secondAttribute="bottom" constant="20" id="725-UY-bsG"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="leading" secondItem="MxH-aj-EXO" secondAttribute="leading" id="DbY-VH-imQ"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="trailing" secondItem="MxH-aj-EXO" secondAttribute="trailing" id="E7l-KF-ph3"/>
+                <constraint firstAttribute="trailing" secondItem="TwL-yO-BXI" secondAttribute="trailing" id="Hi0-k1-dx9"/>
+                <constraint firstItem="TwL-yO-BXI" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="Hle-nR-C5u"/>
+                <constraint firstItem="oeJ-VI-uhE" firstAttribute="centerY" secondItem="Hz6-mo-xeY" secondAttribute="centerY" id="IBz-Qp-LpV"/>
+                <constraint firstItem="TwL-yO-BXI" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="LrF-0X-nHd"/>
+                <constraint firstItem="gFu-2j-j1g" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" id="MnV-YG-76G"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="bottom" secondItem="MxH-aj-EXO" secondAttribute="bottom" id="XO6-7p-v1a"/>
+                <constraint firstAttribute="bottom" secondItem="TwL-yO-BXI" secondAttribute="bottom" id="Yhm-GI-18S"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="top" secondItem="cOl-pS-cP5" secondAttribute="bottom" constant="20" id="ZlU-DX-nL3"/>
+                <constraint firstItem="0v7-mC-auu" firstAttribute="leading" secondItem="cOl-pS-cP5" secondAttribute="trailing" constant="10" id="afB-FF-Op0"/>
+                <constraint firstItem="cOl-pS-cP5" firstAttribute="top" secondItem="dbY-HE-70Z" secondAttribute="bottom" constant="20" id="bNl-00-Thl"/>
+                <constraint firstItem="0v7-mC-auu" firstAttribute="centerY" secondItem="cOl-pS-cP5" secondAttribute="centerY" id="hGt-wT-rrj"/>
+                <constraint firstItem="oeJ-VI-uhE" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" id="l8d-MQ-RwK"/>
+                <constraint firstItem="dbY-HE-70Z" firstAttribute="centerX" secondItem="Hz6-mo-xeY" secondAttribute="centerX" id="orz-1K-VBk"/>
+                <constraint firstItem="oeJ-VI-uhE" firstAttribute="top" secondItem="gFu-2j-j1g" secondAttribute="bottom" constant="60" id="rlm-H5-Lp8"/>
+                <constraint firstItem="WtB-WH-CJz" firstAttribute="top" secondItem="MxH-aj-EXO" secondAttribute="top" id="vuA-zF-FBa"/>
+            </constraints>
+        </customView>
+    </objects>
+    <resources>
+        <image name="NSUser" width="32" height="32"/>
+        <image name="ic_action_audio" width="36" height="36"/>
+        <image name="ic_action_send" width="72" height="72"/>
+        <image name="ic_audio_file" width="75" height="75"/>
+        <image name="ic_exit" width="64" height="64"/>
+    </resources>
+</document>
-- 
GitLab