From 2c1324ba74b31c09093f28cfc9a8cd5963cd9412 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 4 Jan 2022 15:46:07 +0300 Subject: [PATCH 01/33] Update icons & summary view margins --- .../Thread.png | Bin 318 -> 0 bytes .../Thread@2x.png | Bin 418 -> 0 bytes .../Thread@3x.png | Bin 706 -> 0 bytes .../Contents.json | 26 ++++++++++++++++++ .../Vector.png | Bin 0 -> 389 bytes .../Vector@2x.png | Bin 0 -> 593 bytes .../Vector@3x.png | Bin 0 -> 801 bytes .../threads_icon.imageset}/Contents.json | 3 ++ .../Threads/threads_icon.imageset/Thread.png | Bin 0 -> 484 bytes .../threads_icon.imageset/Thread@2x.png | Bin 0 -> 780 bytes .../threads_icon.imageset/Thread@3x.png | Bin 0 -> 1029 bytes Riot/Generated/Images.swift | 3 +- .../RoomContextualMenuAction.swift | 2 +- Riot/Modules/Room/RoomViewController.m | 3 +- .../Views/Threads/ThreadSummaryView.swift | 3 +- .../Room/Views/Threads/ThreadSummaryView.xib | 22 +++++++-------- .../ThreadList/ThreadListViewModel.swift | 4 +-- .../Views/Empty/ThreadListEmptyView.swift | 1 + .../Views/Empty/ThreadListEmptyView.xib | 4 +-- 19 files changed, 52 insertions(+), 19 deletions(-) delete mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Thread.png delete mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Thread@2x.png delete mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Thread@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Vector.png create mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Vector@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Vector@3x.png rename Riot/Assets/Images.xcassets/Room/{ContextMenu/room_context_menu_reply_in_thread.imageset => Threads/threads_icon.imageset}/Contents.json (84%) create mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Thread.png create mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Thread@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Thread@3x.png diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Thread.png b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Thread.png deleted file mode 100644 index ec23ad509d45acc94beb51fef16bf7fdda0b0902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg?3oVGw3ym^DWND9BhG z=tK=QvEMO8= zR8pGBA#K!Y$(U!5cYya9N1p-v0`KUbFVFqauUYN)b@lc4y0a2Ki0v+G&P?gk6=^Nt z37ah3JN-6eBmat~X?&Xtt5 z!$1&4?@TBpr6iS*bbzq@1wkO-2a}`(QUV>|7U%%_Ks)SUtXO&NN^!+Q{)Q{<5G;4GW3BaaWYgX*88F|4fF3n ziLVZtu1<-s5<8;}9D}+rT1F=nqIE(Sam!@k9KNv!Oz4B?GPEv2NEXw_bc`BEZZm|W zjxjPCC6f#-imZ@gqgtMBm&Ha>gHU{z#dJ}K)9o_D$O@^m?XpfNL?^Th9ULRO?C^*m z7-!{N)&|H=uX=4p!Vx$HWg!bUKkz|TMi#=J@o7{D@l##) zz)kW%$j#$-qg3AnWwa2*cW_sfrY9Mm#PM{lVJ>X%;AqFa^7|JU;jJRpS94(q_!>MR zfM8pnQFlQm#5s6`V6!^`n-zWV4DG!EcuFVCH9BFg;jOR`Y#~V1L^FpqLVAjaU}Z;E z!cfv+@^+X&1MD3f$7*IY1w+hBktl6Sl;+dnFhPXW@MB%`_zPlRmj^V&(^r#SBJ*)( zH^x-W@4uXE6Rx*;AVJSYl*YO%l4Z9te1|pN7;}wA4Z4oun$oyI+ZwJZjT^MB;hNGl zj|DXi+SYJQY1E+W7_KRe8gw1QHKiM4uF(l|jZTIc5yEmkCqm%_In=l zSIf`pyE#>>>Kol(#1&QnMOb8)GgQS&m`Z&n89hn(XzfdUTWm`4t4jUdHjC02Wvt1c zkLt3Lutn(|wmVCgS)~-6D7`9IX3VA1s}cqqluNPPUtKJ{D(uJUw_gt)KDw>;)b9U@ o>C$_g@D~~QK+KQ&`T$S(4FO#8{Gg*8G5`Po07*qoM6N<$f{Z{lTmS$7 diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json new file mode 100644 index 0000000000..32dd965fbd --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "Vector.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Vector@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Vector@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Vector.png b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Vector.png new file mode 100644 index 0000000000000000000000000000000000000000..38cd35e5f76db714560f013800ebf86df3f923b7 GIT binary patch literal 389 zcmV;00eb$4P)J9V;&Jm&#D8#Gy zpY_Xgm6PV4XJq1>t)+6(?4V-<-$4zQpXt2(=CS6PuC`R*?G~-zrIKlL)N6~#u~`-3 zPw=OlF)T}i<|w%mHbOTvGY0mdOHw+NVlzsarJL=a{#cLSF?)TTt2`RV=NdIoJb|rC jZE_sgpMM|WK~#7F?U+qY z!ax+q-%LkcU`TJEN6;JC5Et(B2%dnFhzToT#R3g@0^9%Bh>VLu zWLyZHq`>U=#J%z?h#A>U`d^iLZC#GmPI^0rorFLI0odwLvo7cVe3QcP`$X^#2|z@$ zyETUEaF_DLQ8(h#S5z5;bNPTnNDx9=STor~Hi}el<|DM28mJPa&eZTOR*Ezq zTPB(%IkTjUhN^NNW1_?MplM}Rks#GGG8#G7o5v&#@ zRN|ekX>h?f@!F1rce_6!KD@g!f6eTAW<4hG1l7r9gBax#AlLwe8b|~oaED0l0R6AO zn(x1a$KyJi-!5zZ3;KzRY=9cL%is6b;#J?>5nTEHv2K(M2LMe_3y=9|Z3$jk_MrSj zL9uH*WAm4PKvlHtCT1x3SSTaO!Drt}≶Kg>C?jc*XLY4; z<2d5}d!k^~(1KM*3sxO1Satq8!4z_E=v5-v%8A3kU2C z;su)%v*uYxbVROIde(dwoJja&ML^GC)zN}gN5|4>c%E1~eLS3p0>skkGbh%9&{|NI$E&mXu+zZ1*?u0tP-X(+{xsW7RE&MPq z_@*67l@9)cc+6mykl??CP=>b%!scWErG#c|&SNyxryi8wA9^P^y1fJ9`lFkkH$Ud&r( zQdP;XNh?@77mgzA(z3d6luZiMH4T3NI%p$g3v_#z00000NkvXXu0mjf_{3j^ literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Contents.json similarity index 84% rename from Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Contents.json rename to Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Contents.json index d2c033d2dd..92eec13622 100644 --- a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_reply_in_thread.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Threads/threads_icon.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/Threads/threads_icon.imageset/Thread.png b/Riot/Assets/Images.xcassets/Room/Threads/threads_icon.imageset/Thread.png new file mode 100644 index 0000000000000000000000000000000000000000..b2cc0cb7234fc8f5f2abb293b0549d547c373106 GIT binary patch literal 484 zcmVGAwoIq12c>QPzZ^V zzDyf|tdRnL{DKzO5k3=0h_q+FW;zM|;d5Px-s0-oc6g8tGGGh+hSw%x5xw?qZAXAq zGX6+5{aBGm0%0GUgtUmZTKwq{l84#jU<3obp*{CA?;s)CB-D1l@${5hA_dwcO3aJP zo9PP-FiS^}978)$BTE)AkVYWjcy@gApC!b_UrPwoD!MlPw(~Gp%_dh%B$5y~{>ZvW z0gJ5c9d{3-g!p#_7S*<6E-qQX1_MV~AB{W(0%DW+I=sf_!z*(M&+^XM<4(}K={Vo7 aFC3q^XLw01qM;!G0000;`EFqR4QCktk5ouGEpPChvtf1LJ=nm)#;_iT|l_~+A z$ryqZ0VXhGf$f=3LNc}oG{@&&-}wOy27^IkXq%fo|Hic<=bdQw7MX_sV&lnO@a04J z(w!R#;Jv?b?Sq5w;;@WdLA_`^x>_g1ivoBbzaHAQ{X?kgB9~BTMbUBd^Z8)q)pbp0 zPyW??emg&hLg9qUDkoU$nu*R|=D+hXd>+C}Bs$h z!T!M`C`8uY-9R=!!7h{F4DJ%>8*GleVhSN>ju8Nwqgo1gBj=wV_`cFx!1Mi* zGkN22qD$-;6#;tf>zaoYcoNXB)|)Pfc3NLZhX9Y*PoxZIRv$Y?J_k7DB5fo}Sykjq zVNR#<>Jd^R{wTP>Pq%su!)kr~^YNAlBzxOqbqwUr{QS!c)py?Xt)irVxVW z7y+O;MgVAz5da!N9Df$iX(a$BwzOAJ8v){#EM`aj#q;_&fY@!|FK?7gV=Rz;I0l`@ znZN3i4i2~z({_oAxW#oqymT*Y-)Wrp*4>t}05l}dx{O&N_5@jc7&+s?s(4>TY68r% z?5MKoA7_Pha)6i~XZGKtymdZC(E-Bpj9s-podw7#N?T;6mT%U}oXkrghb7(7*O7r?V?XzwL{}hsfhU$ z-$sX*ZMp?btJFKZgY8tjWQACQE?==^e9BgGwyA?P`Vi*{K_$l7OFkygDRXSJO1`cy ztM>o?qO7NxOTXpYpAXMf0$Rtw(6CuVRH0&D_~$86;Y+f9o#qk@&*0Qp#;9$o@NDtl zvd6YhOBM=jiz|6`L@Q>ReU+7I$}F?pYmc{230x=8w0!;Qx}AT*>Z6o@1lL>5%yG$| z$LqUav6w@hG3Mur^Z&FCT3#uzl3YKNZK7t20*Cg$Q>VmP5}epS-rX(gI(u=YuI;G< zySHuXX7DN8x<%;ytSu({g#6w!-{&xzX|&$;?c2I2>BriR_t|@bS~u4O@ju&oGN7;G z9e;Cuz!o_c_LZ>}iv^^r4BR$5N<0Zzxcd0&Ox_-+4$-wjPo5opIahLX(UBcodPjn< zUOCJ%olh}>0WVtMGHFKD>yQw0E@5?WTxm;>uO%GCeB$qZQ{^dv#_f=T0pN zwA~l9d)*1-iJGGGI1Ov zgc1d31c}cSIK*_Mi!JlGVAGz!ME>Qicb@GFXH?{v{cG~GJ!Tw^Lc!-#zAHKj96Gu9 zx3|61|4nhuZ`mZlCFuC==MWE~06?@JDHSL{m*1cJ}$W5zncICGRN-cLng0kFv z?tGtdzw}nG-P00HMHSQFe&yYlD8}8Bapw@ - + - + - - + + - + @@ -84,6 +84,6 @@ - + diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 1e980520d6..b4de8df797 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -117,14 +117,14 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { private var emptyViewModel: ThreadListEmptyViewModel { switch selectedFilterType { case .all: - return ThreadListEmptyViewModel(icon: Asset.Images.roomContextMenuReplyInThread.image, + return ThreadListEmptyViewModel(icon: Asset.Images.threadsIcon.image, title: VectorL10n.threadsEmptyTitle, info: VectorL10n.threadsEmptyInfoAll, tip: VectorL10n.threadsEmptyTip, showAllThreadsButtonTitle: VectorL10n.threadsEmptyShowAllThreads, showAllThreadsButtonHidden: true) case .myThreads: - return ThreadListEmptyViewModel(icon: Asset.Images.roomContextMenuReplyInThread.image, + return ThreadListEmptyViewModel(icon: Asset.Images.threadsIcon.image, title: VectorL10n.threadsEmptyTitle, info: VectorL10n.threadsEmptyInfoMy, tip: VectorL10n.threadsEmptyTip, diff --git a/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.swift b/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.swift index 213f1fa189..98e9b05357 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.swift @@ -64,6 +64,7 @@ extension ThreadListEmptyView: Themable { func update(theme: Theme) { iconBackgroundView.backgroundColor = theme.colors.system + iconView.tintColor = theme.colors.secondaryContent titleLabel.textColor = theme.colors.primaryContent infoLabel.textColor = theme.colors.secondaryContent tipLabel.textColor = theme.colors.secondaryContent diff --git a/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.xib b/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.xib index 50c62af99d..bf0f68982f 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.xib +++ b/Riot/Modules/Threads/ThreadList/Views/Empty/ThreadListEmptyView.xib @@ -36,7 +36,7 @@ - + @@ -105,6 +105,6 @@ - + From 48a027215d825da7838531cac4f04481ca48760a Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 4 Jan 2022 16:31:53 +0300 Subject: [PATCH 02/33] Shrink summary view if content is small --- Riot/Modules/Room/DataSources/RoomDataSource.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 6cdcb8efe9..6f3b583b96 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -553,7 +553,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N constant:leftMargin], topConstraint, [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:component.thread fitting:cellData.maxTextViewWidth]], - [threadSummaryView.trailingAnchor constraintEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] ]]; } From e422917cf3a4a5653394c98400150b621fa2f6da Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 4 Jan 2022 17:26:47 +0300 Subject: [PATCH 03/33] User name coloring on thread list --- .../ThreadList/ThreadListViewController.swift | 2 +- .../Threads/ThreadList/ThreadListViewModel.swift | 3 ++- .../ThreadList/Views/Cell/ThreadTableViewCell.swift | 12 ++++++++++++ .../ThreadList/Views/Cell/ThreadViewModel.swift | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift index 56f16c5dfd..9b9b55bc81 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift @@ -249,10 +249,10 @@ extension ThreadListViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: ThreadTableViewCell = tableView.dequeueReusableCell(for: indexPath) + cell.update(theme: theme) if let threadVM = viewModel.threadViewModel(at: indexPath.row) { cell.configure(withViewModel: threadVM) } - cell.update(theme: theme) return cell } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index b4de8df797..0a3e8aaad2 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -179,7 +179,8 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { lastMessageSenderAvatar: lastAvatarViewData, lastMessageText: lastMessageText) - return ThreadViewModel(rootMessageSenderAvatar: rootAvatarViewData, + return ThreadViewModel(rootMessageSenderUserId: rootMessageSender?.userId, + rootMessageSenderAvatar: rootAvatarViewData, rootMessageSenderDisplayName: rootMessageSender?.displayname, rootMessageText: rootMessageText, lastMessageTime: lastMessageTime, diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift index 000ee1b57c..3a17d8b11e 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift @@ -28,6 +28,11 @@ class ThreadTableViewCell: UITableViewCell { @IBOutlet private weak var rootMessageContentLabel: UILabel! @IBOutlet private weak var lastMessageTimeLabel: UILabel! @IBOutlet private weak var summaryView: ThreadSummaryView! + + private static var usernameColorGenerator: UserNameColorGenerator = { + let generator = UserNameColorGenerator() + return generator + }() override func awakeFromNib() { super.awakeFromNib() @@ -41,6 +46,11 @@ class ThreadTableViewCell: UITableViewCell { } else { rootMessageAvatarView.avatarImageView.image = nil } + if let senderUserId = viewModel.rootMessageSenderUserId { + rootMessageSenderLabel.textColor = Self.usernameColorGenerator.color(from: senderUserId) + } else { + rootMessageSenderLabel.textColor = Self.usernameColorGenerator.defaultColor + } rootMessageSenderLabel.text = viewModel.rootMessageSenderDisplayName rootMessageContentLabel.text = viewModel.rootMessageText lastMessageTimeLabel.text = viewModel.lastMessageTime @@ -56,6 +66,8 @@ extension ThreadTableViewCell: NibReusable {} extension ThreadTableViewCell: Themable { func update(theme: Theme) { + Self.usernameColorGenerator.defaultColor = theme.colors.primaryContent + Self.usernameColorGenerator.userNameColors = theme.colors.namesAndAvatars rootMessageAvatarView.backgroundColor = .clear rootMessageContentLabel.textColor = theme.colors.primaryContent lastMessageTimeLabel.textColor = theme.colors.secondaryContent diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift index 9bc8423452..9692058f43 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift @@ -17,6 +17,7 @@ import Foundation struct ThreadViewModel { + var rootMessageSenderUserId: String? var rootMessageSenderAvatar: AvatarViewDataProtocol? var rootMessageSenderDisplayName: String? var rootMessageText: String? From 9a5bc717ade480bc5b5e27ebcb2a31532ec5d9fe Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 4 Jan 2022 17:27:13 +0300 Subject: [PATCH 04/33] Layout fixes --- .../Room/Views/Threads/ThreadSummaryView.xib | 5 +++- .../Views/Cell/ThreadTableViewCell.xib | 27 ++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib b/Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib index 66752fca3b..12f97e11c2 100644 --- a/Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib +++ b/Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib @@ -34,6 +34,9 @@ - + @@ -58,7 +58,7 @@ - + From d5de3a9b2ff70c1ca843e019a143666214c1efa6 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 17 Jan 2022 16:32:32 +0300 Subject: [PATCH 18/33] Various design fixes --- Riot/Modules/Room/RoomViewController.m | 2 +- .../Title/Thread/ThreadRoomTitleView.xib | 18 ++++---- .../ThreadList/ThreadListViewModel.swift | 3 +- .../Views/Cell/ThreadTableViewCell.swift | 44 ++++++++++++++++--- .../Views/Cell/ThreadViewModel.swift | 1 + 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index b6b4539677..ebb0231794 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1541,7 +1541,7 @@ - (UIBarButtonItem *)threadMoreBarButtonItem - (UIBarButtonItem *)threadListBarButtonItem { - UIImage *icon = [[UIImage imageNamed:@"threads_icon"] vc_resizedWith:CGSizeMake(24, 24)]; + UIImage *icon = [[UIImage imageNamed:@"threads_icon"] vc_resizedWith:CGSizeMake(21, 21)]; UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:icon style:UIBarButtonItemStylePlain target:self diff --git a/Riot/Modules/Room/Views/Title/Thread/ThreadRoomTitleView.xib b/Riot/Modules/Room/Views/Title/Thread/ThreadRoomTitleView.xib index 577c143295..08667bfdc9 100644 --- a/Riot/Modules/Room/Views/Title/Thread/ThreadRoomTitleView.xib +++ b/Riot/Modules/Room/Views/Title/Thread/ThreadRoomTitleView.xib @@ -16,31 +16,31 @@ - + - + - + - + @@ -59,7 +59,7 @@ - + @@ -95,7 +95,7 @@ - + diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index ab8333a74b..9156e5018f 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -136,7 +136,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { return ThreadListEmptyViewModel(icon: Asset.Images.threadsIcon.image, title: VectorL10n.threadsEmptyTitle, info: VectorL10n.threadsEmptyInfoMy, - tip: VectorL10n.threadsEmptyTip, + tip: nil, showAllThreadsButtonTitle: VectorL10n.threadsEmptyShowAllThreads, showAllThreadsButtonHidden: false) } @@ -192,6 +192,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { rootMessageSenderAvatar: rootAvatarViewData, rootMessageSenderDisplayName: rootMessageSender?.displayname, rootMessageText: rootMessageText, + rootMessageRedacted: thread.rootMessage?.isRedactedEvent() ?? false, lastMessageTime: lastMessageTime, summaryViewModel: summaryViewModel) } diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift index 3cb09e0aa6..20b7dfdfcd 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift @@ -22,6 +22,16 @@ class ThreadTableViewCell: UITableViewCell { private enum Constants { static let separatorInset: UIEdgeInsets = UIEdgeInsets(top: 0, left: 56, bottom: 0, right: 0) } + + private var theme: Theme = ThemeService.shared().theme + private var configuredSenderId: String? + private var configuredRootMessageRedacted: Bool = false + + private var rootMessageColor: UIColor { + return configuredRootMessageRedacted ? + theme.colors.secondaryContent : + theme.colors.primaryContent + } @IBOutlet private weak var rootMessageAvatarView: UserAvatarView! @IBOutlet private weak var rootMessageSenderLabel: UILabel! @@ -46,19 +56,37 @@ class ThreadTableViewCell: UITableViewCell { } else { rootMessageAvatarView.avatarImageView.image = nil } - if let senderUserId = viewModel.rootMessageSenderUserId { - rootMessageSenderLabel.textColor = Self.usernameColorGenerator.color(from: senderUserId) + configuredSenderId = viewModel.rootMessageSenderUserId + configuredRootMessageRedacted = viewModel.rootMessageRedacted + updateRootMessageSenderColor() + rootMessageSenderLabel.text = viewModel.rootMessageSenderDisplayName + if let rootMessageText = viewModel.rootMessageText { + updateRootMessageContentAttributes(rootMessageText, color: rootMessageColor) } else { - rootMessageSenderLabel.textColor = Self.usernameColorGenerator.defaultColor + rootMessageContentLabel.attributedText = nil } - rootMessageSenderLabel.text = viewModel.rootMessageSenderDisplayName - rootMessageContentLabel.attributedText = viewModel.rootMessageText lastMessageTimeLabel.text = viewModel.lastMessageTime if let summaryViewModel = viewModel.summaryViewModel { summaryView.configure(withViewModel: summaryViewModel) } } + private func updateRootMessageSenderColor() { + if let senderUserId = configuredSenderId { + rootMessageSenderLabel.textColor = Self.usernameColorGenerator.color(from: senderUserId) + } else { + rootMessageSenderLabel.textColor = Self.usernameColorGenerator.defaultColor + } + } + + private func updateRootMessageContentAttributes(_ string: NSAttributedString, color: UIColor) { + let mutable = NSMutableAttributedString(attributedString: string) + mutable.addAttributes([ + .foregroundColor: color + ], range: NSRange(location: 0, length: mutable.length)) + rootMessageContentLabel.attributedText = mutable + } + } extension ThreadTableViewCell: NibReusable {} @@ -66,10 +94,14 @@ extension ThreadTableViewCell: NibReusable {} extension ThreadTableViewCell: Themable { func update(theme: Theme) { + self.theme = theme Self.usernameColorGenerator.defaultColor = theme.colors.primaryContent Self.usernameColorGenerator.userNameColors = theme.colors.namesAndAvatars + updateRootMessageSenderColor() rootMessageAvatarView.backgroundColor = .clear - rootMessageContentLabel.textColor = theme.colors.primaryContent + if let attributedText = rootMessageContentLabel.attributedText { + updateRootMessageContentAttributes(attributedText, color: rootMessageColor) + } lastMessageTimeLabel.textColor = theme.colors.secondaryContent summaryView.update(theme: theme) summaryView.backgroundColor = .clear diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift index 561625589b..768cb5c37f 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadViewModel.swift @@ -21,6 +21,7 @@ struct ThreadViewModel { var rootMessageSenderAvatar: AvatarViewDataProtocol? var rootMessageSenderDisplayName: String? var rootMessageText: NSAttributedString? + var rootMessageRedacted: Bool var lastMessageTime: String? var summaryViewModel: ThreadSummaryViewModel? } From d7ed2d3b09e81c09671db849b10f7e31a87e796f Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 17 Jan 2022 16:33:02 +0300 Subject: [PATCH 19/33] Fix event content where the thread root event is a reply event --- .../ThreadList/ThreadListViewModel.swift | 17 +++++++++++++++++ RiotNSE/NotificationService.swift | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 9156e5018f..afaa69a67c 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -204,6 +204,23 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { guard let message = thread.rootMessage else { return nil } + if message.isReply(), let newMessage = message.copy() as? MXEvent { + var jsonDict = newMessage.isEncrypted ? newMessage.clear?.jsonDictionary() : newMessage.jsonDictionary() + if var content = jsonDict?["content"] as? [String: Any] { + content.removeValue(forKey: "format") + content.removeValue(forKey: "formatted_body") + content.removeValue(forKey: kMXEventRelationRelatesToKey) + if let replyText = MXReplyEventParser().parse(newMessage)?.bodyParts.replyText { + content["body"] = replyText + } + jsonDict?["content"] = content + } + let trimmedMessage = MXEvent(fromJSON: jsonDict) + let formatterError = UnsafeMutablePointer.allocate(capacity: 1) + return eventFormatter.attributedString(from: trimmedMessage, + with: roomState, + error: formatterError) + } let formatterError = UnsafeMutablePointer.allocate(capacity: 1) return eventFormatter.attributedString(from: message, with: roomState, diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index c77a9dd86b..b43eb8d7be 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -427,7 +427,7 @@ class NotificationService: UNNotificationServiceExtension { if event.isReply() { let parser = MXReplyEventParser() let replyParts = parser.parse(event) - notificationBody = replyParts.bodyParts.replyText + notificationBody = replyParts?.bodyParts.replyText } else { notificationBody = messageContent } From b7b84ad461f4db5f58122787244d9a2b34857a84 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 02:27:23 +0300 Subject: [PATCH 20/33] Align summary last message to the time label --- .../Threads/ThreadList/Views/Cell/ThreadTableViewCell.xib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.xib b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.xib index 3ed1d2ad9d..2b0d46b1b4 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.xib +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.xib @@ -45,7 +45,7 @@ - + @@ -65,7 +65,7 @@ - + From 21d6ea50003790e650214b662458c3e6da221f96 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 02:27:44 +0300 Subject: [PATCH 21/33] Dismiss keyboard when additional menu shown --- Riot/Modules/Room/RoomViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index ebb0231794..3426c1e0bf 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -3890,6 +3890,7 @@ - (void)showAdditionalActionsMenuForEvent:(MXEvent*)selectedEvent inCell:(id Date: Tue, 18 Jan 2022 02:37:25 +0300 Subject: [PATCH 22/33] Speed up toast animation --- Riot/Categories/UIView+Toast.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Categories/UIView+Toast.swift b/Riot/Categories/UIView+Toast.swift index e00858afc8..b8d2db9aa8 100644 --- a/Riot/Categories/UIView+Toast.swift +++ b/Riot/Categories/UIView+Toast.swift @@ -95,7 +95,7 @@ private class ToastOperation: AsyncOperation { private enum Constants { static let margin: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) - static let animationDuration: TimeInterval = 0.25 + static let animationDuration: TimeInterval = 0.15 static let timeBetweenToasts: TimeInterval = 0.5 } From 0cb4d668539a468eab81b8278dc337bb8df48175 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 02:57:30 +0300 Subject: [PATCH 23/33] Center empty view vertically in the whole screen --- .../Threads/ThreadList/ThreadListViewController.storyboard | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard b/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard index c56d0f29dd..9dd19eee18 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard @@ -28,7 +28,7 @@ - + @@ -42,10 +42,10 @@ + - From b9ccd522cbad561a6813bb19440f0896b1f2f948 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 03:13:22 +0300 Subject: [PATCH 24/33] Fix thread screen call button case --- Riot/Modules/TabBar/TabBarCoordinator.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/TabBar/TabBarCoordinator.swift b/Riot/Modules/TabBar/TabBarCoordinator.swift index 141e9ff5bb..1d8c2e86c6 100644 --- a/Riot/Modules/TabBar/TabBarCoordinator.swift +++ b/Riot/Modules/TabBar/TabBarCoordinator.swift @@ -447,11 +447,19 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType { self.activityIndicatorPresenter.removeCurrentActivityIndicator(animated: true) } } else { + let threadId = roomNavigationParameters.threadParameters?.threadId + let displayConfig: RoomDisplayConfiguration + if threadId != nil { + displayConfig = .forThreads + } else { + displayConfig = .default + } let roomCoordinatorParameters = RoomCoordinatorParameters(navigationRouterStore: NavigationRouterStore.shared, session: roomNavigationParameters.mxSession, roomId: roomNavigationParameters.roomId, eventId: roomNavigationParameters.eventId, - threadId: roomNavigationParameters.threadParameters?.threadId) + threadId: threadId, + displayConfiguration: displayConfig) self.showRoom(with: roomCoordinatorParameters, stackOnSplitViewDetail: roomNavigationParameters.presentationParameters.stackAboveVisibleViews, From cb57694d32e6ae547490858a1b85b85e2fb0cf31 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 14:44:56 +0300 Subject: [PATCH 25/33] Add thread decoration views for search results, fix #5268 --- Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Generated/Strings.swift | 4 ++ .../HomeMessagesSearchDataSource.m | 54 +++++++++++++++++ .../HomeMessagesSearchViewController.m | 31 ++++++---- .../Room/CellData/RoomBubbleCellData.m | 33 ++++++++++- .../Search/DataSources/RoomSearchDataSource.m | 58 +++++++++++++++++- .../Encryption/RoomBubbleCellLayout.swift | 1 + .../Views/Threads/From/FromThreadView.swift | 54 +++++++++++++++++ .../Views/Threads/From/FromThreadView.xib | 59 +++++++++++++++++++ .../{ => Summary}/ThreadSummaryView.swift | 0 .../{ => Summary}/ThreadSummaryView.xib | 0 .../ThreadSummaryViewModel.swift | 0 12 files changed, 282 insertions(+), 13 deletions(-) create mode 100644 Riot/Modules/Room/Views/Threads/From/FromThreadView.swift create mode 100644 Riot/Modules/Room/Views/Threads/From/FromThreadView.xib rename Riot/Modules/Room/Views/Threads/{ => Summary}/ThreadSummaryView.swift (100%) rename Riot/Modules/Room/Views/Threads/{ => Summary}/ThreadSummaryView.xib (100%) rename Riot/Modules/Room/Views/Threads/{ => Summary}/ThreadSummaryViewModel.swift (100%) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 228729ca02..fa0e22733b 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -446,6 +446,7 @@ Tap the + to start adding people."; "threads_empty_info_my" = "Reply to an ongoing thread or tap a message and use “Thread” to start a new one."; "threads_empty_tip" = "Tip: Tap a message and use “Thread” to start one."; "threads_empty_show_all_threads" = "Show all threads"; +"message_from_a_thread" = "From a thread"; "media_type_accessibility_image" = "Image"; "media_type_accessibility_audio" = "Audio"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 49ebc94ffd..7a9b3f80c1 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2319,6 +2319,10 @@ public class VectorL10n: NSObject { public static var mediaTypeAccessibilityVideo: String { return VectorL10n.tr("Vector", "media_type_accessibility_video") } + /// From a thread + public static var messageFromAThread: String { + return VectorL10n.tr("Vector", "message_from_a_thread") + } /// More public static var more: String { return VectorL10n.tr("Vector", "more") diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 950715c176..6339a51b4a 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -115,6 +115,60 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Display date for each message [bubbleCell addDateLabel]; + + RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; + MXEvent *event = cellData.events.firstObject; + + if (event) + { + if (cellData.hasThreadRoot) + { + MXThread *thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + [bubbleCell.tmpSubviews addObject:threadSummaryView]; + + threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:threadSummaryView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor + constant:leftMargin], + [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]], + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + else if (event.isInThread) + { + FromThreadView *fromThreadView = [FromThreadView instantiate]; + [bubbleCell.tmpSubviews addObject:fromThreadView]; + + fromThreadView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:fromThreadView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor + constant:leftMargin], + [fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], + [fromThreadView.heightAnchor constraintEqualToConstant:[FromThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]], + [fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + } } return cell; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index b0dd6b9135..f258b9c3e9 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -156,18 +156,29 @@ - (void)refreshSearchResult:(NSNotification *)notif } - (void)showRoomWithId:(NSString*)roomId - andEventId:(NSString*)eventId + andEvent:(MXEvent*)event inMatrixSession:(MXSession*)session { - ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO]; - + ThreadParameters *threadParameters = nil; + if (event.threadId) + { + threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId + stackRoomScreen:NO]; + } + else if ([self.mainSession.threadingService isEventThreadRoot:event]) + { + threadParameters = [[ThreadParameters alloc] initWithThreadId:event.eventId + stackRoomScreen:NO]; + } + + ScreenPresentationParameters *screenParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO]; + RoomNavigationParameters *parameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId - eventId:eventId - mxSession:session - threadParameters:nil - presentationParameters:presentationParameters]; - - [[AppDelegate theDelegate] showRoomWithParameters:parameters]; + eventId:event.eventId + mxSession:self.mainSession + threadParameters:threadParameters + presentationParameters:screenParameters]; + [[LegacyAppDelegate theDelegate] showRoomWithParameters:parameters]; } #pragma mark - MXKDataSourceDelegate @@ -264,7 +275,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath // Make the master tabBar view controller open the RoomViewController [self showRoomWithId:cellData.roomId - andEventId:_selectedEvent.eventId + andEvent:_selectedEvent inMatrixSession:cellData.mxSession]; // Reset the selected event. HomeViewController got it when here diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 8602f43703..55c2212401 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -573,6 +573,8 @@ - (void)addVerticalWhitespaceToString:(NSMutableAttributedString *)attributedStr additionalVerticalHeight+= [self reactionHeightForEventId:eventId]; // Add vertical whitespace in case of a thread root additionalVerticalHeight+= [self threadSummaryViewHeightForEventId:eventId]; + // Add vertical whitespace in case of from a thread + additionalVerticalHeight+= [self fromThreadViewHeightForEventId:eventId]; // Add vertical whitespace in case of read receipts. additionalVerticalHeight+= [self readReceiptHeightForEventId:eventId]; @@ -593,6 +595,7 @@ - (CGFloat)computeAdditionalHeight height+= [self urlPreviewHeightForEventId:eventId]; height+= [self reactionHeightForEventId:eventId]; height+= [self threadSummaryViewHeightForEventId:eventId]; + height+= [self fromThreadViewHeightForEventId:eventId]; height+= [self readReceiptHeightForEventId:eventId]; } @@ -654,7 +657,35 @@ - (CGFloat)threadSummaryViewHeightForEventId:(NSString*)eventId // component is not a thread root return 0; } - return RoomBubbleCellLayout.threadSummaryViewTopMargin + [ThreadSummaryView contentViewHeightForThread:component.thread fitting:self.maxTextViewWidth]; + return RoomBubbleCellLayout.threadSummaryViewTopMargin + + [ThreadSummaryView contentViewHeightForThread:component.thread fitting:self.maxTextViewWidth]; +} + +- (CGFloat)fromThreadViewHeightForEventId:(NSString*)eventId +{ + if (!RiotSettings.shared.enableThreads) + { + // do not show from thread view if threads not enabled + return 0; + } + if (roomDataSource.threadId) + { + // do not show from thread view on threads + return 0; + } + NSInteger index = [self bubbleComponentIndexForEventId:eventId]; + if (index == NSNotFound) + { + return 0; + } + MXKRoomBubbleComponent *component = self.bubbleComponents[index]; + if (!component.event.isInThread) + { + // event is not in a thread + return 0; + } + return RoomBubbleCellLayout.fromThreadViewTopMargin + + [FromThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth]; } - (CGFloat)urlPreviewHeightForEventId:(NSString*)eventId diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index f35ac5c7f9..81d938e33e 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -91,11 +91,65 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N if ([cell isKindOfClass:MXKRoomBubbleTableViewCell.class]) { MXKRoomBubbleTableViewCell *bubbleCell = (MXKRoomBubbleTableViewCell*)cell; - + // Display date for each message [bubbleCell addDateLabel]; + + RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; + MXEvent *event = cellData.events.firstObject; + + if (event) + { + if (cellData.hasThreadRoot) + { + MXThread *thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + [bubbleCell.tmpSubviews addObject:threadSummaryView]; + + threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:threadSummaryView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor + constant:leftMargin], + [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]], + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + else if (event.isInThread) + { + FromThreadView *fromThreadView = [FromThreadView instantiate]; + [bubbleCell.tmpSubviews addObject:fromThreadView]; + + fromThreadView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:fromThreadView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor + constant:leftMargin], + [fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], + [fromThreadView.heightAnchor constraintEqualToConstant:[FromThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]], + [fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + } } - + return cell; } diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift index a860d942bc..2295f634b7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift @@ -50,4 +50,5 @@ final class RoomBubbleCellLayout: NSObject { // Threads static let threadSummaryViewTopMargin: CGFloat = 8.0 + static let fromThreadViewTopMargin: CGFloat = 8.0 } diff --git a/Riot/Modules/Room/Views/Threads/From/FromThreadView.swift b/Riot/Modules/Room/Views/Threads/From/FromThreadView.swift new file mode 100644 index 0000000000..992a8b2028 --- /dev/null +++ b/Riot/Modules/Room/Views/Threads/From/FromThreadView.swift @@ -0,0 +1,54 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import Reusable + +@objcMembers +class FromThreadView: UIView { + + private enum Constants { + static let viewHeight: CGFloat = 18 + } + + @IBOutlet private weak var iconView: UIImageView! + @IBOutlet private weak var titleLabel: UILabel! + + static func contentViewHeight(forEvent event: MXEvent, + fitting maxWidth: CGFloat) -> CGFloat { + return Constants.viewHeight + } + + static func instantiate() -> FromThreadView { + let view = FromThreadView.loadFromNib() + view.update(theme: ThemeService.shared().theme) + view.titleLabel.text = VectorL10n.messageFromAThread + return view + } + +} + +extension FromThreadView: NibLoadable {} + +extension FromThreadView: Themable { + + func update(theme: Theme) { + backgroundColor = .clear + iconView.tintColor = theme.colors.secondaryContent + titleLabel.textColor = theme.colors.secondaryContent + } + +} diff --git a/Riot/Modules/Room/Views/Threads/From/FromThreadView.xib b/Riot/Modules/Room/Views/Threads/From/FromThreadView.xib new file mode 100644 index 0000000000..8e8e9f8b24 --- /dev/null +++ b/Riot/Modules/Room/Views/Threads/From/FromThreadView.xib @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Room/Views/Threads/ThreadSummaryView.swift b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift similarity index 100% rename from Riot/Modules/Room/Views/Threads/ThreadSummaryView.swift rename to Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift diff --git a/Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.xib similarity index 100% rename from Riot/Modules/Room/Views/Threads/ThreadSummaryView.xib rename to Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.xib diff --git a/Riot/Modules/Room/Views/Threads/ThreadSummaryViewModel.swift b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryViewModel.swift similarity index 100% rename from Riot/Modules/Room/Views/Threads/ThreadSummaryViewModel.swift rename to Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryViewModel.swift From dcd78742bd0a4b2229c413b4492f2ffe86df7d21 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 16:20:12 +0300 Subject: [PATCH 26/33] Add background color management on text message highlights --- .../DataSources/HomeMessagesSearchDataSource.m | 5 ++++- .../Models/Room/MXKRoomBubbleCellData.h | 3 ++- .../Models/Room/MXKRoomBubbleCellData.m | 18 ++++++++++++++---- .../Models/Room/MXKRoomBubbleCellDataStoring.h | 8 ++++++-- .../Search/DataSources/RoomSearchDataSource.m | 5 ++++- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 6339a51b4a..fe69086ae5 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -66,7 +66,10 @@ - (void)convertHomeserverResultsIntoCells:(MXSearchRoomEventResults *)roomEventR if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.shared.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText + withBackgroundColor:[UIColor clearColor] + foregroundColor:ThemeService.shared.theme.tintColor + andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.h index e63d2f5864..cd76e39f85 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.h @@ -50,7 +50,8 @@ The optional text pattern to be highlighted in the body of the message. */ NSString *highlightedPattern; - UIColor *highlightedPatternColor; + UIColor *highlightedPatternForegroundColor; + UIColor *highlightedPatternBackgroundColor; UIFont *highlightedPatternFont; } diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index b435b2f9df..0fe6bf0e0d 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -351,10 +351,14 @@ - (NSAttributedString*)attributedTextMessageWithHighlightedEvent:(NSString*)even return customAttributedTextMsg; } -- (void)highlightPatternInTextMessage:(NSString*)pattern withForegroundColor:(UIColor*)patternColor andFont:(UIFont*)patternFont +- (void)highlightPatternInTextMessage:(NSString*)pattern + withBackgroundColor:(UIColor *)backgroundColor + foregroundColor:(UIColor*)foregroundColor + andFont:(UIFont*)patternFont { highlightedPattern = pattern; - highlightedPatternColor = patternColor; + highlightedPatternBackgroundColor = backgroundColor; + highlightedPatternForegroundColor = foregroundColor; highlightedPatternFont = patternFont; // Indicate that the text message layout should be recomputed. @@ -889,10 +893,16 @@ - (void)highlightPattern while (range.location != NSNotFound) { - if (highlightedPatternColor) + if (highlightedPatternBackgroundColor) + { + // Update background color + [customAttributedTextMsg addAttribute:NSBackgroundColorAttributeName value:highlightedPatternBackgroundColor range:range]; + } + + if (highlightedPatternForegroundColor) { // Update text color - [customAttributedTextMsg addAttribute:NSForegroundColorAttributeName value:highlightedPatternColor range:range]; + [customAttributedTextMsg addAttribute:NSForegroundColorAttributeName value:highlightedPatternForegroundColor range:range]; } if (highlightedPatternFont) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h index 06b1584c42..53b96037cd 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h @@ -269,10 +269,14 @@ Update the event because its sent state changed or it is has been redacted. Highlight all the occurrences of a pattern in the resulting message body 'attributedTextMessage'. @param pattern the text pattern to highlight. - @param patternColor optional text color (the pattern text color is unchanged if nil). + @param backgroundColor optional text background color (the patterns background color is unchanged if nil) + @param foregroundColor optional text color (the pattern text color is unchanged if nil). @param patternFont optional text font (the pattern font is unchanged if nil). */ -- (void)highlightPatternInTextMessage:(NSString*)pattern withForegroundColor:(UIColor*)patternColor andFont:(UIFont*)patternFont; +- (void)highlightPatternInTextMessage:(NSString*)pattern + withBackgroundColor:(UIColor *)backgroundColor + foregroundColor:(UIColor*)foregroundColor + andFont:(UIFont*)patternFont; /** Refresh the sender flair information diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 81d938e33e..58e80961e9 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -69,7 +69,10 @@ - (void)convertHomeserverResultsIntoCells:(MXSearchRoomEventResults *)roomEventR if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.shared.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText + withBackgroundColor:[UIColor clearColor] + foregroundColor:ThemeService.shared.theme.tintColor + andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; From 240bf6af950c1e3facc441543dffe01e7908b319 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 16:32:23 +0300 Subject: [PATCH 27/33] Disable sending polls in threads --- Riot/Modules/Room/RoomDisplayConfiguration.swift | 12 +++++++++--- Riot/Modules/Room/RoomViewController.m | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/RoomDisplayConfiguration.swift b/Riot/Modules/Room/RoomDisplayConfiguration.swift index 2c3ab1ab8c..1a5ec34812 100644 --- a/Riot/Modules/Room/RoomDisplayConfiguration.swift +++ b/Riot/Modules/Room/RoomDisplayConfiguration.swift @@ -24,21 +24,27 @@ class RoomDisplayConfiguration: NSObject { let integrationsEnabled: Bool let jitsiWidgetRemoverEnabled: Bool + + let sendingPollsEnabled: Bool init(callsEnabled: Bool, integrationsEnabled: Bool, - jitsiWidgetRemoverEnabled: Bool) { + jitsiWidgetRemoverEnabled: Bool, + sendingPollsEnabled: Bool) { self.callsEnabled = callsEnabled self.integrationsEnabled = integrationsEnabled self.jitsiWidgetRemoverEnabled = jitsiWidgetRemoverEnabled + self.sendingPollsEnabled = sendingPollsEnabled super.init() } static let `default`: RoomDisplayConfiguration = RoomDisplayConfiguration(callsEnabled: true, integrationsEnabled: true, - jitsiWidgetRemoverEnabled: true) + jitsiWidgetRemoverEnabled: true, + sendingPollsEnabled: true) static let forThreads: RoomDisplayConfiguration = RoomDisplayConfiguration(callsEnabled: false, integrationsEnabled: false, - jitsiWidgetRemoverEnabled: false) + jitsiWidgetRemoverEnabled: false, + sendingPollsEnabled: false) } diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 3426c1e0bf..5f3611e776 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -2093,7 +2093,7 @@ - (void)setupActions { [self roomInputToolbarViewDidTapFileUpload]; }]]; } - if (RiotSettings.shared.roomScreenAllowPollsAction) + if (RiotSettings.shared.roomScreenAllowPollsAction && self.displayConfiguration.sendingPollsEnabled) { [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_poll"] andAction:^{ MXStrongifyAndReturnIfNil(self); From 0a85d1b6b4a667eaa7fafd5816b794fe805a703a Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 18 Jan 2022 23:41:36 +0300 Subject: [PATCH 28/33] Fix cell layout when thread root is a poll --- .../Room/CellData/RoomBubbleCellData.m | 6 ++ .../Modules/Room/DataSources/RoomDataSource.m | 72 +++++++++++-------- .../BaseBubbleCell/BaseBubbleCell.swift | 14 ++++ .../BubbleCellContentView.swift | 34 +++++++++ .../BaseBubbleCell/BubbleCellContentView.xib | 5 ++ .../BubbleCellThreadSummaryDisplayable.swift | 23 ++++++ .../Encryption/RoomBubbleCellLayout.swift | 1 + .../BubbleCells/Poll/PollBubbleCell.swift | 2 + .../SizableCell/SizableBubbleCell.swift | 7 ++ .../Threads/Summary/ThreadSummaryView.swift | 5 +- 10 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 55c2212401..5001ecb933 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -297,6 +297,12 @@ - (BOOL)hasThreadRoot // do not consider this cell data if threads not enabled in the timeline return NO; } + + if (roomDataSource.threadId) + { + // do not consider this cell data if in a thread view + return NO; + } return super.hasThreadRoot; } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 322c00541a..f27a0d51ea 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -516,45 +516,55 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N { threadSummaryView = [[ThreadSummaryView alloc] initWithThread:component.thread]; threadSummaryView.delegate = self; - + [temporaryViews addObject:threadSummaryView]; [bubbleCell.tmpSubviews addObject:threadSummaryView]; - + threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; - [bubbleCell.contentView addSubview:threadSummaryView]; - - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; - if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge) - { - leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin; - } - - // The top constraint may need to include the URL preview view or reactions view - NSLayoutConstraint *topConstraint; - if (reactionsView) - { - topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor - constant:RoomBubbleCellLayout.threadSummaryViewTopMargin]; - } - else if (urlPreviewView) + + if ([[bubbleCell class] conformsToProtocol:@protocol(BubbleCellThreadSummaryDisplayable)]) { - topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor - constant:RoomBubbleCellLayout.threadSummaryViewTopMargin]; + id threadSummaryDisplayable = (id)bubbleCell; + + [threadSummaryDisplayable addThreadSummaryView:threadSummaryView]; } else { - topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin]; + [bubbleCell.contentView addSubview:threadSummaryView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + if (roomBubbleCellData.containsBubbleComponentWithEncryptionBadge) + { + leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin; + } + + // The top constraint may need to include the URL preview view or reactions view + NSLayoutConstraint *topConstraint; + if (reactionsView) + { + topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor + constant:RoomBubbleCellLayout.threadSummaryViewTopMargin]; + } + else if (urlPreviewView) + { + topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:urlPreviewView.bottomAnchor + constant:RoomBubbleCellLayout.threadSummaryViewTopMargin]; + } + else + { + topConstraint = [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin]; + } + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor + constant:leftMargin], + topConstraint, + [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:component.thread fitting:cellData.maxTextViewWidth]], + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; } - - // Set constraints for the summary view - [NSLayoutConstraint activateConstraints: @[ - [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor - constant:leftMargin], - topConstraint, - [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:component.thread fitting:cellData.maxTextViewWidth]], - [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] - ]]; } MXKReceiptSendersContainer* avatarsContainer; diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift index 6c0db22801..02a92cb87b 100644 --- a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift @@ -168,6 +168,10 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { if let bubbleCellReactionsDisplayable = self as? BubbleCellReactionsDisplayable { bubbleCellReactionsDisplayable.removeReactionsView() } + + if let bubbleCellThreadSummaryDisplayable = self as? BubbleCellThreadSummaryDisplayable { + bubbleCellThreadSummaryDisplayable.removeThreadSummaryView() + } } override func render(_ cellData: MXKCellData!) { @@ -244,6 +248,16 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { func removeReactionsView() { self.bubbleCellContentView?.removeReactionsView() } + + // MARK: - BubbleCellThreadSummaryDisplayable + + func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { + self.bubbleCellContentView?.addThreadSummaryView(threadSummaryView) + } + + func removeThreadSummaryView() { + self.bubbleCellContentView?.removeThreadSummaryView() + } // Encryption status diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift index 22597a4f20..5a15f64d58 100644 --- a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift +++ b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift @@ -47,6 +47,8 @@ final class BubbleCellContentView: UIView, NibLoadable { @IBOutlet weak var reactionsContainerView: UIView! @IBOutlet weak var reactionsContentView: UIView! + + @IBOutlet weak var threadSummaryContainerView: UIView! @IBOutlet weak var bubbleOverlayContainer: UIView! @@ -69,6 +71,14 @@ final class BubbleCellContentView: UIView, NibLoadable { self.reactionsContainerView.isHidden = !newValue } } + + private var showThreadSummary: Bool { + get { + return !self.threadSummaryContainerView.isHidden + } set { + self.threadSummaryContainerView.isHidden = !newValue + } + } // MARK: Public @@ -143,3 +153,27 @@ extension BubbleCellContentView: BubbleCellReactionsDisplayable { self.reactionsContentView.vc_removeAllSubviews() } } + +// MARK: - BubbleCellThreadSummaryDisplayable +extension BubbleCellContentView: BubbleCellThreadSummaryDisplayable { + + func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { + self.threadSummaryContainerView.vc_removeAllSubviews() + self.threadSummaryContainerView.addSubview(threadSummaryView) + NSLayoutConstraint.activate([ + threadSummaryView.leadingAnchor.constraint(equalTo: innerContentView.leadingAnchor), + threadSummaryView.topAnchor.constraint(equalTo: threadSummaryContainerView.topAnchor), + threadSummaryView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.threadSummaryViewHeight), + threadSummaryView.bottomAnchor.constraint(equalTo: threadSummaryContainerView.bottomAnchor), + threadSummaryView.trailingAnchor.constraint(lessThanOrEqualTo: threadSummaryContainerView.trailingAnchor, + constant: -RoomBubbleCellLayout.reactionsViewRightMargin) + ]) + self.showThreadSummary = true + } + + func removeThreadSummaryView() { + self.showThreadSummary = false + self.threadSummaryContainerView.vc_removeAllSubviews() + } + +} diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib index adbd1b79a9..1a5a30708e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib +++ b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib @@ -195,6 +195,10 @@ + @@ -238,6 +242,7 @@ + diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift new file mode 100644 index 0000000000..6c2848e279 --- /dev/null +++ b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift @@ -0,0 +1,23 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// `BubbleCellThreadSummaryDisplayable` is a protocol indicating that a cell support displaying a thread summary. +@objc protocol BubbleCellThreadSummaryDisplayable { + func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) + func removeThreadSummaryView() +} diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift index 2295f634b7..461da960b2 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomBubbleCellLayout.swift @@ -50,5 +50,6 @@ final class RoomBubbleCellLayout: NSObject { // Threads static let threadSummaryViewTopMargin: CGFloat = 8.0 + static let threadSummaryViewHeight: CGFloat = 40.0 static let fromThreadViewTopMargin: CGFloat = 8.0 } diff --git a/Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift index 4d3d42e288..6b7efebc4d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift @@ -57,3 +57,5 @@ class PollBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { delegate.cell(self, didRecognizeAction: kMXKRoomBubbleCellTapOnContentView, userInfo: [kMXKRoomBubbleCellEventKey: event]) } } + +extension PollBubbleCell: BubbleCellThreadSummaryDisplayable {} diff --git a/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift index d7f00f0d7f..9c802f469b 100644 --- a/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift @@ -130,6 +130,13 @@ class SizableBaseBubbleCell: BaseBubbleCell, SizableBaseBubbleCellType { let reactionsHeight = self.reactionsViewSizer.height(for: bubbleReactionsViewModel, fittingWidth: reactionWidth) height+=reactionsHeight } + + // Add thread summary view height if needed + if sizingView is BubbleCellThreadSummaryDisplayable, + let roomBubbleCellData = cellData as? RoomBubbleCellData, + roomBubbleCellData.hasThreadRoot { + height += RoomBubbleCellLayout.threadSummaryViewHeight + } return height } diff --git a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift index 362a6716b4..61917e30e6 100644 --- a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift +++ b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift @@ -27,7 +27,6 @@ protocol ThreadSummaryViewDelegate: AnyObject { class ThreadSummaryView: UIView { private enum Constants { - static let viewHeight: CGFloat = 40 static let viewDefaultWidth: CGFloat = 320 static let cornerRadius: CGFloat = 8 static let lastMessageFont: UIFont = .systemFont(ofSize: 13) @@ -53,14 +52,14 @@ class ThreadSummaryView: UIView { self.thread = thread super.init(frame: CGRect(origin: .zero, size: CGSize(width: Constants.viewDefaultWidth, - height: Constants.viewHeight))) + height: RoomBubbleCellLayout.threadSummaryViewHeight))) loadNibContent() update(theme: ThemeService.shared().theme) configure() } static func contentViewHeight(forThread thread: MXThread, fitting maxWidth: CGFloat) -> CGFloat { - return Constants.viewHeight + return RoomBubbleCellLayout.threadSummaryViewHeight } required init?(coder: NSCoder) { From 677eb52891285e91cb4f7e6270eadde43594f63e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 20 Jan 2022 12:46:13 +0300 Subject: [PATCH 29/33] Update thread list filter applied icon --- .../Contents.json | 15 ++------------- .../Right controls.png | Bin 435 -> 0 bytes .../Right controls@2x.png | Bin 792 -> 0 bytes .../Right controls@3x.png | Bin 1114 -> 0 bytes .../filter-on.svg | 6 ++++++ 5 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls.png delete mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@2x.png delete mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/filter-on.svg diff --git a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Contents.json index 65fc07b238..5d848cb50a 100644 --- a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Contents.json @@ -1,19 +1,8 @@ { "images" : [ { - "filename" : "Right controls.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Right controls@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Right controls@3x.png", - "idiom" : "universal", - "scale" : "3x" + "filename" : "filter-on.svg", + "idiom" : "universal" } ], "info" : { diff --git a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls.png b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls.png deleted file mode 100644 index b517cdfb138f2124172121804007c4ae0b3f9dea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 435 zcmV;k0ZjghP)j|-_0_^{xbtG0gl6#TV7Cd+nowOtbc6R>+Xp=2%0#KM^c$Y zg{L4RuF$~$%4rvH+x}}ra#>^!G-$Zq{@>)6Z;xh zls{}43-wYm4Tbe=?=I+oUBJ- zH#eo$nxbaQKSjin_%6~ax9X)=aMgmsT6VGm;ew?y9b08gwVG@gSP$?!$1SB%$peg7 zG}VTObAP~X*+ dbWF^w`2j~8b13@Ws@wno002ovPDHLkV1o7Qw$}gv diff --git a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@2x.png b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@2x.png deleted file mode 100644 index a9a275aef9d0084564444d89774f7892665b3ad2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792 zcmV+z1LypSP)S=6QWZQ17ZTH5-Tv!wN$EDo6Im|rbxiZPznA3R9MQG z43rg1DeX|CxM^{kFCTY-D3N1ZPII|*xSwP>e(gKmW54%)gy0NNF4JUWqPapTT?A+b zAQ^6_6eb}kQs85=*7}r6#SG_If-zDqS2KDv^p^cx3^ah^U8CO0^$O82CM>JI5{`rl z2)cLBxl0y9KnTfB#`K(Y0sPI|KpsM{SEUNzKF{5TZOkOZ zV1^-)kgjFD7GG)Bu(4mnc4fDHaBjw@@oZ)ek1pQunldTv3;d5bKi%$?Y85Q)Y_`vC zT!|*IIlI(8JCPQJbe%l(y63lePDddBN>1d3QB8Z`X8v&S!*}r=_%pBf3;okV78G-C z<~Msq1m#=hSD#Iu0FTZ4-8w)}I-9!}&nR?$>(yh}JYG{#A#Wsje*v3kN^y%Xow)n? zLL!Zz%uY`C+5B8c=$kLq-38oETt-lqFZFLD9|3fg9R>ukeYoptU!IwFjqgtQGj0h@ zVj`nSJ=!R{-5Vy6Nv(yBt@;*x%4ePvHuehGv3|F&xqB^4rJ3u@BN2|ej*(l;RarS< zvmQWDF~>VLsSQmk7BgDJ&Os1_%_Y4fn~G25Su-=V2tLO-HrLpC;zQOJhN!kas5|{@ z^zHWI`Srj8L}q9nRo2qC{OWxtUmB$Kl)GZbFt~uvFL_O$fk3#B`>AWVci}pVJZZDr z^zb}H4CXFhoAF3KMTqGfdl~^emXD}DqQ=qP7gq-vaf(eWHbeJdq6J|QN}*6F0S;1 diff --git a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@3x.png b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/Right controls@3x.png deleted file mode 100644 index 190f810eb1417ef0a5399c0674dc558c1e5af1cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1114 zcmV-g1f~0lP)i4l?pJpnOrGI|k$BzRK8fy9fLco$=cN8lNfI&T z#MQ<~xTtI*Co#6PrA^s($9Y>y(9oS(y6x^Z^CeB2?y$69-@KjoW(hPA`8BKsOqs11#YnmtRDF9ju&v^^Lq&ajCy1y;%5s#r15=8}i6q|$Do?AU&kc}MA;G5Gux|uqbNWIZ zat@D}F9aQ5#uvc_d?6^CE9}~tT3ZKuu(H1cTj@RcSxB4j^x`a!Yv_K?Hz}H z7FAYwTF~*DXO}k)Bj?_icfxWiprnnPk1Zof0S^-ll7}MW>_pCK@NaNRTH$FyR0-VW zjamQm{Ui~e2h3MiIm^?62&GZp7!*`1E5CNC9`m#yMwB;T`|vl^ifE ztfpuS2ojFJo}q@qmimVz2nxsN7pOsI8!boV$|SPbguBegdBG_<)=|B96%v#k zot|Y|C@3if4P-s}Lug#=#;92~*u|{JSkY>Q_lwos5o@vXw{y-_tTH)P`3Ld(LJx`p*AL_%S`Haa+WUyWiolTK^TaG z3wVBtA#H8yrW;pM{Ga~X_PL4a?@5|Z+b zAS9xy?1LM_b(WMc<*4PYXI}|IOi6_cgZ0QscuqF0PUIkt=AcHmL?$|W;br$NCn|c4 zmP$|YV(|X~#{`vIBGBlqVG|Vf?CJn_3+D_rfhbE2xq+(f(|nRWx!O#_NV?Bz=LJEhNM%N*Bj5mzC26->B4oTP3yDM`kw_#Gi9{li gNF)-8MB*d<0?L<*Ng(eWm;e9(07*qoM6N<$f)$PKw*UYD diff --git a/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/filter-on.svg b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/filter-on.svg new file mode 100644 index 0000000000..26b34d0e2b --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Threads/threads_filter_applied.imageset/filter-on.svg @@ -0,0 +1,6 @@ + + + + + + From 5f9b9fc175f8ca2445158b8779ea98a1ecd3ec70 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 26 Jan 2022 14:28:24 +0300 Subject: [PATCH 30/33] Implement thread summary displayable on cell decorator --- .../PlainRoomTimelineCellDecorator.swift | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index 20b18a6a69..749ccece50 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -150,41 +150,45 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cell.addTemporarySubview(threadSummaryView) - threadSummaryView.translatesAutoresizingMaskIntoConstraints = false + if let threadSummaryDisplayable = cell as? BubbleCellThreadSummaryDisplayable { + threadSummaryDisplayable.addThreadSummaryView(threadSummaryView) + } else { + threadSummaryView.translatesAutoresizingMaskIntoConstraints = false - let cellContentView = cell.contentView + let cellContentView = cell.contentView - cellContentView.addSubview(threadSummaryView) + cellContentView.addSubview(threadSummaryView) - var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin - if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin - } + if cellData.containsBubbleComponentWithEncryptionBadge { + leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + } - let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin - let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin - let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread, - fitting: cellData.maxTextViewWidth) + let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin + let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin + let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread, + fitting: cellData.maxTextViewWidth) - // The top constraint may need to include the URL preview view - let topConstraint: NSLayoutConstraint - if let upperDecorationView = upperDecorationView { - topConstraint = threadSummaryView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, - constant: topMargin) - } else { - topConstraint = threadSummaryView.topAnchor.constraint(equalTo: cellContentView.topAnchor, - constant: contentViewPositionY + topMargin) - } + // The top constraint may need to include the URL preview view + let topConstraint: NSLayoutConstraint + if let upperDecorationView = upperDecorationView { + topConstraint = threadSummaryView.topAnchor.constraint(equalTo: upperDecorationView.bottomAnchor, + constant: topMargin) + } else { + topConstraint = threadSummaryView.topAnchor.constraint(equalTo: cellContentView.topAnchor, + constant: contentViewPositionY + topMargin) + } - NSLayoutConstraint.activate([ - threadSummaryView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, - constant: leftMargin), - threadSummaryView.trailingAnchor.constraint(lessThanOrEqualTo: cellContentView.trailingAnchor, - constant: -rightMargin), - threadSummaryView.heightAnchor.constraint(equalToConstant: height), - topConstraint - ]) + NSLayoutConstraint.activate([ + threadSummaryView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, + constant: leftMargin), + threadSummaryView.trailingAnchor.constraint(lessThanOrEqualTo: cellContentView.trailingAnchor, + constant: -rightMargin), + threadSummaryView.heightAnchor.constraint(equalToConstant: height), + topConstraint + ]) + } } func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell, withFailedEventIds failedEventIds: Set) { From 9327626021a8b81749cb4852f413034d7dead817 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 26 Jan 2022 15:58:37 +0300 Subject: [PATCH 31/33] Fix Doug's remarks --- .../Contents.json | 3 --- Riot/Categories/UIView+Toast.swift | 3 ++- .../HomeMessagesSearchDataSource.m | 16 ++++++----- .../Room/CellData/RoomBubbleCellData.m | 2 +- Riot/Modules/Room/RoomViewController.m | 14 ++++++++-- .../Search/DataSources/RoomSearchDataSource.m | 16 ++++++----- .../Settings/RoomSettingsViewController.m | 7 ++--- ...ThreadView.swift => FromAThreadView.swift} | 10 +++---- ...FromThreadView.xib => FromAThreadView.xib} | 16 +++++------ .../Threads/Thread/ThreadViewController.swift | 4 +-- .../ThreadList/ThreadListViewController.swift | 27 +++++++++++++------ .../ThreadList/ThreadListViewModel.swift | 15 ++++++----- .../ThreadList/ThreadListViewState.swift | 4 +-- .../Views/Cell/ThreadTableViewCell.swift | 5 +--- 14 files changed, 83 insertions(+), 59 deletions(-) rename Riot/Modules/Room/Views/Threads/From/{FromThreadView.swift => FromAThreadView.swift} (86%) rename Riot/Modules/Room/Views/Threads/From/{FromThreadView.xib => FromAThreadView.xib} (91%) diff --git a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json index 793a299c46..d2c033d2dd 100644 --- a/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/ContextMenu/room_context_menu_thread.imageset/Contents.json @@ -19,8 +19,5 @@ "info" : { "author" : "xcode", "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "original" } } diff --git a/Riot/Categories/UIView+Toast.swift b/Riot/Categories/UIView+Toast.swift index b8d2db9aa8..e395578e3c 100644 --- a/Riot/Categories/UIView+Toast.swift +++ b/Riot/Categories/UIView+Toast.swift @@ -232,7 +232,7 @@ private class ToastView: UIView, Themable { private lazy var messageLabel: UILabel = { let label = UILabel() - label.font = .systemFont(ofSize: 15) + label.font = ThemeService.shared().theme.fonts.body label.backgroundColor = .clear label.numberOfLines = 0 label.textAlignment = .left @@ -305,6 +305,7 @@ private class ToastView: UIView, Themable { backgroundColor = theme.colors.quinaryContent imageView.tintColor = theme.colors.tertiaryContent messageLabel.textColor = theme.colors.primaryContent + messageLabel.font = theme.fonts.body } } diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index fe69086ae5..f964b5b8d0 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -134,6 +134,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N [bubbleCell.contentView addSubview:threadSummaryView]; CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; @@ -141,22 +142,23 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Set constraints for the summary view [NSLayoutConstraint activateConstraints: @[ [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor - constant:leftMargin], + constant:leftMargin], [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], - [threadSummaryView.heightAnchor constraintEqualToConstant:[ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]], + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + [threadSummaryView.heightAnchor constraintEqualToConstant:height], [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] ]]; } else if (event.isInThread) { - FromThreadView *fromThreadView = [FromThreadView instantiate]; + FromAThreadView *fromThreadView = [FromAThreadView instantiate]; [bubbleCell.tmpSubviews addObject:fromThreadView]; fromThreadView.translatesAutoresizingMaskIntoConstraints = NO; [bubbleCell.contentView addSubview:fromThreadView]; CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; @@ -164,10 +166,10 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Set constraints for the summary view [NSLayoutConstraint activateConstraints: @[ [fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor - constant:leftMargin], + constant:leftMargin], [fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], - [fromThreadView.heightAnchor constraintEqualToConstant:[FromThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]], + constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], + [fromThreadView.heightAnchor constraintEqualToConstant:height], [fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] ]]; } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 69bd16f0f5..c0cfaf6cc8 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -695,7 +695,7 @@ - (CGFloat)fromThreadViewHeightForEventId:(NSString*)eventId return 0; } return RoomBubbleCellLayout.fromThreadViewTopMargin + - [FromThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth]; + [FromAThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth]; } - (CGFloat)urlPreviewHeightForEventId:(NSString*)eventId diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index e240116147..49b1269098 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -3282,6 +3282,9 @@ - (void)showAdditionalActionsMenuForEvent:(MXEvent*)selectedEvent inCell:(id FromThreadView { - let view = FromThreadView.loadFromNib() + static func instantiate() -> FromAThreadView { + let view = FromAThreadView.loadFromNib() view.update(theme: ThemeService.shared().theme) view.titleLabel.text = VectorL10n.messageFromAThread return view @@ -41,9 +41,9 @@ class FromThreadView: UIView { } -extension FromThreadView: NibLoadable {} +extension FromAThreadView: NibLoadable {} -extension FromThreadView: Themable { +extension FromAThreadView: Themable { func update(theme: Theme) { backgroundColor = .clear diff --git a/Riot/Modules/Room/Views/Threads/From/FromThreadView.xib b/Riot/Modules/Room/Views/Threads/From/FromAThreadView.xib similarity index 91% rename from Riot/Modules/Room/Views/Threads/From/FromThreadView.xib rename to Riot/Modules/Room/Views/Threads/From/FromAThreadView.xib index 8e8e9f8b24..d1f3061297 100644 --- a/Riot/Modules/Room/Views/Threads/From/FromThreadView.xib +++ b/Riot/Modules/Room/Views/Threads/From/FromAThreadView.xib @@ -11,22 +11,22 @@ - - + + - + - + diff --git a/Riot/Modules/Threads/Thread/ThreadViewController.swift b/Riot/Modules/Threads/Thread/ThreadViewController.swift index 01763d8df7..3609c8bc7c 100644 --- a/Riot/Modules/Threads/Thread/ThreadViewController.swift +++ b/Riot/Modules/Threads/Thread/ThreadViewController.swift @@ -96,11 +96,11 @@ class ThreadViewController: RoomViewController { } private func copyPermalink() { - guard let permalink = permalink else { + guard let permalink = permalink, let url = URL(string: permalink) else { return } - MXKPasteboardManager.shared.pasteboard.string = permalink + MXKPasteboardManager.shared.pasteboard.url = url view.vc_toast(message: VectorL10n.roomEventCopyLinkInfo, image: Asset.Images.linkIcon.image) } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift index 0c1e5098d9..5f23f8c45c 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift @@ -148,10 +148,10 @@ final class ThreadListViewController: UIViewController { renderEmptyView(withViewModel: viewModel) case .showingFilterTypes: renderShowingFilterTypes() - case .showingLongPressActions: - renderShowingLongPressActions() - case .share(let string): - renderShare(string) + case .showingLongPressActions(let index): + renderShowingLongPressActions(index) + case .share(let url, let index): + renderShare(url, index: index) case .toastForCopyLink: toastForCopyLink() case .error(let error): @@ -226,7 +226,7 @@ final class ThreadListViewController: UIViewController { self.present(alertController, animated: true, completion: nil) } - private func renderShowingLongPressActions() { + private func renderShowingLongPressActions(_ index: Int) { let controller = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) controller.addAction(UIAlertAction(title: VectorL10n.roomEventActionViewInRoom, @@ -253,14 +253,25 @@ final class ThreadListViewController: UIViewController { controller.addAction(UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil)) - + + if let cell = threadsTableView.cellForRow(at: IndexPath(row: index, section: 0)) { + controller.popoverPresentationController?.sourceView = cell + } else { + controller.popoverPresentationController?.sourceView = view + } + self.present(controller, animated: true, completion: nil) } - private func renderShare(_ string: String) { - let activityVC = UIActivityViewController(activityItems: [string], + private func renderShare(_ url: URL, index: Int) { + let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil) activityVC.modalTransitionStyle = .coverVertical + if let cell = threadsTableView.cellForRow(at: IndexPath(row: index, section: 0)) { + activityVC.popoverPresentationController?.sourceView = cell + } else { + activityVC.popoverPresentationController?.sourceView = view + } present(activityVC, animated: true, completion: nil) } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 1004ba35ec..e16d060cb2 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -296,7 +296,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { return } longPressedThread = threads[index] - viewState = .showingLongPressActions + viewState = .showingLongPressActions(index) } private func actionViewInRoom() { @@ -311,19 +311,22 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { guard let thread = longPressedThread else { return } - if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId) { - MXKPasteboardManager.shared.pasteboard.string = permalink + if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId), + let url = URL(string: permalink) { + MXKPasteboardManager.shared.pasteboard.url = url viewState = .toastForCopyLink } longPressedThread = nil } private func actionShare() { - guard let thread = longPressedThread else { + guard let thread = longPressedThread, + let index = threads.firstIndex(of: thread) else { return } - if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId) { - viewState = .share(permalink) + if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId), + let url = URL(string: permalink) { + viewState = .share(url, index) } longPressedThread = nil } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift index 5eca64c8dc..6140ef41f3 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift @@ -25,8 +25,8 @@ enum ThreadListViewState { case loaded case empty(_ viewModel: ThreadListEmptyModel) case showingFilterTypes - case showingLongPressActions - case share(_ string: String) + case showingLongPressActions(_ index: Int) + case share(_ url: URL, _ index: Int) case toastForCopyLink case error(Error) } diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift index 43f85d2639..db39511fdf 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadTableViewCell.swift @@ -39,10 +39,7 @@ class ThreadTableViewCell: UITableViewCell { @IBOutlet private weak var lastMessageTimeLabel: UILabel! @IBOutlet private weak var summaryView: ThreadSummaryView! - private static var usernameColorGenerator: UserNameColorGenerator = { - let generator = UserNameColorGenerator() - return generator - }() + private static var usernameColorGenerator = UserNameColorGenerator() override func awakeFromNib() { super.awakeFromNib() From 583fe39d10f5091cf9b41c850574c5b4e169e12f Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 26 Jan 2022 16:03:17 +0300 Subject: [PATCH 32/33] Make remove poll action destructive as well --- Riot/Modules/Room/RoomViewController.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 49b1269098..ae4cc091ce 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -3577,24 +3577,21 @@ - (void)showAdditionalActionsMenuForEvent:(MXEvent*)selectedEvent inCell:(id Date: Thu, 27 Jan 2022 02:16:30 +0300 Subject: [PATCH 33/33] Fix further review remarks --- .../HomeMessagesSearchDataSource.m | 105 +++++++++--------- .../Room/CellData/RoomBubbleCellData.m | 12 +- .../Search/DataSources/RoomSearchDataSource.m | 105 +++++++++--------- .../BubbleCells/RoomBubbleCellLayout.swift | 2 +- 4 files changed, 115 insertions(+), 109 deletions(-) diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index f964b5b8d0..1186e08f40 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -119,59 +119,62 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Display date for each message [bubbleCell addDateLabel]; - RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; - MXEvent *event = cellData.events.firstObject; - - if (event) + if (RiotSettings.shared.enableThreads) { - if (cellData.hasThreadRoot) - { - MXThread *thread = cellData.bubbleComponents.firstObject.thread; - ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; - [bubbleCell.tmpSubviews addObject:threadSummaryView]; - - threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; - [bubbleCell.contentView addSubview:threadSummaryView]; - - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; - CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; - - CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; - CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; - - // Set constraints for the summary view - [NSLayoutConstraint activateConstraints: @[ - [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor - constant:leftMargin], - [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], - [threadSummaryView.heightAnchor constraintEqualToConstant:height], - [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] - ]]; - } - else if (event.isInThread) + RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; + MXEvent *event = cellData.events.firstObject; + + if (event) { - FromAThreadView *fromThreadView = [FromAThreadView instantiate]; - [bubbleCell.tmpSubviews addObject:fromThreadView]; - - fromThreadView.translatesAutoresizingMaskIntoConstraints = NO; - [bubbleCell.contentView addSubview:fromThreadView]; - - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; - CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; - - CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; - CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; - - // Set constraints for the summary view - [NSLayoutConstraint activateConstraints: @[ - [fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor - constant:leftMargin], - [fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], - [fromThreadView.heightAnchor constraintEqualToConstant:height], - [fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] - ]]; + if (cellData.hasThreadRoot) + { + MXThread *thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + [bubbleCell.tmpSubviews addObject:threadSummaryView]; + + threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:threadSummaryView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor + constant:leftMargin], + [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + [threadSummaryView.heightAnchor constraintEqualToConstant:height], + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + else if (event.isInThread) + { + FromAThreadView *fromAThreadView = [FromAThreadView instantiate]; + [bubbleCell.tmpSubviews addObject:fromAThreadView]; + + fromAThreadView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:fromAThreadView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [fromAThreadView.leadingAnchor constraintEqualToAnchor:fromAThreadView.superview.leadingAnchor + constant:leftMargin], + [fromAThreadView.topAnchor constraintEqualToAnchor:fromAThreadView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.fromAThreadViewTopMargin], + [fromAThreadView.heightAnchor constraintEqualToConstant:height], + [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } } } } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index c0cfaf6cc8..c58e145549 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -584,7 +584,7 @@ - (void)addVerticalWhitespaceToString:(NSMutableAttributedString *)attributedStr // Add vertical whitespace in case of a thread root additionalVerticalHeight+= [self threadSummaryViewHeightForEventId:eventId]; // Add vertical whitespace in case of from a thread - additionalVerticalHeight+= [self fromThreadViewHeightForEventId:eventId]; + additionalVerticalHeight+= [self fromAThreadViewHeightForEventId:eventId]; // Add vertical whitespace in case of read receipts. additionalVerticalHeight+= [self readReceiptHeightForEventId:eventId]; @@ -605,7 +605,7 @@ - (CGFloat)computeAdditionalHeight height+= [self urlPreviewHeightForEventId:eventId]; height+= [self reactionHeightForEventId:eventId]; height+= [self threadSummaryViewHeightForEventId:eventId]; - height+= [self fromThreadViewHeightForEventId:eventId]; + height+= [self fromAThreadViewHeightForEventId:eventId]; height+= [self readReceiptHeightForEventId:eventId]; } @@ -671,16 +671,16 @@ - (CGFloat)threadSummaryViewHeightForEventId:(NSString*)eventId [ThreadSummaryView contentViewHeightForThread:component.thread fitting:self.maxTextViewWidth]; } -- (CGFloat)fromThreadViewHeightForEventId:(NSString*)eventId +- (CGFloat)fromAThreadViewHeightForEventId:(NSString*)eventId { if (!RiotSettings.shared.enableThreads) { - // do not show from thread view if threads not enabled + // do not show from a thread view if threads not enabled return 0; } if (roomDataSource.threadId) { - // do not show from thread view on threads + // do not show from a thread view on threads return 0; } NSInteger index = [self bubbleComponentIndexForEventId:eventId]; @@ -694,7 +694,7 @@ - (CGFloat)fromThreadViewHeightForEventId:(NSString*)eventId // event is not in a thread return 0; } - return RoomBubbleCellLayout.fromThreadViewTopMargin + + return RoomBubbleCellLayout.fromAThreadViewTopMargin + [FromAThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth]; } diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 918ef7cc99..f4a1f43a3f 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -98,59 +98,62 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Display date for each message [bubbleCell addDateLabel]; - RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; - MXEvent *event = cellData.events.firstObject; - - if (event) + if (RiotSettings.shared.enableThreads) { - if (cellData.hasThreadRoot) - { - MXThread *thread = cellData.bubbleComponents.firstObject.thread; - ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; - [bubbleCell.tmpSubviews addObject:threadSummaryView]; - - threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; - [bubbleCell.contentView addSubview:threadSummaryView]; - - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; - CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; - - CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; - CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; - - // Set constraints for the summary view - [NSLayoutConstraint activateConstraints: @[ - [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor - constant:leftMargin], - [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], - [threadSummaryView.heightAnchor constraintEqualToConstant:height], - [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] - ]]; - } - else if (event.isInThread) + RoomBubbleCellData *cellData = (RoomBubbleCellData*)[self cellDataAtIndex:indexPath.row]; + MXEvent *event = cellData.events.firstObject; + + if (event) { - FromAThreadView *fromThreadView = [FromAThreadView instantiate]; - [bubbleCell.tmpSubviews addObject:fromThreadView]; - - fromThreadView.translatesAutoresizingMaskIntoConstraints = NO; - [bubbleCell.contentView addSubview:fromThreadView]; - - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; - CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; - - CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; - CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; - - // Set constraints for the summary view - [NSLayoutConstraint activateConstraints: @[ - [fromThreadView.leadingAnchor constraintEqualToAnchor:fromThreadView.superview.leadingAnchor - constant:leftMargin], - [fromThreadView.topAnchor constraintEqualToAnchor:fromThreadView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.fromThreadViewTopMargin], - [fromThreadView.heightAnchor constraintEqualToConstant:height], - [fromThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] - ]]; + if (cellData.hasThreadRoot) + { + MXThread *thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + [bubbleCell.tmpSubviews addObject:threadSummaryView]; + + threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:threadSummaryView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor + constant:leftMargin], + [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + [threadSummaryView.heightAnchor constraintEqualToConstant:height], + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } + else if (event.isInThread) + { + FromAThreadView *fromAThreadView = [FromAThreadView instantiate]; + [bubbleCell.tmpSubviews addObject:fromAThreadView]; + + fromAThreadView.translatesAutoresizingMaskIntoConstraints = NO; + [bubbleCell.contentView addSubview:fromAThreadView]; + + CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; + + CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; + CGFloat bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height; + + // Set constraints for the summary view + [NSLayoutConstraint activateConstraints: @[ + [fromAThreadView.leadingAnchor constraintEqualToAnchor:fromAThreadView.superview.leadingAnchor + constant:leftMargin], + [fromAThreadView.topAnchor constraintEqualToAnchor:fromAThreadView.superview.topAnchor + constant:bottomPositionY + RoomBubbleCellLayout.fromAThreadViewTopMargin], + [fromAThreadView.heightAnchor constraintEqualToConstant:height], + [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + ]]; + } } } } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift b/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift index 461da960b2..641bc0677e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift @@ -51,5 +51,5 @@ final class RoomBubbleCellLayout: NSObject { static let threadSummaryViewTopMargin: CGFloat = 8.0 static let threadSummaryViewHeight: CGFloat = 40.0 - static let fromThreadViewTopMargin: CGFloat = 8.0 + static let fromAThreadViewTopMargin: CGFloat = 8.0 }