From 3130fd5257a6c2808ee30d03cb27253f7d1510d6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 18 Jun 2021 15:49:58 +0300 Subject: [PATCH] #4096 - Added locked mode transition and animations, locked recording mode and real time waveform. --- .../Contents.json | 3 + .../Contents.json | 23 ++ .../voice_message_lock_chevron.png | Bin 0 -> 245 bytes .../voice_message_lock_chevron@2x.png | Bin 0 -> 364 bytes .../voice_message_lock_chevron@3x.png | Bin 0 -> 451 bytes .../Contents.json | 23 ++ .../voice_message_lock_icon_locked.png | Bin 0 -> 1078 bytes .../voice_message_lock_icon_locked@2x.png | Bin 0 -> 1931 bytes .../voice_message_lock_icon_locked@3x.png | Bin 0 -> 2853 bytes .../Contents.json | 23 ++ .../voice_message_lock_icon_unlocked.png | Bin 0 -> 1032 bytes .../voice_message_lock_icon_unlocked@2x.png | Bin 0 -> 1869 bytes .../voice_message_lock_icon_unlocked@3x.png | Bin 0 -> 2716 bytes Riot/Generated/Images.swift | 3 + .../VoiceMessageAudioRecorder.swift | 8 +- .../VoiceMessageController.swift | 45 +++- .../VoiceMessagePlaybackView.swift | 4 + .../VoiceMessagePlaybackView.xib | 64 ++--- .../VoiceMessageToolbarView.swift | 214 ++++++++++++--- .../VoiceMessages/VoiceMessageToolbarView.xib | 245 +++++++++++++----- .../VoiceMessageWaveformView.swift | 5 - 21 files changed, 504 insertions(+), 156 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/voice_message_lock_icon_unlocked.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/voice_message_lock_icon_unlocked@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/voice_message_lock_icon_unlocked@3x.png diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_delete.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_delete.imageset/Contents.json index bb4344e926..a255919c50 100644 --- a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_delete.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_delete.imageset/Contents.json @@ -19,5 +19,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" } } diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/Contents.json new file mode 100644 index 0000000000..6b40d80e49 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voice_message_lock_chevron.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voice_message_lock_chevron@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voice_message_lock_chevron@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron.png new file mode 100644 index 0000000000000000000000000000000000000000..332200ef8a64185eb0105acf87fd8a7185518330 GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-1!HlL zyA#8@b22Z19F}xPUq=Rpjs4tz5?O)#E>9Q7kP61PllF2p7znu83dSg}w&+^Abg6Je zRFqZM>J(nbE2od{SDK{1^}E9a>)Q1mn|uOAob2BmKRKn+aQFAr=+*01>VA?Jsd$p| zCuMtvid4nv&ZCQ_3y3XLvE)uYXl&x7`RSVo?;dC6DO&p-lq)p^CR?W*v#!@Gxo@E1 l@Tumsv*3??+Nby}87_nu?hi;%%mliM!PC{xWt~$(696XSQr!Rm literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ff29e08080b960d7fd4455f6a95029a5c9b09ccf GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=uYs~a{-RF>3Gdd}-1k$e_?N)s0yK<);lp~7$|9Tl*Fu8aQn0bvA8s4OIMV7 z$o<@Nf)8rg+m5M!TxD5jao5?@c>1-IOy!3(52V?A7B#d?I8*UVIVtGCl#f1ENhJ-Z zE7T+nwH%UcCU&uMd{6a=B1wd`FHlLSN*8;zS1uxCG$wL&)NI-JNwdO1y|KI zZ%vU6_sGUBCb0W|JmfSweZ*eC;qpWf-_zC4Wt~$(69D;@ Bijn{T literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_chevron.imageset/voice_message_lock_chevron@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b9f5c04d5b7e6f59a49353f0e9d59bcdcf96cea7 GIT binary patch literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!oCO|{#S9FJ79h;%I?XTvD9BhG z~LEBw_S15gifklFf0tw zoVbbIN)>2Q&@~6m!YSoTavFbi08L8eypk^SRCMKc2g^qq{T_SSPD#2)y1&w$;3|_U zxpKP0w8AN&OP)B$6;5$o(x|dR?DZ+_bAF%m{?^}4F5mY2XqFb|BqrC1fv?k^S*+3y znoyt)1L)(TXjf eVd25R@c*FsAvJNUwdDnBAVE)8KbLh*2~7YjV6>C~ literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/Contents.json new file mode 100644 index 0000000000..93de75077f --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voice_message_lock_icon_locked.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voice_message_lock_icon_locked@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voice_message_lock_icon_locked@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked.png new file mode 100644 index 0000000000000000000000000000000000000000..bb79d77850d2d6f023fd1b3320617320c108b960 GIT binary patch literal 1078 zcmV-61j+k}P)CosTbgvBx$Ct+bSQDz4)xEjD&1MVi`sEGk5H4b!ha1atO zF+@R~&=?vhLQCH}o^xqy3+*fKmfH49n%CaUh=k3!UPR8MyF$eDDuqFJaO zu|i0P(=0NAV>`*)5?-L%;BdOB7p#3ULt;Dbtd_EZEp7jT@vrmxxS5RWwqTtfuAjaD zV=cYV(hvkwWJPT9TkWa$0P+hI;4B#OV*L}0th{l(=JCaAFm$#9OyQ{2f1bMW%g5Ev5O^Qm@aCG0Si!0X>%^iiJd zL9v3g$vI&u>uDPhvUKiE7={wqOz!GqdKl!RBXur48BIYh6cj4#f?C0$HpRCDu0rItx$1!*|#aOU_Dv4k^UUenJ2o?l!V^`t-MWYgN4Wi{>dqKN(YiDnQ9Yj~Jwp@rx$@xtY8QGRF#HQ}?j;x9ns9T($4tT#??~X1={vs&>c*IC>n*FU?o81_3kJymW w9*4GU|83oJ3C5i)aNhmRA>yrDtE8>lzka!lXhk7X?*IS*07*qoM6N<$g0pPu-~a#s literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@2x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..521e0df1f7dedfdac947f6d7c1aa366d6bd570b4 GIT binary patch literal 1931 zcmV;62Xy#}P)VN6AQDl*1)(~r(W{U(yWZV#?EOjcdOw`Re?Px@^JeBP zLLX5qQAV0(Mi`hufC&Q306`jn)DLePC;(sq5LS?&Ac5`^h`dny$vEbrPe9Pf<88_c zfP+Mo1)>bJis%(3yb@W`4GJyk5oMVtz&}AdqTb|+ddMjYUkF?5Py|*M znqJ?Mb0F|Au(j%hEgPf~I<^QQ5U9W`?2{chO;XN7NY?5UwrWDU5VX*N3H+o)rzOer z&}YIn6SUC23taZGbWXb~a0v@7q?jEW!xium0Y1U*K!sVCP|BsKv1>)XmW ze8d+E-q@fiDQJm+reFZ@)0%s>;Ef$Rp+5P0gCZ_dvF3ZlO>-W4q$h#->tvd85&FC# z^GI5m@}*u~hG!R{{OwgB726I2C@!lG${Fy0CxM4b+zN=WI371nf=gTrJdEO2@glM- zAIxFcu!_qN!Q6Vuyz1sPjs>=yJ;|P1)!mLIvWte#k&CEwdoM#o4Z{#~V==te?Ygc4 zb0>mhLKw_YtQQJ~6f@mABVAnt_s}2`*N(Ila_JFKM{PO^%)VxjdT4&bJ-(4`=;)8z zx`>KvScZtMsC@VAp0Saf-MO|FTyYH%4nV_bYsIz#7dLk1BG=#om7Z;v7_xN{YW!?D z64*6`?YNlUi&&^X7;C<&U#$0+_5a|9|Nn%aRv%i=*LJoV&ZlAtcx(K5_45LJ_R>2r zIhq2^q+=zkBX++2V2cIow%&(ZYjF0j9Nbjmy5W----OR659k)U#flpQX6sc$>#q9R ze!`Y|^uf0+*6NhWL<+uo<73OJwLx$uIcn5;y^R8IagWWKVG}wm?g#h220yqpb4;Je zh`D53%vN`6QADv+%IFf8-NL88-2lHh`rtcwxVZ*eP!YxBjqPl8_gN!HhPF)E7k}Te zM7HC=#4GU8zWtCg5)H@K%q_U`&t2Qsv5PsoyaZQYKMYzh#1ZwF%7h^)0K@1Q1URgNB-IrXx0 zajSf|?=?riJ1h|KAaBb8lb+~-S=-rcIo8~uIbp))HD2RsU#Ms*%Hdg*P!9l}tCtay z#1upXgqab@3r!*dffw-zUA?zqK#4mc5XA&U1OgFeP$hWOxLdfL4DP+n|9;ap&l?1X zR0wx*dN%Y_CeJfg0-KK@#3+KreP3nG!VaN0L4P}QJZzB*90!LQqMcKD10C@x|IPV7 zZbHbUeOsg9l<)QB2ekC;LKj#kI=(qWC9n=y-~vPh1vhdS2^AHO zsAy^lto-ng5aBOe@d|45B4iFC{6&bIwc&@#0*=TJ`vfQ2tL4LL$sQFCcU`p@;SelO z{9~SF(@0*22w&g=c-7}Mfh{+In1g^x#YSPU!F+vn!Nz=WrR56}P18v&4(;0yfrE0P zVYhyV*WHektks=?jnkC}J-@M?lNKal40>|oHl8r1>yI^9Ft3gwfCUH;o|<}l=2$q^ z1Z81)mV6i^%3MLP`B=*`t}v{45V5mfre#ddTH{6L1&DBko%J$pSKAj$yR$^14%%5S z({@yu%*cwJ!etoSo@;l4<6@Nr3ber+1k|w5g-&HIOY&5=aiCF=mXq?gj;2l}$6|}@YaqgcwMdS}9o3O@ zRl9O+%Uo2S$O#x?xZ&S38gsm^+jVi!VHQ~eT}vfmb8cSasl4qlitI&P#?$oGRKl1W zrWo0)xQyrd!R&{Iq2c5A=v7>%=erOTH%s$?R$;b5%f1yjJmm-qdZ1^4ndmkT?eS#^ z0skZ82{AngE`!^a=i=SV);h%(3$AC^TC*DP zE^JZj(JF8=EVvvIQ)pER!M6#O-~>}0Z~LpZh?FOQRcTUQm@=PC#`|VM`BQzEBB_mq RCP@GQ002ovPDHLkV1h_WiDv)+ literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_locked.imageset/voice_message_lock_icon_locked@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b7cdaf91174ba081f9d561ba2a4f30c6dbab343d GIT binary patch literal 2853 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 Hu0mjfC1-Qg literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/voice_message_lock_icon_unlocked@3x.png b/Riot/Assets/Images.xcassets/Room/VoiceMessages/voice_message_lock_icon_unlocked.imageset/voice_message_lock_icon_unlocked@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..4264165d47e6e5c3c9db4b800004f42541f6d357 GIT binary patch literal 2716 zcmV;N3S;$&P)JL0!dHM_z5IGL7XR$^aPR7 zf7$}ARd079q(X?g8j++r(joAod%yh(zm&7eNRJ zxZ?wEUzouiNH~cV1Y3juAHnZQ>vte#cMuiqR!o3;JIPifae{DB2wkWk!jAIQ?W74K zF@i{m5YAwPv6UoYBtj4e4O&l|5IPA)C`xV3W$`w|Oss<7U{Pt>q|gLWx@gB3`CMiT zVj>nn1n!|82w@q7GsNjerY?ws+R?JfByK`V-NT^7Wi1p;3APH=I=ySe@IHtb`a)pp zErgqV&7PTS2UB7y7UJ-b3R=;w#0sOq)KoFstWq?IL0YA|z5l1Y)S`J#%;sgvoM~62oXa}L@bI(1R-LGnFvJ@ z$tZ)<&>&)n529k0J6eGtF z)x#s6>^in0h3N4-wK|)@Z5V-(1i`flPNjlmAd^bP)9U&twU41)29GGXPz54}BxCN8 z-W{b%IE!-@4UV) zBUnTuVz3?_b?n#tjeh6#v=94uq!8LkXiBJo{ z)&T?;>1idpS_mm#IZvpS=xQN+@E1YE;4-0BqN|0FyhAFeX_*wC%=5ZCA18J?j zm(_6$K?oMFS#e>#Ad*x|;A*Sw$S5O1>h(I< zjuAvMy3z~r6Z8iKLFmBLGN25CU?9Y@BGTW0AV9FW={Kg9Au)u|LKzFefdmMG0W~+B zM=FCL7&NM~%4)9!f&lC>jD;AbFO%RV`5czo3w6Xwq@Jb*+6#3afRJhssY4J1Vj)rv z0o~)Tfgn6m12^dsT*Z4~AzFc@{k2+ZXaYRb-d~dIPd@P7ypF+ev5YmOY=bg#PlM`e#NgRqUCTN%r;>dCHdw^fpS%f4ftU2z1fjQe z`nj%qg;Z-k@6BUP&n;QXH#}jjpEKP~CV=gox)T8L*v^VxdPDnUB)xk<&->Uy`iFkRPWaB#_10t6>Pgq^U7QK9>d ziIs2{V;vU41QEJ&ORR*O80)arYuaSb9SOxsxJ9sbQ>&$3g6O%nQ>=trXsx&VO{yMf z&r)gqY(HUnhtmwS`de#%4FszR%R8KAAVHj;&F&$f%$Kkf4kX)M_xhd-10n&YoeUC4 zb~5mWAsk?8AaNa*!LDMM)pPR;1 zDqhN|>)2}HJSao&F~zP!XY*7dIWX%<0<4Ne@+ z&8V9&CXsAh+Q{Nf*>ogU9=w#pNODAxHRNk%GHKV9F2NS@U@oT?M;TFcBhn6yB8sUK zsTi0@_qygBMI(nxQV5#@h9HyqUozIPycfzBUD0~;BY(6d(&JJ@z5GKe}+I}A%Qb8-)m4eu43_GV`9H!Dh zg@2KH4zEjGF+67nDrPwOo)N+Z#7rUt z!KBoU1VYH4%iM{>J#-^6f@sqrjJLtv+(qJq&?a$$XcGtn{6)uNjKm6|O=1Pn$@ALL zvImM|jAgJ9Q;6ct+~N!t2gM3Ov}s!n@YG7;XK3;Ej+*Y8Lf=+WtwA@e5=18*E`?)_ zVglSsg}3VQeY$u4oVR0>2s*J=5T~hD>qTQZil&gZXnw70lb@u6C2mVZ8Xj;18dsXx zIU|T}ut;=P6%=8?RBZ}K_!^-ZxeyeZXM|am*3CsIBbh)D=`+wKX@pefww5k;GW-tU WYJ(V0Oq)mm0000 Float { - if decibels < -60.0 || decibels == 0.0 { - return 0.0 - } - - return powf((powf(10.0, 0.05 * decibels) - powf(10.0, 0.05 * -60.0)) * (1.0 / (1.0 - powf(10.0, 0.05 * -60.0))), 1.0 / 2.0) + return decibels / silenceThreshold } } diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageController.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageController.swift index 94306a5aed..b00d68d82e 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageController.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageController.swift @@ -31,6 +31,9 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate, private var audioRecorder: VoiceMessageAudioRecorder? + private var audioSamples: [Float] = [] + private var isInLockedMode: Bool = false + @objc public weak var delegate: VoiceMessageControllerDelegate? @objc public var voiceMessageToolbarView: UIView { @@ -54,6 +57,8 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate, self._voiceMessageToolbarView.update(theme: self.themeService.theme) NotificationCenter.default.addObserver(self, selector: #selector(handleThemeDidChange), name: .themeServiceDidChangeTheme, object: nil) + + updateUI() } // MARK: - VoiceMessageToolbarViewDelegate @@ -87,27 +92,32 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate, } func voiceMessageToolbarViewDidRequestRecordingCancel(_ toolbarView: VoiceMessageToolbarView) { + isInLockedMode = false audioRecorder?.stopRecording() deleteRecordingAtURL(audioRecorder?.url) UINotificationFeedbackGenerator().notificationOccurred(.error) } + func voiceMessageToolbarViewDidRequestLockedModeRecording(_ toolbarView: VoiceMessageToolbarView) { + isInLockedMode = true + updateUI() + } + // MARK: - AudioRecorderDelegate func audioRecorderDidStartRecording(_ audioRecorder: VoiceMessageAudioRecorder) { - _voiceMessageToolbarView.state = .recording - self.displayLink.isPaused = false + updateUI() } func audioRecorderDidFinishRecording(_ audioRecorder: VoiceMessageAudioRecorder) { - _voiceMessageToolbarView.state = .idle - displayLink.isPaused = true + updateUI() } func audioRecorder(_ audioRecorder: VoiceMessageAudioRecorder, didFailWithError: Error) { + isInLockedMode = false + updateUI() + MXLog.error("Failed recording voice message.") - _voiceMessageToolbarView.state = .idle - displayLink.isPaused = true } // MARK: - Private @@ -129,10 +139,27 @@ public class VoiceMessageController: NSObject, VoiceMessageToolbarViewDelegate, } @objc private func handleDisplayLinkTick() { - guard let audioRecorder = audioRecorder else { - return + updateUI() + } + + private func updateUI() { + displayLink.isPaused = !(audioRecorder?.isRecording ?? false) + + let requiredNumberOfSamples = _voiceMessageToolbarView.getRequiredNumberOfSamples() + + if audioSamples.count != requiredNumberOfSamples { + audioSamples = [Float](repeating: 0.0, count: requiredNumberOfSamples) + } + + if let sample = audioRecorder?.averagePowerForChannelNumber(0) { + audioSamples.append(sample) + audioSamples.remove(at: 0) } - _voiceMessageToolbarView.elapsedTime = timeFormatter.string(from: Date(timeIntervalSinceReferenceDate: audioRecorder.currentTime)) + var details = VoiceMessageToolbarViewDetails() + details.state = (audioRecorder?.isRecording ?? false ? (isInLockedMode ? .lockedModeRecord : .record) : (isInLockedMode ? .lockedModePlayback : .idle)) + details.elapsedTime = timeFormatter.string(from: Date(timeIntervalSinceReferenceDate: audioRecorder?.currentTime ?? 0.0)) + details.audioSamples = audioSamples + _voiceMessageToolbarView.configureWithDetails(details) } } diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.swift index 7e9ddce0d8..ba0bd2654f 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.swift @@ -26,6 +26,7 @@ struct VoiceMessagePlaybackViewDetails { var samples: [Float] = [] var playing: Bool = false var playbackEnabled = false + var recording: Bool = false } class VoiceMessagePlaybackView: UIView { @@ -33,6 +34,7 @@ class VoiceMessagePlaybackView: UIView { private var waveformView: VoiceMessageWaveformView! @IBOutlet private var backgroundView: UIView! + @IBOutlet private var recordingIcon: UIView! @IBOutlet private var playButton: UIButton! @IBOutlet private var elapsedTimeLabel: UILabel! @IBOutlet private var waveformContainerView: UIView! @@ -66,6 +68,8 @@ class VoiceMessagePlaybackView: UIView { } playButton.isEnabled = details.playbackEnabled + playButton.isHidden = details.recording + recordingIcon.isHidden = !details.recording elapsedTimeLabel.text = details.currentTime waveformView.progress = details.progress diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.xib b/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.xib index 545fab1747..c49272d995 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.xib +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessagePlaybackView.xib @@ -21,44 +21,48 @@ - - - - - - + - - + - - - - - - + - - - + + @@ -68,6 +72,7 @@ + @@ -75,5 +80,6 @@ + diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift index 8f7b664f9d..d46493b81f 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift @@ -20,16 +20,27 @@ protocol VoiceMessageToolbarViewDelegate: AnyObject { func voiceMessageToolbarViewDidRequestRecordingStart(_ toolbarView: VoiceMessageToolbarView) func voiceMessageToolbarViewDidRequestRecordingCancel(_ toolbarView: VoiceMessageToolbarView) func voiceMessageToolbarViewDidRequestRecordingFinish(_ toolbarView: VoiceMessageToolbarView) + func voiceMessageToolbarViewDidRequestLockedModeRecording(_ toolbarView: VoiceMessageToolbarView) } enum VoiceMessageToolbarViewUIState { case idle - case recording + case record + case lockedModeRecord + case lockedModePlayback +} + +struct VoiceMessageToolbarViewDetails { + var state: VoiceMessageToolbarViewUIState = .idle + var elapsedTime: String = "" + var audioSamples: [Float] = [] } class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDelegate { @IBOutlet private var backgroundView: UIView! + @IBOutlet private var recordingContainerView: UIView! + @IBOutlet private var recordButtonsContainerView: UIView! @IBOutlet private var primaryRecordButton: UIButton! @IBOutlet private var secondaryRecordButton: UIButton! @@ -37,43 +48,40 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel @IBOutlet private var recordingChromeContainerView: UIView! @IBOutlet private var recordingIndicatorView: UIView! + @IBOutlet private var elapsedTimeLabel: UILabel! + @IBOutlet private var slideToCancelContainerView: UIView! @IBOutlet private var slideToCancelLabel: UILabel! @IBOutlet private var slideToCancelChevron: UIImageView! @IBOutlet private var slideToCancelGradient: UIImageView! - @IBOutlet private var elapsedTimeLabel: UILabel! + @IBOutlet private var lockContainerView: UIView! + @IBOutlet private var lockContainerBackgroundView: UIView! + @IBOutlet private var primaryLockButton: UIButton! + @IBOutlet private var secondaryLockButton: UIButton! + @IBOutlet private var lockChevron: UIView! + + @IBOutlet private var lockedModeContainerView: UIView! + @IBOutlet private var deleteButton: UIButton! + @IBOutlet private var playbackViewContainerView: UIView! + @IBOutlet private var sendButton: UIButton! + + private var playbackView: VoiceMessagePlaybackView! private var cancelLabelToRecordButtonDistance: CGFloat = 0.0 + private var lockChevronToRecordButtonDistance: CGFloat = 0.0 + private var lockChevronToLockButtonDistance: CGFloat = 0.0 + private var panDirection: UISwipeGestureRecognizer.Direction? + + private var details: VoiceMessageToolbarViewDetails? private var currentTheme: Theme? { didSet { - updateUIAnimated(true) + updateUIWithDetails(details, animated: true) } } weak var delegate: VoiceMessageToolbarViewDelegate? - - var state: VoiceMessageToolbarViewUIState = .idle { - didSet { - switch state { - case .recording: - let convertedFrame = self.convert(slideToCancelLabel.frame, from: slideToCancelContainerView) - cancelLabelToRecordButtonDistance = recordButtonsContainerView.frame.minX - convertedFrame.maxX - startAnimatingRecordingIndicator() - case .idle: - cancelDrag() - } - - updateUIAnimated(true) - } - } - - var elapsedTime: String? { - didSet { - elapsedTimeLabel.text = elapsedTime - } - } @objc static func instanceFromNib() -> VoiceMessageToolbarView { let nib = UINib(nibName: "VoiceMessageToolbarView", bundle: nil) @@ -87,6 +95,7 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel super.awakeFromNib() slideToCancelGradient.image = Asset.Images.voiceMessageCancelGradient.image.withRenderingMode(.alwaysTemplate) + lockContainerBackgroundView.layer.cornerRadius = lockContainerBackgroundView.bounds.width / 2.0 let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress)) longPressGesture.delegate = self @@ -97,7 +106,52 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel longPressGesture.delegate = self recordButtonsContainerView.addGestureRecognizer(panGesture) - updateUIAnimated(false) + playbackView = VoiceMessagePlaybackView.instanceFromNib() + playbackViewContainerView.vc_addSubViewMatchingParent(playbackView) + + updateUIWithDetails(VoiceMessageToolbarViewDetails(), animated: false) + } + + func configureWithDetails(_ details: VoiceMessageToolbarViewDetails) { + elapsedTimeLabel.text = details.elapsedTime + + UIView.animate(withDuration: 0.25) { + self.updatePlaybackViewWithDetails(details) + } + + if self.details?.state != details.state { + switch details.state { + case .record: + var convertedFrame = self.convert(slideToCancelLabel.frame, from: slideToCancelContainerView) + cancelLabelToRecordButtonDistance = recordButtonsContainerView.frame.minX - convertedFrame.maxX + + convertedFrame = self.convert(lockChevron.frame, from: lockContainerView) + lockChevronToRecordButtonDistance = recordButtonsContainerView.frame.midY + convertedFrame.maxY + + lockChevronToLockButtonDistance = lockChevron.frame.minY - primaryLockButton.frame.midY + + startAnimatingRecordingIndicator() + default: + cancelDrag() + } + + if details.state == .lockedModeRecord && self.details?.state == .record { + UIView.animate(withDuration: 0.25) { + self.secondaryLockButton.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) + self.secondaryLockButton.alpha = 0.0 + } completion: { _ in + self.updateUIWithDetails(details, animated: true) + } + } else { + updateUIWithDetails(details, animated: true) + } + } + + self.details = details + } + + func getRequiredNumberOfSamples() -> Int { + return playbackView.getRequiredNumberOfSamples() } // MARK: - Themable @@ -119,8 +173,7 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel case UIGestureRecognizer.State.began: delegate?.voiceMessageToolbarViewDidRequestRecordingStart(self) case UIGestureRecognizer.State.ended: - delegate?.voiceMessageToolbarViewDidRequestRecordingFinish(self) - case UIGestureRecognizer.State.cancelled: + // delegate?.voiceMessageToolbarViewDidRequestRecordingFinish(self) delegate?.voiceMessageToolbarViewDidRequestRecordingCancel(self) default: break @@ -128,17 +181,49 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel } @objc private func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { - guard self.state == .recording && gestureRecognizer.state == .changed else { + guard details?.state == .record && gestureRecognizer.state == .changed else { return } let translation = gestureRecognizer.translation(in: self) - secondaryRecordButton.transform = CGAffineTransform(translationX: min(translation.x, 0.0), y: 0.0) - slideToCancelContainerView.transform = CGAffineTransform(translationX: min(translation.x + cancelLabelToRecordButtonDistance, 0.0), y: 0.0) + if abs(translation.x) <= 20.0 && abs(translation.y) <= 20.0 { + panDirection = nil + } else if panDirection == nil { + if abs(translation.x) >= abs(translation.y) { + panDirection = .left + } else { + panDirection = .up + } + } - if abs(translation.x - recordButtonsContainerView.frame.width / 2.0) > self.bounds.width / 2.0 { - cancelDrag() + if panDirection == .left { + secondaryRecordButton.transform = CGAffineTransform(translationX: min(translation.x, 0.0), y: 0.0) + slideToCancelContainerView.transform = CGAffineTransform(translationX: min(translation.x + cancelLabelToRecordButtonDistance, 0.0), y: 0.0) + + if abs(translation.x - recordButtonsContainerView.frame.width / 2.0) > self.bounds.width / 2.0 { + delegate?.voiceMessageToolbarViewDidRequestRecordingCancel(self) + } + } else if panDirection == .up { + secondaryRecordButton.transform = CGAffineTransform(translationX: 0.0, y: min(0.0, translation.y)) + + let yTranslation = min(max(translation.y + lockChevronToRecordButtonDistance, -lockChevronToLockButtonDistance), 0.0) + lockChevron.transform = CGAffineTransform(translationX: 0.0, y: yTranslation) + + let transitionPercentage = abs(yTranslation) / lockChevronToLockButtonDistance + + lockChevron.alpha = 1.0 - transitionPercentage + secondaryRecordButton.alpha = 1.0 - transitionPercentage + primaryLockButton.alpha = 1.0 - transitionPercentage + lockContainerBackgroundView.alpha = 1.0 - transitionPercentage + secondaryLockButton.alpha = transitionPercentage + + if transitionPercentage >= 1.0 { + self.delegate?.voiceMessageToolbarViewDidRequestLockedModeRecording(self) + } + + } else { + secondaryRecordButton.transform = CGAffineTransform(translationX: min(0.0, translation.x), y: min(0.0, translation.y)) } } @@ -149,19 +234,42 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel } } - private func updateUIAnimated(_ animated: Bool) { - UIView.animate(withDuration: (animated ? 0.25 : 0.0)) { - switch self.state { - case .idle: - self.backgroundView.alpha = 0.0 - self.primaryRecordButton.alpha = 1.0 - self.secondaryRecordButton.alpha = 0.0 - self.recordingChromeContainerView.alpha = 0.0 - case .recording: + private func updateUIWithDetails(_ details: VoiceMessageToolbarViewDetails?, animated: Bool) { + guard let details = details else { + return + } + + UIView.animate(withDuration: (animated ? 0.25 : 0.0), delay: 0.0, options: .beginFromCurrentState) { + switch details.state { + case .record: self.backgroundView.alpha = 1.0 self.primaryRecordButton.alpha = 0.0 self.secondaryRecordButton.alpha = 1.0 self.recordingChromeContainerView.alpha = 1.0 + self.lockContainerView.alpha = 1.0 + self.lockContainerBackgroundView.alpha = 1.0 + self.lockedModeContainerView.alpha = 0.0 + self.recordingContainerView.alpha = 1.0 + case .lockedModeRecord: + self.backgroundView.alpha = 1.0 + self.primaryRecordButton.alpha = 0.0 + self.secondaryRecordButton.alpha = 0.0 + self.recordingChromeContainerView.alpha = 0.0 + self.lockContainerView.alpha = 0.0 + self.lockedModeContainerView.alpha = 1.0 + self.recordingContainerView.alpha = 0.0 + default: + self.backgroundView.alpha = 0.0 + self.primaryRecordButton.alpha = 1.0 + self.secondaryRecordButton.alpha = 0.0 + self.recordingChromeContainerView.alpha = 0.0 + self.lockContainerView.alpha = 0.0 + self.lockContainerBackgroundView.alpha = 1.0 + self.primaryLockButton.alpha = 1.0 + self.secondaryLockButton.alpha = 0.0 + self.lockChevron.alpha = 1.0 + self.lockedModeContainerView.alpha = 0.0 + self.recordingContainerView.alpha = 1.0 } guard let theme = self.currentTheme else { @@ -176,18 +284,30 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel self.slideToCancelChevron.tintColor = theme.textSecondaryColor self.elapsedTimeLabel.textColor = theme.textSecondaryColor } completion: { _ in - switch self.state { + switch details.state { case .idle: self.secondaryRecordButton.transform = .identity self.slideToCancelContainerView.transform = .identity + self.lockChevron.transform = .identity + self.secondaryLockButton.transform = .identity default: break } } } + private func updatePlaybackViewWithDetails(_ details: VoiceMessageToolbarViewDetails) { + var playbackViewDetails = VoiceMessagePlaybackViewDetails() + playbackViewDetails.recording = (details.state == .record || details.state == .lockedModeRecord) + playbackViewDetails.currentTime = details.elapsedTime + playbackViewDetails.samples = details.audioSamples + playbackViewDetails.playbackEnabled = true + playbackViewDetails.progress = 0.0 + playbackView.configureWithDetails(playbackViewDetails) + } + private func startAnimatingRecordingIndicator() { - if self.state != .recording { + if self.details?.state != .record { return } @@ -202,4 +322,12 @@ class VoiceMessageToolbarView: PassthroughView, Themable, UIGestureRecognizerDel } } + + @IBAction private func onTrashButtonTap(_ sender: UIBarItem) { + delegate?.voiceMessageToolbarViewDidRequestRecordingCancel(self) + } + + @IBAction private func onSendButtonTap(_ sender: UIBarItem) { + delegate?.voiceMessageToolbarViewDidRequestRecordingFinish(self) + } } diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib index 6218ad96ac..fe548450b9 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.xib @@ -11,121 +11,236 @@ - + - + - - + + - - + + - - + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - + + - - + + + + + + + + + + + + + + - - - - - - - - - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + - + + + + + + diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageWaveformView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageWaveformView.swift index 39c159e04a..8a7a65dffb 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageWaveformView.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageWaveformView.swift @@ -56,11 +56,6 @@ class VoiceMessageWaveformView: UIView { updateBarViews() } - func addSample(_ sample: Float) { - samples.append(sample) - updateBarViews() - } - // MARK: - Private private func setupBarViews() {